diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index db514ec17396..d0a57acc540d 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -994,16 +994,27 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { } }; - element.on('keydown', function(event) { - var key = event.keyCode; + element.on('keypress', function(event) { + var key = event.keyCode, + multiline = event.target.nodeName.toLowerCase() === 'textarea'; // ignore - // command modifiers arrows - if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; + // escape enter + if (key === 27 || (key === 13 && !multiline)) return; deferListener(event); }); + element.on('keydown', function(event) { + var key = event.keyCode; + + // only fire listener for a few extra keys not captured by "keypress" + // backspace delete + if (key === 8 || key === 46) { + deferListener(event); + } + }); + // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it if ($sniffer.hasEvent('paste')) { element.on('paste cut', deferListener); diff --git a/src/ng/sniffer.js b/src/ng/sniffer.js index 6b2ea859eb4c..805969ddfab8 100644 --- a/src/ng/sniffer.js +++ b/src/ng/sniffer.js @@ -70,8 +70,8 @@ function $SnifferProvider() { if (event == 'input' && msie == 9) return false; if (isUndefined(eventSupport[event])) { - var divElm = document.createElement('div'); - eventSupport[event] = 'on' + event in divElm; + var elm = document.createElement('input'); + eventSupport[event] = 'on' + event in elm; } return eventSupport[event]; diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index 2d3fb269e3eb..65c9a9f1d86d 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -1495,7 +1495,7 @@ describe('input', function() { } }); - describe('"paste" and "cut" events', function() { + describe('legacy events', function() { beforeEach(function() { // Force browser to report a lack of an 'input' event $sniffer.hasEvent = function(eventName) { @@ -1521,8 +1521,23 @@ describe('input', function() { expect(scope.name).toEqual('john'); }); - }); + it('should update the model on "keypress" event', function() { + compileInput(''); + + inputElm.val('cassius'); + browserTrigger(inputElm, 'keypress'); + $browser.defer.flush(); + expect(scope.name).toEqual('cassius'); + }); + it('should not dirty the model on "keydown" event', function() { + compileInput(''); + + browserTrigger(inputElm, 'keydown'); + $browser.defer.flush(); + expect(inputElm).toBePristine(); + }); + }); it('should update the model and trim the value', function() { compileInput(''); diff --git a/test/ng/snifferSpec.js b/test/ng/snifferSpec.js index 7d48bc79ffea..d68b5ae0d534 100644 --- a/test/ng/snifferSpec.js +++ b/test/ng/snifferSpec.js @@ -25,12 +25,12 @@ describe('$sniffer', function() { describe('hasEvent', function() { - var mockDocument, mockDivElement, $sniffer; + var mockDocument, mockElement, $sniffer; beforeEach(function() { mockDocument = {createElement: jasmine.createSpy('createElement')}; mockDocument.createElement.andCallFake(function(elm) { - if (elm === 'div') return mockDivElement; + if (elm === 'input') return mockElement; }); $sniffer = sniffer({}, mockDocument); @@ -38,21 +38,21 @@ describe('$sniffer', function() { it('should return true if "onchange" is present in a div element', function() { - mockDivElement = {onchange: noop}; + mockElement = {onchange: noop}; expect($sniffer.hasEvent('change')).toBe(true); }); it('should return false if "oninput" is not present in a div element', function() { - mockDivElement = {}; + mockElement = {}; expect($sniffer.hasEvent('input')).toBe(false); }); it('should only create the element once', function() { - mockDivElement = {}; + mockElement = {}; $sniffer.hasEvent('change'); $sniffer.hasEvent('change'); @@ -64,7 +64,7 @@ describe('$sniffer', function() { it('should claim that IE9 doesn\'t have support for "oninput"', function() { // IE9 implementation is fubared, so it's better to pretend that it doesn't have the support - mockDivElement = {oninput: noop}; + mockElement = {oninput: noop}; expect($sniffer.hasEvent('input')).toBe((msie == 9) ? false : true); });