Abstract
This document is inted to provide a detailed review of the Document Object Model and Cascading Style Sheet implementation used to create the Datagrid contro. The information provided here is not Javeline specific
Before I foreget, truly sorry about the example colors used here. I realize they are disgustingly ugly but they are just for demonstration purposes.
Step 1: Set up the Primary Grid Areas
We have set up 5 primary grid areas. These are from a css standpoint:
- .datagrid{width:100%;position:relative;height:200px;}
- .datagrid .feedback{z-index:10; position:absolute; width:100%; top:0px; left:0px; right:0px; height:25px;}
- .datagrid .headings{z-index:5; position:absolute; width:100%; top:25px; left:0px; right:0px; height:24px;}
- .datagrid .content{z-index:1; display:block; width:100%; height:150px; position:absolute; top:50px; left:0px; right:0px; bottom:25px; overflow:auto}
- .datagrid .footer{z-index:5; position:absolute; width:100%; bottom:0px; left:0px; right:0px; height:24px;}
Step 2: Set up the Content Columns
One the big mistakes developers make in creating a grid interface is thinking along the lines of a HTML table object. You have to realize that the selection of a row of data is merely a function of the interface and that selecting it simply does not mean you are putting borders and or background on a element that represents the row. The only think you need to know about row selection is the vertical position of the row.
There is more functional requirements within a column that within a row. Such as resizing, sliding left or right or hiding and of course slicing text that overflows the column. In order to facilitate speed you want to be able to simply resize a master column div for each column and let the browser do the rest for you. If you doing dom iteration on row cells or modifying css your asking the browser to do a lot more than it really needs to.
For arguments sake lets assume we have 4 columns each 25% of width:
Notice and this is important, that there are no borders on the column divs. Borders, padding and margin makes your life a real nightmare because they impact on the width of a column and that is exactly what you do not want. You want to keep things as simply as possible. The CSS for the columns is as follows:
- .datagrid .content .columns{position:absolute; height:100%; top:0px; left:0px; bottom:0px; overflow:hidden}
I will talk about the implementing the headers a little later on as this has several layers for effect and positioning.
Step 3: Setting up the Rows
Rows are real simple and again they are fixed position. Each cell exists within its column and has a set height, top, left and width. The CSS handles the positioning all we have to do inline is set the top in pixels.
Depending on the browser you are running you will see some slight differences. In all supported browsers you will see the long text truncated. In IE7 and Safari you will see ellipsis following the truncated text but not in Firefox as it does not support the text-overflow:ellipsis setting. In IE6 the text is truncated but runs right up the edge of the column which is, in my opinion, pretty ugly. We will deal with this situation in Dealing with Column Percentage and Sizing document. The CSS for the cell is as follows:
- .datagrid .column .cell{position:absolute;top:0px;left:5px;right:5px;height:25px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-right:5px}
Step 4: Setting up the Header Columns
Like the Content Columns the header DIV contains column divs with the same sizing as the content columns but there is some layering in effect on the headings in order to provide visual feedback on mouse actions. The layer order is as follows:
- Effect Layer [z-index:8] - Takes all of the mouse events such as mouseover, mouseout and click. Has a cross browser transparency setting of 1% in order to ensure mouse events are caught in IE. Basically a transparent event grabber.
- Floating Object Layer [z-index:7] - Floating horizontal object that there are only ever one instance of such as the sort image and drop menu image
- Label Layer [z-index:5] - Fix x layer that holds the column label align with Effect Layer.
- Selected Layer [z-index:3] - Floating horizontal object that aligns it's self under the Effect layer on mouse over.
- Highlight Layer [z-index:4] - Floating horizontal object that aligns it's self under the Effect layer on mouse click.
The actual css styles are as follows:
- .datagrid .headings .effect{z-index:8;position:absolute; top:0px; bottom:0px; left:0px; cursor:pointer;moz-opacity:.1;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=10); khtml-opacity:0.1; opacity:0.1;background:#ffffff}
- .datagrid .headings .label{z-index:5;position:absolute; top:0px; bottom:0px; left:2px; white-space:nowrap; overflow:hidden;text-overflow:ellipsis; border:none;vertical-align:bottom;padding-top:5px}
- .datagrid .headings .selected{z-index:3;position:absolute; top:0px; bottom:0px; left:0px;background:url(images/st.bg.on.jpg) repeat-x bottom left;display:none}
- .datagrid .headings .highlight{z-index:4;position:absolute; top:0px; bottom:0px; left:0px;background:url(images/st.bg.highlight.jpg) repeat-x bottom left;display:none}
Step 5: Setting up the Vertical Resizer Bars
The vertical sizer bars sit at the root of the datagrid object and are simply a fixed position DIV object the entire height of the grid but sit behind the feedback and headings dom objects via the z-index. The css is as follows:
- .datagrid .resizer{z-index:8;position:absolute; top:0px; left:0px; bottom:0px; width:4px; cursor:col-resize; background:#ffffff url(images/resizerbar.gif) repeat-y top right; padding:0; }
Step 6: Lets drop the Ugly Colors as I have a Migrain Comming on...
Thats all of the basic structure of the datagrid DOM. I will now display it without all the ugly colors:
I did not mention above as it seemed rather redundant at the time. In order to provide for multi select the content columns are wrapped in a DIV with a class of rows. There is a second DIV under content with a class of selectors. These two divs are there to help in improve in performace with regards to DOM walking.
Below is the resulting HTML
<div class="resizer" style="left:25%"></div>
<div class="resizer" style="left:50%"></div>
<div class="resizer" style="left:75%"></div>
<div class="resizer" style="left:99.8%"></div>
<div class="feedback" style="display:block">feedback area</div>
<div class="headings" >
<div class="effect" style="width:25%; left:0%"></div>
<div class="label" style="padding-left:5px; width:25%; left:0%;">Column 1</div>
<div class="effect" style="width:25%; left:25%"></div>
<div class="label" style="padding-left:5px; width:25%; left:25%;">Column 2</div>
<div class="effect" style="width:25%; left:50%"></div>
<div class="label" style="padding-left:5px; width:25%; left:50%;">Column 3</div>
<div class="effect" style="width:25%; left:75%"></div>
<div class="label" style="padding-left:5px; width:25%; left:75%;">Column 4</div>
</div>
<div class="content" >
<div class="rows">
<div class="column" style="width:25%; left:0%">
<div class="cell" style="top:5px">some data</div>
<div class="cell" style="top:25px;">some much long data demoinstrating that the overflow is being cliped</div>
</div>
<div class="column" style="width:25%; left:25%">
<div class="cell" style="top:5px;">some data</div>
<div class="cell" style="top:25px;">some much long data demoinstrating that the overflow is being cliped</div>
</div>
<div class="column" style="width:25%; left:50%">
<div class="cell" style="top:5px;">some data</div>
<div class="cell" style="top:25px;">some much long data demoinstrating that the overflow is being cliped</div>
</div>
<div class="column" style="width:25%; left:75%">
<div class="cell" style="top:5px;">some data</div>
<div class="cell" style="top:25px;">some much long data demoinstrating that the overflow is being cliped</div>
</div>
</div>
<div class="selectors"></div>
</div>
<div class="footer" style="">Footer</div>
</div>
Conclusion
The above DOM and CSS is of course not exactly how it is. There are a couple more items that are added such as the highlighter div and the selector divs plus the header background effects but programatically the above is what is important. Now its time to move onto Step 2 - Dealing with Column Percentage and Sizing