Bug Tracker

Opened 8 years ago

Closed 8 years ago

Last modified 7 years ago

#8046 closed bug (wontfix)

$().find() triggers DOMSubTreeModified events

Reported by: judson@… 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?

Change History (4)

comment:1 Changed 8 years ago by Rick Waldron

Component: unfiledselector
Priority: undecidedlow
Resolution: wontfix
Status: newclosed

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

comment:2 Changed 8 years ago by anonymous

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

comment:3 in reply to:  2 ; Changed 8 years ago by jitter

Replying to 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" );

comment:4 in reply to:  3 Changed 8 years ago by anonymous

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

Replying to 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.

Note: See TracTickets for help on using tickets.