Jooshe 表格 - JavaScript 面向对象 HTML 元素子类化的第 2 部分 - 轻松创建动态表格!






4.89/5 (5投票s)
Jooshe 很有料!
必备组件
第一部分: Jooshe - JavaScript 面向对象 HTML 元素子类化
引言
本文使用一组与表格相关的类扩展了 Jooshe JavaScript 库。这些类使您能够轻松创建和操作基于 DOM 的表格。
轻松到什么程度?
作为 Jooshe Tables 的一个示例,一个 100 x 100 的表格可以用以下方式创建:
var i, j, theTable = new table;
for(i=0;i<100;i++) for(j=0;j<100;j++) theTable.$.cell(i,j,null,{ innerHTML: i + "," + j });
使用 Jooshe Tables
加载 Jooshe JavaScript 库和 Jooshe Tables JavaScript 库
<script src="jooshe.js"></script>
<script src="jooshe.tables.js"></script>
或
<script src="jooshe.min.js"></script>
<script src="jooshe.tables.min.js"></script>
<script>
元素的 src
属性必须指向 Jooshe 和 Jooshe Tables 的副本。
Jooshe 和 Jooshe Tables 的副本随下载包中的演示代码一起提供。
兼容性
所有主流浏览器,IE 9+。
演示链接
本文中我们将构建的演示可以在 这里 查看。
背景
表格在 HTML 中一直是一个有争议的问题。CSS 纯粹主义者像瘟疫一样避开表格。主要问题是它的 cellpadding 和 cellspacing 属性。这两个属性可能应该被合并到表格的样式中。或者,它们至少应该有一个指定的默认值 0,这样表格就会完全是结构性的。不幸的是,cellpadding 和 cellspacing 的默认值分别是 1px 和 2px。
表格有其存在的价值,不应该遭受所有的 FUD(恐惧、不确定和怀疑)。
用例
表格的用例很简单,即任何容器的集合,其中期望的水平或垂直相对定位是恒定的。
例如,
Google 在其主页的搜索框中使用了表格。我无法在此处包含复制它的 HTML,但您可以通过在他们的网站上执行 Inspect element
来自己查看结构。上面的图片是在 Chrome 上截取的 - 麦克风图标(语音搜索)似乎在其他任何浏览器中都不显示。Google 在这里使用了带有一行和两个单元格的表格——一个用于文本输入,一个用于麦克风图标。在这种情况下,他们希望确保麦克风始终显示在文本输入的右侧(两个元素的恒定相对水平定位)。
Jooshe
Jooshe 首先将表格简化为一个纯粹的结构对象。在 Jooshe (jooshe.js) 的 'CSS-Reset' 部分,我们有以下一行代码:
if(tag == "table") { me.cellPadding = 0; me.cellSpacing = 0; }
如果您需要一个具有非零 cellpadding 或 cellspacing 的表格,创建一个表格就像这样做一样简单:
var myTable = element("table",null,{cellpadding:1,cellspacing:2});
Jooshe Tables
Jooshe Tables 引入了以下 6 个类,每个类都带有一组方法,这些方法使动态表格的创建和操作变得轻而易举!
- table
- tbody
- thead
- tfoot
- tr
- td
jooshe.tables.js
createClass("table",function(o,p,q,r){ return element("table",o,[this].concat(p),q,r); },{$:{
expansionElement:"tbody",
appendCell:function(o,p,q,r){ return this.body(0).$.appendCell(o,p,q,r); },
appendRow:function(o,p,q,r){ return this.body(0).$.appendRow(o,p,q,r); },
body:function(i,o,p,q,r){
var b = /^\[object HTML/.test(Object.prototype.toString.call(o)), x,
u = this.el,
v = window[this.expansionElement],
w = J$.wrap,
s = v == tbody ? "tBodies" : "childNodes"; // this function is used by other classes
i = i || 0;
if(i >= 0 && u[s].length > i) {
x = u[s][i];
if(b) u.replaceChild(x,o);
}
else {
x = b ? o : new v(o,p,q);
if(i < 0 && u[s].length) u.insertBefore(x,u.firstChild);
else {
while(u[s].length < i) u.appendChild(new v);
u.appendChild(x);
}
}
w(x.style,b?p:o);
w(x,b?q:p);
w(x.$,b?r:q);
return x;
},
cell:function(i,j,o,p,q,r){ return this.body(0).$.cell(i,j,o,p,q,r); },
firstCell:function(o,p,q,r){ return this.body(0).$.firstCell(o,p,q,r); },
firstRow:function(o,p,q,r){ return this.body(0).$.firstRow(o,p,q,r); },
foot:function(o,p,q,r){ return this.el.tFoot || this.el.appendChild(new tfoot(o,p,q,r)); },
head:function(o,p,q,r){ return this.el.tHead || this.el.appendChild(new thead(o,p,q,r)); },
lastCell:function(o,p,q,r){ return this.body(0).$.lastCell(o,p,q,r); },
lastRow:function(o,p,q,r){ return this.body(0).$.lastRow(o,p,q); },
prependCell:function(o,p,q,r){ return this.body(0).$.prependCell(o,p,q,r); },
prependRow:function(o,p,q,r){ return this.body(0).$.prependRow(o,p,q,r); },
row:function(i,o,p,q,r){ return this.body(0).$.row(i,o,p,q,r); },
setBackground:function(s){ var o = this.el; o.style.backgroundImage = s; return o; }
}});
createClass("tbody",function(o,p,q,r,s){ return element(s || "tbody",o,[this].concat(p),q,r); },{$:{
expansionElement:"tr",expansionMethod:"row",
appendCell:function(o,p,q,r){ return this.lastRow().$.appendCell(o,p,q,r); },
appendRow:function(o,p,q,r){
return this[this.expansionMethod].call(this,this.el.childNodes.length,o,p,q,r);
},
cell:function(i,j,o,p,q,r){ return this.row(i).$.cell(j,o,p,q,r); },
firstCell:function(o,p,q,r){ return this.cell(0,0,o,p,q,r); },
firstRow:function(o,p,q,r){ return this.row(0,o,p,q,r); },
lastCell:function(o,p,q,r){ return this.lastRow().$.lastCell(o,p,q,r); },
lastRow:function(o,p,q,r){ var i = this.el.childNodes.length; return this.row(i?i-1:0,o,p,q,r); },
prependCell:function(o,p,q,r){ return this.lastRow().$.prependCell(o,p,q,r); },
prependRow:function(o,p,q,r){ return this[this.expansionMethod].call(this,-1,o,p,q,r); },
row:table.prototype.$.body
}});
createClass("thead",function(o,p,q,r){ return new tbody(o,p,q,r,"thead"); });
createClass("tfoot",function(o,p,q,r){ return new tbody(o,p,q,r,"tfoot"); });
createClass("tr",function(o,p,q,r){ return element("tr",o,[this].concat(p),q,r); },{$:{
expansionElement:"td",expansionMethod:"cell",
appendCell:tbody.prototype.$.appendRow,
cell:table.prototype.$.body,
firstCell:function(o,p,q,r){ return this.cell(0,o,p,q,r); },
lastCell:function(o,p,q,r){ var i = this.el.childNodes.length; return this.cell(i?i-1:0,o,p,q,r); },
prependCell:tbody.prototype.$.prependRow
}});
createClass("td",function(o,p,q,r,s){
var me = element("td",o,[this].concat(p),q,r);
if(s)me.$.setImage(s);
return me;
},{$:{
clear:function(){ var o=this.el; while(o.firstChild) o.removeChild(o.firstChild); },
setBackground:table.prototype.$.setBackground,
setImage:function(s,o,p){
this.clear();
var q=this.el;
q.style.textAlign="center";
return q.appendChild(element("img",o,p,null,{src:s}));
},
setSprite:function(s,i,j,k,l){
this.clear();
return this.el.appendChild(
element("div",
{background:"url("+s+") no-repeat "+i+"px "+j+"px",margin:"auto",width:k+"px",height:l+"px"}
)
);
}
}});
好的,代码有点多。好消息是,大多数函数的使用方式相同,并且很多功能在表格元素的各个结构组件中都有复制。
用法
所有 createClass
函数都接受相同的参数集:
o
- 样式级对象或对象数组p
-this
级对象或对象数组q
- $-级对象或对象数组r
- 元素级对象或对象数组
接受参数 o,p,q,r
的所有函数都有两种使用形式:
o
- 样式级对象或对象数组p
- 元素级对象或对象数组q
- $-级对象或对象数组
或
o
- Jooshe 元素p
- 样式级对象或对象数组q
- 元素级对象或对象数组r
- $-级对象或对象数组
如果使用第二种形式,传入的 Jooshe 元素将用于扩展表格或替换表格中现有的元素。prepend / append 函数用于扩展表格——其他接受参数 o,p,q,r
的函数用于访问现有元素。
关于访问类型函数的说明:如果您指定了一个不存在的行/列,表格将自动扩展到指定的维度。
功能
我的目标是使用自解释的函数名。如果任何功能不清楚,请在评论中告知我,我会详细说明。
说明所有这些功能的最佳方法是深入研究演示。
演示
让我们从一个简单的 10 x 10 表格开始
var i, j, o, theTable = new table({borderBottom:"1px solid black"});
for(i=0;i<10;i++)
for(j=0;j<10;j++)
theTable.$.cell(i,j,{padding: "5px 10px"},{innerHTML: i + "," + j});
这将生成以下表格:
0,0 | 0,1 | 0,2 | 0,3 | 0,4 | 0,5 | 0,6 | 0,7 | 0,8 | 0,9 |
1,0 | 1,1 | 1,2 | 1,3 | 1,4 | 1,5 | 1,6 | 1,7 | 1,8 | 1,9 |
2,0 | 2,1 | 2,2 | 2,3 | 2,4 | 2,5 | 2,6 | 2,7 | 2,8 | 2,9 |
3,0 | 3,1 | 3,2 | 3,3 | 3,4 | 3,5 | 3,6 | 3,7 | 3,8 | 3,9 |
4,0 | 4,1 | 4,2 | 4,3 | 4,4 | 4,5 | 4,6 | 4,7 | 4,8 | 4,9 |
5,0 | 5,1 | 5,2 | 5,3 | 5,4 | 5,5 | 5,6 | 5,7 | 5,8 | 5,9 |
6,0 | 6,1 | 6,2 | 6,3 | 6,4 | 6,5 | 6,6 | 6,7 | 6,8 | 6,9 |
7,0 | 7,1 | 7,2 | 7,3 | 7,4 | 7,5 | 7,6 | 7,7 | 7,8 | 7,9 |
8,0 | 8,1 | 8,2 | 8,3 | 8,4 | 8,5 | 8,6 | 8,7 | 8,8 | 8,9 |
9,0 | 9,1 | 9,2 | 9,3 | 9,4 | 9,5 | 9,6 | 9,7 | 9,8 | 9,9 |
现在,让我们在前面添加一行
theTable.$.prependRow();
for(i=0;i<10;i++) theTable.$.cell(0,i,{padding:"10px 0",textAlign:"center"},{innerHTML:i});
我们的表格现在看起来像这样:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0,0 | 0,1 | 0,2 | 0,3 | 0,4 | 0,5 | 0,6 | 0,7 | 0,8 | 0,9 |
1,0 | 1,1 | 1,2 | 1,3 | 1,4 | 1,5 | 1,6 | 1,7 | 1,8 | 1,9 |
2,0 | 2,1 | 2,2 | 2,3 | 2,4 | 2,5 | 2,6 | 2,7 | 2,8 | 2,9 |
3,0 | 3,1 | 3,2 | 3,3 | 3,4 | 3,5 | 3,6 | 3,7 | 3,8 | 3,9 |
4,0 | 4,1 | 4,2 | 4,3 | 4,4 | 4,5 | 4,6 | 4,7 | 4,8 | 4,9 |
5,0 | 5,1 | 5,2 | 5,3 | 5,4 | 5,5 | 5,6 | 5,7 | 5,8 | 5,9 |
6,0 | 6,1 | 6,2 | 6,3 | 6,4 | 6,5 | 6,6 | 6,7 | 6,8 | 6,9 |
7,0 | 7,1 | 7,2 | 7,3 | 7,4 | 7,5 | 7,6 | 7,7 | 7,8 | 7,9 |
8,0 | 8,1 | 8,2 | 8,3 | 8,4 | 8,5 | 8,6 | 8,7 | 8,8 | 8,9 |
9,0 | 9,1 | 9,2 | 9,3 | 9,4 | 9,5 | 9,6 | 9,7 | 9,8 | 9,9 |
现在,我们将所有底部行单元格的字体粗细设置为粗体
o = theTable.$.lastRow();
for(i=0;i<10;i++) o.$.cell(i,{fontWeight:"bold"});
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0,0 | 0,1 | 0,2 | 0,3 | 0,4 | 0,5 | 0,6 | 0,7 | 0,8 | 0,9 |
1,0 | 1,1 | 1,2 | 1,3 | 1,4 | 1,5 | 1,6 | 1,7 | 1,8 | 1,9 |
2,0 | 2,1 | 2,2 | 2,3 | 2,4 | 2,5 | 2,6 | 2,7 | 2,8 | 2,9 |
3,0 | 3,1 | 3,2 | 3,3 | 3,4 | 3,5 | 3,6 | 3,7 | 3,8 | 3,9 |
4,0 | 4,1 | 4,2 | 4,3 | 4,4 | 4,5 | 4,6 | 4,7 | 4,8 | 4,9 |
5,0 | 5,1 | 5,2 | 5,3 | 5,4 | 5,5 | 5,6 | 5,7 | 5,8 | 5,9 |
6,0 | 6,1 | 6,2 | 6,3 | 6,4 | 6,5 | 6,6 | 6,7 | 6,8 | 6,9 |
7,0 | 7,1 | 7,2 | 7,3 | 7,4 | 7,5 | 7,6 | 7,7 | 7,8 | 7,9 |
8,0 | 8,1 | 8,2 | 8,3 | 8,4 | 8,5 | 8,6 | 8,7 | 8,8 | 8,9 |
9,0 | 9,1 | 9,2 | 9,3 | 9,4 | 9,5 | 9,6 | 9,7 | 9,8 | 9,9 |
现在,我们将为表格添加一个标题
o = theTable.$.head();
for(i=0;i<10;i++)
o.$.cell(0,i,
{background:"#f63",color:"#fff",fontWeight:"bold",padding:"5px 0",textAlign:"center"},
{innerHTML:"ABCDEFGHIJ"[i]}
);
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0,0 | 0,1 | 0,2 | 0,3 | 0,4 | 0,5 | 0,6 | 0,7 | 0,8 | 0,9 |
1,0 | 1,1 | 1,2 | 1,3 | 1,4 | 1,5 | 1,6 | 1,7 | 1,8 | 1,9 |
2,0 | 2,1 | 2,2 | 2,3 | 2,4 | 2,5 | 2,6 | 2,7 | 2,8 | 2,9 |
3,0 | 3,1 | 3,2 | 3,3 | 3,4 | 3,5 | 3,6 | 3,7 | 3,8 | 3,9 |
4,0 | 4,1 | 4,2 | 4,3 | 4,4 | 4,5 | 4,6 | 4,7 | 4,8 | 4,9 |
5,0 | 5,1 | 5,2 | 5,3 | 5,4 | 5,5 | 5,6 | 5,7 | 5,8 | 5,9 |
6,0 | 6,1 | 6,2 | 6,3 | 6,4 | 6,5 | 6,6 | 6,7 | 6,8 | 6,9 |
7,0 | 7,1 | 7,2 | 7,3 | 7,4 | 7,5 | 7,6 | 7,7 | 7,8 | 7,9 |
8,0 | 8,1 | 8,2 | 8,3 | 8,4 | 8,5 | 8,6 | 8,7 | 8,8 | 8,9 |
9,0 | 9,1 | 9,2 | 9,3 | 9,4 | 9,5 | 9,6 | 9,7 | 9,8 | 9,9 |
A | B | C | D | E | F | G | H | 我 | J |
现在,我们将向表格添加一行图片
for(i=0;i<10;i++) theTable.$.cell(11,i,{padding:"5px 0 10px"}).$.setImage("ball"+(i%2)+".png");
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0,0 | 0,1 | 0,2 | 0,3 | 0,4 | 0,5 | 0,6 | 0,7 | 0,8 | 0,9 |
1,0 | 1,1 | 1,2 | 1,3 | 1,4 | 1,5 | 1,6 | 1,7 | 1,8 | 1,9 |
2,0 | 2,1 | 2,2 | 2,3 | 2,4 | 2,5 | 2,6 | 2,7 | 2,8 | 2,9 |
3,0 | 3,1 | 3,2 | 3,3 | 3,4 | 3,5 | 3,6 | 3,7 | 3,8 | 3,9 |
4,0 | 4,1 | 4,2 | 4,3 | 4,4 | 4,5 | 4,6 | 4,7 | 4,8 | 4,9 |
5,0 | 5,1 | 5,2 | 5,3 | 5,4 | 5,5 | 5,6 | 5,7 | 5,8 | 5,9 |
6,0 | 6,1 | 6,2 | 6,3 | 6,4 | 6,5 | 6,6 | 6,7 | 6,8 | 6,9 |
7,0 | 7,1 | 7,2 | 7,3 | 7,4 | 7,5 | 7,6 | 7,7 | 7,8 | 7,9 |
8,0 | 8,1 | 8,2 | 8,3 | 8,4 | 8,5 | 8,6 | 8,7 | 8,8 | 8,9 |
9,0 | 9,1 | 9,2 | 9,3 | 9,4 | 9,5 | 9,6 | 9,7 | 9,8 | 9,9 |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
A | B | C | D | E | F | G | H | 我 | J |
现在,我们将使用雪碧图添加另一行图片
for(i=0;i<10;i++){
var a=[[5,5],[31,5],[57,5],[5,31],[31,31],[57,31],[5,57],[31,57],[57,57],[5,31]][i];
theTable.$.cell(12,i,{padding:"5px 0 10px"}).$.setSprite("spritesheet.png",-a[0],-a[1],16,16);
}
我无法在 Code Project 文章中设置元素的背景。演示中的其他所有内容都超出了我能在 Code Project 文章中展示的范围。完整演示请访问 这里。
顺便说一句,使用雪碧图而不是图片是加快应用程序速度的好方法。Stitches 是一个非常棒的创建雪碧图的工具。
最后,我们将添加一些代码来高亮显示随机单元格
var currentCell = null;
setInterval(function(){
if(currentCell)currentCell.style.background="";
var i = Math.floor(Math.random() * 11), j = Math.floor(Math.random() * 10);
currentCell = theTable.$.cell(i,j,{background:"#ffff76"});
},
1000
);
我们可以重构“闪烁单元格”代码,并将其封装在一个自定义的 Jooshe 类中
var i, j, theTable = new table({marginTop:"40px"});
createClass("flashyCell",
function(i,j){return new td({padding:"5px 10px"},this,null,{innerHTML: i + "," + j});},
{$:{
flashNext:function(){
this.el.style.background = "";
var i = Math.floor(Math.random() * 10),
j = Math.floor(Math.random() * 10),
nextCell = theTable.$.cell(i,j,{background:"#ffff76"});
setTimeout(function(){nextCell.$.flashNext();},1000);}
}
}
);
for(i=0;i<10;i++) for(j=0;j<10;j++) theTable.$.cell(i,j,new flashyCell(i,j));
document.body.appendChild(theTable);
theTable.$.cell(0,0).$.flashNext();
有灵感吗?
将您的文章链接发送到 | 我将在那里列出。 |
如果您希望您的演示在 jooshe.org 上托管,请将您的演示文件包含在电子邮件中,我将向您发送 jooshe.org 上的永久链接。
别忘了投票、推特、点赞和喜欢这篇文章(顶部的按钮):)
关注点
- 我多年前开发了 Jooshe 来处理 dbiScript 的动态需求。
- dbiScript 目前包含 350 个 Jooshe 类,其中包括 230 个 Jooshe 表格的类实例。
- 如果您对大型 Jooshe 应用程序的性能感到好奇,请 下载 dbiScript,亲自看看。