/* * jsGrid v1.5.3 (http://js-grid.com) * (c) 2016 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}", ITEM_COUNT_PLACEHOLDER = "{itemCount}", EMPTY_HREF = "javascript:void(0);"; var getOrApply = function (value, context) { if ($.isFunction(value)) { return value.apply(context, $.makeArray(arguments).slice(2)); } return value; }; var normalizePromise = function (promise) { var d = $.Deferred(); if (promise && promise.then) { promise.then(function () { d.resolve.apply(d, arguments); }, function () { d.reject.apply(d, arguments); }); } else { d.resolve(promise); } return d.promise(); }; 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.total = 0;//John Add 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")); } }, rowDoubleClick: $.noop, rowMouseDown: $.noop, rowMouseUp: $.noop, rowMouseUut: $.noop, noDataContent: "Not found", noDataRowClass: "jsgrid-nodata-row", heading: true, headerRowRenderer: null, headerRowClass: "jsgrid-header-row", headerCellClass: "jsgrid-header-cell", 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", cellClass: "jsgrid-cell", 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}      {pagepernumber}", pagerFormat: "{Total} {itemCount} {Pen} {first} {prev} {pages} {next} {last}      {Numth} {pageIndex} {Page} {Total} {pageCount} {Page}", pagePrevText: "Prev", pageNextText: "Next", pageFirstText: "First", pageLastText: "Last", pageNavigatorNextText: "...", pageNavigatorPrevText: "...", pagerContainerClass: "jsgrid-pager-container", pagerClass: "jsgrid-pager", pagerNavButtonClass: "jsgrid-pager-nav-button", pagerNavButtonInactiveClass: "jsgrid-pager-nav-inactive-button", pageClass: "jsgrid-pager-page", currentPageClass: "jsgrid-pager-current-page", customLoading: false, pageLoading: false, autoload: false, controller: defaultController, loadIndication: true, loadIndicationDelay: 500, loadMessage: "Please, wait...", loadShading: true, invalidMessage: "Invalid data entered!", invalidNotify: function (args) { var messages = $.map(args.errors, function (error) { return error.message || null; }); //window.alert([this.invalidMessage].concat(messages).join("\n")); showMsg([this.invalidMessage].concat(messages).join("
"), 'info'); }, onInit: $.noop, onRefreshing: $.noop, onRefreshed: $.noop, onPageChanged: $.noop, onItemDeleting: $.noop, onItemDeleted: $.noop, onItemInserting: $.noop, onItemInserted: $.noop, onItemEditing: $.noop, onItemUpdating: $.noop, onItemUpdated: $.noop, onItemInvalid: $.noop, onDataLoading: $.noop, onDataLoaded: $.noop, onOptionChanging: $.noop, onOptionChanged: $.noop, onError: $.noop, invalidClass: "jsgrid-invalid", containerClass: "jsgrid", tableClass: "jsgrid-table", gridHeaderClass: "jsgrid-grid-header", gridBodyClass: "jsgrid-grid-body", _init: function (config) { //debugger; $.extend(this, config); this._initLoadStrategy(); this._initController(); this._initFields(); this._attachWindowLoadResize(); this._attachWindowResizeCallback(); this._callEventHandler(this.onInit); if (!this.dfheight) { this.dfheight = this.height; } }, 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)); }, renderTemplate: function (source, context, config) { args = []; for (var key in config) { args.push(config[key]); } args.unshift(source, context); source = getOrApply.apply(null, args); return (source === undefined || source === null) ? "" : source; }, loadIndicator: function (config) { return new jsGrid.LoadIndicator(config); }, validation: function (config) { return jsGrid.Validation && new jsGrid.Validation(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); }, fieldOption: function (field, key, value) { field = this._normalizeField(field); if (arguments.length === 2) return field[key]; field[key] = value; this._renderGrid(); }, _handleOptionChange: function (name, value) { this[name] = value; switch (name) { case "width": case "height": this._refreshSize(); break; case "rowClass": case "rowRenderer": case "rowClick": case "rowDoubleClick": case "rowMouseDown": case "rowMouseUp": case "rowMouseUut": 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": case "pagerRenderer": 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 "loadStrategy": 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; case "updateOnResize": this._detachWindowResizeCallback(); this._attachWindowResizeCallback(); break; case "invalidNotify": case "invalidMessage": break; default: this.render(); break; } }, destroy: function () { this._detachWindowResizeCallback(); this._clear(); this._container.removeData(JSGRID_DATA_KEY); }, render: function () { this._renderGrid(); return this.autoload ? this.loadData() : $.Deferred().resolve().promise(); }, _renderGrid: 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._validation = this._createValidation(); this.refresh(); }, _createLoadIndicator: function () { return getOrApply(this.loadIndicator, this, { message: this.loadMessage, shading: this.loadShading, container: this._container }); }, _createValidation: function () { return getOrApply(this.validation, this); }, _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(this.tableClass) .append($headerRow) .append($filterRow) .append($insertRow); var $header = this._header = $("
").addClass(this.gridHeaderClass) .addClass(this._scrollBarWidth() ? "jsgrid-header-scrollbar" : "") .append($headerGrid); return $header; }, _createBody: function () { var $content = this._content = $("
"); var $bodyGrid = this._bodyGrid = $("
").addClass(this.tableClass) .append($content); var $body = this._body = $("
").addClass(this.gridBodyClass) .append($bodyGrid) .on("scroll", $.proxy(function (e) { this._header.scrollLeft(e.target.scrollLeft); }, this)); return $body; }, _createPagerContainer: function () { var pagerContainer = this.pagerContainer || $("
").appendTo(this._container); return $(pagerContainer).addClass(this.pagerContainerClass); }, _eachField: function (callBack) { var self = this; $.each(this.fields, function (index, field) { if (field.visible) { callBack.call(self, field, index); } }); }, _createHeaderRow: function () { if ($.isFunction(this.headerRowRenderer)) return $(this.renderTemplate(this.headerRowRenderer, this)); var $result = $("
").addClass(this.headerRowClass); this._eachField(function (field, index) { var $th = this._prepareCell("").addClass(this.filterRowClass); this._eachField(function (field) { this._prepareCell("").addClass(this.insertRowClass); this._eachField(function (field) { this._prepareCell("").addClass(this.noDataRowClass) .append($(""); this._renderCells($result, item); } $result.addClass(this._getRowClasses(item, itemIndex)) .data(JSGRID_ROW_DATA_KEY, item) .on("click", $.proxy(function (e) { this.rowClick({ item: item, itemIndex: itemIndex, event: e }); $result.siblings().removeClass('grid-selected'); $result.addClass('grid-selected'); }, this)) .on("dblclick", $.proxy(function (e) { this.rowDoubleClick({ item: item, itemIndex: itemIndex, event: e }); }, this)) .on("mousedown", $.proxy(function (e) { this.rowMouseDown({ item: item, itemIndex: itemIndex, event: e }); }, this)) .on("mouseup", $.proxy(function (e) { this.rowMouseUp({ item: item, itemIndex: itemIndex, event: e }); }, this)) .on("mouseout", $.proxy(function (e) { this.rowMouseUut({ item: item, itemIndex: itemIndex, event: e }); }, this)); if (this.selecting) { this._attachRowHover($result); } return $result; }, _getRowClasses: function (item, itemIndex) { var classes = []; classes.push(((itemIndex + 1) % 2) ? this.oddRowClass : this.evenRowClass); classes.push(getOrApply(this.rowClass, this, item, itemIndex)); return classes.join(" "); }, _attachRowHover: function ($row) { var selectedRowClass = this.selectedRowClass; $row.hover(function () { $(this).addClass(selectedRowClass); }, function () { $(this).removeClass(selectedRowClass); } ); }, _renderCells: function ($row, item) { this._eachField(function (field) { $row.append(this._createCell(item, field)); }); return this; }, _createCell: function (item, field) { var $result; var fieldValue = this._getItemFieldValue(item, field); var args = { value: fieldValue, item: item }; if ($.isFunction(field.cellRenderer)) { $result = this.renderTemplate(field.cellRenderer, field, args); } else { $result = $("").addClass(this.editRowClass); this._eachField(function (field) { var fieldValue = this._getItemFieldValue(item, field); this._prepareCell("
", field, "headercss", this.headerCellClass) .append(this.renderTemplate(field.headerTemplate, field)); if (field.title) { $th.attr('data-i18n', field.title); } $th.appendTo($result); if (this.sorting && field.sorting) { $th.addClass(this.sortableClass) .on("click", $.proxy(function () { if (typeof this.headerClick === 'function') { this.headerClick(); } this.sort(index); }, this)); } }); return $result; }, _prepareCell: function (cell, field, cssprop, cellClass) { return $(cell).css("width", field.width) .addClass(cellClass || this.cellClass) .addClass((cssprop && field[cssprop]) || field.css) .addClass(field.align ? ("jsgrid-align-" + field.align) : ""); }, _createFilterRow: function () { if ($.isFunction(this.filterRowRenderer)) return $(this.renderTemplate(this.filterRowRenderer, this)); var $result = $("
", field, "filtercss") .append(this.renderTemplate(field.filterTemplate, field)) .appendTo($result); }); return $result; }, _createInsertRow: function () { if ($.isFunction(this.insertRowRenderer)) return $(this.renderTemplate(this.insertRowRenderer, this)); var $result = $("
", field, "insertcss") .append(this.renderTemplate(field.insertTemplate, field)) .appendTo($result); }); return $result; }, _callEventHandler: function (handler, eventParams) { handler.call(this, $.extend(eventParams, { grid: this })); return eventParams; }, reset: function () { this._resetSorting(); this._resetPager(); return this._loadStrategy.reset(); }, _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 amountOfFields = 0; this._eachField(function () { amountOfFields++; }); return $("
").addClass(this.cellClass).attr("colspan", amountOfFields) .append(this.renderTemplate(this.noDataContent, this))); }, _createRow: function (item, itemIndex) { var $result; if ($.isFunction(this.rowRenderer)) { $result = this.renderTemplate(this.rowRenderer, this, { item: item, itemIndex: itemIndex }); } else { $result = $("
").append(this.renderTemplate(field.itemTemplate || fieldValue, field, args)); } return this._prepareCell($result, field); }, _getItemFieldValue: function (item, field) { var props = field.name.split('.'); var result = item[props.shift()]; while (result && props.length) { result = result[props.shift()]; } return result; }, _setItemFieldValue: function (item, field, value) { var props = field.name.split('.'); var current = item; var prop = props[0]; while (current && props.length) { item = current; prop = props.shift(); current = item[prop]; } if (!current) { while (props.length) { item = item[prop] = {}; prop = props.shift(); } } item[prop] = value; }, 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._normalizeField(field); order = order || ((this._sortField === field) ? this._reversedSortOrder(this._sortOrder) : SORT_ORDER_ASC); this._sortField = field; this._sortOrder = order; }, _normalizeField: 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 = this._visibleFieldIndex(this._sortField); this._headerRow.find("th").eq(fieldIndex) .addClass(this._sortOrder === SORT_ORDER_ASC ? this.sortAscClass : this.sortDescClass); }, _visibleFieldIndex: function (field) { return $.inArray(field, $.grep(this.fields, function (f) { return f.visible; })); }, _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 () { //debugger; 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) { $pagerContainer.append(this._createPager()); } var showPager = this.paging && this._pagesCount() > 1; if (!showPager) $pagerContainer.find('#PerPageNum').val(''); $pagerContainer.toggle(showPager); refreshLang(); }, _createPager: function () { var $result; if ($.isFunction(this.pagerRenderer)) { $result = $(this.pagerRenderer({ pageIndex: this.pageIndex, pageCount: this._pagesCount() })); } else { $result = $("
").append(this._createPagerByFormat()).append(['    ', $('', {// ╠common.PerPage⇒每頁╣ id: 'PerPageNum', 'class': 'form-control w50', value: this.pageSize, keyup: function () { var sValue = this.value, sNewStr = ''; for (var i = 0; i < sValue.length; i++) { if (!isNaN(sValue[i])) { sNewStr += sValue[i]; } } this.value = sNewStr; } }), '']);// ╠common.Pen⇒筆╣ } $result.addClass(this.pagerClass); return $result; }, _createPagerByFormat: function () { //debugger; var pageIndex = this.pageIndex, pageCount = this._pagesCount(), itemCount = this._itemsCount(), pagerParts = this.pagerFormat.split(" "); return $.map(pagerParts, $.proxy(function (pagerPart) { var result = pagerPart; if (pagerPart === PAGES_PLACEHOLDER) { result = this._createPages(); } else if (pagerPart === FIRST_PAGE_PLACEHOLDER) { result = this._createPagerNavButton(this.pageFirstText, 1, pageIndex > 1); } else if (pagerPart === PREV_PAGE_PLACEHOLDER) { result = this._createPagerNavButton(this.pagePrevText, pageIndex - 1, pageIndex > 1); } else if (pagerPart === NEXT_PAGE_PLACEHOLDER) { result = this._createPagerNavButton(this.pageNextText, pageIndex + 1, pageIndex < pageCount); } else if (pagerPart === LAST_PAGE_PLACEHOLDER) { result = this._createPagerNavButton(this.pageLastText, pageCount, pageIndex < pageCount); } else if (pagerPart === PAGE_INDEX_PLACEHOLDER) { result = pageIndex; } else if (pagerPart === PAGE_COUNT_PLACEHOLDER) { result = pageCount; } else if (pagerPart === ITEM_COUNT_PLACEHOLDER) { result = itemCount; } else if (pagerPart === '{Total}') { result = '';// ╠common.Total⇒共╣ } else if (pagerPart === '{Pen}') { result = '';// ╠common.Pen⇒筆╣ } else if (pagerPart === '{Numth}') { result = '';// ╠common.Numth⇒第╣ } else if (pagerPart === '{Page}') { result = '';// ╠common.Page⇒頁╣ } return $.isArray(result) ? result.concat([" "]) : [result, " "]; }, this)); }, _createPages: function () { var pageCount = this._pagesCount(), pageButtonCount = this.pageButtonCount, firstDisplayingPage = this._firstDisplayingPage, pages = []; if (firstDisplayingPage > 1) { pages.push(this._createPagerPageNavButton(this.pageNavigatorPrevText, this.showPrevPages)); } for (var i = 0, pageNumber = firstDisplayingPage; i < pageButtonCount && pageNumber <= pageCount; i++ , pageNumber++) { pages.push(pageNumber === this.pageIndex ? this._createPagerCurrentPage() : this._createPagerPage(pageNumber)); } if ((firstDisplayingPage + pageButtonCount - 1) < pageCount) { pages.push(this._createPagerPageNavButton(this.pageNavigatorNextText, this.showNextPages)); } return pages; }, _createPagerNavButton: function (text, pageIndex, isActive) { return this._createPagerButton(text, this.pagerNavButtonClass + (isActive ? "" : " " + this.pagerNavButtonInactiveClass), isActive ? function () { this.openPage(pageIndex); } : $.noop); }, _createPagerPageNavButton: function (text, handler) { return this._createPagerButton(text, this.pagerNavButtonClass, handler); }, _createPagerPage: function (pageIndex) { return this._createPagerButton(pageIndex, this.pageClass, function () { this.openPage(pageIndex); }); }, _createPagerButton: function (text, css, handler) { var $link = $("").attr("href", EMPTY_HREF) .html(text) .on("click", $.proxy(handler, this)); return $("").addClass(css).append($link); }, _createPagerCurrentPage: function () { return $("") .addClass(this.pageClass) .addClass(this.currentPageClass) .text(this.pageIndex); }, _refreshSize: function () { this._refreshHeight(); this._refreshWidth(); }, _refreshWidth: function () { var width = (this.width === "auto") ? this._getAutoWidth() : this.width; this._container.width(width); }, _getAutoWidth: function () { var $headerGrid = this._headerGrid, $header = this._header; $headerGrid.width("auto"); var contentWidth = $headerGrid.outerWidth(); var borderWidth = $header.outerWidth() - $header.innerWidth(); $headerGrid.width(""); return contentWidth + borderWidth; }, _scrollBarWidth: (function () { var result; return function () { if (result === undefined) { var $ghostContainer = $("
"); var $ghostContent = $("
"); $ghostContainer.append($ghostContent).appendTo("body"); var width = $ghostContent.innerWidth(); $ghostContainer.css("overflow-y", "auto"); var widthExcludingScrollBar = $ghostContent.innerWidth(); $ghostContainer.remove(); result = width - widthExcludingScrollBar; } return result; }; })(), _refreshHeight: function () { var container = this._container, pagerContainer = this._pagerContainer, height = this.height, nonBodyHeight; container.height(height); if (height !== "auto") { height = container.height(); nonBodyHeight = this._header.outerHeight(true); if (pagerContainer.parents(container).length) { nonBodyHeight += pagerContainer.outerHeight(true); } this._body.outerHeight(height - (nonBodyHeight === 0 ? 90 : nonBodyHeight)); } }, showPrevPages: function () { var firstDisplayingPage = this._firstDisplayingPage, pageButtonCount = this.pageButtonCount; this._firstDisplayingPage = (firstDisplayingPage > pageButtonCount) ? firstDisplayingPage - pageButtonCount : 1; this._refreshPager(); }, showNextPages: function () { var firstDisplayingPage = this._firstDisplayingPage, pageButtonCount = this.pageButtonCount, pageCount = this._pagesCount(); this._firstDisplayingPage = (firstDisplayingPage + 2 * pageButtonCount > pageCount) ? pageCount - pageButtonCount + 1 : firstDisplayingPage + pageButtonCount; this._refreshPager(); }, openPage: function (pageIndex) { //if (pageIndex < 1 || pageIndex > this._pagesCount()) // return; this._setPage(pageIndex); this._loadStrategy.openPage(pageIndex); }, _setPage: function (pageIndex) { var firstDisplayingPage = this._firstDisplayingPage, pageButtonCount = this.pageButtonCount; this.pageIndex = pageIndex; if (pageIndex < firstDisplayingPage) { this._firstDisplayingPage = pageIndex; } if (pageIndex > firstDisplayingPage + pageButtonCount - 1) { this._firstDisplayingPage = pageIndex - pageButtonCount + 1; } this._callEventHandler(this.onPageChanged, { pageIndex: pageIndex }); }, _controllerCall: function (method, param, isCanceled, doneCallback) { if (isCanceled) return $.Deferred().reject().promise(); this._showLoading(); var controller = this._controller; if (!controller || !controller[method]) { throw Error("controller has no method '" + method + "'"); } return normalizePromise(controller[method](param)) .done($.proxy(doneCallback, this)) .fail($.proxy(this._errorHandler, this)) .always($.proxy(this._hideLoading, this)); }, _errorHandler: function () { this._callEventHandler(this.onError, { args: $.makeArray(arguments) }); }, _showLoading: function () { if (!this.loadIndication) return; clearTimeout(this._loadingTimer); this._loadingTimer = setTimeout($.proxy(function () { this._loadIndicator.show(); }, this), this.loadIndicationDelay); }, _hideLoading: function () { if (!this.loadIndication) return; clearTimeout(this._loadingTimer); this._loadIndicator.hide(); }, search: function (filter) { this._resetSorting(); this._resetPager(); return this.loadData(filter); }, loadData: function (filter) { //debugger; filter = filter || (this.filtering ? this.getFilter() : {}); $.extend(filter, this._loadStrategy.loadParams(), this._sortingParams()); var args = this._callEventHandler(this.onDataLoading, { filter: filter }); return this._controllerCall("loadData", filter, args.cancel, function (res) { if (!res) { return; } var _data = {}, loadedData = {}; if (res.itemsCount >= 0) { loadedData = res; } else { if (res[0]) { res = res[0]; } if ((res.RESULT !== undefined && !res.RESULT) || (res.d !== undefined && !res.d)) { return; } if (res.RESULT !== undefined) { _data = res.DATA.rel; if ($.isArray(_data)) { _data = { DataList: _data, Total: _data.length }; } } else { _data = JSON.parse(res.d); } loadedData = { data: _data.DataList, itemsCount: _data.Total }; } this._loadStrategy.finishLoad(loadedData); this._callEventHandler(this.onDataLoaded, { data: loadedData }); }); }, getFilter: function () { var result = {}; this._eachField(function (field) { if (field.filtering) { this._setItemFieldValue(result, field, field.filterValue()); } }); return result; }, _sortingParams: function () { if (this.sorting && this._sortField) { return { sortField: this._sortField.name, sortOrder: this._sortOrder }; } return {}; }, getSorting: function () { var sortingParams = this._sortingParams(); return { field: sortingParams.sortField, order: sortingParams.sortOrder }; }, clearFilter: function () { var $filterRow = this._createFilterRow(); this._filterRow.replaceWith($filterRow); this._filterRow = $filterRow; return this.search(); }, insertItem: function (item) { //debugger; var insertingItem = item || this._getValidatedInsertItem(); if (!insertingItem) return $.Deferred().reject().promise(); var args = this._callEventHandler(this.onItemInserting, { item: insertingItem }); return this._controllerCall("insertItem", insertingItem, args.cancel, function (insertedItem) { //debugger; insertedItem = insertedItem || insertingItem; this._loadStrategy.finishInsert(insertedItem); this._callEventHandler(this.onItemInserted, { item: insertedItem }); }); }, _getValidatedInsertItem: function () { var item = this._getInsertItem(); return this._validateItem(item, this._insertRow) ? item : null; }, _getInsertItem: function () { var result = {}; this._eachField(function (field) { if (field.inserting) { this._setItemFieldValue(result, field, field.insertValue()); } }); return result; }, _validateItem: function (item, $row) { var validationErrors = []; var args = { item: item, itemIndex: this._rowIndex($row), row: $row }; this._eachField(function (field) { if (!field.validate || ($row === this._insertRow && !field.inserting) || ($row === this._getEditRow() && !field.editing)) return; var fieldValue = this._getItemFieldValue(item, field); var errors = this._validation.validate($.extend({ value: fieldValue, rules: field.validate }, args)); this._setCellValidity($row.children().eq(this._visibleFieldIndex(field)), errors); if (!errors.length) return; validationErrors.push.apply(validationErrors, $.map(errors, function (message) { return { field: field, message: message }; })); }); if (!validationErrors.length) return true; var invalidArgs = $.extend({ errors: validationErrors }, args); this._callEventHandler(this.onItemInvalid, invalidArgs); this.invalidNotify(invalidArgs); return false; }, _setCellValidity: function ($cell, errors) { $cell .toggleClass(this.invalidClass, !!errors.length) .attr("title", errors.join("\n")); }, clearInsert: function () { var insertRow = this._createInsertRow(); this._insertRow.replaceWith(insertRow); this._insertRow = insertRow; this.refresh(); }, editItem: function (item) { var $row = this.rowByItem(item); if ($row.length) { this._editRow($row); } }, rowByItem: function (item) { if (item.jquery || item.nodeType) return $(item); return this._content.find("tr").filter(function () { return $.data(this, JSGRID_ROW_DATA_KEY) === item; }); }, _editRow: function ($row) { if (!this.editing) return; var item = $row.data(JSGRID_ROW_DATA_KEY); var args = this._callEventHandler(this.onItemEditing, { row: $row, item: item, itemIndex: this._itemIndex(item) }); if (args.cancel) return; if (this._editingRow) { this.cancelEdit(); } var $editRow = this._createEditRow(item); this._editingRow = $row; $row.hide(); $editRow.insertBefore($row); $row.data(JSGRID_EDIT_ROW_DATA_KEY, $editRow); }, _createEditRow: function (item) { if ($.isFunction(this.editRowRenderer)) { return $(this.renderTemplate(this.editRowRenderer, this, { item: item, itemIndex: this._itemIndex(item) })); } var $result = $("
", field, "editcss") .append(this.renderTemplate(field.editTemplate || "", field, { value: fieldValue, item: item })) .appendTo($result); }); return $result; }, updateItem: function (item, editedItem) { //debugger; if (arguments.length === 1) { editedItem = item; } var $row = item ? this.rowByItem(item) : this._editingRow; editedItem = editedItem || this._getValidatedEditedItem(); if (!editedItem) return; return this._updateRow($row, editedItem); }, _getValidatedEditedItem: function () { var item = this._getEditedItem(); return this._validateItem(item, this._getEditRow()) ? item : null; }, _updateRow: function ($updatingRow, editedItem) { //debugger; var updatingItem = $updatingRow.data(JSGRID_ROW_DATA_KEY), updatingItemIndex = this._itemIndex(updatingItem), updatedItem = $.extend(true, {}, updatingItem, editedItem); var args = this._callEventHandler(this.onItemUpdating, { row: $updatingRow, item: updatedItem, itemIndex: updatingItemIndex, previousItem: updatingItem }); return this._controllerCall("updateItem", updatedItem, args.cancel, function (res) { var loadedUpdatedItem = !res || typeof res.DATA.rel !== 'object' ? undefined : res.DATA.rel, previousItem = $.extend(true, {}, updatingItem); updatedItem = loadedUpdatedItem || $.extend(true, updatingItem, editedItem); var $updatedRow = this._finishUpdate($updatingRow, updatedItem, updatingItemIndex); this._callEventHandler(this.onItemUpdated, { row: $updatedRow, item: updatedItem, itemIndex: updatingItemIndex, previousItem: previousItem }); }); }, _rowIndex: function (row) { return this._content.children().index($(row)); }, _itemIndex: function (item) { return $.inArray(item, this.data); }, _finishUpdate: function ($updatingRow, updatedItem, updatedItemIndex) { this.cancelEdit(); this.data[updatedItemIndex] = updatedItem; var $updatedRow = this._createRow(updatedItem, updatedItemIndex); $updatingRow.replaceWith($updatedRow); return $updatedRow; }, _getEditedItem: function () { var result = {}; this._eachField(function (field) { if (field.editing) { this._setItemFieldValue(result, field, field.editValue()); } }); return result; }, cancelEdit: function () { if (!this._editingRow) return; this._getEditRow().remove(); this._editingRow.show(); this._editingRow = null; }, _getEditRow: function () { return this._editingRow && this._editingRow.data(JSGRID_EDIT_ROW_DATA_KEY); }, deleteItem: function (item) { //debugger; var $row = this.rowByItem(item), _this = this; if (!$row.length) return; if (this.confirmDeleting) { layer.confirm(getOrApply(this.deleteConfirm, this, $row.data(JSGRID_ROW_DATA_KEY)), { icon: 3, title: i18next.t('common.Tips') }, function (index) { layer.close(index); //debugger; return _this._deleteRow($row); }); } //return this._deleteRow($row); }, _deleteRow: function ($row) { var deletingItem = $row.data(JSGRID_ROW_DATA_KEY), deletingItemIndex = this._itemIndex(deletingItem); var args = this._callEventHandler(this.onItemDeleting, { row: $row, item: deletingItem, itemIndex: deletingItemIndex }); return this._controllerCall("deleteItem", deletingItem, args.cancel, function () { this._loadStrategy.finishDelete(deletingItem, deletingItemIndex); this._callEventHandler(this.onItemDeleted, { row: $row, item: deletingItem, itemIndex: deletingItemIndex }); }); } }; $.fn.jsGrid = function (config) { var args = $.makeArray(arguments), methodArgs = args.slice(1), result = this; this.each(function () { var $element = $(this), instance = $element.data(JSGRID_DATA_KEY), methodResult; if (instance) { if (typeof config === "string") { methodResult = instance[config].apply(instance, methodArgs); if (methodResult !== undefined && methodResult !== instance) { result = methodResult; return false; } } else { instance._detachWindowResizeCallback(); instance._init(config); instance.render(); } } else { new Grid($element, config); } }); return result; }; var fields = {}; var setDefaults = function (config) { var componentPrototype; if ($.isPlainObject(config)) { componentPrototype = Grid.prototype; } else { componentPrototype = fields[config].prototype; config = arguments[1] || {}; } $.extend(componentPrototype, config); }; var locales = {}; var locale = function (lang) { var localeConfig = $.isPlainObject(lang) ? lang : locales[lang]; if (!localeConfig) throw Error("unknown locale " + lang); setLocale(jsGrid, localeConfig); }; var setLocale = function (obj, localeConfig) { $.each(localeConfig, function (field, value) { if ($.isPlainObject(value)) { setLocale(obj[field] || obj[field[0].toUpperCase() + field.slice(1)], value); return; } if (obj.hasOwnProperty(field)) { obj[field] = value; } else { obj.prototype[field] = value; } }); }; window.jsGrid = { Grid: Grid, fields: fields, setDefaults: setDefaults, locales: locales, locale: locale, version: '1.5.3' }; }(window, jQuery)); (function (jsGrid, $, undefined) { function LoadIndicator(config) { this._init(config); } LoadIndicator.prototype = { container: "body", message: "Loading...", shading: true, zIndex: 1000, shaderClass: "jsgrid-load-shader", loadPanelClass: "jsgrid-load-panel", _init: function (config) { $.extend(true, this, config); this._initContainer(); this._initShader(); this._initLoadPanel(); }, _initContainer: function () { this._container = $(this.container); }, _initShader: function () { if (!this.shading) return; this._shader = $("
").addClass(this.shaderClass) .hide() .css({ position: "absolute", top: 0, right: 0, bottom: 0, left: 0, zIndex: this.zIndex }) .appendTo(this._container); }, _initLoadPanel: function () { this._loadPanel = $("
").addClass(this.loadPanelClass) .text(this.message) .hide() .css({ position: "absolute", top: "50%", left: "50%", zIndex: this.zIndex }) .appendTo(this._container); }, show: function () { var $loadPanel = this._loadPanel.show(); var actualWidth = $loadPanel.outerWidth(); var actualHeight = $loadPanel.outerHeight(); $loadPanel.css({ marginTop: -actualHeight / 2, marginLeft: -actualWidth / 2 }); this._shader.show(); }, hide: function () { this._loadPanel.hide(); this._shader.hide(); } }; jsGrid.LoadIndicator = LoadIndicator; }(jsGrid, jQuery)); (function (jsGrid, $, undefined) { function DirectLoadingStrategy(grid) { this._grid = grid; } DirectLoadingStrategy.prototype = { firstDisplayIndex: function () { var grid = this._grid; return grid.option("paging") ? (grid.option("pageIndex") - 1) * grid.option("pageSize") : 0; }, lastDisplayIndex: function () { var grid = this._grid; //var itemsCount = grid.option("data").length; var itemsCount = grid.option("total").length;//John modified return grid.option("paging") ? Math.min(grid.option("pageIndex") * grid.option("pageSize"), itemsCount) : itemsCount; }, itemsCount: function () { //return this._grid.option("data").length; //debugger; return this._grid.option("total").length;//John modified }, openPage: function (index) { this._grid.refresh(); }, loadParams: function () { return {}; }, sort: function () { this._grid._sortData(); this._grid.refresh(); return $.Deferred().resolve().promise(); }, reset: function () { this._grid.refresh(); return $.Deferred().resolve().promise(); }, finishLoad: function (loadedData) { this._grid.option("data", loadedData); }, finishInsert: function (insertedItem) { var grid = this._grid; grid.option("data").push(insertedItem); grid.refresh(); }, finishDelete: function (deletedItem, deletedItemIndex) { var grid = this._grid; grid.option("data").splice(deletedItemIndex, 1); grid.reset(); } }; function PageLoadingStrategy(grid) { this._grid = grid; this._itemsCount = 0; } PageLoadingStrategy.prototype = { firstDisplayIndex: function () { return 0; }, lastDisplayIndex: function () { return this._grid.option("data").length; }, itemsCount: function () { return this._itemsCount; }, openPage: function (index) { this._grid.loadData(); }, loadParams: function () { var grid = this._grid; return { pageIndex: grid.option("pageIndex"), pageSize: grid.option("pageSize") }; }, reset: function () { return this._grid.loadData(); }, sort: function () { return this._grid.loadData(); }, finishLoad: function (loadedData) { this._itemsCount = loadedData.itemsCount; this._grid.option("data", loadedData.data); }, finishInsert: function (insertedItem) { this._grid.search(); }, finishDelete: function (deletedItem, deletedItemIndex) { this._grid.search(); } }; jsGrid.loadStrategies = { DirectLoadingStrategy: DirectLoadingStrategy, PageLoadingStrategy: PageLoadingStrategy }; }(jsGrid, jQuery)); (function (jsGrid, $, undefined) { var isDefined = function (val) { return typeof (val) !== "undefined" && val !== null; }; var sortStrategies = { string: function (str1, str2) { if (!isDefined(str1) && !isDefined(str2)) return 0; if (!isDefined(str1)) return -1; if (!isDefined(str2)) return 1; return ("" + str1).localeCompare("" + str2); }, number: function (n1, n2) { return n1 - n2; }, date: function (dt1, dt2) { return dt1 - dt2; }, numberAsString: function (n1, n2) { return parseFloat(n1) - parseFloat(n2); } }; jsGrid.sortStrategies = sortStrategies; }(jsGrid, jQuery)); (function (jsGrid, $, undefined) { function Validation(config) { this._init(config); } Validation.prototype = { _init: function (config) { $.extend(true, this, config); }, validate: function (args) { var errors = []; $.each(this._normalizeRules(args.rules), function (_, rule) { if (rule.validator(args.value, args.item, rule.param)) return; var errorMessage = $.isFunction(rule.message) ? rule.message(args.value, args.item) : rule.message; errors.push(errorMessage); }); return errors; }, _normalizeRules: function (rules) { if (!$.isArray(rules)) rules = [rules]; return $.map(rules, $.proxy(function (rule) { return this._normalizeRule(rule); }, this)); }, _normalizeRule: function (rule) { if (typeof rule === "string") rule = { validator: rule }; if ($.isFunction(rule)) rule = { validator: rule }; if ($.isPlainObject(rule)) rule = $.extend({}, rule); else throw Error("wrong validation config specified"); if ($.isFunction(rule.validator)) return rule; return this._applyNamedValidator(rule, rule.validator); }, _applyNamedValidator: function (rule, validatorName) { delete rule.validator; var validator = validators[validatorName]; if (!validator) throw Error("unknown validator \"" + validatorName + "\""); if ($.isFunction(validator)) { validator = { validator: validator }; } return $.extend({}, validator, rule); } }; jsGrid.Validation = Validation; var validators = { required: { message: "Field is required", validator: function (value) { return value !== undefined && value !== null && value !== ""; } }, rangeLength: { message: "Field value length is out of the defined range", validator: function (value, _, param) { return value.length >= param[0] && value.length <= param[1]; } }, minLength: { message: "Field value is too short", validator: function (value, _, param) { return value.length >= param; } }, maxLength: { message: "Field value is too long", validator: function (value, _, param) { return value.length <= param; } }, pattern: { message: "Field value is not matching the defined pattern", validator: function (value, _, param) { if (typeof param === "string") { param = new RegExp("^(?:" + param + ")$"); } return param.test(value); } }, range: { message: "Field value is out of the defined range", validator: function (value, _, param) { return value >= param[0] && value <= param[1]; } }, min: { message: "Field value is too small", validator: function (value, _, param) { return value >= param; } }, max: { message: "Field value is too large", validator: function (value, _, param) { return value <= param; } } }; jsGrid.validators = validators; }(jsGrid, jQuery)); (function (jsGrid, $, undefined) { function Field(config) { $.extend(true, this, config); this.sortingFunc = this._getSortingFunc(); } Field.prototype = { name: "", title: null, css: "", align: "", width: 100, visible: true, filtering: true, inserting: true, editing: true, sorting: true, sorter: "string", // name of SortStrategy or function to compare elements headerTemplate: function () { return (this.title === undefined || this.title === null) ? this.name : this.title; }, itemTemplate: function (value, item) { return value; }, filterTemplate: function () { return ""; }, insertTemplate: function () { return ""; }, editTemplate: function (value, item) { this._value = value; return this.itemTemplate(value, item); }, filterValue: function () { return ""; }, insertValue: function () { return ""; }, editValue: function () { return this._value; }, _getSortingFunc: function () { var sorter = this.sorter; if ($.isFunction(sorter)) { return sorter; } if (typeof sorter === "string") { return jsGrid.sortStrategies[sorter]; } throw Error("wrong sorter for the field \"" + this.name + "\"!"); } }; jsGrid.Field = Field; }(jsGrid, jQuery)); (function (jsGrid, $, undefined) { var Field = jsGrid.Field; function TextField(config) { Field.call(this, config); } TextField.prototype = new Field({ autosearch: true, readOnly: false, filterTemplate: function () { if (!this.filtering) return ""; var grid = this._grid, $result = this.filterControl = this._createTextBox(); if (this.autosearch) { $result.on("keypress", function (e) { if (e.which === 13) { grid.search(); e.preventDefault(); } }); } return $result; }, insertTemplate: function () { if (!this.inserting) return ""; return this.insertControl = this._createTextBox(); }, editTemplate: function (value) { if (!this.editing) return this.itemTemplate.apply(this, arguments); var $result = this.editControl = this._createTextBox(); $result.val(value); return $result; }, filterValue: function () { return this.filterControl.val(); }, insertValue: function () { return this.insertControl.val(); }, editValue: function () { return this.editControl.val(); }, _createTextBox: function () { return $("").attr("type", "text").attr("class", "form-control w100p") .prop("readonly", !!this.readOnly); } }); jsGrid.fields.text = jsGrid.TextField = TextField; }(jsGrid, jQuery)); (function (jsGrid, $, undefined) { var TextField = jsGrid.TextField; function NumberField(config) { TextField.call(this, config); } NumberField.prototype = new TextField({ sorter: "number", align: "right", readOnly: false, filterValue: function () { return this.filterControl.val() ? parseInt(this.filterControl.val() || 0, 10) : undefined; }, insertValue: function () { return this.insertControl.val() ? parseInt(this.insertControl.val() || 0, 10) : undefined; }, editValue: function () { return this.editControl.val() ? parseInt(this.editControl.val() || 0, 10) : undefined; }, _createTextBox: function () { return $("").attr("type", "number").attr("class", "form-control w100p") .prop("readonly", !!this.readOnly); } }); jsGrid.fields.number = jsGrid.NumberField = NumberField; }(jsGrid, jQuery)); (function (jsGrid, $, undefined) { var TextField = jsGrid.TextField; function TextAreaField(config) { TextField.call(this, config); } TextAreaField.prototype = new TextField({ insertTemplate: function () { if (!this.inserting) return ""; return this.insertControl = this._createTextArea(); }, editTemplate: function (value) { if (!this.editing) return this.itemTemplate.apply(this, arguments); var $result = this.editControl = this._createTextArea(); $result.val(value); return $result; }, _createTextArea: function () { return $("