You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2591 lines
80 KiB

2 years ago
  1. /*
  2. * jsGrid v1.5.3 (http://js-grid.com)
  3. * (c) 2016 Artem Tabalin
  4. * Licensed under MIT (https://github.com/tabalinas/jsgrid/blob/master/LICENSE)
  5. */
  6. (function (window, $, undefined) {
  7. var JSGRID = "JSGrid",
  8. JSGRID_DATA_KEY = JSGRID,
  9. JSGRID_ROW_DATA_KEY = "JSGridItem",
  10. JSGRID_EDIT_ROW_DATA_KEY = "JSGridEditRow",
  11. SORT_ORDER_ASC = "asc",
  12. SORT_ORDER_DESC = "desc",
  13. FIRST_PAGE_PLACEHOLDER = "{first}",
  14. PAGES_PLACEHOLDER = "{pages}",
  15. PREV_PAGE_PLACEHOLDER = "{prev}",
  16. NEXT_PAGE_PLACEHOLDER = "{next}",
  17. LAST_PAGE_PLACEHOLDER = "{last}",
  18. PAGE_INDEX_PLACEHOLDER = "{pageIndex}",
  19. PAGE_COUNT_PLACEHOLDER = "{pageCount}",
  20. ITEM_COUNT_PLACEHOLDER = "{itemCount}",
  21. EMPTY_HREF = "javascript:void(0);";
  22. var getOrApply = function (value, context) {
  23. if ($.isFunction(value)) {
  24. return value.apply(context, $.makeArray(arguments).slice(2));
  25. }
  26. return value;
  27. };
  28. var normalizePromise = function (promise) {
  29. var d = $.Deferred();
  30. if (promise && promise.then) {
  31. promise.then(function () {
  32. d.resolve.apply(d, arguments);
  33. }, function () {
  34. d.reject.apply(d, arguments);
  35. });
  36. } else {
  37. d.resolve(promise);
  38. }
  39. return d.promise();
  40. };
  41. var defaultController = {
  42. loadData: $.noop,
  43. insertItem: $.noop,
  44. updateItem: $.noop,
  45. deleteItem: $.noop
  46. };
  47. function Grid(element, config) {
  48. var $element = $(element);
  49. $element.data(JSGRID_DATA_KEY, this);
  50. this._container = $element;
  51. this.data = [];
  52. this.total = 0;//John Add
  53. this.fields = [];
  54. this._editingRow = null;
  55. this._sortField = null;
  56. this._sortOrder = SORT_ORDER_ASC;
  57. this._firstDisplayingPage = 1;
  58. this._init(config);
  59. this.render();
  60. }
  61. Grid.prototype = {
  62. width: "auto",
  63. height: "auto",
  64. updateOnResize: true,
  65. rowClass: $.noop,
  66. rowRenderer: null,
  67. rowClick: function (args) {
  68. if (this.editing) {
  69. this.editItem($(args.event.target).closest("tr"));
  70. }
  71. },
  72. rowDoubleClick: $.noop,
  73. rowMouseDown: $.noop,
  74. rowMouseUp: $.noop,
  75. rowMouseUut: $.noop,
  76. noDataContent: "Not found",
  77. noDataRowClass: "jsgrid-nodata-row",
  78. heading: true,
  79. headerRowRenderer: null,
  80. headerRowClass: "jsgrid-header-row",
  81. headerCellClass: "jsgrid-header-cell",
  82. filtering: false,
  83. filterRowRenderer: null,
  84. filterRowClass: "jsgrid-filter-row",
  85. inserting: false,
  86. insertRowRenderer: null,
  87. insertRowClass: "jsgrid-insert-row",
  88. editing: false,
  89. editRowRenderer: null,
  90. editRowClass: "jsgrid-edit-row",
  91. confirmDeleting: true,
  92. deleteConfirm: "Are you sure?",
  93. selecting: true,
  94. selectedRowClass: "jsgrid-selected-row",
  95. oddRowClass: "jsgrid-row",
  96. evenRowClass: "jsgrid-alt-row",
  97. cellClass: "jsgrid-cell",
  98. sorting: false,
  99. sortableClass: "jsgrid-header-sortable",
  100. sortAscClass: "jsgrid-header-sort jsgrid-header-sort-asc",
  101. sortDescClass: "jsgrid-header-sort jsgrid-header-sort-desc",
  102. paging: false,
  103. pagerContainer: null,
  104. pageIndex: 1,
  105. pageSize: 20,
  106. pageButtonCount: 15,
  107. //pagerFormat: "Pages: {first} {prev} {pages} {next} {last}    {pageIndex} of {pageCount}      {pagepernumber}",
  108. pagerFormat: "{Total} {itemCount} {Pen} {first} {prev} {pages} {next} {last}      {Numth} {pageIndex} {Page} {Total} {pageCount} {Page}",
  109. pagePrevText: "Prev",
  110. pageNextText: "Next",
  111. pageFirstText: "First",
  112. pageLastText: "Last",
  113. pageNavigatorNextText: "...",
  114. pageNavigatorPrevText: "...",
  115. pagerContainerClass: "jsgrid-pager-container",
  116. pagerClass: "jsgrid-pager",
  117. pagerNavButtonClass: "jsgrid-pager-nav-button",
  118. pagerNavButtonInactiveClass: "jsgrid-pager-nav-inactive-button",
  119. pageClass: "jsgrid-pager-page",
  120. currentPageClass: "jsgrid-pager-current-page",
  121. customLoading: false,
  122. pageLoading: false,
  123. autoload: false,
  124. controller: defaultController,
  125. loadIndication: true,
  126. loadIndicationDelay: 500,
  127. loadMessage: "Please, wait...",
  128. loadShading: true,
  129. invalidMessage: "Invalid data entered!",
  130. invalidNotify: function (args) {
  131. var messages = $.map(args.errors, function (error) {
  132. return error.message || null;
  133. });
  134. //window.alert([this.invalidMessage].concat(messages).join("\n"));
  135. showMsg([this.invalidMessage].concat(messages).join("<br>"), 'info');
  136. },
  137. onInit: $.noop,
  138. onRefreshing: $.noop,
  139. onRefreshed: $.noop,
  140. onPageChanged: $.noop,
  141. onItemDeleting: $.noop,
  142. onItemDeleted: $.noop,
  143. onItemInserting: $.noop,
  144. onItemInserted: $.noop,
  145. onItemEditing: $.noop,
  146. onItemUpdating: $.noop,
  147. onItemUpdated: $.noop,
  148. onItemInvalid: $.noop,
  149. onDataLoading: $.noop,
  150. onDataLoaded: $.noop,
  151. onOptionChanging: $.noop,
  152. onOptionChanged: $.noop,
  153. onError: $.noop,
  154. invalidClass: "jsgrid-invalid",
  155. containerClass: "jsgrid",
  156. tableClass: "jsgrid-table",
  157. gridHeaderClass: "jsgrid-grid-header",
  158. gridBodyClass: "jsgrid-grid-body",
  159. _init: function (config) {
  160. //debugger;
  161. $.extend(this, config);
  162. this._initLoadStrategy();
  163. this._initController();
  164. this._initFields();
  165. this._attachWindowLoadResize();
  166. this._attachWindowResizeCallback();
  167. this._callEventHandler(this.onInit);
  168. if (!this.dfheight) {
  169. this.dfheight = this.height;
  170. }
  171. },
  172. loadStrategy: function () {
  173. return this.pageLoading
  174. ? new jsGrid.loadStrategies.PageLoadingStrategy(this)
  175. : new jsGrid.loadStrategies.DirectLoadingStrategy(this);
  176. },
  177. _initLoadStrategy: function () {
  178. this._loadStrategy = getOrApply(this.loadStrategy, this);
  179. },
  180. _initController: function () {
  181. this._controller = $.extend({}, defaultController, getOrApply(this.controller, this));
  182. },
  183. renderTemplate: function (source, context, config) {
  184. args = [];
  185. for (var key in config) {
  186. args.push(config[key]);
  187. }
  188. args.unshift(source, context);
  189. source = getOrApply.apply(null, args);
  190. return (source === undefined || source === null) ? "" : source;
  191. },
  192. loadIndicator: function (config) {
  193. return new jsGrid.LoadIndicator(config);
  194. },
  195. validation: function (config) {
  196. return jsGrid.Validation && new jsGrid.Validation(config);
  197. },
  198. _initFields: function () {
  199. var self = this;
  200. self.fields = $.map(self.fields, function (field) {
  201. if ($.isPlainObject(field)) {
  202. var fieldConstructor = (field.type && jsGrid.fields[field.type]) || jsGrid.Field;
  203. field = new fieldConstructor(field);
  204. }
  205. field._grid = self;
  206. return field;
  207. });
  208. },
  209. _attachWindowLoadResize: function () {
  210. $(window).on("load", $.proxy(this._refreshSize, this));
  211. },
  212. _attachWindowResizeCallback: function () {
  213. if (this.updateOnResize) {
  214. $(window).on("resize", $.proxy(this._refreshSize, this));
  215. }
  216. },
  217. _detachWindowResizeCallback: function () {
  218. $(window).off("resize", this._refreshSize);
  219. },
  220. option: function (key, value) {
  221. var optionChangingEventArgs,
  222. optionChangedEventArgs;
  223. if (arguments.length === 1)
  224. return this[key];
  225. optionChangingEventArgs = {
  226. option: key,
  227. oldValue: this[key],
  228. newValue: value
  229. };
  230. this._callEventHandler(this.onOptionChanging, optionChangingEventArgs);
  231. this._handleOptionChange(optionChangingEventArgs.option, optionChangingEventArgs.newValue);
  232. optionChangedEventArgs = {
  233. option: optionChangingEventArgs.option,
  234. value: optionChangingEventArgs.newValue
  235. };
  236. this._callEventHandler(this.onOptionChanged, optionChangedEventArgs);
  237. },
  238. fieldOption: function (field, key, value) {
  239. field = this._normalizeField(field);
  240. if (arguments.length === 2)
  241. return field[key];
  242. field[key] = value;
  243. this._renderGrid();
  244. },
  245. _handleOptionChange: function (name, value) {
  246. this[name] = value;
  247. switch (name) {
  248. case "width":
  249. case "height":
  250. this._refreshSize();
  251. break;
  252. case "rowClass":
  253. case "rowRenderer":
  254. case "rowClick":
  255. case "rowDoubleClick":
  256. case "rowMouseDown":
  257. case "rowMouseUp":
  258. case "rowMouseUut":
  259. case "noDataRowClass":
  260. case "noDataContent":
  261. case "selecting":
  262. case "selectedRowClass":
  263. case "oddRowClass":
  264. case "evenRowClass":
  265. this._refreshContent();
  266. break;
  267. case "pageButtonCount":
  268. case "pagerFormat":
  269. case "pagePrevText":
  270. case "pageNextText":
  271. case "pageFirstText":
  272. case "pageLastText":
  273. case "pageNavigatorNextText":
  274. case "pageNavigatorPrevText":
  275. case "pagerClass":
  276. case "pagerNavButtonClass":
  277. case "pageClass":
  278. case "currentPageClass":
  279. case "pagerRenderer":
  280. this._refreshPager();
  281. break;
  282. case "fields":
  283. this._initFields();
  284. this.render();
  285. break;
  286. case "data":
  287. case "editing":
  288. case "heading":
  289. case "filtering":
  290. case "inserting":
  291. case "paging":
  292. this.refresh();
  293. break;
  294. case "loadStrategy":
  295. case "pageLoading":
  296. this._initLoadStrategy();
  297. this.search();
  298. break;
  299. case "pageIndex":
  300. this.openPage(value);
  301. break;
  302. case "pageSize":
  303. this.refresh();
  304. this.search();
  305. break;
  306. case "editRowRenderer":
  307. case "editRowClass":
  308. this.cancelEdit();
  309. break;
  310. case "updateOnResize":
  311. this._detachWindowResizeCallback();
  312. this._attachWindowResizeCallback();
  313. break;
  314. case "invalidNotify":
  315. case "invalidMessage":
  316. break;
  317. default:
  318. this.render();
  319. break;
  320. }
  321. },
  322. destroy: function () {
  323. this._detachWindowResizeCallback();
  324. this._clear();
  325. this._container.removeData(JSGRID_DATA_KEY);
  326. },
  327. render: function () {
  328. this._renderGrid();
  329. return this.autoload ? this.loadData() : $.Deferred().resolve().promise();
  330. },
  331. _renderGrid: function () {
  332. this._clear();
  333. this._container.addClass(this.containerClass)
  334. .css("position", "relative")
  335. .append(this._createHeader())
  336. .append(this._createBody());
  337. this._pagerContainer = this._createPagerContainer();
  338. this._loadIndicator = this._createLoadIndicator();
  339. this._validation = this._createValidation();
  340. this.refresh();
  341. },
  342. _createLoadIndicator: function () {
  343. return getOrApply(this.loadIndicator, this, {
  344. message: this.loadMessage,
  345. shading: this.loadShading,
  346. container: this._container
  347. });
  348. },
  349. _createValidation: function () {
  350. return getOrApply(this.validation, this);
  351. },
  352. _clear: function () {
  353. this.cancelEdit();
  354. clearTimeout(this._loadingTimer);
  355. this._pagerContainer && this._pagerContainer.empty();
  356. this._container.empty()
  357. .css({ position: "", width: "", height: "" });
  358. },
  359. _createHeader: function () {
  360. var $headerRow = this._headerRow = this._createHeaderRow(),
  361. $filterRow = this._filterRow = this._createFilterRow(),
  362. $insertRow = this._insertRow = this._createInsertRow();
  363. var $headerGrid = this._headerGrid = $("<table>").addClass(this.tableClass)
  364. .append($headerRow)
  365. .append($filterRow)
  366. .append($insertRow);
  367. var $header = this._header = $("<div>").addClass(this.gridHeaderClass)
  368. .addClass(this._scrollBarWidth() ? "jsgrid-header-scrollbar" : "")
  369. .append($headerGrid);
  370. return $header;
  371. },
  372. _createBody: function () {
  373. var $content = this._content = $("<tbody>");
  374. var $bodyGrid = this._bodyGrid = $("<table>").addClass(this.tableClass)
  375. .append($content);
  376. var $body = this._body = $("<div>").addClass(this.gridBodyClass)
  377. .append($bodyGrid)
  378. .on("scroll", $.proxy(function (e) {
  379. this._header.scrollLeft(e.target.scrollLeft);
  380. }, this));
  381. return $body;
  382. },
  383. _createPagerContainer: function () {
  384. var pagerContainer = this.pagerContainer || $("<div>").appendTo(this._container);
  385. return $(pagerContainer).addClass(this.pagerContainerClass);
  386. },
  387. _eachField: function (callBack) {
  388. var self = this;
  389. $.each(this.fields, function (index, field) {
  390. if (field.visible) {
  391. callBack.call(self, field, index);
  392. }
  393. });
  394. },
  395. _createHeaderRow: function () {
  396. if ($.isFunction(this.headerRowRenderer))
  397. return $(this.renderTemplate(this.headerRowRenderer, this));
  398. var $result = $("<tr>").addClass(this.headerRowClass);
  399. this._eachField(function (field, index) {
  400. var $th = this._prepareCell("<th>", field, "headercss", this.headerCellClass)
  401. .append(this.renderTemplate(field.headerTemplate, field));
  402. if (field.title) {
  403. $th.attr('data-i18n', field.title);
  404. }
  405. $th.appendTo($result);
  406. if (this.sorting && field.sorting) {
  407. $th.addClass(this.sortableClass)
  408. .on("click", $.proxy(function () {
  409. if (typeof this.headerClick === 'function') {
  410. this.headerClick();
  411. }
  412. this.sort(index);
  413. }, this));
  414. }
  415. });
  416. return $result;
  417. },
  418. _prepareCell: function (cell, field, cssprop, cellClass) {
  419. return $(cell).css("width", field.width)
  420. .addClass(cellClass || this.cellClass)
  421. .addClass((cssprop && field[cssprop]) || field.css)
  422. .addClass(field.align ? ("jsgrid-align-" + field.align) : "");
  423. },
  424. _createFilterRow: function () {
  425. if ($.isFunction(this.filterRowRenderer))
  426. return $(this.renderTemplate(this.filterRowRenderer, this));
  427. var $result = $("<tr>").addClass(this.filterRowClass);
  428. this._eachField(function (field) {
  429. this._prepareCell("<td>", field, "filtercss")
  430. .append(this.renderTemplate(field.filterTemplate, field))
  431. .appendTo($result);
  432. });
  433. return $result;
  434. },
  435. _createInsertRow: function () {
  436. if ($.isFunction(this.insertRowRenderer))
  437. return $(this.renderTemplate(this.insertRowRenderer, this));
  438. var $result = $("<tr>").addClass(this.insertRowClass);
  439. this._eachField(function (field) {
  440. this._prepareCell("<td>", field, "insertcss")
  441. .append(this.renderTemplate(field.insertTemplate, field))
  442. .appendTo($result);
  443. });
  444. return $result;
  445. },
  446. _callEventHandler: function (handler, eventParams) {
  447. handler.call(this, $.extend(eventParams, {
  448. grid: this
  449. }));
  450. return eventParams;
  451. },
  452. reset: function () {
  453. this._resetSorting();
  454. this._resetPager();
  455. return this._loadStrategy.reset();
  456. },
  457. _resetPager: function () {
  458. this._firstDisplayingPage = 1;
  459. this._setPage(1);
  460. },
  461. _resetSorting: function () {
  462. this._sortField = null;
  463. this._sortOrder = SORT_ORDER_ASC;
  464. this._clearSortingCss();
  465. },
  466. refresh: function () {
  467. this._callEventHandler(this.onRefreshing);
  468. this.cancelEdit();
  469. this._refreshHeading();
  470. this._refreshFiltering();
  471. this._refreshInserting();
  472. this._refreshContent();
  473. this._refreshPager();
  474. this._refreshSize();
  475. this._callEventHandler(this.onRefreshed);
  476. },
  477. _refreshHeading: function () {
  478. this._headerRow.toggle(this.heading);
  479. },
  480. _refreshFiltering: function () {
  481. this._filterRow.toggle(this.filtering);
  482. },
  483. _refreshInserting: function () {
  484. this._insertRow.toggle(this.inserting);
  485. },
  486. _refreshContent: function () {
  487. var $content = this._content;
  488. $content.empty();
  489. if (!this.data.length) {
  490. $content.append(this._createNoDataRow());
  491. return this;
  492. }
  493. var indexFrom = this._loadStrategy.firstDisplayIndex();
  494. var indexTo = this._loadStrategy.lastDisplayIndex();
  495. for (var itemIndex = indexFrom; itemIndex < indexTo; itemIndex++) {
  496. var item = this.data[itemIndex];
  497. $content.append(this._createRow(item, itemIndex));
  498. }
  499. },
  500. _createNoDataRow: function () {
  501. var amountOfFields = 0;
  502. this._eachField(function () {
  503. amountOfFields++;
  504. });
  505. return $("<tr>").addClass(this.noDataRowClass)
  506. .append($("<td>").addClass(this.cellClass).attr("colspan", amountOfFields)
  507. .append(this.renderTemplate(this.noDataContent, this)));
  508. },
  509. _createRow: function (item, itemIndex) {
  510. var $result;
  511. if ($.isFunction(this.rowRenderer)) {
  512. $result = this.renderTemplate(this.rowRenderer, this, { item: item, itemIndex: itemIndex });
  513. } else {
  514. $result = $("<tr>");
  515. this._renderCells($result, item);
  516. }
  517. $result.addClass(this._getRowClasses(item, itemIndex))
  518. .data(JSGRID_ROW_DATA_KEY, item)
  519. .on("click", $.proxy(function (e) {
  520. this.rowClick({
  521. item: item,
  522. itemIndex: itemIndex,
  523. event: e
  524. });
  525. $result.siblings().removeClass('grid-selected');
  526. $result.addClass('grid-selected');
  527. }, this))
  528. .on("dblclick", $.proxy(function (e) {
  529. this.rowDoubleClick({
  530. item: item,
  531. itemIndex: itemIndex,
  532. event: e
  533. });
  534. }, this))
  535. .on("mousedown", $.proxy(function (e) {
  536. this.rowMouseDown({
  537. item: item,
  538. itemIndex: itemIndex,
  539. event: e
  540. });
  541. }, this))
  542. .on("mouseup", $.proxy(function (e) {
  543. this.rowMouseUp({
  544. item: item,
  545. itemIndex: itemIndex,
  546. event: e
  547. });
  548. }, this))
  549. .on("mouseout", $.proxy(function (e) {
  550. this.rowMouseUut({
  551. item: item,
  552. itemIndex: itemIndex,
  553. event: e
  554. });
  555. }, this));
  556. if (this.selecting) {
  557. this._attachRowHover($result);
  558. }
  559. return $result;
  560. },
  561. _getRowClasses: function (item, itemIndex) {
  562. var classes = [];
  563. classes.push(((itemIndex + 1) % 2) ? this.oddRowClass : this.evenRowClass);
  564. classes.push(getOrApply(this.rowClass, this, item, itemIndex));
  565. return classes.join(" ");
  566. },
  567. _attachRowHover: function ($row) {
  568. var selectedRowClass = this.selectedRowClass;
  569. $row.hover(function () {
  570. $(this).addClass(selectedRowClass);
  571. },
  572. function () {
  573. $(this).removeClass(selectedRowClass);
  574. }
  575. );
  576. },
  577. _renderCells: function ($row, item) {
  578. this._eachField(function (field) {
  579. $row.append(this._createCell(item, field));
  580. });
  581. return this;
  582. },
  583. _createCell: function (item, field) {
  584. var $result;
  585. var fieldValue = this._getItemFieldValue(item, field);
  586. var args = { value: fieldValue, item: item };
  587. if ($.isFunction(field.cellRenderer)) {
  588. $result = this.renderTemplate(field.cellRenderer, field, args);
  589. } else {
  590. $result = $("<td>").append(this.renderTemplate(field.itemTemplate || fieldValue, field, args));
  591. }
  592. return this._prepareCell($result, field);
  593. },
  594. _getItemFieldValue: function (item, field) {
  595. var props = field.name.split('.');
  596. var result = item[props.shift()];
  597. while (result && props.length) {
  598. result = result[props.shift()];
  599. }
  600. return result;
  601. },
  602. _setItemFieldValue: function (item, field, value) {
  603. var props = field.name.split('.');
  604. var current = item;
  605. var prop = props[0];
  606. while (current && props.length) {
  607. item = current;
  608. prop = props.shift();
  609. current = item[prop];
  610. }
  611. if (!current) {
  612. while (props.length) {
  613. item = item[prop] = {};
  614. prop = props.shift();
  615. }
  616. }
  617. item[prop] = value;
  618. },
  619. sort: function (field, order) {
  620. if ($.isPlainObject(field)) {
  621. order = field.order;
  622. field = field.field;
  623. }
  624. this._clearSortingCss();
  625. this._setSortingParams(field, order);
  626. this._setSortingCss();
  627. return this._loadStrategy.sort();
  628. },
  629. _clearSortingCss: function () {
  630. this._headerRow.find("th")
  631. .removeClass(this.sortAscClass)
  632. .removeClass(this.sortDescClass);
  633. },
  634. _setSortingParams: function (field, order) {
  635. field = this._normalizeField(field);
  636. order = order || ((this._sortField === field) ? this._reversedSortOrder(this._sortOrder) : SORT_ORDER_ASC);
  637. this._sortField = field;
  638. this._sortOrder = order;
  639. },
  640. _normalizeField: function (field) {
  641. if ($.isNumeric(field)) {
  642. return this.fields[field];
  643. }
  644. if (typeof field === "string") {
  645. return $.grep(this.fields, function (f) {
  646. return f.name === field;
  647. })[0];
  648. }
  649. return field;
  650. },
  651. _reversedSortOrder: function (order) {
  652. return (order === SORT_ORDER_ASC ? SORT_ORDER_DESC : SORT_ORDER_ASC);
  653. },
  654. _setSortingCss: function () {
  655. var fieldIndex = this._visibleFieldIndex(this._sortField);
  656. this._headerRow.find("th").eq(fieldIndex)
  657. .addClass(this._sortOrder === SORT_ORDER_ASC ? this.sortAscClass : this.sortDescClass);
  658. },
  659. _visibleFieldIndex: function (field) {
  660. return $.inArray(field, $.grep(this.fields, function (f) { return f.visible; }));
  661. },
  662. _sortData: function () {
  663. var sortFactor = this._sortFactor(),
  664. sortField = this._sortField;
  665. if (sortField) {
  666. this.data.sort(function (item1, item2) {
  667. return sortFactor * sortField.sortingFunc(item1[sortField.name], item2[sortField.name]);
  668. });
  669. }
  670. },
  671. _sortFactor: function () {
  672. return this._sortOrder === SORT_ORDER_ASC ? 1 : -1;
  673. },
  674. _itemsCount: function () {
  675. return this._loadStrategy.itemsCount();
  676. },
  677. _pagesCount: function () {
  678. //debugger;
  679. var itemsCount = this._itemsCount(),
  680. pageSize = this.pageSize;
  681. return Math.floor(itemsCount / pageSize) + (itemsCount % pageSize ? 1 : 0);
  682. },
  683. _refreshPager: function () {
  684. var $pagerContainer = this._pagerContainer;
  685. $pagerContainer.empty();
  686. if (this.paging) {
  687. $pagerContainer.append(this._createPager());
  688. }
  689. var showPager = this.paging && this._pagesCount() > 1;
  690. if (!showPager) $pagerContainer.find('#PerPageNum').val('');
  691. $pagerContainer.toggle(showPager);
  692. refreshLang();
  693. },
  694. _createPager: function () {
  695. var $result;
  696. if ($.isFunction(this.pagerRenderer)) {
  697. $result = $(this.pagerRenderer({
  698. pageIndex: this.pageIndex,
  699. pageCount: this._pagesCount()
  700. }));
  701. } else {
  702. $result = $("<div>").append(this._createPagerByFormat()).append(['&nbsp;&nbsp;&nbsp;&nbsp;<span data-i18n="common.PerPage"></span>', $('<input/>', {// ╠common.PerPage⇒每頁╣
  703. id: 'PerPageNum',
  704. 'class': 'form-control w50',
  705. value: this.pageSize,
  706. keyup: function () {
  707. var sValue = this.value,
  708. sNewStr = '';
  709. for (var i = 0; i < sValue.length; i++) {
  710. if (!isNaN(sValue[i])) {
  711. sNewStr += sValue[i];
  712. }
  713. }
  714. this.value = sNewStr;
  715. }
  716. }), '<span data-i18n="common.Pen"></span>']);// ╠common.Pen⇒筆╣
  717. }
  718. $result.addClass(this.pagerClass);
  719. return $result;
  720. },
  721. _createPagerByFormat: function () {
  722. //debugger;
  723. var pageIndex = this.pageIndex,
  724. pageCount = this._pagesCount(),
  725. itemCount = this._itemsCount(),
  726. pagerParts = this.pagerFormat.split(" ");
  727. return $.map(pagerParts, $.proxy(function (pagerPart) {
  728. var result = pagerPart;
  729. if (pagerPart === PAGES_PLACEHOLDER) {
  730. result = this._createPages();
  731. } else if (pagerPart === FIRST_PAGE_PLACEHOLDER) {
  732. result = this._createPagerNavButton(this.pageFirstText, 1, pageIndex > 1);
  733. } else if (pagerPart === PREV_PAGE_PLACEHOLDER) {
  734. result = this._createPagerNavButton(this.pagePrevText, pageIndex - 1, pageIndex > 1);
  735. } else if (pagerPart === NEXT_PAGE_PLACEHOLDER) {
  736. result = this._createPagerNavButton(this.pageNextText, pageIndex + 1, pageIndex < pageCount);
  737. } else if (pagerPart === LAST_PAGE_PLACEHOLDER) {
  738. result = this._createPagerNavButton(this.pageLastText, pageCount, pageIndex < pageCount);
  739. } else if (pagerPart === PAGE_INDEX_PLACEHOLDER) {
  740. result = pageIndex;
  741. } else if (pagerPart === PAGE_COUNT_PLACEHOLDER) {
  742. result = pageCount;
  743. } else if (pagerPart === ITEM_COUNT_PLACEHOLDER) {
  744. result = itemCount;
  745. } else if (pagerPart === '{Total}') {
  746. result = '<span data-i18n="common.Total"></span>';// ╠common.Total⇒共╣
  747. } else if (pagerPart === '{Pen}') {
  748. result = '<span data-i18n="common.Pen"></span>';// ╠common.Pen⇒筆╣
  749. } else if (pagerPart === '{Numth}') {
  750. result = '<span data-i18n="common.Numth"></span>';// ╠common.Numth⇒第╣
  751. } else if (pagerPart === '{Page}') {
  752. result = '<span data-i18n="common.Page"></span>';// ╠common.Page⇒頁╣
  753. }
  754. return $.isArray(result) ? result.concat([" "]) : [result, " "];
  755. }, this));
  756. },
  757. _createPages: function () {
  758. var pageCount = this._pagesCount(),
  759. pageButtonCount = this.pageButtonCount,
  760. firstDisplayingPage = this._firstDisplayingPage,
  761. pages = [];
  762. if (firstDisplayingPage > 1) {
  763. pages.push(this._createPagerPageNavButton(this.pageNavigatorPrevText, this.showPrevPages));
  764. }
  765. for (var i = 0, pageNumber = firstDisplayingPage; i < pageButtonCount && pageNumber <= pageCount; i++ , pageNumber++) {
  766. pages.push(pageNumber === this.pageIndex
  767. ? this._createPagerCurrentPage()
  768. : this._createPagerPage(pageNumber));
  769. }
  770. if ((firstDisplayingPage + pageButtonCount - 1) < pageCount) {
  771. pages.push(this._createPagerPageNavButton(this.pageNavigatorNextText, this.showNextPages));
  772. }
  773. return pages;
  774. },
  775. _createPagerNavButton: function (text, pageIndex, isActive) {
  776. return this._createPagerButton(text, this.pagerNavButtonClass + (isActive ? "" : " " + this.pagerNavButtonInactiveClass),
  777. isActive ? function () { this.openPage(pageIndex); } : $.noop);
  778. },
  779. _createPagerPageNavButton: function (text, handler) {
  780. return this._createPagerButton(text, this.pagerNavButtonClass, handler);
  781. },
  782. _createPagerPage: function (pageIndex) {
  783. return this._createPagerButton(pageIndex, this.pageClass, function () {
  784. this.openPage(pageIndex);
  785. });
  786. },
  787. _createPagerButton: function (text, css, handler) {
  788. var $link = $("<a>").attr("href", EMPTY_HREF)
  789. .html(text)
  790. .on("click", $.proxy(handler, this));
  791. return $("<span>").addClass(css).append($link);
  792. },
  793. _createPagerCurrentPage: function () {
  794. return $("<span>")
  795. .addClass(this.pageClass)
  796. .addClass(this.currentPageClass)
  797. .text(this.pageIndex);
  798. },
  799. _refreshSize: function () {
  800. this._refreshHeight();
  801. this._refreshWidth();
  802. },
  803. _refreshWidth: function () {
  804. var width = (this.width === "auto") ? this._getAutoWidth() : this.width;
  805. this._container.width(width);
  806. },
  807. _getAutoWidth: function () {
  808. var $headerGrid = this._headerGrid,
  809. $header = this._header;
  810. $headerGrid.width("auto");
  811. var contentWidth = $headerGrid.outerWidth();
  812. var borderWidth = $header.outerWidth() - $header.innerWidth();
  813. $headerGrid.width("");
  814. return contentWidth + borderWidth;
  815. },
  816. _scrollBarWidth: (function () {
  817. var result;
  818. return function () {
  819. if (result === undefined) {
  820. var $ghostContainer = $("<div style='width:50px;height:50px;overflow:hidden;position:absolute;top:-10000px;left:-10000px;'></div>");
  821. var $ghostContent = $("<div style='height:100px;'></div>");
  822. $ghostContainer.append($ghostContent).appendTo("body");
  823. var width = $ghostContent.innerWidth();
  824. $ghostContainer.css("overflow-y", "auto");
  825. var widthExcludingScrollBar = $ghostContent.innerWidth();
  826. $ghostContainer.remove();
  827. result = width - widthExcludingScrollBar;
  828. }
  829. return result;
  830. };
  831. })(),
  832. _refreshHeight: function () {
  833. var container = this._container,
  834. pagerContainer = this._pagerContainer,
  835. height = this.height,
  836. nonBodyHeight;
  837. container.height(height);
  838. if (height !== "auto") {
  839. height = container.height();
  840. nonBodyHeight = this._header.outerHeight(true);
  841. if (pagerContainer.parents(container).length) {
  842. nonBodyHeight += pagerContainer.outerHeight(true);
  843. }
  844. this._body.outerHeight(height - (nonBodyHeight === 0 ? 90 : nonBodyHeight));
  845. }
  846. },
  847. showPrevPages: function () {
  848. var firstDisplayingPage = this._firstDisplayingPage,
  849. pageButtonCount = this.pageButtonCount;
  850. this._firstDisplayingPage = (firstDisplayingPage > pageButtonCount) ? firstDisplayingPage - pageButtonCount : 1;
  851. this._refreshPager();
  852. },
  853. showNextPages: function () {
  854. var firstDisplayingPage = this._firstDisplayingPage,
  855. pageButtonCount = this.pageButtonCount,
  856. pageCount = this._pagesCount();
  857. this._firstDisplayingPage = (firstDisplayingPage + 2 * pageButtonCount > pageCount)
  858. ? pageCount - pageButtonCount + 1
  859. : firstDisplayingPage + pageButtonCount;
  860. this._refreshPager();
  861. },
  862. openPage: function (pageIndex) {
  863. //if (pageIndex < 1 || pageIndex > this._pagesCount())
  864. // return;
  865. this._setPage(pageIndex);
  866. this._loadStrategy.openPage(pageIndex);
  867. },
  868. _setPage: function (pageIndex) {
  869. var firstDisplayingPage = this._firstDisplayingPage,
  870. pageButtonCount = this.pageButtonCount;
  871. this.pageIndex = pageIndex;
  872. if (pageIndex < firstDisplayingPage) {
  873. this._firstDisplayingPage = pageIndex;
  874. }
  875. if (pageIndex > firstDisplayingPage + pageButtonCount - 1) {
  876. this._firstDisplayingPage = pageIndex - pageButtonCount + 1;
  877. }
  878. this._callEventHandler(this.onPageChanged, {
  879. pageIndex: pageIndex
  880. });
  881. },
  882. _controllerCall: function (method, param, isCanceled, doneCallback) {
  883. if (isCanceled)
  884. return $.Deferred().reject().promise();
  885. this._showLoading();
  886. var controller = this._controller;
  887. if (!controller || !controller[method]) {
  888. throw Error("controller has no method '" + method + "'");
  889. }
  890. return normalizePromise(controller[method](param))
  891. .done($.proxy(doneCallback, this))
  892. .fail($.proxy(this._errorHandler, this))
  893. .always($.proxy(this._hideLoading, this));
  894. },
  895. _errorHandler: function () {
  896. this._callEventHandler(this.onError, {
  897. args: $.makeArray(arguments)
  898. });
  899. },
  900. _showLoading: function () {
  901. if (!this.loadIndication)
  902. return;
  903. clearTimeout(this._loadingTimer);
  904. this._loadingTimer = setTimeout($.proxy(function () {
  905. this._loadIndicator.show();
  906. }, this), this.loadIndicationDelay);
  907. },
  908. _hideLoading: function () {
  909. if (!this.loadIndication)
  910. return;
  911. clearTimeout(this._loadingTimer);
  912. this._loadIndicator.hide();
  913. },
  914. search: function (filter) {
  915. this._resetSorting();
  916. this._resetPager();
  917. return this.loadData(filter);
  918. },
  919. loadData: function (filter) {
  920. //debugger;
  921. filter = filter || (this.filtering ? this.getFilter() : {});
  922. $.extend(filter, this._loadStrategy.loadParams(), this._sortingParams());
  923. var args = this._callEventHandler(this.onDataLoading, {
  924. filter: filter
  925. });
  926. return this._controllerCall("loadData", filter, args.cancel, function (res) {
  927. if (!res) {
  928. return;
  929. }
  930. var _data = {},
  931. loadedData = {};
  932. if (res.itemsCount >= 0) {
  933. loadedData = res;
  934. }
  935. else {
  936. if (res[0]) { res = res[0]; }
  937. if ((res.RESULT !== undefined && !res.RESULT) || (res.d !== undefined && !res.d)) {
  938. return;
  939. }
  940. if (res.RESULT !== undefined) {
  941. _data = res.DATA.rel;
  942. if ($.isArray(_data)) {
  943. _data = {
  944. DataList: _data,
  945. Total: _data.length
  946. };
  947. }
  948. }
  949. else {
  950. _data = JSON.parse(res.d);
  951. }
  952. loadedData = {
  953. data: _data.DataList,
  954. itemsCount: _data.Total
  955. };
  956. }
  957. this._loadStrategy.finishLoad(loadedData);
  958. this._callEventHandler(this.onDataLoaded, {
  959. data: loadedData
  960. });
  961. });
  962. },
  963. getFilter: function () {
  964. var result = {};
  965. this._eachField(function (field) {
  966. if (field.filtering) {
  967. this._setItemFieldValue(result, field, field.filterValue());
  968. }
  969. });
  970. return result;
  971. },
  972. _sortingParams: function () {
  973. if (this.sorting && this._sortField) {
  974. return {
  975. sortField: this._sortField.name,
  976. sortOrder: this._sortOrder
  977. };
  978. }
  979. return {};
  980. },
  981. getSorting: function () {
  982. var sortingParams = this._sortingParams();
  983. return {
  984. field: sortingParams.sortField,
  985. order: sortingParams.sortOrder
  986. };
  987. },
  988. clearFilter: function () {
  989. var $filterRow = this._createFilterRow();
  990. this._filterRow.replaceWith($filterRow);
  991. this._filterRow = $filterRow;
  992. return this.search();
  993. },
  994. insertItem: function (item) {
  995. //debugger;
  996. var insertingItem = item || this._getValidatedInsertItem();
  997. if (!insertingItem)
  998. return $.Deferred().reject().promise();
  999. var args = this._callEventHandler(this.onItemInserting, {
  1000. item: insertingItem
  1001. });
  1002. return this._controllerCall("insertItem", insertingItem, args.cancel, function (insertedItem) {
  1003. //debugger;
  1004. insertedItem = insertedItem || insertingItem;
  1005. this._loadStrategy.finishInsert(insertedItem);
  1006. this._callEventHandler(this.onItemInserted, {
  1007. item: insertedItem
  1008. });
  1009. });
  1010. },
  1011. _getValidatedInsertItem: function () {
  1012. var item = this._getInsertItem();
  1013. return this._validateItem(item, this._insertRow) ? item : null;
  1014. },
  1015. _getInsertItem: function () {
  1016. var result = {};
  1017. this._eachField(function (field) {
  1018. if (field.inserting) {
  1019. this._setItemFieldValue(result, field, field.insertValue());
  1020. }
  1021. });
  1022. return result;
  1023. },
  1024. _validateItem: function (item, $row) {
  1025. var validationErrors = [];
  1026. var args = {
  1027. item: item,
  1028. itemIndex: this._rowIndex($row),
  1029. row: $row
  1030. };
  1031. this._eachField(function (field) {
  1032. if (!field.validate ||
  1033. ($row === this._insertRow && !field.inserting) ||
  1034. ($row === this._getEditRow() && !field.editing))
  1035. return;
  1036. var fieldValue = this._getItemFieldValue(item, field);
  1037. var errors = this._validation.validate($.extend({
  1038. value: fieldValue,
  1039. rules: field.validate
  1040. }, args));
  1041. this._setCellValidity($row.children().eq(this._visibleFieldIndex(field)), errors);
  1042. if (!errors.length)
  1043. return;
  1044. validationErrors.push.apply(validationErrors,
  1045. $.map(errors, function (message) {
  1046. return { field: field, message: message };
  1047. }));
  1048. });
  1049. if (!validationErrors.length)
  1050. return true;
  1051. var invalidArgs = $.extend({
  1052. errors: validationErrors
  1053. }, args);
  1054. this._callEventHandler(this.onItemInvalid, invalidArgs);
  1055. this.invalidNotify(invalidArgs);
  1056. return false;
  1057. },
  1058. _setCellValidity: function ($cell, errors) {
  1059. $cell
  1060. .toggleClass(this.invalidClass, !!errors.length)
  1061. .attr("title", errors.join("\n"));
  1062. },
  1063. clearInsert: function () {
  1064. var insertRow = this._createInsertRow();
  1065. this._insertRow.replaceWith(insertRow);
  1066. this._insertRow = insertRow;
  1067. this.refresh();
  1068. },
  1069. editItem: function (item) {
  1070. var $row = this.rowByItem(item);
  1071. if ($row.length) {
  1072. this._editRow($row);
  1073. }
  1074. },
  1075. rowByItem: function (item) {
  1076. if (item.jquery || item.nodeType)
  1077. return $(item);
  1078. return this._content.find("tr").filter(function () {
  1079. return $.data(this, JSGRID_ROW_DATA_KEY) === item;
  1080. });
  1081. },
  1082. _editRow: function ($row) {
  1083. if (!this.editing)
  1084. return;
  1085. var item = $row.data(JSGRID_ROW_DATA_KEY);
  1086. var args = this._callEventHandler(this.onItemEditing, {
  1087. row: $row,
  1088. item: item,
  1089. itemIndex: this._itemIndex(item)
  1090. });
  1091. if (args.cancel)
  1092. return;
  1093. if (this._editingRow) {
  1094. this.cancelEdit();
  1095. }
  1096. var $editRow = this._createEditRow(item);
  1097. this._editingRow = $row;
  1098. $row.hide();
  1099. $editRow.insertBefore($row);
  1100. $row.data(JSGRID_EDIT_ROW_DATA_KEY, $editRow);
  1101. },
  1102. _createEditRow: function (item) {
  1103. if ($.isFunction(this.editRowRenderer)) {
  1104. return $(this.renderTemplate(this.editRowRenderer, this, { item: item, itemIndex: this._itemIndex(item) }));
  1105. }
  1106. var $result = $("<tr>").addClass(this.editRowClass);
  1107. this._eachField(function (field) {
  1108. var fieldValue = this._getItemFieldValue(item, field);
  1109. this._prepareCell("<td>", field, "editcss")
  1110. .append(this.renderTemplate(field.editTemplate || "", field, { value: fieldValue, item: item }))
  1111. .appendTo($result);
  1112. });
  1113. return $result;
  1114. },
  1115. updateItem: function (item, editedItem) {
  1116. //debugger;
  1117. if (arguments.length === 1) {
  1118. editedItem = item;
  1119. }
  1120. var $row = item ? this.rowByItem(item) : this._editingRow;
  1121. editedItem = editedItem || this._getValidatedEditedItem();
  1122. if (!editedItem)
  1123. return;
  1124. return this._updateRow($row, editedItem);
  1125. },
  1126. _getValidatedEditedItem: function () {
  1127. var item = this._getEditedItem();
  1128. return this._validateItem(item, this._getEditRow()) ? item : null;
  1129. },
  1130. _updateRow: function ($updatingRow, editedItem) {
  1131. //debugger;
  1132. var updatingItem = $updatingRow.data(JSGRID_ROW_DATA_KEY),
  1133. updatingItemIndex = this._itemIndex(updatingItem),
  1134. updatedItem = $.extend(true, {}, updatingItem, editedItem);
  1135. var args = this._callEventHandler(this.onItemUpdating, {
  1136. row: $updatingRow,
  1137. item: updatedItem,
  1138. itemIndex: updatingItemIndex,
  1139. previousItem: updatingItem
  1140. });
  1141. return this._controllerCall("updateItem", updatedItem, args.cancel, function (res) {
  1142. var loadedUpdatedItem = !res || typeof res.DATA.rel !== 'object' ? undefined : res.DATA.rel,
  1143. previousItem = $.extend(true, {}, updatingItem);
  1144. updatedItem = loadedUpdatedItem || $.extend(true, updatingItem, editedItem);
  1145. var $updatedRow = this._finishUpdate($updatingRow, updatedItem, updatingItemIndex);
  1146. this._callEventHandler(this.onItemUpdated, {
  1147. row: $updatedRow,
  1148. item: updatedItem,
  1149. itemIndex: updatingItemIndex,
  1150. previousItem: previousItem
  1151. });
  1152. });
  1153. },
  1154. _rowIndex: function (row) {
  1155. return this._content.children().index($(row));
  1156. },
  1157. _itemIndex: function (item) {
  1158. return $.inArray(item, this.data);
  1159. },
  1160. _finishUpdate: function ($updatingRow, updatedItem, updatedItemIndex) {
  1161. this.cancelEdit();
  1162. this.data[updatedItemIndex] = updatedItem;
  1163. var $updatedRow = this._createRow(updatedItem, updatedItemIndex);
  1164. $updatingRow.replaceWith($updatedRow);
  1165. return $updatedRow;
  1166. },
  1167. _getEditedItem: function () {
  1168. var result = {};
  1169. this._eachField(function (field) {
  1170. if (field.editing) {
  1171. this._setItemFieldValue(result, field, field.editValue());
  1172. }
  1173. });
  1174. return result;
  1175. },
  1176. cancelEdit: function () {
  1177. if (!this._editingRow)
  1178. return;
  1179. this._getEditRow().remove();
  1180. this._editingRow.show();
  1181. this._editingRow = null;
  1182. },
  1183. _getEditRow: function () {
  1184. return this._editingRow && this._editingRow.data(JSGRID_EDIT_ROW_DATA_KEY);
  1185. },
  1186. deleteItem: function (item) {
  1187. //debugger;
  1188. var $row = this.rowByItem(item),
  1189. _this = this;
  1190. if (!$row.length)
  1191. return;
  1192. if (this.confirmDeleting) {
  1193. layer.confirm(getOrApply(this.deleteConfirm, this, $row.data(JSGRID_ROW_DATA_KEY)), { icon: 3, title: i18next.t('common.Tips') }, function (index) {
  1194. layer.close(index);
  1195. //debugger;
  1196. return _this._deleteRow($row);
  1197. });
  1198. }
  1199. //return this._deleteRow($row);
  1200. },
  1201. _deleteRow: function ($row) {
  1202. var deletingItem = $row.data(JSGRID_ROW_DATA_KEY),
  1203. deletingItemIndex = this._itemIndex(deletingItem);
  1204. var args = this._callEventHandler(this.onItemDeleting, {
  1205. row: $row,
  1206. item: deletingItem,
  1207. itemIndex: deletingItemIndex
  1208. });
  1209. return this._controllerCall("deleteItem", deletingItem, args.cancel, function () {
  1210. this._loadStrategy.finishDelete(deletingItem, deletingItemIndex);
  1211. this._callEventHandler(this.onItemDeleted, {
  1212. row: $row,
  1213. item: deletingItem,
  1214. itemIndex: deletingItemIndex
  1215. });
  1216. });
  1217. }
  1218. };
  1219. $.fn.jsGrid = function (config) {
  1220. var args = $.makeArray(arguments),
  1221. methodArgs = args.slice(1),
  1222. result = this;
  1223. this.each(function () {
  1224. var $element = $(this),
  1225. instance = $element.data(JSGRID_DATA_KEY),
  1226. methodResult;
  1227. if (instance) {
  1228. if (typeof config === "string") {
  1229. methodResult = instance[config].apply(instance, methodArgs);
  1230. if (methodResult !== undefined && methodResult !== instance) {
  1231. result = methodResult;
  1232. return false;
  1233. }
  1234. } else {
  1235. instance._detachWindowResizeCallback();
  1236. instance._init(config);
  1237. instance.render();
  1238. }
  1239. } else {
  1240. new Grid($element, config);
  1241. }
  1242. });
  1243. return result;
  1244. };
  1245. var fields = {};
  1246. var setDefaults = function (config) {
  1247. var componentPrototype;
  1248. if ($.isPlainObject(config)) {
  1249. componentPrototype = Grid.prototype;
  1250. } else {
  1251. componentPrototype = fields[config].prototype;
  1252. config = arguments[1] || {};
  1253. }
  1254. $.extend(componentPrototype, config);
  1255. };
  1256. var locales = {};
  1257. var locale = function (lang) {
  1258. var localeConfig = $.isPlainObject(lang) ? lang : locales[lang];
  1259. if (!localeConfig)
  1260. throw Error("unknown locale " + lang);
  1261. setLocale(jsGrid, localeConfig);
  1262. };
  1263. var setLocale = function (obj, localeConfig) {
  1264. $.each(localeConfig, function (field, value) {
  1265. if ($.isPlainObject(value)) {
  1266. setLocale(obj[field] || obj[field[0].toUpperCase() + field.slice(1)], value);
  1267. return;
  1268. }
  1269. if (obj.hasOwnProperty(field)) {
  1270. obj[field] = value;
  1271. } else {
  1272. obj.prototype[field] = value;
  1273. }
  1274. });
  1275. };
  1276. window.jsGrid = {
  1277. Grid: Grid,
  1278. fields: fields,
  1279. setDefaults: setDefaults,
  1280. locales: locales,
  1281. locale: locale,
  1282. version: '1.5.3'
  1283. };
  1284. }(window, jQuery));
  1285. (function (jsGrid, $, undefined) {
  1286. function LoadIndicator(config) {
  1287. this._init(config);
  1288. }
  1289. LoadIndicator.prototype = {
  1290. container: "body",
  1291. message: "Loading...",
  1292. shading: true,
  1293. zIndex: 1000,
  1294. shaderClass: "jsgrid-load-shader",
  1295. loadPanelClass: "jsgrid-load-panel",
  1296. _init: function (config) {
  1297. $.extend(true, this, config);
  1298. this._initContainer();
  1299. this._initShader();
  1300. this._initLoadPanel();
  1301. },
  1302. _initContainer: function () {
  1303. this._container = $(this.container);
  1304. },
  1305. _initShader: function () {
  1306. if (!this.shading)
  1307. return;
  1308. this._shader = $("<div>").addClass(this.shaderClass)
  1309. .hide()
  1310. .css({
  1311. position: "absolute",
  1312. top: 0,
  1313. right: 0,
  1314. bottom: 0,
  1315. left: 0,
  1316. zIndex: this.zIndex
  1317. })
  1318. .appendTo(this._container);
  1319. },
  1320. _initLoadPanel: function () {
  1321. this._loadPanel = $("<div>").addClass(this.loadPanelClass)
  1322. .text(this.message)
  1323. .hide()
  1324. .css({
  1325. position: "absolute",
  1326. top: "50%",
  1327. left: "50%",
  1328. zIndex: this.zIndex
  1329. })
  1330. .appendTo(this._container);
  1331. },
  1332. show: function () {
  1333. var $loadPanel = this._loadPanel.show();
  1334. var actualWidth = $loadPanel.outerWidth();
  1335. var actualHeight = $loadPanel.outerHeight();
  1336. $loadPanel.css({
  1337. marginTop: -actualHeight / 2,
  1338. marginLeft: -actualWidth / 2
  1339. });
  1340. this._shader.show();
  1341. },
  1342. hide: function () {
  1343. this._loadPanel.hide();
  1344. this._shader.hide();
  1345. }
  1346. };
  1347. jsGrid.LoadIndicator = LoadIndicator;
  1348. }(jsGrid, jQuery));
  1349. (function (jsGrid, $, undefined) {
  1350. function DirectLoadingStrategy(grid) {
  1351. this._grid = grid;
  1352. }
  1353. DirectLoadingStrategy.prototype = {
  1354. firstDisplayIndex: function () {
  1355. var grid = this._grid;
  1356. return grid.option("paging") ? (grid.option("pageIndex") - 1) * grid.option("pageSize") : 0;
  1357. },
  1358. lastDisplayIndex: function () {
  1359. var grid = this._grid;
  1360. //var itemsCount = grid.option("data").length;
  1361. var itemsCount = grid.option("total").length;//John modified
  1362. return grid.option("paging")
  1363. ? Math.min(grid.option("pageIndex") * grid.option("pageSize"), itemsCount)
  1364. : itemsCount;
  1365. },
  1366. itemsCount: function () {
  1367. //return this._grid.option("data").length;
  1368. //debugger;
  1369. return this._grid.option("total").length;//John modified
  1370. },
  1371. openPage: function (index) {
  1372. this._grid.refresh();
  1373. },
  1374. loadParams: function () {
  1375. return {};
  1376. },
  1377. sort: function () {
  1378. this._grid._sortData();
  1379. this._grid.refresh();
  1380. return $.Deferred().resolve().promise();
  1381. },
  1382. reset: function () {
  1383. this._grid.refresh();
  1384. return $.Deferred().resolve().promise();
  1385. },
  1386. finishLoad: function (loadedData) {
  1387. this._grid.option("data", loadedData);
  1388. },
  1389. finishInsert: function (insertedItem) {
  1390. var grid = this._grid;
  1391. grid.option("data").push(insertedItem);
  1392. grid.refresh();
  1393. },
  1394. finishDelete: function (deletedItem, deletedItemIndex) {
  1395. var grid = this._grid;
  1396. grid.option("data").splice(deletedItemIndex, 1);
  1397. grid.reset();
  1398. }
  1399. };
  1400. function PageLoadingStrategy(grid) {
  1401. this._grid = grid;
  1402. this._itemsCount = 0;
  1403. }
  1404. PageLoadingStrategy.prototype = {
  1405. firstDisplayIndex: function () {
  1406. return 0;
  1407. },
  1408. lastDisplayIndex: function () {
  1409. return this._grid.option("data").length;
  1410. },
  1411. itemsCount: function () {
  1412. return this._itemsCount;
  1413. },
  1414. openPage: function (index) {
  1415. this._grid.loadData();
  1416. },
  1417. loadParams: function () {
  1418. var grid = this._grid;
  1419. return {
  1420. pageIndex: grid.option("pageIndex"),
  1421. pageSize: grid.option("pageSize")
  1422. };
  1423. },
  1424. reset: function () {
  1425. return this._grid.loadData();
  1426. },
  1427. sort: function () {
  1428. return this._grid.loadData();
  1429. },
  1430. finishLoad: function (loadedData) {
  1431. this._itemsCount = loadedData.itemsCount;
  1432. this._grid.option("data", loadedData.data);
  1433. },
  1434. finishInsert: function (insertedItem) {
  1435. this._grid.search();
  1436. },
  1437. finishDelete: function (deletedItem, deletedItemIndex) {
  1438. this._grid.search();
  1439. }
  1440. };
  1441. jsGrid.loadStrategies = {
  1442. DirectLoadingStrategy: DirectLoadingStrategy,
  1443. PageLoadingStrategy: PageLoadingStrategy
  1444. };
  1445. }(jsGrid, jQuery));
  1446. (function (jsGrid, $, undefined) {
  1447. var isDefined = function (val) {
  1448. return typeof (val) !== "undefined" && val !== null;
  1449. };
  1450. var sortStrategies = {
  1451. string: function (str1, str2) {
  1452. if (!isDefined(str1) && !isDefined(str2))
  1453. return 0;
  1454. if (!isDefined(str1))
  1455. return -1;
  1456. if (!isDefined(str2))
  1457. return 1;
  1458. return ("" + str1).localeCompare("" + str2);
  1459. },
  1460. number: function (n1, n2) {
  1461. return n1 - n2;
  1462. },
  1463. date: function (dt1, dt2) {
  1464. return dt1 - dt2;
  1465. },
  1466. numberAsString: function (n1, n2) {
  1467. return parseFloat(n1) - parseFloat(n2);
  1468. }
  1469. };
  1470. jsGrid.sortStrategies = sortStrategies;
  1471. }(jsGrid, jQuery));
  1472. (function (jsGrid, $, undefined) {
  1473. function Validation(config) {
  1474. this._init(config);
  1475. }
  1476. Validation.prototype = {
  1477. _init: function (config) {
  1478. $.extend(true, this, config);
  1479. },
  1480. validate: function (args) {
  1481. var errors = [];
  1482. $.each(this._normalizeRules(args.rules), function (_, rule) {
  1483. if (rule.validator(args.value, args.item, rule.param))
  1484. return;
  1485. var errorMessage = $.isFunction(rule.message) ? rule.message(args.value, args.item) : rule.message;
  1486. errors.push(errorMessage);
  1487. });
  1488. return errors;
  1489. },
  1490. _normalizeRules: function (rules) {
  1491. if (!$.isArray(rules))
  1492. rules = [rules];
  1493. return $.map(rules, $.proxy(function (rule) {
  1494. return this._normalizeRule(rule);
  1495. }, this));
  1496. },
  1497. _normalizeRule: function (rule) {
  1498. if (typeof rule === "string")
  1499. rule = { validator: rule };
  1500. if ($.isFunction(rule))
  1501. rule = { validator: rule };
  1502. if ($.isPlainObject(rule))
  1503. rule = $.extend({}, rule);
  1504. else
  1505. throw Error("wrong validation config specified");
  1506. if ($.isFunction(rule.validator))
  1507. return rule;
  1508. return this._applyNamedValidator(rule, rule.validator);
  1509. },
  1510. _applyNamedValidator: function (rule, validatorName) {
  1511. delete rule.validator;
  1512. var validator = validators[validatorName];
  1513. if (!validator)
  1514. throw Error("unknown validator \"" + validatorName + "\"");
  1515. if ($.isFunction(validator)) {
  1516. validator = { validator: validator };
  1517. }
  1518. return $.extend({}, validator, rule);
  1519. }
  1520. };
  1521. jsGrid.Validation = Validation;
  1522. var validators = {
  1523. required: {
  1524. message: "Field is required",
  1525. validator: function (value) {
  1526. return value !== undefined && value !== null && value !== "";
  1527. }
  1528. },
  1529. rangeLength: {
  1530. message: "Field value length is out of the defined range",
  1531. validator: function (value, _, param) {
  1532. return value.length >= param[0] && value.length <= param[1];
  1533. }
  1534. },
  1535. minLength: {
  1536. message: "Field value is too short",
  1537. validator: function (value, _, param) {
  1538. return value.length >= param;
  1539. }
  1540. },
  1541. maxLength: {
  1542. message: "Field value is too long",
  1543. validator: function (value, _, param) {
  1544. return value.length <= param;
  1545. }
  1546. },
  1547. pattern: {
  1548. message: "Field value is not matching the defined pattern",
  1549. validator: function (value, _, param) {
  1550. if (typeof param === "string") {
  1551. param = new RegExp("^(?:" + param + ")$");
  1552. }
  1553. return param.test(value);
  1554. }
  1555. },
  1556. range: {
  1557. message: "Field value is out of the defined range",
  1558. validator: function (value, _, param) {
  1559. return value >= param[0] && value <= param[1];
  1560. }
  1561. },
  1562. min: {
  1563. message: "Field value is too small",
  1564. validator: function (value, _, param) {
  1565. return value >= param;
  1566. }
  1567. },
  1568. max: {
  1569. message: "Field value is too large",
  1570. validator: function (value, _, param) {
  1571. return value <= param;
  1572. }
  1573. }
  1574. };
  1575. jsGrid.validators = validators;
  1576. }(jsGrid, jQuery));
  1577. (function (jsGrid, $, undefined) {
  1578. function Field(config) {
  1579. $.extend(true, this, config);
  1580. this.sortingFunc = this._getSortingFunc();
  1581. }
  1582. Field.prototype = {
  1583. name: "",
  1584. title: null,
  1585. css: "",
  1586. align: "",
  1587. width: 100,
  1588. visible: true,
  1589. filtering: true,
  1590. inserting: true,
  1591. editing: true,
  1592. sorting: true,
  1593. sorter: "string", // name of SortStrategy or function to compare elements
  1594. headerTemplate: function () {
  1595. return (this.title === undefined || this.title === null) ? this.name : this.title;
  1596. },
  1597. itemTemplate: function (value, item) {
  1598. return value;
  1599. },
  1600. filterTemplate: function () {
  1601. return "";
  1602. },
  1603. insertTemplate: function () {
  1604. return "";
  1605. },
  1606. editTemplate: function (value, item) {
  1607. this._value = value;
  1608. return this.itemTemplate(value, item);
  1609. },
  1610. filterValue: function () {
  1611. return "";
  1612. },
  1613. insertValue: function () {
  1614. return "";
  1615. },
  1616. editValue: function () {
  1617. return this._value;
  1618. },
  1619. _getSortingFunc: function () {
  1620. var sorter = this.sorter;
  1621. if ($.isFunction(sorter)) {
  1622. return sorter;
  1623. }
  1624. if (typeof sorter === "string") {
  1625. return jsGrid.sortStrategies[sorter];
  1626. }
  1627. throw Error("wrong sorter for the field \"" + this.name + "\"!");
  1628. }
  1629. };
  1630. jsGrid.Field = Field;
  1631. }(jsGrid, jQuery));
  1632. (function (jsGrid, $, undefined) {
  1633. var Field = jsGrid.Field;
  1634. function TextField(config) {
  1635. Field.call(this, config);
  1636. }
  1637. TextField.prototype = new Field({
  1638. autosearch: true,
  1639. readOnly: false,
  1640. filterTemplate: function () {
  1641. if (!this.filtering)
  1642. return "";
  1643. var grid = this._grid,
  1644. $result = this.filterControl = this._createTextBox();
  1645. if (this.autosearch) {
  1646. $result.on("keypress", function (e) {
  1647. if (e.which === 13) {
  1648. grid.search();
  1649. e.preventDefault();
  1650. }
  1651. });
  1652. }
  1653. return $result;
  1654. },
  1655. insertTemplate: function () {
  1656. if (!this.inserting)
  1657. return "";
  1658. return this.insertControl = this._createTextBox();
  1659. },
  1660. editTemplate: function (value) {
  1661. if (!this.editing)
  1662. return this.itemTemplate.apply(this, arguments);
  1663. var $result = this.editControl = this._createTextBox();
  1664. $result.val(value);
  1665. return $result;
  1666. },
  1667. filterValue: function () {
  1668. return this.filterControl.val();
  1669. },
  1670. insertValue: function () {
  1671. return this.insertControl.val();
  1672. },
  1673. editValue: function () {
  1674. return this.editControl.val();
  1675. },
  1676. _createTextBox: function () {
  1677. return $("<input>").attr("type", "text").attr("class", "form-control w100p")
  1678. .prop("readonly", !!this.readOnly);
  1679. }
  1680. });
  1681. jsGrid.fields.text = jsGrid.TextField = TextField;
  1682. }(jsGrid, jQuery));
  1683. (function (jsGrid, $, undefined) {
  1684. var TextField = jsGrid.TextField;
  1685. function NumberField(config) {
  1686. TextField.call(this, config);
  1687. }
  1688. NumberField.prototype = new TextField({
  1689. sorter: "number",
  1690. align: "right",
  1691. readOnly: false,
  1692. filterValue: function () {
  1693. return this.filterControl.val()
  1694. ? parseInt(this.filterControl.val() || 0, 10)
  1695. : undefined;
  1696. },
  1697. insertValue: function () {
  1698. return this.insertControl.val()
  1699. ? parseInt(this.insertControl.val() || 0, 10)
  1700. : undefined;
  1701. },
  1702. editValue: function () {
  1703. return this.editControl.val()
  1704. ? parseInt(this.editControl.val() || 0, 10)
  1705. : undefined;
  1706. },
  1707. _createTextBox: function () {
  1708. return $("<input>").attr("type", "number").attr("class", "form-control w100p")
  1709. .prop("readonly", !!this.readOnly);
  1710. }
  1711. });
  1712. jsGrid.fields.number = jsGrid.NumberField = NumberField;
  1713. }(jsGrid, jQuery));
  1714. (function (jsGrid, $, undefined) {
  1715. var TextField = jsGrid.TextField;
  1716. function TextAreaField(config) {
  1717. TextField.call(this, config);
  1718. }
  1719. TextAreaField.prototype = new TextField({
  1720. insertTemplate: function () {
  1721. if (!this.inserting)
  1722. return "";
  1723. return this.insertControl = this._createTextArea();
  1724. },
  1725. editTemplate: function (value) {
  1726. if (!this.editing)
  1727. return this.itemTemplate.apply(this, arguments);
  1728. var $result = this.editControl = this._createTextArea();
  1729. $result.val(value);
  1730. return $result;
  1731. },
  1732. _createTextArea: function () {
  1733. return $("<textarea>").prop("readonly", !!this.readOnly);
  1734. }
  1735. });
  1736. jsGrid.fields.textarea = jsGrid.TextAreaField = TextAreaField;
  1737. }(jsGrid, jQuery));
  1738. (function (jsGrid, $, undefined) {
  1739. var NumberField = jsGrid.NumberField;
  1740. var numberValueType = "number";
  1741. var stringValueType = "string";
  1742. function SelectField(config) {
  1743. this.items = [];
  1744. this.selectedIndex = -1;
  1745. this.valueField = "";
  1746. this.textField = "";
  1747. if (config.valueField && config.items.length) {
  1748. var firstItemValue = config.items[0][config.valueField];
  1749. this.valueType = (typeof firstItemValue) === numberValueType ? numberValueType : stringValueType;
  1750. }
  1751. this.sorter = this.valueType;
  1752. NumberField.call(this, config);
  1753. }
  1754. SelectField.prototype = new NumberField({
  1755. align: "center",
  1756. valueType: numberValueType,
  1757. itemTemplate: function (value) {
  1758. var items = this.items,
  1759. valueField = this.valueField,
  1760. textField = this.textField,
  1761. resultItem;
  1762. if (valueField) {
  1763. resultItem = $.grep(items, function (item, index) {
  1764. return item[valueField] === value;
  1765. })[0] || {};
  1766. }
  1767. else {
  1768. resultItem = items[value];
  1769. }
  1770. var result = (textField ? resultItem[textField] : resultItem);
  1771. return (result === undefined || result === null) ? "" : result;
  1772. },
  1773. filterTemplate: function () {
  1774. if (!this.filtering)
  1775. return "";
  1776. var grid = this._grid,
  1777. $result = this.filterControl = this._createSelect();
  1778. if (this.autosearch) {
  1779. $result.on("change", function (e) {
  1780. grid.search();
  1781. });
  1782. }
  1783. return $result;
  1784. },
  1785. insertTemplate: function () {
  1786. if (!this.inserting)
  1787. return "";
  1788. return this.insertControl = this._createSelect();
  1789. },
  1790. editTemplate: function (value) {
  1791. if (!this.editing)
  1792. return this.itemTemplate.apply(this, arguments);
  1793. var $result = this.editControl = this._createSelect();
  1794. (value !== undefined) && $result.val(value);
  1795. return $result;
  1796. },
  1797. filterValue: function () {
  1798. var val = this.filterControl.val();
  1799. return this.valueType === numberValueType ? parseInt(val || 0, 10) : val;
  1800. },
  1801. insertValue: function () {
  1802. var val = this.insertControl.val();
  1803. return this.valueType === numberValueType ? parseInt(val || 0, 10) : val;
  1804. },
  1805. editValue: function () {
  1806. var val = this.editControl.val();
  1807. return this.valueType === numberValueType ? parseInt(val || 0, 10) : val;
  1808. },
  1809. _createSelect: function () {
  1810. var $result = $("<select>"),
  1811. valueField = this.valueField,
  1812. textField = this.textField,
  1813. selectedIndex = this.selectedIndex;
  1814. $.each(this.items, function (index, item) {
  1815. var value = valueField ? item[valueField] : index,
  1816. text = textField ? item[textField] : item;
  1817. var $option = $("<option>")
  1818. .attr("value", value)
  1819. .text(text)
  1820. .appendTo($result);
  1821. $option.prop("selected", (selectedIndex === index));
  1822. });
  1823. $result.prop("disabled", !!this.readOnly);
  1824. return $result;
  1825. }
  1826. });
  1827. jsGrid.fields.select = jsGrid.SelectField = SelectField;
  1828. }(jsGrid, jQuery));
  1829. (function (jsGrid, $, undefined) {
  1830. var Field = jsGrid.Field;
  1831. function CheckboxField(config) {
  1832. Field.call(this, config);
  1833. }
  1834. CheckboxField.prototype = new Field({
  1835. sorter: "number",
  1836. align: "center",
  1837. autosearch: true,
  1838. itemTemplate: function (value) {
  1839. return this._createCheckbox().prop({
  1840. checked: value,
  1841. disabled: true
  1842. });
  1843. },
  1844. filterTemplate: function () {
  1845. if (!this.filtering)
  1846. return "";
  1847. var grid = this._grid,
  1848. $result = this.filterControl = this._createCheckbox();
  1849. $result.prop({
  1850. readOnly: true,
  1851. indeterminate: true
  1852. });
  1853. $result.on("click", function () {
  1854. var $cb = $(this);
  1855. if ($cb.prop("readOnly")) {
  1856. $cb.prop({
  1857. checked: false,
  1858. readOnly: false
  1859. });
  1860. }
  1861. else if (!$cb.prop("checked")) {
  1862. $cb.prop({
  1863. readOnly: true,
  1864. indeterminate: true
  1865. });
  1866. }
  1867. });
  1868. if (this.autosearch) {
  1869. $result.on("click", function () {
  1870. grid.search();
  1871. });
  1872. }
  1873. return $result;
  1874. },
  1875. insertTemplate: function () {
  1876. if (!this.inserting)
  1877. return "";
  1878. return this.insertControl = this._createCheckbox();
  1879. },
  1880. editTemplate: function (value) {
  1881. if (!this.editing)
  1882. return this.itemTemplate.apply(this, arguments);
  1883. var $result = this.editControl = this._createCheckbox();
  1884. $result.prop("checked", value);
  1885. return $result;
  1886. },
  1887. filterValue: function () {
  1888. return this.filterControl.get(0).indeterminate
  1889. ? undefined
  1890. : this.filterControl.is(":checked");
  1891. },
  1892. insertValue: function () {
  1893. return this.insertControl.is(":checked");
  1894. },
  1895. editValue: function () {
  1896. return this.editControl.is(":checked");
  1897. },
  1898. _createCheckbox: function () {
  1899. return $("<input>").attr("type", "checkbox");
  1900. }
  1901. });
  1902. jsGrid.fields.checkbox = jsGrid.CheckboxField = CheckboxField;
  1903. }(jsGrid, jQuery));
  1904. (function (jsGrid, $, undefined) {
  1905. var Field = jsGrid.Field;
  1906. function ControlField(config) {
  1907. Field.call(this, config);
  1908. this._configInitialized = false;
  1909. }
  1910. ControlField.prototype = new Field({
  1911. css: "jsgrid-control-field",
  1912. align: "center",
  1913. width: 50,
  1914. filtering: false,
  1915. inserting: false,
  1916. editing: false,
  1917. sorting: false,
  1918. buttonClass: "jsgrid-button",
  1919. modeButtonClass: "jsgrid-mode-button",
  1920. modeOnButtonClass: "jsgrid-mode-on-button",
  1921. searchModeButtonClass: "jsgrid-search-mode-button",
  1922. insertModeButtonClass: "jsgrid-insert-mode-button",
  1923. editButtonClass: "jsgrid-edit-button",
  1924. deleteButtonClass: "jsgrid-delete-button",
  1925. searchButtonClass: "jsgrid-search-button",
  1926. clearFilterButtonClass: "jsgrid-clear-filter-button",
  1927. insertButtonClass: "jsgrid-insert-button",
  1928. updateButtonClass: "jsgrid-update-button",
  1929. cancelEditButtonClass: "jsgrid-cancel-edit-button",
  1930. searchModeButtonTooltip: "Switch to searching",
  1931. insertModeButtonTooltip: "Switch to inserting",
  1932. editButtonTooltip: "Edit",
  1933. deleteButtonTooltip: "Delete",
  1934. searchButtonTooltip: "Search",
  1935. clearFilterButtonTooltip: "Clear filter",
  1936. insertButtonTooltip: "Insert",
  1937. updateButtonTooltip: "Update",
  1938. cancelEditButtonTooltip: "Cancel edit",
  1939. editButton: true,
  1940. deleteButton: true,
  1941. clearFilterButton: true,
  1942. modeSwitchButton: true,
  1943. _initConfig: function () {
  1944. this._hasFiltering = this._grid.filtering;
  1945. this._hasInserting = this._grid.inserting;
  1946. if (this._hasInserting && this.modeSwitchButton) {
  1947. this._grid.inserting = false;
  1948. }
  1949. this._configInitialized = true;
  1950. },
  1951. headerTemplate: function () {
  1952. if (!this._configInitialized) {
  1953. this._initConfig();
  1954. }
  1955. var hasFiltering = this._hasFiltering;
  1956. var hasInserting = this._hasInserting;
  1957. if (!this.modeSwitchButton || (!hasFiltering && !hasInserting))
  1958. return "";
  1959. if (hasFiltering && !hasInserting)
  1960. return this._createFilterSwitchButton();
  1961. if (hasInserting && !hasFiltering)
  1962. return this._createInsertSwitchButton();
  1963. return this._createModeSwitchButton();
  1964. },
  1965. itemTemplate: function (value, item) {
  1966. var $result = $([]);
  1967. if (this.editButton) {
  1968. $result = $result.add(this._createEditButton(item));
  1969. }
  1970. if (this.deleteButton) {
  1971. $result = $result.add(this._createDeleteButton(item));
  1972. }
  1973. return $result;
  1974. },
  1975. filterTemplate: function () {
  1976. var $result = this._createSearchButton();
  1977. return this.clearFilterButton ? $result.add(this._createClearFilterButton()) : $result;
  1978. },
  1979. insertTemplate: function () {
  1980. return this._createInsertButton();
  1981. },
  1982. editTemplate: function () {
  1983. return this._createUpdateButton().add(this._createCancelEditButton());
  1984. },
  1985. _createFilterSwitchButton: function () {
  1986. return this._createOnOffSwitchButton("filtering", this.searchModeButtonClass, true);
  1987. },
  1988. _createInsertSwitchButton: function () {
  1989. return this._createOnOffSwitchButton("inserting", this.insertModeButtonClass, false);
  1990. },
  1991. _createOnOffSwitchButton: function (option, cssClass, isOnInitially) {
  1992. var isOn = isOnInitially;
  1993. var updateButtonState = $.proxy(function () {
  1994. $button.toggleClass(this.modeOnButtonClass, isOn);
  1995. }, this);
  1996. var $button = this._createGridButton(this.modeButtonClass + " " + cssClass, "", function (grid) {
  1997. isOn = !isOn;
  1998. grid.option(option, isOn);
  1999. updateButtonState();
  2000. });
  2001. updateButtonState();
  2002. return $button;
  2003. },
  2004. _createModeSwitchButton: function () {
  2005. var isInserting = false;
  2006. var updateButtonState = $.proxy(function () {
  2007. $button.attr("title", isInserting ? this.searchModeButtonTooltip : this.insertModeButtonTooltip)
  2008. .toggleClass(this.insertModeButtonClass, !isInserting)
  2009. .toggleClass(this.searchModeButtonClass, isInserting);
  2010. }, this);
  2011. var $button = this._createGridButton(this.modeButtonClass, "", function (grid) {
  2012. isInserting = !isInserting;
  2013. grid.option("inserting", isInserting);
  2014. grid.option("filtering", !isInserting);
  2015. updateButtonState();
  2016. });
  2017. updateButtonState();
  2018. return $button;
  2019. },
  2020. _createEditButton: function (item) {
  2021. return this._createGridButton(this.editButtonClass, this.editButtonTooltip, function (grid, e) {
  2022. grid.editItem(item);
  2023. e.stopPropagation();
  2024. });
  2025. },
  2026. _createDeleteButton: function (item) {
  2027. return this._createGridButton(this.deleteButtonClass, this.deleteButtonTooltip, function (grid, e) {
  2028. grid.deleteItem(item);
  2029. e.stopPropagation();
  2030. });
  2031. },
  2032. _createSearchButton: function () {
  2033. return this._createGridButton(this.searchButtonClass, this.searchButtonTooltip, function (grid) {
  2034. grid.search();
  2035. });
  2036. },
  2037. _createClearFilterButton: function () {
  2038. return this._createGridButton(this.clearFilterButtonClass, this.clearFilterButtonTooltip, function (grid) {
  2039. grid.clearFilter();
  2040. });
  2041. },
  2042. _createInsertButton: function () {
  2043. return this._createGridButton(this.insertButtonClass, this.insertButtonTooltip, function (grid) {
  2044. grid.insertItem().done(function () {
  2045. grid.clearInsert();
  2046. });
  2047. });
  2048. },
  2049. _createUpdateButton: function () {
  2050. return this._createGridButton(this.updateButtonClass, this.updateButtonTooltip, function (grid, e) {
  2051. grid.updateItem();
  2052. e.stopPropagation();
  2053. });
  2054. },
  2055. _createCancelEditButton: function () {
  2056. return this._createGridButton(this.cancelEditButtonClass, this.cancelEditButtonTooltip, function (grid, e) {
  2057. grid.cancelEdit();
  2058. e.stopPropagation();
  2059. });
  2060. },
  2061. _createGridButton: function (cls, tooltip, clickHandler) {
  2062. var grid = this._grid;
  2063. return $("<input>").addClass(this.buttonClass)
  2064. .addClass(cls)
  2065. .attr({
  2066. type: "button",
  2067. title: tooltip
  2068. })
  2069. .on("click", function (e) {
  2070. clickHandler(grid, e);
  2071. });
  2072. },
  2073. editValue: function () {
  2074. return "";
  2075. }
  2076. });
  2077. jsGrid.fields.control = jsGrid.ControlField = ControlField;
  2078. }(jsGrid, jQuery));