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: >>>>>>> >>>>>>>> ricardo, >>>>>>>> >>>>>>>> On 1 Dic, 05:35, ricardobeat <[EMAIL PROTECTED]> wrote: >>>>>>>> >>>>>>>>> I always miss the obvious stuff :) >>>>>>>>> >>>>>>>>> I ended up with this, it's a lot faster than Diogo's code but still >>>>>>>>> requires you to traverse the document all the way up. John Resig's >>>>>>>>> 'contains' function is at least twice faster in FF though, so it >>>>>>>>> seems >>>>>>>>> like the perfect solution. >>>>>>>>> >>>>>>>>> $.fn.inDOM = function(){ >>>>>>>>> var el = this[0]; >>>>>>>>> while (el.parentNode) el = el.parentNode; >>>>>>>>> return el == this[0].ownerDocument; >>>>>>>>> >>>>>>>>> }; >>>>>>>>> >>>>>>>> To make it less dependent: >>>>>>>> >>>>>>>> $.fn.inDOM = function(){ >>>>>>>> var el = this[0]; >>>>>>>> while (el.parentNode) el = el.parentNode; >>>>>>>> return el.nodeType == 9; >>>>>>>> }; >>>>>>>> >>>>>>>> now you can also pass elements present in other DOM contexts. >>>>>>>> >>>>>>>> Don't know if this modifies the intended usage, this will most >>>>>>>> generally tell if the element is an orphan (not attached to any >>>>>>>> document). >>>>>>>> >>>>>>>> To account for both usages, it will be necessary to pass context >>>>>>>> information (an extra parameter to specify the desired context). >>>>>>>> >>>>>>>> -- >>>>>>>> Diego >>>>>>>> >>>>>>>>> - ricardo >>>>>>>>> >>>>>>>>> On 30 nov, 19:43, "Ariel Flesler" <[EMAIL PROTECTED]> wrote: >>>>>>>>> >>>>>>>>>> Yeah, parentNode is not good enough. >>>>>>>>>> >>>>>>>>>> On Sun, Nov 30, 2008 at 4:35 PM, ricardobeat >>>>>>>>>> <[EMAIL PROTECTED]> >>>>>>>>>> >>>>>>>> wrote: >>>>>>>> >>>>>>>>>>> Hi, >>>>>>>>>>> >>>>>>>>>>> It seems the ownerDocument is set for the created element even >>>>>>>>>>> if >>>>>>>>>>> >>>>>>>> it's >>>>>>>> >>>>>>>>>>> not in the DOM, it's the document where jQuery was loaded in. A >>>>>>>>>>> >>>>>>>> simple >>>>>>>> >>>>>>>>>>> check for parentNode or offsetParent would do: >>>>>>>>>>> >>>>>>>>>>> $.fn.inDOM = function(){ >>>>>>>>>>> return !!this.parentNode; //boolean >>>>>>>>>>> }); >>>>>>>>>>> >>>>>>>>>>> parentNode returns faster for elements in the DOM, while >>>>>>>>>>> offsetParent >>>>>>>>>>> returns faster for elements not in the DOM (in FF3 at least). >>>>>>>>>>> >>>>>>>>>>> Hope I'm not missing anything. It surely would need a better >>>>>>>>>>> name :] >>>>>>>>>>> >>>>>>>>>>> cheers, >>>>>>>>>>> - ricardo >>>>>>>>>>> On 29 nov, 14:46, Ariel Flesler <[EMAIL PROTECTED]> wrote: >>>>>>>>>>> >>>>>>>>>>>> 'body' should be replaced by 'html'. >>>>>>>>>>>> >>>>>>>>>>>> Maybe we can make it faster by consulting expandos like >>>>>>>>>>>> ownerDocument ? >>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>>> Ariel Fleslerhttp://flesler.blogspot.com >>>>>>>>>>>> >>>>>>>>>>>> On Nov 27, 12:52 am, diogobaeder <[EMAIL PROTECTED]> wrote: >>>>>>>>>>>> >>>>>>>>>>>>> Hi there, >>>>>>>>>>>>> >>>>>>>>>>>>> I'm new here (and in jQuery), but even though I'd like to >>>>>>>>>>>>> propose >>>>>>>>>>>>> >>>>>>>> some >>>>>>>> >>>>>>>>>>>>> simple but usefull method to the jQuery object (at core.js) >>>>>>>>>>>>> to >>>>>>>>>>>>> >>>>>>>> tell >>>>>>>> >>>>>>>>>>>>> the API user if an element exists in the document. I've tried >>>>>>>>>>>>> to >>>>>>>>>>>>> >>>>>>>> build >>>>>>>> >>>>>>>>>>>>> one as follows: >>>>>>>>>>>>> >>>>>>>>>>>>> [CODE] >>>>>>>>>>>>> (function($) { >>>>>>>>>>>>> >>>>>>>>>>>>> $.fn.inDOM = function() { >>>>>>>>>>>>> return !!this.parents('body').length; >>>>>>>>>>>>> }; >>>>>>>>>>>>> >>>>>>>>>>>>> })(jQuery); >>>>>>>>>>>>> >>>>>>>>>>>>> jQuery(document).ready(function(){ >>>>>>>>>>>>> var jEl = $('.someExistingClass'); >>>>>>>>>>>>> >>>>>>>>>>>>> // Should be in DOM >>>>>>>>>>>>> console.debug(jEl.inDOM()); >>>>>>>>>>>>> >>>>>>>>>>>>> // Removing the element >>>>>>>>>>>>> jEl.remove(); >>>>>>>>>>>>> >>>>>>>>>>>>> // Should NOT be in DOM >>>>>>>>>>>>> console.debug(jEl.inDOM());}); >>>>>>>>>>>>> >>>>>>>>>>>>> [/CODE] >>>>>>>>>>>>> >>>>>>>>>>>>> So, if the client sets a variable as a jQuery object, and at >>>>>>>>>>>>> some >>>>>>>>>>>>> point of the code the DOM element within it can be removed, >>>>>>>>>>>>> he/she >>>>>>>>>>>>> >>>>>>>> can >>>>>>>> >>>>>>>>>>>>> test if it really was. OK, I know it sounds unsignificant, >>>>>>>>>>>>> but I >>>>>>>>>>>>> >>>>>>>> think >>>>>>>> >>>>>>>>>>>>> it would still be usefull. >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks! >>>>>>>>>>>>> >>>>>>>>>>>>> Diogo Baeder >>>>>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> Ariel Fleslerhttp://flesler.blogspot.com >>>>>>>>>> >>>>>>> -- >>>>>>> Diogo Baederhttp://www.diogobaeder.com.br >>>>>>> >>>>> -- >>>>> Diogo Baeder >>>>> http://www.diogobaeder.com.br >>>>> >>>> -- >>>> Ariel Flesler >>>> http://flesler.blogspot.com >>>> >> > >> >> > > > > -- Ariel Flesler http://flesler.blogspot.com --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---