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
This commit is contained in:
Mark Dalgleish 2013-03-21 18:07:49 +11:00 committed by Pete Bacon Darwin
parent c4d5631f1a
commit 363e4cbf64
2 changed files with 47 additions and 8 deletions

View file

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

View file

@ -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('<input type="text" ng-model="name" name="alias" ng-change="change()" />');
inputElm.val('mark');
browserTrigger(inputElm, 'paste');
$browser.defer.flush();
expect(scope.name).toEqual('mark');
});
it('should update the model on "cut" event', function() {
compileInput('<input type="text" ng-model="name" name="alias" ng-change="change()" />');
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('<input type="text" ng-model="name" name="alias" ng-change="change()" />');