class Node { constructor(data, tree) { this.name = data.name; this.id = data.id; if (data.parent === null) { this.parent = "root"; data.parent = {id:"root"}; this.name = "" } if (data.parent.id && data.parent.id !== 'root') { let el = tree._getElementById(data.parent.id); this.parent = el.node || new Node(el, tree); } data.node = this; this.children = data.children.map(function (el_obj) { let el = tree._getElementById(el_obj.id); if(!el) console.log("el not found with id", el_obj.id); // console.log("el = ", el, "el.id = ", el_obj.id); if (el.node) return el.node; el.node = new Node(el, tree); return el.node }); this.children = this.children || []; } } class SpecTree { constructor(data) { this.baseData = data; this._root = new Node(data[0], this); } /** * получить element в базовой структуре */ _getElementById(id) { for (let i = 0; i < this.baseData.length; i++) { // console.log(this.baseData[i].id, " / ", id); if (this.baseData[i].id == id) return this.baseData[i] } } /** * получить element в дереве */ getElementById(id) { function searchInChildren(children) { for (let i = 0; i < children.length; i++) { if (children[i].id == id) return children[i]; let res = searchInChildren(children[i].children); if (res) return res } } return searchInChildren(this._root.children) } /** * Является ли узел c el_id дочерним для parent_id * @param el_id * @param parent_id */ hasChildren(el_id, parent_id){ function checkParent(el, parent) { if (el.parent == parent) return true; if (el.parent && el.parent != 'root') return checkParent(el.parent, parent); return false; } return checkParent(this.getElementById(el_id), this.getElementById(parent_id)) } /** * @param start_parent_id(number) - начиная с * @param attached(bool) - включая вложенные/дочерние * @param exclude_id - исключая узел c exclude_id и всеми его вложенными узлами * @returns [{name, id}, ...] */ dataToList(start_parent_id, attached, exclude_id) { let data_list = []; function goInChildren(children) { for (let i = 0; i < children.length; i++) { if (children[i].id == exclude_id) continue; data_list.push({name: children[i].name, id: children[i].id}); if (attached) goInChildren(children[i].children); } } let start = start_parent_id ? this.getElementById(start_parent_id) : this._root; goInChildren(start.children); return data_list } /** * * @param id * @param incl(bool) - исключая сам элемент * @returns {Array} всех узлов/элементов от элемента с id до корня */ getSpecChain(id, incl){ let chain = []; let el = this.getElementById(id); // console.log("el = ", el); function getParent(el) { if (el.parent && el.parent != "root"){ chain.push(el.parent); getParent(el.parent) } } getParent(el); // console.log("chain = ", chain); if (incl) chain.unshift(el); return chain } }