Alright... I made some tests, but now keeping support for iframes and 
XML documents. Though hoping not to be boring everyone here, I'd like to 
share the results (same 1000 iterations) - note that some of them expect 
a context argument, if you're willing to use iframes or XML (maybe we 
have least situations like these, am I right?):


- IMPLEMENTATIONS:

    $.fn.inDOM4 = function() {
        var el = this[0], doc = el && el.ownerDocument &&  
el.ownerDocument.documentElement;
        return !!doc && (doc.contains ? doc.contains(el) : 
!!(doc.compareDocumentPosition(el) & 16));
    };

    // Fifth implementation, including extra methods (that might be 
usefull) in jQuery
    $.contains = docEl.contains ?
        function(a, b) {
            return a && b && a != b && a.contains(b);
        } :
        function(a, b) {
            return a && b && a != b  && !!a.compareDocumentPosition(b) & 16;
        };
    $.fn.contains = function(el) {
        return $.contains(this[0], el);
    };
    $.fn.inDOM5 = function(contextEl) {
        var doc = contextEl || document.documentElement;
        return $.contains(doc, this[0]);
    };

    $.fn.inDOM6 = function() {
        var el = this[0], doc = el && el.ownerDocument &&  
el.ownerDocument.documentElement;
        return $.contains(doc, this[0]);
    };

    $.fn.inDOM7 = docEl.contains ?
        function(contextEl) {
            var el = this[0], doc = contextEl || document.documentElement;
            return doc && el && doc != el && docEl.contains(el);
        } :
        function(contextEl) {
            var el = this[0], doc = contextEl || document.documentElement;
            return doc && el && doc != el && 
!!(docEl.compareDocumentPosition(el) & 16);
        };


- PERFORMANCE RESULTS:

===== inDOM4 =====
start: 1228363385834 ms
end: 1228363385916 ms
difference: 82 ms

===== inDOM5 =====
start: 1228363386080 ms
end: 1228363386124 ms
difference: 44 ms

===== inDOM6 =====
start: 1228363386319 ms
end: 1228363386391 ms
difference: 72 ms

===== inDOM7 =====
start: 1228363386563 ms
end: 1228363386601 ms
difference: 38 ms


Also, I'm tending to think "isOrphan", as suggested before (was it 
Mevin?), is a more adequate name (considering a boolean inversion in the 
function return), since a code like "if (el.isOrphan()) return;" seems 
more readable to me... what do you guys think?

And sorry for the numerous postings... :-)

Diogo


Ariel Flesler escreveu:
> For an element from any other document.
>
> Examples:
> - IFrames
> - XML
> - Other documents
>
> On Wed, Dec 3, 2008 at 4:44 PM, Diogo Baeder <[EMAIL PROTECTED]> wrote:
>   
>> Alright, but what is the difference between "document" and
>> "el.ownerDocument"? I tested:
>>
>> alert(document.getElementsByTagName('body')[0].ownerDocument == document);
>>
>> And it returns true... which are the cases where this may return false?
>>
>> Diogo
>>
>>
>>
>> On Wed, Dec 3, 2008 at 4:27 PM, Ariel Flesler <[EMAIL PROTECTED]> wrote:
>>     
>>> That's what I was sort of suggesting, el.ownerDocument.documentElement,
>>> that is.
>>>
>>> As someone said (don't recall and don't wanna read up), good browsers
>>> (w3) do set ownerDocument to null when the node is outside any
>>> document.
>>>
>>> Assuming that's true:
>>>
>>> $.fn.inDOM = function(){
>>>    var elem = this[0],
>>>         doc = el && el.ownerDocument &&  el.ownerDocument.documentElement;
>>>
>>>    return !!doc && (doc.contains ?
>>>          doc.contains(el)
>>>        : !!(doc.compareDocumentPosition(el) & 16)
>>>    );
>>> };
>>>
>>> On Wed, Dec 3, 2008 at 4:15 PM, ricardobeat <[EMAIL PROTECTED]> wrote:
>>>       
>>>> Why not simplify?
>>>>
>>>> $.fn.inDOM = function(){
>>>>    var el=this[0];
>>>>    if (!el) return false;
>>>>    var doc = el.ownerDocument.documentElement;
>>>>    return (doc.contains)
>>>>        ? doc.contains(el)
>>>>        : !!(doc.compareDocumentPosition(el) & 16);
>>>> };
>>>>
>>>> 36ms vs 12ms for Diogo's 'inDOM3Optimized', but keeps it compatible
>>>> with other 'document' contexts. That's 1000 iterations, I don't see
>>>> anyone having thousands of elements that he doesn't know if are in the
>>>> DOM or not. It works in all target browsers, so the parentNode
>>>> fallback is not needed.
>>>>
>>>> Ariel, is there any situation where a node has no ownerDocument/
>>>> documentElement property?
>>>>
>>>> - ricardo
>>>>
>>>> On Dec 3, 11:21 am, "Ariel Flesler" <[EMAIL PROTECTED]> wrote:
>>>>         
>>>>> Those functions relying on $('html') wouldn't work for xml or some
>>>>> other special kind of document (namespaced tagnames?).
>>>>>
>>>>> I think it is indeed better to rely on the documentElement of the
>>>>> ownerDocument (if the latter exists else just false).
>>>>>
>>>>> On Wed, Dec 3, 2008 at 12:40 AM, Diogo Baeder <[EMAIL PROTECTED]>
>>>>> wrote:
>>>>>
>>>>>           
>>>>>> Diego, if I can recall, I already tested el.ownerDocument and, in
>>>>>> IE6,
>>>>>> it always returned true in Boolean test, even if the element was
>>>>>> removed.
>>>>>>             
>>>>>> The "bifurcated" implementation was tested in all browsers with
>>>>>> success
>>>>>> (except for FF2, which I didn't have in my machine at the time): FF3,
>>>>>> IE6, IE7, Safari 3.1.2 and Opera 9.62.
>>>>>>             
>>>>>> About the method name, it's a good point... ok by me to change it to
>>>>>> "isOrphan" and invert the return from the past implementation...
>>>>>>             
>>>>>> I also updated the implementations and testing in the benchmark,
>>>>>> putting
>>>>>> a "return false" if no element is false (correcting, thus, the bugs
>>>>>> of
>>>>>> when the elements were removed from DOM) and setting $('#level10') to
>>>>>> a
>>>>>> variable (in the "deep-level" testing), thus eliminating the need for
>>>>>> a
>>>>>> new traversal in every loop iteration. Here they are:
>>>>>>             
>>>>>> ----- IMPLEMENTATIONS:
>>>>>>             
>>>>>>    $.fn.inDOM1 = function() {
>>>>>>        return !!$(this).parents('html').length;
>>>>>>    };
>>>>>>             
>>>>>>    $.fn.inDOM2 = function() {
>>>>>>        var el = this[0];
>>>>>>        if (!el) return false;
>>>>>>        while (el.parentNode) el = el.parentNode;
>>>>>>        return el.nodeType == 9;
>>>>>>    };
>>>>>>             
>>>>>>    $.fn.inDOM3 = function() {
>>>>>>        var el = this[0];
>>>>>>        if (!el) return false;
>>>>>>        var html = $('html').get(0);
>>>>>>        return html.contains ?
>>>>>>            html != el && html.contains(el) :
>>>>>>            !!(html.compareDocumentPosition(el) & 16);
>>>>>>    };
>>>>>>             
>>>>>>    var docEl = document.documentElement;
>>>>>>    $.fn.inDOM3Optimized = docEl.contains ?
>>>>>>        function() {
>>>>>>            var el = this[0];
>>>>>>            if (!el) return false;
>>>>>>            return docEl != el && docEl.contains(el);
>>>>>>        } :
>>>>>>        function() {
>>>>>>            var el = this[0];
>>>>>>            if (!el) return false;
>>>>>>            return !!(docEl.compareDocumentPosition(el) & 16);
>>>>>>        };
>>>>>>             
>>>>>> --- PERFORMANCE RESULTS:
>>>>>>             
>>>>>> ===== inDOM1: parents("html") =====
>>>>>> start: 1228270728766 ms
>>>>>> end: 1228270729258 ms
>>>>>> difference: 492 ms
>>>>>>             
>>>>>> ===== inDOM2: parentNode =====
>>>>>> start: 1228270729274 ms
>>>>>> end: 1228270729437 ms
>>>>>> difference: 163 ms
>>>>>>             
>>>>>> ===== inDOM3: html.contains() =====
>>>>>> start: 1228270729450 ms
>>>>>> end: 1228270729808 ms
>>>>>> difference: 358 ms
>>>>>>             
>>>>>> ===== inDOM3Optimized: html.contains() =====
>>>>>> start: 1228270729821 ms
>>>>>> end: 1228270729911 ms
>>>>>> difference: 90 ms
>>>>>>             
>>>>>> ===== inDOM2: traversing 10 levels =====
>>>>>> start: 1228270729924 ms
>>>>>> end: 1228270730161 ms
>>>>>> difference: 237 ms
>>>>>>             
>>>>>> ===== inDOM3Optimized: traversing 10 levels =====
>>>>>> start: 1228270730173 ms
>>>>>> end: 1228270730184 ms
>>>>>> difference: 11 ms
>>>>>>             
>>>>>> ===== inDOM2: after removal =====
>>>>>> start: 1228270730198 ms
>>>>>> end: 1228270730382 ms
>>>>>> difference: 184 ms
>>>>>>             
>>>>>> ===== inDOM3Optimized: after removal =====
>>>>>> start: 1228270730395 ms
>>>>>> end: 1228270730405 ms
>>>>>> difference: 10 ms
>>>>>>             
>>>>>> Note: inDOM2 is the impl. using parentNode, and inDOM3 is the one
>>>>>> using
>>>>>> special methods ("bifurcated code").
>>>>>> Note 2: the speed in "inDOM3Optimized" changed a lot just because I
>>>>>> setted $('level10') to a variable before all the tests. This
>>>>>> strengthens
>>>>>> the performance reason to favor the "bifurcated code" implementation.
>>>>>> ;-)
>>>>>>             
>>>>>> If everybody agrees with the method name change (to "isOrphan"),
>>>>>> which
>>>>>> is OK by me, I can do it in the benchmarks to keep consistency with a
>>>>>> possible future version of jQuery.
>>>>>>             
>>>>>> Diogo
>>>>>>             
>>>>>> Diego Perini escreveu:
>>>>>>             
>>>>>>> John,
>>>>>>> I believe there is an error, probably you meant:
>>>>>>>               
>>>>>>> $.fn.inDOM = document.documentElement.contains ?
>>>>>>>     function() {
>>>>>>>         var el = this[0], root = el.ownerDocument.documentElement;
>>>>>>>         return root !== el && root.contains(el);
>>>>>>>     } :
>>>>>>>     function() {
>>>>>>>         var el = this[0];
>>>>>>>         return !!
>>>>>>> (el.ownerDocument.documentElement.compareDocumentPosition(el) & 16);
>>>>>>>     };
>>>>>>>               
>>>>>>> or if you prefer in the declaration "var el =
>>>>>>> this[0].ownerDocument".
>>>>>>>               
>>>>>>> As I already said, the native methods are the fastest, no doubt, but
>>>>>>> the standalone version is still to be considered alone or combined.
>>>>>>>               
>>>>>>> However, I believe we should test the following minor implications
>>>>>>> if
>>>>>>> deemed important:
>>>>>>>               
>>>>>>> - all target browser implementing one of the two native methods ?
>>>>>>> - all target browser having an "element.ownerDocument" ?
>>>>>>>               
>>>>>>> And for the function name I see "isOrphan/isOrphanNode" more
>>>>>>> adequate
>>>>>>> since if we can do:
>>>>>>>               
>>>>>>>    var node = document.createElement("div");
>>>>>>>               
>>>>>>> that node seems to me is already in the DOM, explicitly the one
>>>>>>> attached to "document" through the "ownerDocument" DOM property, the
>>>>>>> fact is that the node is not yet attached to the rendered tree, thus
>>>>>>> a
>>>>>>> node without a parent ancestor, that may be a simple element a
>>>>>>> DOMFragment or even a new Image() instance.
>>>>>>>               
>>>>>>> I further suggest to split this and implement "contains" or such in
>>>>>>> jQuery on the track of what you wrote about this on your blog and
>>>>>>> move
>>>>>>> the conditional there so this will simply remain:
>>>>>>>               
>>>>>>>     function() {
>>>>>>>         var el = this[0], root = el.ownerDocument.documentElement;
>>>>>>>         return root !== el && root.contains(el);
>>>>>>>     }
>>>>>>>               
>>>>>>> no branches there. They will be in the generic "contains" method
>>>>>>> (very
>>>>>>> useful...). In that method you could add the parent traversal as
>>>>>>> fall
>>>>>>> back.
>>>>>>>               
>>>>>>> In this way you add more functionalities to jQuery use the fastest
>>>>>>> in
>>>>>>> this OP and keep the code size down to the minimum still covering
>>>>>>> cross-browser 100%.
>>>>>>>               
>>>>>>> --
>>>>>>> Diego
>>>>>>>               
>>>>>>> On 2 Dic, 17:25, "John Resig" <[EMAIL PROTECTED]> wrote:
>>>>>>>               
>>>>>>>> Why not just tweak this implementation to be relative? That way you
>>>>>>>> still get performance but also allow it to work across frames, etc.
>>>>>>>>                 
>>>>>>>> $.fn.inDOM = document.documentElement.contains ?
>>>>>>>>        function() {
>>>>>>>>            var el = this[0], doc = el.documentElement;
>>>>>>>>            return doc !== el && doc.contains(el);
>>>>>>>>        } :
>>>>>>>>        function() {
>>>>>>>>            var el = this[0];
>>>>>>>>            return !!(el.documentElement.compareDocumentPosition(el)
>>>>>>>> & 16);
>>>>>>>>        };
>>>>>>>>                 
>>>>>>>> --John
>>>>>>>>                 
>>>>>>>> On Tue, Dec 2, 2008 at 9:41 AM, Ariel Flesler <[EMAIL PROTECTED]>
>>>>>>>> wrote:
>>>>>>>>                 
>>>>>>>>> I'd just save it as a local var
>>>>>>>>>                   
>>>>>>>>> var html = document.documentElement;
>>>>>>>>> $.fn.inDOM = html.contains ?
>>>>>>>>>        function() {
>>>>>>>>>            var el = this[0];
>>>>>>>>>            return html != el && $.html.contains(el);
>>>>>>>>>        } :
>>>>>>>>>        function() {
>>>>>>>>>            var el = this[0];
>>>>>>>>>            return !!(html.compareDocumentPosition(el) & 16);
>>>>>>>>>        };
>>>>>>>>>                   
>>>>>>>>> Does this work reliably on any browser ?
>>>>>>>>> Note that his doesn't work for any document that is not THE
>>>>>>>>> document.
>>>>>>>>>                   
>>>>>>>>> I think a simple traversal (going up) would do. I'm sorry to spoil
>>>>>>>>> all
>>>>>>>>> the researching but no one said this function will be used
>>>>>>>>> everywhere
>>>>>>>>> and it needs to be as fast as possible. First it most be
>>>>>>>>> effective,
>>>>>>>>> then efficient.
>>>>>>>>>                   
>>>>>>>>> On Tue, Dec 2, 2008 at 12:07 PM, Diogo Baeder
>>>>>>>>> <[EMAIL PROTECTED]> wrote:
>>>>>>>>>                   
>>>>>>>>>> Thanks!
>>>>>>>>>>                     
>>>>>>>>>> Guys, the last proposal gave me about 140ms ~ 150ms within 1000
>>>>>>>>>> method
>>>>>>>>>> calls, but here's something that gave me about 80ms ~ 90ms:
>>>>>>>>>>                     
>>>>>>>>>>     $.htmlEl = $('html').get(0);
>>>>>>>>>>     $.fn.inDOM = $.htmlEl.contains ?
>>>>>>>>>>         function() {
>>>>>>>>>>             var el = this[0];
>>>>>>>>>>             return $.htmlEl != el && $.htmlEl.contains(el);
>>>>>>>>>>         } :
>>>>>>>>>>         function() {
>>>>>>>>>>             var el = this[0];
>>>>>>>>>>             return !!($.htmlEl.compareDocumentPosition(el) & 16);
>>>>>>>>>>         };
>>>>>>>>>>                     
>>>>>>>>>> What do you think of it? A little bit more of coding, but
>>>>>>>>>> considerably
>>>>>>>>>> faster... despite someone would rarely make so much calls to this
>>>>>>>>>> method, I
>>>>>>>>>> think...
>>>>>>>>>>                     
>>>>>>>>>> Diogo
>>>>>>>>>>                     
>>>>>>>>>> On Mon, Dec 1, 2008 at 10:36 PM, Diego Perini
>>>>>>>>>> <[EMAIL PROTECTED]>
>>>>>>>>>> wrote:
>>>>>>>>>>                     
>>>>>>>>>>> Diogo,
>>>>>>>>>>>                       
>>>>>>>>>>> On 1 Dic, 21:56, "Diogo Baeder" <[EMAIL PROTECTED]> wrote:
>>>>>>>>>>>                       
>>>>>>>>>>>> Thank you, guys... I tried the last method as
>>>>>>>>>>>> implemented/adapted by
>>>>>>>>>>>> Diego,
>>>>>>>>>>>> and it works! :-)
>>>>>>>>>>>>                         
>>>>>>>>>>>> Unfortunately, neither "contains" nor "compareDocumentPosition"
>>>>>>>>>>>> are
>>>>>>>>>>>> being
>>>>>>>>>>>> recognized as methods for the "document" node in IE6 or 7, as
>>>>>>>>>>>> you can
>>>>>>>>>>>> test
>>>>>>>>>>>> yourselves:
>>>>>>>>>>>>                         
>>>>>>>>>>>> alert(document.contains);
>>>>>>>>>>>> alert(window.contains);
>>>>>>>>>>>> alert(document.compareDocumentPosition);
>>>>>>>>>>>> alert(window.compareDocumentPosition);
>>>>>>>>>>>>                         
>>>>>>>>>>>> Any ideas why these didn't work for me?
>>>>>>>>>>>>                         
>>>>>>>>>>> The Microsoft "contains" method does not exists for the document
>>>>>>>>>>> object (at least in the docs). Maybe because it is not an
>>>>>>>>>>> element
>>>>>>>>>>> (nodeType == 1).
>>>>>>>>>>>                       
>>>>>>>>>>> Firefox and Opera implement the "compareDocumentPosition"
>>>>>>>>>>> method, also
>>>>>>>>>>> they made it a method of the "document" itself.
>>>>>>>>>>>                       
>>>>>>>>>>> Opera implements both "compareDocumentPosition" and "contains",
>>>>>>>>>>> Safari
>>>>>>>>>>> only has "contains" again not on the "document".
>>>>>>>>>>>                       
>>>>>>>>>>> The conclusion is that the implementations of
>>>>>>>>>>> "compareDocumentPosition
>>>>>>>>>>> ()" and "contains()" disagree on this specific fact.
>>>>>>>>>>>                       
>>>>>>>>>>> At this point, given the messed up implementations, better being
>>>>>>>>>>> independent from them both and go for the traversal.
>>>>>>>>>>>                       
>>>>>>>>>>> It is also much shorter and really cross-browser...
>>>>>>>>>>>                       
>>>>>>>>>>> --
>>>>>>>>>>> Diego
>>>>>>>>>>>                       
>>>>>>>>>>>> Diogo
>>>>>>>>>>>>                         
>>>>>>>>>>>> On Mon, Dec 1, 2008 at 10:58 AM, Diego Perini
>>>>>>>>>>>> <[EMAIL PROTECTED]>wrote:
>>>>>>>>>>>>                         
>>>>> ...
>>>>>
>>>>> read more ยป
>>>>>
>>>>>           
>>>
>>> --
>>> Ariel Flesler
>>> http://flesler.blogspot.com
>>>
>>>
>>>       
>>
>> --
>> Diogo Baeder
>> http://www.diogobaeder.com.br
>>
>>     
>
>
>
>   

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"jQuery Development" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to