diff --git a/omega-web/src/coffee/popup.coffee b/omega-web/src/coffee/popup.coffee index 1fbdae1..adbcc40 100644 --- a/omega-web/src/coffee/popup.coffee +++ b/omega-web/src/coffee/popup.coffee @@ -8,21 +8,73 @@ module.filter 'dispName', (omegaTarget) -> name = name.name omegaTarget.getMessage('profile_' + name) || name -jQuery(document).on 'keydown', (e) -> - return unless e.keyCode == 38 or e.keyCode == 40 - items = jQuery('.popup-menu-nav > li:not(.ng-hide) > a') - - i = items.index(jQuery(e.target).closest('a')) - if i == -1 - i = items.index(jQuery('.popup-menu-nav > li.active > a')) - switch e.keyCode - when 38 - i-- - if i >= 0 - items.eq(i)[0]?.focus() - when 40 - i++ +shortcutKeys = + 38: (activeIndex, items) -> # Up + i = activeIndex - 1 + if i >= 0 items.eq(i)[0]?.focus() + 40: (activeIndex, items) -> # Down + items.eq(activeIndex + 1)[0]?.focus() + 48: '+direct' # 0 + 83: '+system' # s + 191: 'help' # / + 63: 'help' # ? + 69: 'external' # e + 65: 'addRule' # a + 43: 'addRule' # + + 61: 'addRule' # = + 84: 'tempRule' # t + 79: 'option' # o + 73: 'issue' # i + 76: 'log' # l + +for i in [1..9] + shortcutKeys[48 + i] = i + +customProfiles = do -> + _customProfiles = null + return -> + _customProfiles ?= jQuery('.custom-profile:not(.ng-hide) > a') + +jQuery(document).on 'keydown', (e) -> + handler = shortcutKeys[e.keyCode] + return unless handler + switch typeof handler + when 'string' + switch handler + when 'help' + showHelp = (element, key) -> + if typeof element == 'string' + element = jQuery("a[data-shortcut='#{element}']") + span = jQuery('.shortcut-help', element) + if span.length == 0 + span = jQuery('').addClass('shortcut-help') + span.text(key) + element.find('.glyphicon').after(span) + keys = + '+direct': '0' + '+system': 'S' + 'external': 'E' + 'addRule': 'A' + 'tempRule': 'T' + 'option': 'O' + 'issue': 'I' + 'log': 'L' + for shortcut, key of keys + showHelp(shortcut, key) + customProfiles().each (i, el) -> + if i <= 8 + showHelp(jQuery(el), i + 1) + else + jQuery("a[data-shortcut='#{handler}']")[0]?.click() + when 'number' + customProfiles().eq(handler - 1)?.click() + when 'function' + items = jQuery('.popup-menu-nav > li:not(.ng-hide) > a') + i = items.index(jQuery(e.target).closest('a')) + if i == -1 + i = items.index(jQuery('.popup-menu-nav > li.active > a')) + handler(i, items) return false diff --git a/omega-web/src/less/popup.less b/omega-web/src/less/popup.less index abe9c6f..1dba448 100644 --- a/omega-web/src/less/popup.less +++ b/omega-web/src/less/popup.less @@ -25,6 +25,20 @@ li > a { max-width: 20em; } +.shortcut-help { + .monospace(); + border: solid 1px #000; + border-radius: 2px; + display: inline-block; + color: #000; + box-shadow: 1px 1px; + width: 1em; + height: 1em; + line-height: 1em; + text-align: center; + margin-top: -3px; +} + .nav-pills.nav-stacked { > li > a { padding: 5px 25px 5px 8px; diff --git a/omega-web/src/popup.jade b/omega-web/src/popup.jade index bfb5b0a..de3c28a 100644 --- a/omega-web/src/popup.jade +++ b/omega-web/src/popup.jade @@ -26,10 +26,11 @@ html(lang='en' ng-app='omegaPopup' ng-controller='PopupCtrl' ng-csp) body(ng-class='{"with-condition-form": showConditionForm}') ul.popup-menu-nav.nav.nav-pills.nav-stacked(ng-hide='showConditionForm || proxyNotControllable') li.profile(ng-repeat='profile in builtinProfiles' ng-class='{active: isActive(profile.name), "bg-info": isEffective(profile.name)}') - a(href='#' role='button' ng-attr-tabindex='{{100 + $index}}' ng-click='applyProfile(profile)' title='{{getProfileTitle(profile)}}') + a(href='#' role='button' ng-attr-tabindex='{{100 + $index}}' ng-click='applyProfile(profile)' title='{{getProfileTitle(profile)}}' + data-shortcut='+{{profile.name}}') span(omega-profile-inline='profile' icon='getIcon(profile)' options='availableProfiles' disp-name='dispNameFilter') li.profile.external-profile(ng-show='!!externalProfile' ng-class='{active: isActive(""), "bg-info": isEffective("")}') - a(href='#' role='button' ng-click='nameExternal.open = true' title='{{getProfileTitle(externalProfile)}}') + a(href='#' role='button' ng-click='nameExternal.open = true' title='{{getProfileTitle(externalProfile)}}' data-shortcut='external') form(name='nameExternalForm' ng-submit='nameExternalForm.$valid && saveExternal()') span(omega-profile-icon='externalProfile' icon='getIcon(externalProfile, "normal")' options='availableProfiles' disp-name='dispNameFilter') = ' ' @@ -37,7 +38,7 @@ html(lang='en' ng-app='omegaPopup' ng-controller='PopupCtrl' ng-csp) input.form-control(ng-show='!!nameExternal.open' ng-model='externalProfile.name' ng-blur='nameExternalForm.submit()' placeholder='{{"popup_externalProfileName" | tr}}' ui-validate='validateProfileName') li.divider - li.profile(ng-repeat='profile in customProfiles' ng-class='{active: isActive(profile.name), "bg-info": isEffective(profile.name)}' + li.profile.custom-profile(ng-repeat='profile in customProfiles' ng-class='{active: isActive(profile.name), "bg-info": isEffective(profile.name)}' dropdown) a(href='#' role='button' ng-click='applyProfile(profile)' ng-if='!profile.validResultProfiles' title='{{getProfileTitle(profile)}}') span(omega-profile-inline='profile' icon='getIcon(profile)' options='availableProfiles' disp-name='dispNameFilter') @@ -53,12 +54,12 @@ html(lang='en' ng-app='omegaPopup' ng-controller='PopupCtrl' ng-csp) span(omega-profile-inline='p' options='availableProfiles' disp-name='dispNameFilter') li.divider(ng-show='!!currentDomain && validResultProfiles.length') li(ng-show='!!currentProfileCanAddRule') - a(href='#' role='button' ng-click='showConditionForm = true') + a(href='#' role='button' ng-click='showConditionForm = true' data-shortcut='addRule') span.glyphicon.glyphicon-plus = ' ' span {{'popup_addCondition' | tr}} li(ng-show='!!currentDomain && validResultProfiles.length' dropdown is-open="tempRuleMenu.open") - a.dropdown-toggle(href='#' role='button') + a.dropdown-toggle(href='#' role='button' data-shortcut='tempRule') span.glyphicon.glyphicon-filter = ' ' span.current-domain {{currentDomain}} @@ -70,17 +71,18 @@ html(lang='en' ng-app='omegaPopup' ng-controller='PopupCtrl' ng-csp) span(omega-profile-inline='profile' options='availableProfiles' disp-name='dispNameFilter') li.divider li - a(href='#' role='button' ng-click='openOptions()') + a(href='#' role='button' ng-click='openOptions()' data-shortcut='option') span.glyphicon.glyphicon-wrench = ' ' span {{'popup_showOptions' | tr}} li - a.report-issue(href='https://github.com/FelisCatus/SwitchyOmega/issues' target='_blank') + a.report-issue(href='https://github.com/FelisCatus/SwitchyOmega/issues' + target='_blank' data-shortcut='issue') span.glyphicon.glyphicon-comment = ' ' span {{'popup_reportIssues' | tr}} li - a.error-log(href='#' role='button') + a.error-log(href='#' role='button' data-shortcut='log') span.glyphicon.glyphicon-download = ' ' span {{'popup_errorLog' | tr}}