From 1acc373a9f9b4e4e074f3c605a55628c04b31967 Mon Sep 17 00:00:00 2001 From: FelisCatus Date: Fri, 19 Dec 2014 20:55:03 +0800 Subject: [PATCH] Add keyboard navigation (or tab navigation) in popup. Fix #24. --- omega-web/bower.json | 4 ++-- omega-web/grunt/aliases.coffee | 1 - omega-web/src/coffee/options.coffee | 2 +- omega-web/src/coffee/popup.coffee | 16 ++++++++++++++++ omega-web/src/popup.jade | 25 +++++++++++++------------ 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/omega-web/bower.json b/omega-web/bower.json index 1b85611..9beaaf3 100644 --- a/omega-web/bower.json +++ b/omega-web/bower.json @@ -51,13 +51,13 @@ "": [] }, "angular": { - "": "*.js" + "": "*.min.js" }, "angular-animate": { "": "*.min.*" }, "angular-bootstrap": { - "": "*.min.js" + "": "ui-bootstrap-tpls.min.js" }, "angular-i18n": { "": [ diff --git a/omega-web/grunt/aliases.coffee b/omega-web/grunt/aliases.coffee index 6b30259..9d45fdb 100644 --- a/omega-web/grunt/aliases.coffee +++ b/omega-web/grunt/aliases.coffee @@ -6,7 +6,6 @@ module.exports = 'autoprefixer' 'coffeelint' 'coffee' - 'ngAnnotate' 'bower' ] test: ['mochaTest'] diff --git a/omega-web/src/coffee/options.coffee b/omega-web/src/coffee/options.coffee index b0ca0bc..b659d19 100644 --- a/omega-web/src/coffee/options.coffee +++ b/omega-web/src/coffee/options.coffee @@ -34,7 +34,7 @@ $script.ready ['jquery'], -> $script 'lib/spectrum/spectrum.js', 'spectrum' $script.ready ['angular-loader', 'jquery'], -> - $script 'lib/angular/angular.js', 'angular' + $script 'lib/angular/angular.min.js', 'angular' $script.ready ['angular'], -> $script 'lib/angular-ui-router/angular-ui-router.js', 'angular-ui-router' diff --git a/omega-web/src/coffee/popup.coffee b/omega-web/src/coffee/popup.coffee index 281c52e..bbf919c 100644 --- a/omega-web/src/coffee/popup.coffee +++ b/omega-web/src/coffee/popup.coffee @@ -8,6 +8,22 @@ 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')) + switch e.keyCode + when 38 + i-- + if i >= 0 + items.eq(i)[0]?.focus() + when 40 + i++ + items.eq(i)[0]?.focus() + + return false + module.controller 'PopupCtrl', ($scope, $window, $q, omegaTarget, profileIcons, profileOrder, dispNameFilter, getVirtualTarget) -> diff --git a/omega-web/src/popup.jade b/omega-web/src/popup.jade index 5a91988..bfb5b0a 100644 --- a/omega-web/src/popup.jade +++ b/omega-web/src/popup.jade @@ -24,12 +24,12 @@ html(lang='en' ng-app='omegaPopup' ng-controller='PopupCtrl' ng-csp) link(rel='stylesheet' href='lib/bootstrap/css/bootstrap.min.css') link(rel='stylesheet' href='css/popup.css') body(ng-class='{"with-condition-form": showConditionForm}') - ul.nav.nav-pills.nav-stacked(ng-hide='showConditionForm || proxyNotControllable') + 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(ng-click='applyProfile(profile)' title='{{getProfileTitle(profile)}}') + a(href='#' role='button' ng-attr-tabindex='{{100 + $index}}' ng-click='applyProfile(profile)' title='{{getProfileTitle(profile)}}') 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(ng-click='nameExternal.open = true' title='{{getProfileTitle(externalProfile)}}') + a(href='#' role='button' ng-click='nameExternal.open = true' title='{{getProfileTitle(externalProfile)}}') form(name='nameExternalForm' ng-submit='nameExternalForm.$valid && saveExternal()') span(omega-profile-icon='externalProfile' icon='getIcon(externalProfile, "normal")' options='availableProfiles' disp-name='dispNameFilter') = ' ' @@ -39,26 +39,26 @@ html(lang='en' ng-app='omegaPopup' ng-controller='PopupCtrl' ng-csp) li.divider li.profile(ng-repeat='profile in customProfiles' ng-class='{active: isActive(profile.name), "bg-info": isEffective(profile.name)}' dropdown) - a(ng-click='applyProfile(profile)' ng-if='!profile.validResultProfiles' title='{{getProfileTitle(profile)}}') + 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') - a.profile-with-default-edit(ng-click='applyProfile(profile)' ng-if='!!profile.validResultProfiles' title='{{getProfileTitle(profile)}}') + a.profile-with-default-edit(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') = ' ' | [{{profile.defaultProfileName}}] - button.dropdown-toggle.btn.btn-default(ng-click='$event.stopPropagation()') + button.dropdown-toggle.btn.btn-default(href='#' role='button' ng-click='$event.stopPropagation()') span.glyphicon.glyphicon-chevron-down ul.dropdown-menu(ng-if='!!profile.validResultProfiles') li(ng-repeat='p in profile.validResultProfiles' ng-class='{active: p.name == profile.defaultProfileName}') - a(ng-click='setDefaultProfile(profile.name, p.name)' title='{{getProfileTitle(profile)}}') + a(href='#' role='button' ng-click='setDefaultProfile(profile.name, p.name)' title='{{getProfileTitle(profile)}}') span(omega-profile-inline='p' options='availableProfiles' disp-name='dispNameFilter') li.divider(ng-show='!!currentDomain && validResultProfiles.length') li(ng-show='!!currentProfileCanAddRule') - a(ng-click='showConditionForm = true') + a(href='#' role='button' ng-click='showConditionForm = true') span.glyphicon.glyphicon-plus = ' ' span {{'popup_addCondition' | tr}} li(ng-show='!!currentDomain && validResultProfiles.length' dropdown is-open="tempRuleMenu.open") - a.dropdown-toggle + a.dropdown-toggle(href='#' role='button') span.glyphicon.glyphicon-filter = ' ' span.current-domain {{currentDomain}} @@ -66,11 +66,11 @@ html(lang='en' ng-app='omegaPopup' ng-controller='PopupCtrl' ng-csp) ul.dropdown-menu li(ng-repeat='profile in validResultProfiles' ng-class='{active: profile.name == currentTempRuleProfile}' ng-show='!!currentTempRuleProfile || validResultProfiles.length == 1 || profile.name != currentProfileName') - a(ng-click='addTempRule(currentDomain, profile.name)' title='{{getProfileTitle(profile)}}') + a(href='#' role='button' ng-click='addTempRule(currentDomain, profile.name)' title='{{getProfileTitle(profile)}}') span(omega-profile-inline='profile' options='availableProfiles' disp-name='dispNameFilter') li.divider li - a(ng-click='openOptions()') + a(href='#' role='button' ng-click='openOptions()') span.glyphicon.glyphicon-wrench = ' ' span {{'popup_showOptions' | tr}} @@ -80,7 +80,7 @@ html(lang='en' ng-app='omegaPopup' ng-controller='PopupCtrl' ng-csp) = ' ' span {{'popup_reportIssues' | tr}} li - a.error-log + a.error-log(href='#' role='button') span.glyphicon.glyphicon-download = ' ' span {{'popup_errorLog' | tr}} @@ -129,6 +129,7 @@ html(lang='en' ng-app='omegaPopup' ng-controller='PopupCtrl' ng-csp) script(src='lib/FileSaver/FileSaver.js') script(src='js/omega_target_web_basics.js') script(src='js/popup_basics.js') + script(src='lib/jquery/jquery.min.js') script(src='lib/angular/angular.min.js') script(src='lib/angular-bootstrap/ui-bootstrap-tpls.min.js') script(src='lib/angular-ui-utils/validate.min.js')