diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js
index aaabd1033398..797600075537 100644
--- a/src/ng/directive/input.js
+++ b/src/ng/directive/input.js
@@ -413,6 +413,15 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
} else {
var timeout;
+ var deferListener = function() {
+ if (!timeout) {
+ timeout = $browser.defer(function() {
+ listener();
+ timeout = null;
+ });
+ }
+ };
+
element.bind('keydown', function(event) {
var key = event.keyCode;
@@ -420,16 +429,16 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
// command modifiers arrows
if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
- if (!timeout) {
- timeout = $browser.defer(function() {
- listener();
- timeout = null;
- });
- }
+ deferListener();
});
// if user paste into input using mouse, we need "change" event to catch it
element.bind('change', listener);
+
+ // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
+ if ($sniffer.hasEvent('paste')) {
+ element.bind('paste cut', deferListener);
+ }
}
diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js
index 4dcb79a38d12..e1f24afd30f9 100644
--- a/test/ng/directive/inputSpec.js
+++ b/test/ng/directive/inputSpec.js
@@ -309,7 +309,7 @@ describe('ngModel', function() {
describe('input', function() {
- var formElm, inputElm, scope, $compile, changeInputValueTo;
+ var formElm, inputElm, scope, $compile, $sniffer, $browser, changeInputValueTo;
function compileInput(inputHtml) {
inputElm = jqLite(inputHtml);
@@ -318,7 +318,9 @@ describe('input', function() {
$compile(formElm)(scope);
}
- beforeEach(inject(function($injector, $sniffer) {
+ beforeEach(inject(function($injector, _$sniffer_, _$browser_) {
+ $sniffer = _$sniffer_;
+ $browser = _$browser_;
$compile = $injector.get('$compile');
scope = $injector.get('$rootScope');
@@ -385,6 +387,34 @@ describe('input', function() {
expect(scope.name).toEqual('adam');
});
+ describe('"paste" and "cut" events', function() {
+ beforeEach(function() {
+ // Force browser to report a lack of an 'input' event
+ $sniffer.hasEvent = function(eventName) {
+ return eventName !== 'input';
+ };
+ });
+
+ it('should update the model on "paste" event', function() {
+ compileInput('');
+
+ inputElm.val('mark');
+ browserTrigger(inputElm, 'paste');
+ $browser.defer.flush();
+ expect(scope.name).toEqual('mark');
+ });
+
+ it('should update the model on "cut" event', function() {
+ compileInput('');
+
+ inputElm.val('john');
+ browserTrigger(inputElm, 'cut');
+ $browser.defer.flush();
+ expect(scope.name).toEqual('john');
+ });
+
+ });
+
it('should update the model and trim the value', function() {
compileInput('');