UNPKG

jbd

Version:
2,018 lines (1,769 loc) 77.1 kB
"use strict"; (function (global, factory) { if (global.jBD) return; factory.call( {ver: "2.2.32"}, global, { Node: 0, Web: 0xff, WebDesktop: 0x0f, WebMac: 0x08, WebMobile: 0xf0, WebiPhone: 0x10, WebiPad: 0x20, WebAndroid: 0xc0, WebAPhone: 0x40, WebAPad: 0x80 }); })(typeof (window) !== "undefined" ? window : global, function (global, MODE) { const jBD = this; if (!global.navigator) global.navigator = {userAgent: ""}; global.jBD = jBD; jBD.MODE = MODE; jBD.mode = MODE.Node; /** * 环境判断 * * @param {string} [na=undefined] 版本字符串 * @returns {object} * @return {number} mode 模式,对应MODE码表 * @return {string} kernel 内核名称 * @return {string} version 内核版本 */ jBD.version = na => { let r = {mode: MODE.Node, kernel: "node", version: ""}; if (!na && typeof(window) == "undefined" && process) { r.kernel = "node"; r.version = process.versions.node; } else { na = typeof(na) == "string" && na ? na : navigator.userAgent; let s = na.toLowerCase(), t; if (t = s.match(/msie ([\d.]+)/)) { r.kernel = "ie"; r.version = t[1]; } else if (t = s.match(/firefox\/([\d.]+)/)) { r.kernel = "firefox"; r.version = t[1]; } else if (t = s.match(/chrome\/([\d.]+)/)) { r.kernel = "chrome"; r.version = t[1]; } else if (t = s.match(/opera.([\d.]+)/)) { r.kernel = "opera"; r.version = t[1]; } else if (t = s.match(/version\/([\d.]+).*safari/)) { r.kernel = "safari"; r.version = t[1]; } else { r.kernel = "other"; r.version = "0"; } if (na.indexOf("Android") > -1 || na.indexOf("Linux") > -1) r.mode = MODE.WebAndroid; else if (na.indexOf("iPhone") > -1) r.mode = MODE.WebiPhone; else if (na.indexOf("iPad") > -1) r.mode = MODE.WebiPad; else if (na.match(/\(i[^;]+;( U;)? CPU.+Mac OS/)) r.mode = MODE.WebMac; else r.mode = MODE.WebDesktop; } return r; }; jBD.mode = jBD.version().mode; if (jBD.mode == MODE.Node) exports = module.exports = jBD; else if (!global.global) global.global = global; /** * ========================================== * Name: jBD‘s Tools * Author: Buddy-Deus * CreTime: 2014-12-15 * Description: BD's Tools for JavaScript * Log: * 2014-12-15 初始化工具箱 * 2016-09-22 ES6 Format * 2017-02-10 去除函数默认参数,增加适配 * ========================================== */ (jBD => { /** * 对象类型识别 * * @method type * @param {object} obj 检测对象 * @param {boolean} [detail=false] 是否深度识别 * @returns {string} * True: boolean, number, string, function, null * False: boolean, number, string, function, undefined, null, object, arguments, array, date, regexp */ jBD.type = (obj, detail) => { detail = detail === true; let type = typeof obj; switch (type) { default: case "undefined": return detail ? "undefined" : "null"; case "boolean": case "number": case "string": case "function": return type; case "object": if (obj === null) return "null"; if (!detail) return "object"; if (obj.jquery) return "jquery"; if (obj instanceof Array) return "array"; if (obj instanceof RegExp) return "regexp"; type = (/^\[object (.*)\]$/.exec(Object.prototype.toString.call(obj))[1]).toLowerCase(); if (type.indexOf("html") == 0) return "dom"; return type; } }; /** * 是否相等 * * @param {*} a 判断值 * @param {*} b 判断值 * @param {boolean} [abs=true] 判断引用是否相等 * @returns {boolean} */ jBD.is = (a, b, abs) => { if (abs !== false) return Object.is(a, b); else { let type = [jBD.type(a, true), jBD.type(b, true)]; if (type[0] != type[1]) return false; switch (type[0]) { default: return Object.is(a, b); case "function": return a.toString() == b.toString(); case "date": return a.getTime() == b.getTime(); case "array": case "arguments": case "object": if (Object.keys(a).length != Object.keys(b).length) return false; for (let k in a) if (!Object.is(a[k], b[k])) return false; return true; } } }; /** * 是否是简单类型 * * @param value * @returns {boolean} */ jBD.isSimple = value => { switch (typeof(value)) { default: return value === null; case "undefined": case "boolean": case "number": case "string": return true; } }; /** * 是否为Null * * @param {*} value 判断值 * @param {boolean|object} opt 参数 * @param {boolean} [opt.udf=true] undefined是否为null * @param {boolean} [opt.obj=false] 数组/对象为空是否为null * @returns {boolean} */ jBD.isNull = (value, opt) => { let udf, obj; switch (typeof(opt)) { case "object": if (opt) { udf = opt.udf; obj = opt.obj; } break; case "boolean": udf = opt; break; } udf = udf !== false; obj = obj === true; switch (typeof(value)) { default: return false; case "undefined": return udf; case "object": if (value === null) return true; if (!obj) return false; return Object.keys(value).length == 0; } }; /** * 是否为Boolean * * @param {*} value 判断值 * @param {boolean} [str=false] 是否判断字符串 * @returns {boolean} */ jBD.isBool = (value, str) => { return (typeof(value) == "boolean") || (str === true ? (String(value) in { "true": 1, "false": 1 }) : false); }; /** * 是否为Number * * @param {*} value 判断值 * @param {boolean|object} opt 参数 * @param {boolean} [opt.nan=false] NaN是否为数字 * @param {boolean} [opt.str=false] 是否识别字符串 * @param {boolean} [opt.int=false] 是否只识别整数 * @param {number} [opt.min=NaN] 最小值 * @param {number} [opt.max=NaN] 最大值 * @returns {boolean} */ jBD.isNumber = (value, opt) => { let nan, str, int, min, max, func; switch (typeof(opt)) { case "object": if (opt) { nan = opt.nan; str = opt.str; int = opt.int; min = opt.min; max = opt.max; } break; case "boolean": nan = opt; break; } min = Number(min); max = Number(max); nan = nan === true; str = str === true; if (int = int === true) { if (!isNaN(min)) min = parseInt(min); if (!isNaN(max)) max = parseInt(max); func = v => { if (parseInt(v) !== v) return false; if (!isNaN(min) && v < min) return false; if (!isNaN(max) && v > max) return false; return true; } } else { func = (v, b) => { if (!b) return false; if (!isNaN(min) && v < min) return false; if (!isNaN(max) && v > max) return false; return true; }; } switch (typeof(value)) { case "number": return func(value, nan ? true : !isNaN(value)); case "string": return str && value ? jBD.isNumber(Number(value), {nan: nan, int: int}) : false; default: return false; } }; /** * 是否为String * * @param {*} value 判断值 * @param {boolean} [empty=false] 空值是否为字符串 * @returns {boolean} */ jBD.isString = (value, empty) => { return (typeof(value) == "string") && (empty === true ? true : value.length > 0); }; /** * 是否为函数 * * @param {*} value 判断值 * @returns {boolean} */ jBD.isFunction = value => typeof(value) == "function"; /** * 是否为数组 * * @param {*} value 判断值 * @param {boolean} [arg=false] arguments是否为数组 * @returns {boolean} */ jBD.isArray = (value, arg) => { switch (jBD.type(value, true)) { case "array": return true; case "arguments": return arg === true ? arg : false; default: return false; } }; /** * 是否为对象 * * @param {*} value 判断值 * @param {string|boolean} [arg=object] 只识别Object * @returns {boolean} */ jBD.isObject = (value, arg) => { let result = typeof(value) == "object"; switch (arg) { case false: return result && (value !== null); default: return result && (value ? (value.constructor == Object) : false); case true: case "any": return result; } }; /** * 是否为Promise * * @param {*} value 判断值 * @returns {boolean} */ jBD.isPromise = value => jBD.type(value, true) == "promise"; /** * 是否为Generator * * @param {*} value 判断值 * @param {boolean} [obj=false] 是否检测对象 * @returns {boolean} */ jBD.isGenerator = (value, obj) => { const isFunc = jBD.isFunction, isObj = obj => isFunc(obj.next) && isFunc(obj.throw); if (!value) return false; if (!isFunc(value)) return obj === true ? isObj(value) : false; let main = value.constructor; if (main.name == "GeneratorFunction" || main.displayName == "GeneratorFunction") return true; return isObj(main.prototype); }; /** * 是否为JSON * * @param {*} value 判断值 * @param {object} [out=null] out为状态机参数 * @param {function} [callback] * @returns {boolean} */ jBD.isJSON = (value, out, callback) => { if (typeof(value) != "string" || value.length < 2) return false; let data = (o, v) => { o.type = v[0]; o.escape = v[1]; o.index = v[2]; return o; }, result = (o, v) => { if (callback) callback(o, v); return false; }, type, escape; if (callback === void(0)) callback = out; if (!out || typeof (out) != "object") out = {}; else { type = out.type; escape = out.escape; } if (!jBD.isFunction(callback)) callback = null; if (!(type instanceof Array)) type = []; escape = escape === true; let index = 0, len = type.length - 1, str = len >= 0 && type[len] == 1; if (!/^['"\[\{]/.test(value)) return result(data(out, [type, escape, -1])); for (let char of value) { if (escape) escape = false; else { switch (char = char.codePointAt()) { case 92: if (!str) return result(data({}, [type, escape, index]), out); escape = true; break; case 34: case 39: if (!str) { str = true; len = type.push(char) - 1; } else if (char == type[len]) { type.pop(); len--; str = false; } break; case 91: case 123: if (!str) { len = type.push(char + 2) - 1; } break; case 93: case 125: if (!str) { if (char != type[len]) return result(data({}, [type, escape, index]), out); type.pop(); len--; } break; } } index++; if (len == -1) break; } result(null, data(out, [type, escape, index])); return len == -1; }; /** * 是否为jQuery对象 * * @param {*} value 判断值 * @returns {boolean} */ jBD.isjQuery = value => jBD.isObject(value) && value.jquery; /** * 是否为DOM对象 * * @param {*} value 判断值 * @returns {boolean|number} */ jBD.isDOM = value => jBD.type(value, true) == "dom" && value.nodeType; /** * 是否为日期 * * @param {*} value 判断值 * @param {boolean} [str=false] 是否检验字符串 * @returns {boolean} */ jBD.isDate = (value, str) => { switch (jBD.type(value, true)) { default: return false; case "date": return true; case "string": if (!(str === true)) return false; value = value.trim().split(" "); if (!value[0] || value.length > 2) return false; value[0] = value[0].replace(/-/g, "/").split("/"); if (value[0].length != 3) return false; let year = Number(value[0][0]), month = Number(value[0][1]), day = Number(value[0][2]); if (isNaN(year) || year < 1900) return false; if (isNaN(month) || month < 1 || month > 12) return false; if (isNaN(day) || day < 1 || day > 31) return false; switch (month) { case 2: if (day > (28 + ((!(year % 4) && (year % 100)) || !(year % 400) ? 1 : 0))) return false; break; case 4: case 6: case 9: if (day > 30) return false; break; } return value.length > 1 ? jBD.isTime(value[1], true) : true; } }; /** * 是否为时间 * * @param {*} value 判断值 * @param {boolean} [str=false] 是否检验字符串 * @returns {boolean} */ jBD.isTime = (value, str) => { switch (jBD.type(value, true)) { default: return false; case "date": return true; case "string": if (!(str === true)) return false; value = value.trim().replace(/\./g, ":").split(":"); if (value.length < 3 || value.length > 4) return false; if (value.length == 3) value.push("0"); let hour = Number(value[0]), minute = Number(value[1]), second = Number(value[2]), msecond = Number(value[3]); if (isNaN(hour) || isNaN(minute) || isNaN(second) || isNaN(msecond)) return false; if (hour < 0 || hour > 23) return false; if (minute < 0 || minute > 59) return false; if (second < 0 || second > 59) return false; if (msecond < 0 || msecond > 999) return false; return true; } }; /** * 是否为guid * * @param {*} value 判断值 * @returns {boolean} */ jBD.isGuid = value => { if (typeof(value) != "string") return false; value = value.replace(/([{}])/g, ""); if (value.length != 36) return false; value = value.toLowerCase().split("-"); if (value.length != 5) return false; for (let i = 0, dic = [8, 4, 4, 4, 12], c, d; i < value.length; i++) { d = value[i]; if (d.length != dic[i]) return false; for (c of d) { c = c.codePointAt(); if (!((c >= 48 && c <= 57) || (c >= 97 && c <= 102))) return false; } } return true; }; /** * 是否是两者之间,不安全判定方式 * * @param {number} value * @param {number} b1 * @param {number} b2 * @returns {boolean} */ jBD.between = (value, b1, b2) => { value = Number(value); b1 = Number(b1); b2 = Number(b2); return value >= b1 && value <= b2; }; /** * 获得回调函数 * * @param {Array|arguments} value * @param {number} [index=0] 参数序号 * @returns {function/null} */ jBD.callback = (value, index) => { if (!jBD.isArray(value, true)) return null; if (!jBD.isNumber(index)) index = 0; if (index < 0 || index >= value.length) return null; value = value[value.length - 1]; return jBD.isFunction(value) ? value : null; }; /** * 对象遍历 * * @param {Array|object|string|set|map} value * @param {function} callback * @param {boolean|number|object} opt 参数 * @param {boolean} [opt.detail=false] 详细内容 * @param {boolean} [opt.force=false] 强制array识别 * @param {boolean} [opt.index=0] 起始遍历位置,value=array时生效 * @param {boolean} [opt.desc=false] 倒序排列,value=array时生效 * @returns {boolean} */ jBD.each = (value, callback, opt) => { if (!value || !jBD.isFunction(callback)) return false; let detail, force, index, desc, list; switch (typeof(opt)) { case "object": if (opt) { detail = opt.detail; force = opt.force; index = opt.index; desc = opt.desc } break; case "boolean": detail = opt; break; case "number": index = opt; break; } detail = detail === true; force = force === true; index = jBD.isNumber(index) ? index : 0; desc = desc === true; list = value; switch (force ? "array" : jBD.type(value, true)) { default: return false; case "string": case "set": list = Array.from(value); case "array": case "arguments": if (index < 0) return false; let n = desc ? -1 : 1, i = (desc ? list.length - 1 : 0) + index * n, l, d; if (i < 0 || i >= list.length) l = i * -1; else l = desc ? 1 : list.length * -1; for (; i + l; i += n) { d = list[i]; if (callback.apply(value, [d, i, detail ? jBD.type(d, true) : value, value]) === false) return false; } return true; case "object": case "function": desc = list; list = new Map(); for (index in desc) list.set(index, desc[index]); case "map": let o = [null, null], k, v; for (o of list) { k = o[0]; v = o[1]; if (callback.apply(value, [v, k, detail ? jBD.type(v, true) : value, value]) === false) return false; } return true; } }; /** * 去重复 * * @param {Array} value * @param {boolean} [write=false] 是否更改源 * @returns {Array} */ jBD.unique = (value, write) => { if (!jBD.isArray(value, true)) return []; let result = Array.from(new Set(value)); if (write === true) { value.splice(0, value.length); for (let i = 0; i < result.length; i++) value.push(result[i]); } return result; }; /** * 判断值是否存在 * * @param {*} value * @param {Array|object|set|map} list * @param {function} callback * @returns {boolean} */ jBD.has = (value, list, callback) => { let result = false; if (!jBD.isFunction(callback)) callback = null; switch (jBD.type(list, true)) { case "array": case "arguments": case "object": jBD.each(list, (d, k) => { if (!Object.is(value, d)) return; result = true; if (callback && (callback(k) === true)) return; return false; }); break; case "set": case "map": result = list.has(value); break; } return result; }; /** * 深入合并,前项覆盖后项 * * @param {*} src * @param {*} dest * @param {boolean|object} opt 参数,opt=boolean时,默认匹配opt.deep参数 * @param {boolean} [opt.deep=false] 深入copy * @param {boolean} [opt.write=true] 改写dest * @param {function} callback * @returns {*} */ jBD.clone = (src, dest, opt, callback) => { let type = jBD.type(src, true), simple = jBD.isSimple(dest); if (!jBD.has(type, ["array", "object", "function", "set", "map"])) return src; else if (!simple && jBD.type(dest, true) != type) return dest; const cbset = (dest, key, odata, ndata, type) => { return callback ? callback.apply(dest, [key, ndata, type, odata]) : ndata; }, upset = (type, dest, k, d, t) => { switch (type) { case "set": return dest.add(d); case "map": return dest.set(k, cbset(dest, k, dest.has(k) ? dest.get(k) : void(0), d, t)); case "array": return dest.length > k ? dest[k] = cbset(dest, k, dest[k], d, t) : dest.push(cbset(dest, k, void(0), d, t)); default: return dest[k] = cbset(dest, k, dest[k], d, t); } }, deepset = (state, src, dest, k) => { if (!state) return; jBD.clone(src, dest, true, (key, nd, t, od) => callback ? callback.apply(dest, [k + "." + key, nd, t, od]) : nd); }; if (opt === void(0)) opt = dest; if (callback === void(0)) callback = opt; let deep, write; switch (typeof(opt)) { case "object": if (opt) { deep = opt.deep; write = opt.write; } break; case "boolean": deep = opt; break; } deep = deep === true; write = write !== false; if (!jBD.isFunction(callback)) callback = null; if (simple) { switch (type) { case "function": return src; case "set": dest = new Set(); break; case "map": dest = new Map(); break; case "array": dest = []; break; default: dest = {}; break; } } if (!write) dest = jBD.clone(dest, null, true); jBD.each(src, (d, k, t) => { if (Object.is(src, d)) return; if (!deep) upset(type, dest, k, d, t); else { switch (t) { default: upset(type, dest, k, d, t); break; case "null": case "undefined": upset(type, dest, k, null, "null"); break; case "object": upset(type, dest, k, {}, "object"); deepset(jBD.isObject(dest[k]), d, dest[k], k); break; case "array": case "arguments": upset(type, dest, k, [], "array"); deepset(d.length > 0 && jBD.isArray(dest[k]), d, dest[k], k); break; case "set": upset(type, dest, k, new Set(), "set"); deepset(d.size > 0 && jBD.type(dest[k], true) == "set", d, dest[k], k); break; case "map": upset(type, dest, k, new Map(), "map"); deepset(d.size > 0 && jBD.type(dest[k], true) == "map", d, dest[k], k); break; } } }, true); return dest; }; })(this); /** * ========================================== * Name: jBD‘s Class * Author: Buddy-Deus * CreTime: 2016-04-06 * Description: BD‘s Class * Log: * 2016-04-06 重写代码 * 2016-04-20 重构List,以函数形式存在,合并Queue和Stack以配对函数区分 * 2016-04-21 重构ChinaDate,以函数形式存在,内部引用TChinaDate类 * 2016-11-24 基于ES6改写 * ========================================== */ (own => { const initClassError = function () { if (this.getError || this.setError || this.lastError) return; this.__error__ = []; this.errorMax = 5; this.getError = function (index) { index = parseInt(jBD.isNumber(index) && index >= 0 ? index : -1); let list = this.__error__; return list.length < 1 ? null : list[index < 0 ? list.length - 1 : index]; }; this.setError = function (level, code, msg) { if (arguments.length < 2) code = level; if (arguments.length < 3) msg = code; if (!jBD.has(level, ["log", "info", "error"])) level = "log"; if (!jBD.isNumber(code)) code = -1; if (!jBD.isString(msg)) msg = ""; let list = this.__error__, err = {level, code, msg}; while (list.length >= this.errorMax) list.shift(); list.push(err); this.call("error", [err]); return list[list.length - 1]; }; this.lastError = function () { let list = this.__error__; return list.length > 0 ? list[list.length - 1] : null; }; }, initClassEvent = function () { if (this.on || this.off || this.call) return; this.__event__ = {}; this.on = function (key, func) { let each = (o, l, n) => { for (let i = n, f; i < l.length; i++) { f = l[i]; switch (jBD.type(f, true)) { case "function": o.push(f); break; case "array": each(o, f, 0); break; } } }, list = this.__event__[key] || (this.__event__[key] = []); each(list, arguments, 1); return this; }; this.off = function (key, func) { if (arguments.length == 0) this.__event__ = {}; else if (typeof(func) != "function") this.__event__[key] = []; else { let list = this.__event__[key]; if (list && list.length > 0) { for (let i = 0; i < list.length; i++) { if (func !== list[i]) i++; else list.splice(i, 1); } } } return this; }; this.call = function (key, arg) { let list = this.__event__[key]; if (list && list.length > 0) { if (arguments.length < 2) arg = []; else if (!jBD.isArray(arg)) arg = [arg]; for (let i = 0; i < list.length; i++) list[i].apply(this, arg); } return this; }; }; /* ==================================== = 类名: TSeal = 功 能: 密封类生成 = 对象属性: = className = 函数名 = 对象函数: = clone = 复制本体 = Create = 初始化 ==================================== */ own.TSeal = (() => { function TSeal () {} TSeal.extend = function (childAPI) { if (!jBD.isObject(childAPI)) throw new Error(console.error("[TSeal] object is null")); const className = childAPI.className || "TSeal", parentClass = TSeal, initChild = function () { initClassError.call(this); initClassEvent.call(this); this["create"].apply(this, arguments); return this; }; let childClass = null; eval("childClass=function " + className + "(){return initChild.apply(this,arguments);}"); childClass.prototype = Object.create(parentClass.prototype); childClass.className = className; (CLASS => { jBD.each(childAPI, (d, k) => { if (Object.is(CLASS[k], d)) return; CLASS[k] = jBD.clone(d, true); }); })(childClass.prototype); return childClass; }; TSeal.className = "TSeal"; TSeal.prototype = { className: "TSeal", create: function () { return this; }, free: function () {}, clone: function () { return jBD.clone(this, true); } }; return TSeal; })(); /* ==================================== = 类名: TObject = 功 能: 基类 = 类函数: = extend = 继承函数 = 对象属性: = className = 函数名 = 对象函数: = clone = 复制本体 = create = 初始化 = free = 注销 = super = 继承 ==================================== */ own.TObject = (() => { function TObject () {} TObject.extend = function (childAPI, parentClass) { const getClassName = target => { if (target) { if (typeof(target) == "function" && /^function ([a-zA-Z][a-zA-Z0-9_-]*)/.test(target.toString())) return RegExp.$1; if (target.className) return target.className; } return "TObject"; }, initChild = function (parentClass, childAPI, arg) { if (typeof(childAPI) == "function") { childAPI = childAPI(); for (let k in childAPI) if (!Object.is(this[k], childAPI[k])) this[k] = childAPI[k]; } if (!childAPI.hasOwnProperty("create")) parentClass.apply(this, arg); else { initClassError.call(this); initClassEvent.call(this); childAPI["create"].apply(this, arg); } return this; }; parentClass = parentClass || this; childAPI = childAPI || {}; let className = [getClassName(parentClass), getClassName(childAPI)], childClass = null; if (className[0] == className[1] && className[1] == "TObject") className[1] = "Child"; eval("childClass=function " + className[1] + "(){return initChild.call(this,parentClass,childAPI,arguments);}"); childClass.__super__ = parentClass; childClass.prototype = Object.create(parentClass.prototype); childClass.prototype.__super__ = parentClass.prototype; childClass.prototype.className = className[1]; childClass.className = className[1]; jBD.each(parentClass, (d, k) => { if (k == "className" || Object.is(childClass[k], d)) return; if (k == "__super__") childClass["__super__"][k] = d; else childClass[k] = d; }); (CLASS => { jBD.each(childAPI, (d, k, t) => { if (k == "__super__" || Object.is(CLASS[k], d)) return; CLASS[k] = jBD.clone(d, true); }); })(typeof (childAPI) == "function" ? childClass : childClass.prototype, true); return childClass; }; TObject.className = "TObject"; TObject.prototype = { className: "TObject", create: function () { return this; }, free: function () {}, super: function (method, arg, cls) { if (typeof(method) != "string") return; if (!cls) cls = this.__super__; else { if (typeof(cls) == "string" && cls) { let _this = this.__super__; do { if (_this.className != cls) _this = _this.__super__; else { cls = _this; break; } } while (_this.__super__); } if (!cls.className) return; } method = cls[method]; if (!method) return; else if (!jBD.isFunction(method)) return method; else if (jBD.isNull(arg, true)) return method.call(this); else return method.apply(this, jBD.isArray(arg, true) ? arg : [arg]); }, clone: function () { return jBD.clone(this, true); } }; return TObject; })(); own.TCache = (TObject => { return TObject.extend({ className: "TCache", create: function (size) { this.max = size > 0 ? size : 128; this.index = 0; this.length = 0; this.cache = Buffer.alloc(this.max); }, free: function () { this.cache = null; }, surplus: function () { return this.max - this.offset(); }, offset: function () { return this.index + this.length; }, resize: function (force) { if (force === true) this.clear(); else { if (this.length > 0) this.cache.copy(this.cache, 0, this.index, this.offset()); this.index = 0; } return this.surplus(); }, clear: function () { this.index = 0; this.length = 0; return this; }, push: function (buf) { let offset = buf.byteOffset, count = buf.byteLength, write; while (count > 0) { write = Math.min(count, (write = this.surplus()) > 0 ? write : this.resize()); if (write < 1) write = this.resize(true); buf.copy(this.cache, this.offset(), offset, offset + write); this.length += write; offset += write; count -= write; if (this.parse) this.parse(); } return this; }, remove: function (size) { size = Math.min(size, this.length); this.index += size; this.length -= size; return this; } }); })(own.TObject); /* ==================================== = 类名: TList = 功 能: 队列类 = 对象属性: = length = 数据长度 = type = 数据限定类型 = first = 首个数据 = last = 尾端数据 = 对象函数: = clear = 清空数据 = sort = 数据排序,接受自定义排序函数 = each = 数据检索,遍历函数为true时,删除遍历项 = set = 设置数据,校验数据类型 = del = 删除数据 = add = 添加数据,校验数据类型 = addList = 批量添加数据 = push = 先进后出,添加数据 = pop = 先进后出,获取数据 = put = 先进先出,添加数据 = poll = 先进先出,获取数据 ==================================== */ own.TList = (TObject => { const isType = (obj, type) => { let objType; if (!type || type == "*" || (type == (objType = jBD.type(obj, true)))) return true; if (type == "object" && (objType == "null" || objType == "undefined")) return false; if (objType != "object") return false; if (type == "date" && obj.className == "TChinaDate") return true; return false; }, fmtIndex = (index, def, max) => { index = jBD.isNumber(index) ? index : def; if (index < 0) index = -1; else if (index >= max) index = max; return index; }, setData = (own, data) => { let i; for (i = 0; i < own.length; i++) delete own[i]; for (i = 0; i < data.length; i++) own[i] = data[i]; if ((own.length = data.length) > 0) { own.first = own[0]; own.last = own[own.length - 1]; } else { own.first = null; own.last = null; } }; return TObject.extend({ className: "TList", create: function (type) { this.data = []; this.type = jBD.isString(type) ? type : "*"; this.length = 0; this.onChange = null; }, free: function () { this.clear(); }, valueOf: function () { return this.data; }, clear: function () { this.data = []; this.length = 0; setData(this, this.data); if (this.onChange) this.onChange("clear"); return this; }, sort: function (func) { if (func = jBD.isFunction(func) ? func : null) this.data.sort(func); else this.data.sort(); setData(this, this.data); if (this.onChange) this.onChange("sort"); return this; }, each: function (func) { if (jBD.isFunction(func)) { for (let i = 0, r; i < this.length;) { if ((r = func(this.data[i])) === true) this.del(i); else if (r === false) break; else i++; } } return this; }, "set": function (index, data) { index = fmtIndex(index, -1, this.length); if (!isType(data, this.type)) return -1; this.data[index] = data; if (this.onChange) this.onChange("set", {index: index, data: data}); return index; }, del: function (index) { let result; if (this.length == 0) return null; index = fmtIndex(index, 0, this.length - 1); if (index <= 0) result = this.data.shift(); else if (index >= this.length - 1) result = this.data.pop(); else { result = this.data[index]; this.data.splice(index, 1); } setData(this, this.data); if (this.onChange) this.onChange("del", {index: index}); return result; }, add: function (data, index) { index = fmtIndex(index, this.length, this.length); if (!isType(data, this.type)) return -1; if (index <= 0) { this.data.unshift(data); index = 0; } else if (index >= this.length) this.data.push(data); else this.data.splice(index, 0, data); setData(this, this.data); if (this.onChange) this.onChange("add", {index: index, data: data}); return index; }, addList: function (data, index) { if (jBD.isArray(data) && data.length > 0) { index = fmtIndex(index, this.length, this.length); jBD.each(data, function (d, i) { this.add(d, index + i); }); } return this; }, push: function (data) { return this.add(data, this.length); }, pop: function () { return this.del(this.length); }, put: function (data) { return this.add(data, 0); }, poll: function () { return this.del(0); } }); })(own.TSeal); /* ==================================== = 类名: TChinaDate = 功 能: 中文日期类 = 对象函数: = getTime = 获取当前毫秒数 = setTime = 设置当前时间 = toString = 转换为字符串 ==================================== */ own.TChinaDate = (TObject => { const ct = { monthInfoDt: new Date(1900, 0, 31), monthInfo: [ 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0 ], termInfo: [ 0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758 ], tianGan: ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"], diZhi: ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"], monthStr: ["月", "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"], dayStr: [ ["日", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"], ["初", "十", "廿", "卅", " "] ], termStr: [ "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至" ], zodiacStr: ["鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"] }, getTGDZ = num => { num = jBD.isNumber(num) ? num : 0; return ct.tianGan[num % 10] + ct.diZhi[num % 12]; }, getZodiac = num => ct.zodiacStr[(num - 4) % 12], getTermDate = (year, month) => { return (new Date((31556925974.7 * (year - 1900) + ct.termInfo[month % ct.termInfo.length] * 60000) + Date.UTC(1900, 0, 6, 2, 5))).getUTCDate(); }, getTerm = (year, month, date) => { let term = [getTermDate(year, month * 2), getTermDate(year, month * 2 + 1)]; for (let i = 0; i < term.length; i++) { if (term[i] == date) return ct.termStr[(month * 2 + i) % ct.termStr.length]; } return ""; }, getYear = num => getTGDZ(num - 1864), getMonth = (num, leap) => { return (leap ? "闰" : "") + ct.monthStr[num % ct.monthStr.length]; }, getDay = num => { return ct.dayStr[1][(num - num % 10) / 10] + ct.dayStr[0][num % 10 + (num % 10 ? 0 : 10)]; }; let TChinaDate = TObject.extend({ className: "TChinaDate", create: function (dt) { this.nt = {year: 0, month: 0, day: 0}; this.dt = new Date(); this.Year = ""; this.Month = ""; this.Day = ""; this.Term = ""; this.Zodiac = ""; this.cMonth = ""; this.cDay = ""; this.IsLeap = false; this.setTime(dt); }, valueOf: function () { return this.getTime(); }, getTime: function () { return this.dt.getTime(); }, /** * 设置时间 * * @public * @param {date} dt * @returns {object} this */ setTime: function (dt) { const getLeapYearMonth = year => { return ct.monthInfo[year - ct.monthInfoDt.getFullYear()] & 0xf; }, getLeapYearDay = year => { return getLeapYearMonth(year) ? ((ct.monthInfo[year - ct.monthInfoDt.getFullYear()] & 0x10000) ? 30 : 29) : 0; }, getTotalYearDay = year => { let sum = 348, minfo = ct.monthInfo[year - ct.monthInfoDt.getFullYear()]; for (let i = 0x8000; i > 0x8; i >>= 1) sum += (minfo & i) ? 1 : 0; return sum + getLeapYearDay(year); }, getTotalMonthDay = (year, month) => { return (ct.monthInfo[year - ct.monthInfoDt.getFullYear()] & (0x10000 >> month)) ? 30 : 29; }; if (jBD.isDate(dt)) this.dt.setTime(dt.getTime()); let temp = 0, leap = 0, offset = parseInt((this.dt - ct.monthInfoDt) / 86400000), i; this.nt.year = 0; this.nt.month = 14; this.nt.day = offset + 40; for (i = ct.monthInfoDt.getFullYear(); i < ct.monthInfoDt.getFullYear() + ct.monthInfo.length && offset > 0; i++) { temp = getTotalYearDay(i); offset -= temp; this.nt.month += 12; } if (offset < 0) { offset += temp; i--; this.nt.month -= 12; } this.nt.year = i; this.IsLeap = false; leap = getLeapYearMonth(i); for (i = 1; i < 13 && offset > 0; i++) { if (leap > 0 && i == (leap + 1) && !this.IsLeap) { i--; this.IsLeap = true; temp = getLeapYearDay(this.nt.year); } else temp = getTotalMonthDay(this.nt.year, i); if (this.IsLeap && i == (leap + 1)) this.IsLeap = false; offset -= temp; if (!this.IsLeap) this.nt.month++; } if (offset < 0) { offset += temp; i--; this.nt.month--; } else if (offset == 0 && leap > 0 && i == leap + 1) { if (!this.IsLeap) { i--; this.nt.month--; } this.IsLeap = !this.IsLeap; } this.cYear = getTGDZ(this.nt.year - 1864); this.cMonth = getTGDZ(this.nt.month); this.cDay = getTGDZ(this.nt.day); this.nt.month = i; this.nt.day = offset + 1; this.Year = getYear(this.nt.year); this.Month = getMonth(this.nt.month, this.IsLeap); this.Day = getDay(this.nt.day); this.Term = getTerm(this.nt.year, this.nt.month, this.dt.getDate()); this.Zodiac = getZodiac(this.dt.getFullYear()); return this; }, /** * 转换成字符串 * * @public * @param {string} [fmt=Y年(Z) M月 D T] * @returns {string} */ toString: function (fmt) { let result = jBD.isString(fmt) ? fmt : "Y年(Z) M月 D T"; if (/((CY|CM|Y|M|D|T|Z)+)/.test(result)) { fmt = { "CY+": this.cYear, "CM+": this.cMonth, "CD+": this.cDay, "Y+": this.Year, "M+": this.Month, "D+": this.Day, "T+": this.Term, "Z+": this.Zodiac }; jBD.each(fmt, function (d, k) { let rxp = new RegExp("(" + k + ")", "g"); if (rxp.test(result)) result = result.replace(rxp, d + ""); }); } return result.trim(); } }); TChinaDate.toString = function (fmt, date) { if (date == void(0) && jBD.isDate(fmt)) { date = fmt; fmt = ""; } return (new TChinaDate(date)).toString(fmt); }; return TChinaDate; })(own.TSeal); /* ==================================== = 类名: TChinaDate = 功 能: 中文日期类 = 对象函数: = New = 获取新Guid = toString = 获取字符串 = toByteArray = 获取字节数据 ==================================== */ own.TGuid = (TObject => { const rnd = l => Math.round(Math.random() * (Math.pow(2, 8 * l) - 1)), com = (s, l) => { while (s.length < l * 2) s = "0" + s; return s; }, des = (r, d) => { d.reverse(); for (let i = 0; i < d.length; i++) if (d[i].length > 0) r.push(parseInt("0x" + d[i])); }, gd = [4, 2, 2, 2, 6]; let TGuid = TObject.extend({ className: "TGuid", create: function (data) { const fmt = (d, i, t, list) => { switch (t) { case "string": d = "0x" + d; break; case "number": if (!isNaN(d = parseInt(d))) break; default: return false; } if (d < 0 || d >= Math.pow(2, 8 * gd[i])) return false; list[i] = d; }; this.value = [0, 0, 0, 0, 0]; switch (jBD.type(data, true)) { case "string": data = data.replace(/^(\{)|(\})$/g, "").split("-"); break; case "array": if (data.length == gd.length) break; default: data = []; break; } if (data.length == gd.length) { if (jBD.each(data, fmt)) this.value = data; } }, valueOf: function () { return this.toString(); }, toString: function () { let value = this.value, result = ""; for (let i = 0; i < value.length; i++) result += com(value[i].toString(16), gd[i]) + (i < value.length - 1 ? "-" : ""); return result; }, toByteArray: function () { let value = this.value, result = []; for (let i = 0; i < value.length; i++) des(result, value[i].toString(16).split(/(\w{2})/g)); return result; }, New: function () { this.value = [rnd(4), rnd(2), rnd(2), rnd(2), rnd(6)]; return this; } }); TGuid.toString = function () { return (new TGuid()).New().toString(); }; TGuid.toByteArray = function () { return (new TGuid()).New().toByteArray(); }; TGuid.New = function () { return (new TGuid()).New(); }; return TGuid; })(own.TSeal); /** * 队列函数 * * @param {string} [type=*] 限定类型,对输入内容进行过滤 * @returns {object} */ own.List = type => (new own.TList(type)); /** * 中文日期函数 * * @param {date} [dt=now] * @returns {object} */ own.ChinaDate = dt => (new own.TChinaDate(dt)); own.NewGuid = () => (new own.TGuid()).New(); own.EmptyGuid = () => (new own.TGuid()); })(this); /** * ========================================== * Name: jBD‘s Asyn for ES6 * Author: Buddy-Deus * CreTime: 2016-04-06 * Description: BD‘s Callback/Deferred for ES6 * Log: * 2016-04-06 重写代码 * 2017-02-10 去除函数默认参数,增加适配 * 2017-02-22 增加ES6 Promise支持 * ========================================== */ (own => { let TCallback, TDeferred, TPromise; /* ==================================== = 类名: TCallback = 功 能: 回调类 = 对象函数: = lock = 锁定状态 = unlock = 去除锁定 = add = 添加函数 = del = 删除指定函数 = fire = 触发调用 = fireWith = 触发调用,改变this指向 = empty = 清空回调列表 = unique = 去除重复函数 = has = 检测是否存在指定函数 ==================================== */ TCallback = (TObject => { const getFuncs = (list, callback) => { jBD.each(list, (d, k, t) => { switch (t) { case "function": callback(d); break; case "array": if (d.length > 0) getFuncs(d, callback); break; } }, true); }, eachFuncs = (list, callback) => { let i = 0; while (i < list.length) { if (callback(i, list[i]) !== false) i++; } }, fireFuncs = (list, data, once, done, prog) => { if (list.length < 1) return done; eachFuncs(list, (i, f) => { f.apply(data[0], data[1]); if (once) list.splice(i, 1); if (prog) prog(); if (once) return false; }); if (done) done(); return null }; return TObject.extend({ className: "TCallback", create: function (opt, limit, callback) { this.locked = false; this.length = 0; this.__func = []; this.__arg = null; this.__opt = opt; this.__limit = limit; this.__callback = callback || null; }, free: function () { this.__opt = null; this.__callback = null; this.__func = null; this.__arg = null; }, lock: function () { return this.locked = true; }, unlock: function () { return this.locked = false; }, on: function () { if (!this.locked) { let opt = this.__opt, func = this.__func, arg = this.__arg; getFuncs(arguments, d => { func.push(d); if (func.length > this.limit) func.pop(); }); this.length = func.length; if (opt.unique) this.unique(); if (opt.memory && opt.fire && arg) fireFuncs(func, arg, opt.once, this.__callback, d => this.length = func.length); } return this; }, off: function () { if (!this.locked) { let func = this.__func; if (arguments.length == 0) func = this.__func = []; else { getFuncs(arguments, d => { eachFuncs(func, (i, f) => { if (Object.is(d, f)) { func.splice(i, 1); return false; } }) }); } this.length = func.length; } return this; }, fire: function () { return this.fireWith(this, arguments); }, fireWith: function (own, args, done) { if (arguments.length < 2) args = []; if (arguments.length < 1) own = this; let opt = this.__opt, arg; this.__arg = arg = [own, args.slice ? args.slice() : args]; if (opt.memory && !opt.fire) { opt.fire = true; if (opt.limit) this.__arg = null; } else { let func = this.__func; fireFuncs(func, arg, opt.once, done, d => this.length = func.length); if (this.__callback) this.__callback.apply(arg[0], arg[1]); } return this; }, unique: function () { if (!this.locked) this.length = (this.__func = Array.from(new Set(this.__func))).length; return this; }, has: function (func) { return this.__func.indexOf(func) != -1; } }); })(jBD.TSeal); /* ==================================== = 类名: TDeferred = 功 能: 异步类(观察者模式) = 对象函数: = empty = 清空回调列表 = promise = 去除重复函数 = resolve = 触发成功 = reject = 触发失败 = alarm = 触发警告 = notify = 触发进度 = on = 绑定事件 = off = 解除绑定 = 对象事件: = done = 成功 = fail = 失败 = warn = 警告 = progress = 进度 = always = 结束 ==================================== */ TDeferred = (TObject => { let STATE = { inited: 0, pending: 1, resolved: "resolve", rejected: "reject" }, Deferred; Deferred = TObject.extend({ className: "TDeferred", /** * 初始化函数 * * @param {number} [limit=50] 回调上限 * @param {function} [callback] 最终回调,在触发always最后调用 */ create: function (limit, callback) { let _this = this, event = _this.__event = { done: jBD.Callback(limit).fire(), fail: jBD.Callback(limit).fire(), warn: jBD.Callback(limit).fire(), progress: jBD.Callback(limit).fire(), always: jBD.Callback(limit, callback).fire() }, action = _this.__action = { resolve: event.done, reject: event.fail, alarm: event.warn, notify: event.progress }, promise = _this.__promise = { state: STATE.inited, on: function () { _this.on.apply(_this, arguments); return this; }, off: function () { _this.off.apply(_this, arguments); return this; }, promise: function () { return _this.promise.apply(_this, arguments); } }; _this.state = STATE.inited; _this.__owner = void(0); _this.__surp = 0; event.done.on(e => { _this.__promise.state = _this.state = STATE.resolved; event.fail.lock(); event.warn.lock(); event.progress.lock(); }); event.fail.on(e => { _this.__promise.state = _this.state = STATE.rejected; event.done.lock(); event.warn.lock(); event.progress.lock(); }); jBD.each(event, (d, k) => { promise[k] = _this[k] = function () { d.on(Array.from(arguments)); return this; }; }); jBD.each(action, (d, k) => { _this[k] = function () { _this[k + "With"](_this, arguments); return this; }; _this[k + "With"] = function (own, arg) { own = own || _this.__owner; d.fireWith(own, arg); if (_this.state == k) event.always.fireWith(own, arg); else if (k == "notify" && --_this.__surp < 1) _this.resolveWith(own, arg); return this; }; }); }, /** * 释放函数 */ free: function () { this.__promise = null; this.__event = null; this.__action = null; }, /** * 绑定事件 * * @param {string} tag * @param {function|Array} callback * @returns {Window.TDeferred} */ on: function (tag, callback) { if (this.__event[tag]) this.__event[tag].on(callback); return this; }, /** * 解除绑定 * * @param {string} [tag] * @returns {Window.TDeferred} */ off: function (tag) { if (arguments.length == 0) jBD.each(this.__event, d => d.off()); else if (this.__event[tag]) this.__event[tag].off(); return this; }, /** * 返回操作者模式 * * @param {object} [own] 所有者 * @param {number} [max] 最大done次数,用于适配剩余模式 * @returns {null|*} */ promise: function (own, max) { if (this.state == STATE.inited || this.state == STATE.pending) { this.__promise.state = this.state = STATE.pending; if (arguments.length == 1 && jBD.isNumber(own)) max = own;