Hi, Diego, Agreed. Tested and functional with DOCUMENT_POSITION_DISCONNECTED.
I updated the jqbench repository with the new implementations, but I also included the "isOrphan" one, as someone (can't remember who - yourself or Dave, maybe... sorry for that, guys...) proposed here in this thread. Here is the update, then: $.fn.isOrphan = function() { var el = this[0], doc = el && el.ownerDocument && el.ownerDocument.documentElement; return !doc || (doc.contains ? !doc.contains(el) : doc.compareDocumentPosition(el) & 1); }; For the benchmark repository, go to https://jqbench.svn.sourceforge.net/svnroot/jqbench/jquery_branches/1.2.6 . As I said to Ariel, the code is a mess, but is to be reorganized/redesigned/changed to another project. Seeya! Diogo Diego Perini escreveu: > 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" <[EMAIL PROTECTED]> wrote: > >> 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() { >>>>>>>>>> >> ... >> >> leggi tutto >> > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "jQuery Development" group. To post to this group, send email to jquery-dev@googlegroups.com 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 -~----------~----~----~----~------~----~------~--~---