DOMNodeInserted -> Was #id inserted?

Discussion in 'Javascript' started by Matt Kruse, May 27, 2010.

  1. Matt Kruse

    Matt Kruse Guest

    Using a document listener on DOMNodeInserted, I'm trying to determine
    if an element with id="x" was inserted. So either the
    event.target.id=="x" or a child element of the one inserted
    has .id=="x".

    What is the best way to determine if #x is a child of the inserted
    element?

    Currently I'm doing:
    if ( element.querySelectorAll("#x").length==1 )

    But that limits my browser compatibility. I'd like to support Firefox
    < 3.5, which lacks querySelectorAll.

    Matt Kruse
     
    Matt Kruse, May 27, 2010
    #1
    1. Advertising

  2. Matt Kruse wrote:
    > Using a document listener on DOMNodeInserted, I'm trying to determine
    > if an element with id="x" was inserted. So either the
    > event.target.id=="x" or a child element of the one inserted
    > has .id=="x".
    >
    > What is the best way to determine if #x is a child of the inserted
    > element?
    >
    > Currently I'm doing:
    > if ( element.querySelectorAll("#x").length==1 )
    >
    > But that limits my browser compatibility. I'd like to support Firefox
    > < 3.5, which lacks querySelectorAll.


    Well
    element.getElementsByTagName('*')
    gives you alld descendant elements, you could then iterate over that
    node list and look for an element with the id you are interested in.
    That should work back to Firefox 1.0 or IE 6 (which you are probably not
    interested in anyway with using mutation events).
    Firefox also supports XPath over HTML DOMs so you could also try to
    solve that with XPath e.g.
    element.ownerDocument.evaluate('descendant-or-self::*[@id = "' +
    yourId + '"]', element, null, 9, null).singleNodeValue !== null
    should tell you whether "element" itself or one of the descendant
    elements has the id attribute.


    --

    Martin Honnen
    http://msmvps.com/blogs/martin_honnen/
     
    Martin Honnen, May 27, 2010
    #2
    1. Advertising

  3. Matt Kruse wrote:

    > Using a document listener on DOMNodeInserted, I'm trying to determine
    > if an element with id="x" was inserted. So either the
    > event.target.id=="x" or a child element of the one inserted
    > has .id=="x".
    >
    > What is the best way to determine if #x is a child of the inserted
    > element?


    Determine if #x's parent is the inserted element (`parentNode' property).


    PointedEars
    --
    Danny Goodman's books are out of date and teach practices that are
    positively harmful for cross-browser scripting.
    -- Richard Cornford, cljs, <cife6q$253$1$> (2004)
     
    Thomas 'PointedEars' Lahn, May 27, 2010
    #3
  4. Matt Kruse

    Matt Kruse Guest

    On May 27, 8:50 am, Thomas 'PointedEars' Lahn <>
    wrote:
    > Matt Kruse wrote:
    > > What is the best way to determine if #x is a child of the inserted
    > > element?

    > Determine if #x's parent is the inserted element (`parentNode' property).


    I thought of this too, obviously, but it has the drawbacks of:
    1. You may have to look through the parentNode chain all the way up to
    the root document before realizing it's not a match, which seems
    inefficient
    2. If #x already existed in the doc somewhere else, you're going to be
    inspecting this chain for no good reason

    It seems that element.getElementById() would be handy in this case,
    but perhaps performance using any of these methods would be fast
    enough that trying to optimize is pointless.

    Matt Kruse
     
    Matt Kruse, May 27, 2010
    #4
  5. Matt Kruse wrote:

    > Thomas 'PointedEars' Lahn wrote:
    >> Matt Kruse wrote:
    >> > What is the best way to determine if #x is a child of the inserted
    >> > element?

    >> Determine if #x's parent is the inserted element (`parentNode' property).

    >
    > I thought of this too, obviously, but it has the drawbacks of:
    > 1. You may have to look through the parentNode chain all the way up to
    > the root document


    You mean root _element_. You may not have to, since not all element types
    may be descendants of all others.

    > before realizing it's not a match, which seems inefficient


    A linked list lookup is certainly not more inefficient than a tree search.

    > 2. If #x already existed in the doc somewhere else, you're going to be
    > inspecting this chain for no good reason


    If #x already existed in the document somewhere else, you have a design
    problem to solve first.

    > It seems that element.getElementById() would be handy in this case,


    It is. BTDT.

    > but perhaps performance using any of these methods would be fast
    > enough that trying to optimize is pointless.


    Perhaps not.


    PointedEars
    --
    Prototype.js was written by people who don't know javascript for people
    who don't know javascript. People who don't know javascript are not
    the best source of advice on designing systems that use javascript.
    -- Richard Cornford, cljs, <f806at$ail$1$>
     
    Thomas 'PointedEars' Lahn, May 27, 2010
    #5
  6. Matt Kruse

    Matt Kruse Guest

    On May 27, 8:18 am, Martin Honnen <> wrote:
    > Matt Kruse wrote:
    > > What is the best way to determine if #x is a child of the inserted
    > > element?

    > Firefox also supports XPath over HTML DOMs so you could also try to
    > solve that with XPath e.g.
    >    element.ownerDocument.evaluate('descendant-or-self::*[@id = "' +
    > yourId + '"]', element, null, 9, null).singleNodeValue !== null


    Good idea, I went ahead and tested these three:

    function containsId1(el,id) {
    return (el.ownerDocument.evaluate('descendant-or-self::*[@id = "' +id
    + '"]', el, null, 9, null).singleNodeValue !== null);
    }
    function containsId2(el,id) {
    return (el.querySelectorAll('#'+id).length==1);
    }
    function containsId3(el,id) {
    var o = document.getElementById(id);
    if (o) {
    if (id===o.id) { return true; }
    while (o=o.parentNode) {
    if (id===o.id) { return true; }
    }
    }
    return false;
    }

    It turns out that the XPath approach is about 100ms slower over 5,000
    iterations of a simple test case (insignificant), and the other two
    are practically equal. So I guess there is no reason not to use the
    last approach, which is the most backwards-compatible.

    Matt Kruse
     
    Matt Kruse, May 27, 2010
    #6
  7. Matt Kruse

    SAM Guest

    Le 5/27/10 3:07 PM, Matt Kruse a écrit :
    > Using a document listener on DOMNodeInserted, I'm trying to determine
    > if an element with id="x" was inserted.


    alert(document.getElementById('x'))

    alert(typeof document.getElementById('x') != 'undefined')

    > So either the event.target.id=="x"
    > or a child element of the one inserted
    > has .id=="x".


    ??? as you can have only ONE element of same id in a html body
    why do you search more than this 'x' ?


    > What is the best way to determine if #x is a child of the inserted
    > element?


    ?? how does-it inserted ?
    I mean the container or the element of id 'x'


    > Currently I'm doing:
    > if ( element.querySelectorAll("#x").length==1 )


    I don't know what that element.querySelectorAll is.


    > But that limits my browser compatibility. I'd like to support Firefox
    > < 3.5, which lacks querySelectorAll.


    If you search an id use gEBY (see above)



    If there is more than one element with same id
    correct in first your page or the appli creating it.

    --
    sm
     
    SAM, May 27, 2010
    #7
  8. Matt Kruse

    Matt Kruse Guest

    On May 27, 9:26 am, Matt Kruse <> wrote:
    > function containsId3(el,id) {
    >         var o = document.getElementById(id);
    >         if (o) {
    >                 if (id===o.id) { return true; }
    >                 while (o=o.parentNode) {
    >                         if (id===o.id) { return true; }
    >                 }
    >         }
    >         return false;
    > }


    Oops, posted the version with obviously logical snafu. Fixed:

    function containsId3(el,id) {
    var o = document.getElementById(id);
    if (o) {
    do {
    if (o==el) { return true; }
    } while (o=o.parentNode);
    }
    return false;
    }

    Matt Kruse
     
    Matt Kruse, May 27, 2010
    #8
  9. On 5/27/2010 7:10 AM, Thomas 'PointedEars' Lahn wrote:
    > Matt Kruse wrote:
    >
    >> Thomas 'PointedEars' Lahn wrote:
    >>> Matt Kruse wrote:
    >>>> What is the best way to determine if #x is a child of the inserted
    >>>> element?
    >>> Determine if #x's parent is the inserted element (`parentNode' property).

    >>
    >> I thought of this too, obviously, but it has the drawbacks of:
    >> 1. You may have to look through the parentNode chain all the way up to
    >> the root document

    >


    No, to determine if #x is a child of the inserted element, the simplest
    approach is to compare the inserted element to x's parentNode.

    To determine if #x is a *descendant* of the inserted element is a
    different task. It is not a difficult one; and many recent browsers
    supply functionality

    You wrote that you are using a DOMNodeInserted mutation event. Perhaps
    that is not the best choice here.

    What are you trying to do?
     
    Garrett Smith, May 27, 2010
    #9
  10. Garrett Smith wrote:

    > On 5/27/2010 7:10 AM, Thomas 'PointedEars' Lahn wrote:
    >> Matt Kruse wrote:
    >>> Thomas 'PointedEars' Lahn wrote:
    >>>> Matt Kruse wrote:
    >>>>> What is the best way to determine if #x is a child of the inserted
    >>>>> element?
    >>>> Determine if #x's parent is the inserted element (`parentNode'
    >>>> property).
    >>>
    >>> I thought of this too, obviously, but it has the drawbacks of:
    >>> 1. You may have to look through the parentNode chain all the way up to
    >>> the root document

    >
    > No, to determine if #x is a child of the inserted element, the simplest
    > approach is to compare the inserted element to x's parentNode.
    > [...]
    > What are you trying to do?


    Will you *please* learn to post.


    PointedEars
    --
    Danny Goodman's books are out of date and teach practices that are
    positively harmful for cross-browser scripting.
    -- Richard Cornford, cljs, <cife6q$253$1$> (2004)
     
    Thomas 'PointedEars' Lahn, May 27, 2010
    #10
  11. Matt Kruse wrote:

    > function containsId1(el,id) {
    > return (el.ownerDocument.evaluate('descendant-or-self::*[@id = "' +id
    > + '"]', el, null, 9, null).singleNodeValue !== null);
    > }
    > function containsId2(el,id) {
    > return (el.querySelectorAll('#'+id).length==1);
    > }
    > function containsId3(el,id) {
    > var o = document.getElementById(id);
    > if (o) {
    > if (id===o.id) { return true; }
    > while (o=o.parentNode) {
    > if (id===o.id) { return true; }
    > }
    > }
    > return false;
    > }
    >
    > It turns out that the XPath approach is about 100ms slower over 5,000
    > iterations of a simple test case (insignificant), and the other two
    > are practically equal. So I guess there is no reason not to use the
    > last approach, which is the most backwards-compatible.


    Told you :)


    PointedEars
    --
    realism: HTML 4.01 Strict
    evangelism: XHTML 1.0 Strict
    madness: XHTML 1.1 as application/xhtml+xml
    -- Bjoern Hoehrmann
     
    Thomas 'PointedEars' Lahn, May 27, 2010
    #11
  12. Matt Kruse

    Matt Kruse Guest

    On May 27, 12:52 pm, Garrett Smith <> wrote:
    > No, to determine if #x is a child of the inserted element, the simplest
    > approach is to compare the inserted element to x's parentNode.
    > To determine if #x is a *descendant* of the inserted element is a
    > different task. It is not a difficult one; and many recent browsers
    > supply functionality


    Yes, I meant descendant, not direct child.

    > You wrote that you are using a DOMNodeInserted mutation event. Perhaps
    > that is not the best choice here.
    > What are you trying to do?


    I'm actually writing script to manipulate Facebook. When objects with
    certain id's are injected into the page, I want to manipulate them.
    Since Facebook's navigation scheme is a mess, catching node insertions
    and seeing if a given id has been inserted works well.

    Matt Kruse
     
    Matt Kruse, May 27, 2010
    #12
  13. On 5/27/2010 11:21 AM, Matt Kruse wrote:
    > On May 27, 12:52 pm, Garrett Smith<> wrote:
    >> No, to determine if #x is a child of the inserted element, the simplest
    >> approach is to compare the inserted element to x's parentNode.
    >> To determine if #x is a *descendant* of the inserted element is a
    >> different task. It is not a difficult one; and many recent browsers
    >> supply functionality

    >
    > Yes, I meant descendant, not direct child.
    >
    >> You wrote that you are using a DOMNodeInserted mutation event. Perhaps
    >> that is not the best choice here.
    >> What are you trying to do?

    >
    > I'm actually writing script to manipulate Facebook. When objects with
    > certain id's are injected into the page, I want to manipulate them.
    > Since Facebook's navigation scheme is a mess, catching node insertions
    > and seeing if a given id has been inserted works well.
    >


    I'm still a little fuzzy on the big picture, so this may not help.

    Check to see if #x exists prior to appending the container. If it does,
    the container not contain #x (unless the container has removed #x and
    appends it to itself at that time).

    Otherwise, after appending the container, check to see if #x exists. If
    it does, then the container contains it.

    var x = document.getElementById("x");
    addContainer();
    containerHasX = !x && document.getElementById("x");

    Mutation events have been known to hurt performance. I'm not up on the
    details of which mutation events hurt performance in which browsers.
    Generally I avoid mutation event because they don't work in IE <= 8.

    Garrett
     
    Garrett Smith, May 27, 2010
    #13
  14. On 5/27/2010 12:17 PM, Garrett Smith wrote:
    > On 5/27/2010 11:21 AM, Matt Kruse wrote:
    >> On May 27, 12:52 pm, Garrett Smith<> wrote:


    [...]

    > var x = document.getElementById("x");
    > addContainer();
    > containerHasX = !x && document.getElementById("x");
    >


    Make that:

    containerHasX = !x && document.getElementById("x") !== null;

    Garrett
     
    Garrett Smith, May 27, 2010
    #14
  15. Garrett Smith wrote:

    > On 5/27/2010 11:21 AM, Matt Kruse wrote:
    >> On May 27, 12:52 pm, Garrett Smith<> wrote:
    >>> You wrote that you are using a DOMNodeInserted mutation event. Perhaps
    >>> that is not the best choice here.
    >>> What are you trying to do?

    >>
    >> I'm actually writing script to manipulate Facebook. When objects with
    >> certain id's are injected into the page, I want to manipulate them.
    >> Since Facebook's navigation scheme is a mess, catching node insertions
    >> and seeing if a given id has been inserted works well.

    >
    > I'm still a little fuzzy on the big picture, so this may not help.
    >
    > Check to see if #x exists prior to appending the container. If it does,
    > the container not contain #x (unless the container has removed #x and
    > appends it to itself at that time).


    YGCIB.

    > [...]
    > Mutation events have been known to hurt performance. I'm not up on the
    > details of which mutation events hurt performance in which browsers.
    > Generally I avoid mutation event because they don't work in IE <= 8.


    Polling the status of the document tree very likely hurts performance a lot
    more than listening to mutation events. Granted, polling is more
    compatible, but there is no good reason to do that where mutation events are
    supported. And you don't seem to have noticed that the problem has already
    been solved satisfactorily.


    PointedEars
    --
    Danny Goodman's books are out of date and teach practices that are
    positively harmful for cross-browser scripting.
    -- Richard Cornford, cljs, <cife6q$253$1$> (2004)
     
    Thomas 'PointedEars' Lahn, May 27, 2010
    #15
  16. Matt Kruse

    Matt Kruse Guest

    On May 27, 2:17 pm, Garrett Smith <> wrote:
    > Check to see if #x exists prior to appending the container. If it does,
    > the container not contain #x (unless the container has removed #x and
    > appends it to itself at that time).


    I am not appending the container. Facebook's code is. I am just trying
    to trap the insertion of content and do something with it. That's why
    I'm relying on the mutation events, because I can't hook into their
    code and it's near impossible to comprehend even if I could.

    > Mutation events have been known to hurt performance. I'm not up on the
    > details of which mutation events hurt performance in which browsers.


    I've not experienced any performance problems yet. It certain beats
    repeatedly polling document.getElementById() to see if something was
    inserted, which certainly has its own problems.

    One frustration I do have is that DOMNodeInsertedIntoDocument does not
    bubble like DOMNodeInserted does. Since I only watch to catch actual
    insertions and not moving around of elements, I'd prefer the former
    but I have to use the latter and process every insertion event.

    > Generally I avoid mutation event because they don't work in IE <= 8.


    I'd never used them before wandering into the wonderful world of
    Greasemonkey where all I care about is Firefox/Chrome. It's a lovely
    place. :)

    Matt Kruse
     
    Matt Kruse, May 27, 2010
    #16
  17. On 5/27/2010 12:38 PM, Matt Kruse wrote:
    > On May 27, 2:17 pm, Garrett Smith<> wrote:
    >> Check to see if #x exists prior to appending the container. If it does,
    >> the container not contain #x (unless the container has removed #x and
    >> appends it to itself at that time).

    >
    > I am not appending the container. Facebook's code is. I am just trying
    > to trap the insertion of content and do something with it. That's why
    > I'm relying on the mutation events, because I can't hook into their
    > code and it's near impossible to comprehend even if I could.
    >


    OK, so apparently there is there no way to know when FB appends the
    container.

    If #x will be only inserted at most once, then once it is inserted, the
    callback that was listening for that, be it a facebook event, a mutation
    event, or an event of your own design, can be removed.

    >> Mutation events have been known to hurt performance. I'm not up on the
    >> details of which mutation events hurt performance in which browsers.

    >
    > I've not experienced any performance problems yet. It certain beats
    > repeatedly polling document.getElementById() to see if something was
    > inserted, which certainly has its own problems.
    >
    > One frustration I do have is that DOMNodeInsertedIntoDocument does not
    > bubble like DOMNodeInserted does. Since I only watch to catch actual
    > insertions and not moving around of elements, I'd prefer the former
    > but I have to use the latter and process every insertion event.
    >


    If the callback does not find #x, then it exits. Once #x is found, the
    callback gets the information it needs and unregisters itself.

    >> Generally I avoid mutation event because they don't work in IE<= 8.

    >
    > I'd never used them before wandering into the wonderful world of
    > Greasemonkey where all I care about is Firefox/Chrome. It's a lovely
    > place. :)
    >


    Greasemonkey? Does is actually work now? I remember all sorts of
    problems with it. For some reason guys at Yahoo love it. I remember guys
    going out of there way to keep old versions of Firefox just to avoid the
    problems with it not working in the upgrade.
     
    Garrett Smith, May 28, 2010
    #17
  18. Matt Kruse

    Matt Kruse Guest

    On May 27, 10:56 pm, Garrett Smith <> wrote:
    > OK, so apparently there is there no way to know when FB appends the
    > container.


    True.

    > If #x will be only inserted at most once, then once it is inserted, the
    > callback that was listening for that, be it a facebook event, a mutation
    > event, or an event of your own design, can be removed.


    Unfortunately, they do some strange ajax navigation stuff. Containers
    get added, then removed, seemingly at random. My goal is to trap the
    cases where the containers exist, and insert my content. If they get
    removed and added again as the user navigates, add the stuff again. So
    I keep my listeners around.

    > Greasemonkey? Does is actually work now? I remember all sorts of
    > problems with it. For some reason guys at Yahoo love it. I remember guys
    > going out of there way to keep old versions of Firefox just to avoid the
    > problems with it not working in the upgrade.


    It works great for me. Not sure of what issues exist. FWIW,
    http://BetterFacebook.net is the code I'm tinkering with. It's evolved
    into kind of a sloppy mess right now, but I'm re-writing portions of
    it to better use these mutation events in an attempt to make it more
    robust.

    Matt Kruse
     
    Matt Kruse, May 28, 2010
    #18
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?U0s=?=
    Replies:
    4
    Views:
    1,273
    =?Utf-8?B?c2s=?=
    Dec 10, 2003
  2. =?Utf-8?B?Y29kZXIxMA==?=

    DESGNTIMESP inserted in HTML Tags in ASP.Net

    =?Utf-8?B?Y29kZXIxMA==?=, May 11, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    349
    George Ter-Saakov
    May 11, 2004
  3. DC Gringo

    panel inserted unwanted div tag

    DC Gringo, Sep 23, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    430
    Alan Ferrandiz [MCT]
    Sep 23, 2004
  4. =?Utf-8?B?bG91aXNlIHJhaXNiZWNr?=

    Best way to get ID of inserted row??

    =?Utf-8?B?bG91aXNlIHJhaXNiZWNr?=, Nov 16, 2004, in forum: ASP .Net
    Replies:
    4
    Views:
    3,904
    Deepak
    Nov 17, 2004
  5. Steve
    Replies:
    6
    Views:
    243
    Thomas 'PointedEars' Lahn
    Mar 5, 2008
Loading...

Share This Page