Agreed. Tested and functional with DOCUMENT_POSITION_DISCONNECTED.
> Ariel,
> while looking at the specifications and searching in the MDC site I
> found that "compareDocumentPosition()" can test for detached nodes.
> https://developer.mozilla.org/en/DOM/Node.compareDocumentPosition
> DOCUMENT_POSITION_DISCONNECTED = 0x01; // the one we need
> DOCUMENT_POSITION_PRECEDING = 0x02;
> DOCUMENT_POSITION_FOLLOWING = 0x04;
> DOCUMENT_POSITION_CONTAINS = 0x08;
> DOCUMENT_POSITION_IS_CONTAINED = 0x10;
> so:
> a.compareDocumentPosition(b) & 1
> will tell us if the node is connected or disconnected from the DOM
> tree.
> Isn't this what we were after on W3C browsers ?
> --
> Diego
> On 3 Dic, 19:48, "Ariel Flesler" <afles...@gmail.com> wrote:
>> For an element from any other document.
>> Examples:
>> - IFrames
>> - XML
>> - Other documents
>> On Wed, Dec 3, 2008 at 4:44 PM, Diogo Baeder <diogobae...@gmail.com> 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 <afles...@gmail.com> 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 <ricardob...@gmail.com> 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" <afles...@gmail.com> 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 <diogobae...@gmail.com>
>>>>>> 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" <jere...@gmail.com> 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 <afles...@gmail.com>
>>>>>>>>> wrote:
>>>>>>>>>> I'd just save it as a local var
>>>>>>>>>> var html = document.documentElement;
>>>>>>>>>> $.fn.inDOM = html.contains ?
>>>>>>>>>> function() {
>> ...
>> leggi tutto