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

fix(ngModel): use keydown/change events on IE9 instead of input #936

Merged
merged 2 commits into from
May 7, 2012
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/ng/directive/booleanAttrs.js
Original file line number Diff line number Diff line change
@@ -310,10 +310,16 @@ forEach(['src', 'href'], function(attrName) {
attr.$$observers[attrName] = [];
attr.$observe(normalized, function(value) {
attr.$set(attrName, value);

// on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
// then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
// to set the property as well to achieve the desired effect
if (msie) element.prop(attrName, value);
});
} else {
// value present means that no interpolation, so copy to native attribute.
attr.$set(attrName, value);
element.prop(attrName, value);
}
};
}
3 changes: 2 additions & 1 deletion src/ng/directive/input.js
Original file line number Diff line number Diff line change
@@ -379,7 +379,8 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
}
};

// if the browser does support "input" event, we are fine
// if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
// input event on backspace, delete or cut
if ($sniffer.hasEvent('input')) {
element.bind('input', listener);
} else {
5 changes: 5 additions & 0 deletions src/ng/sniffer.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,11 @@ function $SnifferProvider() {
// IE8 compatible mode lies
(!$window.document.documentMode || $window.document.documentMode > 7),
hasEvent: function(event) {
// IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
// it. In particular the event is not fired when backspace or delete key are pressed or
// when cut operation is performed.
if (event == 'input' && msie == 9) return false;

if (isUndefined(eventSupport[event])) {
var divElm = $window.document.createElement('div');
eventSupport[event] = 'on' + event in divElm;
24 changes: 23 additions & 1 deletion test/ng/directive/booleanAttrsSpec.js
Original file line number Diff line number Diff line change
@@ -80,7 +80,8 @@ describe('boolean attr directives', function() {
describe('ngSrc', function() {

it('should interpolate the expression and bind to src', inject(function($compile, $rootScope) {
var element = $compile('<div ng-src="some/{{id}}"></div>')($rootScope)
var element = $compile('<div ng-src="some/{{id}}"></div>')($rootScope);

$rootScope.$digest();
expect(element.attr('src')).toEqual('some/');

@@ -91,6 +92,27 @@ describe('ngSrc', function() {

dealoc(element);
}));

if (msie) {
it('should update the element property as well as the attribute', inject(
function($compile, $rootScope) {
// on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
// then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
// to set the property as well to achieve the desired effect

var element = $compile('<div ng-src="some/{{id}}"></div>')($rootScope);

$rootScope.$digest();
expect(element.prop('src')).toEqual('some/');

$rootScope.$apply(function() {
$rootScope.id = 1;
});
expect(element.prop('src')).toEqual('some/1');

dealoc(element);
}));
}
});


2 changes: 1 addition & 1 deletion test/ng/directive/inputSpec.js
Original file line number Diff line number Diff line change
@@ -254,7 +254,7 @@ describe('ngModel', function() {
expect(element.hasClass('ng-invalid-email')).toBe(true);

element.val('invalid-again');
browserTrigger(element, $sniffer.hasEvent('input') ? 'input' : 'change');
browserTrigger(element, ($sniffer.hasEvent('input')) ? 'input' : 'change');
expect(element).toBeInvalid();
expect(element).toBeDirty();
expect(element.hasClass('ng-valid-email')).toBe(false);
20 changes: 14 additions & 6 deletions test/ng/snifferSpec.js
Original file line number Diff line number Diff line change
@@ -45,10 +45,10 @@ describe('$sniffer', function() {
});


it('should return true if "oninput" is present in a div element', function() {
mockDivElement = {oninput: noop};
it('should return true if "onchange" is present in a div element', function() {
mockDivElement = {onchange: noop};

expect($sniffer.hasEvent('input')).toBe(true);
expect($sniffer.hasEvent('change')).toBe(true);
});


@@ -62,11 +62,19 @@ describe('$sniffer', function() {
it('should only create the element once', function() {
mockDivElement = {};

$sniffer.hasEvent('input');
$sniffer.hasEvent('input');
$sniffer.hasEvent('input');
$sniffer.hasEvent('change');
$sniffer.hasEvent('change');
$sniffer.hasEvent('change');

expect(mockDocument.createElement).toHaveBeenCalledOnce();
});


it('should claim that IE9 doesn\'t have support for "oninput"', function() {
// IE9 implementation is fubared, so it's better to pretend that it doesn't have the support
mockDivElement = {oninput: noop};

expect($sniffer.hasEvent('input')).toBe((msie == 9) ? false : true);
});
});
});