bbtreeview/bbtreeviewnode.js

408 lines
7.9 KiB
JavaScript

/**
* BBTreeview
* @version v0.1.0.244 (2023/09/11 2327)
*/
function BBTreeviewNode(treeview)
{
const a = this;
a.Treeview = treeview;
a.initialise();
};
BBTreeviewNode.prototype.Load = function(node) {
const a = this;
a.ID = node.getAttribute("data-bbtv-id");
a.Node = node;
a.Container = node.querySelectorAll("div.li")[0];
a.Label = node.querySelectorAll("span")[0];
a.Value = node.getAttribute("data-bbtv-value");
a.Name = a.Label.textContent;
a.Hint = a.Label.getAttribute("title");
a.ParentID = a.GetParentID();
a.Checked = a.IsChecked();
a.Highlighted = a.IsHighlighted();
a.Tag = a.GetTag();
};
BBTreeviewNode.prototype.Check = function(value) {
const a = this;
a.setCheckbox(a.Node, value);
// Update children
a.Node.querySelectorAll("li").forEach(function(e) {
a.setCheckbox(e, value);
});
// Update parent state
let parentNode = a.GetParentNode();
if (parentNode == null) {
return;
}
// Handle pull-ups
if (a.Treeview.Options.EnablePullUp) {
while (true) {
const parentChecked = (parentNode.querySelectorAll("li.x").length > 0);
a.setCheckbox(parentNode, parentChecked);
parentNode = a.Treeview.getNode(parentNode);
parentNode = parentNode.GetParentNode();
if (parentNode == null) {
break;
}
}
} else {
let uncheckedCount = 0;
parentNode.querySelectorAll("li").forEach(function(e) {
if (e.classList.contains("x")) {
return;
}
uncheckedCount++;
});
a.setCheckbox(parentNode, (uncheckedCount <= 0));
}
};
BBTreeviewNode.prototype.Collapse = function() {
const a = this;
if (a.Node.classList.contains("e")) {
a.Node.classList.remove("e");
a.Node.classList.add("c");
}
a.GetChildNodes().forEach(function(e) {
e.classList.add("hidden");
});
};
BBTreeviewNode.prototype.Expand = function() {
const a = this;
if (a.Node.classList.contains("c")) {
a.Node.classList.remove("c");
a.Node.classList.add("e");
}
a.GetChildNodes().forEach(function(e) {
e.classList.remove("hidden");
});
};
BBTreeviewNode.prototype.GetCheckbox = function() {
const a = this;
if (!a.Treeview.Options.ShowCheckbox) {
return null;
}
const checkboxes = a.Node.querySelectorAll("div.icon.checkbox");
if (typeof(checkboxes) == "undefined") {
return null;
}
return checkboxes[0];
};
BBTreeviewNode.prototype.GetChildNode = function() {
const a = this;
let result = a.Node.querySelectorAll("ul");
if (result.length <= 0) {
return null;
}
return result[0];
};
BBTreeviewNode.prototype.GetChildNodes = function() {
const a = this;
const childNode = a.GetChildNode();
if (childNode == null) {
return [];
}
let nodes = childNode.querySelectorAll("li");
if (nodes.length <= 0) {
return [];
}
let result = [];
nodes.forEach(function(e) {
if (typeof(e.parentNode) == "undefined") {
return;
}
if (e.parentNode != childNode) {
return;
}
result.push(e);
});
return result;
};
BBTreeviewNode.prototype.GetTag = function() {
const a = this;
let tag = a.Node.getAttribute("data-bbtv-tag");
if (a.Treeview.isNullOrWhitespace(tag)) {
return null;
}
return JSON.parse(decodeURIComponent(tag));
};
BBTreeviewNode.prototype.GetParentID = function() {
const a = this;
const parentNode = a.GetParentNode();
if (parentNode == null) {
return null;
}
return parentNode.getAttribute("data-bbtv-id");
};
BBTreeviewNode.prototype.GetParentNode = function() {
const a = this;
return a.parentsUntilTagName(a.Node, "li");
};
BBTreeviewNode.prototype.IsChecked = function() {
const a = this;
if (!a.Treeview.Options.ShowCheckbox) {
return false;
}
return a.Node.classList.contains("x");
};
BBTreeviewNode.prototype.IsExpanded = function() {
const a = this;
if (a.Node.classList.contains("e")) {
return true;
}
if (a.Node.classList.contains("c")) {
return false;
}
return null;
};
BBTreeviewNode.prototype.IsHighlighted = function() {
const a = this;
return (a.Container.classList.contains("highlighted"));
};
BBTreeviewNode.prototype.Remove = function() {
const a = this;
if (a.GetParentNode() != null) {
if (a.GetParentNode().classList.contains("e")) {
a.GetParentNode().classList.remove("e");
}
if (a.GetParentNode().classList.contains("c")) {
a.GetParentNode().classList.remove("c");
}
}
a.Node.parentNode.removeChild(a.Node);
};
BBTreeviewNode.prototype.SetupEvents = function() {
const a = this;
// collapsible icon behaviour
a.Node.addEventListener("click", function(e){
e.stopPropagation();
e.preventDefault();
if (!a.isTag(e.target, "li")) {
return;
}
if ((e.offsetX < 0) || (e.offsetX > 16) || (e.offsetY < 0) || (e.offsetY > 16)) {
return;
}
const myNode = a.Treeview.getNode(e.target);
if (myNode == null) {
return;
}
myNode.Toggle();
});
// collapsible label behaviour
a.Container.addEventListener("dblclick", function(e){
e.stopPropagation();
e.preventDefault();
const myNode = a.Treeview.getNode(e.target);
if (myNode == null) {
return;
}
myNode.Toggle();
});
// checkbox behaviour
if (a.Treeview.Options.ShowCheckbox) {
a.GetCheckbox().addEventListener("mousedown", function(e){
e.stopPropagation();
e.preventDefault();
a.Check(!a.IsChecked());
});
a.GetCheckbox().addEventListener("click", function(e){
e.stopPropagation();
e.preventDefault();
// do nothing
});
a.GetCheckbox().addEventListener("dblclick", function(e){
e.stopPropagation();
e.preventDefault();
// do nothing
});
}
// highlighting
a.Container.addEventListener("mousedown", function(e){
e.stopPropagation();
e.preventDefault();
const myNode = a.Treeview.getNode(e.target);
if (myNode == null) {
return;
}
a.Treeview.Container.querySelectorAll("div.highlighted").forEach(function(e) {
e.classList.remove("highlighted");
});
// Don't show selection
if (!a.Treeview.Options.ShowSelection) {
return;
}
myNode.Container.classList.add("highlighted");
});
a.invalidateCollapsible();
};
BBTreeviewNode.prototype.Toggle = function() {
const a = this;
switch (a.IsExpanded()) {
case true:
a.Collapse();
break;
case false:
a.Expand();
break;
default: break;
}
};
BBTreeviewNode.prototype.initialise = function() {
const a = this;
// a.ID = null;
// a.ParentID = null;
// a.Name = "";
// a.Hint = "";
// a.Value = "";
// a.Icon = "folder";
// a.Checked = false;
};
BBTreeviewNode.prototype.invalidateCollapsible = function() {
const a = this;
// Invalidate state
if (a.GetParentNode() == null) {
return;
}
if (a.GetParentNode().classList.contains("c")) {
a.Node.classList.add("hidden");
} else if (a.GetParentNode().classList.contains("e")) {
a.Node.classList.remove("hidden");
} else {
a.GetParentNode().classList.add("e");
a.Node.classList.remove("hidden");
}
};
BBTreeviewNode.prototype.isTag = function(el, tagName) {
return (el.tagName.toLowerCase() == tagName);
};
BBTreeviewNode.prototype.parentsUntilTagName = function(el, tagName) {
const a = this;
let node = el;
while (true) {
if (typeof(node.parentNode) == "undefined") {
break;
}
node = node.parentNode;
if (typeof(node) == "undefined") {
break;
}
if (a.isTag(node, "ul")) {
if (node.classList.contains("bbtreeview")) {
return null;
}
}
if (a.isTag(node, tagName)) {
break;
}
}
return node;
};
BBTreeviewNode.prototype.setCheckbox = function(el, value) {
if (value) {
if (!el.classList.contains("x")) {
el.classList.add("x");
}
} else {
if (el.classList.contains("x")) {
el.classList.remove("x");
}
}
};