Table-to-JSON
lightswitch05.github.io
lightswitch05.github.io
I'm not trying to sound harsh, I just don't understand when I'd ever need to do something like this.
tableName.rows[rowNum].cells[cellNum]
Instead of loading all of that into a variable (a second time, it's already an object on your page), trying to keep it in sync, binding events in both directions to keep it in sync, the load of doing twice the work, the lag of redrawing the entire table every time you want to do something, etc..
I don't see why this is cleaner than working on the DOM. I've done this a number of times and only found headaches when trying to build something larger than a silly toy or a list of 30 items on a table. IIRC DataTables did something like this internally last time I looked at it, and that thing konks out and either slows down your page or crashes the browser depending on how many cells you load into it.
Also, for things like plain-text searching, it's faster to do it on a collection of objects detached from the DOM in JavaScript than to scan the DOM, and especially if you're doing non-text comparisons (like comparing a number with the parseFloat representation of the values in one of the table columns for all rows).
And finally, if you are going to read and then redraw in the DOM, it's best to do it as grouped atomic operations due to the inefficiency making the browser reflow (https://developers.google.com/speed/articles/reflow).
For what it's worth, this is how Dynatable works internally, though I haven't had any issues with it being slow, though it's possible I just haven't used it with large enough data sets yet (I've only used it on tables of probably 1000 rows or less so far).
Why not just send back to the server instead? First, sending the JSON back turned out to be faster than rerunning the query. Second, datatables has a full text search option which made things simpler for our case.
(Datatables has an export plugin, but it uses flash and only generates thinly-veiled CSV.)
So there's a use case for something like this.
What if you have headings as the first column in each row? What if you have headings in the first column, and the first row?
Also, what is the use case for data overrides? In my opinion, it completely defeats the purpose when your intention is to take the contents of the table.
var getHeadings = function(table) {
var firstRow = table.find("tr:first").first();
return notNull(opts.headings) ? opts.headings : rowValues(firstRow);
};
The code is also going to fall down if you have things like wide/high cells. But HTML tables are so flexible and so routinely abused, I guess the problem is too hard to be solved robustly with any generality. table.find('thead tr').children('th,td')
But it could easily be something like: var headings = table.find('thead th');
if (!headings.length) headings = table.find('th');
if (!headings.length) headings = table.find('tr:first td');http://www.whatwg.org/specs/web-apps/current-work/multipage/...
This was developed with reference to a corpus of real web tables.
At any rate, it seems like trying to implement their algorithm verbatim in javascript would be pretty slow for large tables. Maybe it's better to just use it for inspiration.
Also, their algorithm seems to come at if from the perspective of, "I have a cell, what is its header?" It would be more efficient in reverse, if we could instead answering the question, "I have a header, what are its cells?". What dynatable does now is sort of a hybrid approach (we find the header cells, make a dictionary, then loop through the rows, assigning each cell value to its attribute in the dictionary). The issue is, according to that article, any table cell could potentially be a header cell, not just those in the header row or in th elements.
It's an alternative to the Datatables plugin. All its logic works on the set of data in JSON, so it first translates an html table into JSON, then vice versa.
The cool thing about this process is, you can write your own translate step to easily work with e.g. JSON from an Ajax request. And you can write your own render step to work with e.g. a styled list instead of a table.
By default, the translate step translates an html table to a JSON object, naming the attributes by the table column headings (underscore format by default, but can be hyphenated, snake-case, or lower-case too).
[1] http://os.alfajango.com/dynatable
EDIT: If anyone is interested, the part of the plugin that essentially does the "table to JSON" part is the getFromTable function here: https://github.com/JangoSteve/jquery-dynatable/blob/master/j...
Other useful things this function does is, determines whether the data is a string, number, boolean, or date (or other user-defined type) to do proper column sorting logic, and much more.
EDIT 2: Also, I can't speak for the author of the table-to-json plugin, but for dynatable, it's useful to have data-override values for the cells for cases like when you have a date in "Jan 1, 2013" format, which is meaningless when doing filter or sorting operations on the JSON; i.e. you could use the data-override to populate the proper date format so JS knows how to process it.
To add to your list, there is of course that old chestnut of "it doesn't support the full tables spec" (which in all fairness is quite complex).
Wouldn't it be nicer to make the default format an object of arrays rather than an array of objects?
In before "but gzip!"
Nice work!
Would have been nice for some Google Finance data I'm scraping in python.