diff --git a/src/dom/dom.js b/src/dom/dom.js index c6e5688..6ab0241 100644 --- a/src/dom/dom.js +++ b/src/dom/dom.js @@ -611,7 +611,7 @@ Element.Methods = { if (arguments.length == 1) return $(element.parentNode); var ancestors = Element.ancestors(element); return Object.isNumber(expression) ? ancestors[expression] : - Prototype.Selector.filter(ancestors, expression)[index || 0]; + Prototype.Selector.find(ancestors, expression, index); }, /** @@ -647,7 +647,7 @@ Element.Methods = { if (!Object.isNumber(index)) index = 0; if (expression) { - return Prototype.Selector.filter(element.previousSiblings(), expression)[index]; + return Prototype.Selector.find(element.previousSiblings(), expression, index); } else { return element.recursivelyCollect("previousSibling", index + 1)[index]; } @@ -669,7 +669,7 @@ Element.Methods = { if (!Object.isNumber(index)) index = 0; if (expression) { - return Prototype.Selector.filter(element.nextSiblings(), expression)[index]; + return Prototype.Selector.find(element.nextSiblings(), expression, index); } else { var maximumLength = Object.isNumber(index) ? index + 1 : 1; return element.recursivelyCollect("nextSibling", index + 1)[index]; diff --git a/src/dom/event.js b/src/dom/event.js index 0bd9fd1..84fda31 100644 --- a/src/dom/event.js +++ b/src/dom/event.js @@ -149,14 +149,10 @@ function findElement(event, expression) { var element = Event.element(event); if (!expression) return element; - while (element) { - if (Prototype.Selector.match(element, expression)) { - return Element.extend(element); - } - element = element.parentNode - } + var elements = [element].concat(element.ancestors()); + return Prototype.Selector.find(elements, expression, 0); } - + /** * Event.pointer(@event) -> Object * diff --git a/src/dom/selector.js b/src/dom/selector.js index 7e7470b..c327603 100644 --- a/src/dom/selector.js +++ b/src/dom/selector.js @@ -42,15 +42,25 @@ window.$$ = function() { // Implementation provided by selector engine. /** - * Prototype.Selector.filter(elements, expression) -> [Element...] + * Prototype.Selector.find(elements, expression[, index]) -> Element * - elements (Enumerable): a collection of DOM elements. * - expression (String): A CSS selector. + # - index: Numeric index of the match to return, or 0 if omitted. * - * Filters the given collection of elements with `expression` and returns an - * array of extended [[Element]] objects. - * - * The only nodes returned will be those that match the given CSS selector. + * Filters the given collection of elements with `expression` and returns the + * first matching element (or the `index`th matching element if `index` is + * specified). **/ +if (!Prototype.Selector.find) { + Prototype.Selector.find = function(elements, expression, index) { + if (Object.isUndefined(index)) index = 0; + var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i; -// Implementation provided by selector engine. + for (i = 0; i < length; i++) { + if (match(elements[i], expression) && index == matchIndex++) { + return Element.extend(elements[i]); + } + } + } +} diff --git a/src/selector_engine.js b/src/selector_engine.js index 9ec1266..45ba30c 100644 --- a/src/selector_engine.js +++ b/src/selector_engine.js @@ -16,16 +16,11 @@ Prototype.Selector = (function(engine) { function match(element, selector) { return engine.matches(selector, [element]).length == 1; } - - function filter(elements, selector) { - return extend(engine.matches(selector, elements)); - } - + return { engine: engine, select: select, - match: match, - filter: filter + match: match }; })(Sizzle); diff --git a/test/unit/selector_engine_test.js b/test/unit/selector_engine_test.js index dec966f..da428b0 100644 --- a/test/unit/selector_engine_test.js +++ b/test/unit/selector_engine_test.js @@ -41,13 +41,10 @@ new Test.Unit.Runner({ this.assertEqual(false, Prototype.Selector.match(element, '.non_existent')); }, - testFilter: function() { + testFind: function() { var elements = document.getElementsByTagName('*'), - filtered = Prototype.Selector.filter(elements, '.test_class'); - - this.assert(Object.isArray(filtered)); - this.assertEqual(2, filtered.length); - this.assertEqual('test_div_parent', filtered[0].id); - this.assertEqual('test_div_child', filtered[1].id); + expression = '.test_class'; + this.assertEqual('test_div_parent', Prototype.Selector.find(elements, expression).id); + this.assertEqual('test_div_child', Prototype.Selector.find(elements, expression, 1).id); } }); \ No newline at end of file diff --git a/vendor/nwmatcher/selector_engine.js b/vendor/nwmatcher/selector_engine.js index 5bc8ac4..2d55a14 100644 --- a/vendor/nwmatcher/selector_engine.js +++ b/vendor/nwmatcher/selector_engine.js @@ -6,22 +6,10 @@ Prototype.Selector = (function(engine) { return engine.select(selector, scope || document, null, Element.extend); } - function filter(elements, selector) { - var results = [], element, i = 0; - while (element = elements[i++]) { - if (engine.match(element, selector)) { - Element.extend(element); - results.push(element); - } - } - return results; - } - return { engine: engine, select: select, - match: engine.match, - filter: filter + match: engine.match }; })(NW.Dom);