Bug Tracker

Modify

Ticket #10832 (closed bug: fixed)

Opened 2 years ago

Last modified 17 months ago

jQuery.contains() fails with SVG elements in IE9 (includes solution)

Reported by: NinjaFish Owned by: timmywil
Priority: low Milestone: None
Component: selector Version: 1.7.1rc1
Keywords: Cc:
Blocking: Blocked by:

Description

See  http://forum.jquery.com/topic/1-6-2-broke-svg-hover-events for the initial discussion.

The currently implemented fallback strategy for jQuery.contains() fails when checking the state of SVG elements in IE9. This is because, while standard DOM elements in IE9 provide a native implementation for contains(), SVG elements do not. As the default result of contains() is "true", you end up with a situation where jQuery reports that two elements contain each other.

SVG elements in IE9 do provide an implementation of compareDocumentPosition(), which appears to provide the expected results. If the most-preferred implementation of contains() were allowed to fall back to compareDocumentPosition() on a per-element basis (rather than globally, as it does today), then jQuery.contains() should work in all cases in IE9.

The following jsFiddle demonstrates the problem and my solution:  http://jsfiddle.net/NinjaFish/7pjCx/

The box should change from blue to red on mouseenter. This does not happen in IE9. You can uncomment the example override script to demonstrate the fix working as intended.

In my own copy of jQuery 1.7, I have changed the contains() implementation on line 5308 from this:

return a !== b && (a.contains ? a.contains(b) : true);

to this:

return a !== b && (a.contains 
	? a.contains(b) 
	: a.compareDocumentPosition 
		? !!(a.compareDocumentPosition(b) & 16) 
		: true);

This is the same implementation as used in the jsFiddle above, and borrows jQuery's existing compareDocumentPosition() implementation.

As far as I have seen, this is only an issue in IE9. All other browsers that I have looked at (Chrome, Firefox 3.x and 6+) work correctly both before and after the change.

Change History

comment:1 Changed 2 years ago by timmywil

  • Owner set to timmywil
  • Priority changed from undecided to low
  • Status changed from new to assigned
  • Component changed from unfiled to selector

I think perhaps we could switch the contains method to use compareDocumentPosition first. This will be good to look at in the 1.8 Sizzle revamp. I was already looking at rewriting the contains method a bit.

comment:2 Changed 23 months ago by timmywil

  • Status changed from assigned to closed
  • Resolution set to fixed

comment:3 Changed 17 months ago by anonymous

Seems that the problem was re-introduced by the fix to http://bugs.jquery.com/ticket/12314

contains was changed to use the native contains and it is not available on the svg element.

comment:4 Changed 17 months ago by Richard Gibson

Fix #10832 (this time with tests): jQuery.contains in SVG

Changeset: abe009cf263e2d3f29d96ad5abe5343922b11510

Please follow the  bug reporting guidlines and use  jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

View

Add a comment

Modify Ticket

Action
as closed
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.