Skip to main content

Bug Tracker

Side navigation

#8046 closed bug (wontfix)

Opened January 25, 2011 08:15AM UTC

Closed January 25, 2011 01:55PM UTC

Last modified March 13, 2012 06:29PM UTC

$().find() triggers DOMSubTreeModified events

Reported by: judson@lrdesign.com Owned by:
Priority: low Milestone: 1.next
Component: selector Version: 1.4.3
Keywords: Cc:
Blocked by: Blocking:
Description

I've been building a library to make packaging behaviors simple. It works very well against jQuery 1.4.2. However, the Sizzle included in 1.4.3 and 1.4.4 uses a technique to keep track of it's place in the DOM - it changes the id of nodes as it traverses. In 1.4.3, it's about line 3904 of the unmini'd version.

When the id changes (at least in Chrome) a DOMSubtreeModified event gets thrown. The trouble is, I've attached a handler to the document for DSM events that needs to find the target Element - which triggers a DSM.

Is it reasonable for $().find(selector) to trigger an event?

Attachments (0)
Change History (4)

Changed January 25, 2011 01:55PM UTC by rwaldron comment:1

component: unfiledselector
priority: undecidedlow
resolution: → wontfix
status: newclosed

Thanks for reporting this, but jQuery cannot provide support to deprecated specs (the mutation events).

Changed January 26, 2011 12:15AM UTC by anonymous comment:2

That's incredibly disappointing, since there aren't satisfactory replacements for the MutationEvent past the stage of industry proposals.

Changed January 27, 2011 01:47PM UTC by jitter comment:3

Replying to [comment:2 anonymous]:

That's incredibly disappointing, since there aren't satisfactory replacements for the MutationEvent past the stage of industry proposals.

The reason $(...).find() modifies the id of an element is to fix some quirks with qSA. There have been some improvements since 1.4.3 and .find() for this specific logic. You might want to try out the current 1.5rc1 release which (depending on your selectors) might trigger less unwanted DSM events.

Personally I think it's not a good idea to rely on a deprecated specification, especially as this one isn't implemented cross-browser anyway nor completely in the browsers which do. So whatever you do is prone to work just in some browsers and for those probably only in specific versions.

Another thing I don't understand is, why you need to look for the target element when a DSM gets triggered?

$("something").bind("DOMSubtreeModified", function( e ) {
  //e.target <-- this should be what you are looking for
});

As a last resort I can propose this very hacky and slow workaround

//this should stop DOMSubtreeModified events triggered by
//jQuery on "something" to bubble up to your DSM handler
//further up the tree
//clearly this comes at a high cost (bind/unbind)
$( "something" )
    .bind( "DOMSubtreeModified", function( e ) {
        e.stopImmediatePropagation();
    })
    .find( "someselector" )
    .unbind( "DOMSubtreeModified" );

Changed January 27, 2011 08:26PM UTC by anonymous comment:4

Thanks very much for the reply - I've been considering tacks along these lines.

Replying to [comment:3 jitter]:

The reason $(...).find() modifies the id of an element is to fix some quirks with qSA. There have been some improvements since 1.4.3 and .find() for this specific logic. You might want to try out the current 1.5rc1 release which (depending on your selectors) might trigger less unwanted DSM events.

Yeah, I could see that was the purpose. I didn't dig to far in, although I assume that something like setting a custom property on the Element itself wouldn't work, since you can't count on the browser to return the same object. (is that so?)

Personally I think it's not a good idea to rely on a deprecated specification, especially as this one isn't implemented cross-browser anyway nor completely in the browsers which do. So whatever you do is prone to work just in some browsers and for those probably only in specific versions.

DSM is part of a larger, admittedly hacky, solution that does it's best to cope with different browsers. My lower bar here is something along the lines of:

setInterval(250, function() {
  $(document).find(...).etc()
})

If I can't do better than that, I'll fall back to that position. I've been doing pretty well so far :)

Another thing I don't understand is, why you need to look for the target element when a DSM gets triggered?
> $("something").bind("DOMSubtreeModified", function( e ) {
>   //e.target <-- this should be what you are looking for
> });
> 

The trouble is that what I care about are nodes that have been inserted or modified such that they might match a selector - DSM is guaranteed not to target the node inserted, and isn't guaranteed to target anything closer than an ancestor.

I might be able to examine the event to find out what changes occurred, but that's a further reliance on a compliant implementation.

As a last resort I can propose this very hacky and slow workaround

I'm pretty sure I can do better than that. I'm already handling and reducing an event queue to make sure that changes I make in response to a ME don't produce an infinite loop internally. It's possible that I can either tighten that up, or change my handling so that I avoid using jQuery while the event is being processed.