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);
});