UNPKG

@true-directive/grid

Version:

Angular Data Grid from Yopsilon.

1,093 lines (1,074 loc) 478 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@true-directive/base'), require('@angular/core'), require('rxjs'), require('@angular/forms'), require('rxjs/operators'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('@true-directive/grid', ['exports', '@true-directive/base', '@angular/core', 'rxjs', '@angular/forms', 'rxjs/operators', '@angular/common'], factory) : (global = global || self, factory((global['true-directive'] = global['true-directive'] || {}, global['true-directive'].grid = {}), global.base, global.ng.core, global.rxjs, global.ng.forms, global.rxjs.operators, global.ng.common)); }(this, function (exports, base, core, rxjs, forms, operators, common) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global Reflect, Promise */ 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); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } function __decorate(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; } function __param(paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } } function __metadata(metadataKey, metadataValue) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); } var InternationalizationService = /** @class */ (function (_super) { __extends(InternationalizationService, _super); function InternationalizationService() { var _this = _super.call(this) || this; // On locale change event _this._onLocaleChanged = new rxjs.BehaviorSubject(_this.locale); _this.onLocaleChanged = _this._onLocaleChanged.asObservable(); return _this; } InternationalizationService.prototype.localeChangedEvent = function (l) { this._onLocaleChanged.next(l); }; InternationalizationService = __decorate([ core.Injectable(), __metadata("design:paramtypes", []) ], InternationalizationService); return InternationalizationService; }(base.Internationalization)); var TranslatePipe = /** @class */ (function () { function TranslatePipe(intl) { this.intl = intl; } TranslatePipe.prototype.transform = function (value) { return this.intl.translate(value); }; TranslatePipe = __decorate([ core.Pipe({ name: 'trueTranslate', pure: false }), __metadata("design:paramtypes", [InternationalizationService]) ], TranslatePipe); return TranslatePipe; }()); var GridEvents = /** @class */ (function () { function GridEvents() { this.name = 'events'; // -- EVENTS ----------------------------------------------------------------- // Запрос данных у родителя this._onDataQuery = new rxjs.Subject(); this.onDataQuery = this._onDataQuery.asObservable(); // Получение данных от родителя this._onDataFetch = new rxjs.Subject(); this.onDataFetch = this._onDataFetch.asObservable(); // Изменения в списке колонок this._onColumnsChanged = new rxjs.Subject(); this.onColumnsChanged = this._onColumnsChanged.asObservable(); // При изменениях в запросе данных (сортировка/фильтр/группировка) this._onQueryChanged = new rxjs.Subject(); this.onQueryChanged = this._onQueryChanged.asObservable(); // При изменениях групп (свернута/развернута) this._onSummariesChanged = new rxjs.Subject(); this.onSummariesChanged = this._onSummariesChanged.asObservable(); // При изменении значения ячейки this._onValueChanged = new rxjs.Subject(); this.onValueChanged = this._onValueChanged.asObservable(); // При изменении чекбокс this._onCheckedChanged = new rxjs.Subject(); this.onCheckedChanged = this._onCheckedChanged.asObservable(); // Перетаскивание колонки // Тащим this._onDrag = new rxjs.Subject(); this.onDrag = this._onDrag.asObservable(); // Бросаем this._onDrop = new rxjs.Subject(); this.onDrop = this._onDrop.asObservable(); // Изменение ширины колонки // Тащим this._onColumnResizing = new rxjs.Subject(); this.onColumnResizing = this._onColumnResizing.asObservable(); // Бросаем this._onColumnResize = new rxjs.Subject(); this.onColumnResize = this._onColumnResize.asObservable(); // При фильтрации this._onFilterShow = new rxjs.Subject(); this.onFilterShow = this._onFilterShow.asObservable(); // Выделение ячейки/строки/области this._onSelect = new rxjs.Subject(); this.onSelect = this._onSelect.asObservable(); // Включение редактора this._onStartEditing = new rxjs.Subject(); this.onStartEditing = this._onStartEditing.asObservable(); // Выключение редактора this._onStopEditing = new rxjs.Subject(); this.onStopEditing = this._onStopEditing.asObservable(); // Строка перестала быть видимой после редактирования this._onRowUnfiltered = new rxjs.Subject(); this.onRowUnfiltered = this._onRowUnfiltered.asObservable(); // Контекстное меню колонки this._onHeaderContextMenu = new rxjs.Subject(); this.onHeaderContextMenu = this._onHeaderContextMenu.asObservable(); // Событие кастомной ячейки this._onCustomCellEvent = new rxjs.Subject(); this.onCustomCellEvent = this._onCustomCellEvent.asObservable(); } GridEvents.prototype.dataQueryEvent = function (query) { this._onDataQuery.next(query); }; GridEvents.prototype.dataFetchEvent = function (query) { if (query.subject) { query.subject.next(); query.subject.complete(); } this._onDataFetch.next(query); }; GridEvents.prototype.columnsChangedEvent = function () { this._onColumnsChanged.next(); }; GridEvents.prototype.queryChangedEvent = function (query) { this._onQueryChanged.next(query); }; GridEvents.prototype.summariesChangedEvent = function (c) { this._onSummariesChanged.next(c); }; GridEvents.prototype.valueChangedEvent = function (e) { this._onValueChanged.next(e); }; GridEvents.prototype.checkedChangedEvent = function (e) { this._onCheckedChanged.next(e); }; GridEvents.prototype.dragEvent = function (e) { this._onDrag.next(e); }; GridEvents.prototype.dropEvent = function (e) { this._onDrop.next(e); }; GridEvents.prototype.columnResizeEvent = function (e) { this._onColumnResize.next(e); }; GridEvents.prototype.filterShowEvent = function (e) { this._onFilterShow.next(e); }; GridEvents.prototype.selectEvent = function (cp) { this._onSelect.next(cp); }; GridEvents.prototype.startEditingEvent = function (cp) { this._onStartEditing.next(cp); }; GridEvents.prototype.stopEditingEvent = function (returnFocus) { this._onStopEditing.next(returnFocus); }; GridEvents.prototype.headerContextMenuEvent = function (e) { this._onHeaderContextMenu.next(e); }; GridEvents.prototype.customCellEvent = function (e) { this._onCustomCellEvent.next(e); }; return GridEvents; }()); var GridSelection = /** @class */ (function (_super) { __extends(GridSelection, _super); function GridSelection() { var _this = _super.call(this) || this; // Изменен фокус _this._onFocusChanged = new rxjs.Subject(); _this.onFocusChanged = _this._onFocusChanged.asObservable(); // Изменено выделение. Аргумент - последняя позиция последнего range _this._onSelectionChanged = new rxjs.Subject(); _this.onSelectionChanged = _this._onSelectionChanged.asObservable(); return _this; } GridSelection.prototype.selectionChangedEvent = function (cp) { this._onSelectionChanged.next(cp); }; GridSelection.prototype.focusChangedEvent = function (cp) { this._onFocusChanged.next(cp); }; return GridSelection; }(base.Selection)); var DOMUtils = /** @class */ (function () { function DOMUtils() { } DOMUtils.focusAndOpenKeyboard = function (el, timeout) { if (el) { // Align temp input element approximately where the input element is // so the cursor doesn't jump around var __tempEl__ = document.createElement('input'); __tempEl__.style.position = 'absolute'; __tempEl__.style.top = (el.offsetTop + 7) + 'px'; __tempEl__.style.left = el.offsetLeft + 'px'; __tempEl__.style.height = '0'; __tempEl__.style.opacity = '0'; // Put this temp element as a child of the page <body> and focus on it document.body.appendChild(__tempEl__); __tempEl__.focus(); // The keyboard is open. Now do a delayed focus on the target element setTimeout(function () { el.focus(); el.click(); // Remove the temp element document.body.removeChild(__tempEl__); }, timeout); } }; DOMUtils.downloadCSV = function (filename, text) { var element = document.createElement('a'); element.setAttribute('href', 'data:text/csv;charset=utf-8,%EF%BB%BF' + encodeURIComponent(text)); element.setAttribute('download', filename); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); }; DOMUtils.copyToClipboard = function (text) { var ta = document.createElement("textarea"); ta.value = text; ta.style.position = 'fixed'; ta.style.opacity = '0.0'; ta.style.width = '20px'; ta.style.height = '20px'; ta.style.top = '-40px'; ta.style.left = '-40px'; document.body.appendChild(ta); ta.focus(); ta.select(); try { var successful = document.execCommand('copy'); return successful; } catch (err) { return false; } document.body.removeChild(ta); }; return DOMUtils; }()); var GridStateService = /** @class */ (function (_super) { __extends(GridStateService, _super); function GridStateService(internationalization) { var _this = _super.call(this) || this; _this.internationalization = internationalization; _this.focusChangedSubscription = _this.selection.onFocusChanged.subscribe(function (v) { _this.layoutsHandler.updateLayoutSelections(v); _this.focusChanged(v); }); // При изменении выделения - обновить в лэйаутах. Но сейчас наоборот _this.selectionChangedSubscription = _this.selection.onSelectionChanged.subscribe(function (v) { _this.layoutsHandler.updateLayoutSelections(v); _this.events.selectEvent(v); }); _this.localeChangedSubscription = _this.internationalization.onLocaleChanged.subscribe(function (locale) { _this.dataSource.valueFormatter.setLocale(locale); }); return _this; } // Инициируем обновление данных со всеми пересчётами GridStateService.prototype.updateDataAsync = function () { var _this = this; var subject = new rxjs.Subject(); if (this.settings.requestData) { // Необходимо запросить данные this.doQuery(subject); // НО! Нужно обновить колонки. this.events.columnsChangedEvent(); return subject; } // Запрашивать не нужно, считаем всё сами // Асинхронное обновление this.recalcData().then(function () { _this.fetchData(new base.DataQuery(_this._dataQueryCounter)); var rc; if (_this.dataSource.resultRows) { rc = _this.dataSource.resultRows.length; } subject.next(rc); subject.complete(); }); return subject; }; GridStateService.prototype.copySelectionToClipboard = function (withHeaders) { DOMUtils.copyToClipboard(this.getSelectedData(this.selection).toString(withHeaders, '\t')); }; GridStateService.prototype.exportToCSV = function (fileName, columnSeparator) { if (columnSeparator === void 0) { columnSeparator = ','; } DOMUtils.downloadCSV(fileName, this.dataToExport().toString(true, columnSeparator, true)); }; GridStateService.prototype.ngOnDestroy = function () { this.focusChangedSubscription.unsubscribe(); this.selectionChangedSubscription.unsubscribe(); this.localeChangedSubscription.unsubscribe(); }; /* // Важно обновить выделенные области в layouts protected subscribe() { this.events.onSelect.subscribe((cp: CellPosition) => { this.layoutsHandler.updateLayoutSelections(cp); }); } */ GridStateService.prototype.registerHandlers = function () { _super.prototype.registerHandlers.call(this); this.handlers['events'] = GridEvents; this.handlers['selection'] = GridSelection; }; __decorate([ base.AxInject('events'), __metadata("design:type", GridEvents) ], GridStateService.prototype, "events", void 0); __decorate([ base.AxInject('selection'), __metadata("design:type", GridSelection) ], GridStateService.prototype, "selection", void 0); GridStateService = __decorate([ core.Injectable() // @AxInjectConsumer , __metadata("design:paramtypes", [InternationalizationService]) ], GridStateService); return GridStateService; }(base.GridState)); /** * Checkbox component */ var CheckboxComponent = /** @class */ (function () { function CheckboxComponent() { this.onChange = function (_) { }; this.onTouched = function () { }; this.caption = ''; } CheckboxComponent_1 = CheckboxComponent; CheckboxComponent.prototype.registerOnChange = function (fn) { this.onChange = fn; }; CheckboxComponent.prototype.registerOnTouched = function (fn) { this.onTouched = fn; }; Object.defineProperty(CheckboxComponent.prototype, "value", { get: function () { return this._value; }, set: function (v) { if (v !== this._value) { this._value = v; this.onChange(v); } }, enumerable: true, configurable: true }); Object.defineProperty(CheckboxComponent.prototype, "inversed", { get: function () { return this._inversed; }, enumerable: true, configurable: true }); CheckboxComponent.prototype.blur = function () { this.onTouched(); }; // Show value. Formatter: Ctrl --> View CheckboxComponent.prototype.writeValue = function (value) { if (this._value !== value) { this._value = value; } }; var CheckboxComponent_1; __decorate([ core.Input('caption'), __metadata("design:type", String) ], CheckboxComponent.prototype, "caption", void 0); __decorate([ core.Input('inversed'), __metadata("design:type", Object) ], CheckboxComponent.prototype, "_inversed", void 0); __decorate([ core.HostBinding('class.inversed'), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], CheckboxComponent.prototype, "inversed", null); CheckboxComponent = CheckboxComponent_1 = __decorate([ core.Component({ selector: 'true-checkbox', template: "\n <true-checkbox-wrapper [class.inversed]=\"inversed\">\n <input type=\"checkbox\" [(ngModel)]=\"value\" (blur)=\"blur()\"/>\n <span caption>{{caption}}</span>\n </true-checkbox-wrapper>\n ", providers: [{ provide: forms.NG_VALUE_ACCESSOR, useExisting: core.forwardRef(function () { return CheckboxComponent_1; }), multi: true }] }) ], CheckboxComponent); return CheckboxComponent; }()); /** * Checkbox wrapper component */ var CheckboxWrapperComponent = /** @class */ (function () { function CheckboxWrapperComponent() { } CheckboxWrapperComponent = __decorate([ core.Component({ selector: "true-checkbox-wrapper", template: "<label class=\"true-checkbox\"><ng-content select=\"[caption]\"></ng-content>\n <ng-content select=\"input\"></ng-content>\n <span class=\"true-checkbox__checkmark\"></span>\n </label>" }) ], CheckboxWrapperComponent); return CheckboxWrapperComponent; }()); var InputWrapperComponent = /** @class */ (function () { function InputWrapperComponent() { this.showError = true; this.disabled = null; this.onBtnClick = new core.EventEmitter(); } Object.defineProperty(InputWrapperComponent.prototype, "hasBtn", { get: function () { return this.icon !== undefined && this.icon !== ""; }, enumerable: true, configurable: true }); Object.defineProperty(InputWrapperComponent.prototype, "hasError", { get: function () { return this.error !== undefined && this.error !== ""; }, enumerable: true, configurable: true }); InputWrapperComponent.prototype.btnClick = function (e) { this.onBtnClick.emit(e); e.stopPropagation(); }; __decorate([ core.HostBinding('class.true-input_with-btn'), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], InputWrapperComponent.prototype, "hasBtn", null); __decorate([ core.HostBinding('class.true-input_with-error'), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], InputWrapperComponent.prototype, "hasError", null); __decorate([ core.Input('icon'), __metadata("design:type", String) ], InputWrapperComponent.prototype, "icon", void 0); __decorate([ core.Input('error'), __metadata("design:type", String) ], InputWrapperComponent.prototype, "error", void 0); __decorate([ core.Input('showError'), __metadata("design:type", Boolean) ], InputWrapperComponent.prototype, "showError", void 0); __decorate([ core.Input('disabled'), __metadata("design:type", Boolean) ], InputWrapperComponent.prototype, "disabled", void 0); __decorate([ core.Output('btnClick'), __metadata("design:type", core.EventEmitter) ], InputWrapperComponent.prototype, "onBtnClick", void 0); InputWrapperComponent = __decorate([ core.Component({ selector: 'true-input-wrapper', // It is important that the button follows the content without line breaking. // Otherwise a suspicious margin to the right of the button appears. // // Inner DIV with display=flex to avoid line breaking if the width of the component = 100% template: "\n <div>\n <ng-content></ng-content><button\n *ngIf=\"icon\"\n type=\"button\"\n tabindex=\"-1\"\n class=\"true-input__btn\"\n [attr.disabled]=\"disabled\"\n (click)=\"btnClick($event)\">\n <div [ngClass]=\"icon\"></div>\n </button>\n </div>\n <div *ngIf=\"showError\" class=\"true-input__err-msg\">{{error}}</div>\n ", host: { 'class': 'true-input' }, styles: ["\n :host {\n overflow-x: visible;\n word-wrap: normal;\n display: inline-block;\n vertical-align: baseline;\n padding: 0;\n margin: 0;\n }\n\n :host > div:first-child {\n width: 100%;\n height: 100%;\n display: inline-flex;\n }\n\n .true-input__err-msg {\n position: absolute;\n display: none;\n }\n\n :host.true-input_with-error > .true-input__err-msg {\n display: block;\n }\n\n "] }) ], InputWrapperComponent); return InputWrapperComponent; }()); var PopupComponent = /** @class */ (function () { function PopupComponent(elementRef, changeDetector, _renderer) { this.elementRef = elementRef; this.changeDetector = changeDetector; this._renderer = _renderer; this.transform0 = 'translateX(15px)'; this.transform1 = 'translateX(0)'; this.modalTransform0 = 'translateY(-20px)'; this.modalTransform1 = 'translateY(0)'; this.modalTransform2 = 'translateY(20px)'; this.snackTransform0 = 'scale(0.85)'; this.snackTransform1 = 'scale(1.0)'; this.snackTransform2 = 'scale(1.5)'; // Number of pixels for shifting the popup to right when position is [left]. this.shiftDx = 6; this.close = new core.EventEmitter(); this.closed = new core.EventEmitter(); this.show = new core.EventEmitter(); this.position = 'RELATIVE'; this.keepOnTargetClick = true; this._x = -1; this._y = -1; this._visible = false; this._stillVisible = false; this._animating = false; this._overlay = null; } PopupComponent_1 = PopupComponent; PopupComponent.prototype.getZ = function () { return this.zIndex; }; /** * Focus trap * Looking for the next element to switch focus. * @param element Элемент, относительно которого нужно найти следующий * @param backward Поиск назад (Shift+Tab) * @param parent Родительский, в котором сейчас ищем * @param found Заданный элемент найден. Берем следующий подходящий * @return Элемент, на который следует перевести фокус */ PopupComponent.prototype.getNextElement = function (element, backward, parent, found) { if (backward === void 0) { backward = false; } if (parent === void 0) { parent = null; } if (found === void 0) { found = false; } if (element === null) { // Элемент, не задан, ищем первый попавшийся found = true; } if (parent === null) { // Родительский элемент не задан, ищем в хосте parent = this.popup.nativeElement; } for (var i = 0; i < parent.children.length; i++) { var el = backward ? parent.children[parent.children.length - i - 1] : parent.children[i]; if (el.hidden || el.disabled) { continue; } if (el === element) { found = true; continue; } if (el.offsetParent === null) { continue; } if (found && el.tabIndex !== -1 && (el.nodeName === 'INPUT' || el.nodeName === 'BUTTON' || el.nodeName === 'SELECT' || el.nodeName === 'TEXTAREA' || el.tabIndex > 0)) { return { found: found, element: el }; } var res = this.getNextElement(element, backward, el, found); found = res.found; if (res.element) { return res; } } return { found: found, element: null }; }; PopupComponent.prototype.popupMouseDown = function (e) { if (this.zIndex >= PopupComponent_1.z) { e.stopPropagation(); } }; PopupComponent.prototype.popupTouchStart = function (e) { e.stopPropagation(); }; PopupComponent.prototype.popupKeyDown = function (e) { if (e.keyCode === base.Keys.ESCAPE) { this.closePopup(); e.preventDefault(); e.stopPropagation(); } if (e.keyCode === base.Keys.TAB) { // Ищем элемент, на который мы можем отправить фокус после target var res = this.getNextElement(e.target, e.shiftKey); // Не найдено после заданного? Ищем первый if (res.element === null) { res = this.getNextElement(null, e.shiftKey); } if (res.element) { res.element.focus(); } e.preventDefault(); e.stopPropagation(); } }; PopupComponent.prototype.addDocumentListeners = function () { if (!this.documentContextMenuBound) { this.documentContextMenuBound = this.documentContextMenu.bind(this); } if (!this.documentMouseDownBound) { this.documentMouseDownBound = this.documentMouseDown.bind(this); } if (!this.documentTouchStartBound) { this.documentTouchStartBound = this.documentTouchStart.bind(this); } if (!this.documentScrollBound) { this.documentScrollBound = this.documentScroll.bind(this); } if (!this.documentResizeBound) { this.documentResizeBound = this.documentResize.bind(this); } document.addEventListener('contextmenu', this.documentContextMenuBound, false); document.addEventListener('mousedown', this.documentMouseDownBound, false); document.addEventListener('touchstart', this.documentTouchStartBound, false); window.addEventListener('scroll', this.documentScrollBound, false); window.addEventListener('resize', this.documentResizeBound, false); }; PopupComponent.prototype.removeDocumentListeners = function () { document.removeEventListener('contextmenu', this.documentContextMenuBound, false); document.removeEventListener('mousedown', this.documentMouseDownBound, false); document.removeEventListener('touchstart', this.documentTouchStartBound, false); window.removeEventListener('scroll', this.documentScrollBound, false); window.removeEventListener('resize', this.documentResizeBound, false); }; PopupComponent.prototype.maxZIndex = function (element) { var z = 0; var parent = element.parentNode; while (parent && parent.style) { if (!isNaN(parent.style.zIndex) && parent.style.zIndex > z) { z = parent.style.zIndex; } parent = parent.parentNode; } return +z; }; PopupComponent.prototype.documentScroll = function (e) { this.updatePosition(); }; PopupComponent.prototype.documentResize = function (e) { this.updatePosition(); }; PopupComponent.prototype.checkClose = function (target) { var l = target; if (this._target === l && this.keepOnTargetClick) { return false; } if (this._target && base.Utils.isAncestor(this._target, l) && this.keepOnTargetClick) { return false; } if (base.Utils.isAncestor(this.popup.nativeElement, l)) { return false; } else { if (this.zIndex < this.maxZIndex(l)) { // Мы кликнули на более высокий уровень return false; } } if (PopupComponent_1.freeze > 0) { PopupComponent_1.freeze--; return false; } this.closePopup(); return true; }; PopupComponent.prototype.documentTouchStart = function (e) { this.checkClose(e.target); }; PopupComponent.prototype.documentMouseDown = function (e) { this.checkClose(e.target); }; PopupComponent.prototype.documentContextMenu = function (e) { this.checkClose(e.target); }; Object.defineProperty(PopupComponent.prototype, "visible", { get: function () { return this._visible; }, enumerable: true, configurable: true }); PopupComponent.prototype.makeOverlay = function () { var _this = this; PopupComponent_1.z++; var zIndex = PopupComponent_1.z; this._overlay = this._renderer.createElement('div'); this._renderer.setStyle(this._overlay, 'z-index', zIndex); this._renderer.addClass(this._overlay, 'true-modal-overlay'); this._renderer.appendChild(document.body, this._overlay); this._renderer.listen(this._overlay, 'touchstart', function (e) { _this.closePopup(); e.stopPropagation(); e.preventDefault(); }); this._renderer.listen(this._overlay, 'mousedown', function (e) { _this.closePopup(); e.stopPropagation(); e.preventDefault(); }); setTimeout(function () { _this._renderer.setStyle(_this._overlay, 'opacity', '1.0'); }, 50); return this._overlay; }; PopupComponent.prototype.removeOverlay = function () { if (this._overlay) { document.body.removeChild(this._overlay); PopupComponent_1.z--; } this._overlay = null; }; PopupComponent.prototype.resetPosition = function () { this.popup.nativeElement.style.transform = 'scale(1.0)'; this.popup.nativeElement.style.top = '0px'; this.popup.nativeElement.style.left = '0px'; }; PopupComponent.prototype.updatePosition = function () { if (this._x !== -1 || this._y !== -1) { if (PopupComponent_1.renderToBody) { this.popup.nativeElement.style.position = 'fixed'; } this.popup.nativeElement.style.left = this._x + 'px'; this.popup.nativeElement.style.top = this._y + 'px'; return; } if (this.position === 'ABSOLUTE') { this.popup.nativeElement.style.position = 'absolute'; this.popup.nativeElement.style.top = 'unset'; this.popup.nativeElement.style.left = 'unset'; return; } var popupRect = this.popup.nativeElement.getBoundingClientRect(); if (this.position === 'MODAL' || this.position === 'SNACK') { var ww = document.body.clientWidth; var width = popupRect.width; var modalX = (ww - width) / 2; if (modalX <= 10) { modalX = 10; width = ww - 20; } this.popup.nativeElement.style.left = modalX + 'px'; this.popup.nativeElement.style.top = '35px'; return; } var targetRect = this._target.getBoundingClientRect(); var xx = targetRect.left; var yy = targetRect.bottom; if (this._direction.toLowerCase() === 'left') { xx = targetRect.right - popupRect.width + this.shiftDx; } if (this._direction.toLowerCase() === 'right') { xx = targetRect.right; yy = targetRect.top - this.shiftDx; } if (yy + popupRect.height > window.innerHeight && this._direction !== 'right') { yy = targetRect.top - popupRect.height; } if (yy + popupRect.height > window.innerHeight && this._direction === 'right') { yy = targetRect.bottom - popupRect.height + 4; } if (this._direction === 'AboveLeft') { xx = targetRect.right - popupRect.width + 6; yy = targetRect.top - popupRect.height; } if (this._direction === 'AboveRight') { xx = targetRect.left - 6; yy = targetRect.top - popupRect.height; } if (xx + popupRect.width > window.innerWidth) { xx = window.innerWidth - popupRect.width - 4; } else { xx = xx < 0 ? 4 : xx; } yy = yy < 0 ? 4 : yy; this.popup.nativeElement.style.position = 'fixed'; this.popup.nativeElement.style.left = xx + 'px'; this.popup.nativeElement.style.top = yy + 'px'; }; PopupComponent.prototype.resetAnimation = function () { var t0 = this.transform0; if (this.position === 'MODAL') { t0 = this.modalTransform0; } if (this.position === 'SNACK') { t0 = this.snackTransform0; } this.popup.nativeElement.style.opacity = '0'; this.popup.nativeElement.style.transform = t0; }; PopupComponent.prototype.startAnimation = function () { var t1 = this.transform1; if (this.position === 'MODAL') { t1 = this.modalTransform1; } if (this.position === 'SNACK') { t1 = this.snackTransform1; } this.popup.nativeElement.style.opacity = '1.0'; this.popup.nativeElement.style.transform = t1; }; PopupComponent.prototype.display = function () { var _this = this; if (this._visible) { // To prevent the Z-index from being updated during false closures. return; } this._visible = true; this.popup.nativeElement.style.display = 'none'; this.resetAnimation(); this.resetPosition(); setTimeout(function () { if (_this.position === 'MODAL' || _this.position === 'SNACK') { _this.popup.nativeElement.style.position = 'fixed'; _this.popup.nativeElement.style.display = 'block'; if (_this.position === 'MODAL') { _this.makeOverlay(); _this._overlay.appendChild(_this.popup.nativeElement); _this.resetAnimation(); } else { _this._renderer.removeChild(_this.elementRef.nativeElement, _this.popup.nativeElement); _this.changeDetector.detectChanges(); document.body.appendChild(_this.popup.nativeElement); _this.resetAnimation(); } _this.updatePosition(); } else { _this.popup.nativeElement.style.display = 'block'; _this.updatePosition(); if (_this.position === 'RELATIVE' && PopupComponent_1.renderToBody) { _this.popup.nativeElement.style.opacity = '0'; _this._renderer.removeChild(_this.elementRef.nativeElement, _this.popup.nativeElement); _this.changeDetector.detectChanges(); document.body.appendChild(_this.popup.nativeElement); } } PopupComponent_1.z++; _this.zIndex = PopupComponent_1.z; _this.popup.nativeElement.style.zIndex = _this.zIndex; _this.resetAnimation(); setTimeout(function () { _this.startAnimation(); if (_this.position === 'SNACK') { _this.closeSnack(); } }, 50); _this.addDocumentListeners(); _this.show.emit(); }); }; PopupComponent.prototype.closeSnack = function () { var _this = this; this._stillVisible = true; setTimeout(function () { if (_this._stillVisible) { _this.popup.nativeElement.style.opacity = '0'; _this.popup.nativeElement.style.transform = _this.snackTransform2; setTimeout(function () { _this.closePopup(); }, 300); } }, 1000); }; PopupComponent.prototype.showByXY = function (x, y) { this._x = x; this._y = y; this.display(); }; PopupComponent.prototype.showByTarget = function (target, direction) { if (target === void 0) { target = null; } if (direction === void 0) { direction = ''; } this._target = target; this._direction = direction; this.display(); }; PopupComponent.prototype.showPopup = function () { if (this._visible) { this.closePopup(); } this.showByTarget(); }; PopupComponent.prototype.closePopup = function (result, confirmed) { if (result === void 0) { result = null; } if (confirmed === void 0) { confirmed = false; } if (!this._visible) { return; // Чтобы Z-индекс не обновлялся при ложных закрытиях } this._visible = false; this._stillVisible = false; // можно отменить закрытие var event = new base.CloseEvent(result); event.confirmed = confirmed; this.close.emit(event); if (event.isCanceled) { return; } PopupComponent_1.z--; if (PopupComponent_1.z <= 9) { PopupComponent_1.z = 9; } if (this.position === 'MODAL') { this._overlay.removeChild(this.popup.nativeElement); this.removeOverlay(); this.elementRef.nativeElement.appendChild(this.popup.nativeElement); } if (this.position === 'SNACK') { document.body.removeChild(this.popup.nativeElement); this.elementRef.nativeElement.appendChild(this.popup.nativeElement); } this._target = null; this._x = -1; this._y = -1; this.popup.nativeElement.style.display = 'none'; this.resetAnimation(); if (this.position === 'RELATIVE' && PopupComponent_1.renderToBody) { this._renderer.removeChild(document.body, this.popup.nativeElement); this.changeDetector.detectChanges(); this.elementRef.nativeElement.appendChild(this.popup.nativeElement); } else { this.changeDetector.detectChanges(); } this.removeDocumentListeners(); this.closed.emit(result); }; PopupComponent.prototype.toggle = function (target, direction) { if (this._visible) { this.closePopup(); } else { this.showByTarget(target, direction); } }; var PopupComponent_1; // Popup will not be closed if value of this property more than 0 PopupComponent.freeze = 0; PopupComponent.z = 19; PopupComponent.renderToBody = true; __decorate([ core.ViewChild('popup', { static: true }), __metadata("design:type", Object) ], PopupComponent.prototype, "popup", void 0); __decorate([ core.Output('close'), __metadata("design:type", core.EventEmitter) ], PopupComponent.prototype, "close", void 0); __decorate([ core.Output('closed'), __metadata("design:type", core.EventEmitter) ], PopupComponent.prototype, "closed", void 0); __decorate([ core.Output('show'), __metadata("design:type", core.EventEmitter) ], PopupComponent.prototype, "show", void 0); __decorate([ core.Input('position'), __metadata("design:type", String) ], PopupComponent.prototype, "position", void 0); __decorate([ core.Input('keepOnTargetClick'), __metadata("design:type", Object) ], PopupComponent.prototype, "keepOnTargetClick", void 0); PopupComponent = PopupComponent_1 = __decorate([ core.Component({ selector: 'true-popup', template: "\n <div [style.zIndex]=\"getZ()\" class=\"true-popup\"\n [class.true-snack]=\"position==='SNACK'\"\n (mousedown)=\"popupMouseDown($event)\"\n (touchstart)=\"popupTouchStart($event)\"\n (keydown)=\"popupKeyDown($event)\" #popup>\n <ng-content #content></ng-content>\n </div>", host: { '(touchend)': '$event.stopPropagation()' }, styles: ["\n :host > div {\n position: fixed;\n display: none;\n opacity: 0.0;\n }\n\n .true-modal-overlay {\n position: fixed;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n opacity: 0.0;\n overflow-y: auto;\n }\n "] }), __metadata("design:paramtypes", [core.ElementRef, core.ChangeDetectorRef, core.Renderer2]) ], PopupComponent); return PopupComponent; }()); /** * Calendar component. */ var CalendarComponent = /** @class */ (function () { function CalendarComponent(intl, cd, el) { this.intl = intl; this.cd = cd; this.el = el; this.onChange = function (_) { }; this.onTouched = function () { }; this._value = null; this.mode = 'days'; this.dateClick = new core.EventEmitter(); this.escape = new core.EventEmitter(); // Day names this.dayNames = []; // Month weeks this.weeks = []; // Year months this.monthRows = []; // Matrix of displayed years this.yearRows = []; this._minYear = 0; this._maxYear = 0; } CalendarComponent_1 = CalendarComponent; Object.defineProperty(CalendarComponent.prototype, "value", { get: function () { return this._value; }, set: function (v) { if (v !== this._value) { this._value = v; this.createWeeks(this._value); this.onChange(v); } }, enumerable: true, configurable: true }); Object.defineProperty(CalendarComponent.prototype, "valueTime", { get: function () { var vTime = 0; if (this.value !== null && !isNaN(this.value.getTime())) { vTime = this.value.getTime(); } return vTime; }, enumerable: true, configurable: true }); Object.defineProperty(CalendarComponent.prototype, "monthYear", { get: function () { var m = this.calendarDateStart.getMonth(); var y = this.calendarDateStart.getFullYear(); if (this.mode === 'days') { return this.intl.locale.longMonthNames[m] + ' ' + y; } if (this.mode === 'months') { return y; } if (this.mode === 'years') { return this._minYear + ' - ' + this._maxYear; } }, enumerable: true, configurable: true }); Object.defineProperty(CalendarComponent.prototype, "today", { get: function () { return base.Dates.today(); }, enumerable: true, configurable: true }); CalendarComponent.prototype.registerOnChange = function (fn) { this.onChange = fn; }; CalendarComponent.prototype.registerOnTouched = function (fn) { this.onTouched = fn; }; CalendarComponent.prototype.blur = function () { this.onTouched(); }; // Отображаем значение в компоненте. Formatter: Ctrl --> View Calenda