A Grid in jQuery
Posted in Kiloblog, Professional, Software Development | Leave a Comment
After a disappointing start with jQuery:
- No clear strategy to preserve state of custom objects.
- No response to questions in the jQuery discuss mailing list.
As a result, I fetched the Yahoo UI Library and Jack Slocum’s Yahoo UI Extension Library. That grid worked well in Internet Explorer 6 and in Firefox. In Safari, the column resize seemed to fail.
Nice. A bit heavy. There are a lot of dependencies. A lot of features that I don’t really need. I can turn them off, but the code and the complexity are still present. In essence, I wanted a table that had a sticky headers.
I found that state is stored in jQuery fancy-pants extensions by creating a hash and attaching it to the target element. I don’t know why that couldn’t have been said on jQuery discuss.
I’d imagined that there was some limitation, that not all browsers supported “expando” properties on document elements, but it must not be the case.
Here is the simple table that I’ve created in jQuery. No resizable columns.
This works on IE 6, Firefox 1.5 and Safari 2.0.4.
It was only possible once I’d abandoned table markup, however. The table is rendered with div and span elements, rather than table, tbody, tr, td, etc.
Much easier. The implementation of tables has a lot of baggage attacted to it.
However, I’m not finding that it doesn’t scale. The rendering causes the “Unresponsive Script” warning in Firefox when the table is large.
In the course of creating this grid, I fixed the innerWidth and innerHeight methods of dimensions.js, which incorrectly named the border properites, “borderLeft” instead of “borderLeftWidth”, and neglected to deduct the padding width.
Update: I’ve addressed some of the performance issues of loading the table. The time that it takes to load this new revision is greatly reduced. Speed up is a factor of ten.
I build the cells as spans, so that I can measure the width of the text, when rendered as a span, an inline element, this is possible. A assign a class name for the span, based on it’s column position. Then I’d set the dispaly property of the span to block. In the end, I’ll define a CSS class for each column, with the width set to the maximum width for that span.
By removing the assignment of the display property of the span, I got my speed up.
I also speed up loading by measuring the border and padding for each column once, rather than calculating the inner width for each column, I keep track check the offset width, and calculate the innner width by dedcuting the total of all borders and padding of the first from form the offset width. The assumes that the styles for each column are identical in all rows (which is perfectly reasonable and all I need).
It still chokes on the large datasets that I’m using, 500+ rows. For my next trick, I’m going to load incrementally, so that the unresponsive script warning does not appear.
The grid will render much faster if I have a set width, of course. I can create an optimized rendering method that builds a large HTML string and injects it, 100 rows at a time, in the case of resorting, or in the case where I’ve assigned widths to all the columns.
Update: The grid now renders concurrently. Different browsers prefer different combinations of rows per timeout and time between timeout.
The important thing is that the page is responsive. The user can scroll the grid while it loads, the back button and other controls still work.
The key tradeoff is that the slower the grid loads, the more responsive it is.
Rendering is faster in this incarnation. Absolute positioning is much faster that relative layout. Much faster than laying out the grid as blocks that float left.
Leave a Reply