Skip to content

Instantly share code, notes, and snippets.

@mindscratch
Created August 17, 2011 09:39
Show Gist options
  • Select an option

  • Save mindscratch/1151201 to your computer and use it in GitHub Desktop.

Select an option

Save mindscratch/1151201 to your computer and use it in GitHub Desktop.
jqGrid widget using JavaScriptMVC
<table id="<%= options.gridId %>" class="grid <%= options.gridClass %>">
<tr>
<td />
</tr>
</table>
<div id="<%= options.pagerId %>"></div>
// JavaScript MVC 3.0.5
// jQuery 1.6
// jqGrid 4.0
steal.plugins('jquery/controller/subscribe', 'jquery/view/ejs')
.views('grid.ejs').then(function($) {
/**
* A grid component that uses data from a local source (i.e. array) as opposed to
* fetching it remotely.
*
* The idea was to let some other part of the application fetch the data and
* then give it to this widget to update the grid, instead of having the grid
* handle making remote calls to the server (to fetch data, sort, page, etc).
*/
$.Controller.extend('MyApp.Widgets.LocalGrid',
{
defaults: {
// the column model
colModel: null, // a column model must be provided
// the default view template
grid: '//myapp/controllers/widgets/grid/views/grid.ejs',
// a CSS class to apply to the <table> element
gridClass: "",
altRowClass: "",
// the ID for the grid
gridId: 'myapp_grid',
// the ID for the pager component
pagerId: 'myapp_grid_pager',
// callback for when a sort operation occurs, is given 3 params:
// - column name
// - column index
// - sort order ('asc', 'desc')
onSort: $.noop,
// callback for when a paging operation occurs, is given 2 params:
// - pager (see jqGrid 'onpaging' docs)
// - page: the page number being asked for
onPage: $.noop,
// provide the object to use as "this" when invoking callbacks
callbackScope: null
}
},
{
init: function(el) {
this.ignoreSortEvent = false;
this.update();
},
update: function(options) {
this._super(options || {});
this.draw();
},
draw: function() {
// render the view
this.element.html(this.options.grid, {options: this.options});
// add the jqGrid
this.gridEl = this.element.find('#' + this.options.gridId);
this._createGrid(this.gridEl);
},
/**
* Add a jqGrid to the given element
*
* @param {HtmlElement} el
*/
_createGrid: function(el) {
var self = this,
sortCallback = this.options.onSort,
pageCallback = this.options.onPage,
scope = this.options.callbackScope;
/* a timeout function is used so the grid width will be calculated properly by jqGrid */
setTimeout(function() {
el.jqGrid({
altRows: true,
altClass: self.options.altRowClass,
datatype: 'local',
colModel: self.options.colModel,
rowNum: 20,
recordText: "Show {0} - {1} of {2}",
pager: '#' + self.options.pagerId,
viewrecords: true,
gridview: true,
height: '100%',
autowidth: true,
onSortCol: function(index, iCol, sortorder) {
if (self.ignoreSortEvent) {
return "stop";
}
return sortCallback.apply(scope, arguments);
},
onPaging: function(type) {
// only handler 'user' paging (e.g. when a user types in a page number).
// the paging buttons are handled by a custom click event handler (see code further down)
var requestedPage = $('.ui-pg-input').val() || '',
last = el.jqGrid('getGridParam', 'lastpage') || 1,
isNumber = requestedPage.match(/^\d+$/),
cp = self.currentPage || 1;
if (!isNumber || last <= 1) {
return false;
}
requestedPage = parseInt(requestedPage, 10);
if (requestedPage === cp || requestedPage < 1 || requestedPage > last) {
return false;
}
return pageCallback.call(scope, this.id, requestedPage);
}
});
// instead of having "Showing 3 901 - 3 919 of 3919"
// setting the separator to a comma gives us: Showing 3,901 - 3,919 of 3,919
$.jqgrid.formatter.integer.thousandsSeparator = ',';
/*
* instead of using the 'onPaging' event handler for the grid (it's used for one case)
* we unbind the click event handlers that jqgrid configures and we define our own.
* This is done b/c the jqgrid click handler references a "ts.p.page" to determine whiche
* page to go to, however, it doesn't work properly (meaning it will say the current page
* is 1 even though the user is looking at page 2).
*/
$('#first, #prev, #next, #last').unbind('click').bind('click', function(e) {
var cp = self.currentPage || 1,
last = el.jqGrid('getGridParam', 'lastpage') || 1,
requestedPage = -1,
selclick = false,
fp = true,
pp = true,
np = true,
lp = true;
if (last === 0 || last === 1) {
fp = pp = np = lp = false;
}
else if (last > 1 && cp >= 1) {
if (cp === 1) {
fp = pp = false;
}
else if (cp > 1 && cp < last) {
}
else if (cp === last) {
np = lp = false;
}
}
else if (last > 1 && cp === 0) {
np = lp = false;
cp = last - 1;
}
if (this.id === 'first' && fp) { requestedPage = 1; selclick = true; }
if (this.id === 'prev' && pp) { requestedPage = (cp - 1); selclick = true; }
if (this.id === 'next' && np) { requestedPage = (cp + 1); selclick = true; }
if (this.id === 'last' && lp) { requestedPage = last; selclick = true; }
if (selclick) {
return pageCallback.call(scope, this.id, requestedPage);
}
});
}, 30);
},
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* API Methods
*
* These methods ar emeant to be invoked by users/clients of this code.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/**
* Set the data for the grid.
*
* @param {Object} data the data for the grid, this should contain the following properties:
* - rows: array of objects, one per row
* - page: the page number of this dataset (1-based, so page 1,2,3. Not page, 0,1,2).
* - total: the total number of pages available
* - records: the number of records available
* - sidx: the name of the column to sort
* - sord: the sort order, either 'asc' or 'desc'
*/
setData: function(data) {
this.currentPage = data.page;
var self = this,
reader = {
root: function(obj) { return data.rows; },
page: function(obj) { return data.page; },
total: function(obj) { return data.total; },
records: function(obj) { return data.records; },
repeatItems: false
};
this.gridel.jqGrid('setGridParam', {
data: data.rows,
localReader: reader,
sortname: String(data.sidx),
sortorder: data.sord,
page: data.page
}).trigger('reloadGrid');
// update the sort icons in the columns
setTimeout(function() {
self.updateSortIcons(data.sidx, data.sord);
}, 50);
},
updateSortIcons: function(columnName, sortorder) {
this.ignoreSortEvent = true;
this.gridEl.sortGrid(String(columnName), false, sortorder);
this.ignoreSortEvent = false;
},
redraw: function() {
this.gridEl.trigger('reloadGrid');
}
})
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment