This project is archived and is in readonly mode.

#574 ✓invalid
mattcoz

Element.match w/ complex selector support

Reported by mattcoz | January 26th, 2009 @ 08:23 PM | in 2.0 (closed)

Element.match has a distinct flaw in that it can not match against complex selectors. So if you want to match an element against "div > a" it would not work. This was causing problems for me when I was writing some event delegation code, so I took a stab at fixing it.


Selectors.RegExps.matcher = /(.*[^\s>+~])\s*([\s>+~](?![^\[]*\]))\s*([^\s>+~].*)/;
Selectors.Cache.matcher = {};
 
Element.implement({
    
    match: function(selector){
        if (!selector || (selector == this)) return true;
        
        var selectors = Selectors.Cache.matcher[selector];
        if (selectors === undefined) selectors = (Selectors.Cache.matcher[selector] = Selectors.RegExps.matcher.exec(selector));
        if (selectors) selector = selectors[3];
        
        var tagid = Selectors.Utils.parseTagAndID(selector);
        var tag = tagid[0], id = tagid[1];
        if (!Selectors.Filters.byID(this, id) || !Selectors.Filters.byTag(this, tag)) return false;
        var parsed = Selectors.Utils.parseSelector(selector);
        var match = (!parsed || Selectors.Utils.filter(this, parsed, {})) ? this : null;
            
        if (match && selectors) switch(selectors[2]) {
            case ' ': match = Element.getParent(match, selectors[1]); break;
            case '>': match = Element.getParent(match); if (!Element.match(match, selectors[1])) match = null; break;
            case '+': match = Element.getPrevious(match); if (!Element.match(match, selectors[1])) match = null; break;
            case '~': match = Element.getPrevious(match, selectors[1]); break;
        }
            
        return !!match;
    }
        
});

What this code does is parse the complex selector(caching the result) and run recursively through each part. If it is not a complex selector, it behaves exactly the same as before. I've tested it thoroughly and it works across every selector and situation I've thrown at it.

Comments and changes to this ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

Shared Ticket Bins

People watching this ticket

Pages