forked from madrobby/zepto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
selector.js
138 lines (130 loc) · 3.67 KB
/
selector.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Zepto.js
// (c) 2010-2015 Thomas Fuchs
// Zepto.js may be freely distributed under the MIT license.
//重写zepto.matches与qsa,加上了对:的支持
;(function($){
var zepto = $.zepto, oldQsa = zepto.qsa, oldMatches = zepto.matches;
function visible(elem){
elem = $(elem);
//无高宽也视为不可见
return !!(elem.width() || elem.height()) && elem.css("display") !== "none";
}
// Implements a subset from:
// http://api.jquery.com/category/selectors/jquery-selector-extensions/
//
// Each filter function receives the current index, all nodes in the
// considered set, and a value if there were parentheses. The value
// of `this` is the node currently being considered. The function returns the
// resulting node(s), null, or undefined.
//
// Complex selectors are not supported:
// li:has(label:contains("foo")) + li:has(label:contains("bar"))
// ul.inner:first > li
var filters = $.expr[':'] = {
visible: function(){
if (visible(this)) {
return this;
}
},
hidden: function(){
if (!visible(this)) {
return this;
}
},
selected: function(){
if (this.selected) {
return this;
}
},
checked: function(){
if (this.checked) {
return this;
}
},
parent: function(){
return this.parentNode;
},
first: function(idx){
if (idx === 0) {
return this
}
},
last: function(idx, nodes){
if (idx === nodes.length - 1) {
return this
}
},
eq: function(idx, _, value){
if (idx === value) {
return this
}
},
contains: function(idx, _, text){
if ($(this).text().indexOf(text) > -1) {
return this
}
},
has: function(idx, _, sel){
if (zepto.qsa(this, sel).length) {
return this
}
}
};
var filterRe = new RegExp('(.*):(\\w+)(?:\\(([^)]+)\\))?$\\s*'),
childRe = /^\s*>/,
classTag = 'Zepto' + (+new Date());
//预处理selector
function process(sel, fn) {
// quote the hash in `a[href^=#]` expression
sel = sel.replace(/=#\]/g, '="#"]');
var filter, arg, match = filterRe.exec(sel);
if (match && match[2] in filters) {
filter = filters[match[2]];//得到filter函数
arg = match[3];//filter函数参数
sel = match[1];//前部select
if (arg) {
var num = Number(arg);
if (isNaN(num)) {
arg = arg.replace(/^["']|["']$/g, '');
} else {
arg = num;
}
}
}
return fn(sel, filter, arg);
}
//重写qsa方法
zepto.qsa = function(node, selector) {
return process(selector, function(sel, filter, arg){
try {
var taggedParent;
if (!sel && filter) {
sel = '*';
} else if (childRe.test(sel)) {
// support "> *" child queries by tagging the parent node with a
// unique class and prepending that classname onto the selector
taggedParent = $(node).addClass(classTag);
sel = '.'+classTag+' '+sel;
}
var nodes = oldQsa(node, sel);
} catch(e) {
console.error('error performing selector: %o', selector);
throw e;
} finally {
if (taggedParent) {
taggedParent.removeClass(classTag);
}
}
return !filter ? nodes :
zepto.uniq($.map(nodes, function(n, i){
return filter.call(n, i, nodes, arg);
}));
});
};
zepto.matches = function(node, selector){
return process(selector, function(sel, filter, arg){
return (!sel || oldMatches(node, sel)) &&
(!filter || filter.call(node, null, arg) === node);
});
};
})(Zepto);