You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
430 lines
12 KiB
JavaScript
430 lines
12 KiB
JavaScript
5 years ago
|
/*
|
||
|
Version: 1.0
|
||
|
|
||
|
Modified by: AaronJan (aaronjan@qq.com)
|
||
|
note: add support for pack.
|
||
|
|
||
|
|
||
|
********** In **********
|
||
|
Project Home: http://injs.org
|
||
|
|
||
|
Author: Guokai
|
||
|
Gtalk: badkaikai@gmail.com
|
||
|
Blog: http://benben.cc
|
||
|
Licence: MIT License
|
||
|
Version: 0.2.1-stable
|
||
|
|
||
|
Philosophy: Just in time.
|
||
|
Build: 110428120728
|
||
|
*/
|
||
|
|
||
|
(function() {
|
||
|
var __head = document.head || document.getElementsByTagName('head')[0];
|
||
|
var __waterfall = {};
|
||
|
var __loaded = {};
|
||
|
var __loading = {};
|
||
|
var __globals = [];
|
||
|
var __configure = {autoload: false, core: '', serial: false};
|
||
|
var __in;
|
||
|
|
||
|
// mapping for `In.load`
|
||
|
// This method used for loading javascript or
|
||
|
// style files asynchronous and non-blocking.
|
||
|
|
||
|
var __load = function(url, type, charset, callback) {
|
||
|
if(__loading[url]) {
|
||
|
if(callback) {
|
||
|
setTimeout(function() {
|
||
|
__load(url, type, charset, callback);
|
||
|
}, 1);
|
||
|
return;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(__loaded[url]) {
|
||
|
if(callback) {
|
||
|
callback();
|
||
|
return;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
__loading[url] = true;
|
||
|
|
||
|
var pureurl = url.split('?')[0];
|
||
|
var n, t = type || pureurl.toLowerCase().substring(pureurl.lastIndexOf('.') + 1);
|
||
|
|
||
|
if(t === 'js') {
|
||
|
n = document.createElement('script');
|
||
|
n.type = 'text/javascript';
|
||
|
n.src = url;
|
||
|
n.async = 'true';
|
||
|
if(charset) {
|
||
|
n.charset = charset;
|
||
|
}
|
||
|
} else if(t === 'css') {
|
||
|
n = document.createElement('link');
|
||
|
n.type = 'text/css';
|
||
|
n.rel = 'stylesheet';
|
||
|
n.href = url;
|
||
|
__loaded[url] = true;
|
||
|
__loading[url] = false;
|
||
|
__head.appendChild(n);
|
||
|
if(callback) callback();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
n.onload = n.onreadystatechange = function() {
|
||
|
if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
|
||
|
__loading[url] = false;
|
||
|
__loaded[url] = true;
|
||
|
|
||
|
if(callback) {
|
||
|
callback();
|
||
|
}
|
||
|
|
||
|
n.onload = n.onreadystatechange = null;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
n.onerror = function() {
|
||
|
__loading[url] = false;
|
||
|
|
||
|
if(callback) {
|
||
|
callback();
|
||
|
}
|
||
|
|
||
|
n.onerror = null;
|
||
|
}
|
||
|
|
||
|
__head.appendChild(n);
|
||
|
};
|
||
|
|
||
|
// private method, analyze the dependency.
|
||
|
// This is the core function for dependency management.
|
||
|
|
||
|
var __analyze = function(array) {
|
||
|
var riverflow = [];
|
||
|
|
||
|
for(var i = array.length-1; i >= 0; i--) {
|
||
|
var current = array[i];
|
||
|
|
||
|
if(typeof(current) === 'string') {
|
||
|
if(!__waterfall[current]) {
|
||
|
console && console.warn && console.warn('In Error :: Module not found: ' + current);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
riverflow.push(current);
|
||
|
var relylist = __waterfall[current].rely;
|
||
|
|
||
|
if(relylist) {
|
||
|
riverflow = riverflow.concat(__analyze(relylist));
|
||
|
}
|
||
|
} else if(typeof(current) === 'function') {
|
||
|
riverflow.push(current);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return riverflow;
|
||
|
};
|
||
|
|
||
|
// private method, serial process.
|
||
|
// This method used for loading modules in serial.
|
||
|
|
||
|
var __stackline = function(blahlist) {
|
||
|
var o = this;
|
||
|
|
||
|
this.stackline = blahlist;
|
||
|
this.current = this.stackline[0];
|
||
|
this.bag = {returns: [], complete: false};
|
||
|
|
||
|
this.start = function() {
|
||
|
if(typeof(o.current) != 'function' && __waterfall[o.current]) {
|
||
|
__load(__waterfall[o.current].path, __waterfall[o.current].type, __waterfall[o.current].charset, o.next);
|
||
|
} else {
|
||
|
o.bag.returns.push(o.current());
|
||
|
o.next();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
this.next = function() {
|
||
|
if(o.stackline.length == 1 || o.stackline.length < 1) {
|
||
|
o.bag.complete = true;
|
||
|
if(o.bag.oncomplete) {
|
||
|
o.bag.oncomplete(o.bag.returns);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
o.stackline.shift();
|
||
|
o.current = o.stackline[0];
|
||
|
o.start();
|
||
|
};
|
||
|
};
|
||
|
|
||
|
// private method, parallel process.
|
||
|
// This method used for loading modules in parallel.
|
||
|
|
||
|
var __parallel = function(blahlist, callback) {
|
||
|
var length = blahlist.length;
|
||
|
var hook = function() {
|
||
|
if(!--length && callback) callback();
|
||
|
};
|
||
|
|
||
|
if(length == 0) {
|
||
|
callback && callback();
|
||
|
return;
|
||
|
};
|
||
|
|
||
|
for(var i = 0; i < blahlist.length; i++) {
|
||
|
var current = __waterfall[blahlist[i]];
|
||
|
|
||
|
if(typeof(blahlist[i]) == 'function') {
|
||
|
blahlist[i]();
|
||
|
hook();
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if(typeof(current) === 'undefined') {
|
||
|
console && console.warn && console.warn('In Error :: Module not found: ' + blahlist[i]);
|
||
|
hook();
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if(current.rely && current.rely.length != 0) {
|
||
|
__parallel(current.rely, (function(current) {
|
||
|
return function() {
|
||
|
__load(current.path, current.type, current.charset, hook);
|
||
|
};
|
||
|
})(current));
|
||
|
} else {
|
||
|
__load(current.path, current.type, current.charset, hook);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// mapping for `In.add`
|
||
|
// This method used for adding module.
|
||
|
|
||
|
var __add = function(name, config) {
|
||
|
if(!name || !config || !config.path) return;
|
||
|
__waterfall[name] = config;
|
||
|
};
|
||
|
|
||
|
// mapping for `In.adds`
|
||
|
// This method used for adding modules.
|
||
|
|
||
|
var __adds = function(config) {
|
||
|
if(!config.modules) return;
|
||
|
|
||
|
for(var module in config.modules) {
|
||
|
if(config.modules.hasOwnProperty(module)) {
|
||
|
var module_config = config.modules[module];
|
||
|
|
||
|
if(!config.modules.hasOwnProperty(module)) continue;
|
||
|
if(config.type && !module_config.type) module_config.type = config.type;
|
||
|
if(config.charset && !module_config.charset) module_config.charset = config.charset;
|
||
|
__add.call(this, module, module_config);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// mapping for `In.config`
|
||
|
// This method used for change the default config.
|
||
|
|
||
|
var __config = function(name, conf) {
|
||
|
__configure[name] = conf;
|
||
|
};
|
||
|
|
||
|
// mapping for `In.css`
|
||
|
// This method used for insert inline css to your page dynamically.
|
||
|
|
||
|
var __css = function(csstext) {
|
||
|
var css = document.getElementById('in-inline-css');
|
||
|
|
||
|
if(!css) {
|
||
|
css = document.createElement('style');
|
||
|
css.type = 'text/css';
|
||
|
css.id = 'in-inline-css';
|
||
|
__head.appendChild(css);
|
||
|
}
|
||
|
|
||
|
if(css.styleSheet) {
|
||
|
css.styleSheet.cssText = css.styleSheet.cssText + csstext;
|
||
|
} else {
|
||
|
css.appendChild(document.createTextNode(csstext));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// mapping for `In.later`
|
||
|
// This method used for loading modules delay time specified.
|
||
|
|
||
|
var __later = function() {
|
||
|
var args = [].slice.call(arguments);
|
||
|
var timeout = args.shift();
|
||
|
|
||
|
window.setTimeout(function() {
|
||
|
__in.apply(this, args);
|
||
|
}, timeout);
|
||
|
};
|
||
|
|
||
|
// mapping for `In.ready`
|
||
|
// This method used for loading modules while domready.
|
||
|
|
||
|
var __ready = function() {
|
||
|
var args = arguments;
|
||
|
|
||
|
__contentLoaded(window, function() {
|
||
|
__in.apply(this, args);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
var __global = function() {
|
||
|
var args = arguments[0].constructor === Array ? arguments[0] : [].slice.call(arguments);
|
||
|
|
||
|
__globals = __globals.concat(args);
|
||
|
};
|
||
|
|
||
|
// mapping for `In`
|
||
|
// This is the main function, also mapping for method `use`.
|
||
|
|
||
|
var __in = function() {
|
||
|
var args = [].slice.call(arguments);
|
||
|
|
||
|
if(__globals.length) {
|
||
|
args = __globals.concat(args);
|
||
|
}
|
||
|
|
||
|
if(__configure.serial) {
|
||
|
if(__configure.core && !__loaded[__configure.core]) {
|
||
|
args = ['__core'].concat(args);
|
||
|
}
|
||
|
|
||
|
var blahlist = __analyze(args).reverse();
|
||
|
var stack = new __stackline(blahlist);
|
||
|
|
||
|
stack.start();
|
||
|
return stack.bag;
|
||
|
}
|
||
|
|
||
|
if(typeof(args[args.length-1]) === 'function') {
|
||
|
var callback = args.pop();
|
||
|
}
|
||
|
|
||
|
if(__configure.core && !__loaded[__configure.core]) {
|
||
|
__parallel(['__core'], function() {
|
||
|
__parallel(args, callback);
|
||
|
});
|
||
|
} else {
|
||
|
__parallel(args, callback);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// private method, contentLoaded.
|
||
|
// This method used for domready.
|
||
|
|
||
|
var __contentLoaded = function(win,fn) {
|
||
|
var done = false, top=true,
|
||
|
doc = win.document, root = doc.documentElement,
|
||
|
add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
|
||
|
rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
|
||
|
pre = doc.addEventListener ? '' : 'on',
|
||
|
|
||
|
init = function(e) {
|
||
|
if(e.type == 'readystatechange' && doc.readyState != 'complete') return;
|
||
|
(e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
|
||
|
if(!done && (done=true)) fn.call(win, e.type || e);
|
||
|
},
|
||
|
|
||
|
poll = function() {
|
||
|
try {root.doScroll('left');} catch(e) {setTimeout(poll, 50);return;}
|
||
|
init('poll');
|
||
|
};
|
||
|
|
||
|
if(doc.readyState == 'complete') {
|
||
|
fn.call(win, 'lazy');
|
||
|
} else {
|
||
|
if(doc.createEventObject && root.doScroll) {
|
||
|
try {top =! win.frameElement;} catch(e) {}
|
||
|
if(top) poll();
|
||
|
}
|
||
|
|
||
|
doc[add](pre + 'DOMContentLoaded', init, false);
|
||
|
doc[add](pre + 'readystatechange', init, false);
|
||
|
win[add](pre + 'load', init, false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// private method, initialize.
|
||
|
// This is a self-executing function while in.js loaded.
|
||
|
|
||
|
void function() {
|
||
|
var myself = (function() {
|
||
|
var scripts = document.getElementsByTagName('script');
|
||
|
return scripts[scripts.length - 1];
|
||
|
})();
|
||
|
|
||
|
var autoload = myself.getAttribute('autoload');
|
||
|
var core = myself.getAttribute('core');
|
||
|
|
||
|
if(core) {
|
||
|
__configure['autoload'] = eval(autoload);
|
||
|
__configure['core'] = core;
|
||
|
__add('__core', {path: __configure.core});
|
||
|
}
|
||
|
|
||
|
// autoload the core files
|
||
|
if(__configure.autoload && __configure.core) {
|
||
|
__in();
|
||
|
}
|
||
|
}();
|
||
|
|
||
|
//Manually load
|
||
|
var __setup = function(name, config)
|
||
|
{
|
||
|
if(!name || !config || !config.path) {
|
||
|
return;
|
||
|
}
|
||
|
__waterfall[name] = config;
|
||
|
|
||
|
if(!__loaded[config.path]) {
|
||
|
__loaded[config.path] = true;
|
||
|
}
|
||
|
return ;
|
||
|
};
|
||
|
|
||
|
// Is exists
|
||
|
var __exists = function(name)
|
||
|
{
|
||
|
if(!name) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (typeof(__waterfall[name]) === 'undefined') {
|
||
|
return false;
|
||
|
}else{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
// Bind the private method to in.
|
||
|
|
||
|
__in.add = __add;
|
||
|
__in.adds = __adds;
|
||
|
__in.config = __config;
|
||
|
__in.css = __css;
|
||
|
__in.later = __later;
|
||
|
__in.load = __load;
|
||
|
__in.ready = __ready;
|
||
|
__in.global = __global;
|
||
|
__in.use = __in;
|
||
|
|
||
|
__in.setup = __setup;
|
||
|
__in.exists = __exists;
|
||
|
|
||
|
this.In = __in;
|
||
|
})();
|