diff --git a/src/ng/directive/booleanAttrs.js b/src/ng/directive/booleanAttrs.js index 5da98ef425b0..1468008ccdd2 100644 --- a/src/ng/directive/booleanAttrs.js +++ b/src/ng/directive/booleanAttrs.js @@ -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); } }; } diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index dadf07c4c37b..6e394afd379f 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -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 { diff --git a/src/ng/sniffer.js b/src/ng/sniffer.js index 5389dc863a50..b19e7ccf4832 100644 --- a/src/ng/sniffer.js +++ b/src/ng/sniffer.js @@ -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; diff --git a/test/ng/directive/booleanAttrsSpec.js b/test/ng/directive/booleanAttrsSpec.js index f398441e7df3..435ffcb9727f 100644 --- a/test/ng/directive/booleanAttrsSpec.js +++ b/test/ng/directive/booleanAttrsSpec.js @@ -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('
')($rootScope) + var element = $compile('')($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('')($rootScope); + + $rootScope.$digest(); + expect(element.prop('src')).toEqual('some/'); + + $rootScope.$apply(function() { + $rootScope.id = 1; + }); + expect(element.prop('src')).toEqual('some/1'); + + dealoc(element); + })); + } }); diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index 6cecf125e48f..45e3e1bf918b 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -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); diff --git a/test/ng/snifferSpec.js b/test/ng/snifferSpec.js index 4e5f50ec8fd9..81a0db5e54fe 100644 --- a/test/ng/snifferSpec.js +++ b/test/ng/snifferSpec.js @@ -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); + }); }); });