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

/*
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;
})();