import {VetproviehElement} from './vetprovieh-element'; import {Indexable, IRepository} from '../interfaces'; import {ViewHelper} from '../helpers'; /** * Repeats Template Element. Amount is set by the amount of objects * inside */ export class VetproviehBasicRepeat extends VetproviehElement { /** * Getting observed Attributes * @return {string[]} */ static get observedAttributes() { return ['objects', 'orderBy']; } private _objects: Array = []; protected _listTemplate: DocumentFragment; private _orderBy = '+position'; private _afterClearAndRender: (() => void) | undefined; public repository: IRepository | undefined; /** * Default-Contructor * @param {HTMLTemplateElement | undefined} pListTemplate * @param {Boolean} shadowed */ constructor( pListTemplate: HTMLTemplateElement | undefined = undefined, shadowed = true) { super(shadowed); const listTemplate = pListTemplate || this.querySelector('template'); if (listTemplate) { this._listTemplate = listTemplate.content; } else { this._listTemplate = new DocumentFragment(); } } /** * Set List Template and Render * @param {DocumentFragment} val */ public set listTemplate(val: DocumentFragment) { if (this._listTemplate !== val) { this._listTemplate = val; this.clearAndRender(); } } /** * Get objects * @return {Array} */ public get objects(): Array { return this._objects; } /** * Set objects * @param {Array} v */ public set objects(v: Array) { if (this._objects != v) { this._objects = v; this.clearAndRender(); } } /** * Get Function for afterClearAndRender * @return {Function | undefined} */ public get afterClearAndRender() : (() => void) | undefined { return this._afterClearAndRender; } /** * Set Function for afterClearAndRender * @param {Function | undefined} func */ public set afterClearAndRender(func: (() => void) | undefined) { if (func !== this._afterClearAndRender) { this._afterClearAndRender = func; } } /** * Get OrderBy * Expect "+position" for asceding positon * Expect "-position" for descending position * @return {string} */ public get orderBy(): string { return this._orderBy; } /** * Set OrderBy * @param {string} v */ public set orderBy(v: string) { if (this._orderBy != v) { this._orderBy = v; this.clearAndRender(); } } /** * Delete Element * @param {number} index */ public delete(index: number) { if (this.objects.length > index) { const obj = this.objects[index]; if (this.repository) { this.repository.destroy(obj.id).then((result) => { if (result) { this.dropObject(index); } }).catch((error) => { console.log(error); }); } else { this.dropObject(index); } } } /** * Drop Object from List * @param {number} index */ private dropObject(index: number) { this.objects.splice(index, 1); this.clearAndRender(); } /** * Connected Callback */ connectedCallback() { this._initalizeShadowRoot(VetproviehBasicRepeat.template); this.renderList(); } /** * Clear and Render */ clearAndRender() { this.clear(); this._sortObjects(); this.renderList(); if (this._afterClearAndRender !== undefined) this._afterClearAndRender(); } /** * Sorting Objects */ private _sortObjects() { try { const asc = this.orderBy.substring(0, 1) == '+' ? 1 : -1; const argument = this.orderBy.substring(1); this.objects = this.objects .sort((a: any, b: any) => { const aValue = a[argument]; const bValue = b[argument]; return (aValue - bValue) * asc; }); } catch (e) { } } /** * List will be cleared */ clear() { const list = this.list; if (list) list.innerHTML = ''; } /** * Rendering List-Content */ renderList() { this.objects .forEach((obj: any, index: number) => { this._attachToList(obj, index); }); } /** * Inserts Element to List * @param {any} dataItem * @param {number} index * @private */ protected _attachToList(dataItem: any, index = 0) { if (this.shadowRoot) { const newListItem: HTMLElement = this._generateListItem(dataItem); if (typeof (dataItem) === 'object') { dataItem['index'] = index.toString(); } ViewHelper.replacePlaceholders(newListItem, dataItem); const list = this.list; if (list && newListItem.children[0]) { list.appendChild(newListItem.children[0]); } } } /** * Getting List Element * @return {HTMLElement | undefined} */ protected get list(): HTMLElement | undefined { if (this.shadowRoot) { return this.shadowRoot.getElementById('listElements') as HTMLElement; } else { return undefined; } } /** * Generate new Item for List which is based on the template * @param {any} dataItem * @param {boolean} activatedEventListener * @return {HTMLDivElement} * @private */ protected _generateListItem(dataItem: any, activatedEventListener = false) { const newNode = document.importNode(this._listTemplate, true); const div = document.createElement('div'); if (activatedEventListener) { div.addEventListener('click', () => { const selectedEvent = new Event('selected'); (selectedEvent as Indexable)['data'] = dataItem; this.dispatchEvent(selectedEvent); }); } div.appendChild(newNode); return div; } /** * Intializing Shadow-Root * @param {string} template * @protected */ protected _initalizeShadowRoot(template: string) { // Lazy creation of shadowRoot. if (!this.shadowRoot) { super.attachShadow({ mode: 'open', }).innerHTML = template; } } }