- // 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');
- }
- })
- });