Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 363e4cb

Browse files
markdalgleishpetebacondarwin
authored andcommitted
fix(ngModel): use paste/cut events in IE to support context menu
In IE the model is not updated when the input value is modified using the context menu, e.g. pasting from the clipboard, or cutting all or part of the current value. To capture these changes, we bind to the proprietary 'paste' and 'cut' events. Closes #1462
1 parent c4d5631 commit 363e4cb

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

src/ng/directive/input.js

+15-6
Original file line numberDiff line numberDiff line change
@@ -413,23 +413,32 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
413413
} else {
414414
var timeout;
415415

416+
var deferListener = function() {
417+
if (!timeout) {
418+
timeout = $browser.defer(function() {
419+
listener();
420+
timeout = null;
421+
});
422+
}
423+
};
424+
416425
element.bind('keydown', function(event) {
417426
var key = event.keyCode;
418427

419428
// ignore
420429
// command modifiers arrows
421430
if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
422431

423-
if (!timeout) {
424-
timeout = $browser.defer(function() {
425-
listener();
426-
timeout = null;
427-
});
428-
}
432+
deferListener();
429433
});
430434

431435
// if user paste into input using mouse, we need "change" event to catch it
432436
element.bind('change', listener);
437+
438+
// if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
439+
if ($sniffer.hasEvent('paste')) {
440+
element.bind('paste cut', deferListener);
441+
}
433442
}
434443

435444

test/ng/directive/inputSpec.js

+32-2
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ describe('ngModel', function() {
309309

310310

311311
describe('input', function() {
312-
var formElm, inputElm, scope, $compile, changeInputValueTo;
312+
var formElm, inputElm, scope, $compile, $sniffer, $browser, changeInputValueTo;
313313

314314
function compileInput(inputHtml) {
315315
inputElm = jqLite(inputHtml);
@@ -318,7 +318,9 @@ describe('input', function() {
318318
$compile(formElm)(scope);
319319
}
320320

321-
beforeEach(inject(function($injector, $sniffer) {
321+
beforeEach(inject(function($injector, _$sniffer_, _$browser_) {
322+
$sniffer = _$sniffer_;
323+
$browser = _$browser_;
322324
$compile = $injector.get('$compile');
323325
scope = $injector.get('$rootScope');
324326

@@ -385,6 +387,34 @@ describe('input', function() {
385387
expect(scope.name).toEqual('adam');
386388
});
387389

390+
describe('"paste" and "cut" events', function() {
391+
beforeEach(function() {
392+
// Force browser to report a lack of an 'input' event
393+
$sniffer.hasEvent = function(eventName) {
394+
return eventName !== 'input';
395+
};
396+
});
397+
398+
it('should update the model on "paste" event', function() {
399+
compileInput('<input type="text" ng-model="name" name="alias" ng-change="change()" />');
400+
401+
inputElm.val('mark');
402+
browserTrigger(inputElm, 'paste');
403+
$browser.defer.flush();
404+
expect(scope.name).toEqual('mark');
405+
});
406+
407+
it('should update the model on "cut" event', function() {
408+
compileInput('<input type="text" ng-model="name" name="alias" ng-change="change()" />');
409+
410+
inputElm.val('john');
411+
browserTrigger(inputElm, 'cut');
412+
$browser.defer.flush();
413+
expect(scope.name).toEqual('john');
414+
});
415+
416+
});
417+
388418

389419
it('should update the model and trim the value', function() {
390420
compileInput('<input type="text" ng-model="name" name="alias" ng-change="change()" />');

0 commit comments

Comments
 (0)