[转帖]Mootools源码分析-23 -- Selectors-2
原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-404235
原作者:我佛山人
//根据四种操作符查找
Selectors.Getters = {
//空格,表示根据标签名和id的常规查找
' ': function(found, self, tag, id, uniques) {
var items = Selectors.Utils.getByTagAndID(self, tag, id);
for (var i = 0, l = items.length; i < l; i++) {
var item = items[i];
if (Selectors.Utils.chk(item, uniques)) found.push(item);
}
return found;
},
//大于号>表示子节点的查找
'>': function(found, self, tag, id, uniques) {
var children = Selectors.Utils.getByTagAndID(self, tag, id);
for (var i = 0, l = children.length; i < l; i++) {
var child = children[i];
if (child.parentNode == self && Selectors.Utils.chk(child, uniques)) found.push(child);
}
return found;
},
//加号+表示后兄弟节点的查找
'+': function(found, self, tag, id, uniques) {
while ((self = self.nextSibling)) {
if (self.nodeType == 1) {
if (Selectors.Utils.chk(self, uniques) && Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id))
found.push(self);
break;
}
}
return found;
},
//波浪号~表示后兄弟节点的查找
'~': function(found, self, tag, id, uniques) {
while ((self = self.nextSibling)) {
if (self.nodeType == 1) {
if (!Selectors.Utils.chk(self, uniques)) break;
if (Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);
}
}
return found;
}
};
//过滤器
Selectors.Filters = {
//根据标签过滤
byTag: function(self, tag) {
return (tag == '*' || (self.tagName && self.tagName.toLowerCase() == tag));
},
//根据id过滤
byID: function(self, id) {
return (!id || (self.id && self.id == id));
},
//根据CSS类名过滤
byClass: function(self, klass) {
return (self.className && self.className.contains(klass, ' '));
},
//根据伪类过滤
byPseudo: function(self, parser, argument, local) {
return parser.call(self, argument, local);
},
//根据属性过滤
byAttribute: function(self, name, operator, value) {
//获取属性值
var result = Element.prototype.getProperty.call(self, name);
if (!result) return false;
if (!operator || value == undefined) return true;
//属性值运算
switch (operator) {
//相等
case '=': return (result == value);
//包含
case '*=': return (result.contains(value));
//打头
case '^=': return (result.substr(0, value.length) == value);
//结尾
case '$=': return (result.substr(result.length - value.length) == value);
//不等
case '!=': return (result != value);
//空格分隔包含
case '~=': return result.contains(value, ' ');
//连接符分隔包含
case '|=': return result.contains(value, '-');
}
return false;
}
};
//伪类查找
Selectors.Pseudo = new Hash({
// w3c pseudo selectors
//:empty,匹配不包含文本的节点
empty: function() {
return !(this.innerText || this.textContent || '').length;
},
//:not,匹配非指定标签
not: function(selector) {
return !Element.match(this, selector);
},
//:contains,匹配节点内容中包含指定字符的节点
contains: function(text) {
return (this.innerText || this.textContent || '').contains(text);
},
//:first-child,匹配第一个节点
'first-child': function() {
return Selectors.Pseudo.index.call(this, 0);
},
//:last-child,匹配最后一个节点
'last-child': function() {
var element = this;
while ((element = element.nextSibling)) {
if (element.nodeType == 1) return false;
}
return true;
},
//:only-child,匹配一个子节点类型全为Element的节点
'only-child': function() {
var prev = this;
while ((prev = prev.previousSibling)) {
if (prev.nodeType == 1) return false;
}
var next = this;
while ((next = next.nextSibling)) {
if (next.nodeType == 1) return false;
}
return true;
},
//:nth-child,匹配第n个节点
'nth-child': function(argument, local) {
argument = (argument == undefined) ? 'n' : argument;
var parsed = Selectors.Utils.parseNthArgument(argument);
//非nth伪类的处理转移
if (parsed.special != 'n') return Selectors.Pseudo[parsed.special].call(this, parsed.a, local);
var count = 0;
local.positions = local.positions || {};
var uid = $uid(this);
//如果没有位置标记的记录
if (!local.positions[uid]) {
var self = this;
//查找前面的兄弟节点
while ((self = self.previousSibling)) {
//忽略非Element节点
if (self.nodeType != 1) continue;
count ++;
var position = local.positions[$uid(self)];
//如果有标记了位置的兄弟节点,加上位置后即可跳出循环
if (position != undefined) {
count = position + count;
break;
}
}
local.positions[uid] = count;
}
//a*n + b的判断,可由count = a*n + b推出
return (local.positions[uid] % parsed.a == parsed.b);
},
// custom pseudo selectors
//:index,匹配指定索引的节点
index: function(index) {
var element = this, count = 0;
//向前步进计算当前索引
while ((element = element.previousSibling)) {
if (element.nodeType == 1 && ++count > index) return false;
}
return (count == index);
},
//:even,匹配索引为偶数的节点
even: function(argument, local) {
return Selectors.Pseudo['nth-child'].call(this, '2n+1', local);
},
//:odd,匹配索引为奇数的节点
odd: function(argument, local) {
return Selectors.Pseudo['nth-child'].call(this, '2n', local);
}
})
Selectors.Getters = {
//空格,表示根据标签名和id的常规查找
' ': function(found, self, tag, id, uniques) {
var items = Selectors.Utils.getByTagAndID(self, tag, id);
for (var i = 0, l = items.length; i < l; i++) {
var item = items[i];
if (Selectors.Utils.chk(item, uniques)) found.push(item);
}
return found;
},
//大于号>表示子节点的查找
'>': function(found, self, tag, id, uniques) {
var children = Selectors.Utils.getByTagAndID(self, tag, id);
for (var i = 0, l = children.length; i < l; i++) {
var child = children[i];
if (child.parentNode == self && Selectors.Utils.chk(child, uniques)) found.push(child);
}
return found;
},
//加号+表示后兄弟节点的查找
'+': function(found, self, tag, id, uniques) {
while ((self = self.nextSibling)) {
if (self.nodeType == 1) {
if (Selectors.Utils.chk(self, uniques) && Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id))
found.push(self);
break;
}
}
return found;
},
//波浪号~表示后兄弟节点的查找
'~': function(found, self, tag, id, uniques) {
while ((self = self.nextSibling)) {
if (self.nodeType == 1) {
if (!Selectors.Utils.chk(self, uniques)) break;
if (Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);
}
}
return found;
}
};
//过滤器
Selectors.Filters = {
//根据标签过滤
byTag: function(self, tag) {
return (tag == '*' || (self.tagName && self.tagName.toLowerCase() == tag));
},
//根据id过滤
byID: function(self, id) {
return (!id || (self.id && self.id == id));
},
//根据CSS类名过滤
byClass: function(self, klass) {
return (self.className && self.className.contains(klass, ' '));
},
//根据伪类过滤
byPseudo: function(self, parser, argument, local) {
return parser.call(self, argument, local);
},
//根据属性过滤
byAttribute: function(self, name, operator, value) {
//获取属性值
var result = Element.prototype.getProperty.call(self, name);
if (!result) return false;
if (!operator || value == undefined) return true;
//属性值运算
switch (operator) {
//相等
case '=': return (result == value);
//包含
case '*=': return (result.contains(value));
//打头
case '^=': return (result.substr(0, value.length) == value);
//结尾
case '$=': return (result.substr(result.length - value.length) == value);
//不等
case '!=': return (result != value);
//空格分隔包含
case '~=': return result.contains(value, ' ');
//连接符分隔包含
case '|=': return result.contains(value, '-');
}
return false;
}
};
//伪类查找
Selectors.Pseudo = new Hash({
// w3c pseudo selectors
//:empty,匹配不包含文本的节点
empty: function() {
return !(this.innerText || this.textContent || '').length;
},
//:not,匹配非指定标签
not: function(selector) {
return !Element.match(this, selector);
},
//:contains,匹配节点内容中包含指定字符的节点
contains: function(text) {
return (this.innerText || this.textContent || '').contains(text);
},
//:first-child,匹配第一个节点
'first-child': function() {
return Selectors.Pseudo.index.call(this, 0);
},
//:last-child,匹配最后一个节点
'last-child': function() {
var element = this;
while ((element = element.nextSibling)) {
if (element.nodeType == 1) return false;
}
return true;
},
//:only-child,匹配一个子节点类型全为Element的节点
'only-child': function() {
var prev = this;
while ((prev = prev.previousSibling)) {
if (prev.nodeType == 1) return false;
}
var next = this;
while ((next = next.nextSibling)) {
if (next.nodeType == 1) return false;
}
return true;
},
//:nth-child,匹配第n个节点
'nth-child': function(argument, local) {
argument = (argument == undefined) ? 'n' : argument;
var parsed = Selectors.Utils.parseNthArgument(argument);
//非nth伪类的处理转移
if (parsed.special != 'n') return Selectors.Pseudo[parsed.special].call(this, parsed.a, local);
var count = 0;
local.positions = local.positions || {};
var uid = $uid(this);
//如果没有位置标记的记录
if (!local.positions[uid]) {
var self = this;
//查找前面的兄弟节点
while ((self = self.previousSibling)) {
//忽略非Element节点
if (self.nodeType != 1) continue;
count ++;
var position = local.positions[$uid(self)];
//如果有标记了位置的兄弟节点,加上位置后即可跳出循环
if (position != undefined) {
count = position + count;
break;
}
}
local.positions[uid] = count;
}
//a*n + b的判断,可由count = a*n + b推出
return (local.positions[uid] % parsed.a == parsed.b);
},
// custom pseudo selectors
//:index,匹配指定索引的节点
index: function(index) {
var element = this, count = 0;
//向前步进计算当前索引
while ((element = element.previousSibling)) {
if (element.nodeType == 1 && ++count > index) return false;
}
return (count == index);
},
//:even,匹配索引为偶数的节点
even: function(argument, local) {
return Selectors.Pseudo['nth-child'].call(this, '2n+1', local);
},
//:odd,匹配索引为奇数的节点
odd: function(argument, local) {
return Selectors.Pseudo['nth-child'].call(this, '2n', local);
}
})