├── test
├── a1.js
├── a2.js
├── a3.js
├── a4.js
├── a5.js
├── core.js
└── index.html
├── README
├── do.min.js
└── do.js
/test/a1.js:
--------------------------------------------------------------------------------
1 | var a1 = 1;
2 |
--------------------------------------------------------------------------------
/test/a2.js:
--------------------------------------------------------------------------------
1 | var a2 = 2;
2 |
--------------------------------------------------------------------------------
/test/a3.js:
--------------------------------------------------------------------------------
1 | var a3 = 3;
2 |
--------------------------------------------------------------------------------
/test/a4.js:
--------------------------------------------------------------------------------
1 | var a4 = 4;
2 |
--------------------------------------------------------------------------------
/test/a5.js:
--------------------------------------------------------------------------------
1 | var a5 = 5;
2 |
--------------------------------------------------------------------------------
/test/core.js:
--------------------------------------------------------------------------------
1 | var core_lib_loaded = 1;
2 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | ________
2 | ___ __ \_____
3 | __ / / / __ \
4 | _ /_/ // /_/ /
5 | /_____/ \____/ v 2.0 pre
6 |
7 | Do是一个很轻量文件加载和依赖关系管理的库。目前do.min.js(4.6k)。可能灵活的组织开发中的JS/CSS模块文件,定制各种加载策略。
8 |
9 | 具体使用方法: http://kejun.github.com/Do/
10 |
11 |
--------------------------------------------------------------------------------
/do.min.js:
--------------------------------------------------------------------------------
1 | /* Do version 2.0 pre
2 | * creator: kejun (listenpro@gmail.com)
3 | * 最新更新:2011-7-12
4 | */(function(a,b){var c={},d={},e={},f={autoLoad:!0,timeout:6e3,coreLib:["http://t.douban.com/js/jquery.min.js"],mods:{}},g=function(){var a=b.getElementsByTagName("script");return a[a.length-1]}(),h=[],i,j=[],k=!1,l={},m={},n=function(a){return a.constructor===Array},o=function(a){var b=f.mods,c;typeof a=="string"?c=b[a]?b[a]:{path:a}:c=a;return c},p=function(d,h,i,j){var k,l,m,n,o=function(){c[d]=1,j&&j(d),j=null,a.clearTimeout(k)};if(!!d){if(c[d]){e[d]=!1,j&&j(d);return}if(e[d]){setTimeout(function(){p(d,h,i,j)},10);return}e[d]=!0,k=a.setTimeout(function(){if(f.timeoutCallback)try{f.timeoutCallback(d)}catch(a){}},f.timeout),m=h||d.toLowerCase().substring(d.lastIndexOf(".")+1),m==="js"?(l=b.createElement("script"),l.setAttribute("type","text/javascript"),l.setAttribute("src",d),l.setAttribute("async",!0)):m==="css"&&(l=b.createElement("link"),l.setAttribute("type","text/css"),l.setAttribute("rel","stylesheet"),l.setAttribute("href",d)),i&&(l.charset=i),m==="css"?(n=new Image,n.onerror=function(){o(),n.onerror=null,n=null},n.src=d):(l.onerror=function(){o(),l.onerror=null},l.onload=l.onreadystatechange=function(){var a;if(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")o(),l.onload=l.onreadystatechange=null}),g.parentNode.insertBefore(l,g)}},q=function(a,b){function k(){--j||(d[e]=1,b())}var c=f.mods,e,g,h,i=0,j;e=a.join(""),j=a.length;if(d[e])b();else for(;g=a[i++];)h=o(g),h.requires?q(h.requires,function(a){return function(){p(a.path,a.type,a.charset,k)}}(h)):p(h.path,h.type,h.charset,k)},r=function(b){var c=!1,d=!0,e=a.document,f=e.documentElement,g=e.addEventListener?"addEventListener":"attachEvent",h=e.addEventListener?"removeEventListener":"detachEvent",i=e.addEventListener?"":"on",j=function(d){if(d.type!="readystatechange"||e.readyState=="complete")(d.type=="load"?a:e)[h](i+d.type,j,!1),!c&&(c=!0)&&b.call(a,d.type||d)},k=function(){try{f.doScroll("left")}catch(a){setTimeout(k,50);return}j("poll")};if(e.readyState=="complete")b.call(a,"lazy");else{if(e.createEventObject&&f.doScroll){try{d=!a.frameElement}catch(l){}d&&k()}e[g](i+"DOMContentLoaded",j,!1),e[g](i+"readystatechange",j,!1),a[g](i+"load",j,!1)}},s=function(){var a=0,b;if(j.length)for(;b=j[a++];)t.apply(this,b)},t=function(){var a=[].slice.call(arguments),b,c;if(f.autoLoad&&!d[f.coreLib.join("")])q(f.coreLib,function(){t.apply(null,a)});else{if(h.length>0&&!d[h.join("")]){q(h,function(){t.apply(null,a)});return}typeof a[a.length-1]=="function"&&(b=a.pop()),c=a.join("");if((a.length===0||d[c])&&b){b();return}q(a,function(){d[c]=1,b&&b()})}};t.add=function(a,b){!a||!b||!b.path||(f.mods[a]=b)},t.delay=function(){var b=[].slice.call(arguments),c=b.shift();a.setTimeout(function(){t.apply(this,b)},c)},t.global=function(){var a=n(arguments[0])?arguments[0]:[].slice.call(arguments);h=h.concat(a)},t.ready=function(){var a=[].slice.call(arguments);if(k)return t.apply(this,a);j.push(a)},t.css=function(a){var c=b.getElementById("do-inline-css");c||(c=b.createElement("style"),c.type="text/css",c.id="do-inline-css",g.parentNode.insertBefore(c,g)),c.styleSheet?c.styleSheet.cssText=c.styleSheet.cssText+a:c.appendChild(b.createTextNode(a))},t.setData=t.setPublicData=function(a,b){var c=m[a];l[a]=b;if(!!c)while(c.length>0)c.pop().call(this,b)},t.getData=t.getPublicData=function(a,b){l[a]?b(l[a]):(m[a]||(m[a]=[]),m[a].push(function(a){b(a)}))},t.setConfig=function(a,b){f[a]=b;return t},t.getConfig=function(a){return f[a]},a.Do=t,r(function(){k=!0,s()}),i=g.getAttribute("data-cfg-autoload"),i&&(f.autoLoad=i.toLowerCase()==="true"?!0:!1),i=g.getAttribute("data-cfg-corelib"),i&&(f.coreLib=i.split(","))})(window,document)
--------------------------------------------------------------------------------
/test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Do 2.0 单元测试
6 |
7 |
8 |
9 |
10 |
11 |
12 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/do.js:
--------------------------------------------------------------------------------
1 | /* Do version 2.0 pre
2 | * creator: kejun (listenpro@gmail.com)
3 | * 最新更新:2011-7-12
4 | */
5 |
6 | (function(win, doc) {
7 |
8 | // 已加载模块
9 | var loaded = {},
10 |
11 | // 已加载列表
12 | loadList = {},
13 |
14 | // 加载中的模块
15 | loadingFiles = {},
16 |
17 | // 内部配置文件
18 | config = {
19 | // 是否自动加载核心库
20 | autoLoad: true,
21 |
22 | // 加载延迟
23 | timeout: 6000,
24 |
25 | // 核心库
26 | coreLib: ['http://t.douban.com/js/jquery.min.js'],
27 |
28 | /* 模块依赖
29 | * {
30 | * moduleName: {
31 | * path: 'URL',
32 | * type:'js|css',
33 | * requires:['moduleName1', 'fileURL']
34 | * }
35 | * }
36 | */
37 | mods: {}
38 | },
39 |
40 | jsSelf = (function() {
41 | var files = doc.getElementsByTagName('script');
42 | return files[files.length - 1];
43 | })(),
44 |
45 | // 全局模块
46 | globalList = [],
47 |
48 | // 外部参数
49 | extConfig,
50 |
51 | // domready回调堆栈
52 | readyList = [],
53 |
54 | // DOM Ready
55 | isReady = false,
56 |
57 | // 模块间的公共数据
58 | publicData = {},
59 |
60 | // 公共数据回调堆栈
61 | publicDataStack = {},
62 |
63 | isArray = function(e) {
64 | return e.constructor === Array;
65 | },
66 |
67 | getMod = function(e) {
68 | var mods = config.mods, mod;
69 | if (typeof e === 'string') {
70 | mod = (mods[e])? mods[e] : { path: e };
71 | } else {
72 | mod = e;
73 | }
74 | return mod;
75 | },
76 |
77 | load = function(url, type, charset, cb) {
78 | var wait, n, t, img,
79 |
80 | done = function() {
81 | loaded[url] = 1;
82 | cb && cb(url);
83 | cb = null;
84 | win.clearTimeout(wait);
85 | };
86 |
87 | if (!url) {
88 | return;
89 | }
90 |
91 | if (loaded[url]) {
92 | loadingFiles[url] = false;
93 | if (cb) {
94 | cb(url);
95 | }
96 | return;
97 | }
98 |
99 | if (loadingFiles[url]) {
100 | setTimeout(function() {
101 | load(url, type, charset, cb);
102 | }, 10);
103 | return;
104 | }
105 |
106 | loadingFiles[url] = true;
107 |
108 | wait = win.setTimeout(function() {
109 | /* 目前延时回调处理,超时后如果有延时回调,执行回调,然后继续等
110 | * 延时回调的意义是log延时长的URI,这个处理不属于加载器本身的功能移到外部
111 | * 没有跳过是为了避免错误。
112 | */
113 | if (config.timeoutCallback) {
114 | try {
115 | config.timeoutCallback(url);
116 | } catch(ex) {}
117 | }
118 | }, config.timeout);
119 |
120 | t = type || url.toLowerCase().split(/\./).pop().replace(/[\?#].*/, '');
121 |
122 | if (t === 'js') {
123 | n = doc.createElement('script');
124 | n.setAttribute('type', 'text/javascript');
125 | n.setAttribute('src', url);
126 | n.setAttribute('async', true);
127 | } else if (t === 'css') {
128 | n = doc.createElement('link');
129 | n.setAttribute('type', 'text/css');
130 | n.setAttribute('rel', 'stylesheet');
131 | n.setAttribute('href', url);
132 | }
133 |
134 | if (charset) {
135 | n.charset = charset;
136 | }
137 |
138 | if (t === 'css') {
139 | img = new Image();
140 | img.onerror = function() {
141 | done();
142 | img.onerror = null;
143 | img = null;
144 | }
145 | img.src = url;
146 | } else {
147 | // firefox, safari, chrome, ie9下加载失败触发
148 | // 如果文件是404, 会比timeout早触发onerror。目前不处理404,只处理超时
149 | n.onerror = function() {
150 | done();
151 | n.onerror = null;
152 | };
153 |
154 | // ie6~8通过创建vbscript可以识别是否加载成功。
155 | // 但这样需先测试性加载再加载影响性能。即使没成功加载而触发cb,顶多报错,没必要杜绝这种报错
156 |
157 | // ie6~9下加载成功或失败,firefox, safari, opera下加载成功触发
158 | n.onload = n.onreadystatechange = function() {
159 | var url;
160 | if (!this.readyState ||
161 | this.readyState === 'loaded' ||
162 | this.readyState === 'complete') {
163 | done();
164 | n.onload = n.onreadystatechange = null;
165 | }
166 | };
167 | }
168 |
169 | jsSelf.parentNode.insertBefore(n, jsSelf);
170 | },
171 |
172 | // 加载依赖论文件(顺序)
173 | loadDeps = function(deps, cb) {
174 | var mods = config.mods,
175 | id, m, mod, i = 0, len;
176 |
177 | id = deps.join('');
178 | len = deps.length;
179 |
180 | if (loadList[id]) {
181 | cb();
182 | return;
183 | }
184 |
185 | function callback() {
186 | if(!--len) {
187 | loadList[id] = 1;
188 | cb();
189 | }
190 | }
191 |
192 | for (; m = deps[i++]; ) {
193 | mod = getMod(m);
194 | if (mod.requires) {
195 | loadDeps(mod.requires, (function(mod){
196 | return function(){
197 | load(mod.path, mod.type, mod.charset, callback);
198 | };
199 | })(mod));
200 | } else {
201 | load(mod.path, mod.type, mod.charset, callback);
202 | }
203 | }
204 | },
205 |
206 | /*!
207 | * contentloaded.js
208 | *
209 | * Author: Diego Perini (diego.perini at gmail.com)
210 | * Summary: cross-browser wrapper for DOMContentLoaded
211 | * Updated: 20101020
212 | * License: MIT
213 | * Version: 1.2
214 | *
215 | * URL:
216 | * http://javascript.nwbox.com/ContentLoaded/
217 | * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
218 | *
219 | */
220 |
221 | // @win window reference
222 | // @fn function reference
223 | contentLoaded = function(fn) {
224 | var done = false, top = true,
225 | doc = win.document,
226 | root = doc.documentElement,
227 | add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
228 | rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
229 | pre = doc.addEventListener ? '' : 'on',
230 |
231 | init = function(e) {
232 | if (e.type == 'readystatechange' && doc.readyState != 'complete') return;
233 | (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
234 | if (!done && (done = true)) fn.call(win, e.type || e);
235 | },
236 |
237 | poll = function() {
238 | try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
239 | init('poll');
240 | };
241 |
242 | if (doc.readyState == 'complete') fn.call(win, 'lazy');
243 | else {
244 | if (doc.createEventObject && root.doScroll) {
245 | try { top = !win.frameElement; } catch(e) { }
246 | if (top) {
247 | poll();
248 | }
249 | }
250 | doc[add](pre + 'DOMContentLoaded', init, false);
251 | doc[add](pre + 'readystatechange', init, false);
252 | win[add](pre + 'load', init, false);
253 | }
254 | },
255 |
256 | fireReadyList = function() {
257 | var i = 0, list;
258 | if (readyList.length) {
259 | for(; list = readyList[i++]; ) {
260 | d.apply(this, list);
261 | }
262 | }
263 | },
264 |
265 | d = function() {
266 | var args = [].slice.call(arguments), fn, id;
267 |
268 | // 加载核心库
269 | if (config.autoLoad &&
270 | !loadList[config.coreLib.join('')]) {
271 | loadDeps(config.coreLib, function(){
272 | d.apply(null, args);
273 | });
274 | return;
275 | }
276 |
277 | // 加载全局库
278 | if (globalList.length > 0 &&
279 | !loadList[globalList.join('')]) {
280 | loadDeps(globalList, function(){
281 | d.apply(null, args);
282 | });
283 | return;
284 | }
285 |
286 | if (typeof args[args.length - 1] === 'function' ) {
287 | fn = args.pop();
288 | }
289 |
290 | id = args.join('');
291 |
292 | if ((args.length === 0 || loadList[id]) && fn) {
293 | fn();
294 | return;
295 | }
296 |
297 | loadDeps(args, function() {
298 | loadList[id] = 1;
299 | fn && fn();
300 | });
301 | };
302 |
303 | d.add = function(sName, oConfig) {
304 | if (!sName || !oConfig || !oConfig.path) {
305 | return;
306 | }
307 | config.mods[sName] = oConfig;
308 | };
309 |
310 | d.delay = function() {
311 | var args = [].slice.call(arguments), delay = args.shift();
312 | win.setTimeout(function() {
313 | d.apply(this, args);
314 | }, delay);
315 | };
316 |
317 | d.global = function() {
318 | var args = isArray(arguments[0])? arguments[0] : [].slice.call(arguments);
319 | globalList = globalList.concat(args);
320 | };
321 |
322 | d.ready = function() {
323 | var args = [].slice.call(arguments);
324 | if (isReady) {
325 | return d.apply(this, args);
326 | }
327 | readyList.push(args);
328 | };
329 |
330 | d.css = function(s) {
331 | var css = doc.getElementById('do-inline-css');
332 | if (!css) {
333 | css = doc.createElement('style');
334 | css.type = 'text/css';
335 | css.id = 'do-inline-css';
336 | jsSelf.parentNode.insertBefore(css, jsSelf);
337 | }
338 |
339 | if (css.styleSheet) {
340 | css.styleSheet.cssText = css.styleSheet.cssText + s;
341 | } else {
342 | css.appendChild(doc.createTextNode(s));
343 | }
344 | };
345 |
346 | d.setData = d.setPublicData = function(prop, value) {
347 | var cbStack = publicDataStack[prop];
348 |
349 | publicData[prop] = value;
350 |
351 | if (!cbStack) {
352 | return;
353 | }
354 |
355 | while (cbStack.length > 0) {
356 | (cbStack.pop()).call(this, value);
357 | }
358 | };
359 |
360 | d.getData = d.getPublicData = function(prop, cb) {
361 | if (publicData[prop]) {
362 | cb(publicData[prop]);
363 | return;
364 | }
365 |
366 | if (!publicDataStack[prop]) {
367 | publicDataStack[prop] = [];
368 | }
369 |
370 | publicDataStack[prop].push(function(value){
371 | cb(value);
372 | });
373 | };
374 |
375 | d.setConfig = function(n, v) {
376 | config[n] = v;
377 | return d;
378 | };
379 |
380 | d.getConfig = function(n) {
381 | return config[n];
382 | };
383 |
384 | win.Do = d;
385 |
386 | contentLoaded(function() {
387 | isReady = true;
388 | fireReadyList();
389 | });
390 |
391 | // 初始外部配置
392 | extConfig = jsSelf.getAttribute('data-cfg-autoload');
393 | if (extConfig) {
394 | config.autoLoad = (extConfig.toLowerCase() === 'true') ? true : false;
395 | }
396 |
397 | extConfig = jsSelf.getAttribute('data-cfg-corelib');
398 | if (extConfig) {
399 | config.coreLib = extConfig.split(',');
400 | }
401 |
402 | })(window, document);
403 |
--------------------------------------------------------------------------------