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

Commit

Permalink
fix(jqLite): ensure mouseenter works with svg elements on IE
Browse files Browse the repository at this point in the history
Closes #10259
Closes #10276
  • Loading branch information
Kuzminov Aleksandr Sergeevich authored and petebacondarwin committed Oct 26, 2015
1 parent 7bf5429 commit c1f34e8
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 32 deletions.
10 changes: 9 additions & 1 deletion src/jqLite.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,14 @@ function jqLiteParseHTML(html, context) {
return [];
}


// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
var jqLiteContains = Node.prototype.contains || function(arg) {
// jshint bitwise: false
return !!(this.compareDocumentPosition(arg) & 16);
// jshint bitwise: true
};

/////////////////////////////////////////////
function JQLite(element) {
if (element instanceof JQLite) {
Expand Down Expand Up @@ -826,7 +834,7 @@ forEach({
var target = this, related = event.relatedTarget;
// For mousenter/leave call the handler if related is outside the target.
// NB: No relatedTarget if the mouse left/entered the browser window
if (!related || (related !== target && !target.contains(related))) {
if (!related || (related !== target && !jqLiteContains.call(target, related))) {
handle(event, type);
}
});
Expand Down
86 changes: 55 additions & 31 deletions test/jqLiteSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1193,52 +1193,54 @@ describe('jqLite', function() {
});

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

beforeEach(function() {
function setup(html, parentNode, childNode) {
log = '';
root = jqLite('<div>root<p>parent<span>child</span></p><ul></ul></div>');
parent = root.find('p');
sibling = root.find('ul');
child = parent.find('span');
root = jqLite(html);
parent = root.find(parentNode);
child = parent.find(childNode);

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

child.on('mouseenter', function() { log += 'childEnter;'; });
child.on('mouseleave', function() { log += 'childLeave;'; });
});
}

function browserMoveTrigger(from, to) {
var fireEvent = function(type, element, relatedTarget) {
var evnt;
evnt = document.createEvent('MouseEvents');

var originalPreventDefault = evnt.preventDefault,
appWindow = window,
fakeProcessDefault = true,
finalProcessDefault;

evnt.preventDefault = function() {
fakeProcessDefault = false;
return originalPreventDefault.apply(evnt, arguments);
};

var x = 0, y = 0;
evnt.initMouseEvent(type, true, true, window, 0, x, y, x, y, false, false,
false, false, 0, relatedTarget);

element.dispatchEvent(evnt);
};
fireEvent('mouseout', from[0], to[0]);
fireEvent('mouseover', to[0], from[0]);
}

afterEach(function() {
dealoc(root);
});

it('should fire mouseenter when coming from outside the browser window', function() {
if (window.jQuery) return;
var browserMoveTrigger = function(from, to) {
var fireEvent = function(type, element, relatedTarget) {
var evnt;
evnt = document.createEvent('MouseEvents');

var originalPreventDefault = evnt.preventDefault,
appWindow = window,
fakeProcessDefault = true,
finalProcessDefault;

evnt.preventDefault = function() {
fakeProcessDefault = false;
return originalPreventDefault.apply(evnt, arguments);
};

var x = 0, y = 0;
evnt.initMouseEvent(type, true, true, window, 0, x, y, x, y, false, false,
false, false, 0, relatedTarget);

element.dispatchEvent(evnt);
};
fireEvent('mouseout', from[0], to[0]);
fireEvent('mouseover', to[0], from[0]);
};

setup('<div>root<p>parent<span>child</span></p><ul></ul></div>', 'p', 'span');

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

});

it('should fire the mousenter on SVG elements', function() {
if (window.jQuery) return;

setup(
'<div>' +
'<svg xmlns="http://www.w3.org/2000/svg"' +
' viewBox="0 0 18.75 18.75"' +
' width="18.75"' +
' height="18.75"' +
' version="1.1">' +
' <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"' +
' fill-rule="nonzero"' +
' fill="#CCC"' +
' ng-attr-fill="{{data.color || \'#CCC\'}}"/>' +
'</svg>' +
'</div>',
'svg', 'path');

browserMoveTrigger(parent, child);
expect(log).toEqual('childEnter;');
});
});

// Only run this test for jqLite and not normal jQuery
Expand Down

0 comments on commit c1f34e8

Please sign in to comment.