From 733a7350d178ed5a34469a26b6b030d9a4e7893a Mon Sep 17 00:00:00 2001 From: Yaroslaff Fedin Date: Fri, 22 Apr 2011 10:26:42 +0800 Subject: [PATCH 1/2] Add a recursive matcher on top of upstream --- Source/Slick.Finder.js | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/Source/Slick.Finder.js b/Source/Slick.Finder.js index 43fb7dec..7f927cfb 100644 --- a/Source/Slick.Finder.js +++ b/Source/Slick.Finder.js @@ -551,33 +551,29 @@ local.pushUID = function(node, tag, id, classes, attributes, pseudos){ } }; -local.matchNode = function(node, selector){ - if (this.isHTMLDocument && this.nativeMatchesSelector){ +var reSingularCombinator = /^\!?[>+^]$/; // "+", ">", "^" +local.matchNode = function(node, selector, needle){ + if (!needle && this.isHTMLDocument && this.nativeMatchesSelector){ try { return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]')); } catch(matchError) {} } - var parsed = this.Slick.parse(selector); if (!parsed) return true; - - // simple (single) selectors - var expressions = parsed.expressions, reversedExpressions, simpleExpCounter = 0, i; - for (i = 0; (currentExpression = expressions[i]); i++){ - if (currentExpression.length == 1){ - var exp = currentExpression[0]; - if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true; - simpleExpCounter++; - } - } - - if (simpleExpCounter == parsed.length) return false; - - var nodes = this.search(this.document, parsed), item; - for (i = 0; item = nodes[i++];){ - if (item === node) return true; + parsed = parsed.reverse(); + for (var i = 0, expression, expressions, built, length, multiple; expression = parsed.expressions[i]; i++) { + var first = expression[0]; + if (local.matchSelector(node, (this.isXMLDocument) ? first.tag : first.tag.toUpperCase(), first.id, first.classes, first.attributes, first.pseudos)) { // matching first selector against element + if ((length = expression.length) == 1) continue; + if (!built) built = {Slick: true, expressions: [], length: 0}; + built.expressions.push(expressions = []); + built.length++; + for (var j = 1; j < length; j++) expressions.push(expression[j]); + if (!multiple) multiple = !expression[expression.length - 1].combinator.match(reSingularCombinator); + } else return false; } - return false; + var found = built ? this.search(node, built, null, !(multiple && needle)) : node; + return needle ? (multiple ? found.indexOf(needle) > -1 : found == needle) : !!found; }; local.matchPseudo = function(node, name, argument){ From 4518bfef2d9197c3ab9f18559462d2575ec49201 Mon Sep 17 00:00:00 2001 From: Yaroslaff Fedin Date: Fri, 22 Apr 2011 10:41:25 +0800 Subject: [PATCH 2/2] Dont parse already parsed selector --- Source/Slick.Finder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Slick.Finder.js b/Source/Slick.Finder.js index 7f927cfb..9e0edf15 100644 --- a/Source/Slick.Finder.js +++ b/Source/Slick.Finder.js @@ -558,7 +558,7 @@ local.matchNode = function(node, selector, needle){ return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]')); } catch(matchError) {} } - var parsed = this.Slick.parse(selector); + var parsed = ((selector.Slick) ? selector : this.Slick.parse(selector)); if (!parsed) return true; parsed = parsed.reverse(); for (var i = 0, expression, expressions, built, length, multiple; expression = parsed.expressions[i]; i++) {