/* * jsGrid v1.0.1 (http://js-grid.com) * (c) 2015 Artem Tabalin * Licensed under MIT (https://github.com/tabalinas/jsgrid/blob/master/LICENSE) */ (function(window, $, undefined) { var JSGRID = "JSGrid", JSGRID_DATA_KEY = JSGRID, JSGRID_ROW_DATA_KEY = "JSGridItem", JSGRID_EDIT_ROW_DATA_KEY = "JSGridEditRow", SORT_ORDER_ASC = "asc", SORT_ORDER_DESC = "desc", FIRST_PAGE_PLACEHOLDER = "{first}", PAGES_PLACEHOLDER = "{pages}", PREV_PAGE_PLACEHOLDER = "{prev}", NEXT_PAGE_PLACEHOLDER = "{next}", LAST_PAGE_PLACEHOLDER = "{last}", PAGE_INDEX_PLACEHOLDER = "{pageIndex}", PAGE_COUNT_PLACEHOLDER = "{pageCount}", EMPTY_HREF = "javascript:void(0);"; var getOrApply = function(value, context) { if($.isFunction(value)) { return value.apply(context, $.makeArray(arguments).slice(2)); } return value; }; var defaultController = { loadData: $.noop, insertItem: $.noop, updateItem: $.noop, deleteItem: $.noop }; function Grid(element, config) { var $element = $(element); $element.data(JSGRID_DATA_KEY, this); this._container = $element; this.data = []; this.fields = []; this._editingRow = null; this._sortField = null; this._sortOrder = SORT_ORDER_ASC; this._firstDisplayingPage = 1; this._init(config); this.render(); } Grid.prototype = { width: "auto", height: "auto", updateOnResize: true, rowClass: $.noop, rowRenderer: null, rowClick: function(args) { if(this.editing) { this.editItem($(args.event.target).closest("tr")); } }, noDataContent: "Not found", noDataRowClass: "jsgrid-nodata-row", heading: true, headerRowRenderer: null, headerRowClass: "jsgrid-header-row", filtering: false, filterRowRenderer: null, filterRowClass: "jsgrid-filter-row", inserting: false, insertRowRenderer: null, insertRowClass: "jsgrid-insert-row", editing: false, editRowRenderer: null, editRowClass: "jsgrid-edit-row", confirmDeleting: true, deleteConfirm: "Are you sure?", selecting: true, selectedRowClass: "jsgrid-selected-row", oddRowClass: "jsgrid-row", evenRowClass: "jsgrid-alt-row", sorting: false, sortableClass: "jsgrid-header-sortable", sortAscClass: "jsgrid-header-sort jsgrid-header-sort-asc", sortDescClass: "jsgrid-header-sort jsgrid-header-sort-desc", paging: false, pagerContainer: null, pageIndex: 1, pageSize: 20, pageButtonCount: 15, pagerFormat: "Pages: {first} {prev} {pages} {next} {last} {pageIndex} of {pageCount}", pagePrevText: "Prev", pageNextText: "Next", pageFirstText: "First", pageLastText: "Last", pageNavigatorNextText: "...", pageNavigatorPrevText: "...", pagerContainerClass: "jsgrid-pager-container", pagerClass: "jsgrid-pager", pagerNavButtonClass: "jsgrid-pager-nav-button", pageClass: "jsgrid-pager-page", currentPageClass: "jsgrid-pager-current-page", pageLoading: false, autoload: false, controller: defaultController, loadIndication: true, loadIndicationDelay: 500, loadMessage: "Please, wait...", loadShading: true, onRefreshing: $.noop, onRefreshed: $.noop, onItemDeleting: $.noop, onItemDeleted: $.noop, onItemInserting: $.noop, onItemInserted: $.noop, onItemUpdating: $.noop, onItemUpdated: $.noop, onDataLoading: $.noop, onDataLoaded: $.noop, onOptionChanging: $.noop, onOptionChanged: $.noop, onError: $.noop, containerClass: "jsgrid", tableClass: "jsgrid-table", gridHeaderClass: "jsgrid-grid-header", gridBodyClass: "jsgrid-grid-body", _init: function(config) { $.extend(this, config); this._initLoadStrategy(); this._initController(); this._initFields(); this._attachWindowLoadResize(); this._attachWindowResizeCallback(); }, loadStrategy: function() { return this.pageLoading ? new jsGrid.loadStrategies.PageLoadingStrategy(this) : new jsGrid.loadStrategies.DirectLoadingStrategy(this); }, _initLoadStrategy: function() { this._loadStrategy = getOrApply(this.loadStrategy, this); }, _initController: function() { this._controller = $.extend({}, defaultController, getOrApply(this.controller, this)); }, loadIndicator: function(config) { return new jsGrid.LoadIndicator(config); }, _initFields: function() { var self = this; self.fields = $.map(self.fields, function(field) { if($.isPlainObject(field)) { var fieldConstructor = (field.type && jsGrid.fields[field.type]) || jsGrid.Field; field = new fieldConstructor(field); } field._grid = self; return field; }); }, _attachWindowLoadResize: function() { $(window).on("load", $.proxy(this._refreshSize, this)); }, _attachWindowResizeCallback: function() { if(this.updateOnResize) { $(window).on("resize", $.proxy(this._refreshSize, this)); } }, _detachWindowResizeCallback: function() { $(window).off("resize", this._refreshSize); }, option: function(key, value) { var optionChangingEventArgs, optionChangedEventArgs; if(arguments.length === 1) { return this[key]; } optionChangingEventArgs = { option: key, oldValue: this[key], newValue: value }; this._callEventHandler(this.onOptionChanging, optionChangingEventArgs); this._handleOptionChange(optionChangingEventArgs.option, optionChangingEventArgs.newValue); optionChangedEventArgs = { option: optionChangingEventArgs.option, value: optionChangingEventArgs.newValue }; this._callEventHandler(this.onOptionChanged, optionChangedEventArgs); }, _handleOptionChange: function(name, value) { this[name] = value; switch(name) { case "width": case "height": this._refreshSize(); break; case "rowClass": case "rowRenderer": case "rowClick": case "noDataText": case "noDataRowClass": case "noDataContent": case "selecting": case "selectedRowClass": case "oddRowClass": case "evenRowClass": this._refreshContent(); break; case "pageButtonCount": case "pagerFormat": case "pagePrevText": case "pageNextText": case "pageFirstText": case "pageLastText": case "pageNavigatorNextText": case "pageNavigatorPrevText": case "pagerClass": case "pagerNavButtonClass": case "pageClass": case "currentPageClass": this._refreshPager(); break; case "fields": this._initFields(); this.render(); break; case "data": case "editing": case "heading": case "filtering": case "inserting": case "paging": this.refresh(); break; case "pageLoading": this._initLoadStrategy(); this.search(); break; case "pageIndex": this.openPage(value); break; case "pageSize": this.refresh(); this.search(); break; case "editRowRenderer": case "editRowClass": this.cancelEdit(); break; default: this.render(); break; } }, destroy: function() { this._detachWindowResizeCallback(); this._clear(); this._container.removeData(JSGRID_DATA_KEY); }, render: function() { this._clear(); this._container.addClass(this.containerClass) .css("position", "relative") .append(this._createHeader()) .append(this._createBody()); this._pagerContainer = this._createPagerContainer(); this._loadIndicator = this._createLoadIndicator(); this.refresh(); return this.autoload ? this.loadData() : $.Deferred().resolve().promise(); }, _createLoadIndicator: function() { return getOrApply(this.loadIndicator, this, { message: this.loadMessage, shading: this.loadShading, container: this._container }); }, _clear: function() { this.cancelEdit(); clearTimeout(this._loadingTimer); this._pagerContainer && this._pagerContainer.empty(); this._container.empty() .css({ position: "", width: "", height: "" }); }, _createHeader: function() { var $headerRow = this._headerRow = this._createHeaderRow(), $filterRow = this._filterRow = this._createFilterRow(), $insertRow = this._insertRow = this._createInsertRow(); var $headerGrid = this._headerGrid = $("
| ").addClass(field.css) .appendTo($result) .append(field.headerTemplate ? field.headerTemplate() : "") .css("width", field.width); if(this.sorting && field.sorting) { $th.addClass(this.sortableClass) .on("click", $.proxy(function() { this.sort(index); }, this)); } }); return $result; }, _createFilterRow: function() { if($.isFunction(this.filterRowRenderer)) { return $(this.filterRowRenderer()); } var $result = $(" |
|---|
| ").addClass(field.css) .appendTo($result) .append(field.filterTemplate ? field.filterTemplate() : "") .width(field.width); }); return $result; }, _createInsertRow: function() { if($.isFunction(this.insertRowRenderer)) { return $(this.insertRowRenderer()); } var $result = $(" |
| ").addClass(field.css) .appendTo($result) .append(field.insertTemplate ? field.insertTemplate() : "") .width(field.width); }); return $result; }, _callEventHandler: function(handler, eventParams) { return handler.call(this, $.extend(eventParams, { grid: this })); }, reset: function() { this._resetSorting(); this._resetPager(); this.refresh(); }, _resetPager: function() { this._firstDisplayingPage = 1; this._setPage(1); }, _resetSorting: function() { this._sortField = null; this._sortOrder = SORT_ORDER_ASC; this._clearSortingCss(); }, refresh: function() { this._callEventHandler(this.onRefreshing); this.cancelEdit(); this._refreshHeading(); this._refreshFiltering(); this._refreshInserting(); this._refreshContent(); this._refreshPager(); this._refreshSize(); this._callEventHandler(this.onRefreshed); }, _refreshHeading: function() { this._headerRow.toggle(this.heading); }, _refreshFiltering: function() { this._filterRow.toggle(this.filtering); }, _refreshInserting: function() { this._insertRow.toggle(this.inserting); }, _refreshContent: function() { var $content = this._content; $content.empty(); if(!this.data.length) { $content.append(this._createNoDataRow()); return this; } var indexFrom = this._loadStrategy.firstDisplayIndex(); var indexTo = this._loadStrategy.lastDisplayIndex(); for(var itemIndex = indexFrom; itemIndex < indexTo; itemIndex++) { var item = this.data[itemIndex]; $content.append(this._createRow(item, itemIndex)); } }, _createNoDataRow: function() { var noDataContent = getOrApply(this.noDataContent, this); return $(" |
| ").attr("colspan", this.fields.length).append(noDataContent)); }, _createNoDataContent: function () { return $.isFunction(this.noDataRenderer) ? this.noDataRenderer() : this.noDataText; }, _createRow: function(item, itemIndex) { var $result; if($.isFunction(this.rowRenderer)) { $result = $(this.rowRenderer(item, itemIndex)); } else { $result = $(" |
| ").append(field.itemTemplate ? field.itemTemplate(fieldValue, item) : fieldValue); } $result.addClass(field.css) .width(field.width); field.align && $result.addClass("jsgrid-align-" + field.align); return $result; }, sort: function(field, order) { if($.isPlainObject(field)) { order = field.order; field = field.field; } this._clearSortingCss(); this._setSortingParams(field, order); this._setSortingCss(); return this._loadStrategy.sort(); }, _clearSortingCss: function() { this._headerRow.find("th") .removeClass(this.sortAscClass) .removeClass(this.sortDescClass); }, _setSortingParams: function(field, order) { field = this._normalizeSortingField(field); order = order || ((this._sortField === field) ? this._reversedSortOrder(this._sortOrder) : SORT_ORDER_ASC); this._sortField = field; this._sortOrder = order; }, _normalizeSortingField: function(field) { if($.isNumeric(field)) { return this.fields[field]; } if(typeof field === "string") { return $.grep(this.fields, function (f) { return f.name === field; })[0]; } return field; }, _reversedSortOrder: function(order) { return (order === SORT_ORDER_ASC ? SORT_ORDER_DESC : SORT_ORDER_ASC); }, _setSortingCss: function() { var fieldIndex = $.inArray(this._sortField, this.fields); this._headerRow.find("th").eq(fieldIndex) .addClass(this._sortOrder === SORT_ORDER_ASC ? this.sortAscClass : this.sortDescClass); }, _sortData: function() { var sortFactor = this._sortFactor(), sortField = this._sortField; if(sortField) { this.data.sort(function(item1, item2) { return sortFactor * sortField.sortingFunc(item1[sortField.name], item2[sortField.name]); }); } }, _sortFactor: function() { return this._sortOrder === SORT_ORDER_ASC ? 1 : -1; }, _itemsCount: function() { return this._loadStrategy.itemsCount(); }, _pagesCount: function() { var itemsCount = this._itemsCount(), pageSize = this.pageSize; return Math.floor(itemsCount / pageSize) + (itemsCount % pageSize ? 1 : 0); }, _refreshPager: function() { var $pagerContainer = this._pagerContainer; $pagerContainer.empty(); if(this.paging && this._pagesCount() > 1) { $pagerContainer.show() .append(this._createPager()); } else { $pagerContainer.hide(); } }, _createPager: function() { var pageIndex = this.pageIndex, pageCount = this._pagesCount(), pagerParts = this.pagerFormat.split(" "); pagerParts = $.map(pagerParts, $.proxy(function(pagerPart) { var result = pagerPart; if(pagerPart === PAGES_PLACEHOLDER) { result = this._createPages(); } else if(pagerPart === FIRST_PAGE_PLACEHOLDER) { result = pageIndex > 1 ? this._createPagerNavButton(this.pageFirstText, 1) : ""; } else if(pagerPart === PREV_PAGE_PLACEHOLDER) { result = pageIndex > 1 ? this._createPagerNavButton(this.pagePrevText, pageIndex - 1) : ""; } else if(pagerPart === NEXT_PAGE_PLACEHOLDER) { result = pageIndex < pageCount ? this._createPagerNavButton(this.pageNextText, pageIndex + 1) : ""; } else if(pagerPart === LAST_PAGE_PLACEHOLDER) { result = pageIndex < pageCount ? this._createPagerNavButton(this.pageLastText, pageCount) : ""; } else if(pagerPart === PAGE_INDEX_PLACEHOLDER) { result = pageIndex; } else if(pagerPart === PAGE_COUNT_PLACEHOLDER) { result = pageCount; } return $.isArray(result) ? result.concat([" "]) : [result, " "]; }, this)); var $pager = $(" |