UNPKG

@true-directive/base

Version:

The set of base classes for the TrueDirective Grid

629 lines (628 loc) 25.7 kB
var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; /** * Copyright (c) 2018-2019 Aleksey Melnikov, True Directive Company. * @link https://truedirective.com/ * @license MIT */ import { SelectionMode, LazyLoadingMode, EditorShowMode } from './classes/enums'; import { FilterShowEvent } from './classes/events'; import { DataSource } from './classes/data-source.class'; import { PageInfo } from './classes/page-info.class'; import { ColumnCollection } from './classes/column-collection.class'; import { DataQuery } from './classes/data-query.class'; import { CellPosition } from './classes/cell-position.class'; import { Selection } from './classes/selection.class'; import { GridLayout } from './classes/grid-layout.class'; import { GridExporter } from './classes/grid-exporter.class'; import { Utils } from './common/utils.class'; import { AxInject } from './classes/ax-inject.class'; import { AxInjectConsumer } from './classes/ax-inject-consumer.class'; import { GridSettings } from './classes/grid-settings.class'; import { GridUIHandler } from './handlers/grid-ui.handler'; import { GridCheckHandler } from './handlers/grid-check.handler'; import { GridDragHandler } from './handlers/grid-drag.handler'; import { GridLazyLoadHandler } from './handlers/grid-lazy-load.handler'; import { LayoutsHandler } from './handlers/layouts.handler'; /** * Grid's state. Contains: * - grid's settings * - provided column's list * - column's lists for every part of the grid (only main area in the current version) * - sorting info * - drag-n-drop state * - current page info * Receives changes of the state and provides it for all parts. */ var GridState = /** @class */ (function (_super) { __extends(GridState, _super); function GridState() { var _this = _super.call(this) || this; // -- etc -- _this.IE = Utils.detectIE(); _this.iOS = Utils.detectIOS(); _this.android = Utils.detectAndroid(); _this.safari = Utils.detectSafari(); _this.pageInfo = new PageInfo(0, 1); /** * The width of viewport's visible area. * This property is used for column's width calculation * with setting columnAutoWidth=true. */ _this._clientWidth = 0; _this._clientHeight = 0; /** * Index of the first row is displayed according to current scroll position. */ _this._displayedStartIndex = 0; /** * Data query counter */ _this._dataQueryCounter = 0; _this.registerHandlers(); _this.updateInjections(); return _this; } Object.defineProperty(GridState.prototype, "settings", { get: function () { return this._settings; }, set: function (s) { this._settings = s; this.updateInjections(); }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "st", { get: function () { return this._settings; } // Short alias , enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "ds", { get: function () { return this.dataSource; }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "sta", { get: function () { return this.settings.appearance; } // Short alias , enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "model", { get: function () { return this.dataSource.model; }, /** * Данные грида */ set: function (rows) { this.dataSource.model = rows; }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "columns", { get: function () { return this.columnCollection.columns; }, set: function (v) { this.columnCollection.columns = v; this.layoutsHandler.setLayoutsVisibility(); this.updateLayouts(); }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "layout", { get: function () { return this.layoutsHandler.layout; }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "layoutDrag", { get: function () { return this.layoutsHandler.layoutDrag; }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "showFixedLeft", { // Это всё мы передадим в обработчики get: function () { return false; }, set: function (v) { }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "showFixedRight", { get: function () { return false; }, set: function (v) { }, enumerable: true, configurable: true }); /** * Gets column by field name * @param f Field name * @return Column if exists */ GridState.prototype.columnByFieldName = function (f) { return this.columnCollection.columnByFieldName(f); }; Object.defineProperty(GridState.prototype, "isTree", { /** * Отображать ли данные в виде дерева */ get: function () { // Текущая версия не поддерживает отображение дерева return false; }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "maxLevel", { /** * Уровень вложенности - ноль */ get: function () { return 0; }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "clientWidth", { get: function () { return this._clientWidth; }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "clientHeight", { get: function () { return this._clientHeight; }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "layouts", { /** * The list of grid parts */ get: function () { return this.layoutsHandler.layouts; }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "touchMode", { /** * The device supporting touch events is used. */ get: function () { return this.iOS || this.android; }, enumerable: true, configurable: true }); Object.defineProperty(GridState.prototype, "displayedStartIndex", { get: function () { return this._displayedStartIndex; }, set: function (index) { this._displayedStartIndex = index; this.layouts.forEach(function (l) { return l.selection.updateDisplayedStartIndex(index); }); }, enumerable: true, configurable: true }); // --------------------------------------------------------------------------- GridState.prototype.checkClientWidth = function (v) { if (this._clientWidth !== v) { this._clientWidth = v; this.updateLayouts(); return true; } return false; }; GridState.prototype.checkClientHeight = function (v) { var res = false; if (this._clientHeight !== v) { res = true; } this._clientHeight = v; return res; }; /** * Recalculation of rows in accordance with the specified filters, * sorting and other. */ GridState.prototype.recalcData = function () { var _this = this; return new Promise(function (resolve) { _this.ds.recalcData(); resolve(); }); }; GridState.prototype.getQuery = function (subject) { if (subject === void 0) { subject = null; } return this.ds.getQuery(++this._dataQueryCounter, subject); }; /** * Request data from an observer. * @param counter Query counter value * @param subject Observer */ GridState.prototype.doQuery = function (subject, force) { if (subject === void 0) { subject = null; } if (force === void 0) { force = false; } if (this.lazyLoader.query(0, false, force)) { // Если запрос сделает ленивый загрузчик, то выходим return; } this.events.dataQueryEvent(this.getQuery()); }; /** * Initiation of data update with all recalculations. * @param async Recalculation in the asynchronous thread. */ GridState.prototype.updateData = function (async) { var _this = this; if (async === void 0) { async = true; } if (this.st.lazyLoading === LazyLoadingMode.FRAGMENTARY) { if (this.ds.totalRowCount > 0) { // Force current page update this.lazyLoader.query(this.pageInfo.offset, false, true); return; } } if (this.settings.requestData || this.settings.lazyLoading !== LazyLoadingMode.NONE) { // Необходимо запросить данные this.doQuery(null, true); // НО! Нужно обновить колонки. this.events.columnsChangedEvent(); return; } // Запрашивать не нужно, считаем всё сами if (async) { // Асинхронное обновление this.recalcData().then(function () { _this.fetchData(new DataQuery(_this._dataQueryCounter)); }); } else { // Синхронное this.ds.recalcData(); this.fetchData(new DataQuery(this._dataQueryCounter)); } }; // Принимаем данные извне GridState.prototype.fetchData = function (query, data, totalRowCount) { if (data === void 0) { data = null; } if (totalRowCount === void 0) { totalRowCount = null; } if (this.settings.lazyLoading !== LazyLoadingMode.NONE) { this.lazyLoader.fetch(data, query, totalRowCount); } else { // Если счетчик не совпадает, то позднее был новый запрос. И в этих данных смысла // уже нет if (this._dataQueryCounter !== query.queryId) { return; } if (data !== null) { // Если данные пересчитаны извне.. this.ds.fetchData(data, totalRowCount); } } // Обновить нужно. Потому что уровни дерева могли поменяться this.updateLayouts(); // Обновляем галки колонок this.check.updateCheckColumns(); // Обновляем индексы строк выделенных областей this.layoutsHandler.updateSelectionIndices(); // Отправляем информацию о том, что данные получены this.events.dataFetchEvent(query); }; // Обновляем отображаемые данные в основном компоненте GridState.prototype.queryChanged = function () { // Генерируем событие о необходимости обновления данных // Проверяем ленивую загрузку с флагом сбрасывания данных //if (!this.lazyLoader.query(0, true)) { // Если не ленивая загрузка, то как всегда. // Иначе ленивая загрузка сама отправит данные this.events.queryChangedEvent(this.ds.getQuery()); //} // вроде как здесь не нужна эта тема с ленивой загрузкой, т.к. при // updateData всё происходит }; // Делаем так, чтобы ничего не было выделено GridState.prototype.clearSelection = function () { this.selection.clearAll(); }; // -- LAYOUTS ---------------------------------------------------------------- // Обновление состояния дочерних компонентов GridState.prototype.updateLayouts = function () { var _this = this; if (!this.columns) { throw new Error('GRID: Columns are not defined'); } // Все секции. Хотя пока у нас и одна только.. // Автоматическая ширина колонок только в основной секции this.layouts.forEach(function (l) { return l.update(_this.columns, _this.st.widthUnit, _this.st.levelIndent, _this.clientWidth, l === _this.layout && _this.st.columnAutoWidth); }); // Это для нас обновление сопутствующих дел this.resizeLayouts(); this.layoutsHandler.updateLayoutSelections(); }; GridState.prototype.resizeLayouts = function () { var _this = this; this.layouts.forEach(function (l) { return l.resize(_this.st.widthUnit, _this.st.levelIndent, _this.clientWidth, l === _this.layout && _this.st.columnAutoWidth); }); }; // Фильтр GridState.prototype.showFilter = function (e, c) { var f = this.ds.getFilter(c); f = f ? f.clone(true) : c.createFilter(this.selection.focusedValue(c)); this.events.filterShowEvent(new FilterShowEvent(e.target, f)); }; // Установка фильтра GridState.prototype.setFilter = function (f) { this.ds.setFilter(f); this.queryChanged(); }; // Очистка фильтра по заданной колонке GridState.prototype.resetFilter = function (f) { if (this.ds.removeFilter(f.fieldName)) { this.queryChanged(); } }; /** * Data sorting * @param sortings List of sortings */ GridState.prototype.sort = function (sortings, update) { if (update === void 0) { update = true; } this.ds.sort(sortings); if (update) { this.queryChanged(); } }; /** * Data filtering * @param filter List of filters */ GridState.prototype.filter = function (filters, update) { if (update === void 0) { update = true; } this.ds.filter(filters); if (update) { this.queryChanged(); } }; /** * Sort by given column * @param col Column * @param add Если true, то оставляем предыдущую сортировку (с зажатым shift) */ GridState.prototype.sortByColumn = function (col, add) { if (!this.st.allowSorting) { return; } this.ds.sortByColumn(col, add); this.queryChanged(); }; /** * Сортировать по полю * @param fieldName Наименование поля * @param add Добавить сортировку к другим сортировкам */ GridState.prototype.sortByField = function (fieldName, add) { var col = this.columnByFieldName(fieldName); this.sortByColumn(col, add); }; // -- COLUMN RESIZING & REORDERING ------------------------------------------- // Изменение ширины колонки GridState.prototype.resizeColumn = function (col, newWidth) { col.width = newWidth; this.updateLayouts(); this.events.columnsChangedEvent(); }; GridState.prototype.hideColumn = function (col) { col.visible = false; this.updateLayouts(); this.events.columnsChangedEvent(); }; // Чиним состояние после drag-n-drop GridState.prototype.fixDrag = function (target) { }; // Перемещение бэнда GridState.prototype.reorderBand = function (targetBand, dropInfo) { if (this.columnCollection.reorderBand(targetBand, dropInfo)) { this.updateLayouts(); this.events.columnsChangedEvent(); } }; // Перемещение колонки GridState.prototype.reorderColumn = function (target, dropInfo, commit) { if (commit === void 0) { commit = true; } if (this.columnCollection.reorderColumn(target, dropInfo)) { this.updateLayouts(); this.events.columnsChangedEvent(); } }; // -- PAGING ----------------------------------------------------------------- // Проверка необходимости установки страницы отображаемых данных GridState.prototype.needSetPage = function (i0, i1) { return i0 < this.pageInfo.offset || i1 > (this.pageInfo.offset + this.pageInfo.limit); }; // Установка страницы отображаемых данных GridState.prototype.setPage = function (offset, limit) { this.pageInfo.offset = offset; this.pageInfo.limit = limit; }; // Фокус сместился GridState.prototype.focusChanged = function (cp) { if (this.st.editorShowMode === EditorShowMode.ON_MOUSE_DOWN) { this.ui.stopEditing(this.ui.editor, cp !== null); this.ui.startEditing(cp); } else { this.ui.stopEditing(this.ui.editor, cp !== null); } }; // Выделить заданную строку GridState.prototype.selectRow = function (r, ri) { return this.selection.selectRow(this.layouts, r, ri, '', this.settings.keyField); }; // Выделение заданной строки GridState.prototype.locateRow = function (r) { var ri = this.ds.resultRows.indexOf(r); if (ri >= 0) { this.selectRow(r, ri); return true; } return false; }; // Выделение строки по значению поля-идентифиатора GridState.prototype.locateByKey = function (keyValue, keyField) { if (keyField === void 0) { keyField = ''; } if (keyField === '') { keyField = this.settings.keyField; } if (this.ds.resultRowCount === 0) { return false; } var found = this.ds.resultRows.find(function (r) { return r[keyField] === keyValue; }); if (found) { var ri = this.ds.resultRows.indexOf(found); if (ri >= 0) { this.selectRow(found, ri); return true; } } return false; }; // -- HEADER CONTEXT MENU ---------------------------------------------------- GridState.prototype.headerContextMenu = function (e, column) { this.events.headerContextMenuEvent({ originalEvent: e, column: column }); }; // -- SUMMARIES -------------------------------------------------------------- GridState.prototype.updateSummaries = function () { this.ds.summaries(this.columns); }; // Добавляет суммирование GridState.prototype.addSummary = function (column, t) { column.addSummary(t); this.events.summariesChangedEvent(column); }; // Заменяет суммирование GridState.prototype.setSummary = function (column, t, a) { if (a === void 0) { a = null; } column.setSummary(t, a); this.events.summariesChangedEvent(column); }; // -- ROW DRAG --------------------------------------------------------------- GridState.prototype.canDrop = function (draggedRows, dropRow, dropPos) { return this.ds.canDrop(draggedRows, dropRow, dropPos); }; GridState.prototype.moveRows = function (draggedRows, dropTarget, dropPos) { this.ds.moveRows(draggedRows, dropTarget, dropPos); this.updateData(); }; GridState.prototype.headerContextMenuEvent = function (e, column) { // Not implemented }; GridState.prototype.getSelectedData = function (selection) { return GridExporter.dataToExport(this.layouts, selection, this.st.selectionMode, this.ds.resultRows, this.ds.valueFormatter); }; GridState.prototype.selectAll = function (sel) { var firstCol = GridLayout.firstColumn(this.layouts); var lastCol = GridLayout.lastColumn(this.layouts); var rr = this.ds.resultRows; sel.startSelect(new CellPosition(rr[0], 0, firstCol.fieldName)); sel.proceedToSelect(new CellPosition(rr[rr.length - 1], rr.length - 1, lastCol.fieldName), false); return sel; }; // -- Data to export GridState.prototype.dataToExport = function () { return GridExporter.dataToExport(this.layouts, this.selectAll(new Selection()), SelectionMode.RANGE, this.ds.resultRows, this.ds.valueFormatter); }; // -- CUSTOM CELL EVENTS ----------------------------------------------------- GridState.prototype.emitCustomCellEvent = function (e) { this.events.customCellEvent(e); }; GridState.prototype.registerHandlers = function () { this.handlers = { 'settings': GridSettings, 'columns': ColumnCollection, 'selection': Selection, 'dataSource': DataSource, 'check': GridCheckHandler, 'ui': GridUIHandler, 'lazyLoader': GridLazyLoadHandler, 'dragDrop': GridDragHandler, 'layouts': LayoutsHandler }; }; __decorate([ AxInject('dataSource'), __metadata("design:type", DataSource) ], GridState.prototype, "dataSource", void 0); __decorate([ AxInject('selection'), __metadata("design:type", Selection) ], GridState.prototype, "selection", void 0); __decorate([ AxInject('check'), __metadata("design:type", GridCheckHandler) ], GridState.prototype, "check", void 0); __decorate([ AxInject('dragDrop'), __metadata("design:type", GridDragHandler) ], GridState.prototype, "dragDrop", void 0); __decorate([ AxInject('ui'), __metadata("design:type", GridUIHandler) ], GridState.prototype, "ui", void 0); __decorate([ AxInject('lazyLoader'), __metadata("design:type", GridLazyLoadHandler) ], GridState.prototype, "lazyLoader", void 0); __decorate([ AxInject('events'), __metadata("design:type", Object) ], GridState.prototype, "events", void 0); __decorate([ AxInject('layouts'), __metadata("design:type", LayoutsHandler) ], GridState.prototype, "layoutsHandler", void 0); __decorate([ AxInject('columns'), __metadata("design:type", ColumnCollection) ], GridState.prototype, "columnCollection", void 0); __decorate([ AxInject('settings'), __metadata("design:type", GridSettings) ], GridState.prototype, "_settings", void 0); return GridState; }(AxInjectConsumer)); export { GridState };