Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
feat(timepicker): have up/down arrow keys control time selection
Browse files Browse the repository at this point in the history
Add ability to use arrow keys to control time selection
  • Loading branch information
Josh Friend authored and wesleycho committed Mar 23, 2015
1 parent 0d8820b commit 2296115
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 3 deletions.
8 changes: 6 additions & 2 deletions src/timepicker/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,9 @@ All settings can be provided as attributes in the `<timepicker>` or globally con
Whether user can type inside the hours & minutes input.

* `mousewheel`
_(Defaults: true)_ :
Whether user can scroll inside the hours & minutes input to increase or decrease it's values.
_(Defaults: true)_ :
Whether user can scroll inside the hours & minutes input to increase or decrease it's values.

* `arrowkeys`
_(Defaults: true)_ :
Whether user can use up/down arrowkeys inside the hours & minutes input to increase or decrease it's values.
83 changes: 83 additions & 0 deletions src/timepicker/test/timepicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,25 @@ describe('timepicker directive', function () {
return e;
}

function keydown(key) {
var e = $.Event('keydown');
switch(key) {
case 'left':
e.which = 37;
break;
case 'up':
e.which = 38;
break;
case 'right':
e.which = 39;
break;
case 'down':
e.which = 40;
break;
}
return e;
}

it('contains three row & three input elements', function() {
expect(element.find('tr').length).toBe(3);
expect(element.find('input').length).toBe(2);
Expand Down Expand Up @@ -376,6 +395,70 @@ describe('timepicker directive', function () {
expect(getModelState()).toEqual([14, 40]);
});

it('responds properly on "keydown" events', function() {
var inputs = element.find('input');
var hoursEl = inputs.eq(0), minutesEl = inputs.eq(1);
var upKeydownEvent = keydown('up');
var downKeydownEvent = keydown('down');
var leftKeydownEvent = keydown('left');

expect(getTimeState()).toEqual(['02', '40', 'PM']);
expect(getModelState()).toEqual([14, 40]);

// UP
hoursEl.trigger( upKeydownEvent );
$rootScope.$digest();
expect(getTimeState()).toEqual(['03', '40', 'PM']);
expect(getModelState()).toEqual([15, 40]);

hoursEl.trigger( upKeydownEvent );
$rootScope.$digest();
expect(getTimeState()).toEqual(['04', '40', 'PM']);
expect(getModelState()).toEqual([16, 40]);

minutesEl.trigger( upKeydownEvent );
$rootScope.$digest();
expect(getTimeState()).toEqual(['04', '41', 'PM']);
expect(getModelState()).toEqual([16, 41]);

minutesEl.trigger( upKeydownEvent );
$rootScope.$digest();
expect(getTimeState()).toEqual(['04', '42', 'PM']);
expect(getModelState()).toEqual([16, 42]);

// DOWN
minutesEl.trigger( downKeydownEvent );
$rootScope.$digest();
expect(getTimeState()).toEqual(['04', '41', 'PM']);
expect(getModelState()).toEqual([16, 41]);

minutesEl.trigger( downKeydownEvent );
$rootScope.$digest();
expect(getTimeState()).toEqual(['04', '40', 'PM']);
expect(getModelState()).toEqual([16, 40]);

hoursEl.trigger( downKeydownEvent );
$rootScope.$digest();
expect(getTimeState()).toEqual(['03', '40', 'PM']);
expect(getModelState()).toEqual([15, 40]);

hoursEl.trigger( downKeydownEvent );
$rootScope.$digest();
expect(getTimeState()).toEqual(['02', '40', 'PM']);
expect(getModelState()).toEqual([14, 40]);

// Other keydown
hoursEl.trigger( leftKeydownEvent );
$rootScope.$digest();
expect(getTimeState()).toEqual(['02', '40', 'PM']);
expect(getModelState()).toEqual([14, 40]);

minutesEl.trigger( leftKeydownEvent );
$rootScope.$digest();
expect(getTimeState()).toEqual(['02', '40', 'PM']);
expect(getModelState()).toEqual([14, 40]);
});

describe('attributes', function () {
beforeEach(function() {
$rootScope.hstep = 2;
Expand Down
37 changes: 36 additions & 1 deletion src/timepicker/timepicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ angular.module('ui.bootstrap.timepicker', [])
showMeridian: true,
meridians: null,
readonlyInput: false,
mousewheel: true
mousewheel: true,
arrowkeys: true
})

.controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) {
Expand All @@ -26,6 +27,11 @@ angular.module('ui.bootstrap.timepicker', [])
this.setupMousewheelEvents( hoursInputEl, minutesInputEl );
}

var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys;
if (arrowkeys) {
this.setupArrowkeyEvents( hoursInputEl, minutesInputEl );
}

$scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;
this.setupInputEvents( hoursInputEl, minutesInputEl );
};
Expand Down Expand Up @@ -114,6 +120,35 @@ angular.module('ui.bootstrap.timepicker', [])

};

// Respond on up/down arrowkeys
this.setupArrowkeyEvents = function( hoursInputEl, minutesInputEl ) {
hoursInputEl.bind('keydown', function(e) {
if ( e.which === 38 ) { // up
e.preventDefault();
$scope.incrementHours();
$scope.$apply();
}
else if ( e.which === 40 ) { // down
e.preventDefault();
$scope.decrementHours();
$scope.$apply();
}
});

minutesInputEl.bind('keydown', function(e) {
if ( e.which === 38 ) { // up
e.preventDefault();
$scope.incrementMinutes();
$scope.$apply();
}
else if ( e.which === 40 ) { // down
e.preventDefault();
$scope.decrementMinutes();
$scope.$apply();
}
});
};

this.setupInputEvents = function( hoursInputEl, minutesInputEl ) {
if ( $scope.readonlyInput ) {
$scope.updateHours = angular.noop;
Expand Down

0 comments on commit 2296115

Please sign in to comment.