From 7cf17c7becba5322346a10acd0cc447b0eb99281 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Thu, 1 Nov 2007 15:11:52 +0000 Subject: [PATCH] Performance optimizations for Element#descendantOf. Costliness should no longer be dependent on the difference in depth between the parent and the child. [Andrew Dupont] --- CHANGELOG | 2 ++ src/dom.js | 14 ++++++++++++++ test/unit/dom.html | 32 +++++++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 643b69b..fd7e73c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Performance optimizations for Element#descendantOf. Costliness should no longer be dependent on the difference in depth between the parent and the child. [Andrew Dupont] + * Apply the workaround for the Firefox "blinking element" opacity=1 bug only to Firefox 1.5. [Thomas Fuchs] * Add event.stopped, a boolean that is set to `true` when Event#stop is called. [Andrew Dupont, sam] diff --git a/src/dom.js b/src/dom.js index a3d24e2..17161eb 100644 --- a/src/dom.js +++ b/src/dom.js @@ -358,6 +358,20 @@ Element.Methods = { descendantOf: function(element, ancestor) { element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 24) === 8; + + if (element.sourceIndex) { + var e = element.sourceIndex, a = ancestor.sourceIndex, + nextAncestor = ancestor.nextSibling; + if (!nextAncestor) { + do { ancestor = ancestor.parentNode; } + while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); + } + if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex); + } + while (element = element.parentNode) if (element == ancestor) return true; return false; diff --git a/test/unit/dom.html b/test/unit/dom.html index fb2438b..1ed5565 100644 --- a/test/unit/dom.html +++ b/test/unit/dom.html @@ -319,7 +319,13 @@

content

-
+
+
+
+
+
+
+

some content.

@@ -1003,8 +1009,28 @@ testDescendantOf: function() {with(this) { assert($('child').descendantOf('ancestor')); assert($('child').descendantOf($('ancestor'))); - assert($('great-grand-child').descendantOf('ancestor')); - assert(!$('great-grand-child').descendantOf('not-in-the-family')); + + assert(!$('ancestor').descendantOf($('child'))); + + assert($('great-grand-child').descendantOf('ancestor'), 'great-grand-child < ancestor'); + assert($('grand-child').descendantOf('ancestor'), 'grand-child < ancestor'); + assert($('great-grand-child').descendantOf('grand-child'), 'great-grand-child < grand-child'); + assert($('grand-child').descendantOf('child'), 'grand-child < child'); + assert($('great-grand-child').descendantOf('child'), 'great-grand-child < child'); + + window.debug = true; + assert($('sibling').descendantOf('ancestor'), 'sibling < ancestor'); + assert($('grand-sibling').descendantOf('sibling'), 'grand-sibling < sibling'); + assert($('grand-sibling').descendantOf('ancestor'), 'grand-sibling < ancestor'); + + assert($('grand-sibling').descendantOf(document.body), 'grand-sibling < body'); + window.debug = false; + + assert(!$('great-grand-child').descendantOf('great-grand-child'), 'great-grand-child < great-grand-child'); + assert(!$('great-grand-child').descendantOf('sibling'), 'great-grand-child < sibling'); + assert(!$('sibling').descendantOf('child'), 'sibling < child'); + assert(!$('great-grand-child').descendantOf('not-in-the-family'), 'great-grand-child < not-in-the-family'); + assert(!$('child').descendantOf('not-in-the-family'), 'child < not-in-the-family'); }}, testChildOf: function() {with(this) {