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

Commit 3ebc2c2

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 631d86f commit 3ebc2c2

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
@@ -398,23 +398,32 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
398398
} else {
399399
var timeout;
400400

401+
var deferListener = function() {
402+
if (!timeout) {
403+
timeout = $browser.defer(function() {
404+
listener();
405+
timeout = null;
406+
});
407+
}
408+
};
409+
401410
element.bind('keydown', function(event) {
402411
var key = event.keyCode;
403412

404413
// ignore
405414
// command modifiers arrows
406415
if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
407416

408-
if (!timeout) {
409-
timeout = $browser.defer(function() {
410-
listener();
411-
timeout = null;
412-
});
413-
}
417+
deferListener();
414418
});
415419

416420
// if user paste into input using mouse, we need "change" event to catch it
417421
element.bind('change', listener);
422+
423+
// if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
424+
if ($sniffer.hasEvent('paste')) {
425+
element.bind('paste cut', deferListener);
426+
}
418427
}
419428

420429

test/ng/directive/inputSpec.js

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

298298

299299
describe('input', function() {
300-
var formElm, inputElm, scope, $compile, changeInputValueTo;
300+
var formElm, inputElm, scope, $compile, $sniffer, $browser, changeInputValueTo;
301301

302302
function compileInput(inputHtml) {
303303
inputElm = jqLite(inputHtml);
@@ -306,7 +306,9 @@ describe('input', function() {
306306
$compile(formElm)(scope);
307307
}
308308

309-
beforeEach(inject(function($injector, $sniffer) {
309+
beforeEach(inject(function($injector, _$sniffer_, _$browser_) {
310+
$sniffer = _$sniffer_;
311+
$browser = _$browser_;
310312
$compile = $injector.get('$compile');
311313
scope = $injector.get('$rootScope');
312314

@@ -373,6 +375,34 @@ describe('input', function() {
373375
expect(scope.name).toEqual('adam');
374376
});
375377

378+
describe('"paste" and "cut" events', function() {
379+
beforeEach(function() {
380+
// Force browser to report a lack of an 'input' event
381+
$sniffer.hasEvent = function(eventName) {
382+
return eventName !== 'input';
383+
};
384+
});
385+
386+
it('should update the model on "paste" event', function() {
387+
compileInput('<input type="text" ng-model="name" name="alias" ng-change="change()" />');
388+
389+
inputElm.val('mark');
390+
browserTrigger(inputElm, 'paste');
391+
$browser.defer.flush();
392+
expect(scope.name).toEqual('mark');
393+
});
394+
395+
it('should update the model on "cut" event', function() {
396+
compileInput('<input type="text" ng-model="name" name="alias" ng-change="change()" />');
397+
398+
inputElm.val('john');
399+
browserTrigger(inputElm, 'cut');
400+
$browser.defer.flush();
401+
expect(scope.name).toEqual('john');
402+
});
403+
404+
});
405+
376406

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

0 commit comments

Comments
 (0)