Fattable.js Gives You Infinite Scrolling Tables

If you have lots of data, it’s easier to keep it neat and clean if you put them in a table. By ‘lots of data’, what I mean here is in the range of hundreds. If your data needs more than 10,000 cells, basically, a big table, DOM just won’t cut it, as you’ll most likely start getting choppy scrolling. Introducing Fattable.js, a javascript library to help you with that problem.

Fattable.js is a javascript Library that helps create a table with infinite scrolling capabilities, with an infinite number of rows and columns. It can also help when clients are unable to download or retain the immense volumes of table data – Fattable.js lets you load your data asynchronously. Check out the demo here.

API And Painter

Fattable has the following APIs to be used. These APIs are used for building the table automatically. You can specify the row height and column width here.

 var table = fattable({ "painter": painter, // your painter (see below) "model": model, // model describing your data (see below) "nbRows": 1000000, // overall number of rows "rowHeight": 35, // constant row height (px) "headerHeight": 100, // height of the header (px) "columnWidths": [300, 300, 300, 300] // array of column width (px) }) 

painter is an object, which is used to fill the content of your cells and column headers. It is expected to implement the following interface.

 var painter = { "setupHeader": function(headerDiv) { /* Setup method are called at the creation of the column header. That is during initialization and for all window resize event. Columns are recycled. */ } , "setupCell": function(cellDiv) { /* The cell painter tells how to fill, and style cells. Do not set height or width. in either fill and setup methods. */ } , "fillHeader": function(headerDiv, data) { /* Fills and style a column div. Data is whatever the datalayer is returning. A String, or a more elaborate object. */ colHeaderDiv.textContent = data; } , "fillCell": function(cellDiv, data) { /* Fills and style a cell div. Data is whatever the datalayer is returning. A String, or a more elaborate object. */ cellDiv.textContent = data; } , "fillHeaderPending": function(headerDiv) { /* Mark a column header as pending. When using an asynchronous. Its content is not in cache and needs to be fetched */ cellDiv.textContent = "NA"; } , "fillCellPending": function(cellDiv) { /* Mark a cell content as pending Its content is not in cache and needs to be fetched */ cellDiv.textContent = "NA"; } }; 

Actually, this very simple implementation is the default. And it is available as fattable.Painter, so that you can just override it.

Data Layer

If your data isn’t too big, you could probably just fetch it all at once, and then display the table. For this simple case, the best solution is to extend the SyncTableData object.

You just need to extend fattable.SyncTableModel and implement the following methods:

 { "getCellSync": function(i,j) { return "cell " + i + "," + j; }, "getHeaderSync": function(i,j) { return "col " + j; } } 

Asynchronous And Paged Async

You probably don’t want your backend to receive one request per cell that is displayed. A good solution to this problem is to partition your table into pages of cells.

Queries are only sent when the user stops scrolling.

To use such a system, you just have to extend the PagedAsyncTableModel class with the following methods. In addition, it includes a simple LRU cache.

 { "cellPageName": function(i,j) { // returns a string which stands for the id of // the page the cell (i,j) belongs to. var I = (i / 128) | 0; var J = (j / 29) | 0; return JSON.stringify([I,J]); }, "fetchCellPage": function(pageName, cb) { // Async method to return the page of var coords = JSON.parse(pageName); var I = coords[0]; var J = coords[1]; getJSON("data/page-" + I + "-" + J + ".json", function(data) { cb(function(i,j) { return { rowId: i, content: data[i-I*128][j-J*29] }; }); }); }, "headerCellPage" : function(j) { // Same as for cellPageName but for cells. }, "fetchHeaderPage" : function(j) { // Same as for fetchCellPage but for headers } } 

Final Thoughts

If you’re planning on using <!DOCTYPE html>with the library, then it has to be with the more recent versions of IE, as anything preceeding IE9 isn’t supported. The library currently uses a huge container with overflow. Browsers have a bit of a limitation when it comes to the size of such a container. Therefore, expect some bugs to appear at 40,000 rows into IE and 50,000 rows into other browsers.


Leave a Comment