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

// `
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 ? "" : "&nbsp;") , 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);
}
}