From 7947bc91ade9309e2de26ec56767b340db82977b Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Wed, 6 Jan 2016 22:43:10 +0100 Subject: [PATCH] fix(ngAnimate): allow event listeners on document in IE Fixes #13548 --- src/ngAnimate/animateQueue.js | 11 ++++++++-- test/ngAnimate/animateSpec.js | 39 ++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js index fbfc0cc78426..89fe6cad31f0 100644 --- a/src/ngAnimate/animateQueue.js +++ b/src/ngAnimate/animateQueue.js @@ -171,6 +171,13 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { return mergeAnimationOptions(element, options, {}); } + // IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259. + var contains = Node.prototype.contains || function(arg) { + // jshint bitwise: false + return this === arg || !!(this.compareDocumentPosition(arg) & 16); + // jshint bitwise: true + }; + function findCallbacks(parent, element, event) { var targetNode = getDomNode(element); var targetParentNode = getDomNode(parent); @@ -179,9 +186,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { var entries = callbackRegistry[event]; if (entries) { forEach(entries, function(entry) { - if (entry.node.contains(targetNode)) { + if (contains.call(entry.node, targetNode)) { matches.push(entry.callback); - } else if (event === 'leave' && entry.node.contains(targetParentNode)) { + } else if (event === 'leave' && contains.call(entry.node, targetParentNode)) { matches.push(entry.callback); } }); diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index dc665ead5398..56efecef20a3 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -1535,7 +1535,9 @@ describe("animations", function() { }); return function($document, $rootElement, $animate) { - jqLite($document[0].body).append($rootElement); + if ($document !== $rootElement) { + jqLite($document[0].body).append($rootElement); + } $animate.enabled(true); }; })); @@ -1946,5 +1948,40 @@ describe("animations", function() { expect(capturedElement).toBe(element); })); + they('should trigger a callback for a $prop animation if the listener is on the document', + ['enter', 'leave'], function($event) { + module(function($provide) { + $provide.factory('$rootElement', function($document) { + // Since we listen on document, $document must be the $rootElement for animations to work + return $document; + }); + }); + + inject(function($animate, $rootScope, $document) { + + var callbackTriggered = false; + + + $animate.on($event, $document[0], function() { + callbackTriggered = true; + }); + + var container = jqLite('
'); + jqLite($document[0].body).append(container); + element = jqLite('
'); + + if ($event === 'leave') { + container.append(element); + } + + $animate[$event](element, container); + $rootScope.$digest(); + + $animate.flush(); + + expect(callbackTriggered).toBe(true); + }); + }); + }); });