|
1545 | 1545 | return selector.match(element);
|
1546 | 1546 | }
|
1547 | 1547 |
|
| 1548 | + |
| 1549 | + // Internal method for optimizing traversal. Works like |
| 1550 | + // `recursivelyCollect`, except it stops at the first match and doesn't |
| 1551 | + // extend any elements except for the returned element. |
| 1552 | + function _recursivelyFind(element, property, expression, index) { |
| 1553 | + element = $(element), expression = expression || 0, index = index || 0; |
| 1554 | + if (Object.isNumber(expression)) { |
| 1555 | + index = expression, expression = null; |
| 1556 | + } |
| 1557 | + |
| 1558 | + while (element = element[property]) { |
| 1559 | + // Skip any non-element nodes. |
| 1560 | + if (element.nodeType !== 1) continue; |
| 1561 | + // Skip any nodes that don't match the expression, if there is one. |
| 1562 | + if (expression && !Prototype.Selector.match(element, expression)) |
| 1563 | + continue; |
| 1564 | + // Skip the first `index` matches we find. |
| 1565 | + if (--index >= 0) continue; |
| 1566 | + |
| 1567 | + return Element.extend(element); |
| 1568 | + } |
| 1569 | + } |
| 1570 | + |
| 1571 | + |
1548 | 1572 | /**
|
1549 | 1573 | * Element.up(@element[, expression[, index = 0]]) -> Element
|
1550 | 1574 | * Element.up(@element[, index = 0]) -> Element
|
|
1648 | 1672 | **/
|
1649 | 1673 | function up(element, expression, index) {
|
1650 | 1674 | element = $(element);
|
1651 |
| - |
| 1675 | + |
1652 | 1676 | if (arguments.length === 1) return $(element.parentNode);
|
1653 |
| - |
1654 |
| - var ancestors = Element.ancestors(element); |
1655 |
| - return Object.isNumber(expression) ? ancestors[expression] : |
1656 |
| - Prototype.Selector.find(ancestors, expression, index); |
| 1677 | + return _recursivelyFind(element, 'parentNode', expression, index); |
1657 | 1678 | }
|
1658 |
| - |
| 1679 | + |
1659 | 1680 | /**
|
1660 | 1681 | * Element.down(@element[, expression[, index = 0]]) -> Element
|
1661 | 1682 | * Element.down(@element[, index = 0]) -> Element
|
|
1754 | 1775 | * // -> undefined
|
1755 | 1776 | **/
|
1756 | 1777 | function down(element, expression, index) {
|
1757 |
| - element = $(element); |
| 1778 | + element = $(element), expression = expression || 0, index = index || 0; |
1758 | 1779 |
|
1759 |
| - if (arguments.length === 1) return firstDescendant(element); |
| 1780 | + if (Object.isNumber(expression)) |
| 1781 | + index = expression, expression = '*'; |
1760 | 1782 |
|
1761 |
| - return Object.isNumber(expression) ? Element.descendants(element)[expression] : |
1762 |
| - Element.select(element, expression)[index || 0]; |
1763 |
| - } |
1764 |
| - |
1765 |
| - |
1766 |
| - function _descendants(element) { |
1767 |
| - var nodes = element.getElementsByTagName('*'), results = []; |
1768 |
| - for (var i = 0, node; node = nodes[i]; i++) |
1769 |
| - if (node.tagName !== "!") // Filter out comment nodes. |
1770 |
| - results.push(node); |
1771 |
| - return results; |
1772 |
| - } |
1773 |
| - |
1774 |
| - // We optimize Element#down for IE so that it does not call |
1775 |
| - // Element#descendants (and therefore extend all nodes). |
1776 |
| - function down_IE(element, expression, index) { |
1777 |
| - element = $(element); |
1778 |
| - if (arguments.length === 1) |
1779 |
| - return Element.firstDescendant(element); |
1780 |
| - |
1781 |
| - var node = Object.isNumber(expression) ? _descendants(element)[expression] : |
1782 |
| - Element.select(element, expression)[index || 0]; |
| 1783 | + var node = Prototype.Selector.select(expression, element)[index]; |
1783 | 1784 | return Element.extend(node);
|
1784 | 1785 | }
|
1785 |
| - |
1786 |
| - if (!Prototype.BrowserFeatures.ElementExtensions) |
1787 |
| - down = down_IE; |
1788 |
| - |
| 1786 | + |
1789 | 1787 | /**
|
1790 | 1788 | * Element.previous(@element[, expression[, index = 0]]) -> Element
|
1791 | 1789 | * Element.previous(@element[, index = 0]) -> Element
|
|
1886 | 1884 | * // -> undefined
|
1887 | 1885 | **/
|
1888 | 1886 | function previous(element, expression, index) {
|
1889 |
| - element = $(element); |
1890 |
| - if (Object.isNumber(expression)) |
1891 |
| - index = expression, expression = false; |
1892 |
| - if (!Object.isNumber(index)) index = 0; |
1893 |
| - |
1894 |
| - if (expression) { |
1895 |
| - return Prototype.Selector.find(previousSiblings(element), expression, index); |
1896 |
| - } else { |
1897 |
| - return recursivelyCollect(element, 'previousSibling', index + 1)[index]; |
1898 |
| - } |
| 1887 | + return _recursivelyFind(element, 'previousSibling', expression, index); |
1899 | 1888 | }
|
1900 | 1889 |
|
1901 | 1890 | /**
|
|
1998 | 1987 | * // -> undefined
|
1999 | 1988 | **/
|
2000 | 1989 | function next(element, expression, index) {
|
2001 |
| - element = $(element); |
2002 |
| - if (Object.isNumber(expression)) |
2003 |
| - index = expression, expression = false; |
2004 |
| - if (!Object.isNumber(index)) index = 0; |
2005 |
| - |
2006 |
| - if (expression) { |
2007 |
| - return Prototype.Selector.find(nextSiblings(element), expression, index); |
2008 |
| - } else { |
2009 |
| - return recursivelyCollect(element, 'nextSibling', index + 1)[index]; |
2010 |
| - } |
| 1990 | + return _recursivelyFind(element, 'nextSibling', expression, index); |
2011 | 1991 | }
|
2012 | 1992 |
|
2013 | 1993 | /**
|
|
0 commit comments