diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js
index aa73a5f188cd..7c46c2b24477 100644
--- a/src/ng/directive/input.js
+++ b/src/ng/directive/input.js
@@ -7,6 +7,7 @@
UNTOUCHED_CLASS: false,
TOUCHED_CLASS: false,
ngModelMinErr: false,
+ KEYS_PER_DATE_INPUT_TYPE: true
*/
// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
@@ -20,6 +21,34 @@ var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
var MONTH_REGEXP = /^(\d{4})-(\d\d)$/;
var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
+var KEYS = {
+ backspace: 8,
+ del: 46,
+ down: 40,
+ up: 38
+};
+var KEY_RANGES = {
+ numeric: [48, 57],
+ numpadNumeric: [96, 105],
+ alpha: [65, 90]
+};
+var DEFAULT_KEYS_FOR_DATE_INPUT_TYPE = [
+ KEY_RANGES.numeric,
+ KEY_RANGES.numpadNumeric,
+ KEYS.up,
+ KEYS.down,
+ KEYS.backspace,
+ KEYS.del
+];
+var KEYS_PER_DATE_INPUT_TYPE = {
+ date: DEFAULT_KEYS_FOR_DATE_INPUT_TYPE,
+ 'datetime-local': DEFAULT_KEYS_FOR_DATE_INPUT_TYPE,
+ month: DEFAULT_KEYS_FOR_DATE_INPUT_TYPE.concat([KEY_RANGES.alpha]),
+ time: DEFAULT_KEYS_FOR_DATE_INPUT_TYPE,
+ week: DEFAULT_KEYS_FOR_DATE_INPUT_TYPE
+};
+var DATE_INPUT_TYPES = Object.keys(KEYS_PER_DATE_INPUT_TYPE);
+
var inputType = {
/**
@@ -1087,6 +1116,24 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
stringBasedInputType(ctrl);
}
+function createKeyupListener(type, callback) {
+ // A list containing single keyCodes and keyCode-ranges (in the form [min, max])
+ var keys = KEYS_PER_DATE_INPUT_TYPE[type];
+
+ return function keyupListener(evt) {
+ // Ignore if a modifier key is also pressed
+ if (!evt || evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return;
+
+ var key = evt.keyCode;
+ var affectsInput = keys.some(function(keyOrRange) {
+ return !isArray(keyOrRange)
+ ? (key === keyOrRange) : (keyOrRange[0] <= key) && (key <= keyOrRange[1]);
+ });
+
+ if (affectsInput) callback('input');
+ };
+}
+
function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
var type = lowercase(element[0].type);
@@ -1134,6 +1181,15 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
// input event on backspace, delete or cut
if ($sniffer.hasEvent('input')) {
element.on('input', listener);
+
+ // On date-family inputs, we also need to listen for `keyup` in case the date is partially
+ // edited by the user using the keyboard, resulting in a change in the validity state, but
+ // without an accompanying change in the input value (thus no `input` event).
+ // (This is only necessary on browsers that support inputs of that type - other browsers set the
+ // `type` property to "text".)
+ var browserSupportsType = (type === attr.type);
+ var listenForKeyup = browserSupportsType && (DATE_INPUT_TYPES.indexOf(type) !== -1);
+ if (listenForKeyup) element.on('keyup', createKeyupListener(type, listener));
} else {
var timeout;
@@ -1756,6 +1812,3 @@ var ngValueDirective = function() {
}
};
};
-
-
-
diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js
index 053c64931cfe..36887a573221 100644
--- a/test/ng/directive/inputSpec.js
+++ b/test/ng/directive/inputSpec.js
@@ -1,6 +1,8 @@
'use strict';
-/* globals getInputCompileHelper: false */
+/* globals getInputCompileHelper: false,
+ KEYS_PER_DATE_INPUT_TYPE: false
+ */
describe('input', function() {
var helper, $compile, $rootScope, $browser, $sniffer, $timeout, $q;
@@ -645,6 +647,7 @@ describe('input', function() {
expect(inputElm.val()).toBe('2013-12');
});
+
it('should only change the month of a bound date in any timezone', function() {
var inputElm = helper.compileInput('');
@@ -656,6 +659,106 @@ describe('input', function() {
expect(inputElm.val()).toBe('2013-09');
});
+
+ they('should re-validate when partially editing the input value (keyCode: $prop)',
+ getKeyCodesForType('month'),
+ function(keyCode) {
+ // This testcase simulates keyboard interactions that lead to a change in the validity state
+ // of the element, but no change in its value (thus no 'input' event).
+ // For a more detailed explanation, see: https://github.com/angular/angular.js/pull/12902
+
+ var inputType = 'month';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeInvalid();
+
+ mockValidity.valid = true;
+ mockValidity.badInput = false;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeValid();
+ }
+ }
+ );
+
+
+ they('should not re-validate when a modifier key is pressed (modifier: $prop)',
+ ['alt', 'ctrl', 'meta', 'shift'],
+ function(modifier) {
+ // This testcase simulates keyboard interactions that lead to a change in the validity state
+ // of the element, but no change in its value (thus no 'input' event).
+ // For a more detailed explanation, see: https://github.com/angular/angular.js/pull/12902
+
+ var inputType = 'month';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+ var mockEvt = {type: 'keyup', keyCode: 8};
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler(mockEvt);
+ expect(inputElm).toBeInvalid();
+
+ mockEvt[modifier + 'Key'] = true;
+
+ mockValidity.valid = true;
+ mockValidity.badInput = false;
+ inputElm.triggerHandler(mockEvt);
+ expect(inputElm).toBeInvalid();
+ }
+ }
+ );
+
+
+ they('should not re-validate on keys that can\'t affect the input (keyCode: $prop)',
+ getIgnoredKeyCodesForType('month'),
+ function(keyCode) {
+ var inputType = 'month';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeValid();
+ }
+ }
+ );
+
+
+ it('should listen for \'keyup\' only on browsers that support this input type', function() {
+ var inputType = 'month';
+
+ var shouldListenForKeyup = browserSupportsInputTypeAndEvent(inputType, 'input');
+ var keyCode = getKeyCodesForType(inputType)[0];
+ var inputElm = helper.compileInput('');
+ var ctrl = inputElm.controller('ngModel');
+ spyOn(ctrl, '$setViewValue');
+
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+
+ expect(ctrl.$setViewValue.callCount).toBe(shouldListenForKeyup ? 1 : 0);
+ });
+
+
describe('min', function() {
var inputElm;
beforeEach(function() {
@@ -698,6 +801,7 @@ describe('input', function() {
});
});
+
describe('max', function() {
var inputElm;
beforeEach(function() {
@@ -870,6 +974,106 @@ describe('input', function() {
expect($rootScope.form.alias.$error.week).toBeTruthy();
});
+
+ they('should re-validate when partially editing the input value (keyCode: $prop)',
+ getKeyCodesForType('week'),
+ function(keyCode) {
+ // This testcase simulates keyboard interactions that lead to a change in the validity state
+ // of the element, but no change in its value (thus no 'input' event).
+ // For a more detailed explanation, see: https://github.com/angular/angular.js/pull/12902
+
+ var inputType = 'week';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeInvalid();
+
+ mockValidity.valid = true;
+ mockValidity.badInput = false;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeValid();
+ }
+ }
+ );
+
+
+ they('should not re-validate when a modifier key is pressed (modifier: $prop)',
+ ['alt', 'ctrl', 'meta', 'shift'],
+ function(modifier) {
+ // This testcase simulates keyboard interactions that lead to a change in the validity state
+ // of the element, but no change in its value (thus no 'input' event).
+ // For a more detailed explanation, see: https://github.com/angular/angular.js/pull/12902
+
+ var inputType = 'week';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+ var mockEvt = {type: 'keyup', keyCode: 8};
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler(mockEvt);
+ expect(inputElm).toBeInvalid();
+
+ mockEvt[modifier + 'Key'] = true;
+
+ mockValidity.valid = true;
+ mockValidity.badInput = false;
+ inputElm.triggerHandler(mockEvt);
+ expect(inputElm).toBeInvalid();
+ }
+ }
+ );
+
+
+ they('should not re-validate on keys that can\'t affect the input (keyCode: $prop)',
+ getIgnoredKeyCodesForType('week'),
+ function(keyCode) {
+ var inputType = 'week';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeValid();
+ }
+ }
+ );
+
+
+ it('should listen for \'keyup\' only on browsers that support this input type', function() {
+ var inputType = 'week';
+
+ var shouldListenForKeyup = browserSupportsInputTypeAndEvent(inputType, 'input');
+ var keyCode = getKeyCodesForType(inputType)[0];
+ var inputElm = helper.compileInput('');
+ var ctrl = inputElm.controller('ngModel');
+ spyOn(ctrl, '$setViewValue');
+
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+
+ expect(ctrl.$setViewValue.callCount).toBe(shouldListenForKeyup ? 1 : 0);
+ });
+
+
describe('min', function() {
var inputElm;
beforeEach(function() {
@@ -912,6 +1116,7 @@ describe('input', function() {
});
});
+
describe('max', function() {
var inputElm;
@@ -1119,6 +1324,106 @@ describe('input', function() {
expect($rootScope.form.alias.$error.datetimelocal).toBeTruthy();
});
+
+ they('should re-validate when partially editing the input value (keyCode: $prop)',
+ getKeyCodesForType('datetime-local'),
+ function(keyCode) {
+ // This testcase simulates keyboard interactions that lead to a change in the validity state
+ // of the element, but no change in its value (thus no 'input' event).
+ // For a more detailed explanation, see: https://github.com/angular/angular.js/pull/12902
+
+ var inputType = 'datetime-local';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeInvalid();
+
+ mockValidity.valid = true;
+ mockValidity.badInput = false;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeValid();
+ }
+ }
+ );
+
+
+ they('should not re-validate when a modifier key is pressed (modifier: $prop)',
+ ['alt', 'ctrl', 'meta', 'shift'],
+ function(modifier) {
+ // This testcase simulates keyboard interactions that lead to a change in the validity state
+ // of the element, but no change in its value (thus no 'input' event).
+ // For a more detailed explanation, see: https://github.com/angular/angular.js/pull/12902
+
+ var inputType = 'datetime-local';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+ var mockEvt = {type: 'keyup', keyCode: 8};
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler(mockEvt);
+ expect(inputElm).toBeInvalid();
+
+ mockEvt[modifier + 'Key'] = true;
+
+ mockValidity.valid = true;
+ mockValidity.badInput = false;
+ inputElm.triggerHandler(mockEvt);
+ expect(inputElm).toBeInvalid();
+ }
+ }
+ );
+
+
+ they('should not re-validate on keys that can\'t affect the input (keyCode: $prop)',
+ getIgnoredKeyCodesForType('datetime-local'),
+ function(keyCode) {
+ var inputType = 'datetime-local';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeValid();
+ }
+ }
+ );
+
+
+ it('should listen for \'keyup\' only on browsers that support this input type', function() {
+ var inputType = 'datetime-local';
+
+ var shouldListenForKeyup = browserSupportsInputTypeAndEvent(inputType, 'input');
+ var keyCode = getKeyCodesForType(inputType)[0];
+ var inputElm = helper.compileInput('');
+ var ctrl = inputElm.controller('ngModel');
+ spyOn(ctrl, '$setViewValue');
+
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+
+ expect(ctrl.$setViewValue.callCount).toBe(shouldListenForKeyup ? 1 : 0);
+ });
+
+
describe('min', function() {
var inputElm;
beforeEach(function() {
@@ -1161,6 +1466,7 @@ describe('input', function() {
});
});
+
describe('max', function() {
var inputElm;
beforeEach(function() {
@@ -1444,6 +1750,106 @@ describe('input', function() {
expect(+$rootScope.value).toBe(+new Date(2013, 2, 3, 1, 2, 0));
});
+
+ they('should re-validate when partially editing the input value (keyCode: $prop)',
+ getKeyCodesForType('time'),
+ function(keyCode) {
+ // This testcase simulates keyboard interactions that lead to a change in the validity state
+ // of the element, but no change in its value (thus no 'input' event).
+ // For a more detailed explanation, see: https://github.com/angular/angular.js/pull/12902
+
+ var inputType = 'time';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeInvalid();
+
+ mockValidity.valid = true;
+ mockValidity.badInput = false;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeValid();
+ }
+ }
+ );
+
+
+ they('should not re-validate when a modifier key is pressed (modifier: $prop)',
+ ['alt', 'ctrl', 'meta', 'shift'],
+ function(modifier) {
+ // This testcase simulates keyboard interactions that lead to a change in the validity state
+ // of the element, but no change in its value (thus no 'input' event).
+ // For a more detailed explanation, see: https://github.com/angular/angular.js/pull/12902
+
+ var inputType = 'time';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+ var mockEvt = {type: 'keyup', keyCode: 8};
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler(mockEvt);
+ expect(inputElm).toBeInvalid();
+
+ mockEvt[modifier + 'Key'] = true;
+
+ mockValidity.valid = true;
+ mockValidity.badInput = false;
+ inputElm.triggerHandler(mockEvt);
+ expect(inputElm).toBeInvalid();
+ }
+ }
+ );
+
+
+ they('should not re-validate on keys that can\'t affect the input (keyCode: $prop)',
+ getIgnoredKeyCodesForType('time'),
+ function(keyCode) {
+ var inputType = 'time';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeValid();
+ }
+ }
+ );
+
+
+ it('should listen for \'keyup\' only on browsers that support this input type', function() {
+ var inputType = 'time';
+
+ var shouldListenForKeyup = browserSupportsInputTypeAndEvent(inputType, 'input');
+ var keyCode = getKeyCodesForType(inputType)[0];
+ var inputElm = helper.compileInput('');
+ var ctrl = inputElm.controller('ngModel');
+ spyOn(ctrl, '$setViewValue');
+
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+
+ expect(ctrl.$setViewValue.callCount).toBe(shouldListenForKeyup ? 1 : 0);
+ });
+
+
describe('min', function() {
var inputElm;
beforeEach(function() {
@@ -1486,6 +1892,7 @@ describe('input', function() {
});
});
+
describe('max', function() {
var inputElm;
beforeEach(function() {
@@ -1744,6 +2151,106 @@ describe('input', function() {
dealoc(formElm);
});
+
+ they('should re-validate when partially editing the input value (keyCode: $prop)',
+ getKeyCodesForType('date'),
+ function(keyCode) {
+ // This testcase simulates keyboard interactions that lead to a change in the validity state
+ // of the element, but no change in its value (thus no 'input' event).
+ // For a more detailed explanation, see: https://github.com/angular/angular.js/pull/12902
+
+ var inputType = 'date';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeInvalid();
+
+ mockValidity.valid = true;
+ mockValidity.badInput = false;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeValid();
+ }
+ }
+ );
+
+
+ they('should not re-validate when a modifier key is pressed (modifier: $prop)',
+ ['alt', 'ctrl', 'meta', 'shift'],
+ function(modifier) {
+ // This testcase simulates keyboard interactions that lead to a change in the validity state
+ // of the element, but no change in its value (thus no 'input' event).
+ // For a more detailed explanation, see: https://github.com/angular/angular.js/pull/12902
+
+ var inputType = 'date';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+ var mockEvt = {type: 'keyup', keyCode: 8};
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler(mockEvt);
+ expect(inputElm).toBeInvalid();
+
+ mockEvt[modifier + 'Key'] = true;
+
+ mockValidity.valid = true;
+ mockValidity.badInput = false;
+ inputElm.triggerHandler(mockEvt);
+ expect(inputElm).toBeInvalid();
+ }
+ }
+ );
+
+
+ they('should not re-validate on keys that can\'t affect the input (keyCode: $prop)',
+ getIgnoredKeyCodesForType('date'),
+ function(keyCode) {
+ var inputType = 'date';
+
+ if (browserSupportsInputTypeAndEvent(inputType, 'input')) {
+ var mockValidity = {valid: true, badInput: false};
+ helper.compileInput('', mockValidity);
+ var inputElm = helper.inputElm;
+
+ expect(inputElm).toBeValid();
+
+ mockValidity.valid = false;
+ mockValidity.badInput = true;
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+ expect(inputElm).toBeValid();
+ }
+ }
+ );
+
+
+ it('should listen for \'keyup\' only on browsers that support this input type', function() {
+ var inputType = 'date';
+
+ var shouldListenForKeyup = browserSupportsInputTypeAndEvent(inputType, 'input');
+ var keyCode = getKeyCodesForType(inputType)[0];
+ var inputElm = helper.compileInput('');
+ var ctrl = inputElm.controller('ngModel');
+ spyOn(ctrl, '$setViewValue');
+
+ inputElm.triggerHandler({type: 'keyup', keyCode: keyCode});
+
+ expect(ctrl.$setViewValue.callCount).toBe(shouldListenForKeyup ? 1 : 0);
+ });
+
+
describe('min', function() {
it('should invalidate', function() {
@@ -1783,6 +2290,7 @@ describe('input', function() {
});
});
+
describe('max', function() {
it('should invalidate', function() {
@@ -2859,4 +3367,45 @@ describe('input', function() {
dealoc(inputElm);
});
});
+
+
+ // Helpers
+ function browserSupportsInputTypeAndEvent(inputType, event) {
+ var input = jqLite('');
+
+ var supportsType = (inputType === input.prop('type'));
+ var supportsEvent = $sniffer.hasEvent(event);
+
+ return supportsType && supportsEvent;
+ }
+
+ function getKeyCodesForType(type) {
+ var keyCodes = [];
+
+ (KEYS_PER_DATE_INPUT_TYPE[type] || []).forEach(function(keyOrRange) {
+ if (isArray(keyOrRange)) {
+ var min = keyOrRange[0];
+ var max = keyOrRange[1];
+
+ for (var i = min; i <= max; i++) {
+ keyCodes.push(i);
+ }
+ } else {
+ keyCodes.push(keyOrRange);
+ }
+ });
+
+ return keyCodes;
+ }
+
+ function getIgnoredKeyCodesForType(type) {
+ var keyCodes = [];
+
+ var notIgnored = getKeyCodesForType(type);
+ for (var i = 1; i <= 222; i++) {
+ if (notIgnored.indexOf(i) === -1) keyCodes.push(i);
+ }
+
+ return keyCodes;
+ }
});