/**
* author:prk
* date:2008-08-04
* comment:comment for selector of jQuery
*
*/
var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417
? "(?:[\\w*_-]|\\\\.)"
: "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)", quickChild = new RegExp("^>\\s*("
+ chars + "+)"), quickID = new RegExp("^(" + chars + "+)(#)(" + chars
+ "+)"), // ^((?:[\\w*_-]|\\\\.))(#)((?:[\\w*_-]|\\\\.))
quickClass = new RegExp("^([#.]?)(" + chars + "*)");// ^([#.]?)((?:[\\w*_-]|\\\\.)*)
jQuery.extend( {
expr : {
"" : function(a, i, m) {
return m[2] == "*" || jQuery.nodeName(a, m[2]);
},
"#" : function(a, i, m) {
return a.getAttribute("id") == m[2];
},
":" : {
// Position Checks
lt : function(a, i, m) {
return i < m[3] - 0;
},
gt : function(a, i, m) {
return i > m[3] - 0;
},
nth : function(a, i, m) {
return m[3] - 0 == i;
},
eq : function(a, i, m) {
return m[3] - 0 == i;
},
first : function(a, i) {
return i == 0;
},
last : function(a, i, m, r) {
return i == r.length - 1;
},
even : function(a, i) {
return i % 2 == 0;
},
odd : function(a, i) {
return i % 2;
},
// Child Checks
"first-child" : function(a) {
return a.parentNode.getElementsByTagName("*")[0] == a;
},
"last-child" : function(a) {
return jQuery.nth(a.parentNode.lastChild, 1, "previousSibling") == a;
},
"only-child" : function(a) {
return !jQuery.nth(a.parentNode.lastChild, 2, "previousSibling");
},
// Parent Checks
parent : function(a) {
return a.firstChild;
},
empty : function(a) {
return !a.firstChild;
},
// Text Check
contains : function(a, i, m) {
return (a.textContent || a.innerText || jQuery(a).text() || "")
.indexOf(m[3]) >= 0;
},
// Visibility
visible : function(a) {
return "hidden" != a.type && jQuery.css(a, "display") != "none"
&& jQuery.css(a, "visibility") != "hidden";
},
hidden : function(a) {
return "hidden" == a.type || jQuery.css(a, "display") == "none"
|| jQuery.css(a, "visibility") == "hidden";
},
// Form attributes
enabled : function(a) {
return !a.disabled;
},
disabled : function(a) {
return a.disabled;
},
checked : function(a) {
return a.checked;
},
selected : function(a) {
return a.selected || jQuery.attr(a, "selected");
},
// Form elements
text : function(a) {
return "text" == a.type;
},
radio : function(a) {
return "radio" == a.type;
},
checkbox : function(a) {
return "checkbox" == a.type;
},
file : function(a) {
return "file" == a.type;
},
password : function(a) {
return "password" == a.type;
},
submit : function(a) {
return "submit" == a.type;
},
image : function(a) {
return "image" == a.type;
},
reset : function(a) {
return "reset" == a.type;
},
button : function(a) {
return "button" == a.type || jQuery.nodeName(a, "button");
},
input : function(a) {
return /input|select|textarea|button/i.test(a.nodeName);
},
// :has()
has : function(a, i, m) {
return jQuery.find(m[3], a).length;
},
// :header
header : function(a) {
return /h\d/i.test(a.nodeName);
},
// :animated
animated : function(a) {
return jQuery.grep(jQuery.timers, function(fn) {
return a == fn.elem;
}).length;
}
}
},
// The regular expressions that power the parsing engine
parse : [
// Match: [@value='test'], [@foo]
/^(\[) *@?([\w:-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
// Match: :contains('foo')
/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
// Match: :even, :last-child, #id, .class
new RegExp("^([:.#]*)(" + chars + "+)")],
multiFilter : function(expr, elems, not) {
var old, cur = [];
while (expr && expr != old) {//
old = expr;
var f = jQuery.filter(expr, elems, not);
expr = f.t.replace(/^\s*,\s*/, "");
cur = not ? elems = f.r : jQuery.merge(cur, f.r);
}
return cur;
},
find : function(t, context) {
if (typeof t != "string")
return [t];//
if (context && context.nodeType != 1 && context.nodeType != 9)
return [];// context DOM document
context = context || document;// context
// ,ret:result, done: ,last: t,nodeName: , p
var ret = [context], done = [], last, nodeName;
while (t && last != t) {// t ,
var r = []; // ret tempValue
last = t; // last: t
t = jQuery.trim(t);//
var foundToken = false, re = quickChild, // > regexp
m = re.exec(t);
if (m) {// >
nodeName = m[1].toUpperCase();
// regexp nodeName 。
for (var i = 0;ret[i]; i++)
for (var c = ret[i].firstChild;c; c = c.nextSibling)
if (c.nodeType == 1
&& (nodeName == "*" || c.nodeName.toUpperCase() == nodeName))
r.push(c);
ret = r; // (context)
t = t.replace(re, "");// remove
if (t.indexOf(" ") == 0)// "E F"
continue;//
foundToken = true;//
} else {// +~
re = /^([>+~])\s*(\w*)/i;
if ((m = re.exec(t)) != null) {// +~
r = [];
var merge = {};
nodeName = m[2].toUpperCase();//
m = m[1];// , +,~
// t " " >( ), context ,
// t ~ +( ), context
for (var j = 0, rl = ret.length;j < rl; j++) {// (context)
// ~ +
var n = (m == "~" || m == "+"
? ret[j].nextSibling
: ret[j].firstChild);
for (;n; n = n.nextSibling)
if (n.nodeType == 1) {//
var id = jQuery.data(n);// n id
if (m == "~" && merge[id])// ret
break;// nextSibling ?
if (!nodeName
|| n.nodeName.toUpperCase() == nodeName) {
if (m == "~")//
merge[id] = true;
r.push(n);
}
if (m == "+")// , 。
break;
}
}
ret = r;//
t = jQuery.trim(t.replace(re, ""));
foundToken = true;
}
}
if (t && !foundToken) {// >~+
if (!t.indexOf(",")) {// ,
if (context == ret[0])
ret.shift();// context ret
done = jQuery.merge(done, ret);// ret done
r = ret = [context];//
// Touch up the selector string
t = " " + t.substr(1, t.length);
} else {// ,
/*
* qId:^((?:[\w*_-]|\.)+)(#)((?:[\w*_-]|\.)+)
* qclass:^([#.]?)((?:[\\w*_-]|\.)*)
*/
var re2 = quickID;// (.)nodeName#idName
var m = re2.exec(t);//
if (m) {
m = [0, m[2], m[3], m[1]];// m=[0,#,idName,nodeName]
} else {
re2 = quickClass;// #nodeName,.className
m = re2.exec(t);// m=[all,#,idName]
}
m[2] = m[2].replace(/\\/g, "");//
var elem = ret[ret.length - 1];//
// Id
if (m[1] == "#" && elem && elem.getElementById
&& !jQuery.isXMLDoc(elem)) {
var oid = elem.getElementById(m[2]);
// ID , IE name , form
// form name id 。
if ((jQuery.browser.msie || jQuery.browser.opera) && oid
&& typeof oid.id == "string" && oid.id != m[2])
oid = jQuery('[@id="' + m[2] + '"]', elem)[0];
// node Name , div#foo,
ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3]))
? [oid]
: [];
} else {// ,
for (var i = 0;ret[i]; i++) {
var tag = (m[1] == "#" && m[3] ? m[3] : (m[1] != ""
|| m[0] == "" ? "*" : m[2]));// tagName
if (tag == "*"
&& ret[i].nodeName.toLowerCase() == "object")
tag = "param";// Handle IE7 being really dumb
// about <object>s
r = jQuery.merge(r, ret[i].getElementsByTagName(tag));
}
if (m[1] == ".") // class
r = jQuery.classFilter(r, m[2]);
if (m[1] == "#") {// id , regexp id
var tmp = [];
for (var i = 0;r[i]; i++)
if (r[i].getAttribute("id") == m[2]) {
tmp = [r[i]];
break;
}
r = tmp;
}
ret = r;
}
t = t.replace(re2, "");
}
}
if (t) {// selector, r
var val = jQuery.filter(t, r);
ret = r = val.r;
t = jQuery.trim(val.t);//
}
}
if (t)// selector , []。
ret = [];
if (ret && context == ret[0])
ret.shift();//
done = jQuery.merge(done, ret);//
return done;
},
// r element className m
classFilter : function(r, m, not) {
m = " " + m + " ";
var tmp = [];
for (var i = 0;r[i]; i++) {
var pass = (" " + r[i].className + " ").indexOf(m) >= 0;
if (!not && pass || not && !pass)
tmp.push(r[i]);
}
return tmp;
},
filter : function(t, r, not) {
var last;
while (t && t != last) {// t ,
last = t;
// Match: [@value='test'], [@foo]
// 1、^(\[) *@?([\w:-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
// Match: :contains('foo')
// 2、^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
// Match: :even, :last-child, #id, .class
// 3、new RegExp("^([:.#]*)(" + chars + "+)")],
// isSimple = /^.[^:#\[\.]*$/
var p = jQuery.parse, m;
for (var i = 0;p[i]; i++) {// jQuery.parse regexp
m = p[i].exec(t);
if (m) {
t = t.substring(m[0].length);
m[2] = m[2].replace(/\\/g, "");// \
break;
}
}
if (!m)// regexp
break;
// :not(.class) .class
if (m[1] == ":" && m[2] == "not")
// m[3] .class
r = isSimple.test(m[3])
? jQuery.filter(m[3], r, true).r
: jQuery(r).not(m[3]);
else if (m[1] == ".")//
r = jQuery.classFilter(r, m[2], not);
else if (m[1] == "[") {// [@value='test']
var tmp = [], type = m[3];// , =
for (var i = 0, rl = r.length;i < rl; i++) {
var a = r[i], z = a[jQuery.props[m[2]] || m[2]];//
if (z == null || /style|href|src|selected/.test(m[2]))
z = jQuery.attr(a, m[2]) || '';//
// [foo],[foo=aa][foo!=aa][foo^=aa][foo$=aa][foo~=aa]
if ((type == "" && !!z || type == "=" && z == m[5]
|| type == "!=" && z != m[5] || type == "^=" && z
&& !z.indexOf(m[5]) || type == "$="
&& z.substr(z.length - m[5].length) == m[5] || (type == "*=" || type == "~=")
&& z.indexOf(m[5]) >= 0)
^ not)
tmp.push(a);
}
r = tmp;
} else if (m[1] == ":" && m[2] == "nth-child") {//
var merge = {}, tmp = [],
// parse equations like 'even', 'odd', '5', '2n', '3n+2',
// '4n-1', '-n+6'
test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3] == "even" && "2n"
|| m[3] == "odd" && "2n+1" || !/\D/.test(m[3]) && "0n+"
+ m[3] || m[3]),
// (first)n+(last),first=(-?)(\d*),last=((?:\+|-)?\d*)
first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
for (var i = 0, rl = r.length;i < rl; i++) {
var node = r[i], parentNode = node.parentNode, id = jQuery
.data(parentNode);
if (!merge[id]) {// ,
var c = 1;
for (var n = parentNode.firstChild;n; n = n.nextSibling)
if (n.nodeType == 1)
n.nodeIndex = c++;
merge[id] = true;
}
var add = false;
if (first == 0) {// 0
if (node.nodeIndex == last)
add = true;
}
// 3n+2 0
else if ((node.nodeIndex - last) % first == 0
&& (node.nodeIndex - last) / first >= 0)
add = true;
if (add ^ not)
tmp.push(node);
}
r = tmp;
} else {// m[1]m[2] Query.expr
var fn = jQuery.expr[m[1]];
if (typeof fn == "object")
fn = fn[m[2]];
if (typeof fn == "string")
fn = eval("false||function(a,i){return " + fn + ";}");
// r
r = jQuery.grep(r, function(elem, i) {
return fn(elem, i, m, r);
}, not);
}
}
// Return an array of filtered elements (r)
// and the modified expression string (t)
return {
r : r,
t : t
};
},
// dir:nextSibling elem:element
dir : function(elem, dir) {
var matched = [], cur = elem[dir];
while (cur && cur != document) {
if (cur.nodeType == 1)
matched.push(cur);
cur = cur[dir];
}
return matched;
},
// dir:nextSibling result:deep cur:current. elem :no use
nth : function(cur, result, dir, elem) {
result = result || 1;
var num = 0;
for (;cur; cur = cur[dir])
if (cur.nodeType == 1 && ++num == result)
break;
return cur;
},
// elem n 。
sibling : function(n, elem) {
var r = [];
for (;n; n = n.nextSibling) {
if (n.nodeType == 1 && n != elem)
r.push(n);
}
return r;
}
});