<html> <head> <style type = "text/css"> .grid {borda: 1px Solid #808080; espaçamento de borda: 0; Largura: 500px; colapso da borda: colapso} .Grid th, .Grid td {borda: 0; Text-align: Center;} .Grid tr {Hight: 25px; altura da linha: 25px;} .Grid tr.odd {background:#d0d0d0} .grid .btn {width: 80px; Text-align: Center} </style> <script type = "text/javascript"> (function () {// var util = {a seguir: função a seguir (ele) {if (ele) {var n = elexnextSibling; if (n && n.nodetype == 1) {return n;} JSON! Array.Prototype.slice.Call (Obj, 0); "Undefinido") {Result.push (Target); deslocamento (ele) {var resultado = {top: 0, esquerda: 0}; (ele.style.top || "0"). Substitua (/[^/d]+$/, "")); resultado.left = número (ele.offsetleft || (ele.style.left || "0"). substituir (/[^/d]+$/, "")); if (ele.parentNode) {var r = deslocamento (ele.parentnode); resultado.top += r.top; resultado.left += r.left; } resultado de retorno; }}; // 事件处理 var event = {on: function (eventType, fn) {var element = this; if (this.addeventListener) {this.addeventListener (EventType, fn, false); } else if (this.attachevent) {// 将事件缓冲到该标签上, 已解决 已解决 指向 指向 janela (现 fn 内 this 指向 elemento) 和移除匿名事件问题 var _eventRef = '_'+EventType+'Eventref'; if (! Element [_eventRef]) {elemento [_eventRef] = []; } var _eventRefs = elemento [_eventRef]; Índice var; para (índice em _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); }}, remova: function (eventType, fn) {var element = 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; para (índice em _eventRefs) {if (_eventRefs [index] ['realfn'] == fn) {nestfn = _eventRefs [index] ['nagefn']; if (index == _ EventRefs.Length-1) {elemento [_EventRef] = _ EventRefs.slice (0, index); } else {element [_eventRef] = _ eventrefs.slice (0, index) .concat (_eventrefs.slice (index+1, _eventrefs.lengths-1)); } quebrar; }} if (Nestfn) {element.Detachevent ('on'+EventType, Nestfn); }}}}; // extend (function () {// 删除数组中指定下标出的元素 Array.prototype.Remove = function (index) {var o = this [index]; if (typeof o! == "undefined") {if (index == 0) {this.shift ();} se (index ===}, this) (this); AR2 = INDEX (INDICE); i = 0; i <this.length; i ++) {if (time this.__data[this.length++] = obj; }, get:function(index){ return this.__data[index]; }, remove:function(index){ var obj = this.__data[index]; if(typeof obj !== "undefined"){ this.length--; } delete this.__data[index]; }, clear:function(){ this.__data = {}; this.length = 0;}, cada: função (fn) {var index = 0; para (var k neste .__ dados) {if (k && typeof este .__ dados [k]! == "indefinido") {fn.call (this .__ dados [k], index ++); }}}, ToArray: function () {var arr = []; this.each (function () {arr.push (this);}); retornar arr; }}; }) (); // var grid = this.grid = function (tabela, opções) {grid.prototype._init.call (this, tabela, opções); } grid.prototype = {_init: function (tabela, opções) {if (typeof tabela === "indefinido" ||! tabela) {throw "tabela é indefinida ou nula"; } if (tabela.nodetype! == 1 ||!/^Tabela $/i.test (tabela.TagName)) {throw "tabela deve ser 'tabela' elemento."; } tabela.guid = ++ grid.guid; este .__ cache = {}; var self = this; var cabeçalho = this .__ cache ["cabeçalho"] = loadHeader (); // cabeçalho this .__ root = cabeçalho.parentnode; var templaterow = this .__ cache ["modelo"] = loadtemplate (); // 模板行 this .__ cache ["dataFormat"] = loadDataFormat (); // 数据模板 this .__ cache ["Dataws"] = nova coleção (); // this. este .__ SaveContainer = CreateSaveButton (); // 保存按钮 this .__ cache ["commandHandles"] = {// comando manifesta removero: function () {var rowindex = this.getAttribute ("index"); self.removerow.apply (self, [rowindex]); }, newline: function () {self.newline (); }}; este .__ regCommand = function (commandName, linha) {// 注册 comando if (linha) {var arg = row.getAttribute ("index"); this.setAtAttribute ("índice", arg || false); } this.CommandName = CommandName; Event.remove.call (isto, "clique", exec); Event.on.call (isto, "clique", exec); } this .__ removerowCallback = function () {// 改变行的背景样式 var lobs = this .__ cache ["DATAROWS"]; var customCache = this .__ cache ["customCache"]; var Arr = linhas.ToArray (), Dataarr = []; var rowindex, linha, dados; linhas.clear (); arr.each (function (i) {rowIndex = this.getAttribute ("index"); data = customCache.get (rowIndex); dataarr.push (data); this.setAttribute ("index", i.tostring ()); linhas; if (! // sodd/s | /sodd$/g.test (this.className)) {this.className = (this.className || "") + "ímpar"; this.className.replace (// sodd/s |/sodd $/g ""); customCache.clear (); dataarr.each (function () {customcache.add (this);}); } // 事件处理 Opções = opções || {}; this.ondatabinding = options.ondatabinding || this.ondatabinding; this.OnRowBinding = Options.onRowBinding || this.onrowbinding; this.onRowbinDed = options.onRowBedin || this.onRowbinDed; função loadHeader () {var tr = tabela.firstChild; if (tr && tr.nodetype! = 1) {tr = util.next (tr); } if (!/tr/i.test (tr.TagName)) {// 如果第一个元素不是 tr , 则浏览器支持 tody tr = tr.firstchild; if (tr.nodeType! = 1) {tr = util.next (tr); }} retornar tr; } function loadTemplate () {tr = util.next (cabeçalho); // 获取模板行 return tr; } função loadDataFormat () {var modes = templaterow.childnodes, ele, dados, resultado = {}, att; nós = util.parsearray (nós); modes.each (function (i) {ele = this; if (ele && ele.nodetype == 1) {att = ele.data || ele.getAttribute ("data"); if (att) {data = util.parsejson (att); eLe.field = data.field; resultado; resultado de retorno; } função createSaveButton () {var div = document.createElement ("div"); div.style.Position = "Absolute"; div.style.display = "nenhum"; div.style.width = "Auto"; var btn = document.createElement ("botão"); btn.innerhtml = btn.innerText = btn.textContent = btn.value = "salvar"; tente {btn.type = "Button"; } catch (e) {btn.setAttribute ("tipo", "botão"); } div.appendChild (btn); var BtNCancel = Document.CreateElement ("Button"); btncancel.innerhtml = btncancel.innertext = btncancel.textContent = btncancel.value = "cancel"; tente {btncancel.type = "Button"; } catch (e) {btncancel.setAttribute ("tipo", "botão"); } div.appendChild (btncancel); document.body.appendChild (div); Event.on.call (btn, "clique", function () {self.save ();}); Event.on.call (btncancel, "clique", function () {div.style.display = "nenhum"; if (self .__ editrow) {self .__ editrow.parentnode.RemoveChild (self .__ editrow); self .__ editrow = null;}}); retornar div; } function Exec () {if (self .__ editrow) {// 如果当前处于编辑模式 , 则禁用所有 comando return; } var commandName = this.CommandName; var manipulador = self .__ cache ["commandHandles"] [commandName]; if (manipulador) {handler.call (this); }} // 去除模板行 templaterow.parentnode.removechild (Templaterow); // 处理表格中的 comando 事件 var elements = header.getElementsByTagName ("*"); elementos = util.parsearray (elementos); Elements.Each (function () {if (this.nodEType === 1) {var commandName = this.Command || this.getAttribute ("command"); se (commandName) {self .__ regCommand.Call (this, commandName, header);}}}); }, // BANDing Bind: function (dados) {this.clear (); if (data && data.length> 0) {var self = this; data.each (function () {self.append (this);}); }}, // 清理表 , 删除所以除 Cabeçalho 以外的数据行 claro: function () {var lobs = this .__ cache ["dataarows"], linha; linhas.each (function () {linha = this; if (linha) {row.parentnode.removeChild (linha);}}); linhas.clear (); // 清理 linhas}, // 删除指定的行 removero: function (rowIndex) {var lobs = this .__ cache ["datarows"]; var linha = linhas.get (rowIndex); if (linha) {var data = this .__ cache ["customCache"] [rowIndex]; row.parentnode.removeChild (linha); linhas.Remove (RowIndex); // 通知用户数据行被移除 if (util.isfunction (this.onRowRemoved)) {this.onRowRemoved (dados, linha); }} this .__ removerowCallback (); }, // 添加 行 Appender: function (dados) {if (! Data) {return; } var modelo = this .__ cache ["modelo"]; var linhas = this .__ cache ["datarows"]; var rowindex = linhas.length; var tr = template.cloneNode (); var customCache = this .__ cache ["customCache"]; customCache.add (dados); // 将数据行添加到 tabela this .__ root.appendChild (tr); var self = this; var td, // 数据单元格 dataFormat, // 数据格式化器 value; // 单元格中的给定的数据 tr.setAttribute ("index", rowindex.toString ()); // 更改样式 if (rowIndex % 2 == 1) {tr.className = (tr.className || "") + "ímpar"; } // 通知 行数据绑定开始 if (util.isfunction (this.onRowBinding)) {this.onRowBinding (rowindex, tr); } var templatetd = modelo.firstChild; while (templatetd) {td = templatetd.cloneNode (true); tr.appendChild (TD); if (td.nodetype == 1 && templatetd.field) {dataFormat = this .__ cache ["dataFormat"] [templatetd.field]; td.removeattribute ("dados"); td.field = templatetd.field; valor = dados [dataFormat.field]; // 通知单元格数据绑定事件 value = this.ondatabinding (dataFormat.field, value, td, dados); if (value! == false) {// 如果返回 false , switch (dataFormat.render) {case "innerhtml": td.innerhtml = typeof value == "indefinido" || valor == nulo? "" : valor; quebrar; Caso "InnerText": padrão: td.innerText = td.textContent = typeof value == "indefinido" || valor == nulo? "" : valor; quebrar; }}} templatetd = templatetd.nextsibling; } linhas.add (tr); // 处理 comando var elements = tr.getElementsByTagName ("*"), ele, att; elementos = util.parsearray (elementos); Elements.Each (function () {ele = this; if (ele.nodEType == 1 && (ele.Command || ele.getAttribute ("command"))) {att = ele.Command || ele.getAttribute ("comando"); self .__ RegCommand.call (et att, att); // 通知 行数据绑定完成 if (util.isfunction (this.onRowbiEd)) {this.onRowbinGed (rowindex, tr); }}, // 手动产生新的输入行 newline: function () {if (this .__ editrow) {// 如果当前有存在编辑行 , 则直接返回 , 每次最多限制编辑一行数据 return; } var modelo = this .__ cache ["modelo"]; var row = this .__ editrow = model.cloneNode (false); 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") {textAtea = document.createElement ("texttarea"); } else {textarea = document.createElement ("input"); textarea.type = "text"; } textarea.style.display = "nenhum"; td.appendChild (textarea); textarealist.push (textarea); }} templatetd = templatetd.nextsbling; } // tabela tabela esta .__ root.appendChild (linha); var a altura = row.offsetHeight, width = row.offsetWidth, offset = util.offset (linha); textarealist.each (function () {this.style.Height = (0,8 * altura) + "px"; this.style.width = (0,8 * this.parentnode.offsetWidth) + "px"; var esquerdo = offset.left + largura + 5; var top = offset.top; this.__SaveContainer.style.top = top + "px"; este .__ SaveContainer.style.left = esquerda + "px"; este .__ SaveContainer.style.Height = this .__ SaveContainer.style.LineHeight = altura + "px"; este .__ SaveContainer.style.display = "bloco"; }, // 保存手动产生的数据行数据 salvar: function () {if (! This .__ editrow) {return; } var row = this .__ editrow; var td = row.firstchild; var dados = {}; while (td) {if (td.nodetype === 1 && td.field) {var dataFormat = this .__ cache ["dataFormat"] [td.field]; var textarea = nulo; if (dataFormat.render == "innerhtml") {textAea = td.getElementsByTagName ("textarea") [0]; } else {textarea = td.getElementsByTagName ("input") [0]; } value = textarea.value; switch (dataFormat.datatype) {case "número": value = util.trim (value); valor = número (value.Length == 0? 0: valor); quebrar; Padrão: quebra; } dados [td.field] = value; } td = td.nextsibling; } this .__ editrow.parentnode.removeChild (this .__ editrow); este .__ editrow = nulo; este .__ SaveContainer.style.display = "nenhum"; // 通知用户正在保存数据 if (util.isfunction (this.onsaving)) {this.onsaving (dados); } this.append (dados); }, getRowData: function (rowIndex) {return this .__ cache ["customCache"]. get (rowindex); }, // 数据绑定到指定 célula 时的事件 OnDatabinding: function (campo, valor, célula, dados) {Return Value; }, // 当数据行绑定开始时的事件 OnRowBinding: function (rowIndex, linha) {}, // 当数据行绑定完成时的事件 //@param Row {dom elemento tr} onrowbinDeen: function (rowindex, linha) {}, // 当编辑的数据被保存时的事件 em queda: function (dados) {}, // 当数据行被移除时的通知事件 当数据行被移除时的通知事件 当数据行被移除时的通知事件 当数据行被移除时的通知事件rowRemoved: function: grid.guid = 0; }) (); </script> </head> <body> <tabela id = "tabela_demo"> <tr> <th> id </th> <th> nome </th> <th> descrição </th> <th> <botão tipo = "button" command = "newline"> nova linha </button> </th> </tr> <tr> " data data = '{"campo": "id", "datatype": "número", "render": "innerText"}'> 1 </td> <td data = '{"field": "name", "datatype": "string", "render": "InnerText"}'> funcionando Data = '{"campo": "Descrição", "Datatype": "String", "Render": "Innerhtml"}'> WorkingService </td> <td> <button type = "Button" Command = "Removerow"> Excluir </butão> </td> </tr> </tabela> <argd type = "> text/jav"/jav = " document.getElementById ("tabela_demo"); var g = nova grade (tabela, {ondatabinding: function (campo, value) {return value;}, onrowbined: function (rowindex, linha) {}}); g.bind ([{id: 0, nome: "kilin"}, {id: 1, nome: "kilin1"}, {id: 2, nome: "kilin2"}, {id: 3, nome: "kilin3"}]); </script> </body> </html>