tgrid
tgrid is a jQuery based data grid. I have modified it below to do a few new tricks. the original script came from http://dreakmore.info/tgrid/ I have modified it to add a few new features and tweak ones I didn't much care for.
The process of using the grid involves these three steps:
- Link in the jquery and trgid libraries and CSS.
- Create a table with the desired headings inside a thead.
- Create a script that pipes data from a data source to the grid.
- Create a data source that feeds JSON into the script in step 3.
The table source
This is the most effortless step. A simple table that has the titles you want in the order you want them.
<table class="datagrid" id="m1_table"> <thead><tr> <th style="width: 10px">NID</th> <th style="width: 90px">Title</th> <th style="width: 50px">Start</th> <th style="width: 50px">End</th> <th style="width: 30px">Import.</th> </tr></thead> <tbody /> </table>
Note -- the columns are mapped to the __defined_cols below simply by order.
The linking script
Creating a script to link the data to the table is pretty easy:
function model1(id)
{
// this function is a class definition that contains the information
// tgrid needs to transfer the data from the remote source
// into the table.
this.id = id;
this.__defined_cols =
["nid","title", "start_date", "end_date", "importance"];
this.sortOrder = [[2,1][3,1]];
this.renderers = {
title: _task_title,
start_date: _model_parse_date,
end_date: _model_parse_date};
}
model1.prototype = new jsModel();
var m1 = new model1("m1");
$(document).ready(function(){
$("#m1_table").tgrid({object: m1});
m1.rf();
});
first you create a local class with the table definitions. Then you instantiate it and attach it.
One very important thing to note here is that the renderers hash, keyed to the column list above, is filled with array objects that are part of my custom script.
these custom "column filters" values are ready for two values. the first is the column text given by the column named in __defined_columns. The second is the JSON object of the ENTIRE ROW. This makes it easy to, for instance, assemble a hyperlink in a single column based on several columns (title, id, etc.).
This means as well you are free to completely ignore the passed-in expected columns and remake the data entirely through custom javascript functions if you like.
Undocumented Feature: the sortOrder parameter of the module is very useful -- it allows you to choose which order the table will sort in initially. You can sort by more than one column, in ascending(0) or descending(1) order. In this example, the sortOrder tells the table to load with the columns sorted by startDate (descending) then endDate (descending).
There is no automatic way to set sort orders as multi-column when the user starts clicking on columns -- only one field will be sent through the order_by request variable. you would need to interpret it in the PHP responder to add nuance to a column selection.
Core Settings and Field Filters
The core variable below, in global context, is used by tgrid as a bridge to the datasource. it doesn't appear to be added to any of the below code so I assume it is global to any tgrid elements on the page.
The other functions listed are added to the model above to post-filter the data coming from the JSON to a prettier format. Note that the field value is passed so you can reuse column filters if you want.
function coreSettings(){
this.prefix = "/admin/project_master/tasks/data";
}
var core = new coreSettings();
_months = ['Jan','Feb','Mar','Apr','May','Jun',
'Jul', 'Aug', 'Sep','Oct','Nov','Dec'];
function _model_parse_date(v){
if(!v) return ' ';
var va = v.split(' ');
var vd = va[0].split('-');
var d = new Date(vd[0], vd[1], vd[2]);
var m = _months[d.getMonth()];
return m + ' ' + d.getDate() + ', ' + d.getFullYear();
}
function _short_text(t){
if (t.length > 30){
return t.slice(0, 30) + '...';
}
return t;
}
function _task_edit_href (r){
return '/node/' + r.nid + '/edit/';
}
function _task_title(t, row){
return _short_text(t).link(_task_edit_href(row));
}
Odd side effect bug of the day: enableFilter() looks for elements whose id matches the pattern /.*_filter$/ to add events to. If for some reason your page has unrelated objects named thus you will either have to rename them or create your own custom version of enableFilter().
The Data
Every request for data comes with two values in post: page and per_page. these have analogs to the footer choices in the table. page is a value ranging from 0..(count/per_page). The expected returned JSON block is:
{ "count": "54", "config": "m1", "out": [
{ "title": "Beta Task", "vid": "9", "nid": "9",
"project_master_nid": "0", "time_sensitive": "1", "start_date": "2010-02-26 12:00:00",
"end_date": "2010-04-14 11:30:00", "task_status": "1", "importance": "0" }, { "title":
"Task Master Foo", "vid": "15", "nid": "13"
... "start_date": null, "end_date": null,
"task_status": "0", "importance": "0" } ] }
The count field is the total number of rows -- not the number of rows in out.
The config value is the value of the variable you wielded to the table.
My Mods to tGrid
There were a few loose ends in tGrid. I modded them in the file below.
- The checkbox that comes in if you set the model's checkBoxName property now comes in as the first column, not the last.
- The pagination and page size controls are now spread across the entire footer. the base version squeezed the pagination into the first cell, resulting in a bloated first column.
- I included a different style sheet that is a little more modern.
- I included tag wrappers for the pagination cells (a current page for the unlinked current page number and an other_page class for all the pagination links).
Sample pagination markup:
<span class="pagination"><span class="current_page">1</span> <a class="other_page" href="javascript:m1.setPage(1);">2</a> <a class="other_page" href="javascript:m1.setPage(2);">3</a> <a class="other_page" href="javascript:m1.setPage(3);">4</a> ... <a class="other_page" href="javascript:m1.setPage(10);">11</a> </span>
| Attachment | Size |
|---|---|
| tgrid.zip | 129.56 KB |

the "good" css
the 'good' CSS example expects a named container div, tied to the Drupal theme I was using.
Post new comment