diff --git a/CHANGELOG b/CHANGELOG index d2b1994..3880358 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ *SVN* +* Optimize DOM navigation methods (Element#up, Element#down, Element#previous, Element#next) for no-argument calls. Closes #7848. [haraldmartin, sam] + +* Add Element#firstDescendant to retrieve the first non-text child node of an element. [sam] + * Element.addMethods should add methods to Element as well as Element.Methods. Closes #7888. [Andrew Dupont] * Add support for per-request onCreate callbacks to Ajax.Request. Closes #8011. [Andrew Dupont] diff --git a/src/dom.js b/src/dom.js index e2406fb..7a47873 100644 --- a/src/dom.js +++ b/src/dom.js @@ -152,6 +152,12 @@ Element.Methods = { return $A($(element).getElementsByTagName('*')).each(Element.extend); }, + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + immediateDescendants: function(element) { if (!(element = $(element).firstChild)) return []; while (element && element.nodeType != 1) element = element.nextSibling; @@ -179,25 +185,33 @@ Element.Methods = { }, up: function(element, expression, index) { - var ancestors = $(element).ancestors(); + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); return expression ? Selector.findElement(ancestors, expression, index) : ancestors[index || 0]; }, down: function(element, expression, index) { - var descendants = $(element).descendants(); + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + var descendants = element.descendants(); return expression ? Selector.findElement(descendants, expression, index) : descendants[index || 0]; }, previous: function(element, expression, index) { - var previousSiblings = $(element).previousSiblings(); + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); return expression ? Selector.findElement(previousSiblings, expression, index) : previousSiblings[index || 0]; }, next: function(element, expression, index) { - var nextSiblings = $(element).nextSiblings(); + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); return expression ? Selector.findElement(nextSiblings, expression, index) : nextSiblings[index || 0]; }, diff --git a/test/unit/dom.html b/test/unit/dom.html index 6b4e541..89a36f5 100644 --- a/test/unit/dom.html +++ b/test/unit/dom.html @@ -479,6 +479,11 @@ assert(typeof dummy.descendants()[0].setStyle == 'function'); }}, + testElementFirstDescendant: function() {with(this) { + assertElementMatches($('navigation_test').firstDescendant(), 'li.first'); + assertNull($('navigation_test_next_sibling').firstDescendant()); + }}, + testElementImmediateDescendants: function() {with(this) { assertElementsMatch($('navigation_test').immediateDescendants(), 'li.first', 'li', 'li#navigation_test_c', 'li.last');