forked from gucong3000/lQuery
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlightquery.js
More file actions
232 lines (212 loc) · 5.76 KB
/
lightquery.js
File metadata and controls
232 lines (212 loc) · 5.76 KB
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*
* Light Query v0.5
* https://github.com/gucong3000/lQuery
*/
(function(){
"use strict";
var queryName = "LQ",
win = window,
doc = win.document,
root = doc.documentElement,
addEventListener = doc.addEventListener,
querySelector = doc.querySelector,
protoProp = "prototype",
randomNames = {},
loopFns = !addEventListener && querySelector ? [] : null,
readyFns = [],
readyFnOld,
dataAttr;
//对象初始化函数
function LightQuery(selector) {
return new LightQuery.fn.init(selector);
}
//将callback在文档就绪时和节点插入时执行
function readyEval(call){
if(doc.body || !readyFns){
//如果document.body可访问,说明文档已经开始渲染,尝试执行一次
//如果队列不存在,表示文档就绪,直接执行
call();
}
if (readyFns) {
//如果文档就绪函数队列存在,表示文档未就绪,call放入队列
readyFns.push(call);
}
if(addEventListener){
//将call注册为节点插入事件响应函数
addEventListener( "DOMNodeInserted", call );
}
}
//执行文档就绪队列中的函数
function completed(){
if (readyFns) {
readyFns.forEach(function(fn){
fn();
});
readyFns = null;
}
}
//返回文档状态是否就绪
LightQuery.isReady = function(){
return doc.readyState === "complete";
};
//生成一个不重复的变量名
LightQuery.randomName = function(){
var name = (function(){
name = queryName + (+new Date()) + parseInt(Math.random() * 0xfff);
return randomNames[name] ? arguments.callee() : name;
})();
return randomNames[name] = name;
};
//LightQuery.data函数所需的在Node上存储数据所需的属性的名称
dataAttr = LightQuery.randomName();
//在Node上储存数据所用的函数
LightQuery.data = function(node, key, val, udf){
var dataSet = node[dataAttr];
if(!dataSet){
node[dataAttr] = dataSet = {};
}
if(val === udf){
val = dataSet[key];
} else {
dataSet[key] = val;
val = this;
}
return val;
};
//doc.addEventListener缩写
if(addEventListener) {
addEventListener = function(eType, call){
doc.addEventListener( eType, call, false );
};
}
//除IE6、7外,建立DOMContentLoaded响应机制
if(querySelector && !LightQuery.isReady()){
if ( addEventListener ) {
//w3c标准的DOMContentLoaded事件
addEventListener( "DOMContentLoaded", completed );
} else {
//IE模拟DOMContentLoaded事件
var readyFnOld = doc.onreadystatechange;
doc.onreadystatechange = function(){
completed();
if(readyFnOld){
readyFnOld.apply(this, arguments);
}
};
}
}
//IE8下不支持节点插入事件,用setInterval模拟
if(loopFns){
setInterval(function(){
loopFns.forEach(function(loopFnsArry){
if(loopFnsArry && loopFnsArry.hooks){
loopFnsArry.hooks.forEach(function(fn){
fn();
});
}
});
}, 100);
}
//声明LightQuery对象的prototype
LightQuery.fn = {
//初始化
init: function(selector) {
this.hooks = [];
this.selector = selector;
//声明一个css样式表并插入页面当前位置
root.lastChild.appendChild(this.styleNode = doc.createElement("style"));
//IE8下降hooks加入全局定时器
loopFns && loopFns.push(this);
},
//写入css
style: function(rule, css){
if(!css){
css = rule;
rule = this.selector;
}
if(rule && css){
if(this.styleNode.styleSheet){
//担心IE低版遇到表达式中部分不识别导致整体失效,所以将规则拆分后写入
rule.trim().split(/\s?,\s?/).forEach(function(subRule){
this.styleNode.styleSheet.addRule(subRule, css);
}, this);
} else {
//一般浏览器下写入css
this.styleNode.appendChild(doc.createTextNode(rule + "{" + css + "}"));
}
}
return this;
},
//动态元素查找
query: function(rule, callback){
var randomName = LightQuery.randomName(),
index = 0,
stop = 0,
hook;
//去重后带参执行回调,参数为节点对象
function call(node){
//过滤回调过的节点
if(!LightQuery.data(node, randomName) && !stop){
//标记为已回调过了
LightQuery.data(node, randomName, true);
LightQuery.fn.query.hijack.forEach(function(fn){
try {
fn(node);
} catch (ex){}
});
stop = callback.call(node, index++, node) === false;
}
}
if(querySelector){
//其他浏览器下利用document.querySelectorAll查找
readyEval(hook = function(){
Array[protoProp].forEach.call(doc.querySelectorAll(rule), function(node){
call(node);
});
});
} else {
//IE6\7下利用css表达式查找节点
LightQuery[randomName] = call;
this.style(rule, randomName + ":expression((function(n){try{return " + queryName + "." + randomName + "(n)}catch(ex){}})(this))");
hook = randomName;
}
this.hooks.push(hook);
return this;
},
//动态元素遍历,参数可变
each: function(rule, callback){
if(!callback){
callback = rule;
rule = this.selector;
}
return this.query(rule, callback);
},
//停止动态遍历节点
die: function (){
if(this.hooks){
//删除初始化时插入的css样式表
this.styleNode.parentNode.removeChild(this.styleNode);
this.hooks.forEach(function(fn){
if(addEventListener){
//标准浏览器下删除DOMNodeInserted事件
doc.removeEventListener( "DOMNodeInserted", fn, false );
} else {
//IE6\7删除hook函数
delete LightQuery[fn];
}
});
this.hooks = null;
}
}
};
LightQuery.fn.query.hijack = [];
LightQuery.fn.init[protoProp] = LightQuery.fn;
if (typeof define === 'function' && ( define.amd || define.cmd )) {
// AMD. CMD. Register as an anonymous module.
define(function(){
return LightQuery;
});
}
// Browser globals
win[queryName] = LightQuery;
})();