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

Commit 941c1c3

Browse files
Kuzminov Aleksandr Sergeevichpetebacondarwin
Kuzminov Aleksandr Sergeevich
authored andcommitted
fix(jqLite): ensure mouseenter works with svg elements on IE
Closes #10259 Closes #10276
1 parent 29a0598 commit 941c1c3

File tree

2 files changed

+64
-32
lines changed

2 files changed

+64
-32
lines changed

src/jqLite.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,14 @@ function jqLiteParseHTML(html, context) {
241241
return [];
242242
}
243243

244+
245+
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
246+
var jqLiteContains = Node.prototype.contains || function(arg) {
247+
// jshint bitwise: false
248+
return !!(this.compareDocumentPosition(arg) & 16);
249+
// jshint bitwise: true
250+
};
251+
244252
/////////////////////////////////////////////
245253
function JQLite(element) {
246254
if (element instanceof JQLite) {
@@ -826,7 +834,7 @@ forEach({
826834
var target = this, related = event.relatedTarget;
827835
// For mousenter/leave call the handler if related is outside the target.
828836
// NB: No relatedTarget if the mouse left/entered the browser window
829-
if (!related || (related !== target && !target.contains(related))) {
837+
if (!related || (related !== target && !jqLiteContains.call(target, related))) {
830838
handle(event, type);
831839
}
832840
});

test/jqLiteSpec.js

+55-31
Original file line numberDiff line numberDiff line change
@@ -1193,52 +1193,54 @@ describe('jqLite', function() {
11931193
});
11941194

11951195
describe('mouseenter-mouseleave', function() {
1196-
var root, parent, sibling, child, log;
1196+
var root, parent, child, log;
11971197

1198-
beforeEach(function() {
1198+
function setup(html, parentNode, childNode) {
11991199
log = '';
1200-
root = jqLite('<div>root<p>parent<span>child</span></p><ul></ul></div>');
1201-
parent = root.find('p');
1202-
sibling = root.find('ul');
1203-
child = parent.find('span');
1200+
root = jqLite(html);
1201+
parent = root.find(parentNode);
1202+
child = parent.find(childNode);
12041203

12051204
parent.on('mouseenter', function() { log += 'parentEnter;'; });
12061205
parent.on('mouseleave', function() { log += 'parentLeave;'; });
12071206

12081207
child.on('mouseenter', function() { log += 'childEnter;'; });
12091208
child.on('mouseleave', function() { log += 'childLeave;'; });
1210-
});
1209+
}
1210+
1211+
function browserMoveTrigger(from, to) {
1212+
var fireEvent = function(type, element, relatedTarget) {
1213+
var evnt;
1214+
evnt = document.createEvent('MouseEvents');
1215+
1216+
var originalPreventDefault = evnt.preventDefault,
1217+
appWindow = window,
1218+
fakeProcessDefault = true,
1219+
finalProcessDefault;
1220+
1221+
evnt.preventDefault = function() {
1222+
fakeProcessDefault = false;
1223+
return originalPreventDefault.apply(evnt, arguments);
1224+
};
1225+
1226+
var x = 0, y = 0;
1227+
evnt.initMouseEvent(type, true, true, window, 0, x, y, x, y, false, false,
1228+
false, false, 0, relatedTarget);
1229+
1230+
element.dispatchEvent(evnt);
1231+
};
1232+
fireEvent('mouseout', from[0], to[0]);
1233+
fireEvent('mouseover', to[0], from[0]);
1234+
}
12111235

12121236
afterEach(function() {
12131237
dealoc(root);
12141238
});
12151239

12161240
it('should fire mouseenter when coming from outside the browser window', function() {
12171241
if (window.jQuery) return;
1218-
var browserMoveTrigger = function(from, to) {
1219-
var fireEvent = function(type, element, relatedTarget) {
1220-
var evnt;
1221-
evnt = document.createEvent('MouseEvents');
1222-
1223-
var originalPreventDefault = evnt.preventDefault,
1224-
appWindow = window,
1225-
fakeProcessDefault = true,
1226-
finalProcessDefault;
1227-
1228-
evnt.preventDefault = function() {
1229-
fakeProcessDefault = false;
1230-
return originalPreventDefault.apply(evnt, arguments);
1231-
};
1232-
1233-
var x = 0, y = 0;
1234-
evnt.initMouseEvent(type, true, true, window, 0, x, y, x, y, false, false,
1235-
false, false, 0, relatedTarget);
1236-
1237-
element.dispatchEvent(evnt);
1238-
};
1239-
fireEvent('mouseout', from[0], to[0]);
1240-
fireEvent('mouseover', to[0], from[0]);
1241-
};
1242+
1243+
setup('<div>root<p>parent<span>child</span></p><ul></ul></div>', 'p', 'span');
12421244

12431245
browserMoveTrigger(root, parent);
12441246
expect(log).toEqual('parentEnter;');
@@ -1253,6 +1255,28 @@ describe('jqLite', function() {
12531255
expect(log).toEqual('parentEnter;childEnter;childLeave;parentLeave;');
12541256

12551257
});
1258+
1259+
it('should fire the mousenter on SVG elements', function() {
1260+
if (window.jQuery) return;
1261+
1262+
setup(
1263+
'<div>' +
1264+
'<svg xmlns="http://www.w3.org/2000/svg"' +
1265+
' viewBox="0 0 18.75 18.75"' +
1266+
' width="18.75"' +
1267+
' height="18.75"' +
1268+
' version="1.1">' +
1269+
' <path d="M0,0c0,4.142,3.358,7.5,7.5,7.5s7.5-3.358,7.5-7.5-3.358-7.5-7.5-7.5-7.5,3.358-7.5,7.5"' +
1270+
' fill-rule="nonzero"' +
1271+
' fill="#CCC"' +
1272+
' ng-attr-fill="{{data.color || \'#CCC\'}}"/>' +
1273+
'</svg>' +
1274+
'</div>',
1275+
'svg', 'path');
1276+
1277+
browserMoveTrigger(parent, child);
1278+
expect(log).toEqual('childEnter;');
1279+
});
12561280
});
12571281

12581282
// Only run this test for jqLite and not normal jQuery

0 commit comments

Comments
 (0)