Source: hui/hui.js

'::hui::';
'use strict';
//   __    __           ______   ______  _____    __  __     
//  /\ \  /\ \ /'\_/`\ /\  _  \ /\__  _\/\  __`\ /\ \/\ \    
//  \ `\`\\/'//\      \\ \ \/\ \\/_/\ \/\ \ \/\ \\ \ \ \ \   
//   `\ `\ /' \ \ \__\ \\ \  __ \  \ \ \ \ \ \ \ \\ \ \ \ \  
//     `\ \ \  \ \ \_/\ \\ \ \/\ \  \ \ \ \ \ \_\ \\ \ \_\ \ 
//       \ \_\  \ \_\\ \_\\ \_\ \_\  \ \_\ \ \_____\\ \_____\
//        \/_/   \/_/ \/_/ \/_/\/_/   \/_/  \/_____/ \/_____/
//                                                                                                                                      
//     

/**
 * @namespace hui
 * @description hui是一个简单易用的前端H5框架
 * @public
 * @author haiyang5210
 * @since 2015-06-25 10:48
 */

// 使用window.hui定义可能会导致速度下降约7倍
window.hui = window.hui ? window.hui : {};

/**
 * @property {Boolean} hui.startDebug 通过检测地址栏中startDebug=true参数确定是否开启调试模式
 */
hui.startDebug = window.location.href.indexOf('startDebug=true') !== -1 ? true : false;
/**
 * @method hui.showLog
 * @static
 * @description 弹出错误提示信息
 * @param {String} msg 错误提示信息
 * @example 
 * hui.showLog("Exception 'open failed: EACCES (Permission denied)'");
 */
hui.showLog = function (msg) {
    if (hui.startDebug) {
        window.alert(msg);
    }
    else {
        window.console.log(msg);
    }
};



if (!hui.define) {
    /** 
     * @method hui.require
     * @description 请求需要的模块(和定义匿名模块类似)<br/>
     * Nodejs support 'require' and does not support 'define', browser does not supported both. 
     * @param {Array} n 依赖的模块
     * @param {Function} cb 模块构造器
     * @param {String} [asyc] 'syc': 立即加载依赖, '': 否 (默认)
     * @example 
     * hui.require(['jquery', 'button'], function () {
     *     console.log('This is anonymous module.');
     * });
     */
    // Nodejs support 'require' and does not support 'define', browser does not supported both. 
    // hui.require(['jquery', 'button'], function(){})
    hui.require = function (n, cb, asyc) {
        if (!n) return;
        if (Object.prototype.toString.call(n) !== '[object Array]') {
            n = [n];
        }
        hui.define('', n, cb, 'force', asyc);
    };
    /** 
     * @method hui.define
     * @description 定义模块,规则同CMD
     * @param {String} name 模块名称
     * @param {Array} deps 依赖的模块
     * @param {Function} fun 模块构造器
     * @param {String} [force] 'force': 强制覆盖, '': 否 (默认)
     * @param {String} [asyc] 'syc': 立即加载依赖, '': 否 (默认)
     * @example 
     * hui.define('hy_mod01', ['ext_md5'], function () {
     *     console.log('This is hy_mod01.');
     * });
     */
    hui.define = function (name, deps, fun, force, asyc) {
        if (force) hui.define.removeModule(name);
        if (!name || !hui.define.getModule(name)) {
            //Name missing. Allow for anonymous modules
            name = typeof name !== 'string' ? '' : String(name).toLowerCase();
            deps = deps && deps.splice && deps.length ? deps : [];
            var left = [];
            for (var i = 0, len = deps.length; i < len; i++) {
                left.push(String(deps[i]).toLowerCase());
            }

            var conf = {
                name: name,
                depend: deps,
                left: left,
                todo: fun,
                loaded: false,
                exports: {},
                asyc: asyc
            };
            hui.define.modules.push(conf);

            hui.define.checkDepend();

            if (asyc === 'syc' || hui.define_autoload !== false) {
                conf.left.length && hui.define.loadmod(conf.left);
            }
        }
    };
    // 注:模块源地址
    hui.define.source = 'http://bpmjs.org/api/combo??';
    // 注:已通过<script>标签发送请求的模块
    hui.define.loadfile = [];
    // 注:请求成功返回但尚未初始化的模块
    hui.define.modules = [];
    // 注:执行初始化后的模块
    hui.define.parsed = [];
    // 注:是否自动加载依赖模块
    hui.define_autoload = hui.define_autoload === undefined ? false : true;

    hui.define.loadmod = function (n, conf) {
        var left = [];
        for (var i = 0; i < n.length; i++) {
            if (!hui.define.checkLoaded(n[i], conf)) {
                left.push(n[i]);
            }
        }
        if (left.length) {
            for (var i = 0, len = left.length; i < len; i++) {
                // 先查找本地模块
                if (window.sourcemap_local && window.sourcemap_local[left[i]]) {
                    hui.define.loadfile.push(left[i]);
                    hui.loadjs((hui.staticDomain || '') + window.sourcemap_local[left[i]]);
                }
                // 再查找非本地的模块
                else if (window.sourcemap_third && window.sourcemap_third[left[i]]) {
                    hui.define.loadfile.push(left[i]);
                    hui.loadjs(window.sourcemap_third[left[i]]);
                }
            }
        }
    };
    hui.define.checkLoaded = function (n, conf) {
        var loaded = !!hui.define.getModule(n, conf);
        if (!loaded) {
            for (var i = 0, len = hui.define.loadfile.length; i < len; i++) {
                if (hui.define.loadfile[i].split('@')[0].replace('./', '') === n) {
                    loaded = true;
                    break;
                }
            }
        }
        return loaded;
    };

    hui.define.checkDepend = function () {
        hui.define.modules = hui.define.modules || [];
        // 注: 只能用倒序, 否则会碰到依赖项未定义的错误
        for (var i = hui.define.modules.length - 1; i > -1; i--) {
            var m = hui.define.modules[i];

            for (var j = 0, len2 = hui.define.parsed.length; j < len2; j++) {
                var n = hui.define.parsed[j];
                for (var k = m.left.length - 1; k > -1; k--) {
                    if (m.left[k].replace('./', '').split('@')[0] == n) {
                        m.left.splice(k, 1);
                    }
                }
            }

            if (!m.loaded && m.left.length < 1) {
                m.loaded = true;
                // 放在前面未执行todo就放到loaded中了,会误触其他函数的todo,只能放在后面
                // [注: push放在这里则后面检测依赖只能用倒序,放在后面不好实现][有误]
                m.todo && m.todo(m.exports);
                // 放在todo前面有问题,依赖项刚加载还没来得及执行就触发了其他依赖此项的todo,会报依赖项未定义的错误
                m.name && hui.define.parsed.push(m.name);

                i = hui.define.modules.length;
            }
        }
    };

    hui.define.getModule = function (n) {
        n = n.split('@')[0].replace('./', '');
        var module = null;
        if (hui.define.modules) {
            for (var i = 0, len = hui.define.modules.length; i < len; i++) {
                if (hui.define.modules[i] && hui.define.modules[i].name === n) {
                    module = hui.define.modules[i];
                    break;
                }
            }
        }
        return module;
    };
    hui.define.removeModule = function (n) {
        n = n.split('@')[0].replace('./', '');
        var result = false;
        if (hui.define.modules) {
            for (var i = 0, len = hui.define.modules.length; i < len; i++) {
                if (hui.define.modules[i] && hui.define.modules[i].name === n) {
                    hui.define.modules.splice(i, 1);
                    result = true;
                    break;
                }
            }
        }
        return result;
    };

    hui.define.checkLeft = function () {
        var left = [];
        var list = hui.define.modules;
        for (var i = 0, len = list.length; i < len; i++) {
            left = left.concat(hui.define.modules[i].left);
        }
        return left;
    };
    hui.define.loadLeft = function () {
        var left = hui.define.checkLeft();
        left && hui.define.loadmod(left);
    };
}

hui.define('hui', [], function () {
    // !!! global.hui = ...
    hui.window = window; /*hui.bocument = document;//注:hui.bocument与document不相同!!*/
    hui.window.cc = [];

    /** 
     * @method hui.fn
     * @description 绑定方法执行时的this指向的对象
     * @param {Function|String} func 要绑定的函数,或者一个在作用域下可用的函数名
     * @param {Object} obj 执行运行时this,如果不传入则运行时this为函数本身
     * @param {} args 函数执行时附加到执行时函数前面的参数
     * @returns {Function} 封装后的函数
     * @example 
     * var a = {name:'Tom',age:16,say: function(){console.log('Tom aged ' + this.age)}};
     * a.say()
     * >> Tom aged 16
     * var b = {name:'Nancy',age:40};
     * b.say = a.say
     * b.say()
     * >> Tom aged 40
     * b.say = hui.fn(a.say, a);
     * b.say()
     * >> Tom aged 16
     */
    hui.fn = function (func, scope) {
        if (Object.prototype.toString.call(func) === '[object String]') {
            func = scope[func];
        }
        if (Object.prototype.toString.call(func) !== '[object Function]') {
            throw 'Error "hui.util.fn()": "func" is null';
        }
        var xargs = arguments.length > 2 ? [].slice.call(arguments, 2) : null;
        return function () {
            var fn = '[object String]' == Object.prototype.toString.call(func) ? scope[func] : func,
                args = (xargs) ? xargs.concat([].slice.call(arguments, 0)) : arguments;
            return fn.apply(scope || fn, args);
        };
    };

    /**
     * @method hui.inherits
     * @description 原型继承
     * @public
     * @param {Class} child 子类
     * @param {Class} parent 父类
     * @example 
     * hui.Form = function (options, pending) {
     *     //如果使用this.constructor.superClass.call将无法继续继承此子类,否则会造成死循环!!
     *     hui.Form.superClass.call(this, options, 'pending');
     *     //进入控件处理主流程!
     *     if (pending != 'pending') {
     *         this.enterControl();
     *     }
     * };
     * hui.Form.prototype = {
     *     render: function () {
     *         hui.Form.superClass.prototype.render.call(this);
     *         //Todo...
     *     }
     * };
     * hui.inherits(hui.Form, hui.Control);
     */
    hui.inherits = function (child, parent) {
        var clazz = new Function();
        clazz.prototype = parent.prototype;

        var childProperty = child.prototype;
        child.prototype = new clazz();

        for (var key in childProperty) {
            if (childProperty.hasOwnProperty(key)) {
                child.prototype[key] = childProperty[key];
            }
        }

        child.prototype.constructor = child;

        //child是一个function
        //使用super在IE下会报错!!!
        child.superClass = parent;
    };

    /**
     * @method hui.extends
     * @description 对象扩展(伪继承)
     * @public
     * @param {Object} child 子对象
     * @param {Object} parent 父对象
     * @example 
     * var a = {a: 123};
     * var b = {b: 456};
     * var c = hui.extends({}, a, b);
     * console.log(c);
     * >> {a: 123, b: 456}
     * var d = {a: 789};
     * var c = hui.extends({}, a, b, d);
     * console.log(c);
     * >> {a: 789, b: 456}
     */
    hui.extends = function (src) {
        var obj, args = arguments;
        for (var i = 1; i < args.length; ++i) {
            if ((obj = args[i])) {
                for (var key in obj) {
                    src[key] = obj[key];
                }
            }
        }
        return src;
    };


});



// 执行后续加载
if (!hui.loadNextLoaded) {
    hui.loadNextLoaded = true;
    hui.loadNext && hui.loadNext();

    hui.loadNextCallback = hui.loadNextCallback || [];
    for (var i = 0, len = hui.loadNextCallback.length; i < len; i++) {
        (typeof hui.loadNextCallback[i]) === 'function' && hui.loadNextCallback[i]();
    }
}