You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
5.3 KiB
163 lines
5.3 KiB
// `
|
|
import DataTree from './data/DataTree'
|
|
import NoTreeData from './data/NoTreeData'
|
|
import onBind from './decorators'
|
|
|
|
let tmpl_selectedElement = (header, name, id) =>
|
|
`
|
|
<div class="selected-element" style="${header ? '': 'display:flex; align-items: center;' }">
|
|
<div class="${header ? 'header' : ''}">
|
|
${header}
|
|
</div>
|
|
<div class="name">
|
|
${name}
|
|
</div>
|
|
<span data-id="${id}" class="icon-remove"></span>
|
|
</div>
|
|
`;
|
|
|
|
export default class SelectedContainer {
|
|
constructor($container, {obj, noTree = false, noHeader = false, onlyOne = false}) {
|
|
// TODO: rename variables to camelCase
|
|
this.$self = $container;
|
|
this.elements_id = []; // [spec_id, spec_id, ...]
|
|
this.onlyOne = onlyOne;
|
|
this.options = {noHeader};
|
|
const self = this;
|
|
this.$self.hide();
|
|
this.dataPromise = obj.dataPromise;
|
|
|
|
this.dataPromise
|
|
.then(
|
|
(data) => {
|
|
data = data.results ? data.results : data;
|
|
this.dataTree = noTree ? new NoTreeData(data) : new DataTree(data);
|
|
this.$input = this.$self.find('input[type="hidden"]');
|
|
if (this.$input.length == 0) throw new URIError(`input for ${this.$self.attr("class")} not found`);
|
|
|
|
this.restoreElements();
|
|
}
|
|
)
|
|
.catch(
|
|
self._onLoadDataError.bind(self)
|
|
);
|
|
|
|
}
|
|
|
|
restoreElements() {
|
|
const self = this;
|
|
if (this.$input && this.$input.val()) {
|
|
|
|
let clearString = this.$input.val().replace(/[\[\]\'\'\"\"]/g, '');
|
|
let data = clearString.split(',').filter((el) => el);
|
|
this.elements_id = [];
|
|
if (this.$input) this.$input.val(this.elements_id.join(','));
|
|
data.forEach((el) => self.add(el));
|
|
}
|
|
}
|
|
|
|
static getTemplate(header, name, id) {
|
|
return tmpl_selectedElement(header, name, id)
|
|
}
|
|
|
|
static getHeader(spec_chain, separator, max_len) {
|
|
function toShortString(string, max_len) {
|
|
return string.slice(0, max_len) + (string.length > max_len ? "..." : "");
|
|
}
|
|
|
|
separator = separator || ' / ';
|
|
let str_chain = "";
|
|
|
|
spec_chain.forEach(function (el) {
|
|
str_chain = (max_len ? toShortString(el.name, max_len) : el.name) + (str_chain ? separator : "") + str_chain;
|
|
});
|
|
|
|
return str_chain;
|
|
}
|
|
|
|
on(methodName, func) {
|
|
this[methodName] = this[methodName].bind(this, {func, bindFunc: true});
|
|
}
|
|
|
|
_removeById(id) {
|
|
let index = this.elements_id.indexOf(id);
|
|
if (index >= 0) {
|
|
this.elements_id.splice(index, 1);
|
|
}
|
|
this.$self.find(`span[data-id='${id}']`).parents('.selected-element').remove();
|
|
}
|
|
|
|
_onLoadDataError(error) {
|
|
console.log("Error loading data -->", error);
|
|
}
|
|
|
|
removeAll() {
|
|
for (let id of this.elements_id){
|
|
this._removeById(id);
|
|
}
|
|
}
|
|
|
|
@onBind
|
|
remove(e) {
|
|
let spec_id = $(e.target).data("id");
|
|
this._removeById(spec_id);
|
|
if (this.$input) this.$input.val(this.elements_id.join(','));
|
|
if (!this.elements_id.length) this.$self.hide();
|
|
e.preventDefault();
|
|
}
|
|
|
|
replace(_id, max_len) {
|
|
const id = Number(_id);
|
|
if (this.elements_id.length > 1) throw new RangeError("Replace error: more than one element");
|
|
// Remove old
|
|
this._removeById(this.elements_id[0]);
|
|
//Add new
|
|
this._addElementToHtml(id, max_len);
|
|
this.elements_id = [id];
|
|
}
|
|
|
|
_addElementToHtml(id, max_len) {
|
|
let self = this;
|
|
const header = SelectedContainer.getHeader(this.dataTree.getSpecChain(id), "", max_len);
|
|
const name = this.dataTree.getElementById(id).name;
|
|
this.elements_id.push(id);
|
|
if (this.$input) this.$input.val(this.elements_id.join(','));
|
|
// console.log("header = ", header);
|
|
this.$self.append(SelectedContainer.getTemplate(header || (this.options.noHeader ? "" : " ") , name, id));
|
|
this.btn_remove = this.$self.find('.icon-remove');
|
|
this.btn_remove.on("click", this.remove.bind(self));
|
|
if (this.elements_id.length) this.$self.show();
|
|
}
|
|
|
|
@onBind
|
|
add(_id, max_len) {
|
|
const id = Number(_id);
|
|
const el = this.dataTree.getElementById(id);
|
|
if (!el){
|
|
throw new Error(`Элемент с id = ${_id} не найден и не может быть добавлен`)
|
|
}
|
|
let self = this;
|
|
if (this.onlyOne) {
|
|
this.replace(_id, max_len);
|
|
return
|
|
}
|
|
|
|
let has_already = this.elements_id.filter(function (el) {
|
|
return self.dataTree.isChild(el, id)
|
|
});
|
|
|
|
if (has_already.length || (this.elements_id).indexOf(Number(id)) != -1) {
|
|
//TODO: do popup messages
|
|
return;
|
|
}
|
|
|
|
let not_valid = this.elements_id.filter(function (el) {
|
|
return self.dataTree.isChild(id, el)
|
|
});
|
|
|
|
not_valid.forEach(function (el) {
|
|
self._removeById(el);
|
|
});
|
|
this._addElementToHtml(id, max_len);
|
|
}
|
|
}
|
|
|