重构一段基于原生JavaScript的表格绘制代码

为了在CardSimulate项目中方便的显示技能和效果列表,决定重构以前编写的一段JavaScript代码——att表格绘制库,这段代码的作用是将特定的JavaScript数据对象转化为表格,支持精细的样式设置和一些复杂报表功能并且提供了自由的扩展性。可以用较新的Chrome浏览器访问https://ljzc002.github.io/Att/HTML/TEST/AttSample.html查看新版代码的例子,旧版代码的介绍见:https://www.cnblogs.com/ljzc002/p/5511510.html。 1、从表格类初始化表格对象 旧版的代码直接将表格对象作为一个全局变量,新版代码则定义了一个表格类,而每一个表格对象则是表格类的实例,这样就可以方便的在一个页面里添加多个表格对象,并有条理的管理多个表格的工作流程和属性。表格对象的初始化代码如下: 复制代码 1 /** 2 * Created by Administrator on 2015/5/11. 3 */ 4 //动态画表类,尝试使用自包含结构 5 //2016/8/31在表格中加入更多的格式选择 6 //2018/10/31重构att6框架为att7版本 7 Att7=function() 8 { 9 10 } 11 Att7.prototype.init=function(param)//只初始化对象的属性,不实际绘制 12 { 13 try 14 { 15 this.base=param.base;//表格的容器对象 16 this.id=param.id;//表格的id 17 //this.left=param.left?param.left:0;//在容器对象内的左侧距离->认为tab_data和div_table完全重合 18 //this.top=param.top?param.top:0;//上部距离 19 this.rowsp=param.rowsp?param.rowsp:50;//默认每页显示50条数据,输入负值表示无限制 20 //this.page_current=param.page_current?param.page_current:0;//默认显示数据集的第一页,初始索引为0 21 this.isStripe=param.isStripe?param.isStripe:1;//这种三目运算不适用于布尔值!!!!默认奇偶行使用不同颜色 22 this.isThlocked=param.isThlocked?param.isThlocked:0;//默认不锁定表头 23 this.isCollocked=param.isCollocked?param.isCollocked:0;//默认不锁定表列 24 this.showIndex=param.showIndex?param.showIndex:1;//默认在左侧显示行号 25 this.baseColor=param.baseColor?param.baseColor:"#ffffff";//默认背景色为白色,间隔色为背景色亮度降低十六分之一 26 this.stripeColor=param.stripeColor?param.stripeColor:"#eeeeee";//有时要求奇数行和偶数行使用不同的颜色 27 this.pickColor=param.pickColor?param.pickColor:"#97ceef";//选择了某一行时要突出显示这一行 28 this.div_temp1=document.createElement("div");//这几个div用来对背景颜色进行比较,因为不同的浏览器对背景颜色的保存方式不同 29 this.div_temp1.style.backgroundColor=this.baseColor;//有的用小写字母有的用大写字母,有的用rgb+数字,所以这里主动建立div 30 this.div_temp2=document.createElement("div");//在同样的保存方式下对颜色进行比较 31 this.div_temp2.style.backgroundColor=this.stripeColor; 32 this.div_temp3=document.createElement("div"); 33 this.div_temp3.style.backgroundColor=this.pickColor; 34 this.str_indexwid=param.str_indexwid?param.str_indexwid:"100px";//索引列的宽度 35 this.num_toolhei=param.num_toolhei?param.num_toolhei:80;//表格上部的工具区的高度 36 //固有属性,点击某些单元格时可以打开的小窗口 37 this.html_onclick="
" + 39 "
" + 40 " 详情" + 41 " " + 43 "
" + 44 "
"; 45 this.html_onmouseover=//鼠标移入时弹出的小文本提示框 46 "
" + 48 " " + 50 "
"; 51 } 52 catch(e) 53 { 54 console.log("表格初始化异常!"+e); 55 return false; 56 } 57 return "ok"; 58 } 复制代码 这里设置了表格对象的各项属性,第28到33行用不显示的div解决了dom标签颜色比较问题,第37到50行定义了两个窗口小控件以备后续调用。init方法的调用方式如下: 复制代码 1 var table1=new Att7(); 2 var objp={ 3 base:"div_tab", 4 id:"table1", 5 //left:50, 6 //top:50, 7 rowsp:999, 8 isThlocked:1, 9 isCollocked:2,//不包括索引列?-》包括 10 baseColor:"#00ff00", 11 stripeColor:"#00aa00", 12 pickColor:"#97ceef" 13 } 14 if(table1.init(objp)=="ok") 15 {//下面是数据显示 复制代码 2、表格容器的建立: 表格显示时dom结构如下: 其中all_base是所有表格相关元素的总容器,div_tool是表格上面的工具区,里面可以放置一些选择筛选条件的控件,div_tab是表格主体所在的区域,table1是根据数据生成的表格dom,三个div_mask是锁定表头或者锁定表列时使用的遮罩层dom。 使用的样式表文件如下: 复制代码 1 /*专用于表格框架的样式*/ 2 body{ margin: 0; padding: 0; border: 0; text-align: center; overflow: hidden;width: 100%; 3 height: 100%;position: fixed; font-family: verdana,arial,sans-serif; touch-action: none; 4 -ms-touch-action: none;font-size: 12px;min-width: 600px;} 5 #all_base{min-height: 576px;min-width: 1024px;height: 100%;width:100%;position: relative;overflow-x:auto;overflow-y: hidden;} 6 /*表格的属性*/ 7 td input{ height: 100%; width: 100%; border:0; text-align: center; background-color: inherit;} 8 .div_tab{float: left;position: relative;width:4000px;overflow-x: hidden;overflow-y: scroll} 9 .div_tab td{ text-align: center; /*border: solid 1px #008000;*/ border-right:solid 1px #008000; border-bottom: solid 1px #008000; 10 line-height: 16px; font-size: 13px; height: 24px; padding: 1px; background-color: inherit; word-break: keep-all; 11 /*display: inline-block*/} 12 .div_tab th{ text-align: center; /*border: solid 1px #008000;*/ line-height: 16px; font-size: 13px; height: 36px; 13 padding: 1px; text-align: center; border-right: solid 1px #008000; border-bottom: solid 1px #008000; word-break: keep-all; 14 white-space:nowrap; overflow: hidden; text-overflow: ellipsis;/*display: inline-block*/} 15 .div_tab table{ float: left; width: auto; border-right-width:0px; border: solid 1px #008000; table-layout: fixed;} 16 .div_tab tr{ width: auto; vertical-align: middle; /*border: solid 1px #008000;*/ padding: 1px;} 17 td a{ cursor: pointer;} 18 td button{ cursor: pointer;} 19 .div_mask2{ display:block; left: 0px; top: 0px; /*filter: alpha(opacity=50); opacity: 0.50;*/ overflow: hidden;/*锁定的表头表列*/ 20 position: absolute; float: left; overflow-x: hidden} 21 table{ border-spacing:0;} 22 .div_mask2 td{ text-align: center; /*border: solid 1px #008000;*/ border-right:solid 1px #008000; border-bottom: solid 1px #008000; 23 line-height: 16px; font-size: 13px; height: 24px; padding: 1px; background-color: inherit; word-break: keep-all;} 24 .div_mask2 th{ text-align: center; /*border: solid 1px #008000;*/ line-height: 16px; font-size: 13px; height: 36px; 25 padding: 1px; text-align: center; border-right: solid 1px #008000; border-bottom: solid 1px #008000; word-break: keep-all; 26 white-space:nowrap; overflow: hidden; text-overflow: ellipsis;} 27 .div_mask2 table{ float: left; width: auto; border-right-width:0px; border: solid 1px #008000; table-layout: fixed; 28 position: absolute;} 29 .div_mask2 tr{ width: auto; vertical-align: middle; /*border: solid 1px #008000;*/ padding: 1px;} 30 .combo-panel li{ float:none;} 31 .btn_limlen{ /*float: left;*/ height: 20px; width: 20px; border: 1px solid; /*margin-top: 6px;*/ /*margin-left: 4px;*/ 32 background: url(../ASSETS/IMAGE/play.png) no-repeat; position: absolute; -moz-border-radius: 3px; /* Gecko browsers圆角 */ 33 -webkit-border-radius: 3px; /* Webkit browsers */ border-radius:3px; /* W3C syntax */ position: absolute; 34 top: 6px; right: 4px;} 复制代码 遗憾的是,因为上述CSS的调试过程太长,以至于已经忘记了这样设置的原因,如果您使用时出现莫名其妙的元素错位,请自己调试。 3、启动表格绘制 通过表格对象的draw方法启动表格绘制 调用draw方法的方式如下: 复制代码 1 if(table1.init(objp)=="ok") 2 { 3 var obj_datas=[ 4 "测试表格", 5 ["测试表头","测试表头","测试表头","测试表头","测试表头","测试表头","测试表头","测试表头"], 6 ["str" 7 ,"limit" 8 ,["switch",["value1","text1"],["value2","text2"]] 9 ,["input",["class1"],["height","10px"]] 10 ,["select","class2",[["value1","text1"],["value2","text2"],["value3","text3"]],"onChange()"] 11 ,["check","class3"] 12 ,["button","class4","按钮","80px",["height","10px"]] 13 ,["a","class5",["height","10px"]] 14 ], 15 [100,200,300,400,500,600,700,800], 16 ["value1","value2value2value2value2value2value2value2value2value2value2","value1","value2","value1","value2","value1","value2"], 17 ["value1","value2","value1","value2","value1","value2","value1","value2"] 18 ,["value1","value2","value1","value2","value1","value2","value1","value2"] 19 ]; 20 table1.draw(obj_datas,0);//显示数据obj_datas的第0行 21 requestAnimFrame(function(){table1.AdjustWidth();}); 22 } 复制代码 其中obj_datas是一个自定义的数据对象,这个对象可能从后端程序发送过来也可能是在前台组装生成。requestAnimFrame是截取自谷歌WebGL工具库的一个方法,用来“延时一会”,等待浏览器完成表格容器渲染后,再调整表格尺寸从而使表格布局紧密。 延时代码如下: 复制代码 1 // Copyright 2010, Google Inc. 2 window.requestAnimFrame = (function() { 3 return window.requestAnimationFrame || 4 window.webkitRequestAnimationFrame || 5 window.mozRequestAnimationFrame || 6 window.oRequestAnimationFrame || 7 window.msRequestAnimationFrame || 8 function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) { 9 window.setTimeout(callback, 1000/60); 10 }; 11 })(); 复制代码 4、表格绘制代码的介绍: a、首先做一些和表格翻页有关的准备工作: 复制代码 1 Att7.prototype.draw=function(data,page_current)//实际绘制dom元素 2 { 3 this.totalpages=0;//记录下一共有多少页 4 if(this.rowsp>0) 5 { 6 this.totalpages=Math.ceil((data.length-4)/this.rowsp); 7 } 8 if(this.totalpages==0) 9 { 10 this.totalpages=1; 11 } 12 //计算当前页数 13 if(page_current<0) 14 { 15 alert("到达数据首页!"); 16 this.page_current=0; 17 } 18 else if(page_current>=this.totalpages) 19 { 20 alert("到达数据末尾"); 21 this.page_current=this.totalpages-1; 22 } 23 else 24 { 25 this.page_current=page_current; 26 } 复制代码 因为att将所有dom标签的生成工作放在浏览器端,所以可以一次性将所有数据从后台读取到前端,由前端JavaScript程序进行分页操作。(而传统表格绘制工具多把dom标签生成放在后台程序中,为了降低后台压力,分页操作多在数据库层面进行) 翻页方法代码如下: 复制代码 1 //翻页处理 2 Att7.prototype.ChangePage=function(flag) 3 { 4 document.body.style.cursor='wait'; 5 switch(flag)//不同的翻页动作对应不同的页号处理 6 { 7 case "0": 8 { 9 this.page_current=0; 10 break; 11 } 12 case "+": 13 { 14 this.page_current++; 15 break; 16 } 17 case "-": 18 { 19 this.page_current--; 20 break; 21 } 22 case "9999": 23 { 24 this.page_current=9999; 25 break; 26 } 27 } 28 this.draw(this.data,this.page_current); 29 document.getElementById('t_page_span').innerHTML=this.totalpages; 30 try {//万一没有定义 31 AdjustColor(); 32 } 33 catch(e) 34 { 35 36 } 37 document.getElementById('c_page_span').innerHTML=this.page_current+1; 38 document.body.style.cursor='default'; 39 var _this=this; 40 try 41 { 42 requestAnimFrame(function () { 43 _this.AdjustWidth() 44 }); 45 } 46 catch(e) 47 { 48 49 } 50 } 复制代码 根据ChangePage方法的不同参数,可以进行四种不同的翻页操作,您可以再需要的地方建立四个按钮来对应这些操作,而翻页操作实际上只是改变了参数的draw方法。t_page_span和c_page_span是两个span标签,用来显示总页数和当前页数。AdjustColor是一个可选的方法,在绘制表格后遍历单元格,根据需求改变符合某种条件的单元格的颜色。(这里并未使用) b、在开始绘制之前清理以前可能绘制过的id相同的表格: 复制代码 1 //接着上面的翻页准备 2 this.data=data;//表格的数据集 3 var tab_data;//table标签 4 var tab_colmask;//列锁定遮罩标签 5 if (document.getElementById(this.id))//如果已有该表 6 {//清理已有的dom 7 tab_data= document.getElementById(this.id); 8 var parent = tab_data.parentNode; 9 parent.removeChild(tab_data); 10 if(document.getElementById("div_thmask"))//删除锁定表头的遮罩层 11 { 12 var div =document.getElementById("div_thmask");//看来这样的设定还不能支持一个页面中同时存在多个锁定表头表格 13 div.parentNode.removeChild(div); 14 } 15 if(document.getElementById("tab_mask2"))//删除锁定表列的遮罩层 16 { 17 var tab =document.getElementById("tab_mask2"); 18 tab.parentNode.removeChild(tab); 19 } 20 if(document.getElementById("div_thmask3"))// 21 { 22 var tab =document.getElementById("div_thmask3"); 23 tab.parentNode.removeChild(tab); 24 } 25 } 26 tab_data = document.createElement("table");//重新建立table标签 27 tab_data.id = this.id; 28 tab_data.cellPadding = "0"; 29 tab_data.cellSpacing = "0"; 30 tab_data.style.position = "absolute"; 31 //tab_data.style.top = this.top + "px"; 32 //tab_data.style.left = this.left + "px"; 33 var div_table;//包含表格的容器元素 34 35 var obj=this.base;//这个属性可能是id字符串也可能是对象本身 36 if((typeof obj)=="string"||(typeof obj)=="String") 37 { 38 div_table = document.getElementById(obj); 39 } 40 else 41 { 42 div_table=obj; 43 } 44 div_table.innerHTML=""; 45 div_table.appendChild(tab_data);//将table标签放入容器里 46 this.div_table=div_table; 47 tab_data = document.getElementById(this.id); 复制代码
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信