aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Dalgleish2013-03-21 18:07:49 +1100
committerPete Bacon Darwin2013-04-17 21:20:08 +0100
commit363e4cbf649de4c5206f1904ee76f89301ceaab0 (patch)
tree34ae51c17ec2698732332f5a2975df282b71c85e
parentc4d5631f1a3d66340f82a0cd6a50d53057110c1a (diff)
downloadangular.js-363e4cbf649de4c5206f1904ee76f89301ceaab0.tar.bz2
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
-rw-r--r--src/ng/directive/input.js21
-rw-r--r--test/ng/directive/inputSpec.js34
2 files changed, 47 insertions, 8 deletions
diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js
index 2574360c..db594ebe 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 d69be27c..f8898074 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('<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()" />');