2022-07-30 14:13:02 +02:00
|
|
|
import {Controller} from "@hotwired/stimulus";
|
|
|
|
|
2022-08-13 00:28:03 +02:00
|
|
|
import {BSTreeView, BS5Theme, FAIconTheme, EVENT_INITIALIZED} from "@jbtronics/bs-treeview";
|
|
|
|
import "@jbtronics/bs-treeview/styles/bs-treeview.css";
|
2022-07-30 14:13:02 +02:00
|
|
|
|
|
|
|
export default class extends Controller {
|
|
|
|
static targets = [ "tree" ];
|
|
|
|
|
2022-07-31 15:50:16 +02:00
|
|
|
_url = null;
|
|
|
|
_data = null;
|
|
|
|
|
2022-08-13 00:28:03 +02:00
|
|
|
/**
|
|
|
|
* @type {BSTreeView}
|
|
|
|
* @private
|
|
|
|
*/
|
2022-08-07 01:55:44 +02:00
|
|
|
_tree = null;
|
|
|
|
|
2022-07-30 14:13:02 +02:00
|
|
|
connect() {
|
|
|
|
const treeElement = this.treeTarget;
|
|
|
|
if (!treeElement) {
|
|
|
|
console.error("You need to define a tree target for the controller!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-31 15:50:16 +02:00
|
|
|
this._url = this.element.dataset.treeUrl;
|
|
|
|
this._data = this.element.dataset.treeData;
|
|
|
|
|
|
|
|
this.reinitTree();
|
|
|
|
}
|
|
|
|
|
|
|
|
reinitTree()
|
|
|
|
{
|
2022-07-30 14:13:02 +02:00
|
|
|
//Fetch data and initialize tree
|
2022-07-31 15:50:16 +02:00
|
|
|
this._getData()
|
|
|
|
.then(this._fillTree.bind(this))
|
2022-08-13 00:28:03 +02:00
|
|
|
.catch((err) => {
|
2022-07-31 15:50:16 +02:00
|
|
|
console.error("Could not load the tree data: " + err);
|
2022-08-13 00:28:03 +02:00
|
|
|
});
|
2022-07-31 15:50:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
setData(data) {
|
|
|
|
this._data = data;
|
|
|
|
this.reinitTree();
|
|
|
|
}
|
2022-07-30 14:13:02 +02:00
|
|
|
|
2022-07-31 15:50:16 +02:00
|
|
|
setURL(url) {
|
|
|
|
this._url = url;
|
|
|
|
this.reinitTree();
|
2022-07-30 14:13:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
_fillTree(data) {
|
2022-08-13 00:28:03 +02:00
|
|
|
if(this._tree) {
|
|
|
|
this._tree.remove();
|
|
|
|
}
|
2022-07-30 14:13:02 +02:00
|
|
|
|
2022-08-07 01:55:44 +02:00
|
|
|
this._tree = new BSTreeView(this.treeTarget, {
|
2022-08-13 00:28:03 +02:00
|
|
|
levels: 1,
|
|
|
|
//showTags: true,
|
2022-07-30 14:13:02 +02:00
|
|
|
data: data,
|
|
|
|
showIcon: false,
|
2022-08-06 04:04:06 +02:00
|
|
|
onNodeSelected: function (event) {
|
2022-08-13 00:28:03 +02:00
|
|
|
const node = event.detail.node;
|
|
|
|
if (node.href) {
|
2022-07-30 14:13:02 +02:00
|
|
|
|
|
|
|
//Simulate a click so we just change the inner frame
|
|
|
|
let a = document.createElement('a');
|
2022-08-13 00:28:03 +02:00
|
|
|
a.setAttribute('href', node.href);
|
2022-07-30 14:13:02 +02:00
|
|
|
a.innerHTML = "";
|
2022-08-06 03:40:24 +02:00
|
|
|
document.body.appendChild(a);
|
2022-07-30 14:13:02 +02:00
|
|
|
a.click();
|
|
|
|
a.remove();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
//onNodeContextmenu: contextmenu_handler,
|
2022-08-13 00:28:03 +02:00
|
|
|
}, [BS5Theme, FAIconTheme]);
|
|
|
|
|
|
|
|
this.treeTarget.addEventListener(EVENT_INITIALIZED, (event) => {
|
|
|
|
const treeView = event.detail.treeView;
|
|
|
|
treeView.revealNode(treeView.getSelected());
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2022-07-30 14:13:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
collapseAll() {
|
2022-08-07 01:55:44 +02:00
|
|
|
this._tree.collapseAll({silent: true});
|
2022-07-30 14:13:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
expandAll() {
|
2022-08-07 01:55:44 +02:00
|
|
|
this._tree.expandAll({silent: true});
|
2022-07-30 14:13:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
searchInput(event) {
|
2022-07-31 15:50:16 +02:00
|
|
|
const data = event.target.value;
|
2022-07-30 14:13:02 +02:00
|
|
|
//Do nothing if no data was passed
|
|
|
|
|
|
|
|
const tree = this.treeTarget;
|
2022-08-07 01:55:44 +02:00
|
|
|
this._tree.collapseAll({silent: true});
|
2022-08-13 00:28:03 +02:00
|
|
|
this._tree.search(data);
|
|
|
|
|
|
|
|
//Rereveal the selected node again
|
|
|
|
this._tree.revealNode(this._tree.getSelected());
|
2022-07-30 14:13:02 +02:00
|
|
|
}
|
|
|
|
|
2022-07-31 21:29:00 +02:00
|
|
|
/**
|
|
|
|
* Check if the tree is already initialized (meaning bootstrap treeview was called on the object)
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_isInitialized() {
|
2022-08-07 01:55:44 +02:00
|
|
|
return this._tree !== null;
|
2022-07-31 21:29:00 +02:00
|
|
|
}
|
2022-07-31 15:50:16 +02:00
|
|
|
|
2022-07-30 14:13:02 +02:00
|
|
|
_getData() {
|
|
|
|
//Use lambda function to preserve this context
|
|
|
|
return new Promise((myResolve, myReject) => {
|
2022-07-31 15:50:16 +02:00
|
|
|
//If a url is defined, fetch the data from the url
|
|
|
|
if (this._url) {
|
|
|
|
return fetch(this._url)
|
|
|
|
.then((response) => myResolve(response.json()))
|
|
|
|
.catch((err) => myReject(err));
|
|
|
|
}
|
|
|
|
|
|
|
|
//Otherwise load the data provided via the data attribute
|
|
|
|
return myResolve(this._data);
|
2022-07-30 14:13:02 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|