<html> <éadfr> <style type = "text / css"> .grid {border: 1px solide # 808080; Espacement des bordures: 0; Largeur: 500px; Border-Collapse: effondrement} .grid th, .grid td {border: 0; Text-Align: Centre;} .grid tr {hauteur: 25px; line-height: 25px;} .grid tr.odd {background: # d0d0d0} .grid .btn {width: 80px; Text-Align: Center} </ Style> <Script Type = "Text / JavaScript"> (fonction () {// var util = {next: function next (ele) {if (ele) {var n = ele.nextsibling; if (n && n.nodetype === 1) {return n;} return (n);}}, parsejson: furet {si JSON! == "Undefined") {return json.parse (str);} return eval ("(" + str + ")"); Array.prototype.slice.call (obj, 0); "Undefined") {Result.Push (Target); offset (ele) {var result = {top: 0, gauche: 0}; (ele.style.top || "0"). remplacer (/ [^ / d] + $ /, "")); résultat.left = nombre (ele.offsetleft || (ele.style.left || "0"). Remplace (/ [^ / d] + $ /, "")); if (ele.parentNode) {var r = offset (ele.parentNode); résultat.top + = r.top; résultat.left + = r.left; } Retour Résultat; }}; // 事件处理 var event = {on: function (EventType, fn) {var element = this; if (this.addeventListener) {this.addeventListener (EventType, fn, false); } else if (this.attachevent) {// 将事件缓冲到该标签上, 已解决 this 指向 window (现 fn 内 this 指向 element) 和移除匿名事件问题 var _eventRef = '_' + eventType + 'EventRef'; if (! element [_eventRef]) {élément [_eventRef] = []; } var _eventRefs = élément [_EventRef]; var index; for (index in _eventRefs) {if (_eventRefs [index] ['realfn'] == fn) {return; }} var nestfn = function () {fn.apply (élément, arguments); }; élément [_eventRef] .push ({'realfn': fn, 'nestfn': nestfn}); element.Attachevent ('on' + EventType, nestFn); }}, supprimer: fonction (eventType, fn) {var element = this; if (this.reMoveEventListener) {this.reMoveEventListener (EventType, fn, false); } else if (this.detachevent) {var _eventRef = '_' + EventType + 'EventRef'; if (! element [_eventRef]) {élément [_eventRef] = []; } var _eventRefs = élément [_eventRef] var index; var nestfn; for (index in _eventRefs) {if (_eventRefs [index] ['realfn'] == fn) {nestfn = _eventRefs [index] ['nestfn']; if (index == _ EventRefs.Length-1) {élément [_EventRef] = _ EventRefs.slice (0, index); } else {element [_eventRef] = _ EventRefs.slice (0, index) .Concat (_eventRefs.slice (index + 1, _eventRefs.Length-1)); } casser; }} if (nestfn) {element.detachevent ('on' + eventType, nestfn); }}}}; // extension (function () {// 删除数组中指定下标出的元素 array.prototype.remove = function (index) {var o = this [index]; if (typeof o! == "Undefined") {if (index == 0) {this.shift ();} else if (index === this.length - 1) {this.pop ();} else {var arred = this.SLice (0, this.pop ();} arr2 = this.slice (index + 1); i = 0; i <this.length; i ++) {if (typeof this [i]! == "Undefined") {fn.call (this [i], i);}}} // var collection = this.collection = function () {this .__ data = {}; Cet .__ Données [LETTRAPHESSEMENT = 0;}, chaque: fonction (fn) {var index = 0; pour (var k dans ce .__ data) {if (k && typeof this .__ data [k]! == "Undefined") {fn.call (this .__ data [k], index ++); }}}, toArray: function () {var arr = []; this.each (function () {arr.push (this);}); retour arr; }}; }) (); // var grid = this.grid = fonction (table, options) {grid.prototype._init.call (this, table, options); } grid.prototype = {_Init: fonction (table, options) {if (typeof table === "Undefined" ||! Table) {throw "La table est indéfinie ou nul"; } if (table.NodeType! == 1 ||! / ^ TABLE $ / i.test (table.tagname)) {thord "Table doit être 'Table' Element."; } table.guid = ++ grid.guid; this .__ cache = {}; var self = this; var en-tête = ce cache .__ ["en-tête"] = chargeur (); // en-tête ce .__ root = en-tête.parentNode; var templaterow = this .__ cache ["template"] = loadTemplate (); // 模板行 this .__ cache ["dataformat"] = loaddataformat (); // 数据模板 this .__ cache ["datarows"] = new collection (); // 数据行 ce .__ cache ["coustomCache"] = new collection (); // 用户缓存数据 ce. 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) {// 注册 Command if (row) {var arg = row.getAttribute ("index"); this.setAttribute ("index", arg || false); } this.commandName = CommandName; Event.remove.call (this, "click", exec); Event.on.call (this, "click", exec); } this .__ RemoverowCallback = function () {// 改变行的背景样式 var lignes = this .__ cache ["datarows"]; var customCache = this .__ cache ["CustomCache"]; var arr = rows.toArray (), dataarr = []; var rowIndex, ligne, données; Rows.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 || "") + "od";}} else if (// soDd / s | /sodd$/g.test (this.className)) {this.classname = this.classname.replace (// sodd / s | / sodd $ / g, "");} i ++; CustomCache.Clear (); dataarr.each (function () {CustomCache.add (this);}); } // 事件处理 Options = Options || {}; this.ondatabinding = options.ondatabinding || this.ondatabinding; this.onrowbinding = options.onrowbinding || this.onrowbinding; this.OnrowbIondd = options.OnrowBIDend || this.onrowbided; 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; } fonction loadTemplate () {tr = util.next (en-tête); // 获取模板行 return tr; } fonction chargedataformat () {var nœuds = templaterow.childnodes, ele, data, result = {}, att; nœuds = util.parsarray (nœuds); NODES.EACH (FONCTION (i) {ele = this; if (ele && ele.nodeType == 1) {att = ele.data || ele.getAttribute ("data"); if (att) {data = util.parsejson (att); ele.field = data.field; résultat [ele.field] = data;}}}); Résultat de retour; } Fonction CreateSaveButton () {var div = document.CreateElement ("div"); div.style.position = "absolu"; div.style.display = "Aucun"; div.style.width = "auto"; var btn = document.createElement ("bouton"); btn.innerhtml = btn.innertext = btn.textContent = btn.value = "Save"; essayez {btn.type = "bouton"; } catch (e) {btn.setAttribute ("type", "bouton"); } div.appendChild (btn); var btncancel = document.createElement ("bouton"); btncancel.innerhtml = btncancel.innertext = btncancel.textContent = btncancel.value = "annuler"; essayez {btncancel.type = "bouton"; } catch (e) {btncancel.setAttribute ("type", "bouton"); } div.appendChild (btncancel); Document.Body.ApendChild (Div); Event.on.call (btn, "click", function () {self.save ();}); Event.on.call (btncancel, "click", function () {div.style.display = "non"; if (self .__ editrow) {self .__ editrow.parentNode.reMoveChild (self .__ editrow); self .__ editrow = null;}}); retourner div; } fonction exec () {if (self .__ eDitrow) {// 如果当前处于编辑模式 , 则禁用所有 Commande return; } var commandname = this.commandName; var handler = self .__ cache ["CommandHandles"] [CommandName]; if (handler) {handler.call (this); }} // 去除模板行 Templaterow.parentNode.Removechild (Templaterow); // 处理表格中的 Commande 事件 var elements = header.getElementsByTagName ("*"); éléments = util.parsarray (éléments); elements.each (function () {if (this.nodeType === 1) {var commandName = this.command || this.getAttribute ("Command"); if (commandName) {self .__ regCommand.call (this, CommandName, Header);}}}); }, // Bangding bind: function (data) {this.clear (); if (data && data.length> 0) {var self = this; data.each (function () {self.append (this);}); }}, // 清理表 , 删除所以除 En-tête 以外的数据行 Clear: function () {var lignes = this .__ cache ["datarows"], row; rows.each (function () {row = this; if (row) {row.parentNode.RemoveChild (row);}}); Rows.Clear (); // 清理 Rows}, // 删除指定的行 Removerow: function (RowIndex) {var lignes = this .__ cache ["datarows"]; var row = rows.get (rowIndex); if (row) {var data = this .__ cache ["CustomCache"] [RowIndex]; row.parentNode.RemoveChild (row); Rows.Remove (RowIndex); // 通知用户数据行被移除 if (util.isfunction (this.onrowReMoved)) {this.OnrowReMoved (data, row); }} this .__ RemoverowCallback (); }, // 添加 行 APPEND: fonction (data) {if (! Data) {return; } var template = this .__ cache ["template"]; var lignes = this .__ cache ["datarows"]; var rowIndex = Rows.Length; var tr = template.clonenode (); var customCache = this .__ cache ["CustomCache"]; CustomCache.add (données); // 将数据行添加到 Tableau this .__ root.appendChild (tr); var self = this; var td, // 数据单元格 dataformat, // 数据格式化器 valeur; // 单元格中的给定的数据 tr.setAttribute ("index", rowIndex.ToString ()); // 更改样式 if (rowIndex% 2 == 1) {tr.classname = (tr.classname || "") + "Odd"; } // 通知 行数据绑定开始 if (util.isfunction (this.onrowbinding)) {this.onrowbinding (rowIndex, tr); } var templatetd = template.firstchild; while (templatetd) {td = templatetd.clonenode (true); Tr.ApendChild (TD); if (td.NodeType == 1 && templatetd.field) {dataformat = this .__ cache ["dataformat"] [templatetd.field]; TD.RemoveAtTribute ("Data"); td.field = templatetd.field; Value = data [dataformat.field]; // 通知单元格数据绑定事件 Value = this.ondatabinding (dataformat.field, valeur, td, données); if (value! == false) {// 如果返回 false , 则不用做赋值操作 switch (dataformat.render) {case "innerhtml": td.innerhtml = type de valeur == "Undefined" || valeur == null? "" : valeur; casser; case "innerText": par défaut: td.innertext = td.textContent = typeof value == "Undefined" || valeur == null? "" : valeur; casser; }}} templatetd = templatetd.nextsibling; } wows.add (tr); // 处理 Command var Elements = tr.getElementsByTagName ("*"), ele, att; éléments = util.parsarray (éléments); elements.each (function () {ele = this; if (ele.nodeType == 1 && (ele.command || ele.getAttribute ("Command"))) {att = ele.command || ele.getAttribute ("Command"); self .__ repragand.call (ele, att, tr);}}); // 通知 行数据绑定完成 if (util.isfunction (this.onrowbided)) {this.onrowbided (rowIndex, tr); }}, // 手动产生新的输入行 newline: function () {if (this .__ eDitrow) {// 如果当前有存在编辑行 , 则直接返回 , 每次最多限制编辑一行数据 return; } var template = this .__ cache ["template"]; var row = this .__ editrow = template.clonenode (false); var templatetd = template.firstChild; var textaRealist = []; while (templatetd) {td = templatetd.clonenode (true); Row.ApendChild (TD); if (td.NodeType == 1) {if (templatetd.field) {td.field = templatetd.field; td.innerhtml = ""; var dataformat = this .__ cache ["dataformat"] [templatetd.field]; var textarea = null; if (dataformat.render == "innerhtml") {textarea = document.createElement ("textArea"); } else {textArea = document.CreateElement ("Input"); textarea.type = "text"; } textarea.style.display = "Aucun"; TD.APPEndChild (TextArea); TextArealist.push (TextArea); }} templatetd = templatetd.nextsibling; } // 将数据行添加到 Tableau this .__ root.appendChild (row); var height = row.offsetheight, width = row.offsetwidth, offset = util.offset (row); textaRealist.each (function () {this.style.height = (0,8 * hauteur) + "px"; this.style.width = (0.8 * this.parentNode.offsetWidth) + "px"; this.style.display = "";}); var gauche = offset.left + largeur + 5; var top = offset.top; this.__savecontainer.style.top = top + "px"; Ce .__ SAVECONTAINER.STYLE.LEFT = Left + "PX"; this .__ savecontainer.style.height = this .__ savecontainer.style.lineHeight = height + "px"; Ce .__ SAVECONTAINER.STYLE.DISPlay = "Block"; }, // 保存手动产生的数据行数据 sauve: function () {if (! This .__ eDitrow) {return; } var row = 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 = null; if (dataformat.render == "innerhtml") {textarea = td.getElementsByTagName ("textArea") [0]; } else {textArea = td.getElementsByTagName ("Input") [0]; } value = textarea.value; switch (dataformat.datatype) {case "nombre": value = util.trim (valeur); valeur = nombre (valeur.length == 0? 0: valeur); casser; par défaut: pause; } data [td.field] = valeur; } td = td.nextsibling; } this .__ editrow.parentnode.removechild (this .__ editrow); this .__ editrow = null; Ce .__ SAVECONTAINER.STYLE.DISPlay = "Aucun"; // 通知用户正在保存数据 if (util.isfunction (this.onsaving)) {this.onsaving (data); } this.append (data); }, getrowData: function (rowIndex) {return this .__ cache ["CustomCache"]. get (rowIndex); }, // 数据绑定到指定 Cell 时的事件 ondatabinding: fonction (champ, valeur, cellule, données) {valeur de retour; }, //当数据行绑定开始时的事件 onRowBinding:function(rowIndex, row){ }, //当数据行绑定完成时的事件 //@param row {DOM element tr} onRowBinded:function(rowIndex, row){ }, //当编辑的数据被保存时的事件 onSaving:function(data){ }, //当数据行被移除时的通知事件 onRowRemoved:function(data,row){ } }; grid.guid = 0; }) (); </ script> </ head> <body> <table id = "table_demo"> <tr> <th> id </th> <th> name </ th> <th> descpriprition </th> <th> <bouton type = "Button" Command = "newline"> new Line </ Button> </th> </tr> <tr> <tr> <ttor data = '{"champ": "id", "dataType": "nombre", "rendu": "innertex data = '{"Field": "Description", "DataType": "String", "rendu": "innerHtml"}'> WorkingService </td> <Td> <Button type = "Button" Command = "Removerow"> Delete </ Button> </ td> </tr> </pall document.getElementById ("table_demo"); var g = new Grid (table, {ondatabinding: function (champ, valeur) {return value;}, onrowbIdD: function (rowIndex, row) {}}); g.bind ([{id: 0, nom: "kilin"}, {id: 1, name: "kilin1"}, {id: 2, name: "kilin2"}, {id: 3, name: "kilin3"}]); </cript> </ body> </html>