@true-directive/grid
Version:
Angular Data Grid from Yopsilon.
1,093 lines (1,074 loc) • 478 kB
JavaScript
(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