2019-06-29 12:54:32 +02:00
|
|
|
/*
|
|
|
|
* μlogger
|
|
|
|
*
|
|
|
|
* Copyright(C) 2019 Bartek Fabiszewski (www.fabiszewski.net)
|
|
|
|
*
|
|
|
|
* This is free software; you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2019-05-15 11:32:36 +02:00
|
|
|
import uData from './data.js';
|
|
|
|
import uEvent from './event.js';
|
|
|
|
import uUtils from './utils.js';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @class uList
|
|
|
|
* @template T
|
|
|
|
*/
|
|
|
|
export default class uList {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {string} selector
|
|
|
|
* @param {uBinder} binder
|
|
|
|
* @param {Class<T>} type
|
|
|
|
* @template T
|
|
|
|
*/
|
|
|
|
constructor(selector, binder, type) {
|
|
|
|
/** @type {T[]} */
|
|
|
|
this.data = [];
|
|
|
|
/** @type {uBinder} */
|
|
|
|
this.binder = binder;
|
|
|
|
/** @type {boolean} */
|
2019-06-29 12:54:32 +02:00
|
|
|
this._showAllOption = false;
|
2019-05-15 11:32:36 +02:00
|
|
|
/** @type {boolean} */
|
|
|
|
this.hasHead = false;
|
|
|
|
this.headValue = '';
|
|
|
|
this.allValue = '';
|
|
|
|
/** @type {(T|uData)} */
|
|
|
|
this.T = type || uData;
|
|
|
|
/** @type {HTMLSelectElement} */
|
|
|
|
this.domElement = document.querySelector(selector);
|
|
|
|
if (this.binder) {
|
|
|
|
this.binder.addEventListener(uEvent.ADD, this);
|
2019-06-29 12:54:32 +02:00
|
|
|
this.binder.addEventListener(uEvent.CHANGE, this);
|
|
|
|
this.binder.addEventListener(uEvent.CONFIG, this);
|
2019-05-15 11:32:36 +02:00
|
|
|
this.binder.addEventListener(uEvent.EDIT, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @type {string} */
|
|
|
|
this.selectedId = '';
|
|
|
|
this.fromDom();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return {(T|null)}
|
|
|
|
* @template T
|
|
|
|
*/
|
|
|
|
get current() {
|
|
|
|
const i = parseInt(this.selectedId);
|
|
|
|
if (!isNaN(i)) {
|
|
|
|
return this.data.find((item) => item.key === i);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return {boolean}
|
|
|
|
*/
|
|
|
|
get isSelectedAllOption() {
|
|
|
|
return this.selectedId === 'all';
|
|
|
|
}
|
|
|
|
|
2019-06-29 12:54:32 +02:00
|
|
|
get showAllOption() {
|
|
|
|
return this._showAllOption;
|
|
|
|
}
|
|
|
|
|
|
|
|
set showAllOption(value) {
|
|
|
|
if (this._showAllOption !== value) {
|
|
|
|
this._showAllOption = value;
|
|
|
|
if (value === false) {
|
|
|
|
this.selectDefault();
|
|
|
|
}
|
|
|
|
this.render();
|
|
|
|
this.onChange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-15 11:32:36 +02:00
|
|
|
/**
|
|
|
|
* @param {number} id
|
|
|
|
* @param {boolean=} skipUpdate
|
|
|
|
*/
|
|
|
|
select(id, skipUpdate) {
|
|
|
|
this.selectedId = id.toString();
|
|
|
|
this.render();
|
|
|
|
if (!skipUpdate) {
|
|
|
|
this.onChange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clear() {
|
|
|
|
this.domElement.options.length = 0;
|
|
|
|
this.data.length = 0;
|
|
|
|
this.selectedId = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get list from XML structure
|
|
|
|
* @param {Element|Document} xml
|
|
|
|
* @param {string} key Name of key node
|
|
|
|
* @param {string} value Name of value node
|
|
|
|
*/
|
|
|
|
fromXml(xml, key, value) {
|
|
|
|
if (!xml) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (const item of xml) {
|
|
|
|
const row = new this.T(uUtils.getNodeAsInt(item, key), uUtils.getNode(item, value));
|
|
|
|
this.updateDataRow(row);
|
|
|
|
row.binder = this.binder;
|
|
|
|
this.data.push(row);
|
|
|
|
}
|
|
|
|
if (this.data.length) {
|
|
|
|
this.selectedId = this.data[0].key.toString();
|
|
|
|
}
|
|
|
|
this.render();
|
|
|
|
this.onChange();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize list from DOM select element options
|
|
|
|
*/
|
|
|
|
fromDom() {
|
|
|
|
if (!this.domElement) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (const option of this.domElement) {
|
|
|
|
if (option.value === 'all') {
|
2019-06-29 12:54:32 +02:00
|
|
|
this._showAllOption = true;
|
2019-05-15 11:32:36 +02:00
|
|
|
} else if (!option.disabled) {
|
|
|
|
const row = new this.T(parseInt(option.value), option.innerText);
|
|
|
|
this.updateDataRow(row);
|
|
|
|
row.binder = this.binder;
|
|
|
|
this.data.push(row);
|
|
|
|
}
|
|
|
|
if (option.selected) {
|
|
|
|
this.selectedId = option.value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-06-29 12:54:32 +02:00
|
|
|
* @param {uEvent} event
|
2019-05-15 11:32:36 +02:00
|
|
|
* @param {*=} eventData
|
|
|
|
*/
|
|
|
|
handleEvent(event, eventData) {
|
2019-06-29 12:54:32 +02:00
|
|
|
if (event.type === uEvent.CHANGE && eventData.el === this.domElement) {
|
|
|
|
this.selectedId = eventData.id;
|
2019-05-15 11:32:36 +02:00
|
|
|
this.onChange();
|
2019-06-29 12:54:32 +02:00
|
|
|
} else if (event.type === uEvent.EDIT && eventData === this.domElement) {
|
2019-05-15 11:32:36 +02:00
|
|
|
this.onEdit();
|
2019-06-29 12:54:32 +02:00
|
|
|
} else if (event.type === uEvent.ADD && eventData === this.domElement) {
|
2019-05-15 11:32:36 +02:00
|
|
|
this.onAdd();
|
2019-06-29 12:54:32 +02:00
|
|
|
} else if (event.type === uEvent.CONFIG) {
|
|
|
|
this.onConfigChange(eventData);
|
2019-05-15 11:32:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// /**
|
|
|
|
// * @param {T[]} data
|
|
|
|
// */
|
|
|
|
// set list(data) {
|
|
|
|
// this.data = data;
|
|
|
|
// }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add item
|
|
|
|
* @param {T} item
|
|
|
|
* @template T
|
|
|
|
*/
|
|
|
|
add(item) {
|
|
|
|
this.data.push(item);
|
|
|
|
this.render();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {number} id
|
|
|
|
* @return {boolean}
|
|
|
|
*/
|
|
|
|
has(id) {
|
|
|
|
return this.data.findIndex((o) => o.key === id) !== -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove item
|
|
|
|
* @param {number} id
|
|
|
|
*/
|
|
|
|
remove(id) {
|
|
|
|
const currentId = this.current.key;
|
|
|
|
this.data.splice(this.data.findIndex((o) => o.key === id), 1);
|
|
|
|
if (id === currentId) {
|
2019-06-29 12:54:32 +02:00
|
|
|
this.selectDefault();
|
2019-05-15 11:32:36 +02:00
|
|
|
this.onChange();
|
|
|
|
}
|
|
|
|
this.render();
|
|
|
|
}
|
|
|
|
|
2019-06-29 12:54:32 +02:00
|
|
|
selectDefault() {
|
|
|
|
if (this.data.length) {
|
|
|
|
this.selectedId = this.data[0].key.toString();
|
|
|
|
} else {
|
|
|
|
this.selectedId = '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-15 11:32:36 +02:00
|
|
|
render() {
|
|
|
|
this.domElement.options.length = 0;
|
|
|
|
if (this.hasHead) {
|
|
|
|
const head = new Option(this.headValue, '0', true, this.selectedId === '0');
|
|
|
|
head.disabled = true;
|
|
|
|
this.domElement.options.add(head);
|
|
|
|
}
|
2019-06-29 12:54:32 +02:00
|
|
|
if (this._showAllOption) {
|
2019-05-15 11:32:36 +02:00
|
|
|
this.domElement.options.add(new Option(this.allValue, 'all'));
|
|
|
|
}
|
|
|
|
for (const item of this.data) {
|
|
|
|
this.domElement.options.add(new Option(item.value, item.key.toString(), false, item.key.toString() === this.selectedId));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {T} row
|
|
|
|
* @template T
|
|
|
|
*/
|
|
|
|
// eslint-disable-next-line no-unused-vars,no-empty-function,class-methods-use-this
|
|
|
|
updateDataRow(row) {
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @abstract
|
|
|
|
*/
|
|
|
|
// eslint-disable-next-line no-unused-vars,no-empty-function,class-methods-use-this
|
|
|
|
onChange() {
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @abstract
|
|
|
|
*/
|
|
|
|
// eslint-disable-next-line no-unused-vars,no-empty-function,class-methods-use-this
|
|
|
|
onEdit() {
|
|
|
|
}
|
|
|
|
|
2019-06-29 12:54:32 +02:00
|
|
|
/**
|
|
|
|
* @abstract
|
|
|
|
*/
|
|
|
|
// eslint-disable-next-line no-unused-vars,no-empty-function,class-methods-use-this
|
|
|
|
onReload() {
|
|
|
|
}
|
|
|
|
|
2019-05-15 11:32:36 +02:00
|
|
|
/**
|
|
|
|
* @abstract
|
|
|
|
*/
|
|
|
|
// eslint-disable-next-line no-unused-vars,no-empty-function,class-methods-use-this
|
|
|
|
onAdd() {
|
|
|
|
}
|
2019-06-29 12:54:32 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @abstract
|
|
|
|
* @param {string} property
|
|
|
|
*/
|
|
|
|
// eslint-disable-next-line no-unused-vars,no-empty-function,class-methods-use-this
|
|
|
|
onConfigChange(property) {
|
|
|
|
}
|
2019-05-15 11:32:36 +02:00
|
|
|
}
|