<html> <head> <style type = "text/css"> .grid {border: 1px sólido #808080; espaciado fronterizo: 0; Ancho: 500px; border-colapso: colapso} .grid th, .grid td {border: 0; text-align: center;} .grid tr {altura: 25px; line-height: 25px;} .grid tr.odd {fondo:#d0d0d0} .grid .btn {ancho: 80px; text-align:center} </style> <script type="text/javascript"> (function(){ // var util = { next:function next(ele){ if(ele){ var n = ele.nextSibling; if(n && n.nodeType === 1){ return n; } return next(n); } }, parseJSON:function(str){ if(typeof JSON !== "undefined"){ return JSON.parse(str); } return eval("("+str+")"); }, parseArray:function(obj){ if(!obj){ return obj; } var result = []; if(typeof obj.length !== "undefined"){ try{ var arr = Array.prototype.slice.call(obj,0); resultado = arr;} catch (e) {for (var i = 0; i <obj.length; i ++) {try {var target = obj [i]; } Resultado de retorno; if (! ele || ele.nodeType! == 1) {return resultado; (ele.style.top || "0"). reemplazar (/[^/d]+$/, "")); result.left = number (ele.offsetleft || (ele.style.left || "0"). reemplazar (/[^/d]+$/, "")); if (ele.parentnode) {var r = offset (ele.parentnode); resultado.top += r.top; resultado.left += r.left; } resultado de retorno; }}; // 事件处理 var event = {on: function (eventType, fn) {var elemento = this; if (this.addeventListener) {this.addeventListener (eventType, fn, false); } else if (this.attachevent) {// 将事件缓冲到该标签上, 已解决 esta ventana 指向 指向 (现 fn 内 este elemento 指向) 和移除匿名事件问题 var _eventref = '_'+eventType+'eventRef'; if (! Element [_EventRef]) {elemento [_EVENTREF] = []; } var _EventRefs = elemento [_EVENTREF]; índice var; for (índice en _EventRefs) {if (_EventRefs [index] ['Realfn'] == fn) {return; }} var nestfn = function () {fn.apply (elemento, argumentos); }; elemento [_EventRef] .push ({'Realfn': fn, 'nestfn': nestfn}); element.attachevent ('on'+eventtype, nestfn); }}, eliminar: function (eventType, fn) {var elemento = this; if (this.removeEventListener) {this.RemoveEventListener (eventType, fn, false); } else if (this.detachevent) {var _eventref = '_'+eventtype+'eventRef'; if (! Element [_EventRef]) {elemento [_EVENTREF] = []; } var _EventRefs = elemento [_EVENTREF] Var index; var nestfn; for (índice en _EventRefs) {if (_EventRefs [index] ['Realfn'] == fn) {nestfn = _EventRefs [index] ['nestfn']; if (index == _ eventRefs.length-1) {elemento [_EventRef] = _ eventRefs.slice (0, index); } else {elemento [_EventRef] = _ eventRefs.slice (0, índice) .concat (_eventRefs.slice (índice+1, _eventrefs.length-1); } romper; }} if (nestfn) {element.detachevent ('on'+eventtype, nestfn); }}}}; // extend (function () {// 删除数组中指定下标出的元素 array.prototype.remove = function (index) {var o = this [index]; if (typeOf o! == "undefinado") {if (index == 0) {this.shift ();} else if (index === this.length - 1) {this.pop ();} el más {var flil arr2 = this.slice (índice+1); i = 0; i <this.length; i ++) {if (typeOf este [i]! == "Undefinado") {fn.call (this [i], i); this .__ data [this.length ++] = obj; = 0; for (var k en this .__ data) {if (k && typeof this .__ data [k]! == "indefinido") {fn.call (this .__ data [k], index ++); }}}, toArray: function () {var arr = []; this.each (function () {arr.push (this);}); regresar arr; }}; }) (); // var grid = this.grid = function (tabla, opciones) {grid.prototype._init.call (this, table, opciones); } grid.prototype = {_init: function (table, options) {if (typeof table === "Undefined" || } if (table.nodeType! == 1 || } table.guid = ++ grid.guid; this .__ cache = {}; var self = this; encabezado var = this .__ cache ["encabezado"] = loadHeader (); // encabezado this .__ root = header.parentnode; var templaterow = this .__ cache ["Template"] = loadTemplate (); // 模板行 this .__ cache ["dataFormat"] = loadDataFormat (); // 数据模板 this .__ cache ["datarows"] = nueva colección (); // 数据行 this .__ cache ["customCache"] = nueva colección (); // 用户缓存数据 this .__ .__ .__ .__ NEW COLECED (); this .__ saveContainer = CreateSaveButton (); // 保存按钮 this .__ Cache ["CommandHandles"] = {// Command Handels removerow: function () {var rowIndex = this.getAttribute ("index"); self.removerow.apply (self, [rowIndex]); }, newline: function () {self.newline (); }}; this .__ regCommand = function (commandName, row) {// 注册 comando if (fila) {var arg = row.getAttribute ("index"); this.SetAttribute ("índice", arg || false); } this.commandName = commandName; Event.remove.call (esto, "hacer clic", exec); Event.on.call (this, "haga clic", exec); } this .__ removeroWCallback = function () {// 改变行的背景样式 var filas = this .__ cache ["datarars"]; var customCache = this .__ cache ["customCache"]; var arr = shows.toarray (), dataRarr = []; var rowindex, fila, datos; filas.clear (); arr.each (function (i) {rowIndex = this.getAttribute ("index"); data = customCache.get (rowIndex); dataarr.push (data); this.setattribute ("index", i.ToString ()); Rows.add (this); if (i % 2 == 1) {/// 基数行 基数行 基数行 基数行 基数行 基数行 基数行 基数行 基数行 基数行 基数行 基数行 基数行if (! // sodd/s | /sodd$/g.test (this.classname)) {this.classname = (this.classname || "") + "impar"; this.classname.replace (// sodd/s |/sodd $/g, "); CustomCache.Clear (); dataarr.each (function () {customCache.add (this);}); } // 事件处理 Opciones = Opciones || {}; this.ondatabinding = options.ondatabinding || this.databinding; this.onrowbinding = options.onrowbinding || this.enrowbinding; this.onrowbindin = options.onrowbindind || esto. function loadHeader () {var tr = table.firstchild; if (tr && tr.nodetype! = 1) {tr = util.next (tr); } if (!/tr/i.test (tr.tagname)) {// 如果第一个元素不是 tr , 则浏览器支持 tbody tr = tr.firstchild; if (tr.nodeType! = 1) {tr = util.next (tr); }} return tr; } function loadTemplate () {tr = util.next (encabezado); // 获取模板行 return tr; } function loadDataFormat () {var nodos = templaterow.childNodes, ele, data, resultado = {}, attr; nodos = util.parsearray (nodos); nodos.each (function (i) {ele = this; if (ele && ele.nodeType == 1) {attr = ele.data || ele.getattribute ("data"); if (attr) {data = util.parsejson (attr); ele.field = data.field; resultado [ele.field] = data;}}}); resultado de retorno; } función createSaveButton () {var div = document.createElement ("div"); div.style.position = "Absolute"; div.style.display = "Ninguno"; div.style.width = "auto"; var btn = document.createElement ("botón"); btn.innerhtml = btn.inntext = btn.TextContent = btn.value = "salvar"; intente {btn.type = "botón"; } catch (e) {btn.setAttribute ("type", "botón"); } div.appendChild (btn); var btncancel = document.createElement ("botón"); btncancel.innerhtml = btncancel.inntext = btncancel.textContent = btncancel.value = "cancelar"; intente {btncancel.type = "botón"; } catch (e) {btncancel.setattribute ("type", "botón"); } div.appendChild (btncancel); document.body.appendChild (div); Event.on.call (btn, "hacer clic", function () {self.save ();}); Event.on.call (btncancel, "hacer clic", function () {div.style.display = "none"; if (self .__ editrow) {self .__ editrow.parentnode.removechild (self .__ editrow); self .__ editrow = null;}}); regreso div; } function exec () {if (self .__ Editrow) {// 如果当前处于编辑模式 , 则禁用所有 则禁用所有 comando return; } var comandoName = this.commandName; var handler = self .__ cache ["CommandHandles"] [CommandName]; if (handler) {handler.call (this); }} // 去除模板行 TEMPLATEROW.PARENTNODE.REMOVECHILD (TEMPLATEROW); // 处理表格中的 comando 事件 var elements = header.getElementsByTagName ("*"); elementos = util.parsearray (elementos); Elements.each (function () {if (this.nodeType ==== 1) {var comandante = this.command || this.getAttribute ("comandante"); if (commandName) {self .__ regCommand.call (this, commandName, Header);}}}); }, // billing bind: function (data) {this.clear (); if (data && data.length> 0) {var self = this; data.each (function () {self.append (this);}); }}, // 清理表 , 删除所以除 encabezado 以外的数据行 claro: function () {var filas = this .__ cache ["datarows"], fila; Rows.each (function () {row = this; if (row) {row.ParentNode.RemoVeChild (fila);}}); ROWS.CLEAR (); // 清理 filas}, // 删除指定的行 removerow: function (rowIndex) {var filas = this .__ cache ["dataRows"]; var fila = shows.get (rowIndex); if (fila) {var data = this .__ cache ["customCache"] [rowIndex]; Row.ParentNode.RemoVechild (fila); filas.remove (RowIndex); // 通知用户数据行被移除 if (Util.Isfunction (this.onrowremoved)) {this.onrowremoved (data, fila); }} this .__ RemoverOWCallback (); }, // 添加 行 append: function (data) {if (! Data) {return; } plantilla var = this .__ cache ["plantilla"]; var filas = this .__ cache ["dataRows"]; var rowIndex = shows.length; var tr = TEMPLATE.CLONENEDE (); var customCache = this .__ cache ["customCache"]; customCache.add (datos); // 将数据行添加到 Tabla this .__ root.appendChild (tr); var self = this; var td, // 数据单元格 dataFormat, // 数据格式化器 valor; // 单元格中的给定的数据 tr.setAttribute ("index", rowIndex.ToString ()); // 更改样式 if (rowIndex % 2 == 1) {tr.classname = (tr.classname || "") + "impar"; } // 通知 行数据绑定开始 行数据绑定开始 if (util.Isfunction (this.onrowbinding)) {this.onrowbinding (rowIndex, tr); } var templateTd = Template.firstChild; while (TempLatetd) {td = TempLatetd.clonenode (true); Tr.AppendChild (TD); if (td.nodeType == 1 && templateTd.field) {dataFormat = this .__ cache ["dataFormat"] [templateTd.field]; td.removeattribute ("datos"); td.field = TempLatetd.field; valor = data [dataFormat.field]; // 通知单元格数据绑定事件 valor = this.ondatabinding (dataFormat.field, valor, td, data); if (value! == false) {// 如果返回 false , 则不用做赋值操作 switch (dataFormat.render) {case "innerhtml": td.innerhtml = typeof value == "indefinido" || valor == nulo? "" : valor; romper; caso "Innertext": predeterminado: td.inntext = td.TextContent = typeof value == "Undefined" || valor == nulo? "" : valor; romper; }}} TEMPLATETD = TEMPLATETD.NEXTSIBLE; } filas.add (tr); // 处理 comando var elements = tr.getElementsBytagName ("*"), ele, attr; elementos = util.parsearray (elementos); Elements.each (function () {ele = this; if (ele.nodeType == 1 && (ele.command || ele.getattribute ("comandante"))) {attr = ele.command || ele.getattribute ("comando"); self .__ regCal.call (ele, attr, tr);}}); // 通知 行数据绑定完成 行数据绑定完成 if (Util.Isfunction (this.onrowbinded)) {this.onrowbinded (rowIndex, tr); }}, // 手动产生新的输入行 newline: function () {if (this .__ editrow) {// 如果当前有存在编辑行 , 则直接返回 每次最多限制编辑一行数据 每次最多限制编辑一行数据 return; } plantilla var = this .__ cache ["plantilla"]; var fila = this .__ editrow = Template.clonenode (falso); var templatetd = Template.firstChild; var textarealist = []; while (TempLatetd) {td = TempLatetd.clonenode (true); Row.appendChild (TD); if (td.nodeType == 1) {if (templateTd.field) {td.field = templateTd.field; td.innerhtml = ""; var dataFormat = this .__ cache ["dataFormat"] [TempLatetd.field]; var textARea = nulo; if (dataFormat.render == "innerhtml") {textAREA = document.createElement ("textAREA"); } else {textArea = document.createElement ("entrada"); textAREA.Type = "Text"; } textAREA.style.display = "Ninguno"; TD.AppendChild (TextAREA); textarealist.push (textAREA); }} TEMPLATETD = TEMPLATETD.NEXTSIBLE; } // 将数据行添加到 tabla this .__ root.appendChild (fila); var altura = fila textreealist.each (function () {this.style.height = (0.8 * altura) + "px"; this.style.width = (0.8 * this.parentnode.offsetwidth) + "px"; this.style.display = "";}); var izquierda = offset.left + ancho + 5; var top = offset.top; this.__saveContainer.style.top = top + "px"; this .__ saveContainer.style.left = izquierda + "px"; this .__ saveContainer.style.Height = this .__ saveContainer.style.lineheight = altura + "Px"; this .__ saveContainer.style.display = "bloque"; }, // 保存手动产生的数据行数据 save: function () {if (!__ Editrow) {return; } var fila = this .__ editrow; var td = row.firstchild; var data = {}; while (td) {if (td.nodeType ==== 1 && td.field) {var dataFormat = this .__ cache ["dataFormat"] [td.field]; var textARea = nulo; if (dataFormat.render == "InnerHtml") {textArea = td.getElementsByTagName ("TextArea") [0]; } else {textAea = td.getElementsBytagName ("entrada") [0]; } valor = textAREA.Value; switch (dataFormat.datatype) {case "número": value = util.trim (valor); valor = número (valor.length == 0? 0: valor); romper; predeterminado: ruptura; } datos [td.field] = valor; } td = td.nextsibling; } this .__ editrow.parentnode.removechild (this .__ editrow); this .__ editrow = null; this .__ saveContainer.style.display = "Ninguno"; // 通知用户正在保存数据 if (util.Isfunction (this.onsaving)) {this.onsaving (data); } this.append (datos); }, getRowData: function (rowIndex) {return this .__ cache ["customCache"]. get (rowIndex); }, // 数据绑定到指定 Cell 时的事件 onDatabinding: función (campo, valor, celda, datos) {valor de retorno; }, // 当数据行绑定开始时的事件 onRowBinding: function (rowIndex, fila) {}, // 当数据行绑定完成时的事件 //@param row {domem Element tr} onrowbinding: function (rowIndex, row) {}, // 当编辑的数据被保存时的事件 onsaving: function (data) {}, // 当数据行被移除时的通知事件 onrowrowrowrowRemoved (data) {}}; grid.guid = 0; }) (); </script> </head> <body> <table id = "table_demo"> <tr> <th> id </th> <th> name </th> <th> Descpription </th> <th> <botte type = "button" command = "Newline"> nueva línea </botter> </th> </tr> <tr> <td data = '' {"campo": "id", "DataType": "Número", "Render": "Innertext"} '> 1 </td> <td data =' {"campo": "name", "DataType": "String", "Render": "Inn -text"} '> WorkingService </td> <td <td <td data = '{"campo": "Descripción", "DataType": "String", "Render": "InnerHtml"}'> WorkingService </td> <td> <button type = "button" command = "removerow"> Eliminar </botón> </td> </tr> </table> <script type = "text/javaScript"> var table = document.getElementById ("table_demo"); var g = new Grid (table, {onDatabinding: function (campo, valor) {value de retorno;}, onrowbinding: function (rowIndex, row) {}}); G.Bind ([{{id: 0, nombre: "kilin"}, {id: 1, nombre: "kilin1"}, {id: 2, nombre: "kilin2"}, {id: 3, nombre: "kilin3"}]); </script> </body> </html>