SOURCE

/*
 * compose.js
 * 异步加载框架
 * */
(function (window){
    'use strict'
    /**
     * 属性覆盖
     */
    function extend(orig, target, deep){
        var toStr = Object.prototype.toString,
            arrayFlag = "[object Array]";
        orig = orig || {};
        for (var i in target) {
            if(deep === true && target.hasOwnProperty(i)) {
                if (typeof target[i] === "object") {
                    if(!orig[i]){
                        orig[i] = toStr.call(target[i]) === arrayFlag ? [] : {};
                    }
                    extend(orig[i], target[i]);
                }
                else {
                    orig[i] = target[i];
                }
            }
            else orig[i] = target[i];
        }
        return orig;
    }
    /**
     * 添加script事件
     */
    function addOnloadEvent(dom, callback, fail){
        if(dom && typeof dom.onload !== 'undefined'){
            dom.onload = function(){
                this.onload = null;
                this.onerror = null;
                setTimeout(function(){callback();}, 0);
            };
            dom.onerror = function(){
                this.onload = null;
                this.onerror = null;
                setTimeout(function(){callback();}, 0);
            };
        }
        else if(dom){
            dom.onreadystatechange = function(event){
                if(this.readyState =='complete' || this.readyState =='loaded'){
                    this.onreadystatechange = null;
                    setTimeout(function(){callback();}, 0);
                }
            };
        }
    }
    function isArray(object){
        return object && typeof object==='object' &&
            Array == object.constructor;
    }
    function trimUrl(str){
        if(str){
            var ret = str.match(/^\s*(\S*)\s*$/), retS;
            if(ret){
                retS = ret[1].match(/(.*)\?+$/);
                if(retS){
                    return retS[1];
                }
                else return ret[1];
            }
        }
        return str;
    }
    function isNoStorage(){
        var userAgent = window.navigator.userAgent.toLowerCase();
        return !(userAgent.match(/snyifubao|ebuy-snyifubao/) && userAgent.match(/android/));
    }
    var compose = {
        constant:{
          CSS: 'css',
          JS: 'js',
          PARAl: 'paral',
          ASYNC: 'async'
        },
        /**
         * 配置信息
         */
        _config: {
            basePath:"",//基本路径
            contextPath: false,//上下文路径设置,字符串标示绝对路径,true标示从compose中获取
            paths:{},
            storage: isNoStorage()===false?false:true//缓存开关
        },
        /**
         * 需求列表状态相关信息
         */
        _process: [],
        /**
         * satisfyMap记录
         */
        _satisfies: [],
        /**
         * 完成的js文件路径集合
         */
        _completedPaths: {},
        /**
         * 发生onload后获取事件源
         */
        _onLoadEvents: [],
        /**
         * 缓存key值
         */
        _storageKey: 'storage-param-',
        isElement: function(obj) {
            return !!(obj && obj.nodeType === 1);
        },
        isArray: function(obj) {
            return toString.call(obj) === '[object Array]';
        },
        isObject: function(obj) {
            var type = typeof obj;
            return type === 'function' || type === 'object' && !!obj;
        },
        cacheStorage:{},
        /**
         * 延迟执行
         */
        _delayer: {
            time: 0,
            used: false,
            push: function(callback, time){
                var self = this;
                this.used = true;
                this._callback = function(){
                    if(callback){
                        callback();
                    }
                    self._timer = null;
                    self._callback = null;
                };
                this.time = time || 0;
                this._timer = setTimeout(this._callback, this.time);
            },
            delay: function(time){
                if(this._timer){
                    clearTimeout(this._timer);
                }
                if(this._callback){
                    if(time !== undefined) this._timer = time;
                    this._timer = setTimeout(this._callback, this.time);
                }
            }
        },
        /**
         * 初始化
         */
        init: function () {
            this.initConfig();
            this.initLoad();
            this.initAndClearStorage();
        },
        /**
         * 添加script属性配置
         */
        initConfig: function(){
            var _config = this._config,
                scripts = document.getElementsByTagName('script'),
                l = scripts.length, script, contextPath, basePath, param, main;
            for(var i=0; i<l; i++){
                script = scripts[i];
                contextPath = script.getAttribute('data-contextpath') || '';
                basePath = script.getAttribute('data-basepath') || '';
                param = script.getAttribute('data-param') || '';
                main = script.getAttribute('data-main') || '';
                if(contextPath || basePath || main || param){
                    _config.contextPath = contextPath;
                    _config.basePath = basePath;
                    _config.param = param;
                    _config.main = main;
                    break;
                }
            }
        },
        /*
         *加载main入口文件
         * */
        initLoad: function(){
            var main = this._config.main;
            if(main){
                var main = main.split(',');
                this.require(main);
            }
        },
        /**
         * 添加javascript配置
         */
        config: function(opt){
            var _config = this._config;
            extend(_config, opt, true);
            _config.contextPath = _config.contextPath || "";
            _config.basePath = _config.basePath || "";
            _config.param = _config.param || "";
            if(opt.storage && isNoStorage() === false){
                _config.storage = false;
            }
        },
        /**
         * 获取项目路径
         */
        getContext: function(opt){
            return this._config.contextPath;
        },
        /**
         * 需求

         * param depend 判断此模块是否有依赖并需要提前获取该资源
         */
        require: function(pathId, requires, success, fail, existObjectNames){
            this.req(pathId, requires, success, fail, existObjectNames);
        },
        /**
         * 异步请求资源
         */
        async: function(pathId, requires, success, fail, existObjectNames){
            this.req(pathId, requires, success, fail, existObjectNames, {method:this.constant.ASYNC});
        },
        /**
         * 并发请求资源,建议加载css资源等
         */
        paral: function(pathId, requires, success, fail, existObjectNames){
            this.req(pathId, requires, success, fail, existObjectNames, {method: this.constant.PARAl});
        },

        /**
         * 需求处理函数
         *
         */
        req: function(pathId, requires, callback, fail, existObjectNames, opts){
            this._delayer.delay();
            if(isArray(pathId) || typeof pathId  === 'function'){
                existObjectNames = fail;
                fail = callback;
                callback = requires;
                requires = pathId;
                pathId = null;
            }
            if(typeof requires  === 'function'){
                existObjectNames = fail;
                fail = callback;
                callback = requires;
                requires = [];
            }
            if(!callback || typeof callback === 'string'){
                callback = function(){}
            }
            if(typeof fail  !== 'function'){
                existObjectNames = fail;
                fail = function(){};
            }
            if(existObjectNames === true){
                existObjectNames = null;
            }
            requires._opts = opts = opts || {};
            requires._existObjectNames = existObjectNames || [];
            if(pathId && !pathId.match(/\.css|\.js/)){
                pathId += '.js';
            }
            requires.pathId = pathId;
            requires.callback = callback;
            requires.contextPath = this._config.contextPath;
            requires.param = this._config.param;
            requires.basePath = this._config.basePath;
            requires.fail = fail;
            requires.method = opts.method;
            var handlingRequire = this._handlingRequire,
                requireHandles;
            this.addCache(requires);
            if(opts.method === this.constant.PARAl){
                requireHandles = this.preHandleRequires(requires);
                return this.handleRequire(requireHandles[0]);
            }
            else if(handlingRequire){
                if(!handlingRequire.completed){
                    if(opts.method !== this.constant.ASYNC && handlingRequire.waiting){
                        requires.parent = handlingRequire;
                    }
                    else{
                        requireHandles = this.preHandleRequires(requires);
                        return requireHandles;
                    }
                }
            }
            requireHandles = this.preHandleRequires(requires);
            if(this.handling){
                return;
            }
            var self = this;
            this.handling = true;
            setTimeout(function () {
                self.handling = false;
                self._handlingRequire = requireHandles[0];
                self.handleRequire(requireHandles[0]);
            });
        },
        /**
         * 满足
         */
        satisfy: function(require){
            if(require){
                if(require.method != this.constant.PARAl){
                    var loadRequire = this._onLoadEvents.shift(),
                        handlingRequire = this._handlingRequire;
                    if(loadRequire !== handlingRequire && (loadRequire && loadRequire._process.length)){
                        return;
                    }
                }
                else{
                    var nextRequire = this.getNextRequire(require);
                    //如果第一个是CSScss,下一个是js则返回
                    if(nextRequire.type == this.constant.css && nextRequire && nextRequire.type == this.constant.JS){
                        return;
                    }
                }
                if(require.type == this.constant.CSS){
                    require.completed = true;
                }
                else{
                    if(!require.resourceObject){
                        this.checkAndSetObjectByName(require);
                    }
                }
                if(require.method == this.constant.PARAl){
                    this.checkComplete(require);
                }
                else{
                    this.excCompleteAndExcNext(require);
                }
            }
        },
        /**
         * 满足
         */
        unsatisfy: function(require){
            if(require.method != this.constant.PARAl) {
                this._onLoadEvents.shift();
            }
            var requires = this.getRequires(require);
            if(requires.fail){
                requires.fail();
                requires.failed = true;
                delete require.fail;
            }
            if(this._handlingRequire === require){
                this._handlingRequire = null;
            }
            if(require.element){
                require.element.remove();
            }
            this.deleteRequires(require);
        },
        /**
         * 预处理
         */
        preHandleRequires: function(requires){
            var l = requires.length,
                callback = requires.callback,
                pathId = requires.pathId,
                existObjectNames = requires._existObjectNames,
                _process = requires.parent? requires.parent._process: this._process,
                _satisfies = requires.parent? requires.parent._satisfies: this._satisfies,
                i = _process.length,
                tailFileExp = /\.css|\.js/,
                path,
                _requires = [],
                count = 0,
                type,
                _satisfy,
                require,
                resourceObject,
                configPath;
            for(var i=0; i<_process.length; i++){
                count += _process[i].length;
            }
            for(var j=0; j<=requires.length; j++){
                path = requires[j] ;
                configPath = this._config.paths[path];
                type = (configPath||path)&&(configPath||path).match(/\.css$/) ? this.constant.CSS:this.constant.JS;
                _satisfy = _satisfies[count+j];
                resourceObject = _satisfy && _satisfy.value;
                require = {
                    type: type,
                    completed: _satisfy?true:false,
                    j: j,
                    i: i,
                    parent: requires.parent,
                    resourceObject: resourceObject,
                    resourceObjectPath: existObjectNames[j],
                    _process:[],
                    _satisfies:[],
                    method: type == this.constant.CSS ? this.constant.PARAl : requires.method
                };
                if(path){
                    if(path && path.match(/^http[s]?:\/\//)){
                        if(type == this.constant.JS && !path.match(tailFileExp)){
                            require.path = path+'.js';
                        }
                        else{
                            require.path = path;
                        }
                    }
                    else if(configPath){
                        require.path = configPath&&configPath.match(tailFileExp)?configPath : configPath+'.js';
                        if(!require.resourceObjectPath){
                            require.resourceObjectPath = path;
                        }
                    }
                    else{
                        this.handleRequirePath(require, path, requires);
                    }
                }
                if(j == requires.length){
                    require.callback = callback;
                    if(pathId){
                        this.handleRequirePath(require, pathId, requires);
                    }
                }
                if(_satisfy){
                    this._completedPaths[require.path] = require;
                }
                _requires.push(require);
            }
            if(pathId){
                this.handleRequirePath(_requires, pathId, requires);
            }
            if(requires.fail){
                _requires.fail = requires.fail;
            }
            _process.push(_requires);
            return _requires;
        },
        /**
         * 处理require path
         */
        handleRequirePath: function(require, pathId, requires){
            var basePath = requires.basePath,
                contextPath = requires.contextPath,
                param = requires.param;
            require.path = this.handlePath(pathId, contextPath, basePath, param);
            if(!pathId.match(/\.js$|\.css$/) && pathId.match(/\./)){
                require.resourceObjectPath = pathId;
            }
        },
        /**
         * 处理普通的path
         */
        handlePath: function(pathId, contextPath, basePath, param){
            var path,
                tailFileExp = /\.css|\.js/;
            pathId = trimUrl(pathId);
            if(pathId.match(/\.css$/)){
                path = contextPath ? contextPath + '/' + pathId : pathId;
            }
            else{
                var tpath = contextPath ? contextPath + '/' + basePath : basePath;
                path = (tpath ? tpath + '/' : '') + (pathId.match(tailFileExp)?pathId : pathId+'.js');
            }
            if(param){
                path += pathId.match(/\.js\?/) ? pathId.match(/\?$/) ? param : '&' + param : '?'+ param;
            }
            path = path.replace(/\/+/g, '/').replace(/:\/+/, '://');
            return path;
        },
        /**
         * 处理单个require
         */
        handleRequire: function(require){
            //对处理过的需求直接返回
            if(!require || !require.parent && require.completed){
                return;
            }
            var paral = require.method == this.constant.PARAl;
            if(!paral){
                this._handlingRequire = require;
                this.checkAndSetObjectByName(require);
            }
            if(!require.completed && require.callback && !paral){
                this.checkComplete(require);
            }
            else if( !paral && (!require.path || require.resourceObject || (require.completed == true && require.type === this.constant.CSS))){
                this.excCompleteAndExcNext(require);
            }
            else{
                if(paral){
                    var requires = this.getRequires(require);
                    for(var i=0; i<requires.length; i++){
                        require = requires[i];
                        this.checkAndSetObjectByName(require);
                        if(require.completed){
                            this.checkComplete(require)
                        }
                        else{
                            if(require.method == this.constant.PARAl){
                                this.addEvent(require);
                            }
                            else{
                                this.handleRequire(require);
                                break;
                            }
                        }
                    }
                }
                else{
                    //require.waiting = false;
                    this.addEvent(require);
                }
            }
        },
        /**
         * 注册回调事件
         */
        addEvent: function(require, elementLoad){
            var path = require.path;
            if(!elementLoad && this._config.storage && path && path.match(/\.css/)){
                var self = this;
                this.getRemote(path, function (data) {
                    require.waiting = false;
                    self.satisfy(require);
                }, function () {
                    self.addEvent(require, true);
                })
                return;
            }
            else if(!elementLoad && this._config.storage && path){
                var param;
                var storageObj = this.get(path.replace(/\?.*/, function (value) {
                    param = value;
                    return '';
                }), true);
                if(storageObj){
                    if(require.method != this.constant.PARAl) {
                        require.waiting = true;
                    }
                    var callback = storageObj.callback.replace(/^function\s*[\w\d_]*\(/, 'function anonymous(');
                    this.require(
                        storageObj.pathId,
                        storageObj.requires?storageObj.requires.split(','):[],
                        new Function(callback + ';return anonymous.apply(null, Array.prototype.slice.apply(arguments)) \n //# sourceURL=' + storageObj.pathId)
                    );
                    return;
                }
            }

            if(this._onLoadEvents.some(function (item) {
                if(item.path == require.path){
                    return true;
                }
            })){
                return;
            }
            var element = this.createElement(require.type, path),
                self = this;
            if(!element){
                return;
            }

            addOnloadEvent(element, function(){
                require.waiting = false;
                self.satisfy(require);
            }, function(){
                require.waiting = false;
                self.unsatisfy(require);
            });
            require.element = element;

            var head = document.head || document.getElementsByTagName('head')[0];
            if(require.method != this.constant.PARAl) {
                this._onLoadEvents.push(require);
                setTimeout(function(){
                    head.appendChild(element);
                    require.waiting = true;
                }, 0);
            }
            else{
                head.appendChild(element);
            }

        },
        /**
         * 完成当前complete并执行下一个需求
         */
        createElement: function(type, path){
            if(!path)return;
            var element, config = this._config;
            if(type === this.constant.CSS){
                element = document.createElement("link");
                element.setAttribute('type', 'text/css');
                element.setAttribute('rel', 'stylesheet');
                element.setAttribute('href', path);
            }
            else{
                element = document.createElement("script");
                element.setAttribute('type', 'text/javascript');
                element.setAttribute('src', path);
                element.setAttribute('data-basepath', config.basePath);
            }
            element.setAttribute('data-contextpath', config.contextPath);
            return element;
        },
        /**
         * 完成当前complete并执行下一个需求
         */
        excCompleteAndExcNext: function(require){
            require.completed = true;
            var nextRequire = this.excCompleteAnGetNext(require);
            this.handleRequire(nextRequire);
        },
        /**
         * 获取下一个需求并判断当前是否需要执行回调
         */
        excCompleteAnGetNext: function(require){
            this.checkComplete(require);
            return this.getNextRequire(require);
        },
        /**
         * 获取下一个需求
         */
        getNextRequire: function(require){
            if(!require)return;
            if(require._process && require._process.length){
                var _process = require._process, l = _process.length;
                for(var i=0; i<l; i++){
                    if(!_process[i]._called){
                        return _process[i][0];
                    }
                }
            }
            var i = require.i,
                j = require.j,
                _process = require.parent && require.parent._process?require.parent._process:this._process,
                requires = _process[require.i];
            if(!requires){
                return require;
            }
            else if(j == requires.length - 1 || (j==0 && requires.length == 0)){
                i += 1;
                j = 0;
                requires = _process[i];
                if(!requires){
                    if(require.parent){
                        this.checkComplete(require.parent);
                        return this.getNextRequire(require.parent);
                    }
                }
            }
            else{
                j += 1;
            }
            var nextRequire = _process[i] && _process[i][j];
            return nextRequire;
        },
        /**
         * 是否需要执行回调
         */
        checkComplete: function(require){
            if(!require)return;
            this._handling = true;
            var j = require.j,
                requires = this.getRequires(require),
                resources = [];
            if(require.method == this.constant.PARAl){
                var object;
                for(var i=0; i<requires.length; i++){
                    require = requires[i];
                    if(!require || !require.completed){
                        break;
                    }
                    else{
                        object = require.resourceObject;
                        if(!object){
                            object = this.checkAndSetObjectByName(requires[i]);
                        }
                        resources.push(object);
                    }
                }
                if(i == requires.length -1){
                    require.completed = true;
                    require.callback.apply(window, resources);
                    this.handleRequire(this.getNextRequire(require));
                }
            }
            else if(requires && (requires.length == 0 || j == requires.length - 1)){
                if(require._process && require._process.length){
                    var _process = require._process, l = _process.length;
                    for(var i=0; i<l; i++){
                        if(!_process[i]._called){
                            return;
                        }
                    }
                }
                if(!requires._called){
                    //先把状态置为true,防止重复
                    this.execCallback(require);
                    if(require !== this._handlingRequire){
                        return;
                    }
                    if(require.parent){
                        this.excCompleteAndExcNext(require.parent);
                    }
                    else{
                        this.handleRequire(this.getNextRequire(require));
                    }
                }
            }
        },
        execCallback: function (require) {
            var requires = this.getRequires(require),
                l = requires.length,
                object,
                resources=[];
            for(var i=0; i<l-1; i++){
                object = requires[i].resourceObject;
                if(!object){
                    object = this.checkAndSetObjectByName(requires[i]);
                }
                resources.push(object);
            }
            require.callbacking = true;
            var ret = require.callback.apply(window, resources);
            require.callbacking = false;
            require.resourceObject = ret;
            require.completed = true;
            if(requires.path){
                this._completedPaths[require.path] = require;
            }
            if(require.parent){
                require.parent.resourceObject = ret;
                require.parent.completed = true;

                (requires || require.parent._process[0])._called = true;
            }
            else{
                this._process[require.i]._called = true;
            }
            return ret;
        },
        /**
         * 获取requires
         */
        getRequires: function (require) {
            var i = require.i,
                j = require.j,
                _process = require.parent && require.parent._process ? require.parent._process : this._process,
                requires = _process[require.i];
            return requires;
        },
        /**
         * 删除requires
         */
        deleteRequires: function (require) {
            var i = require.i,
                j = require.j,
                parent = require.parent && require.parent._process ? require.parent : this,
                _process = parent._process,
                requires = _process[require.i];
            if(requires){
                parent._process =  _process.slice(0, i).concat( _process.slice(i+1));
            }
        },
        /**
         * 判断当前对象是否存在,如存在,则不加载对应组的js文件
         */
        checkAndSetObjectByName: function(require){
            var origRequire = this._completedPaths[require.path],
                resourceObjectPath = require.resourceObjectPath,
                resourceObject;
            if(require.type == this.constant.CSS){
                if(origRequire){
                    require.completed = true;
                    require.resourceObject = true;
                    return true;
                }
                else if(require.completed){
                    this._completedPaths[require.path] = true;
                    return require.resourceObject = true;
                }
                return;
            }
            if(require.resourceObject){return require.resourceObject}
            if(origRequire){
                resourceObject = origRequire.resourceObject;
                if(resourceObject){
                    require.resourceObject = resourceObject;
                    require.completed = true;
                    return resourceObject;
                }
            }
            else if(!origRequire && require.path){
                this._completedPaths[require.path] = require;
                /*if(require.callback){
                    this.execCallback(require);
                }*/
            }

            if(!resourceObjectPath){
                return;
            }
            if(require && require.callback){
                return;
            }
            var names = resourceObjectPath.split('.'),
                namesLength = names.length,
                name,
                obj = window;
            for(var j=0; j<namesLength; j++){
                name = names[j];
                if(!(j==0 && name == 'window')){
                    obj = obj && obj[name];
                }
            }
            if(!obj){
                return;
            }
            require.resourceObject = obj;
            require.completed = true;
            if(!this._completedPaths[require.path]){
                this._completedPaths[require.path] = require;
            }
            return obj;
        },
        /*
         * 使用storage存数据
         * */
        put: function (key, value, noStorageKey){
            if(!this._config.storage){
                return;
            }
            if(value && this.isObject(value) &&!(this.isFunction(value)
                ||this.isArray(value)
                ||this.isString(value)
                ||this.isNumber(value))){
                value = JSON.stringify(value);
            }
            var key = noStorageKey?key : (this._storageKey||'') + key,
                localStorage = window.localStorage;
            try{
                if(localStorage){
                    localStorage.setItem(key, value);
                }
            }catch(e){
            }
        },
        /*
         * 使用storage取数据,如果失败从this.sessionStorage取
         * */
        get: function (key){
            var value = '', localStorage = window.localStorage;
            if(localStorage && !this._config.storage){
                return value;
            }
            try{
                var key = (this._storageKey||'') + key;
                if(localStorage){
                    value = localStorage.getItem(key);
                }
            }catch(e){
            }
            if(value && /^\{[\s\S]*\}$/.test(value)){
                value = JSON.parse(value);
            }
            if(value === 'undefined' || value === 'null'){
                value = '';
            }
            return value;
        },
        addCache: function (requires) {
            var pathId = requires.pathId;
            if(pathId){
                pathId = this.handlePath(pathId, requires.contextPath, requires.basePath);
                if(this._config.storage && pathId && !this.get(pathId)){
                    this.put(pathId, {
                        pathId: pathId,
                        requires: requires.toString(),
                        callback: requires.callback.toString()
                    });
                }
            }
        },
        /*
         * 初始化storage版本设置和清空历史数据
         * */
        initAndClearStorage: function (){
            var localStorage = window.localStorage;
            if(localStorage && this._config.storage){
                try{
                    var param = this._config.param,
                        _storageKey = this._storageKey,
                        lastParam = localStorage.getItem(_storageKey),
                        length = localStorage.length;
                    localStorage.setItem(_storageKey, param||'');
                    if(lastParam && lastParam != param){
                        var matchReg = new RegExp('^'+_storageKey+'.+'),
                            key;
                        while(length--){
                            key = localStorage.key(length);
                            if(key.match(matchReg)){
                                localStorage.removeItem(key);
                            }
                        }
                    }
                }catch(e){
                }
            }
        },
        ajax: function(options){
            var xmlhttp = null;
            if (window.XMLHttpRequest){
                xmlhttp=new XMLHttpRequest();
            }
            else if (window.ActiveXObject){
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            if (xmlhttp!=null){
                xmlhttp.onreadystatechange = function ()
                {
                    if (xmlhttp.readyState==4)
                    {
                        if (xmlhttp.status==200)
                        {
                            if(options.success){
                                options.success(xmlhttp.responseText, xmlhttp);
                            }
                        }
                        else
                        {
                            if(options.failed){
                                options.failed(xmlhttp);
                            }
                        }
                    }
                };
                xmlhttp.open("GET", options.url||'', true);
                xmlhttp.send(null);
            }
        },
        handleCss: function (data, url){
            var path = '',
                httpPreReg = /^https?:\/\//,
                handledData,
                tailReg = /[^\/]*$/,
                filePathReg = /[\:]/;

            if(url.match(httpPreReg)){
                path = url.replace(tailReg, '');
            }
            else{
                path = (location.origin+location.pathname).replace(tailReg, '')
                    + url.replace(tailReg, '');
            }
            handledData = data.replace(/url\s*\(([^\s;\(\)]*)\)\s*/g, function (value, url){
                if(url){
                    if(url.match(httpPreReg) || url.match(filePathReg)){
                        return value;
                    }
                    else{
                        var split = url.match(/^\s*(['"])?([^'"]*)/);
                        split[1] = split[1]||'';
                        return 'url('+split[1]+path+split[2]+split[1]+')';                            }
                }
                else{
                    return value;
                }
            });
            return handledData;
        },
        getRemote: function (url, success, fail) {
            var self = this,
                pathId = url.replace(/\?.*/,''),
                storageData = self.get(pathId);
            if(storageData){
                append(storageData);
            }
            else{
                this.ajax({
                    url: url,
                    success: function (data, xmlhttp) {
                        if(pathId){
                            self.put(pathId, data);
                        }
                        append(data);
                    },
                    failed: function (xmlhttp) {
                        fail && fail.call(this, xmlhttp);
                    }
                });
            }
            function append(data){
                var el = document.createElement('style');
                el.setAttribute('type', 'text/css');
                el.innerHTML = self.handleCss(data, url);
                document.head.appendChild(el);
                success && success(data);
            }
        }

    };
    // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
    ['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'].forEach(function(name) {
        compose['is' + name] = function(obj) {
            return toString.call(obj) === '[object ' + name + ']';
        };
    });
    window.compose = compose;
    compose.init();
})(window);
console 命令行工具 X clear

                    
>
console