/// String.prototype.trim = function () { return this.replace(/(^\s*)|(\s*$)/g, ""); } /* * 获取数组中符合条件的项目 * obj [object] 不可空 条件对象,如: {name:'lance',age:18} 表示从数组中查找 name为lance,age为18的元素 * getIndex [bool] 可空 返回结果是元素下标 * all [bool] 可空 返回所有满足条件的元素集合 */ Array.prototype.get = function (obj, getIndex, all) { var r = []; for (var i = 0; i < this.length; i++) { var val = this[i]; var flag = true; for (var ff in obj) { if (val[ff] != obj[ff]) { flag = false; break; } } if (flag) { var ts = (getIndex ? i : val); if (!all) return ts; else r.push(ts); } } return all ? r : (getIndex ? -1 : null); } //扩展 filter 与 find if (typeof (Array.prototype.filter) == "undefined") { Array.prototype.filter = function (fn) { var r = []; for (var i = 0; i < this.length; i++) { if (fn(this[i])) r.push(this[i]); } return r; } } if (typeof (Array.prototype.find) == "undefined") { Array.prototype.find = function (fn) { for (var i = 0; i < this.length; i++) { if (fn(this[i])) return this[i]; } } } /* * 删除指定元素 * val [任意] 需要删除的元素 */ Array.prototype.remove = function (val) { var i = this.indexOf(val); if (i > -1) this.splice(i, 1); } //交换元素顺序 Array.prototype.swap = function (i, j) { if (i > -1 && j > -1 && i < this.length && j < this.length) { var temp = this[j]; this[j] = this[i]; this[i] = temp; } } //将对象数组特定字段使用分割符连接起来 Array.prototype.joinField = function (name, separator) { separator = separator || ","; var str = ""; for (var i = 0; i < this.length; i++) { if (this[i][name] != null) { if (str) str += separator; str += this[i][name]; } } return str; } ke = { types: { string: "string", int: "int", float: "float", date: "date", boolean: "bool" }, charIndex: function (ch, htm, i) { i++; for (i; i < htm.length; i++) { if (htm[i] == ch) { return i; } } return -1; }, //使用模板生成字符串,支持{属性名}的嵌入式写法 //@参数0 {string}模板 //@其它参数 {对象}需要填充的对象,如果是多个对象则按顺序查找填充 format: function (tmpl, data, data2) { var htm = ""; for (var j = 0; j < tmpl.length; j++) { if (tmpl[j] == '{') { var rindex = this.charIndex('}', tmpl, j); if (rindex > -1) { var field = ""; for (var n = j + 1; n < rindex; n++) { field += tmpl[n]; } if (field == "this") htm += data; else if (data[field] != null) htm += data[field]; else if (data2 && data2[field] != null) htm += data2[field]; j = rindex; continue; } } htm += tmpl[j]; } return htm; }, //使用模板生成字符串,支持{属性名}的嵌入式写法 //@tmpl 模板 @arr 对象数组 @prepare 绑定之前的对象格式化处理 formatForeach: function (tmpl, arr, prepare) { var htm = ""; for (var i = 0; i < arr.length; i++) { var data = arr[i]; data = (prepare ? prepare(data, i) : data); if (data != null) htm += ke.format(tmpl, data, { rowIndex: i }); } return htm; }, //取dom get: function (id) { return document.getElementById(id); }, //设置dom的innerHTML set: function (id, htm) { this.get(id).innerHTML = htm; }, //获取Get参数并组织成对象 getRequestParmsObject: function () { var r = {}; var query = window.location.search; query = query.substring(1); var pairs = query.split("&"); for (var i = 0; i < pairs.length; i++) { var sign = pairs[i].indexOf("="); if (sign == -1) { continue; } var k = pairs[i].substring(0, sign); var v = unescape(pairs[i].substring(sign + 1)); r[k] = v; } return r; }, //获取Get参数列表 getRequestParms: function () { var argsArr = new Array(); var query = window.location.search; query = query.substring(1); var pairs = query.split("&"); for (var i = 0; i < pairs.length; i++) { var sign = pairs[i].indexOf("="); if (sign == -1) { continue; } var aKey = pairs[i].substring(0, sign); var aValue = pairs[i].substring(sign + 1); argsArr.push({ name: aKey, value: aValue }); } return argsArr; }, //取Get参数 @name 参数名 @def 如果不存在时返回的默认值[可空] parm: function (name, def) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if (r != null) { return unescape(r[2]); } else if (def != null) return def; else return ""; }, //将dom的attributes集合连接成字符串 joinAttr: function (el, notContains) { var r = ""; for (var i = 0; i < el.attributes.length; i++) { var t = el.attributes[i]; if (notContains.indexOf(t.name) < 0) r += " " + t.name + "=\"" + t.value + "\""; } return r.trim(); }, //取多个参数中的最小值 min: function () { var r = null; for (var i = 0; i < arguments.length; i++) { if (r == null || arguments[i] < r) r = arguments[i]; } return r; }, //取多个参数中的最大值 max: function () { var r = null; for (var i = 0; i < arguments.length; i++) { if (r == null || arguments[i] > r) r = arguments[i]; } return r; }, isString: function (arg) { return $.type(arg) == "string"; }, isBool: function (arg) { return $.type(arg) == "boolean"; }, //获取bool类型 0,null,false,undefine均为false 其它为 true getBool: function (v) { return v == true; }, //获取浮点类型 @v 需要转换的值, @d 需要保留的小数位数[四舍五入] getFloat: function (v, d) { if (!d) d = 0; var f = parseFloat(v); if (isNaN(f)) { return null; } d = Math.pow(10, d); return Math.round(v * d) / d; }, //获取可为空的整形 getInt: function (v) { var r = parseInt(v); return (isNaN(r) ? null : r); }, //将字符串转换为Date类型 getDate: function (v) { if (v) { if ($.isNumeric(v)) return new Date((v - 28800) * 1000); else if (v instanceof Date) return v; else { v = v.toString().trim().replace(/-/g, "/"); if (v.match(/[\d]{4,4}[/]{1}[\d]{1,2}[/]{1}[\d]{1,2}/g)) return new Date(v); } } return null; }, //中国时间 getTimeSpan: function (v) { var r = ke.getDate(v); return (r != null ? (r.getTime() / 1000 + 28800) : null); }, //将日期格式转换为年月日时分秒数组 //@v 可支持时间戳、形如 2018-1-1 的字符串及Date类型 //@type [可选]返回类型,默认为全部 date:仅返回日期部分 time:返回时间部分 getYMD: function (v, type) { if (!v) return []; var dt = v; if ($.isNumeric(v)) dt = new Date((v - 28800) * 1000); else if (ke.isString(v)) { if (v.match(/^[\+\-]?\d*?\.?\d{0,4}?$/)) dt = new Date(parseInt(v) * 1000); else dt = this.getDate(v); } if (!type) return [dt.getFullYear(), dt.getMonth() + 1, dt.getDate(), dt.getHours(), dt.getMinutes(), dt.getSeconds()]; else if (type == "date") return [dt.getFullYear(), dt.getMonth() + 1, dt.getDate()]; else if (type == "time") return [dt.getHours(), dt.getMinutes(), dt.getSeconds()]; }, //将时间转换为格式:2018-1-1 12:01:01 //@v 需要转换的值,可支持时间戳、形如 2018-1-1 的字符串及Date类型 //@hm 显示时分 //@sec 显示秒 getDateTip: function (v, hm, sec) { try { if (!v) return ""; var dt = ke.getYMD(v); for (var i = 1; i < dt.length; i++) { if (dt[i] < 10) dt[i] = "0" + dt[i]; } var tip = dt[0] + "-" + dt[1] + "-" + dt[2]; if (hm === true) { tip = tip + " " + dt[3] + ":" + dt[4]; if (sec) tip = tip + ":" + dt[5]; } return tip; } catch (e) { return ""; } }, getTimeTip: function (v) { return ke.getDateTip(v, true); }, //类型强制转换 //@val 需要转换的值 @type 目标类型[支持:string,bool,float,int,date] @d:需要保留的小数位[可选] convert: function (val, type, d) { if (type == null && type == this.types.string) return (val || "").toString(); if (type == this.types.int) return this.getInt(val); else if (type == this.types.float) return this.getFloat(val, (d != null ? d : 4)); else if (type == this.types.date) return this.getDate(val); else if (type == this.types.boolean) return this.getBool(val); return val; }, //数组操作 //希尔排序 数组、改名名、是否强制转换为数字、是否降序 orderArray: function (arr, field, fn, desc) { if (!fn) fn = function (d, f) { return d[f]; }; var n = arr.length; var h = 1; while (h < n / 3) { h = 3 * h + 1; } while (h >= 1) { for (var i = h; i < n; i++) { if (!desc) { for (j = i; j >= h && fn(arr[j], field) > fn(arr[j - h], field); j -= h) arr.swap(j, j - h); } else { for (j = i; j >= h && fn(arr[j], field) < fn(arr[j - h], field); j -= h) arr.swap(j, j - h); } } h = (h - 1) / 3; } return arr; }, /** * 显示遮罩 * @id {目标元素id} [可空] 配置项 * @unIcon {bool}[可空] 不显示loading图片 */ mask: function (id, unIcon, cls) { id = (id || "ms_ajax") + "_mask"; clearTimeout(window["hide_" + id]); cls = cls || "mask"; var $el = $("#" + id); if (!$el.length) { $(document.body).prepend("
" + (unIcon ? "" : "loading...") + "
"); } return $el; }, //移除遮罩 unMask: function (id, delay) { id = (id || "ms_ajax") + "_mask"; delay = (delay || 10); clearTimeout(window["hide_" + id]); if ($("#" + id).length) window["hide_" + id] = setTimeout("$('#" + id + "').remove();", delay); }, //寄生继承 extend: function (superClass, sub) { //var temp = Object.create(superClass.prototype); //temp.constructor = sub; //sub.prototype = temp; //sub.superClass = temp; ////var temp = Object.create(superClass.prototype);//复制父类型的原理方法 ////// superClass.call(temp); ////sub.supperClass = temp; ////temp.constructor = sub; ////sub.prototype = temp; var F = function () { }; F.prototype = superClass.prototype; sub.prototype = new F(); sub.prototype.constructor = sub; sub.uber = superClass.prototype; }, //dom是否包含特定样式类 hasClass: function (dom, cls) { return (" " + dom.className + " ").indexOf(" " + cls + " ") > -1; } }; //字典(键值对) ke.dict = function () { this.keys = []; this.values = []; this.length = 0; this.contain = function (k) { for (var i = 0; i < this.length; i++) { if (this.keys[i] == k) return true; } return false; } this.insertAt = function (k, v, index) { for (var i = 0; i < this.length; i++) { if (this.keys[i] == k) { this.values[i] = v; return; } } if (index < this.length) { var tempK = this.keys[index]; var tempV = this.values[index]; this.keys.splice(index, 1, k, tempK); this.values.splice(index, 1, v, tempV); this.length = this.keys.length; } else this.add(k, v); }, this.add = function (k, v) { for (var i = 0; i < this.length; i++) { if (this.keys[i] == k) { this.values[i] = v; return; } } this.keys.push(k); this.values.push(v); this.length = this.keys.length; } this.remove = function (k) { for (var i = 0; i < this.length; i++) { if (this.keys[i] == k) { this.values.splice(i, 1); this.keys.splice(i, 1); break; } } this.length = this.keys.length; return this; } this.get = function (k) { for (var i = 0; i < this.length; i++) { if (this.keys[i] == k) return this.values[i]; } return null; } this.set = function (k, v) { if (this.contain(k)) this.add(k, v); } this.clear = function () { this.keys = []; this.values = []; this.length = 0; return this; } this.add_range = function (keys, vals) { for (i = 0; i < keys.length; i++) { this.add(keys[i], vals[i]); } this.length = this.keys.length; return this; } } //数据交互中间件 ke.row = function (tab) { //行的ID,与行号不是一个概念 this.id = -1; this.table = tab; this.selected = false; //当前行所存储的数据,是一个对象 this.data = {}; //初始化数据行 //@data 初始化所使用的,支持数组与对象 //如果是数组则按序填充,如果是对象则进行属性名匹配填充 this.init = function (arg) { if (!$.isArray(arg)) this.data = arg; else { for (var i = 0; i < this.table.cols.length; i++) { var col = this.table.cols[i]; this.data[col.name] = arg[i]; } } return this; } //设置此行中特定列的值 //@val 目标值 @colName 需要设置的列名 this.set = function (val, colName) { var col = this.table.getColumn(colName); var old = this.get(colName); if (col) val = ke.convert(val, col.type); this.data[colName] = val; if (old != val && (val != "" || (old != null && old != ""))) this.table.change(); return this; } //取此行中特定列的值 //@colName 列名 this.get = function (colName) { var col = this.table.getColumn(colName); if (col) return ke.convert(this.data[colName], col.type); else return this.data[colName]; }, //获取格式化后的数据 this.getData = function () { var r = {}; var self = this; this.table.cols.forEach(function (col) { r[col.name] = ke.convert(self.data[col.name], col.type); }); return r; } return this; } //浅复制数据表 ke.table = function (data) { //change事件,通过重载监控其值变化事件 this.change = function () { } var column = function (colName, type) { this.name = colName; this.type = type; this.desc = null; } //列 this.cols = []; //行 this.rows = []; //数据 this.datas = []; //当前最大行ID this.maxRowId = 0; //行数 this.length = 0; //是否单选 this.singleSelect = true; //添加新列 @name 列名 @type 值类型[支持:string,bool,float,int,date] this.addColumn = function (colName, type) { var i = this.cols.get({ name: colName }, true); cl = new column(colName, type); if (i > -1) this.cols[i] = cl; else this.cols.push(cl); return cl; } //添加一行数据 //可扩展参数。如果参数只有一个,当作对象做行初始化,如果参数有多个则当作数组调用行初始化 this.addRow = function (obj) { this.datas.push(obj); var row = new ke.row(this).init(obj); row.id = this.maxRowId++; this.rows.push(row); this.length = this.rows.length; this.change(); return this; } //根据行号删除行 //@rowIndex 行号[从0开始] this.deleteRow = function (rowIndex) { if (rowIndex > -1) { this.rows.splice(rowIndex, 1); this.datas.splice(rowIndex, 1); this.length = this.rows.length; this.change(); } } //根据行ID删除行 this.deleteById = function (id) { var index = this.rows.get({ id: id }, true); this.deleteRow(index); } //获取列 this.getColumn = function (colName) { return this.cols.get({ name: colName }); } //获取包含指定值的行数组 //@val 值 @colName 列名 this.getRows = function (val, colName) { var r = []; for (var i = 0; i < this.rows.length; i++) { if (this.rows[i].get(colName) == val) { r.push(this.rows[i]); } } return r; } //获取指定行的指定列 //@rowIndex 行号 colName 列名 this.get = function (rowIndex, colName) { return this.rows[rowIndex].get(colName); } //设置指定行列的值 //@val 值 @rowIndex 行号 @colName 列名 this.set = function (val, rowIndex, colName) { this.rows[rowIndex].set(val, colName); } //根据指定函数获取符合条件的列 this.val = function (colName, fn) { for (var i = 0; i < this.rows.length; i++) { if (fn(this.rows[i].data)) return this.get(i, colName); } return null; } //删除所有数据 this.clear = function () { this.rows = []; this.datas = []; this.length = 0; } //将指定行标记为选中或非选中状态 //@rowIndex 行号 @val this.select = function (rowIndex, val) { if (this.singleSelect)//根据选择模式做不同处理 this.rows.forEach(function (d) { d.selected = false; }); this.rows[rowIndex].selected = val; } //删除所有选中的行 this.deleteSelected = function () { var arr = this.getSelected(); if (arr.length <= 0) { return $.messager.notify("请选中行后再进行删除"); } for (var i = 0; i < arr.length; i++) { this.deleteById(arr[i].id); } } //获取所有选中行 this.getSelected = function () { var r = []; this.rows.forEach(function (d) { if (d.selected) r.push(d); }); return r; } //获取第一个选中行的数据 this.getFirstSelectedData = function () { var r = this.getSelected(); return (!r.length || r[0].data); } //转换为对象数组 this.toArray = function () { var r = []; this.rows.forEach(function (row) { r.push(row.getData()); }); return r; } //载入数据 //@data {Array}数据源 @initCols{bool} 是否初始化列结构 this.load = function (data, initCols) { this.rows = []; this.datas = data; if (initCols) { this.cols = []; for (var field in data[0]) { if (!$.isFunction(field)) { this.addColumn(field); } } } for (i = 0; i < data.length; i++) { var row = new ke.row(this).init(data[i]); row.id = i; this.rows.push(row); } this.maxRowId = data.length; this.length = this.rows.length; this.change(); return this; } //转换为JSON字符串 this.toJson = function () { return JSON.stringify(this.toArray()); } //将指定字段用特定连接符连接起来 this.joinSelected = function (colName, separator) { separator = separator || ","; var str = ""; this.getSelected().forEach(function (d) { if (str != "") str += separator; str += d.data[colName]; }); return str; } //以一列一行的形式转换为值数组 this.toColsArray = function () { var r = []; for (var i = 0; i < this.cols.length; i++) { var vals = []; for (var k = 0; k < this.rows.length; k++) { vals.push(this.rows[k].data[this.cols[i].name]); } r.push(vals); } return r; }, this.orderBy = function (colName, desc) { var col = this.getColumn(colName); if (desc == null) desc = !col.desc; col.desc = desc; this.rows = ke.orderArray(this.rows, colName, function (d) { return d.get(colName); }, desc); }, //汇总某列的值 this.sum = function (colName, prepare) { var r = 0; for (var k = 0; k < this.rows.length; k++) { var val = parseFloat(this.rows[k].get(colName)); r += (prepare ? prepare(val, this.rows[k].data, k) : val); } return r; } if (data) this.load(data, true); return this; } //模板片断 ke.templateText = function (txt) { this.parts = []; var temp = ""; for (var i = 0; i < txt.length; i++) { if (txt[i] == '{') { var isDouble = false;//兼容双括号与单括号,后续逐步取消单括号 if (txt[i + 1] == '{') { isDouble = true; i++; } i++; var val = ""; if (!isDouble) { while (txt[i] != '}' && i < txt.length) { val += txt[i]; i++; } } else { while (i < txt.length && (txt[i] != '}' || txt[i + 1] != '}')) { val += txt[i]; i++; } i++; } if (temp != "") { this.parts.push(temp); temp = ""; } this.parts.push(ke.template.createFunction(val)); } else temp += txt[i]; } if (temp != "") this.parts.push(temp); this.render = function (t) { var htm = ""; this.parts.forEach(function (item) { var val = ($.isFunction(item) ? item(t) : item); if (val != null) htm += val; }); return htm; } } //脚本 ke.templateScript = function (txt) { this.script = txt; this.render = function (t) { if (t.index == 0) {//脚本标签只执行一次 var tag = document.createElement("script"); tag.innerHTML = this.script; document.body.appendChild(tag); } return ""; } } ke.templateStyle = function (txt) { this.content = txt; this.render = function (t) { if (t.index == 0) {//样式标签只执行一次 return ""; } return ""; } } //模板结点 ke.templateNode = function (node) { if (node.nodeType == 1) { if (node.tagName == "SCRIPT") this.nodes = new ke.templateScript(node.innerHTML); else if (node.tagName == "STYLE") this.nodes = new ke.templateStyle(node.innerHTML); else { this.name = node.tagName; //判断是不是自闭合标签 this.selfClose = ke.templateNode.selfCloseTags.indexOf(this.name) > -1; this.attributes = []; this.nodes = []; this.condition = null; this.foreach = null; if (node.attributes) { //解析属性 for (var k = 0; k < node.attributes.length; k++) { var attr = node.attributes[k]; var n = attr.name; var v = attr.value; if (n == "ke-if") this.condition = ke.template.createFunction(v); else if (n == "ke-foreach") this.foreach = ke.template.createFunction(v); else this.attributes.push({ name: n, fn: new ke.templateText(attr.value) }); } } for (var i = 0; i < node.childNodes.length; i++) { this.nodes.push(new ke.templateNode(node.childNodes[i])); } this.create = function (tmpl) { var htm = "<" + this.name; this.attributes.forEach(function (item) { htm += " " + item.name + "=\"" + item.fn.render(tmpl) + "\""; }); if (this.selfClose) return htm += " />"; else { htm += ">"; this.nodes.forEach(function (item) { htm += item.render(tmpl); }); htm = htm + ""; return htm; } }, this.render = function (t) { var htm = ""; if (!this.condition || this.condition(t)) { if (this.foreach) { var items = this.foreach(t) || []; var preForData = t.forData; var preForIndex = t.forIndex; for (var i = 0; i < items.length; i++) { t.forData = items[i]; t.forIndex = i; htm += this.create(t); } t.forData = preForData; t.forIndex = preForIndex; } else htm += this.create(t); } return htm; } } } else this.nodes = new ke.templateText(node.textContent); if (!this.render) this.render = function (t) { return this.nodes.render(t); } } ke.templateNode.selfCloseTags = ["META", "BASE", "BR", "HR", "IMG", "INPUT", "COL", "FRAME", "LINK", "AREA", "PARAM", "OBJECT", "EMBED", "KEYGEN", "SOURCE"]; /* * 模板 * 模板内容可使用 t.data 或者简写 d 获取到当前所在的行对象,使用 * 使用 t.index 获取到所在的行号(从0开始) * 使用 t.forData 获取 ke-for 循环主体下的行 * 使用 t.forIndex 获取 ke-for 循环主体下的行号 */ ke.template = function (htm) { this.nodes = []; this.foreach = {}; this.data = null; this.index = -1; this.forData = null; this.forIndex = -1; this.prase = function (htm) { var r = ""; for (var i = 0; i < htm.length; i++) {//检查script与 style if (htm[i] == '<') { if (htm.substr(i, 8) == ""); this.nodes.push(new ke.templateScript(htm.substr(i + 8, e - i - 8))); i = e + 9; continue; } else if (htm.substr(i, 7) == ""); this.nodes.push(new ke.templateStyle(htm.substr(i + 7, e - i - 7))); i = e + 8; continue; } } r += htm[i]; } return $.parseHTML("
" + r + "
"); // return new DOMParser().parseFromString("
" + r + "
", "text/xml"); } this.render = function (d, i) { this.data = d; this.index = i; var htm = ""; for (var i = 0; i < this.nodes.length; i++) htm += this.nodes[i].render(this); return htm; } this.renderForeach = function (arr) { var r = ""; for (var i = 0; i < arr.length; i++) { r += this.render(arr[i], i); } return r; } var xml = htm; if (typeof htm == "string") { xml = this.prase(htm); xml = xml[0]; } for (var i = 0; i < xml.childNodes.length; i++) { var temp = new ke.templateNode(xml.childNodes[i]); this.nodes.push(temp); } // delete xml; } ke.template.createFunction = function (val) { var reg = /^([a-zA-Z0-9_]){1,30}$/ val = val.trim(); if (val == "rowIndex") val = "return t.index"; else if (!reg.test(val)) //自定义脚本 { if (val.charAt(val.length - 1) == ";") val = val.substr(0, val.length - 2); var pos = val.lastIndexOf(";"); if (pos < 0) val = "return " + val; else val = val.substring(0, pos + 1) + " return " + val.substr(pos + 1, val.length - pos - 1); val = "var d=t.data;" + val; } else val = "return t.data." + val; return new Function("t", val + ";"); } //根据id生成模板 ke.template.get = function (id) { var el = ke.get(id); if (el.tagName == "SCRIPT") return new ke.template(el.innerHTML); else return new ke.template(el); }