mootools / slick

Standalone CSS Selector Parser and Engine. An official MooTools project.
MIT License
149 stars 22 forks source link

Faster complex selector matching #48

Closed cpojer closed 8 years ago

cpojer commented 13 years ago

Repost from mootools lighthouse:

https://mootools.lighthouseapp.com/projects/2706/tickets/947-faster-complex-selector-matching

Currently in Slick you're doing a brute force search of the document to find if the element matches the selector, this can be very slow. By leveraging the Slick parser's reverse function, we can speed this up quite a bit.

local.matchNode = function(node, selector){
    var parsed = ((selector.Slick) ? selector : this.Slick.parse(selector));
    if (!parsed) return true;

    var expressions = parsed.expressions, reversedExpressions;
        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.parts)) return true;
            }
        }
        for (i = 0; (currentExpression = expressions[i]); i++){
            if(currentExpression.length > 1){
                reversedExpressions = reversedExpressions || parsed.reverse().expressions;
                currentExpression = reversedExpressions[i];
                var exp = currentExpression.shift();
                if(this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.parts)){
                    if(!!this.search(node, { Slick: true, expressions: [ currentExpression ] }, null, true)) return true;
                }
            }
        }
        return false;
};

It's actually not quite as fast as some previous code I submitted(#574), but that no longer works with Slick.

Inviz commented 13 years ago

You can find a modern one that works on current slick here

https://github.com/lovelyscalabledrawings/slick/blob/master/Source/Slick.Finder.js

I tried to merge it back, even made two pull requests. The tests were all green, but i didnt have the time to check back with Fabio.

Inviz commented 13 years ago

My approach was to use third argument Slick.matchNode(li, 'ul > li', ul), you can read about it in a neighbor issue