CSS Scripting Layout – Mixing Layout Policies
CSS Script – Line Wrapping
In this example we present a CSS Scripting Layout policy that arranges rectangles left to right and line-wraps rectangles as required depending on the available width. With this line wrapping layout we also present a set of policies that can be included with it to alter fine points of the layout to achieve different effects. These set of policies largely emulate inline layout and associated properties.
The HTML in Example 1 produces the screen shots in Figures 1 and 2.
Example 1 – Line-Wrapping Container
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Line Wrap</title>
<style type="text/css">
@layout-policy line_wrap {
initial-script: "\
var lineSpacing=2;\
function containerHeight() {\
var line = lines[lines.length-1];\
return line.top+line.rects.preferred_height.max;\
}\
function containerWidth() {\
var width=0;\
for(var i=lines.length; --i>=0;) {\
var w = lines[i].preferred_width;\
if (width<w) width=w;\
}\
return width;\
}\
function getLine(position) {\
var i=-1;\
var p=0;\
do {\
p+=lines[++i].rects.length;\
} while (position >= p);\
return lines[i];\
}\
function deriveLines(width) {\
var lines = new Array;\
var list = rectangles;\
do {\
var line = lines[lines.length] = new Object;\
var rects = line.rects = list.preferred_width.cumulate.gt(width);\
if (rects.length==0) rects = line.rects = list(0,1);\
var lineNo = line.number = lines.length;\
line.height=rects.preferred_height.max;\
line.preferred_width=rects.preferred_width.sum;\
if (lineNo>1) {\
line.top=lineSpacing+lines[lineNo-2].bottom;\
line.bottom=line.height+line.top;\
} else {\
line.bottom=line.height;\
line.top=0;\
}\
list = list(rects.length, list.length);\
} while (list.length > 0);\
return lines;\
}\
var defaultHeight;\
var lines = deriveLines(rectangles.preferred_width.sum);\
";
container-script: "\
if (sizing)\
defaultHeight=containerHeight();\
else\
lines = deriveLines(container.width);\
";
rectangle-attributes: '{\
"line":"getLine(rectangle.position)",\
"isFirst":"rectangle.line.rects[0]==rectangle"\
}';
top:"rectangle.line.top";
height:"rectangle.preferred_height";
left:"rectangle.isFirst ? 0 : predecessor.right";
container-height:"defaultHeight";
container-width:"containerWidth()";
}
@layout-policy vcenter {
container-script: "\
if (!sizing)for(var i=lines.length; --i>=0;) {\
var line = lines[i];\
line.center = line.top+line.height/2;\
}\
";
top:none;
vertical-center:"rectangle.line.center";
}
@layout-policy justify {
container-script: "\
if (!sizing) {\
var w=container.width;\
for(var i=lines.length; --i>=0;) {\
var line = lines[i];\
var rects = line.rects;\
var len=rects.length;\
if (len>1) line.spread = (w-rects.width.sum)/(len-1);\
}\
}\
";
left:"rectangle.isFirst ? 0 : predecessor.right+rectangle.line.spread";
}
@layout-policy fill_line {
container-script: "\
if (!sizing) {\
var w=container.width;\
for(var i=lines.length; --i>=0;) {\
var line = lines[i];\
var rects = line.rects;\
var sum = rects.preferred_width.sum;\
line.space = (w-sum)/sum;\
}\
}\
";
width:"rectangle.preferred_width+(rectangle.line.space*rectangle.preferred_width)";
}
@layout-policy fixed_height {
height:"rectangle.line.rects.preferred_height.max";
}
@layout-policy pack_column {
initial-script: "\
var margin=8;\
var space=(rectangles.length+1)*margin;\
";
width:"container.width";
height:"rectangle.preferred_height";
top:"margin+(predecessor ? predecessor.bottom : 0)";
container-height:"space+rectangles.preferred_height.sum";
container-width:"rectangles.preferred_width.max";
}
#body {
layout-policy:"pack_column";
container-width:100%;
border:0px black solid;
padding:0px;
margin:0px;
position:relative;
}
div {
background:gray;
margin:0px;
border:0px black dotted;
padding:0px;
position:absolute;
}
div button {
margin:0px;
padding:0px;
position:absolute;
}
span {
margin:0px;
border:1px black dashed;
padding:0px;
position:absolute;
}
#line_wrap1 {
layout-policy:"line_wrap";
}
#line_wrap2 {
layout-policy:"line_wrap vcenter";
}
#line_wrap3 {
layout-policy:"line_wrap justify";
}
#line_wrap4 {
layout-policy:"line_wrap vcenter justify";
}
#line_wrap5 {
layout-policy:"line_wrap fill_line";
}
#line_wrap6 {
layout-policy:"line_wrap fill_line fixed_height";
}
</style>
</head>
<body id="body">
<span>
The line wrapping displayed in the following containers illustrates how a mixin set of layout policies can
work together to achieve different effects.
</span>
<div id="line_wrap1">
<span>line_wrap</span>
<button>button 1</button>
<button>button 2</button>
<button>button 3</button>
<button>button 4</button>
<button>button 5</button>
<button>button 6</button>
<button>button 7</button>
<button>button 8</button>
<button>button 9</button>
<button>button 10</button>
<button>button 11</button>
<button>button 12</button>
</div>
<div id="line_wrap2">
<span>line_wrap vcenter</span>
<button>button 1</button>
<button>button 2</button>
<button>button 3</button>
<button>button 4</button>
<button>button 5</button>
<button>button 6</button>
<button>button 7</button>
<button>button 8</button>
<button>button 9</button>
<button>button 10</button>
<button>button 11</button>
<button>button 12</button>
</div>
<div id="line_wrap3">
<span>line_wrap justify</span>
<button>button 1</button>
<button>button 2</button>
<button>button 3</button>
<button>button 4</button>
<button>button 5</button>
<button>button 6</button>
<button>button 7</button>
<button>button 8</button>
<button>button 9</button>
<button>button 10</button>
<button>button 11</button>
<button>button 12</button>
</div>
<div id="line_wrap4">
<span>line_wrap vcenter justify</span>
<button>button 1</button>
<button>button 2</button>
<button>button 3</button>
<button>button 4</button>
<button>button 5</button>
<button>button 6</button>
<button>button 7</button>
<button>button 8</button>
<button>button 9</button>
<button>button 10</button>
<button>button 11</button>
<button>button 12</button>
</div>
<div id="line_wrap5">
<span>line_wrap fill_line</span>
<button>button 1</button>
<button>button 2</button>
<button>button 3</button>
<button>button 4</button>
<button>button 5</button>
<button>button 6</button>
<button>button 7</button>
<button>button 8</button>
<button>button 9</button>
<button>button 10</button>
<button>button 11</button>
<button>button 12</button>
</div>
<div id="line_wrap6">
<span>line_wrap fill_line fixed_height</span>
<button>button 1</button>
<button>button 2</button>
<button>button 3</button>
<button>button 4</button>
<button>button 5</button>
<button>button 6</button>
<button>button 7</button>
<button>button 8</button>
<button>button 9</button>
<button>button 10</button>
<button>button 11</button>
<button>button 12</button>
</div>
</body>
</html>
Figure 1 - Scripted line wrapping layout
Figure 3 - Scripted line wrapping layout in narrow window.