js方法封装大全

空扰寡人 提交于 2020-01-15 02:41:11
/**
 * @version:    v2.5.0
 * @buildTime:  Thu Jul 16 2015 17:36:29 GMT+0800 (中国标准时间)
 */
(function (global, document, S, undefined) {

    var location = global.location,

        ua = navigator.userAgent,

        documentElement = document.documentElement,

        head = document.head || document.getElementsByTagName("head")[0],

        isSupportConsole = global.console && console.log,

        noop = function () { },

        error = function (msg) {
            throw isError(msg) ? msg : new Error(msg);
        },

        /**
         * 配置对象
         * @type {Object}
         */
        Config = {
            debug: location.search.indexOf("debug") !== -1 ? true : false
        },

        _config = function (key, value) {
            var ret = S;

            if (isString(key)) {
                // get config
                if (value === undefined) {
                    ret = Config[key];
                } else { // set config
                    Config[key] = value;
                }
            } else {
                // Object config
                each(key, function (v, k) {
                    Config[k] = v;
                });
            }

            return ret;
        };

    S = global[S] = {

        version: "2.5",

        /**
         * 在log环境下输出log信息,避免因为忘记删除log语句而引发错误
         * @param  {String} msg 消息
         * @param  {String} src 消息来源,可选
         * @return {Object}     返回this以链式调用,如S.log().log()
         */
        log: isSupportConsole ? function (msg, src) {
            if (S.config("debug")) {
                if (src) {
                    msg = src + ": " + msg;
                }
                console.log(msg);
            }

            return S;
        } : noop,

        /**
         * Throws error message.
         */
        error: error,

        /**
         * global对象,在浏览器环境中为window
         * @type {Object}
         */
        global: global,

        /**
         * 空函数,在需要使用空函数作为参数时使用
         */
        noop: noop,

        Config: Config,

        config: _config
    };

    /**
    * 语言扩展
    */
    var AP = Array.prototype,

        SP = String.prototype,

        FP = Function.prototype,

        class2type = {},

        toString = class2type.toString,

        hasOwn = class2type.hasOwnProperty,

        slice = AP.slice,

        hasOwnProperty = function (o, p) {
            return hasOwn.call(o, p);
        },

        rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,

        //切割字符串为一个个小块,以空格或逗号分开它们,结合replace实现字符串的forEach
        rword = /[^, ]+/g,

        // 是否是复杂类型
        // rcomplexType = /^(?:object|array)$/,

        rtags = /<[^>]+>/img,

        rsubstitute = /\\?\{\{\s*([^{}\s]+)\s*\}\}/mg,

        /**
         * return false终止循环
         * 原生every必须return true or false
         */
        each = function (object, fn, context) {
            var i = 0,
                length = object.length;

            if (context) {
                fn = fn.bind(context);
            }
            if (length === +length) {
                for (; i < length; i++) {
                    if (fn(object[i], i, object) === false) {
                        break;
                    }
                }
            } else {
                for (i in object) {
                    if (hasOwnProperty(object, i) && (fn(object[i], i, object) === false)) {
                        break;
                    }
                }
            }
        };

    /**
     * Object.keys
     * 不支持enum bug
     */
    if (!Object.keys) {
        Object.keys = function (o) {
            var ret = [],
                p;

            for (p in o) {
                if (hasOwnProperty(o, p)) {
                    ret.push(p);
                }
            }

            return ret;
        };
    }

    if (!FP.bind) {
        FP.bind = function (context) {
            var args = slice.call(arguments, 1),
                fn = this,
                noop = function () { },
                ret = function () {
                    return fn.apply(this instanceof noop ? this : context || global, args.concat(slice.call(arguments)));
                };

            noop.prototype = fn.prototype;
            ret.prototype = new noop();
            return ret;
        };
    }

    /**
     * Date.now
     */
    if (!Date.now) {
        Date.now = function () {
            return +new Date();
        };
    }

    if (!SP.trim) {
        SP.trim = function () {
            return this.replace(rtrim, "");
        };
    }

    if (!SP.startsWith) {
        SP.startsWith = function (search) {
            return this.lastIndexOf(search, 0) === 0;
        };
    }

    if (!SP.endsWith) {
        SP.endsWith = function (search) {
            var index = this.length - search.length;
            return index >= 0 && this.indexOf(search, index) === index;
        };
    }


    /*
     * array shim
     * Array.prototype.every
     * Array.prototype.filter
     * Array.prototype.forEach
     * Array.prototype.indexOf
     * Array.prototype.lastIndexOf
     * Array.prototype.map
     * Array.prototype.some
     * Array.prototype.reduce
     * Array.prototype.reduceRight
     * Array.isArray
     */
    if (!AP.forEach) {
        AP.forEach = function (fn, context) {
            var i = 0,
                length = this.length;

            for (; i < length; i++) {
                fn.call(context, this[i], i, this);
            }
        };
    }

    if (!AP.map) {
        AP.map = function (fn, context) {
            var ret = [],
                i = 0,
                length = this.length;

            for (; i < length; i++) {
                ret.push(fn.call(context, this[i], i, this));
            }
            return ret;
        };
    }

    if (!AP.filter) {
        AP.filter = function (fn, context) {
            var ret = [],
                i = 0,
                length = this.length,
                item;

            for (; i < length; i++) {
                item = this[i];
                if (fn.call(context, item, i, this)) {
                    ret.push(item);
                }
            }
            return ret;
        };
    }

    if (!AP.some) {
        AP.some = function (fn, context) {
            var i = 0,
                length = this.length;

            for (; i < length; i++) {
                if (fn.call(context, this[i], i, this)) {
                    return true;
                }
            }
            return false;
        };
    }

    if (!AP.every) {
        AP.every = function (fn, context) {
            var i = 0,
                length = this.length;

            for (; i < length; i++) {
                if (!fn.call(context, this[i], i, this)) {
                    return false;
                }
            }
            return true;
        };
    }

    if (!AP.indexOf) {
        AP.indexOf = function (searchElement, fromIndex) {
            var ret = -1,
                i,
                length = this.length;

            i = fromIndex * 1 || 0;
            i = i >= 0 ? i : Math.max(0, length + i);

            for (; i < length; i++) {
                if (this[i] === searchElement) {
                    return i;
                }
            }
            return ret;
        };
    }

    if (!AP.lastIndexOf) {
        AP.lastIndexOf = function (searchElement, fromIndex) {
            var ret = -1,
                length = this.length,
                i = length - 1;

            fromIndex = fromIndex * 1 || length - 1;
            i = Math.min(i, fromIndex);

            for (; i > -1; i--) {
                if (this[i] === searchElement) {
                    return i;
                }
            }
            return ret;
        };
    }

    if (!AP.reduce) {
        AP.reduce = function (fn, initialValue) {
            var previous = initialValue,
                i = 0,
                length = this.length;

            if (initialValue === undefined) {
                previous = this[0];
                i = 1;
            }

            for (; i < length; i++) {
                previous = fn(previous, this[i], i, this);
            }
            return previous;
        };
    }

    if (!AP.reduceRight) {
        AP.reduceRight = function (fn, initialValue) {
            var length = this.length,
                i = length - 1,
                previous = initialValue;

            if (initialValue === undefined) {
                previous = this[length - 1];
                i--;
            }
            for (; i > -1; i--) {
                previous = fn(previous, this[i], i, this);
            }
            return previous;
        };
    }

    "Boolean Number String Function Array Date RegExp Object Error".replace(rword, function (name, lc) {
        class2type["[object " + name + "]"] = (lc = name.toLowerCase());
        S["is" + name] = function (o) {
            return type(o) === lc;
        };
    });

    var isArray = Array.isArray = S.isArray = Array.isArray || S.isArray,
        isFunction = S.isFunction,
        isObject = S.isObject,
        isString = S.isString,
        isError = S.isError,
        isDate = S.isDate,

        isNotEmptyString = function (val) {
            return isString(val) && val !== "";
        },

        memoize = function (fn, hasher) {
            var memo = {};

            // 默认拿第一个传入的参数做key
            hasher = hasher || function (val) {
                return val;
            };

            return function () {
                var args = arguments,
                    key = hasher.apply(this, args),
                    val = memo[key];

                // 必须有返回结果才缓存
                return hasOwnProperty(memo, key) && val != null ? memo[key] : (memo[key] = fn.apply(this, args));
            };
        },

        /**
         * 单例模式
         * return only one instance
         * @param  {Function} fn      the function to return the instance
         * @return {Function}
         */
        singleton = function (fn) {
            return memoize(fn, function () {
                return 1;
            });
        },

        /**
         * {{ name }} -> {{ o[name] }}
         * \{{}} -> \{{}}
         * reserve 是否保留{{ var }}来进行多次替换, 默认不保留,即替换为空
         */
        substitute = function (str, o, reserve) {
            if (!isString(str) || (!isArray(o) && !isPlainObject(o))) {
                return str;
            }

            return str.replace(rsubstitute, function (match, name) {
                if (match.charAt(0) === '\\') {
                    return match.slice(1);
                }
                return (o[name] == null) ? reserve ? match : "" : o[name];
            });
        },

        /**
         * jQuery type()
         */
        type = function (object) {
            if (object == null) {
                return object + "";
            }

            var t = typeof object;
            return t === "object" || t === "function" ?
                class2type[toString.call(object)] || "object" :
                t;
        },

        isWindow = function (object) {
            return object != null && object == object.window;
        },

        isPlainObject = function (object) {
            // Must be an Object.
            // Because of IE, we also have to check the presence of the constructor property.
            // Make sure that Dom nodes and window objects don't pass through, as well
            if (!isObject(object) || object.nodeType || isWindow(object)) {
                return false;
            }

            var key, constructor;

            try {
                // Not own constructor property must be Object
                if ((constructor = object.constructor) && !hasOwnProperty(object, "constructor") && !hasOwnProperty(constructor.prototype, "isPrototypeOf")) {
                    return false;
                }
            } catch (e) {
                // IE8,9 Will throw exceptions on certain host objects
                return false;
            }

            // Own properties are enumerated firstly, so to speed up,
            // if last one is own, then all properties are own.
            for (key in object) { }

            return key === undefined || hasOwnProperty(object, key);
        },

        makeArray = function (o) {
            if (o == null) {
                return [];
            }
            if (isArray(o)) {
                return o;
            }

            var ret = [],
                i = 0,
                length = o.length,
                lengthType = type(length),
                oType = type(o);

            if (lengthType !== "number" || typeof o.nodeName === "string" || isWindow(o) || oType === "string" || oType === "function" && !("item" in o && lengthType === "number")) {
                return [o];
            }
            for (; i < length; i++) {
                ret[i] = o[i];
            }
            return ret;
        },

        extend = function () {
            var src, copyIsArray, copy, name, options, clone,
                target = arguments[0] || {},
                i = 1,
                length = arguments.length,
                deep = false;

            // Handle a deep copy situation
            if (typeof target === "boolean") {
                deep = target;

                // skip the boolean and the target
                target = arguments[i] || {};
                i++;
            }

            // Handle case when target is a string or something (possible in deep copy)
            if (typeof target !== "object" && !isFunction(target)) {
                target = {};
            }

            // extend itself if only one argument is passed
            if (i === length) {
                target = S;
                i--;
            }

            for (; i < length; i++) {
                // Only deal with non-null/undefined values
                if ((options = arguments[i]) != null) {
                    // Extend the base object
                    for (name in options) {
                        src = target[name];
                        copy = options[name];

                        // Prevent never-ending loop
                        if (target === copy) {
                            continue;
                        }

                        // Recurse if we're merging plain objects or arrays
                        if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
                            if (copyIsArray) {
                                copyIsArray = false;
                                clone = src && isArray(src) ? src : [];
                            } else {
                                clone = src && isPlainObject(src) ? src : {};
                            }

                            // Never move original objects, clone them
                            target[name] = extend(deep, clone, copy);

                            // Don't bring in undefined values
                        } else if (copy !== undefined) {
                            target[name] = copy;
                        }
                    }
                }
            }

            // Return the modified object
            return target;
        },

        /**
         * 判断两个变量是否相等
         * 数字特殊情况不做判断 如0 == -0
         * regexp不特殊判断
         */
        isEqual = function (a, b) {

            var ret = a === b,
                aType,
                bType;

            if (ret || (a == null || b == null)) {
                return ret;
            }

            aType = type(a);
            bType = type(b);
            /**
             * type不同即不相等
             */
            if (aType !== bType) {
                return false;
            }

            switch (aType) {
                case "array":
                case "object":
                    return compareObject(a, b);
                /**
                 * new String("a")
                 */
                case "string":
                    return a == String(b);
                case "number":
                    return ret;
                case "date":
                case "boolean":
                    return +a == +b;
            }

            return ret;
        },

        compareObject = function (a, b) {
            var p;

            for (p in b) {
                if (!hasOwnProperty(a, p) && hasOwnProperty(b, p)) {
                    return false;
                }
            }
            for (p in a) {
                if (!hasOwnProperty(b, p) && hasOwnProperty(a, p)) {
                    return false;
                }
            }
            for (p in b) {
                if (!isEqual(a[p], b[p])) {
                    return false;
                }
            }
            if (isArray(a) && isArray(b) && a.length !== b.length) {
                return false;
            }
            return true;
        },

        _cid = function (prefix) {
            prefix = prefix || 0;

            var counter = 0;
            return function () {
                return prefix + counter++;
            };
        },

        ucfirst = function (str) {
            return str.charAt(0).toUpperCase() + str.substring(1);
        },

        // 转为下划线风格
        underscored = function (str) {
            return str.replace(/([a-z\d])([A-Z])/g, "$1_$2").replace(/\-/g, "_").toLowerCase();
        },

        // 转为连字符风格
        dasherize = function (str) {
            return underscored(str).replace(/_/g, "-");
        },

        htmlEntities = {
            "&amp;": "&",
            "&gt;": ">",
            "&lt;": "<",
            "&#x60;": "`",
            "&#x2F;": "/",
            "&quot;": '"',
            "&#x27;": "'"
        },
        reverseEntities = {},
        getEscapeReg = singleton(function () {
            var str = "";
            each(htmlEntities, function (entity) {
                str += entity + "|";
            });
            str = str.slice(0, -1);
            return new RegExp(str, "g");
        }),
        getUnEscapeReg = singleton(function () {
            var str = "";
            each(reverseEntities, function (entity) {
                str += entity + "|";
            });
            str += "&#(\\d{1,5});";

            return new RegExp(str, "g");
        }),
        escapeHtml = function (text) {
            return (text + "").replace(getEscapeReg(), function (all) {
                return reverseEntities[all];
            });
        },
        unEscapeHtml = function (text) {
            return (text + "").replace(getUnEscapeReg(), function (all) {
                return htmlEntities[all];
            });
        };

    each(htmlEntities, function (entity, k) {
        reverseEntities[entity] = k;
    });

    extend({

        each: each,

        mix: extend,
        extend: extend,

        isWindow: isWindow,

        isPlainObject: isPlainObject,

        isEqual: isEqual,

        type: type,

        makeArray: makeArray,

        memoize: memoize,
        singleton: singleton,

        uniqueCid: _cid(),

        isNotEmptyString: isNotEmptyString,

        ucfirst: ucfirst,
        dasherize: dasherize,

        random: function (min, max) {
            var array, seed;

            if (isArray(min)) {
                array = min;
                min = 0;
                max = array.length - 1;
            }
            if (max == null) {
                max = min;
                min = 0;
            }
            seed = min + Math.floor(Math.random() * (max - min + 1));
            return array ? array[seed] : seed;
        },

        /**
         * [later description]
         * @param  {Function} fn       要执行的函数
         * @param  {number}   when     延迟时间
         * @param  {boolean}   periodic 是否周期执行
         * @param  {object}   context  context
         * @param  {Array}   data     传递的参数
         * @return {object}            timer,cancel and interval
         */
        later: function (fn, when, periodic, context, data) {
            when = when || 0;
            var m = fn,
                d = makeArray(data),
                f,
                r;

            if (isString(fn)) {
                m = context[fn];
            }

            if (!m) {
                S.error("later: method undefined");
            }

            f = function () {
                m.apply(context, d);
            };

            r = (periodic) ? setInterval(f, when) : setTimeout(f, when);

            return {
                id: r,
                interval: periodic,
                cancel: function () {
                    if (this.interval) {
                        clearInterval(r);
                    } else {
                        clearTimeout(r);
                    }
                }
            };
        },

        /**
         * 在underscore里面有实现,这个版本借鉴的是kissy
         */
        throttle: function (fn, ms, context) {
            ms = ms || 150;

            if (ms === -1) {
                return fn.bind(context || this);
            }

            var last = Date.now();

            return function () {
                var now = Date.now();
                if (now - last > ms) {
                    last = now;
                    fn.apply(context || this, arguments);
                }
            };
        },

        debounce: function (fn, ms, context) {
            context = context || this;
            ms = ms || 150;

            if (ms === -1) {
                return fn.bind(context);
            }
            var timer = null,
                f = function () {
                    f.stop();
                    timer = S.later(fn, ms, 0, context, arguments);
                };

            f.stop = function () {
                if (timer) {
                    timer.cancel();
                    timer = 0;
                }
            };
            return f;
        },

        substitute: substitute,

        /**
         * 对字符串进行截断处理
         */
        truncate: function (str, length, truncation) {
            str += "";
            truncation = truncation || "...";

            return str.length > length ? str.slice(0, length - truncation.length) + truncation : str;
        },

        stripTags: function (str) {
            return (str + "").replace(rtags, "");
        },

        escapeHtml: escapeHtml,
        unEscapeHtml: unEscapeHtml
    });



    /**
    * Uri 相关
    */
    var encode = encodeURIComponent,

        decode = function (s) {
            return decodeURIComponent(s.replace(/\+/g, " "));
        },

        param = function (o, sep, eq) {
            sep = sep || "&";
            eq = eq || "=";

            var buf = [];
            each(o, function (val, key) {
                key = encode(key);
                if (isValidParamValue(val)) {
                    buf.push(key);
                    if (val !== undefined) {
                        buf.push(eq, encode(val));
                    }
                    buf.push(sep);
                }
            });

            buf.pop();
            return buf.join("");
        },

        /**
         * query字符串转为对象
         */
        unparam = function (str, sep, eq) {
            str = (str + "").trim();
            sep = sep || "&";
            eq = eq || "=";

            var ret = {},
                eqIndex,
                pairs = str.split(sep),
                key,
                val,
                i = 0,
                length = pairs.length;

            if (!str) {
                return ret;
            }

            for (; i < length; ++i) {
                eqIndex = pairs[i].indexOf(eq);
                if (eqIndex == -1) { // 没有=
                    key = decode(pairs[i]);
                    val = undefined;
                } else {
                    // remember to decode key!
                    key = decode(pairs[i].substring(0, eqIndex));
                    val = pairs[i].substring(eqIndex + 1);
                    try {
                        val = decode(val);
                    } catch (e) {
                        error(e + val);
                    }
                }
                ret[key] = val;
            }
            return ret;
        },

        parseUri = function (uri) {
            uri = uri || location.href;

            var a = document.createElement('a'),
                protocol,
                path,
                port;

            a.href = uri;
            protocol = a.protocol;
            protocol = protocol.slice(0, protocol.length - 1);

            path = a.pathname;
            // IE10 pathname返回不带/
            if (path.charAt(0) != "/") {
                path = "/" + path;
            }

            port = a.port;
            if (port == 80) {
                port = "";
            }

            return {
                scheme: protocol,
                domain: a.hostname,
                port: port,
                path: path,
                query: a.search.slice(1),
                fragment: a.hash.slice(1)
            };
        },

        Query = function (query) {
            this._query = query;
            this._map = unparam(query);
        },

        Uri = function (uriStr) {
            var uri = this,
                components = parseUri(uriStr);

            each(components, function (v, key) {

                if (key === "query") {
                    // need encoded content
                    uri.query = new Query(v);
                } else {
                    // https://github.com/kissyteam/kissy/issues/298
                    try {
                        v = decode(v);
                    } catch (e) {
                        error(e);
                    }
                    // need to decode to get data structure in memory
                    uri[key] = v;
                }
            });

            return uri;
        },

        ruri = /^(http|file|\/|\.)/,

        /**
         * 简单判断
         * 以http,file,/.开头的为uri
         */
        isUri = function (val) {
            val += "";
            return ruri.test(val);
        };


    Query.prototype = {

        /**
         * Return parameter value corresponding to current key
         * @param {String} [key]
         */
        get: function (key) {
            var map = this._map;
            return key ? map[key] : map;
        },

        /**
         * Set parameter value corresponding to current key
         * @param {String} key
         * @param value
         * @chainable
         */
        set: function (key, value) {
            var query = this,
                map = query._map;

            if (isString(key)) {
                map[key] = value;
            } else {
                if (key instanceof Query) {
                    key = key.get();
                }
                each(key, function (v, k) {
                    map[k] = v;
                });
            }
            return query;
        },

        /**
         * Remove parameter with specified name.
         * @param {String} key
         * @chainable
         */
        remove: function (key) {
            var query = this;

            if (key) {
                key = makeArray(key);
                each(key, function (k) {
                    delete query._map[k];
                });
            } else {
                query._map = {};
            }
            return query;
        },

        /**
         * Serialize query to string.
         */
        toString: function () {
            return param(this._map);
        }
    };

    Query.prototype.add = Query.prototype.set;

    Uri.prototype = {

        getFragment: function () {
            return this.fragment;
        },

        toString: function () {
            var ret = [],
                uri = this,
                scheme = uri.scheme,
                domain = uri.domain,
                path = uri.path,
                // fix port "0" bug
                port = parseInt(uri.port, 10),
                fragment = uri.fragment,
                query = uri.query.toString(),
                credentials = uri.credentials;

            if (scheme) {
                ret.push(scheme);
                ret.push(":");
            }

            if (domain) {
                ret.push("//");

                ret.push(encode(domain));

                if (port) {
                    ret.push(":");
                    ret.push(port);
                }
            }

            if (path) {
                ret.push(path);
            }

            if (query) {
                ret.push("?");
                ret.push(query);
            }

            if (fragment) {
                ret.push("#");
                ret.push(fragment);
            }

            return ret.join("");
        }
    };


    function isValidParamValue(val) {
        var t = typeof val;
        // If the type of val is null, undefined, number, string, boolean, return TRUE.
        return val === null || (t !== "object" && t !== "function");
    }

    /**
     * get/set/remove/add QueryParam
     * uri, args... or args.., uri
     */
    "add get remove set".replace(rword, function (name) {
        S[name + "QueryParam"] = function () {
            var args = makeArray(arguments),
                length = args.length,
                uriStr;

            // 第一个跟最后一个参数都可能是uri
            if (isUri(args[0])) {
                uriStr = args.shift();
            } else if (isUri(args[length - 1])) {
                uriStr = args.pop();
            }

            var uri = new Uri(uriStr),
                query = uri.query,
                ret = query[name].apply(query, args);

            return ret === query ? uri.toString() : ret || "";
        };
    });

    extend({
        urlEncode: encode,
        urlDecode: decode,

        param: param,
        unparam: unparam,

        isUri: isUri,

        parseUri: parseUri,

        getFragment: function (uri) {
            return new Uri(uri).getFragment();
        }
    });
    /**
     * events
     */
    var events = S.events = {};

    // Bind event
    var on = S.on = function (name, callback) {
        var list = events[name] || (events[name] = []);
        list.push(callback);
        return S;
    };

    S.one = function (name, callback) {
        var _callback = function () {
            S.off(name, _callback);
            callback.apply(S, arguments);
        };
        return S.on(name, _callback);
    };

    // Remove event. If `callback` is undefined, remove all callbacks for the
    // event. If `event` and `callback` are both undefined, remove all callbacks
    // for all events
    S.off = function (name, callback) {
        // Remove *all* events
        if (!(name || callback)) {
            events = S.events = {};
            return S;
        }

        var list = events[name];
        if (list) {
            if (callback) {
                for (var i = list.length - 1; i >= 0; i--) {
                    if (list[i] === callback) {
                        list.splice(i, 1);
                    }
                }
            } else {
                delete events[name];
            }
        }

        return S;
    };

    // Emit event, firing all bound callbacks. Callbacks receive the same
    // arguments as `emit` does, apart from the event name
    var trigger = S.trigger = function (name) {
        var list = events[name],
            args = slice.call(arguments, 1);

        if (list) {
            // Copy callback lists to prevent modification
            list = list.slice();

            // Execute event callbacks, use index because it's the faster.
            for (var i = 0, len = list.length; i < len; i++) {
                list[i].apply(S, args);
            }
        }

        return S;
    };

    // thanks modernizr
    var createElement = function (type) {
        return document.createElement(type);
    },

        splitter = " ",
        supportElem = createElement("tbtx"),
        supportStyl = supportElem.style,
        inputElem = createElement("input"),

        /**
         * css 使用 -webkit-box-sizing
         * dom使用boxSizing
         */
        // prefixes = ' -webkit- -moz- -o- -ms- '.split(splitter),
        omPrefixes = 'Webkit Moz O ms',
        cssomPrefixes = omPrefixes.split(splitter),
        // domPrefixes = omPrefixes.toLowerCase().split(splitter),

        prefixed = function (prop) {
            return testPropsAll(prop, "pfx");
        },
        testProps = function (props, prefixed) {
            var prop,
                i;

            for (i in props) {
                prop = props[i];
                if (supportStyl[prop] !== undefined) {
                    return prefixed == "pfx" ? prop : true;
                }
            }
            return false;
        },
        testPropsAll = function (prop, prefixed) {
            var ucProp = ucfirst(prop),
                props = (prop + splitter + cssomPrefixes.join(ucProp + splitter) + ucProp).split(splitter);

            return testProps(props, prefixed);
        },

        transform = prefixed("transform"),
        transition = prefixed("transition"),

        support = {
            touch: "ontouchstart" in documentElement,
            pad: !!ua.match(/iPad/i),

            transition: transition,
            transform: transform,

            placeholder: "placeholder" in inputElem,

            translate3d: testPropsAll('perspective')
        };

    each({
        mobile: function () {
            return !!ua.match(/AppleWebKit.*Mobile.*/) || this.touch;
        },

        phone: function () {
            return this.mobile && !this.pad && screen.width < 800;
        },

        canvas: function () {
            var elem = createElement("canvas");
            return !!(elem.getContext && elem.getContext("2d"));
        }
    }, function (factory, name) {
        support[name] = factory.call(support);
    });

    var transEndEventNames = {
        WebkitTransition: 'webkitTransitionEnd',
        MozTransition: 'transitionend',
        OTransition: 'oTransitionEnd otransitionend',
        transition: 'transitionend'
    };
    support.transitionEnd = transition ? transEndEventNames[transition] : "";

    extend({
        support: support,
        testPropsAll: testPropsAll,
        prefixed: prefixed
    });


    /**
    * an amd loader
    * thanks [seajs](http://seajs.org/)
    * 将seajs改造为一个amd加载器
    * 尽量减少对seajs代码的修改
    */
    var Loader = S.Loader = {},
        data = Loader.data = {},
        cid = _cid(),

        DIRNAME_RE = /[^?#]*\//,
        DOT_RE = /\/\.\//g,
        DOUBLE_DOT_RE = /\/[^/]+\/\.\.\//,
        MULTI_SLASH_RE = /([^:/])\/+\//g;

    // Extract the directory portion of a path
    // dirname("a/b/c.js?t=123#xx/zz") ==> "a/b/"
    // ref: http://jsperf.com/regex-vs-split/2
    function dirname(path) {
        return path.match(DIRNAME_RE)[0];
    }

    // Canonicalize a path
    // realpath("http://test.com/a//./b/../c") ==> "http://test.com/a/c"
    function realpath(path) {
        // /a/b/./c/./d ==> /a/b/c/d
        path = path.replace(DOT_RE, "/");

        // a//b/c  ==>  a/b/c
        path = path.replace(MULTI_SLASH_RE, "$1/");

        // a/b/c/../../d  ==>  a/b/../d  ==>  a/d
        while (path.match(DOUBLE_DOT_RE)) {
            path = path.replace(DOUBLE_DOT_RE, "/");
        }

        return path;
    }

    // Normalize an id
    // normalize("path/to/a") ==> "path/to/a.js"
    // NOTICE: substring is faster than negative slice and RegExp
    function normalize(path) {
        var last = path.length - 1;
        var lastC = path.charAt(last);

        // If the uri ends with `#`, just return it without '#'
        if (lastC === "#") {
            return path.substring(0, last);
        }

        return (path.substring(last - 2) === ".js" ||
            path.indexOf("?") > 0 ||
            path.substring(last - 3) === ".css" ||
            lastC === "/") ? path : path + ".js";
    }


    var PATHS_RE = /^([^/:]+)(\/.+)$/,
        VARS_RE = /{([^{]+)}/g;

    function parseAlias(id) {
        var alias = data.alias;
        return alias && isString(alias[id]) ? alias[id] : id;
    }

    function parsePaths(id) {
        var paths = data.paths,
            m;

        if (paths && (m = id.match(PATHS_RE)) && isString(paths[m[1]])) {
            id = paths[m[1]] + m[2];
        }

        return id;
    }

    function parseVars(id) {
        var vars = data.vars;

        if (vars && id.indexOf("{") > -1) {
            id = id.replace(VARS_RE, function (m, key) {
                return isString(vars[key]) ? vars[key] : m;
            });
        }

        return id;
    }

    function parseMap(uri) {
        var map = data.map,
            ret = uri;

        if (map) {
            for (var i = 0, len = map.length; i < len; i++) {
                var rule = map[i];

                ret = isFunction(rule) ?
                    (rule(uri) || uri) :
                    uri.replace(rule[0], rule[1]);

                // Only apply the first matched rule
                if (ret !== uri) break;
            }
        }

        return ret;
    }


    var ABSOLUTE_RE = /^\/\/.|:\//,
        ROOT_DIR_RE = /^.*?\/\/.*?\//;

    function addBase(id, refUri) {
        var ret,
            first = id.charAt(0);

        // Absolute
        if (ABSOLUTE_RE.test(id)) {
            ret = id;
        }
        // Relative
        else if (first === ".") {
            ret = (refUri ? dirname(refUri) : data.cwd) + id;
        }
        // Root
        else if (first === "/") {
            var m = data.cwd.match(ROOT_DIR_RE);
            ret = m ? m[0] + id.substring(1) : id;
        }
        // Top-level
        else {
            ret = data.base + id;
        }

        if (ret.indexOf("//") === 0) {
            ret = location.protocol + ret;
        }

        return realpath(ret);
    }

    function id2Uri(id, refUri) {
        if (!id) return "";

        id = id.replace('//img.miiee.com/tbtx/', staticUrl);

        id = parseAlias(id);
        id = parsePaths(id);
        id = parseVars(id);
        id = normalize(id);

        var uri = addBase(id, refUri);
        uri = parseMap(uri);

        return uri;
    }

    var cwd = dirname(location.href),
        scripts = document.scripts,
        loaderDir = dirname(getScriptAbsoluteSrc(scripts[scripts.length - 1]) || cwd);

    function getScriptAbsoluteSrc(node) {
        return node.hasAttribute ? // non-IE6/7
            node.src :
            // see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
            node.getAttribute("src", 4);
    }


    /**
     * util-request.js - The utilities for requesting script and style files
     * ref: tests/research/load-js-css/test.html
     */

    var baseElement = head.getElementsByTagName("base")[0],

        currentlyAddingScript,
        interactiveScript,
        IS_CSS_RE = /\.css(?:\?|$)/i,
        isOldWebKit = +navigator.userAgent
            .replace(/.*(?:AppleWebKit|AndroidWebKit)\/(\d+).*/, "$1") < 536;

    function request(url, callback, charset) {
        callback = callback || noop;

        var isCSS = IS_CSS_RE.test(url),
            node = document.createElement(isCSS ? "link" : "script");

        if (charset) {
            var cs = isFunction(charset) ? charset(url) : charset;
            if (cs) {
                node.charset = cs;
            }
        }

        addOnload(node, callback, isCSS);

        if (isCSS) {
            node.rel = "stylesheet";
            node.href = url;
        }
        else {
            node.async = true;
            node.src = url;
        }

        // For some cache cases in IE 6-8, the script executes IMMEDIATELY after
        // the end of the insert execution, so use `currentlyAddingScript` to
        // hold current node, for deriving url in `define` call
        currentlyAddingScript = node;

        // ref: #185 & http://dev.jquery.com/ticket/2709
        if (baseElement) {
            head.insertBefore(node, baseElement);
        } else {
            head.appendChild(node);
        }

        currentlyAddingScript = null;
    }

    function addOnload(node, callback, isCSS) {
        // 不支持 onload事件
        var supportOnload = "onload" in node;
        // for Old WebKit and Old Firefox
        if (isCSS && (isOldWebKit || !supportOnload)) {
            setTimeout(function () {
                pollCss(node, callback);
            }, 1); // Begin after node insertion
            return;
        }

        var onload = function () {
            // Ensure only run once and handle memory leak in IE
            node.onload = node.onerror = node.onreadystatechange = null;

            if (!isCSS && !_config("debug")) {
                head.removeChild(node);
            }

            // Dereference the node
            node = null;
            callback();
        };

        if (supportOnload) {
            node.onload = node.onerror = onload;
        } else {
            node.onreadystatechange = function () {
                if (/loaded|complete/.test(node.readyState)) {
                    onload();
                }
            };
        }
    }

    function pollCss(node, callback) {
        var sheet = node.sheet,
            isLoaded;

        // for WebKit < 536
        if (isOldWebKit) {
            if (sheet) {
                isLoaded = true;
            }
        }
        // for Firefox < 9.0
        else if (sheet) {
            try {
                if (sheet.cssRules) {
                    isLoaded = true;
                }
            } catch (ex) {
                // The value of `ex.name` is changed from "NS_ERROR_DOM_SECURITY_ERR"
                // to "SecurityError" since Firefox 13.0. But Firefox is less than 9.0
                // in here, So it is ok to just rely on "NS_ERROR_DOM_SECURITY_ERR"
                if (ex.name === "NS_ERROR_DOM_SECURITY_ERR") {
                    isLoaded = true;
                }
            }
        }

        setTimeout(function () {
            if (isLoaded) {
                // Place callback here to give time for style rendering
                callback();
            } else {
                pollCss(node, callback);
            }
        }, 20);
    }

    function getCurrentScript() {
        // @update
        if (document.currentScript) {
            return document.currentScript;
        }
        if (currentlyAddingScript) {
            return currentlyAddingScript;
        }

        // For IE6-9 browsers, the script onload event may not fire right
        // after the script is evaluated. Kris Zyp found that it
        // could query the script nodes and the one that is in "interactive"
        // mode indicates the current script
        // ref: http://goo.gl/JHfFW
        if (interactiveScript && interactiveScript.readyState === "interactive") {
            return interactiveScript;
        }

        var scripts = head.getElementsByTagName("script"),
            script,
            i = scripts.length - 1;

        for (; i >= 0; i--) {
            script = scripts[i];
            if (script.readyState === "interactive") {
                interactiveScript = script;
                return interactiveScript;
            }
        }
    }

    /**
     * module.js - The core of module loader
     */

    var cachedMods = Loader.cache = {},
        anonymousMeta,
        fetchingList = {},
        fetchedList = {},
        callbackList = {};

    var STATUS = Module.STATUS = {
        // 1 - The `module.uri` is being fetched
        FETCHING: 1,
        // 2 - The meta data has been saved to cachedMods
        SAVED: 2,
        // 3 - The `module.dependencies` are being loaded
        LOADING: 3,
        // 4 - The module are ready to execute
        LOADED: 4,
        // 5 - The module is being executed
        EXECUTING: 5,
        // 6 - The `module.exports` is available
        EXECUTED: 6
    };

    function Module(uri, deps) {
        this.uri = uri;
        this.dependencies = deps || [];
        this.exports = null;
        this.status = 0;

        // Who depends on me
        this._waitings = {};

        // The number of unloaded dependencies
        // 未加载的依赖数
        this._remain = 0;
    }

    Module.prototype = {
        // Resolve module.dependencies
        // 返回依赖模块的uri数组
        resolve: function () {
            var mod = this,
                uri = mod.uri,
                ids = mod.dependencies;

            return ids.map(function (id) {
                return Module.resolve(id, uri);
            });
        },

        // Load module.dependencies and fire onload when all done
        load: function () {
            var mod = this;

            // If the module is being loaded, just wait it onload call
            if (mod.status >= STATUS.LOADING) {
                return;
            }

            mod.status = STATUS.LOADING;

            var uris = mod.resolve();
            trigger("load", uris);

            // 未加载的依赖数
            var len = mod._remain = uris.length,
                m,
                i,
                uri = mod.uri;

            // Initialize modules and register waitings
            for (i = 0; i < len; i++) {
                m = Module.get(uris[i]);

                if (m.status < STATUS.EXECUTED) {
                    // Maybe duplicate
                    m._waitings[uri] = (m._waitings[uri] || 0) + 1;
                } else {
                    mod._remain--;
                }
            }

            if (mod._remain === 0) {
                mod.onload();
                return;
            }

            // for (i = 0; i < len; i++) {
            //     m = cachedMods[uris[i]];

            //     // 模块尚未define及加载
            //     if (m.status < STATUS.FETCHING) {
            //         m.fetch();
            //     }
            //     // 模块define过
            //     else if (m.status === STATUS.SAVED) {
            //         m.load();
            //     }
            // }

            var requestCache = {};

            for (i = 0; i < len; i++) {
                m = cachedMods[uris[i]];

                if (m.status < STATUS.FETCHING) {
                    m.fetch(requestCache);
                } else if (m.status === STATUS.SAVED) {
                    m.load();
                }
            }

            // Send all requests at last to avoid cache bug in IE6-9. Issues#808
            for (var requestUri in requestCache) {
                if (requestCache.hasOwnProperty(requestUri)) {
                    requestCache[requestUri]();
                }
            }
        },

        onload: function () {
            var mod = this;
            mod.status = STATUS.LOADED;

            if (mod.callback) {
                mod.callback();
            }

            mod.exec();
        },

        // exec to get exports
        exec: function () {
            var mod = this;

            // When module is executed, DO NOT execute it again. When module
            // is being executed, just return `module.exports` too, for avoiding
            // circularly calling
            if (mod.status >= STATUS.EXECUTING) {
                return mod.exports;
            }

            mod.status = STATUS.EXECUTING;

            var uri = mod.uri,
                uris = mod.resolve(),
                deps = [],
                i = 0,
                len = uris.length;

            for (; i < len; i++) {
                deps[i] = Module.get(uris[i]).exports;
            }

            // Exec factory
            var factory = mod.factory,
                exports = isFunction(factory) ?
                    factory.apply(null, deps) :
                    factory;

            if (exports === undefined) {
                exports = mod.exports;
            }

            // if (exports === null) {

            // }

            // Reduce memory leak
            delete mod.factory;

            mod.exports = exports;
            mod.status = STATUS.EXECUTED;

            // Emit `exec` event
            // emit("exec", mod)
            //
            // Notify waiting modules to fire onload
            var waitings = mod._waitings,
                m;

            for (uri in waitings) {
                if (waitings.hasOwnProperty(uri)) {
                    m = cachedMods[uri];
                    m._remain -= waitings[uri];
                    if (m._remain === 0) {
                        m.onload();
                    }
                }
            }

            // Reduce memory taken
            delete mod._waitings;
            delete mod._remain;

            return exports;
        },

        fetch: function (requestCache) {
            var mod = this,
                uri = mod.uri;

            mod.status = STATUS.FETCHING;
            var eventData = { uri: uri };
            trigger("fetch", eventData);
            var requestUri = eventData.requestUri || uri;

            // Empty uri or a non-AMD module
            if (!requestUri || fetchedList[requestUri]) {
                mod.load();
                return;
            }

            if (fetchingList[requestUri]) {
                callbackList[requestUri].push(mod);
                return;
            }

            fetchingList[requestUri] = true;
            callbackList[requestUri] = [mod];


            // sendRequest();
            if (requestCache) {
                requestCache[requestUri] = sendRequest;
            } else {
                sendRequest();
            }

            function sendRequest() {
                request(requestUri, onRequest, data.charset);
            }


            function onRequest() {
                delete fetchingList[requestUri];
                fetchedList[requestUri] = true;

                // Save meta data of anonymous module
                if (anonymousMeta) {
                    Module.save(uri, anonymousMeta);
                    anonymousMeta = null;
                }

                // Call callbacks
                var m, mods = callbackList[requestUri];
                delete callbackList[requestUri];
                while ((m = mods.shift())) m.load();
            }
        }
    };

    // Save meta data to cachedMods
    Module.save = function (uri, meta) {
        var mod = Module.get(uri);

        // Do NOT override already saved modules
        if (mod.status < STATUS.SAVED) {
            mod.id = meta.id || uri;
            mod.dependencies = meta.deps || [];
            mod.factory = meta.factory;
            mod.status = STATUS.SAVED;
        }
    };

    Module.get = function (uri, deps) {
        return cachedMods[uri] || (cachedMods[uri] = new Module(uri, deps));
    };
    // 不直接调用Module.require, 在其他地方使用并传入uri
    // Use function is equal to load a anonymous module
    Module.require = function (ids, callback, uri) {
        // 匿名模块uri根据preload,require等+cid进行区分
        // 需要uri来创建模块,注册依赖
        var mod = Module.get(uri, makeArray(ids));

        // 注册模块完成时的callback
        // 获取依赖模块的export并且执行callback
        if (callback) {
            mod.callback = function () {
                var uris = mod.resolve(),
                    exports = uris.map(function (uri) {
                        return cachedMods[uri].exports;
                    });

                callback.apply(global, exports);
                delete mod.callback;
            };
        }

        mod.load();
    };

    // Resolve id to uri
    Module.resolve = function (id, refUri) {
        return id2Uri(id, refUri);
    };

    /**
     * define
     * 匿名模块与非匿名模块
     * 非匿名模块调用module.save保存模块信息。模块状态变为SAVED
     */
    Module.define = function (id, deps, factory) {
        var argsLen = arguments.length;

        // define(factory)
        if (argsLen === 1) {
            factory = id;
            id = undefined;
        } else if (argsLen === 2) {
            factory = deps;

            // define(deps, factory)
            if (isArray(id)) {
                deps = id;
                id = undefined;
            }
            // define(id, factory)
            else {
                deps = undefined;
            }
        }

        if (!isArray(deps)) {
            deps = [];
        }

        var meta = {
            id: id,
            uri: Module.resolve(id),
            deps: deps,
            factory: factory
        };

        /**
         * 具名模块直接save,匿名模块使用meta信息,在onload里面保存
         */
        if (!meta.uri) {
            var script = getCurrentScript();
            if (script) {
                meta.uri = script.src;
            }

            // NOTE: If the id-deriving methods above is failed, then falls back
            // to use onload event to get the uri
        }

        if (meta.uri) {
            Module.save(meta.uri, meta);
        } else {
            // Save information for "saving" work in the script onload event
            anonymousMeta = meta;
        }
    };

    Module.define.amd = {};
    data.fetchedList = fetchedList;

    /**
     * config.js - The configuration for the loader
     */

    // The root path to use for id2uri parsing
    // If loaderUri is `http://test.com/libs/seajs/[??][seajs/1.2.3/]sea.js`, the
    // baseUri should be `http://test.com/libs/`
    // 请求的baseUrl
    data.base = loaderDir;

    // The loader directory
    // loader所在目录,base默认是这个
    data.dir = loaderDir;

    // The current working directory
    data.cwd = cwd;

    // The charset for requesting files
    data.charset = "utf-8";

    // data.alias - An object containing shorthands of module id
    // data.paths - An object containing path shorthands in module id
    // data.vars - The {xxx} variables in module id
    // data.map - An array containing rules to map module uri
    // data.debug - Debug mode. The default value is false

    Loader.config = function (configData) {

        for (var key in configData) {
            var curr = configData[key],
                prev = data[key];

            // Merge object config such as alias, vars
            if (prev && isObject(prev)) {
                for (var k in curr) {
                    prev[k] = curr[k];
                }
            } else {
                // Concat array config such as map, preload
                if (isArray(prev)) {
                    curr = prev.concat(curr);
                }
                // Make sure that `data.base` is an absolute path
                else if (key === "base") {
                    if (curr.slice(-1) !== "/") {
                        curr += "/";
                    }
                    curr = addBase(curr);
                }

                // Set config
                data[key] = curr;
            }
        }
    };

    Loader.resolve = id2Uri;

    var define = global.define = Module.define;
    var require = global.require = function (ids, callback) {
        Module.require(ids, callback, data.cwd + "_require_" + cid());
        // return S;
    };

    extend({
        Module: Module,
        define: define,
        require: require,
        realpath: realpath,
        loadScript: request,
        loadCss: request
    });



    /**
     * 模块配置与注册
     * 只写常用的
     * @type {[type]}
     */


    var staticUrl = S.staticUrl = realpath(loaderDir + "../../../"),

        paths = {},

        alias = {},

        aliasConfig = {

            component: {
                switchable: "1.0.4",
                validator: "0.9.7",
                popup: "1.0.0",
                circle: "1.0.0"
            },

            plugin: {
                lazyload: "1.8.4",
                easing: "1.3"
            },

            gallery: {
                jquery: support.mobile ? "2.1.1" : "1.11.3",
                handlebars: "1.3.0",
                json: "2",
                hammer: "2.0.4"
            },

            arale: {
                base: "1.1.1",
                widget: "1.1.1",
                position: "1.0.1"
            },

            dist: {
                msg: "1.0.0"
            }
        },

        // 目录规范
        dirPattern = "{{ dir }}/{{ name }}/{{ version }}/{{ name }}";

    each(aliasConfig, function (config, dir) {

        paths[dir] = realpath(loaderDir + "../../") + dir;

        each(config, function (v, name) {
            alias[name] = substitute(dirPattern, {
                dir: dir,
                name: name,
                version: v
            });
        });
    });

    alias.$ = alias.jquery;

    Loader.config({

        base: staticUrl,

        alias: alias,

        paths: paths

    });

    if (!_config("debug")) {
        if (location.href.indexOf("zhaopin.taobao") > 0 || location.href.indexOf("alizhaopin") > 0) {
            var scriptstamp = Math.floor(Date.now() / 60000);
            Loader.config({
                // 每分钟
                map: [
                    function (uri) {
                        if (uri.indexOf("t=") === -1) {
                            return uri.replace(/^(.*\.(?:css|js))(.*)$/i, "$1?t=" + scriptstamp);
                        }
                    }
                ]
            });
        } else {
            var scriptstamp = Math.floor(Date.now() / 3600000);
            Loader.config({
                // 每小时更新时间戳
                map: [
                    function (uri) {
                        if (uri.indexOf("t=") === -1) {
                            return uri.replace(/^(.*\.(?:css|js))(.*)$/i, "$1?t=" + scriptstamp);
                        }
                    }
                ]
            });
        }

    }

    define("tbtx", S);

    if (typeof JSON !== undefined + "") {
        define("json", JSON);
    }
    if (typeof jQuery !== undefined + "") {
        define("jquery", function () {
            return jQuery;
        });
    }


    var preloadConfig = {
        broadcast: "msg",
        pin: "position",
        center: "position"
    };

    // 某些没有return的模块接口可以提前写入
    each(preloadConfig, function (module, name) {

        S[name] = function () {
            var args = arguments;

            require(module, function (exports) {
                var fn = exports[name];

                if (isFunction(fn)) {
                    fn.apply(S, args);
                    S[name] = fn;
                }
            });
        };
    });


    var MILLISECONDS_OF_DAY = 24 * 60 * 60 * 1000,

        cookie = S.cookie = {
            /**
             * 获取 cookie 值
             * @return {string} 如果 name 不存在,返回 undefined
             */
            get: function (name) {
                var ret, m;
                if (isNotEmptyString(name)) {
                    if ((m = String(document.cookie).match(
                        new RegExp('(?:^| )' + name + '(?:(?:=([^;]*))|;|$)')))) {
                        ret = m[1] ? decode(m[1]) : '';
                    }
                }
                return ret;
            },

            // 缓存csrfToken 6H
            setCsrfToken(val) {
                var text = String(encode(val)),
                    date = new Date();
                date.setTime(date.getTime() + 24 * 60 * 60 * 100);
                console.log(date);
                text += '; expires=' + date.toUTCString() + '; path=/';
                document.cookie = 'TP-XSRF-TOKEN' + '=' + text;
                return this;
            },

            set: function (name, val, domain, expires, path, secure) {
                var text = String(encode(val)),
                    date = expires;

                // 从当前时间开始,多少天后过期
                if (typeof date === 'number') {
                    date = new Date();
                    date.setTime(date.getTime() + expires * MILLISECONDS_OF_DAY);
                }

                // expiration date
                if (date instanceof Date) {
                    text += '; expires=' + date.toUTCString();
                }

                // domain
                if (isNotEmptyString(domain)) {
                    text += '; domain=' + domain;
                }

                // path
                if (isNotEmptyString(path)) {
                    text += '; path=' + path;
                } else {
                    text += '; path=/';
                }

                // secure
                if (secure) {
                    text += '; secure';
                }

                document.cookie = name + '=' + text;
                return this;
            },

            remove: function (name, domain, path, secure) {
                // 置空,并立刻过期
                this.set(name, '', domain, -1, path, secure);
                return this;
            }
        };

    /**
     * formate格式只有2014/07/12 12:34:35的格式可以跨平台
     * new Date()
     * new Date(时间戳)
     * new Date(year, month, day[, hour[, minute[, second[, millisecond]]]])
     */

    var rformatDate = /y|m|d|h|i|s/gi,
        rnumberDate = /^\d{13}$/,
        // from moment
        riso = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
        rdate = /\d{4}-\d{2}-\d{2}/;

    // 判断参数是否是日期格式
    // 包括数字,日期
    // iso日期字符串
    function isDateFormat(val) {
        return rnumberDate.test(val) || riso.test(val) || isDate(val);
    }

    // 解析一个日期, 返回日期对象
    function parseDate(val) {
        var match,
            matchYmd;

        if (isDate(val)) {
            return val;
        }

        if (rnumberDate.test(val)) {
            return new Date(+val);
        }

        match = riso.exec(val);
        matchYmd = rdate.exec(val);
        if (match && matchYmd) {
            // 暂时只支持 2014-11-26T11:22:23这种4位年的日期
            return new Date(matchYmd[0].replace(/-/g, "/") + " " + match[7]);
        }

        return new Date();
    }

    /*
     * 将日期格式化成字符串
     *  Y - 4位年
     *  y - 2位年
     *  M - 不补0的月,
     *  m - 补0的月
     *  D - 不补0的日期
     *  d - 补0的日期
     *  H - 不补0的小时
     *  h - 补0的小时
     *  I - 不补0的分
     *  i - 补0的分
     *  S - 不补0的秒
     *  s - 补0的秒
     *  毫秒暂不支持
     *
     * date只支持毫秒和Date
     *  @return:指定格式的字符串
     */
    function formatDate(format, date) {
        // 交换参数
        if (isDateFormat(format)) {
            date = [format, format = date][0];
        }

        format = format || "Y-m-d h:i:s";
        date = normalizeDate(date);

        return format.replace(rformatDate, function (k) {
            return date[k];
        });
    }

    // date转对象
    function normalizeDate(date) {
        date = parseDate(date);

        var o = {
            Y: date.getFullYear(),
            M: date.getMonth() + 1,
            D: date.getDate(),
            H: date.getHours(),
            I: date.getMinutes(),
            S: date.getSeconds()
        },
            ret = {};

        each(o, function (v, k) {
            // 统一结果为字符串
            ret[k] = v + "";

            ret[k.toLowerCase()] = padding2(v).slice(-2);
        });

        return ret;
    }

    function padding2(str) {
        str += "";
        return str.length === 1 ? "0" + str : str;
    }

    extend({
        parseDate: parseDate,
        normalizeDate: normalizeDate,
        formatDate: formatDate
    });


    var randomToken = function () {
        return Math.random().toString(36).substring(2, 15);
    },

        token = randomToken() + randomToken(),

        generateToken = function () {
            cookie.set(_config("tokenName"), token, "", "", "/");
            return token;
        };

    S.generateToken = generateToken;

    // 默认蜜儿
    _config({
        tokenName: "MIIEE_JTOKEN",

        request: {
            code: {
                fail: -1,
                success: 100
            },
            msg: {
                0: "无法连接到服务器!请检查网络连接!",
                500: "服务器出错!",
                timeout: "请求超时!",
                abort: "请求被终止!",
                parsererror: "服务器出错或数据解析出错!"
            }
        }
    });

    define("request", ["jquery"], function ($) {

        var config = _config("request"),
            code = config.code,
            msg = config.msg,
            // 互斥锁
            isTokenLock = 0,

            /**
             * 解决后端删除jtoken后ajax cookie没有token
             * 每次同时只处理一个request 请求
             */
            send = function (options, successCode, defer) {
                if (isTokenLock) {
                    setTimeout(function () {
                        send(options, successCode, defer);
                    }, 50);
                    return false;
                }

                isTokenLock = 1;
                options.data.jtoken = generateToken();
                $.ajax(options)
                    .done(function (response) {
                        var code, result;
                        if (response) {
                            code = response.code;
                            result = response.result;

                            // 有result返回result,没有result返回response
                            // 返回result时加一层result来兼容之前的写法
                            if (result) {
                                result.code = code;
                                result.msg = response.msg;
                                result.result = extend(true, isArray(result) ? [] : {}, result);

                                response = result;
                            }
                        }

                        if (code === successCode) {
                            defer.resolve(response, options);
                        } else {
                            defer.reject(code, response, options);
                        }
                    })
                    .fail(function (xhr, status, err) {
                        defer.reject(code.fail, {
                            code: code.fail,
                            url: options.url,
                            msg: msg[xhr.status] || msg[status] || msg.def
                        });
                    })
                    .always(function () {
                        isTokenLock = 0;
                    });
            },

            request = function (url, data, successCode) {
                var ret = $.Deferred(),
                    options = {
                        type: "post",
                        dataType: "json",
                        timeout: 10000
                    };

                if (typeof url === "object") {
                    options = extend(options, url);
                    successCode = data;
                } else {
                    extend(options, {
                        url: url,
                        data: data
                    });
                }

                successCode = successCode || code.success;
                data = options.data || {};
                url = S.addQueryParam(options.url.trim(), "_", Date.now());
                if (isString(data)) {
                    data = unparam(data);
                }

                options.url = url;
                options.data = data;

                send(options, successCode, ret);
                return ret.promise();
            };

        return request;
    });
})(typeof window !== "undefined" ? window : this, document, "tbtx");
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!