65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (5投票s)

2013年12月23日

MIT

7分钟阅读

viewsIcon

21934

downloadIcon

118

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,00,10,20,30,40,50,60,70,80,9
1,01,11,21,31,41,51,61,71,81,9
2,02,12,22,32,42,52,62,72,82,9
3,03,13,23,33,43,53,63,73,83,9
4,04,14,24,34,44,54,64,74,84,9
5,05,15,25,35,45,55,65,75,85,9
6,06,16,26,36,46,56,66,76,86,9
7,07,17,27,37,47,57,67,77,87,9
8,08,18,28,38,48,58,68,78,88,9
9,09,19,29,39,49,59,69,79,89,9

现在,让我们在前面添加一行

theTable.$.prependRow();

for(i=0;i<10;i++) theTable.$.cell(0,i,{padding:"10px 0",textAlign:"center"},{innerHTML:i});

我们的表格现在看起来像这样:

0123456789
0,00,10,20,30,40,50,60,70,80,9
1,01,11,21,31,41,51,61,71,81,9
2,02,12,22,32,42,52,62,72,82,9
3,03,13,23,33,43,53,63,73,83,9
4,04,14,24,34,44,54,64,74,84,9
5,05,15,25,35,45,55,65,75,85,9
6,06,16,26,36,46,56,66,76,86,9
7,07,17,27,37,47,57,67,77,87,9
8,08,18,28,38,48,58,68,78,88,9
9,09,19,29,39,49,59,69,79,89,9

现在,我们将所有底部行单元格的字体粗细设置为粗体

o = theTable.$.lastRow();
for(i=0;i<10;i++) o.$.cell(i,{fontWeight:"bold"});
0123456789
0,00,10,20,30,40,50,60,70,80,9
1,01,11,21,31,41,51,61,71,81,9
2,02,12,22,32,42,52,62,72,82,9
3,03,13,23,33,43,53,63,73,83,9
4,04,14,24,34,44,54,64,74,84,9
5,05,15,25,35,45,55,65,75,85,9
6,06,16,26,36,46,56,66,76,86,9
7,07,17,27,37,47,57,67,77,87,9
8,08,18,28,38,48,58,68,78,88,9
9,09,19,29,39,49,59,69,79,89,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]}
  );
0123456789
0,00,10,20,30,40,50,60,70,80,9
1,01,11,21,31,41,51,61,71,81,9
2,02,12,22,32,42,52,62,72,82,9
3,03,13,23,33,43,53,63,73,83,9
4,04,14,24,34,44,54,64,74,84,9
5,05,15,25,35,45,55,65,75,85,9
6,06,16,26,36,46,56,66,76,86,9
7,07,17,27,37,47,57,67,77,87,9
8,08,18,28,38,48,58,68,78,88,9
9,09,19,29,39,49,59,69,79,89,9
ABCDEFGHJ

现在,我们将向表格添加一行图片

for(i=0;i<10;i++) theTable.$.cell(11,i,{padding:"5px 0 10px"}).$.setImage("ball"+(i%2)+".png");
0123456789
0,00,10,20,30,40,50,60,70,80,9
1,01,11,21,31,41,51,61,71,81,9
2,02,12,22,32,42,52,62,72,82,9
3,03,13,23,33,43,53,63,73,83,9
4,04,14,24,34,44,54,64,74,84,9
5,05,15,25,35,45,55,65,75,85,9
6,06,16,26,36,46,56,66,76,86,9
7,07,17,27,37,47,57,67,77,87,9
8,08,18,28,38,48,58,68,78,88,9
9,09,19,29,39,49,59,69,79,89,9
ABCDEFGHJ

现在,我们将使用雪碧图添加另一行图片

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 Tables 的可能性感到兴奋,请考虑撰写您自己的 Code Project 文章,展示您如何使用它,并在您的文章中包含指向本文的链接。
将您的文章链接发送到  我将在那里列出。

如果您希望您的演示在 jooshe.org 上托管,请将您的演示文件包含在电子邮件中,我将向您发送 jooshe.org 上的永久链接。

别忘了投票、推特、点赞和喜欢这篇文章(顶部的按钮):)

关注点

  • 我多年前开发了 Jooshe 来处理 dbiScript 的动态需求。
  • dbiScript 目前包含 350 个 Jooshe 类,其中包括 230 个 Jooshe 表格的类实例。
  • 如果您对大型 Jooshe 应用程序的性能感到好奇,请 下载 dbiScript,亲自看看。

Jooshe 在网络上

© . All rights reserved.