diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/AngularPublic.js | 1 | ||||
| -rw-r--r-- | src/ng/directive/input.js | 121 | ||||
| -rw-r--r-- | src/ngScenario/Scenario.js | 2 | ||||
| -rw-r--r-- | src/ngScenario/dsl.js | 3 |
4 files changed, 48 insertions, 79 deletions
diff --git a/src/AngularPublic.js b/src/AngularPublic.js index 8597de9c..1326bf8c 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -98,7 +98,6 @@ function publishExternalAPI(angular){ ngModel: ngModelDirective, ngList: ngListDirective, ngChange: ngChangeDirective, - ngModelInstant: ngModelInstantDirective, required: requiredDirective, ngRequired: requiredDirective, ngValue: ngValueDirective diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 3d53f7ca..aab12e34 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -367,12 +367,43 @@ function isEmpty(value) { } -function textInputType(scope, element, attr, ctrl) { - element.bind('blur', function() { - scope.$apply(function() { - ctrl.$setViewValue(trim(element.val())); +function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { + + var listener = function() { + var value = trim(element.val()); + + if (ctrl.$viewValue !== value) { + scope.$apply(function() { + ctrl.$setViewValue(value); + }); + } + }; + + // if the browser does support "input" event, we are fine + if ($sniffer.hasEvent('input')) { + element.bind('input', listener); + } else { + var timeout; + + element.bind('keydown', function(event) { + var key = event.keyCode; + + // ignore + // command modifiers arrows + if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; + + if (!timeout) { + timeout = $browser.defer(function() { + listener(); + timeout = null; + }); + } }); - }); + + // if user paste into input using mouse, we need "change" event to catch it + element.bind('change', listener); + } + ctrl.$render = function() { element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue); @@ -448,8 +479,8 @@ function textInputType(scope, element, attr, ctrl) { } }; -function numberInputType(scope, element, attr, ctrl) { - textInputType(scope, element, attr, ctrl); +function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { + textInputType(scope, element, attr, ctrl, $sniffer, $browser); ctrl.$parsers.push(function(value) { var empty = isEmpty(value); @@ -510,8 +541,8 @@ function numberInputType(scope, element, attr, ctrl) { }); } -function urlInputType(scope, element, attr, ctrl) { - textInputType(scope, element, attr, ctrl); +function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { + textInputType(scope, element, attr, ctrl, $sniffer, $browser); var urlValidator = function(value) { if (isEmpty(value) || URL_REGEXP.test(value)) { @@ -527,8 +558,8 @@ function urlInputType(scope, element, attr, ctrl) { ctrl.$parsers.push(urlValidator); } -function emailInputType(scope, element, attr, ctrl) { - textInputType(scope, element, attr, ctrl); +function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { + textInputType(scope, element, attr, ctrl, $sniffer, $browser); var emailValidator = function(value) { if (isEmpty(value) || EMAIL_REGEXP.test(value)) { @@ -709,13 +740,14 @@ function checkboxInputType(scope, element, attr, ctrl) { </doc:scenario> </doc:example> */ -var inputDirective = [function() { +var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) { return { restrict: 'E', require: '?ngModel', link: function(scope, element, attr, ctrl) { if (ctrl) { - (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl); + (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer, + $browser); } } }; @@ -1004,69 +1036,6 @@ var ngChangeDirective = valueFn({ }); -/** - * @ngdoc directive - * @name angular.module.ng.$compileProvider.directive.ng-model-instant - * - * @element input - * - * @description - * By default, Angular udpates the model only on `blur` event - when the input looses focus. - * If you want to update after every key stroke, use `ng-model-instant`. - * - * @example - * <doc:example> - * <doc:source> - * First name: <input type="text" ng-model="firstName" /><br /> - * Last name: <input type="text" ng-model="lastName" ng-model-instant /><br /> - * - * First name ({{firstName}}) is only updated on `blur` event, but the last name ({{lastName}}) - * is updated immediately, because of using `ng-model-instant`. - * </doc:source> - * <doc:scenario> - * it('should update first name on blur', function() { - * input('firstName').enter('santa', 'blur'); - * expect(binding('firstName')).toEqual('santa'); - * }); - * - * it('should update last name immediately', function() { - * input('lastName').enter('santa', 'keydown'); - * expect(binding('lastName')).toEqual('santa'); - * }); - * </doc:scenario> - * </doc:example> - */ -var ngModelInstantDirective = ['$browser', function($browser) { - return { - require: 'ngModel', - link: function(scope, element, attr, ctrl) { - var handler = function() { - scope.$apply(function() { - ctrl.$setViewValue(trim(element.val())); - }); - }; - - var timeout; - element.bind('keydown', function(event) { - var key = event.keyCode; - - // command modifiers arrows - if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; - - if (!timeout) { - timeout = $browser.defer(function() { - handler(); - timeout = null; - }); - } - }); - - element.bind('change input', handler); - } - }; -}]; - - var requiredDirective = [function() { return { require: '?ngModel', diff --git a/src/ngScenario/Scenario.js b/src/ngScenario/Scenario.js index cd3c335f..7335d5de 100644 --- a/src/ngScenario/Scenario.js +++ b/src/ngScenario/Scenario.js @@ -327,7 +327,7 @@ function browserTrigger(element, type, keys) { (function(fn){ var parentTrigger = fn.trigger; fn.trigger = function(type) { - if (/(click|change|keydown|blur)/.test(type)) { + if (/(click|change|keydown|blur|input)/.test(type)) { var processDefaults = []; this.each(function(index, node) { processDefaults.push(browserTrigger(node, type)); diff --git a/src/ngScenario/dsl.js b/src/ngScenario/dsl.js index 8a1bccb1..7f399394 100644 --- a/src/ngScenario/dsl.js +++ b/src/ngScenario/dsl.js @@ -198,12 +198,13 @@ angular.scenario.dsl('binding', function() { */ angular.scenario.dsl('input', function() { var chain = {}; + var supportInputEvent = 'oninput' in document.createElement('div'); chain.enter = function(value, event) { return this.addFutureAction("input '" + this.name + "' enter '" + value + "'", function($window, $document, done) { var input = $document.elements('[ng\\:model="$1"]', this.name).filter(':input'); input.val(value); - input.trigger(event || 'blur'); + input.trigger(event || supportInputEvent && 'input' || 'change'); done(); }); }; |
