CSS Scripting– Table Layout
CSS Script HTML Table Emulation
In Example 1 we present a CSS Scripting Layout policy that emulates a HTML table. For comparison we display the emulation in green overlaying a HTML table in blue containing the same content. The Script table layout is able to achieve a better content distribution consuming less screen space as can be seen in Figure 1.
Example 1 – HTML Table
The HTML in Example 1 produces the screen shot in Figure 1.
Example 1 – Html Table Overlay
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>HTML Table Overlay</title>
<style type="text/css">
@layout-policy HTMLTable {
initial-script: "\
function setNumColumns(nc,space) {\
if (arguments.length>1) spacing=space;\
if (numColumns!=nc) {\
numColumns=nc;\
columns = new Array(numColumns);\
for(var i=numColumns; --i>=0;) {\
var column = columns[i] = new Object;\
column.rects = rectangles(i,container.numChildren,numColumns);\
}\
numRows = Math.ceil(container.numChildren/numColumns);\
rows = new Array(numRows);\
for(var i=numRows; --i>=0;) {\
var row=rows[i] = new Object;\
row.rects = rectangles(i*numColumns,(i+1)*numColumns);\
}\
}\
}\
var rows = null;\
var columns = null;\
var numColumns=0;\
var numRows=0;\
var widthDeficit = false;\
var excessiveHeight = false;\
var defaultHeight,defaultWidth;\
var spacing=0;\
function deriveWidth() {\
var width = (numColumns+1)*spacing;\
widthDeficit = true;\
for(var i=numColumns; --i>=0;) {\
var rects = columns[i].rects;\
widthDeficit &= rects.preferred_width.max > rects.current_width.max;\
width += rects.preferred_width.max;\
}\
return width;\
}\
function deriveHeight() {\
var height= (numRows+1)*spacing;\
excessiveHeight = false;\
for(var i=numRows; --i>=0;) {\
var rects = rows[i].rects;\
excessiveHeight |= rects.max_height.max > rects.preferred_height.max;\
height+= rects.preferred_height.max;\
}\
if (excessiveHeight) excessiveHeight = rectangles.size_deficit.eq(true).length == 0;\
return height;\
}\
function deriveRows() {\
for(var i=0; i<numRows; ++i) {\
var row = rows[i];\
var rects = row.rects;\
row.height = rects.preferred_height.max;\
if (i==0) {\
row.top = spacing;\
row.bottom = row.height+spacing;\
} else {\
row.top = rows[i-1].bottom+spacing;\
row.bottom = row.top+row.height;\
}\
}\
}\
function deriveColumns() {\
if (!excessiveHeight) {\
var pie=0;\
var usable_width=(widthDeficit?defaultWidth:container.current_width)-(numColumns+1)*spacing;\
for(var i=numColumns; --i>=0;) {\
var column = columns[i];\
var rects = column.rects;\
var isPliant = column.pliant = column.pliant !== false && rects.pliant.eq(false).length == 0;\
if (!isPliant) {\
usable_width -= column.portion = rects.min_width.max;\
} else {\
pie += column.portion = rects.preferred_width.max;\
}\
}\
var ratio=usable_width/pie;\
for(var i=0; i<numColumns; ++i) {\
var column = columns[i];\
column.width = column.pliant ? column.portion*ratio : column.portion;\
column.left = i!=0?columns[i-1].left+columns[i-1].width+spacing:spacing;\
}\
}\
}\
";
rectangle-attributes: '{\
"column":"columns[rectangle.position%numColumns]",\
"row":"rows[Math.floor(rectangle.position/numColumns)]",\
"max_height":"rectangle.preferred_height>=rectangle.current_height?\
rectangle.preferred_height:rectangle.current_height",\
"max_width":"rectangle.preferred_width>=rectangle.current_width?\
rectangle.preferred_width:rectangle.current_width",\
"pliant":"rectangle.pliant!==false&&rectangle.preferred_width<=rectangle.current_width",\
"size_deficit":"rectangle.preferred_width>rectangle.current_width\
||rectangle.preferred_height>rectangle.current_height",\
"min_width":"rectangle.pliant?0:rectangle.preferred_width"\
}';
container-script: "\
if (numColumns<=0) setNumColumns(Math.ceil(Math.sqrt(container.numChildren)));\
if (sizing) {\
defaultWidth=deriveWidth();\
defaultHeight=deriveHeight();\
} else {\
deriveRows();\
deriveColumns();\
}\
";
top:"rectangle.row.top";
left:"rectangle.column.left";
height:"rectangle.row.height";
width:"rectangle.column.width";
container-width:"defaultWidth";
container-height:"defaultHeight";
}
#body {
border:0px green dotted;
padding:0px;
margin:0px;
position:relative;
layout-policy: "HTMLTable";
initial-script: "setNumColumns(4,2);";
container-width:100%;
}
.text {
margin:0px;
position:absolute;
color:green;
border:1px green solid;
padding:0px;
}
span {
float:left;
border:1px red solid;
}
/*
html table rules
display:none;
*/
.table {
border:0px blue dotted;
margin:0px;
padding:0px;
}
.ttext {
margin:0px;
color:blue;
border:1px blue solid;
padding:0px;
vertical-align:top;
}
</style>
</head>
<body id='body'>
<table class='table' cellspacing='2'>
<tr class='ttext'>
<td class='ttext'>
CSSScript in green HTML in blue...
</td>
<td class='ttext'>
Fusce enim sem, ornare in ornare nec, ornare sed neque. Ut sed felis orci, in pretium lectus. Cras nec felis sed nibh venenatis dignissim in sit amet massa.
</td>
<td class='ttext'>
veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?
</td>
<td class='ttext'>
Cras posuere metus at ligula posuere in consequat lorem malesuada.
</td>
</tr>
<tr class='ttext'>
<td class='ttext'>
Nulla facilisi. Aliquam ultrices consequat rutrum.
</td>
<td class='ttext'>
In hac habitasse platea dictumst.
</td>
<td class='ttext'>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
</td>
<td class='ttext'>
Sed scelerisque fringilla ligula at laoreet. Cras posuere metus at ligula posuere in consequat lorem malesuada.
</td>
</tr>
<tr class='ttext'>
<td class='ttext'>
sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima
</td>
<td class='ttext'>
Fusce quis lacus ligula, a dictum metus.
</td>
<td class='ttext'>
vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
</td>
<td class='ttext'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vestibulum fringilla interdum. Fusce suscipit vehicula nunc, nec sagittis risus mollis non. Cras non rhoncus magna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
</td>
</tr>
<tr class='ttext'>
<td class='ttext'>
Cras sodales mollis arcu, quis sagittis tellus euismod eu. Nulla facilisi.
</td>
<td class='ttext'>
Aliquam ultrices consequat rutrum. Quisque pharetra adipiscing porta.
</td>
<td class='ttext'>
Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
</td>
<td class='ttext'>
Nullam sem urna, fringilla tempus aliquet a, ornare non risus.
</td>
</tr>
<tr class='ttext'>
<td class='ttext'>
Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
</td>
<td class='ttext'>
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
</td>
<td class='ttext'>
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
</td>
<td class='ttext'>
Sed id lobortis nulla.
</td>
</tr>
</table>
<div class='text'>
CSSScript in green HTML in blue...
</div>
<div class='text'>
Fusce enim sem, ornare in ornare nec, ornare sed neque. Ut sed felis orci, in pretium lectus. Cras nec felis sed nibh venenatis dignissim in sit amet massa.
</div>
<div class='text'>
veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?
</div>
<div class='text'>
Cras posuere metus at ligula posuere in consequat lorem malesuada.
</div>
<div class='text'>
Nulla facilisi. Aliquam ultrices consequat rutrum.
</div>
<div class='text'>
In hac habitasse platea dictumst.
</div>
<div class='text'>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
</div>
<div class='text'>
Sed scelerisque fringilla ligula at laoreet. Cras posuere metus at ligula posuere in consequat lorem malesuada.
</div>
<div class='text'>
sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima
</div>
<div class='text'>
Fusce quis lacus ligula, a dictum metus.
</div>
<div class='text'>
vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
</div>
<div class='text'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vestibulum fringilla interdum. Fusce suscipit vehicula nunc, nec sagittis risus mollis non. Cras non rhoncus magna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
</div>
<div class='text'>
Cras sodales mollis arcu, quis sagittis tellus euismod eu. Nulla facilisi.
</div>
<div class='text'>
Aliquam ultrices consequat rutrum. Quisque pharetra adipiscing porta.
</div>
<div class='text'>
Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
</div>
<div class='text'>
Nullam sem urna, fringilla tempus aliquet a, ornare non risus.
</div>
<div class='text'>
Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
</div>
<div class='text'>
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
</div>
<div class='text'>
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
</div>
<div class='text'>
Sed id lobortis nulla.
</div>
</body>
</html>
Figure 1 – HTML Table emulation. The Script table in green overlays the HTML table in blue rendering a configuration that consumes less screen space.
This layout renders in less than 16 or up to 32 milliseconds on a Dell LATITUDE D630 Laptop (Intel Core 2 Duo T7500 2.20GHz, 2.49 GB RAM) running MS Windows XP V2002 Service Pack 3.
CSS Script Optimized Table – A Multiphase Layout
In Example 2 we present the same CSS Table Scripting Layout policy of Example 1 followed by an optimization step. The optimization step is achieved through a multiphase layout specification. Layout phases are delimited by colons in a rule’s layout-policy. Phases are executed sequentially in the order in which they appear. Each phase in a multiphase layout executes to completion as an independent layout, i.e. each phase converges to some solution. Subsequent phases begin with the final configuration of the prior phase. This allows the fine tuning of a configuration or any other kind of modification to achieve a desired result.
The Optimization phase defined in the Optimize layout-policy in Example 2 applies a heuristic measure to reduce the total whitespace in the table.
For comparison we display the optimized script table in green overlaying a HTML table in blue containing the same content as in Example 1. The Scripting table layout finds better content distributions resulting in a reduced total area as exhibited in Figure 2.
Example 2 – Optimized Table Layout
The layout-policy defined in Example 2 extends Example 1 and produces the screen shot in Figure 2. The screen width of Figures 1 and 2 is identical.
Example 2 – Optimized Table
@layout-policy Optimize {
initial-script: "\
function deriveColumns() {\
if (!excessiveHeight) {\
var pie=0;\
var usable_width=(widthDeficit?defaultWidth:container.current_width)-(numColumns+1)*spacing;\
var wratio=container.width/(container.height+container.width);\
var hratio=container.height/(container.height+container.width);\
for(var i=numColumns; --i>=0;) {\
var column = columns[i];\
var rects = column.rects;\
var isPliant = column.pliant = rects.pliant.eq(false).length == 0;\
if (isPliant) {\
var colWaste = rects.waste;\
var rowWaste = rects.rowWaste;\
var rowWasteValue = hratio*(rowWaste.avg+(-1)*((0.5)*rowWaste.stddev\
+((-0.3)*(rowWaste.max+rowWaste.min))));\
var colWasteValue= wratio*(colWaste.avg+(-1)*((0.5)*colWaste.stddev\
+((-0.15)*(colWaste.max+colWaste.min))));\
var wasteArea = rowWasteValue-colWasteValue;\
pie += column.portion = rects.preferred_width.max\
+(wasteArea<0?-Math.sqrt(-wasteArea):Math.sqrt(wasteArea));\
} else {\
usable_width -= column.portion = rects.min_width.max;\
}\
}\
pie=usable_width/pie;\
for(var i=0; i<numColumns; ++i) {\
var column = columns[i];\
if (column.pliant) column.width = column.portion*pie;\
column.left = i!=0?columns[i-1].left+columns[i-1].width+spacing:spacing;\
}\
}\
}\
";
rectangle-attributes: '{\
"current_area":"rectangle.current_width*rectangle.current_height",\
"preferred_area":"rectangle.preferred_width*rectangle.preferred_height",\
"waste":"rectangle.current_area-rectangle.preferred_area-rectangle.requiredSpace",\
"requiredSpace":"(rectangle.current_width-rectangle.preferred_width)\
*(rectangle.current_height-rectangle.preferred_height)",\
"rowRectsWaste":"rectangle.row.rects.remove(rectangle).waste",\
"rowWaste":"rectangle.rowRectsWaste.sum+(numColumns-1)*rectangle.rowRectsWaste.min",\
"pliant":"rectangle.preferred_width<=rectangle.current_width"\
}';
}
#body {
layout-policy: "HTMLTable:Optimize";
initial-script: "\
setNumColumns(4,2);\
";
container-width:100%;
border:0px green dotted;
padding:0px;
margin:0px;
position:relative;
}
Figure 2 – The optimized script table in green from Example 2 uses a multiphase layout that applies an optimization that reduces whitespace in the table. The result is a tighter configuration than otherwise possible by a HTML table shown in blue.
Depending on the window size, this layout renders somewhere between 15 and 50 milliseconds on a Dell LATITUDE D630 Laptop (Intel Core 2 Duo T7500 2.20GHz, 2.49 GB RAM) running MS Windows XP V2002 Service Pack 3.
An Optimized Cell Spanning Table
In Example 3 we present a CSS Table Scripting Layout policy that builds on the ideas presented in Examples 1 and 2 further extending capabilities by allowing cells to span multiple rows and columns. Cell spanning is achieved through rectangle-attributes colSpan and rowSpan. These values default to one in the SpanningTable layout-policy. Other classes define rectangle-attributes with colSpan and rowSpan values greater than one.
For comparison we display the Script table in green overlaying a HTML table in blue containing the same content and employing the same spans. As in the prior examples the Scripting table layout finds better content distributions resulting in a reduced total area as exhibited in Figure 3.
Example 3 – Cell Spanning Table Layout
The layout-policy defined in Example 3 produces the screen shot in Figure 3.
Example 3 – Cell Spanning Table
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Cell Spanning Table Overlaying Equivalent HTML</title>
<style type="text/css">
@layout-policy SpanningTable {
initial-script: "\
function fillCell(cell,rect) {\
var undefined;\
var rs=rect.rowSpan;\
var cs=rect.colSpan;\
var row=cell[0];\
var col=cell[1];\
var pos=rect.position;\
while(rs--) {\
var r = rows[row++];\
var x=cs;\
while(x--) r[col+x]=pos;\
}\
col+=cs;\
r = rows[cell[0]];\
if (pos+1!=rectangles.length)\
if (col >= numColumns || r[col]!==undefined) do {\
if (col >= numColumns) {\
r = rows[cell[0]=cell[0]+1];\
col=0;\
}\
while(col<numColumns && r[col]!==undefined) ++col;\
} while(col >= numColumns);\
cell[1]=col;\
}\
function setNumColumns(nc,space) {\
if (arguments.length>1) spacing=space;\
if (numColumns!=nc) {\
numColumns=nc;\
numRows = Math.ceil(rectangles.cellCount.sum/numColumns);\
rows = new Array(numRows);\
for(var i=0;i<numRows;++i) rows[i] = new Array(numColumns);\
var cell = new Array(0,0);\
for(var x=0;x<rectangles.length;++x) fillCell(cell,rectangles[x]);\
for(var i=0;i<numRows;++i) {\
var r=rows[i];\
var row=rows[i] = new Object;\
row.cells=rectangles(r);\
var len=r.length;\
for(var j=len-1;--j>=0;) {\
var k=j+1;\
if (r[j]==r[k]) while(--j>=0 && r[j]==r[k]); r.splice(j+1,k-j-1);\
}\
row.rects=len==r.length?row.cells:rectangles(r);\
}\
columns = new Array(numColumns);\
for(var i=0;i<numColumns;++i) {\
var column = columns[i] = new Object;\
var cells=rows[0].cells(i,i+1);\
var colRects=cells;\
for(var j=1;j<numRows;++j) {\
var r=rows[j].cells[i];\
if (r != colRects[colRects.length-1]) colRects=colRects.append(r);\
cells=cells.append(r);\
}\
column.cells=cells;\
column.rects=colRects;\
}\
for(var i=numRows;--i>=0;) rows[i].bottomRects=rectangles.bottomRow.eq(i);\
for(var i=numColumns;--i>=0;) columns[i].leftRects=rectangles.leftCol.eq(i);\
deriveRows();\
deriveColumns();\
}\
}\
var rows = null;\
var columns = null;\
var numColumns=0;\
var numRows=0;\
var widthDeficit = false;\
var excessiveHeight = false;\
var defaultHeight,defaultWidth;\
var spacing=0;\
function deriveWidth() {\
widthDeficit = true;\
for(var i=numColumns; --i>=0;) {\
var rects = columns[i].leftRects;\
widthDeficit &= rects.preferred_width.max > rects.current_width.max;\
}\
return spacing + columns[numColumns-1].cells.preferred_right.max;\
}\
function deriveHeight() {\
excessiveHeight = false;\
for(var i=numRows; --i>=0;) {\
var rects = rows[i].bottomRects;\
excessiveHeight |= rects.current_bottom.max > rects.preferred_bottom.max;\
}\
if (excessiveHeight) excessiveHeight = rectangles.size_deficit.eq(true).length == 0;\
return spacing + rows[numRows-1].cells.preferred_bottom.max;\
}\
function deriveRows() {\
for(var i=0; i<numRows; ++i) {\
var row = rows[i];\
if (i==0) {\
row.top = spacing;\
} else {\
row.top = rows[i-1].bottom+spacing;\
}\
row.bottom = row.bottomRects.preferred_bottom.max;\
row.height = row.bottom-row.top;\
}\
}\
function deriveColumns() {\
if (!excessiveHeight) {\
var pie=0;\
var usable_width=(widthDeficit?defaultWidth:container.current_width)-(numColumns+1)*spacing;\
for(var i=numColumns; --i>=0;) {\
var column = columns[i];\
var rects = column.rects;\
var isPliant = column.pliant = rects.pliant.eq(false).length == 0;\
if (!isPliant) {\
usable_width -= column.portion = rects.min_width(i).max;\
} else {\
pie += column.portion = rects.portion(i).max;\
}\
}\
var ratio=usable_width/pie;\
for(var i=0; i<numColumns; ++i) {\
var column = columns[i];\
if (i==0) {\
column.left = spacing;\
column.width = column.right = spacing + (column.pliant ? column.portion*ratio : column.portion);\
} else {\
column.left = columns[i-1].right+spacing;\
column.width = column.pliant ? column.portion*ratio : column.portion;\
column.right= column.left + column.width;\
}\
}\
}\
}\
function column(rect) {\
for (var i=0;i<columns.length;++i)\
if (columns[i].rects.contains(rect)) return i;\
}\
function row(rect) {\
for (var i=0;i<rows.length;++i)\
if (rows[i].rects.contains(rect)) return i;\
}\
function spansCol(currentCol){return this.colSpan+this.column-currentCol;}\
function portion(currentCol){\
var nc=this.colSpan-1;\
return nc>0\
?this.preferred_width*(columns[currentCol].width+(nc*spacing)/(nc+1))/this.cellWidth\
:this.preferred_width;\
}\
function min_width(currentCol){\
var mw=0;\
if (!this.pliant) {\
var nc=this.colSpan-1;\
var ratio=nc>0?(columns[currentCol].width+(nc*spacing)/(nc+1))/this.cellWidth:1;\
mw=this.preferred_width*ratio;\
}\
return mw;\
}\
function cellWidth(rect) {\
var c=rect.column;\
var nc=c+rect.colSpan-1;\
return columns[nc].right-columns[c].left;\
}\
";
rectangle-attributes: '{\
"column":"column(rectangle)",\
"row":"row(rectangle)",\
"leftCol":"rectangle.column+rectangle.colSpan-1",\
"bottomRow":"var br=rectangle.row+rectangle.rowSpan-1; br>=numRows?numRows-1:br",\
"portion":"portion",\
"cellWidth":"cellWidth(rectangle)",\
"cellBottom":"rows[rectangle.bottomRow].bottom",\
"spansCol":"spansCol",\
"cellCount":"rectangle.colSpan*rectangle.rowSpan",\
"colSpan":"1",\
"rowSpan":"1",\
"max_height":"rectangle.preferred_height>=rectangle.current_height?\
rectangle.preferred_height:rectangle.current_height",\
"max_width":"rectangle.preferred_width>=rectangle.current_width?\
rectangle.preferred_width:rectangle.current_width",\
"pliant":"rectangle.pliant!==false&&rectangle.preferred_width<=rectangle.current_width",\
"size_deficit":"rectangle.preferred_width>rectangle.current_width\
||rectangle.preferred_height>rectangle.current_height",\
"min_width":"min_width",\
"current_bottom":"rows[rectangle.row].top+rectangle.current_height",\
"preferred_bottom":"rows[rectangle.row].top+rectangle.preferred_height",\
"preferred_right":"columns[rectangle.column].left+rectangle.preferred_width"\
}';
container-script: "\
if (numColumns<=0) setNumColumns(Math.ceil(Math.sqrt(container.numChildren)));\
if (sizing) {\
defaultWidth=deriveWidth();\
defaultHeight=deriveHeight();\
} else {\
deriveRows();\
deriveColumns();\
}\
";
top:"rows[rectangle.row].top";
bottom:"rectangle.cellBottom";
left:"columns[rectangle.column].left";
right:"columns[rectangle.column+rectangle.colSpan-1].right";
container-width:"defaultWidth";
container-height:"defaultHeight";
}
@layout-policy Optimize {
initial-script: "\
function deriveColumns() {\
if (!excessiveHeight) {\
var pie=0;\
var usable_width=(widthDeficit?defaultWidth:container.current_width)-(numColumns+1)*spacing;\
var wratio=container.width/(container.height+container.width);\
var hratio=container.height/(container.height+container.width);\
for(var i=numColumns; --i>=0;) {\
var column = columns[i];\
var rects = column.rects;\
var isPliant = column.pliant = rects.pliant.eq(false).length == 0;\
if (isPliant) {\
var colWaste = rects.columnSpace(i);\
var rowWaste = rects.columnRowSpace(i);\
var rowWasteValue = hratio*((1.0)*rowWaste.avg+(-1)*((0.5)*rowWaste.stddev\
+((-0.3)*(rowWaste.max+rowWaste.min))));\
var colWasteValue= wratio*((1.0)*colWaste.avg+(-1)*((0.5)*colWaste.stddev\
+((-0.15)*(colWaste.max+colWaste.min))));\
var wasteArea = rowWasteValue-colWasteValue;\
var wasteArea = -colWasteValue;\
pie += column.portion = rects.portion(i).max\
+(wasteArea<0?-Math.sqrt(-wasteArea):Math.sqrt(wasteArea));\
} else {\
usable_width -= column.portion = rects.min_width(i).max;\
}\
}\
var ratio=usable_width/pie;\
for(var i=0; i<numColumns; ++i) {\
var column = columns[i];\
if (i==0) {\
column.left = spacing;\
column.width = column.right = spacing + (column.pliant ? column.portion*ratio : column.portion);\
} else {\
column.left = columns[i-1].right+spacing;\
column.width = column.pliant ? column.portion*ratio : column.portion;\
column.right= column.left + column.width;\
}\
}\
}\
}\
function columnSpace(currentCol){\
var nc=this.colSpan-1;\
var ws=this.whiteSpace;\
return nc>0\
?ws*(columns[currentCol].width+(nc*spacing)/(nc+1))/this.cellWidth\
:ws;\
}\
function cellHeight(rect) {\
var r=rect.row;\
var nr=r+rect.rowSpan-1;\
return rows[nr].bottom-rows[r].top;\
}\
function rowSpace(currentRow){\
var nr=this.rowSpan-1;\
var ws=this.whiteSpace;\
return nr>0\
?ws*(rows[currentRow].height+(nr*spacing)/(nr+1))/this.cellHeight\
:ws;\
}\
function columnRowSpace(currentCol){\
var nc=this.colSpan-1;\
var colPortion=nc>0?(this.cellWidth-columns[currentCol].width+(nc*spacing)/(nc+1))/this.cellWidth:0;\
var wasteValue= colPortion*this.whiteSpace;\
var ri=this.row;\
var nr=this.rowSpan;\
while (--nr>=0) {\
var rowRects=rows[ri+nr].rects.remove(this);\
var space=rowRects.rowSpace(ri+nr);\
if (colPortion>0) {\
var rowPortion=colPortion*this.rowSpace(ri+nr);\
wasteValue += space.sum+(numColumns-1)*(space.min<rowPortion?space.min:rowPortion);\
} else {\
wasteValue += space.sum+(numColumns-1)*space.min;\
}\
}\
return wasteValue;\
}\
";
rectangle-attributes: '{\
"cellHeight":"cellHeight(rectangle)",\
"whiteSpace":"rectangle.current_area-rectangle.preferred_area-\
rectangle.requiredSpace",\
"current_area":"rectangle.current_width*rectangle.current_height",\
"preferred_area":"rectangle.preferred_width*rectangle.preferred_height",\
"columnSpace":"columnSpace",\
"columnRowSpace":"columnRowSpace",\
"rowSpace":"rowSpace",\
"requiredSpace":"(rectangle.current_width-rectangle.preferred_width)\
*(rectangle.current_height-rectangle.preferred_height)",\
"rightWaste":"(rectangle.current_width-rectangle.preferred_width)\
*rectangle.current_height",\
"pliant":"rectangle.preferred_width<=rectangle.current_width"\
}';
}
#body {
border:0px green dotted;
padding:0px;
margin:0px;
position:relative;
layout-policy: "SpanningTable:Optimize";
initial-script: "setNumColumns(4,2);";
container-width:100%;
}
.text {
margin:0px;
position:absolute;
color:green;
border:1px green solid;
padding:0px;
}
.bigger {
rectangle-attributes: '{\
"rowSpan":"2",\
"colSpan":"2",\
}';
}
.taller {
rectangle-attributes: '{\
"rowSpan":"2",\
}';
}
.wider {
rectangle-attributes: '{\
"colSpan":"2",\
}';
}
.widest {
rectangle-attributes: '{\
"colSpan":"3",\
}';
}
/*
html table rules
*/
.table {
border:0px blue dotted;
margin:0px;
padding:0px;
}
.ttext {
margin:0px;
color:blue;
border:1px blue solid;
padding:0px;
vertical-align:top;
}
</style>
</head>
<body id="body">
<table class="table" cellspacing="2">
<tr class="ttext">
<td class="ttext">
CSSScript in green HTML in blue...
</td>
<td class="ttext">
Fusce enim sem, ornare in ornare nec, ornare sed neque. Ut sed felis orci, in pretium lectus. Cras nec felis sed nibh venenatis dignissim in sit amet massa.
</td>
<td class="ttext" rowSpan="2">
veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?
In hac habitasse platea dictumst.
veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?
In hac habitasse platea dictumst.
veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?
In hac habitasse platea dictumst.
</td>
<td class="ttext">
Cras posuere metus at ligula posuere in consequat lorem malesuada.
</td>
</tr>
<tr class="ttext">
<td class="ttext" colSpan="2">
Nulla facilisi. Aliquam ultrices consequat rutrum.
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
</td>
<td class="ttext" rowSpan="2">
Sed scelerisque fringilla ligula at laoreet. Cras posuere metus at ligula posuere in consequat lorem malesuada.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vestibulum fringilla interdum. Fusce suscipit vehicula nunc, nec sagittis risus mollis non. Cras non rhoncus magna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
</td>
</tr>
<tr class="ttext">
<td class="ttext" colspan="3">
sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima
Fusce quis lacus ligula, a dictum metus.
vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
</td>
</tr>
<tr class="ttext">
<td class="ttext">
Cras sodales mollis arcu, quis sagittis tellus euismod eu. Nulla facilisi.
</td>
<td class="ttext">
Aliquam ultrices consequat rutrum. Quisque pharetra adipiscing porta.
</td>
<td class="ttext" colSpan="2" rowSpan="2">
Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
Nullam sem urna, fringilla tempus aliquet a, ornare non risus.
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
Sed id lobortis nulla.
</td>
</tr>
<tr class="ttext">
<td class="ttext">
Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
</td>
<td class="ttext">
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
</td>
</tr>
</table>
<div class="text">
CSSScript in green HTML in blue...
</div>
<div class="text">
Fusce enim sem, ornare in ornare nec, ornare sed neque. Ut sed felis orci, in pretium lectus. Cras nec felis sed nibh venenatis dignissim in sit amet massa.
</div>
<div class="text taller">
veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?
In hac habitasse platea dictumst.
veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?
In hac habitasse platea dictumst.
veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?
In hac habitasse platea dictumst.
</div>
<div class="text">
Cras posuere metus at ligula posuere in consequat lorem malesuada.
</div>
<div class="text wider">
Nulla facilisi. Aliquam ultrices consequat rutrum.
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
</div>
<div class="text taller">
Sed scelerisque fringilla ligula at laoreet. Cras posuere metus at ligula posuere in consequat lorem malesuada.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vestibulum fringilla interdum. Fusce suscipit vehicula nunc, nec sagittis risus mollis non. Cras non rhoncus magna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
</div>
<div class="text widest">
sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima
Fusce quis lacus ligula, a dictum metus.
vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
</div>
<div class="text">
Cras sodales mollis arcu, quis sagittis tellus euismod eu. Nulla facilisi.
</div>
<div class="text">
Aliquam ultrices consequat rutrum. Quisque pharetra adipiscing porta.
</div>
<div class="text bigger">
Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
Nullam sem urna, fringilla tempus aliquet a, ornare non risus.
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
Sed id lobortis nulla.
</div>
<div class="text">
Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel eros iaculis ac rhoncus nibh tincidunt.
</div>
<div class="text">
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
</div>
</body>
</html>
Figure 3– Optimized Cell Spanning Table. The layout in Example 3 extends the ideas and techniques applied in Examples 1 and 2. The Script table in green achieves better results than an equivalent HTML table.
Depending on the window size and V8 JavaScript garbage collection events, this layout renders somewhere between 50 and 250 milliseconds and most often under 100 milliseconds on a Dell LATITUDE D630 Laptop (Intel Core 2 Duo T7500 2.20GHz, 2.49 GB RAM) running MS Windows XP V2002 Service Pack 3.