javascript实现动态模态绑定grid过程代码

<html>
<head>
  <style type="text/css">
    .grid{border:1px solid #808080; border-spacing:0; width:500px; border-collapse:collapse}
    .grid th,.grid td{border:0; text-align:center;}
    .grid tr{height:25px;line-height:25px;}
    .grid tr.odd{background:#d0d0d0}
    .grid .btn{width: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);
              result = arr;
            }catch(e){
              for(var i=0;i<obj.length;i++){
                try{
                  var target = obj[i];
                }catch(e){
                  if(obj.item){
                    var target = this.item(i);//nodeList
                  }
                }
                if(typeof target !== "undefined"){
                  result.push(target);
                  delete target;
                }
              }
            }
          }
          return result;
        },
        isFunction:function(fn){
          return typeof fn === "function";
        },
        trim:function(str){
          if(typeof str !== "string"){
            return str;
          }
          return str.replace(/^\s+|\s+$/g,"");
        },
        offset:function offset(ele){
          var result = {top:0,left:0};
          if(!ele || ele.nodeType !== 1){
            return result;
          }
          result.top = Number(ele.offsetTop || (ele.style.top || "0").replace(/[^\d]+$/,""));
          result.left = Number(ele.offsetLeft || (ele.style.left || "0").replace(/[^\d]+$/,""));
          if(ele.parentNode){
            var r = offset(ele.parentNode);
            result.top += r.top;
            result.left += r.left;
          }
          return result;
        }
      }; 

      //事件处理
      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]){
              element[_EventRef]=[];
            }
            var _EventRefs=element[_EventRef];
            var index;
            for(index in _EventRefs){
              if(_EventRefs[index]['realFn']==fn){
                return;
              }
            }
            var nestFn=function(){
              fn.apply(element,arguments);
            };
            element[_EventRef].push({'realFn':fn,'nestFn':nestFn});
            element.attachEvent('on'+eventType,nestFn);
          }
        },
        remove: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]){
              element[_EventRef]=[];
            }
            var _EventRefs=element[_EventRef]
            var index;
            var nestFn;
            for(index in _EventRefs){
              if(_EventRefs[index]['realFn']==fn){
                nestFn=_EventRefs[index]['nestFn'];
                if(index==_EventRefs.length-1){
                  element[_EventRef]=_EventRefs.slice(0,index);
                }else{
                  element[_EventRef]=_EventRefs.slice(0,index).concat(_EventRefs.slice(index+1,_EventRefs.length-1));
                }
                break;
              }
            }
            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();
            }else if(index === this.length - 1){
              this.pop();
            }else{
              var arr1 = this.slice(0,index);
              var arr2 = this.slice(index+1);
              this.length = 0;
              this.concat(arr1,arr2);
            }
          }
        }
        //删除数组中所有的元素
        Array.prototype.clear = function(){
          this.length = 0;
        }
        //each
        Array.prototype.each = function(fn){
          if(!util.isFunction(fn)){
            return;
          }
          for(var i=0;i<this.length;i++){
            if(typeof this[i] !== "undefined"){
              fn.call(this[i],i);
            }
          }
        } 

        //
        var collection = this.collection = function(){
          this.__data = {};
          this.length = 0;
        }
        collection.prototype = {
          add:function(obj){
            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;
          },
          each:function(fn){
            var index = 0;
            for(var k in this.__data){
              if(k && typeof this.__data[k] !== "undefined"){
                fn.call(this.__data[k],index++);
              }
            }
          },
          toArray:function(){
            var arr = [];
            this.each(function(){
              arr.push(this);
            });
            return arr;
          }
        };
      })();
      //
      var grid = this.grid = function(table, options){
        grid.prototype._init.call(this,table,options);
      }
      grid.prototype = {
        _init:function(table, options){
          if(typeof table === "undefined" || !table){
            throw "table is undefined or null";
          }
          if(table.nodeType !== 1 || !/^table$/i.test(table.tagName)){
            throw "table must be 'table' element.";
          }
          table.guid = ++grid.guid;
          this.__cache = {};
          var self = this;
          var header = this.__cache["header"] = loadHeader();//header
          this.__root = header.parentNode;
          var templateRow = this.__cache["template"] = loadTemplate();//模板行
          this.__cache["dataFormat"] = loadDataFormat();//数据模板
          this.__cache["dataRows"] = new collection();//数据行
          this.__cache["customCache"] = new collection();//用户缓存数据
          this.__editRow = null;//当前编辑行
          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 rows = this.__cache["dataRows"];
            var customCache = this.__cache["customCache"];
            var arr = rows.toArray(),dataArr=[];
            var rowIndex,row,data; 

            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 || "") + " odd";
                }
              }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.onRowBinded = options.onRowBinded || this.onRowBinded;          

          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(header);//获取模板行
            return tr;
          } 

          function loadDataFormat(){
            var nodes = templateRow.childNodes,ele,data,result = {},attr;
            nodes = util.parseArray(nodes);
            nodes.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;
                  result[ele.field] = data;
                }
              }
            });
            return result;
          } 

          function createSaveButton(){
            var div = document.createElement("div");
            div.style.position = "absolute";
            div.style.display = "none";
            div.style.width = "auto";
            var btn = document.createElement("button");
            btn.innerHTML = btn.innerText = btn.textContent = btn.value = "Save";
            try{
              btn.type = "button";
            }catch(e){
              btn.setAttribute("type","button");
            }
            div.appendChild(btn); 

            var btnCancel = document.createElement("button");
            btnCancel.innerHTML = btnCancel.innerText = btnCancel.textContent = btnCancel.value = "Cancel";
            try{
              btnCancel.type = "button";
            }catch(e){
              btnCancel.setAttribute("type","button");
            }
            div.appendChild(btnCancel); 

            document.body.appendChild(div);
            Event.on.call(btn,"click",function(){
              self.save();
            });
            Event.on.call(btnCancel,"click",function(){
              div.style.display = "none";
              if(self.__editRow){
                self.__editRow.parentNode.removeChild(self.__editRow);
                self.__editRow = null;
              }
            }); 

            return div;
          } 

          function exec(){
            if(self.__editRow){//如果当前处于编辑模式,则禁用所有command
              return;
            }
            var commandName = this.commandName;
            var handler = self.__cache["commandHandles"][commandName];
            if(handler){
              handler.call(this);
            }
          } 

          //去除模板行
          templateRow.parentNode.removeChild(templateRow); 

          //处理表格中的command事件
          var elements = header.getElementsByTagName("*");
          elements = util.parseArray(elements);
          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);
            });
          }
        },
        //清理表,删除所以除header以外的数据行
        clear:function(){
          var rows = this.__cache["dataRows"],row;
          rows.each(function(){
            row = this;
            if(row){
              row.parentNode.removeChild(row);
            }
          });
          rows.clear();//清理rows
        },
        //删除指定的行
        removeRow:function(rowIndex){
          var rows = 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:function(data){
          if(!data){
            return ;
          }
          var template = this.__cache["template"];
          var rows = this.__cache["dataRows"];
          var rowIndex = rows.length;
          var tr = template.cloneNode();
          var customCache = this.__cache["customCache"];
          customCache.add(data);
          //将数据行添加到table
          this.__root.appendChild(tr);
          var self = this;
          var td,//数据单元格
            dataFormat,//数据格式化器
            value;//单元格中的给定的数据
          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.appendChild(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,value,td,data);
              if(value !== false){//如果返回false,则不用做赋值操作
                switch(dataFormat.render){
                  case "innerHTML":
                    td.innerHTML = typeof value == "undefined" || value == null ? "" : value;
                    break;
                  case "innerText":
                  default:
                    td.innerText = td.textContent = typeof value == "undefined" || value == null ? "" : value;
                    break;
                }
              }
            }
            templateTD = templateTD.nextSibling;
          }
          rows.add(tr); 

          //处理command
          var elements = tr.getElementsByTagName("*"),ele,attr;
          elements = util.parseArray(elements);
          elements.each(function(){
            ele = this;
            if(ele.nodeType == 1 && (ele.command || ele.getAttribute("command"))){
              attr = ele.command || ele.getAttribute("command");
              self.__regCommand.call(ele,attr,tr);
            }
          }); 

          //通知 行数据绑定完成
          if(util.isFunction(this.onRowBinded)){
            this.onRowBinded(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.appendChild(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 = "none";
                td.appendChild(textarea);
                textareaList.push(textarea);
              }
            }
            templateTD = templateTD.nextSibling;
          }
          //将数据行添加到table
          this.__root.appendChild(row); 

          var height = row.offsetHeight,
            width = row.offsetWidth,
            offset = util.offset(row); 

          textareaList.each(function(){
            this.style.height = (0.8 * height) + "px";
            this.style.width = (0.8 * this.parentNode.offsetWidth) + "px";
            this.style.display = "";
          }); 

          var left = offset.left + width + 5;
          var top = offset.top;
          this.__saveContainer.style.top = top + "px";
          this.__saveContainer.style.left = left + "px";
          this.__saveContainer.style.height = this.__saveContainer.style.lineHeight = height + "px";
          this.__saveContainer.style.display = "block";
        },
        //保存手动产生的数据行数据
        save: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 "number":
                  value = util.trim(value);
                  value = Number(value.length == 0 ? 0 : value);
                  break;
                default:
                  break;
              }
              data[td.field] = value;
            }
            td = td.nextSibling;
          }
          this.__editRow.parentNode.removeChild(this.__editRow);
          this.__editRow = null;
          this.__saveContainer.style.display = "none"; 

          //通知用户正在保存数据
          if(util.isFunction(this.onSaving)){
            this.onSaving(data);
          } 

          this.append(data);
        },
        getRowData:function(rowIndex){
          return this.__cache["customCache"].get(rowIndex);
        }, 

        //数据绑定到指定cell时的事件
        onDataBinding:function(field,value,cell,data){
          return value;
        },
        //当数据行绑定开始时的事件
        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" class="grid">
    <tr class="odd">
      <th>ID</th>
      <th>Name</th>
      <th>Descpription</th>
      <th><button type="button" command="newLine" class="btn">New Line</button></th>
    </tr>
    <tr>
      <td data='{"field":"id","dataType":"number","render":"innerText"}'>1</td>
      <td data='{"field":"name","dataType":"string","render":"innerText"}'>WorkingService</td>
      <td data='{"field":"description","dataType":"string","render":"innerHTML"}'>WorkingService</td>
      <td>
        <button type="button" command="removeRow" class="btn">Delete</button>
      </td>
    </tr>
  </table>
  <script type="text/javascript">
    var table = document.getElementById("table_demo");
    var g = new grid(table,{
      onDataBinding:function(field,value){
        return value;
      },
      onRowBinded:function(rowIndex,row){}
    });
    g.bind([
      {id:0,name:"kilin"},
      {id:1,name:"kilin1"},
      {id:2,name:"kilin2"},
      {id:3,name:"kilin3"}
    ]);
  </script>
</body>
</html>
(0)

相关推荐

  • javascript实现动态模态绑定grid过程代码

    <html> <head> <style type="text/css"> .grid{border:1px solid #808080; border-spacing:0; width:500px; border-collapse:collapse} .grid th,.grid td{border:0; text-align:center;} .grid tr{height:25px;line-height:25px;} .grid tr.odd

  • Javascript实现动态菜单添加的实例代码

    先来看看效果: Html源码: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  <html xmlns="http://www.w3.org/1999/xhtml">  <head>  <

  • javascript下动态this与动态绑定实例代码

    那么函数就是被掰成两部分储存于对象,一是其函数名(键),一是函数体(值),那么函数中的this一般都指向函数所在的对象.但这是一般而已,在全局调用函数时,我们并没有看到调用者,或者这时就是window.不过,函数声明后,其实并没有绑定到任何对象,因此我们可以用call apply这些方法设置调用者. 一个简单的例子: [script] <script> window.name = "window"; var run = function() { alert("My

  • JavaScript实现动态表格的方法详解

    目录 JavaScript实现动态表格 基本效果如下 代码如下: 第一种方式(较简单,建议使用) 方式二 改进版 代码如下: 总结 JavaScript实现动态表格 (改建版,代码见最下面) 基本效果如下 点击添加,可以将输入框中的值,新增到表格中:点击删除可以删除本行内容. 代码如下: 第一种方式(较简单,建议使用) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF

  • JavaScript实现拖动模态框

    本文实例为大家分享了JavaScript实现拖动模态框的具体代码,供大家参考,具体内容如下 案例:模态框拖拽 弹出框,我们也称为模态框. 1.点击弹出层,会弹出模态框,并且显示灰色半透明的遮挡层.2.点击关闭按钮,可以关闭模态框,并且同时关闭灰色半透明遮挡层.3.鼠标放到模态框最上面一行,可以按住鼠标拖拽模态框在页面中移动.4.鼠标松开,可以停止拖动模态框移动. 案例分析 ①点击弹出层,模态框和遮挡层就会显示出来display:block;②点击关闭按钮,模态框和遮挡层就会隐藏起来display

  • JavaScript实现动态生成表格

    本文实例为大家分享了JavaScript实现动态生成表格的具体代码,供大家参考,具体内容如下 功能描述 在输入框中输入行和列,点击按钮,生成拥有对应行和列的表格.如下图所示: 分析 HTML界面设计 <body> 行:<input type="text" id="row" /> 列: <input type="text" id="col" /> <input type="bu

  • JavaScript实现动态数字时钟

    本文实例为大家分享了JavaScript实现动态数字时钟的具体代码,供大家参考,具体内容如下 实现效果 代码实现 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> * { padding: 0; margin: 0; } #box { width

  • JavaScript实现动态表格效果

    本文实例为大家分享了JavaScript实现动态表格效果的具体代码,供大家参考,具体内容如下 代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>动态表格</title> <style> .bigDiv{ width: 600px; margin: 50px auto; } table{

  • JavaScript实现动态网页时钟

    本文实例为大家分享了JavaScript实现动态网页时钟的具体代码,供大家参考,具体内容如下 设计思路: 1先建立一个数组保存带有0〜9数字的10张图片; 2.通过GETDATE()获得本地时间保存在变量数值指明MyTime中; 3. getHours()返回的是24进制即0~23的整数,getMinutes()方法返回一个处于0到59之间的整数,getSeconds()方法返回一个处于0到59之间的整数; 4.通过的setTimeout()每隔1秒调用一次显示()函数改变图像对象的SRC属性.

  • 原生JavaScript实现动态省市县三级联动下拉框菜单实例代码

    像平时购物选择地址时一样,通过选择的省动态加载城市列表,通过选择的城市动态加载县区列表,从而可以实现省市县的三级联动,下面使用原生的JavaScript来实现这个功能: 先给大家展示下测试结果: 未做任何选择时: 选择时: 代码如下所示: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>三级联动测试</titl

随机推荐