Skip to content

Commit 7b09d80

Browse files
Optimize traversal in Element#up, #down, #next, and #previous by extending only the element that will be returned. Do the same for Event#findElement. (shagstrom)
1 parent 978efc8 commit 7b09d80

File tree

2 files changed

+44
-59
lines changed

2 files changed

+44
-59
lines changed

src/prototype/dom/dom.js

Lines changed: 34 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,30 @@
15451545
return selector.match(element);
15461546
}
15471547

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+
15481572
/**
15491573
* Element.up(@element[, expression[, index = 0]]) -> Element
15501574
* Element.up(@element[, index = 0]) -> Element
@@ -1648,14 +1672,11 @@
16481672
**/
16491673
function up(element, expression, index) {
16501674
element = $(element);
1651-
1675+
16521676
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);
16571678
}
1658-
1679+
16591680
/**
16601681
* Element.down(@element[, expression[, index = 0]]) -> Element
16611682
* Element.down(@element[, index = 0]) -> Element
@@ -1754,38 +1775,15 @@
17541775
* // -> undefined
17551776
**/
17561777
function down(element, expression, index) {
1757-
element = $(element);
1778+
element = $(element), expression = expression || 0, index = index || 0;
17581779

1759-
if (arguments.length === 1) return firstDescendant(element);
1780+
if (Object.isNumber(expression))
1781+
index = expression, expression = '*';
17601782

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];
17831784
return Element.extend(node);
17841785
}
1785-
1786-
if (!Prototype.BrowserFeatures.ElementExtensions)
1787-
down = down_IE;
1788-
1786+
17891787
/**
17901788
* Element.previous(@element[, expression[, index = 0]]) -> Element
17911789
* Element.previous(@element[, index = 0]) -> Element
@@ -1886,16 +1884,7 @@
18861884
* // -> undefined
18871885
**/
18881886
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);
18991888
}
19001889

19011890
/**
@@ -1998,16 +1987,7 @@
19981987
* // -> undefined
19991988
**/
20001989
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);
20111991
}
20121992

20131993
/**

src/prototype/dom/event.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,13 @@
220220
* });
221221
**/
222222
function element(event) {
223+
// The public version of `Event.element` is a thin wrapper around the
224+
// private `_element` method below. We do this so that we can use it
225+
// internally as `_element` without having to extend the node.
226+
return Element.extend(_element(event));
227+
}
228+
229+
function _element(event) {
223230
event = Event.extend(event);
224231

225232
var node = event.target, type = event.type,
@@ -268,13 +275,11 @@
268275
* });
269276
**/
270277
function findElement(event, expression) {
271-
var element = Event.element(event);
272-
273-
if (!expression) return element;
278+
var element = _element(event), match = Prototype.Selector.match;
279+
if (!expression) return Element.extend(element);
274280
while (element) {
275-
if (Object.isElement(element) && Prototype.Selector.match(element, expression)) {
281+
if (Object.isElement(element) && match(element, expression))
276282
return Element.extend(element);
277-
}
278283
element = element.parentNode;
279284
}
280285
}

0 commit comments

Comments
 (0)