/************************************************************************ * PAGING extension for jTable * *************************************************************************/ (function ($) { //Reference to base object members var base = { load: $.hik.jtable.prototype.load, _create: $.hik.jtable.prototype._create, _setOption: $.hik.jtable.prototype._setOption, _createRecordLoadUrl: $.hik.jtable.prototype._createRecordLoadUrl, _createJtParamsForLoading: $.hik.jtable.prototype._createJtParamsForLoading, _addRowToTable: $.hik.jtable.prototype._addRowToTable, _addRow: $.hik.jtable.prototype._addRow, _removeRowsFromTable: $.hik.jtable.prototype._removeRowsFromTable, _onRecordsLoaded: $.hik.jtable.prototype._onRecordsLoaded }; //extension members $.extend(true, $.hik.jtable.prototype, { /************************************************************************ * DEFAULT OPTIONS / EVENTS * *************************************************************************/ options: { paging: false, pageList: 'normal', //possible values: 'minimal', 'normal' pageSize: 10, pageSizes: [10, 25, 50, 100, 250, 500], pageSizeChangeArea: true, gotoPageArea: 'combobox', //possible values: 'textbox', 'combobox', 'none' messages: { pagingInfo: 'Showing {0}-{1} of {2}', pageSizeChangeLabel: 'Row count', gotoPageLabel: 'Go to page' } }, /************************************************************************ * PRIVATE FIELDS * *************************************************************************/ _$bottomPanel: null, //Reference to the panel at the bottom of the table (jQuery object) _$pagingListArea: null, //Reference to the page list area in to bottom panel (jQuery object) _$pageSizeChangeArea: null, //Reference to the page size change area in to bottom panel (jQuery object) _$pageInfoSpan: null, //Reference to the paging info area in to bottom panel (jQuery object) _$gotoPageArea: null, //Reference to 'Go to page' input area in to bottom panel (jQuery object) _$gotoPageInput: null, //Reference to 'Go to page' input in to bottom panel (jQuery object) _totalRecordCount: 0, //Total count of records on all pages _currentPageNo: 1, //Current page number /************************************************************************ * CONSTRUCTOR AND INITIALIZING METHODS * *************************************************************************/ /* Overrides base method to do paging-specific constructions. *************************************************************************/ _create: function() { base._create.apply(this, arguments); if (this.options.paging) { this._loadPagingSettings(); this._createBottomPanel(); this._createPageListArea(); this._createGotoPageInput(); this._createPageSizeSelection(); } }, /* Loads user preferences for paging. *************************************************************************/ _loadPagingSettings: function() { if (!this.options.saveUserPreferences) { return; } var pageSize = this._getCookie('page-size'); if (pageSize) { this.options.pageSize = this._normalizeNumber(pageSize, 1, 1000000, this.options.pageSize); } }, /* Creates bottom panel and adds to the page. *************************************************************************/ _createBottomPanel: function() { this._$bottomPanel = $('
') .addClass('jtable-bottom-panel') .insertAfter(this._$table); this._jqueryuiThemeAddClass(this._$bottomPanel, 'ui-state-default'); $('').addClass('jtable-left-area').appendTo(this._$bottomPanel); $('').addClass('jtable-right-area').appendTo(this._$bottomPanel); }, /* Creates page list area. *************************************************************************/ _createPageListArea: function() { this._$pagingListArea = $('') .addClass('jtable-page-list') .appendTo(this._$bottomPanel.find('.jtable-left-area')); this._$pageInfoSpan = $('') .addClass('jtable-page-info') .appendTo(this._$bottomPanel.find('.jtable-right-area')); }, /* Creates page list change area. *************************************************************************/ _createPageSizeSelection: function() { var self = this; if (!self.options.pageSizeChangeArea) { return; } //Add current page size to page sizes list if not contains it if (self._findIndexInArray(self.options.pageSize, self.options.pageSizes) < 0) { self.options.pageSizes.push(parseInt(self.options.pageSize)); self.options.pageSizes.sort(function(a, b) { return a - b; }); } //Add a span to contain page size change items self._$pageSizeChangeArea = $('') .addClass('jtable-page-size-change') .appendTo(self._$bottomPanel.find('.jtable-left-area')); //Page size label self._$pageSizeChangeArea.append('' + self.options.messages.pageSizeChangeLabel + ': '); //Page size change combobox var $pageSizeChangeCombobox = $('').appendTo(self._$pageSizeChangeArea); //Add page sizes to the combobox for (var i = 0; i < self.options.pageSizes.length; i++) { $pageSizeChangeCombobox.append(''); } //Select current page size $pageSizeChangeCombobox.val(self.options.pageSize); //Change page size on combobox change $pageSizeChangeCombobox.change(function() { self._changePageSize(parseInt($(this).val())); }); }, /* Creates go to page area. *************************************************************************/ _createGotoPageInput: function() { var self = this; if (!self.options.gotoPageArea || self.options.gotoPageArea == 'none') { return; } //Add a span to contain goto page items this._$gotoPageArea = $('') .addClass('jtable-goto-page') .appendTo(self._$bottomPanel.find('.jtable-left-area')); //Goto page label this._$gotoPageArea.append('' + self.options.messages.gotoPageLabel + ': '); //Goto page input if (self.options.gotoPageArea == 'combobox') { self._$gotoPageInput = $('') .appendTo(this._$gotoPageArea) .data('pageCount', 1) .change(function() { self._changePage(parseInt($(this).val())); }); self._$gotoPageInput.append(''); } else { //textbox self._$gotoPageInput = $('') .appendTo(this._$gotoPageArea) .keypress(function(event) { if (event.which == 13) { //enter event.preventDefault(); self._changePage(parseInt(self._$gotoPageInput.val())); } else if (event.which == 43) { // + event.preventDefault(); self._changePage(parseInt(self._$gotoPageInput.val()) + 1); } else if (event.which == 45) { // - event.preventDefault(); self._changePage(parseInt(self._$gotoPageInput.val()) - 1); } else { //Allow only digits var isValid = ( (47 < event.keyCode && event.keyCode < 58 && event.shiftKey == false && event.altKey == false) || (event.keyCode == 8) || (event.keyCode == 9) ); if (!isValid) { event.preventDefault(); } } }); } }, /* Refreshes the 'go to page' input. *************************************************************************/ _refreshGotoPageInput: function() { if (!this.options.gotoPageArea || this.options.gotoPageArea == 'none') { return; } if (this._totalRecordCount <= 0) { this._$gotoPageArea.hide(); } else { this._$gotoPageArea.show(); } if (this.options.gotoPageArea == 'combobox') { var oldPageCount = this._$gotoPageInput.data('pageCount'); var currentPageCount = this._calculatePageCount(); if (oldPageCount != currentPageCount) { this._$gotoPageInput.empty(); //Skip some pages is there are too many pages var pageStep = 1; if (currentPageCount > 10000) { pageStep = 100; } else if (currentPageCount > 5000) { pageStep = 10; } else if (currentPageCount > 2000) { pageStep = 5; } else if (currentPageCount > 1000) { pageStep = 2; } for (var i = pageStep; i <= currentPageCount; i += pageStep) { this._$gotoPageInput.append(''); } this._$gotoPageInput.data('pageCount', currentPageCount); } } //same for 'textbox' and 'combobox' this._$gotoPageInput.val(this._currentPageNo); }, /************************************************************************ * OVERRIDED METHODS * *************************************************************************/ /* Overrides load method to set current page to 1. *************************************************************************/ load: function() { this._currentPageNo = 1; base.load.apply(this, arguments); }, /* Used to change options dynamically after initialization. *************************************************************************/ _setOption: function(key, value) { base._setOption.apply(this, arguments); if (key == 'pageSize') { this._changePageSize(parseInt(value)); } }, /* Changes current page size with given value. *************************************************************************/ _changePageSize: function(pageSize) { if (pageSize == this.options.pageSize) { return; } this.options.pageSize = pageSize; //Normalize current page var pageCount = this._calculatePageCount(); if (this._currentPageNo > pageCount) { this._currentPageNo = pageCount; } if (this._currentPageNo <= 0) { this._currentPageNo = 1; } //if user sets one of the options on the combobox, then select it. var $pageSizeChangeCombobox = this._$bottomPanel.find('.jtable-page-size-change select'); if ($pageSizeChangeCombobox.length > 0) { if (parseInt($pageSizeChangeCombobox.val()) != pageSize) { var selectedOption = $pageSizeChangeCombobox.find('option[value=' + pageSize + ']'); if (selectedOption.length > 0) { $pageSizeChangeCombobox.val(pageSize); } } } this._savePagingSettings(); this._reloadTable(); }, /* Saves user preferences for paging *************************************************************************/ _savePagingSettings: function() { if (!this.options.saveUserPreferences) { return; } this._setCookie('page-size', this.options.pageSize); }, /* Overrides _createRecordLoadUrl method to add paging info to URL. *************************************************************************/ _createRecordLoadUrl: function() { var loadUrl = base._createRecordLoadUrl.apply(this, arguments); loadUrl = this._addPagingInfoToUrl(loadUrl, this._currentPageNo); return loadUrl; }, /* Overrides _createJtParamsForLoading method to add paging parameters to jtParams object. *************************************************************************/ _createJtParamsForLoading: function () { var jtParams = base._createJtParamsForLoading.apply(this, arguments); if (this.options.paging) { jtParams.jtStartIndex = (this._currentPageNo - 1) * this.options.pageSize; jtParams.jtPageSize = this.options.pageSize; } return jtParams; }, /* Overrides _addRowToTable method to re-load table when a new row is created. * NOTE: THIS METHOD IS DEPRECATED AND WILL BE REMOVED FROM FEATURE RELEASES. * USE _addRow METHOD. *************************************************************************/ _addRowToTable: function ($tableRow, index, isNewRow) { if (isNewRow && this.options.paging) { this._reloadTable(); return; } base._addRowToTable.apply(this, arguments); }, /* Overrides _addRow method to re-load table when a new row is created. *************************************************************************/ _addRow: function ($row, options) { if (options && options.isNewRow && this.options.paging) { this._reloadTable(); return; } base._addRow.apply(this, arguments); }, /* Overrides _removeRowsFromTable method to re-load table when a row is removed from table. *************************************************************************/ _removeRowsFromTable: function ($rows, reason) { base._removeRowsFromTable.apply(this, arguments); if (this.options.paging) { if (this._$tableRows.length <= 0 && this._currentPageNo > 1) { --this._currentPageNo; } this._reloadTable(); } }, /* Overrides _onRecordsLoaded method to to do paging specific tasks. *************************************************************************/ _onRecordsLoaded: function (data) { if (this.options.paging) { this._totalRecordCount = data.TotalRecordCount; this._createPagingList(); this._createPagingInfo(); this._refreshGotoPageInput(); } base._onRecordsLoaded.apply(this, arguments); }, /************************************************************************ * PRIVATE METHODS * *************************************************************************/ /* Adds jtStartIndex and jtPageSize parameters to a URL as query string. *************************************************************************/ _addPagingInfoToUrl: function (url, pageNumber) { if (!this.options.paging) { return url; } var jtStartIndex = (pageNumber - 1) * this.options.pageSize; var jtPageSize = this.options.pageSize; return (url + (url.indexOf('?') < 0 ? '?' : '&') + 'jtStartIndex=' + jtStartIndex + '&jtPageSize=' + jtPageSize); }, /* Creates and shows the page list. *************************************************************************/ _createPagingList: function () { if (this.options.pageSize <= 0) { return; } this._$pagingListArea.empty(); if (this._totalRecordCount <= 0) { return; } var pageCount = this._calculatePageCount(); this._createFirstAndPreviousPageButtons(); if (this.options.pageList == 'normal') { this._createPageNumberButtons(this._calculatePageNumbers(pageCount)); } this._createLastAndNextPageButtons(pageCount); this._bindClickEventsToPageNumberButtons(); }, /* Creates and shows previous and first page links. *************************************************************************/ _createFirstAndPreviousPageButtons: function () { var $first = $('') .addClass('jtable-page-number-first') .html('<<') .data('pageNumber', 1) .appendTo(this._$pagingListArea); var $previous = $('') .addClass('jtable-page-number-previous') .html('<') .data('pageNumber', this._currentPageNo - 1) .appendTo(this._$pagingListArea); this._jqueryuiThemeAddClass($first, 'ui-button ui-state-default', 'ui-state-hover'); this._jqueryuiThemeAddClass($previous, 'ui-button ui-state-default', 'ui-state-hover'); if (this._currentPageNo <= 1) { $first.addClass('jtable-page-number-disabled'); $previous.addClass('jtable-page-number-disabled'); this._jqueryuiThemeAddClass($first, 'ui-state-disabled'); this._jqueryuiThemeAddClass($previous, 'ui-state-disabled'); } }, /* Creates and shows next and last page links. *************************************************************************/ _createLastAndNextPageButtons: function (pageCount) { var $next = $('') .addClass('jtable-page-number-next') .html('>') .data('pageNumber', this._currentPageNo + 1) .appendTo(this._$pagingListArea); var $last = $('') .addClass('jtable-page-number-last') .html('>>') .data('pageNumber', pageCount) .appendTo(this._$pagingListArea); this._jqueryuiThemeAddClass($next, 'ui-button ui-state-default', 'ui-state-hover'); this._jqueryuiThemeAddClass($last, 'ui-button ui-state-default', 'ui-state-hover'); if (this._currentPageNo >= pageCount) { $next.addClass('jtable-page-number-disabled'); $last.addClass('jtable-page-number-disabled'); this._jqueryuiThemeAddClass($next, 'ui-state-disabled'); this._jqueryuiThemeAddClass($last, 'ui-state-disabled'); } }, /* Creates and shows page number links for given number array. *************************************************************************/ _createPageNumberButtons: function (pageNumbers) { var previousNumber = 0; for (var i = 0; i < pageNumbers.length; i++) { //Create "..." between page numbers if needed if ((pageNumbers[i] - previousNumber) > 1) { $('') .addClass('jtable-page-number-space') .html('...') .appendTo(this._$pagingListArea); } this._createPageNumberButton(pageNumbers[i]); previousNumber = pageNumbers[i]; } }, /* Creates a page number link and adds to paging area. *************************************************************************/ _createPageNumberButton: function (pageNumber) { var $pageNumber = $('') .addClass('jtable-page-number') .html(pageNumber) .data('pageNumber', pageNumber) .appendTo(this._$pagingListArea); this._jqueryuiThemeAddClass($pageNumber, 'ui-button ui-state-default', 'ui-state-hover'); if (this._currentPageNo == pageNumber) { $pageNumber.addClass('jtable-page-number-active jtable-page-number-disabled'); this._jqueryuiThemeAddClass($pageNumber, 'ui-state-active'); } }, /* Calculates total page count according to page size and total record count. *************************************************************************/ _calculatePageCount: function () { var pageCount = Math.floor(this._totalRecordCount / this.options.pageSize); if (this._totalRecordCount % this.options.pageSize != 0) { ++pageCount; } return pageCount; }, /* Calculates page numbers and returns an array of these numbers. *************************************************************************/ _calculatePageNumbers: function (pageCount) { if (pageCount <= 4) { //Show all pages var pageNumbers = []; for (var i = 1; i <= pageCount; ++i) { pageNumbers.push(i); } return pageNumbers; } else { //show first three, last three, current, previous and next page numbers var shownPageNumbers = [1, 2, pageCount - 1, pageCount]; var previousPageNo = this._normalizeNumber(this._currentPageNo - 1, 1, pageCount, 1); var nextPageNo = this._normalizeNumber(this._currentPageNo + 1, 1, pageCount, 1); this._insertToArrayIfDoesNotExists(shownPageNumbers, previousPageNo); this._insertToArrayIfDoesNotExists(shownPageNumbers, this._currentPageNo); this._insertToArrayIfDoesNotExists(shownPageNumbers, nextPageNo); shownPageNumbers.sort(function (a, b) { return a - b; }); return shownPageNumbers; } }, /* Creates and shows paging informations. *************************************************************************/ _createPagingInfo: function () { if (this._totalRecordCount <= 0) { this._$pageInfoSpan.empty(); return; } var startNo = (this._currentPageNo - 1) * this.options.pageSize + 1; var endNo = this._currentPageNo * this.options.pageSize; endNo = this._normalizeNumber(endNo, startNo, this._totalRecordCount, 0); if (endNo >= startNo) { var pagingInfoMessage = this._formatString(this.options.messages.pagingInfo, startNo, endNo, this._totalRecordCount); this._$pageInfoSpan.html(pagingInfoMessage); } }, /* Binds click events of all page links to change the page. *************************************************************************/ _bindClickEventsToPageNumberButtons: function () { var self = this; self._$pagingListArea .find('.jtable-page-number,.jtable-page-number-previous,.jtable-page-number-next,.jtable-page-number-first,.jtable-page-number-last') .not('.jtable-page-number-disabled') .click(function (e) { e.preventDefault(); self._changePage($(this).data('pageNumber')); }); }, /* Changes current page to given value. *************************************************************************/ _changePage: function (pageNo) { pageNo = this._normalizeNumber(pageNo, 1, this._calculatePageCount(), 1); if (pageNo == this._currentPageNo) { this._refreshGotoPageInput(); return; } this._currentPageNo = pageNo; this._reloadTable(); } }); })(jQuery);