Вход Регистрация
Файл: framework/thirdparty/jquery-selector/src/jquery.selector.matches.js
Строк: 314
<?php
/*
This attempts to do the opposite of Sizzle.
Sizzle is good for finding elements for a selector, but not so good for telling if an individual element matches a selector
*/

(function($) {
    
    
/**** CAPABILITY TESTS ****/
    
var div document.createElement('div');
    
div.innerHTML '<form id="test"><input name="id" type="text"/></form>';
    
    
// In IE 6-7, getAttribute often does the wrong thing (returns similar to el.attr), so we need to use getAttributeNode on that browser
    
var getAttributeDodgy div.firstChild.getAttribute('id') !== 'test';
    
    
// Does browser support Element.firstElementChild, Element.previousElementSibling, etc.
    
var hasElementTraversal div.firstElementChild && div.firstElementChild.tagName == 'FORM';
    
    
// Does browser support Element.children
    
var hasChildren div.children && div.children[0].tagName == 'FORM';

    var 
FUNC_IN  = /^s*functions*([^)]*)s*{/;
    var 
FUNC_OUT = /}s*$/;

    var 
funcToString = function(f) {
        return (
''+f).replace(FUNC_IN,'').replace(FUNC_OUT,'');
    }

    
// Can we use Function#toString ?
    
try {
        var 
testFunc = function(){ return 'good' };
        if ((new Function(
'',funcToString(testFunc)))() != 'good'funcToString false;
    }
    catch(
e) { funcToString falseconsole.log(e.message);/*pass*/ }

    
/**** INTRO ****/
    
    
var GOOD = /GOOD/g;
    var 
BAD = /BAD/g;
    
    var 
STARTS_WITH_QUOTES = /^['"]/g;
    
    var join = function(js) {
        return js.join('
n');
    }
    
    var join_complex = function(js) {
        code = new String(js.join('
n')); // String objects can have properties set. strings can't
        code
.complex true;
        return 
code;
    }
    
    
/**** ATTRIBUTE ACCESSORS ****/
    
    
var getAttr;
    
    
// Good browsers
    
if (!getAttributeDodgy) {
        
getAttr = function(attr){ return 'var _'+attr+' = el.getAttribute("'+attr+'");' ; }
    }
    
// IE 6, 7
    
else {
        
// On IE 6 + 7, getAttribute still has to be called with DOM property mirror name, not attribute name. Map attributes to those names
        
var getAttrIEMap = { 'class''className''for''htmlFor' };
        
        
getAttr = function(attr) {
            var 
ieattr getAttrIEMap[attr] || attr;
            return 
'var _'+attr+' = el.getAttribute("'+ieattr+'",2) || (el.getAttributeNode("'+attr+'")||{}).nodeValue;';
        }
    }
    
    
/**** ATTRIBUTE COMPARITORS ****/
    
    
var attrchecks = {
        
'-':  '!_K',
        
'=':  '_K != "V"',
        
'!=''_K == "V"',
        
'~=''__K.indexOf(" V ") == -1',
        
'^=''!_K || _K.indexOf("V") != 0',
        
'*=''!_K || _K.indexOf("V") == -1',
        
'$=''!_K || _K.substr(_K.length-"V".length) != "V"'
    
}

    
/**** STATE TRACKER ****/
    
    
var State = $.selector.State Base.extend({
        
init: function(){ 
            
this.reset(); 
        },
        
reset: function() {
            
this.attrs = {}; this.wsattrs = {};
        },

        
prev: function(){
            
this.reset();
            if (
hasElementTraversal) return 'el = el.previousElementSibling';
            return 
'while((el = el.previousSibling) && el.nodeType != 1) {}';
        },
        
next: function() {
            
this.reset();
            if (
hasElementTraversal) return 'el = el.nextElementSibling';
            return 
'while((el = el.nextSibling) && el.nodeType != 1) {}';
        },
        
prevLoop: function(body){
            
this.reset();
            if (
hasElementTraversal) return join([ 'while(el = el.previousElementSibling){'body]);
            return 
join([
                
'while(el = el.previousSibling){',
                    
'if (el.nodeType != 1) continue;',
                    
body,
            ]);
        },
        
parent: function() {
            
this.reset();
            return 
'el = el.parentNode;';
        },
        
parentLoop: function(body) {
            
this.reset();
            return 
join([
                
'while((el = el.parentNode) && el.nodeType == 1){',
                    
body,
                
'}'
            
]);
        },
        
        
uses_attr: function(attr) {
            if (
this.attrs[attr]) return;
            
this.attrs[attr] = true;
            return 
getAttr(attr); 
        },
        
uses_wsattr: function(attr) {
            if (
this.wsattrs[attr]) return;
            
this.wsattrs[attr] = true;
            return 
join([this.uses_attr(attr), 'var __'+attr+' = " "+_'+attr+'+" ";']); 
        },
        
        
save: function(lbl) {
            return 
'var el'+lbl+' = el;';
        },
        
restore: function(lbl) {
            
this.reset();
            return 
'el = el'+lbl+';';
        }
    });
    
    
/**** PSEUDO-CLASS DETAILS ****/
    
    
var pseudoclschecks = {
        
'first-child'join([
            
'var cel = el;',
            
'while(cel = cel.previousSibling){ if (cel.nodeType === 1) BAD; }',
        ]),
        
'last-child'join([
            
'var cel = el;',
            
'while(cel = cel.nextSibling){ if (cel.nodeType === 1) BAD; }'
        
]),
        
'nth-child': function(a,b) {
            var 
get_i join([
                
'var i = 1, cel = el;',
                
'while(cel = cel.previousSibling){',
                    
'if (cel.nodeType === 1) i++;',
                
'}',
            ]);
            
            if (
== 0) return join([
                
get_i,
                
'if (i- '+b+' != 0) BAD;'
            
]);
            else if (
== && >= 0) return join([
                
get_i,
                
'if (i%'+a+' != 0 || i/'+a+' < 0) BAD;'
            
]);
            else if (
== && 0) return join([
                
'BAD;'
            
]);
            else return 
join([
                
get_i,
                
'if ((i- '+b+')%'+a+' != 0 || (i- '+b+')/'+a+' < 0) BAD;'
            
]);
        }
    };
    
    
// Needs to refence contents of object, so must be injected after definition
    
pseudoclschecks['only-child'] = join([
        
pseudoclschecks['first-child'],
        
pseudoclschecks['last-child']
    ]);
    
    
/**** SimpleSelector ****/
    
    
$.selector.SimpleSelector.addMethod('compile', function(el) {
        var 
js = [];
        
        
/* Check against element name */            
        
if (this.tag && this.tag != '*') {
            
js[js.length] = 'if (el.tagName != "'+this.tag.toUpperCase()+'") BAD;';
        }

        
/* Check against ID */
        
if (this.id) {
            
js[js.length] = el.uses_attr('id');
            
js[js.length] = 'if (_id !== "'+this.id+'") BAD;';
        }
        
        
/* Build className checking variable */
        
if (this.classes.length) {
            
js[js.length] = el.uses_wsattr('class');
            
            
/* Check against class names */
            
$.each(this.classes, function(icls){
                
js[js.length] = 'if (__class.indexOf(" '+cls+' ") == -1) BAD;';
            })
        }
        
        
/* Check against attributes */
        
$.each(this.attrs, function(iattr){
            
js[js.length] = (attr[1] == '~=') ? el.uses_wsattr(attr[0]) : el.uses_attr(attr[0]);
            var 
check attrchecksattr[1] || '-' ];
            
check check.replace( /K/gattr[0]).replace( /V/gattr[2] && attr[2].match(STARTS_WITH_QUOTES) ? attr[2].slice(1,-1) : attr[2] );
            
js[js.length] = 'if ('+check+') BAD;';
        });
        
        
/* Check against nots */
        
$.each(this.nots, function(inot){
            var 
lbl = ++lbl_id;
            var 
func join([
                
'l'+lbl+':{',
                    
not.compile(el).replace(BAD'break l'+lbl).replace(GOOD'BAD'),
                
'}'
            
]);
            
            if (!(
not instanceof $.selector.SimpleSelector)) func join([
                
el.save(lbl),
                
func,
                
el.restore(lbl)
            ])
                
            
js[js.length] = func;
        });
        
        
/* Check against pseudo-classes */
        
$.each(this.pseudo_classes, function(ipscls){
            var 
check pseudoclschecks[pscls[0]];
            if (
check) {
                
js[js.length] = ( typeof check == 'function' check.apply(thispscls[1]) : check );
            }
            else if (
check = $.find.selectors.filters[pscls[0]]) {
                if (
funcToString) {
                    
js[js.length] = funcToString(check).replace(/elem/g,'el').replace(/return([^;]+);/,'if (!($1)) BAD;');
                }
                else {
                    
js[js.length] = 'if (!$.find.selectors.filters.'+pscls[0]+'(el)) BAD;'
                
}
            }
        });
        
        
js[js.length] = 'GOOD';
        
        
/* Pass */
        
return join(js);
    });
    
    var 
lbl_id 0;
    
/** Turns an compiled fragment into the first part of a combination */
    
function as_subexpr(f) {
        if (
f.complex)
            return 
join([
                
'l'+(++lbl_id)+':{',
                    
f.replace(GOOD'break l'+lbl_id),
                
'}',
            ]);
        else
            return 
f.replace(GOOD'');
    }
    
    var 
combines = {
        
' ': function(elf1f2) {
            return 
join_complex([
                
f2,
                
'while(true){',
                    
el.parent(),
                    
'if (!el || el.nodeType !== 1) BAD;',
                    
f1.compile(el).replace(BAD'continue'),
                
'}'
            
]);
        },
        
        
'>': function(elf1f2) {
            return 
join([
                
f2,
                
el.parent(),
                
'if (!el || el.nodeType !== 1) BAD;',
                
f1.compile(el)
            ]);
        },
        
        
'~': function(elf1f2) {
            return 
join_complex([
                
f2,
                
el.prevLoop(),
                    
f1.compile(el).replace(BAD'continue'),
                
'}',
                
'BAD;'
            
]);
        },
        
        
'+': function(elf1f2) {
            return 
join([
                
f2,
                
el.prev(),
                
'if (!el) BAD;',
                
f1.compile(el)
            ]);
        }
    };
    
    $.
selector.Selector.addMethod('compile', function(el) {
        
this.parts.length;
        
        
expr this.parts[--l].compile(el);
        while (
l) {
            
combinator this.parts[--l];
            
expr combines[combinator](elthis.parts[--l], as_subexpr(expr));
        }
        
        return 
expr;
    });

    $.
selector.SelectorsGroup.addMethod('compile', function(el) {
        var 
expr = [], lbl = ++lbl_id;
        
        for (var 
i=0this.parts.lengthi++) {
            
expr[expr.length] = join([
                
== el.save(lbl) : el.restore(lbl), 
                
'l'+lbl+'_'+i+':{',
                    
this.parts[i].compile(el).replace(BAD'break l'+lbl+'_'+i),
                
'}'
            
]);
        }
        
        
expr[expr.length] = 'BAD;';
        return 
join(expr);
    });

    $.
selector.SelectorBase.addMethod('matches', function(el){    
        
this.matches = new Function('el'join([ 
            
'if (!el) return false;',
            
this.compile(new State()).replace(BAD'return false').replace(GOOD'return true')
        ]));
        return 
this.matches(el);
    });
    
})(
jQuery);
?>
Онлайн: 0
Реклама