From 7355f906f41a90853012d611282a830009678831 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 10 Sep 2023 13:41:58 +0100 Subject: [PATCH] WIP: Refactor to compartmentalise treeview node --- bbtreeview.js | 465 +++++++++++++++++++++++++++++++++++----------- bbtreeviewnode.js | 4 + demo-test.html | 166 +++++++++++++---- 3 files changed, 486 insertions(+), 149 deletions(-) create mode 100644 bbtreeviewnode.js diff --git a/bbtreeview.js b/bbtreeview.js index 1f90b00..cd4c78d 100644 --- a/bbtreeview.js +++ b/bbtreeview.js @@ -30,7 +30,7 @@ BBTreeview.prototype.AddItem = function(options) { if (parentNode == null) { parentNode = a.Container; } else { - parentNode = parentNode.ChildNode; + parentNode = parentNode.GetChildNode(); } const nodeHtml = a.generateNodeHtml(_options); @@ -63,23 +63,24 @@ BBTreeview.prototype.AddItem = function(options) { // Setup checkbox events if (a.Options.ShowCheckbox) { - node.Checkbox.addEventListener("mousedown", function(e){ + node.GetCheckbox().addEventListener("mousedown", function(e){ e.stopPropagation(); e.preventDefault(); - node.Checked = !node.Checked; + // node.Checked = !node.Checked; - a.CheckNode(node, node.Checked); + // a.CheckNode(node, node.Checked); + node.Check(!node.IsChecked()); }); - node.Checkbox.addEventListener("click", function(e){ + node.GetCheckbox().addEventListener("click", function(e){ e.stopPropagation(); e.preventDefault(); // do nothing }); - node.Checkbox.addEventListener("dblclick", function(e){ + node.GetCheckbox().addEventListener("dblclick", function(e){ e.stopPropagation(); e.preventDefault(); @@ -107,6 +108,11 @@ BBTreeview.prototype.AddItem = function(options) { e.classList.remove("highlighted"); }); + // Don't show selection + if (!a.Options.ShowSelection) { + return; + } + myNode.Container.classList.add("highlighted"); }); @@ -124,13 +130,13 @@ BBTreeview.prototype.AddItem = function(options) { }); // Invalidate state - if (node.ParentNode != null) { - if (node.ParentNode.classList.contains("c")) { + if (node.GetParentNode() != null) { + if (node.GetParentNode().classList.contains("c")) { node.Node.classList.add("hidden"); - } else if (node.ParentNode.classList.contains("e")) { + } else if (node.GetParentNode().classList.contains("e")) { node.Node.classList.remove("hidden"); } else { - node.ParentNode.classList.add("e"); + node.GetParentNode().classList.add("e"); node.Node.classList.remove("hidden"); } } @@ -146,17 +152,19 @@ BBTreeview.prototype.Remove = function(id) { return false; } - node.Node.parentNode.removeChild(node.Node); + node.Remove(); - if (node.ParentNode != null) { - if (node.ParentNode.classList.contains("e")) { - node.ParentNode.classList.remove("e"); - } + // node.Node.parentNode.removeChild(node.Node); - if (node.ParentNode.classList.contains("c")) { - node.ParentNode.classList.remove("c"); - } - } + // if (node.GetParentNode() != null) { + // if (node.GetParentNode().classList.contains("e")) { + // node.GetParentNode().classList.remove("e"); + // } + + // if (node.GetParentNode().classList.contains("c")) { + // node.GetParentNode().classList.remove("c"); + // } + // } return true; }; @@ -166,7 +174,8 @@ BBTreeview.prototype.Default = function() { return { TreeviewOptions: { ID: null, - ShowCheckbox: false + ShowCheckbox: false, + ShowSelection: true }, TreeNodeOptions: { ID: null, @@ -181,55 +190,61 @@ BBTreeview.prototype.Default = function() { }; -BBTreeview.prototype.CheckNode = function(node, value) { +// BBTreeview.prototype.CheckNode = function(node, value) { +// const a = this; + +// a.setNodeCheckbox(node.Node, value); + +// // Update children +// node.Node.querySelectorAll("li").forEach(function(e) { +// a.setNodeCheckbox(e, value); +// }); + +// // Invalidate ParentNode +// // node.ParentNode = a.GetParentNode(node.Node); + +// // Update parent state +// if (node.GetParentNode() != null) { +// let uncheckedCount = 0; +// node.GetParentNode().querySelectorAll("li").forEach(function(e) { +// if (e.classList.contains("x")) { +// return; +// } + +// uncheckedCount++; +// }); + +// a.setNodeCheckbox(node.GetParentNode(), (uncheckedCount <= 0)); +// } +// }; + +BBTreeview.prototype.Clear = function() { const a = this; - a.setNodeCheckbox(node.Node, value); - - // Update children - node.Node.querySelectorAll("li").forEach(function(e) { - a.setNodeCheckbox(e, value); - }); - - // Invalidate ParentNode - node.ParentNode = a.GetParentNode(node.Node); - - // Update parent state - if (node.ParentNode != null) { - let uncheckedCount = 0; - node.ParentNode.querySelectorAll("li").forEach(function(e) { - if (e.classList.contains("x")) { - return; - } - - uncheckedCount++; - }); - - a.setNodeCheckbox(node.ParentNode, (uncheckedCount <= 0)); - } + a.initialise(a.Options); }; -BBTreeview.prototype.CollapseNode = function(node) { - const a = this; +// BBTreeview.prototype.CollapseNode = function(node) { +// const a = this; - node.Node.classList.remove("e"); - node.Node.classList.add("c"); +// node.Node.classList.remove("e"); +// node.Node.classList.add("c"); - a.GetChildNodes(node.Node).forEach(function(e) { - e.classList.add("hidden"); - }); -}; +// a.GetChildNodes(node.Node).forEach(function(e) { +// e.classList.add("hidden"); +// }); +// }; -BBTreeview.prototype.ExpandNode = function(node) { - const a = this; +// BBTreeview.prototype.ExpandNode = function(node) { +// const a = this; - node.Node.classList.remove("c"); - node.Node.classList.add("e"); +// node.Node.classList.remove("c"); +// node.Node.classList.add("e"); - a.GetChildNodes(node.Node).forEach(function(e) { - e.classList.remove("hidden"); - }); -}; +// a.GetChildNodes(node.Node).forEach(function(e) { +// e.classList.remove("hidden"); +// }); +// }; BBTreeview.prototype.Find = function(id) { const a = this; @@ -240,65 +255,74 @@ BBTreeview.prototype.Find = function(id) { return null; } - let response = { - ID: id, - Node: node[0], - ParentNode: a.GetParentNode(node[0]), - ChildNode: a.getChildNode(node[0]), - Container: node[0].querySelectorAll("div.li")[0], - Label: node[0].querySelectorAll("span")[0], - Checked: node[0].classList.contains("x"), - Checkbox: (a.Options.ShowCheckbox ? node[0].querySelectorAll("div.icon.checkbox")[0] : null), - Value: node[0].getAttribute("data-bbtv-value") - }; + let treenode = new BBTreeviewNode(this); + treenode.Load(node[0]); - // console.log(response); + console.log(treenode); - return response; + return treenode; + + // let response = { + // ID: id, + // Node: node[0], + // ParentNode: a.GetParentNode(node[0]), + // ChildNode: a.getChildNode(node[0]), + // Container: node[0].querySelectorAll("div.li")[0], + // Label: node[0].querySelectorAll("span")[0], + // Checked: node[0].classList.contains("x"), + // Checkbox: (a.Options.ShowCheckbox ? node[0].querySelectorAll("div.icon.checkbox")[0] : null), + // Value: node[0].getAttribute("data-bbtv-value") + // }; + + // // console.log(response); + + // return response; }; -BBTreeview.prototype.GetChildNodes = function(node) { - const a = this; +// BBTreeview.prototype.GetChildNodes = function(node) { +// const a = this; - const childNode = a.getChildNode(node); - if (childNode == null) { - return []; - } +// const childNode = a.getChildNode(node); +// if (childNode == null) { +// return []; +// } - let nodes = childNode.querySelectorAll("li"); - if (nodes.length <= 0) { - return []; - } +// let nodes = childNode.querySelectorAll("li"); +// if (nodes.length <= 0) { +// return []; +// } - let result = []; - nodes.forEach(function(e) { - if (typeof(e.parentNode) == "undefined") { - return; - } +// let result = []; +// nodes.forEach(function(e) { +// if (typeof(e.parentNode) == "undefined") { +// return; +// } - if (e.parentNode != childNode) { - return; - } +// if (e.parentNode != childNode) { +// return; +// } - result.push(e); - }); +// result.push(e); +// }); - return result; -}; +// return result; +// }; -BBTreeview.prototype.GetParentNode = function(node) { - const a = this; +// BBTreeview.prototype.GetParentNode = function(node) { +// const a = this; - return a.parentsUntilTagName(node, "li"); -}; +// return a.parentsUntilTagName(node, "li"); +// }; BBTreeview.prototype.Toggle = function(node) { const a = this; if (node.Node.classList.contains("c")) { - a.ExpandNode(node); + // a.ExpandNode(node); + node.Expand(); } else if (node.Node.classList.contains("e")) { - a.CollapseNode(node); + // a.CollapseNode(node); + node.Collapse(); } else { // do nothing } @@ -360,16 +384,16 @@ BBTreeview.prototype.generateNodeHtml = function(options) { return html; }; -BBTreeview.prototype.getChildNode = function(node) { - const a = this; +// BBTreeview.prototype.getChildNode = function(node) { +// const a = this; - let result = node.querySelectorAll("ul"); - if (result.length <= 0) { - return null; - } +// let result = node.querySelectorAll("ul"); +// if (result.length <= 0) { +// return null; +// } - return result[0]; -}; +// return result[0]; +// }; BBTreeview.prototype.getNode = function(el) { const a = this; @@ -443,9 +467,228 @@ BBTreeview.prototype.parentsUntilTagName = function(el, tagName) { return node; }; -BBTreeview.prototype.setNodeCheckbox = function(el, value) { +// BBTreeview.prototype.setNodeCheckbox = function(el, value) { +// const a = this; + +// if (value) { +// if (!el.classList.contains("x")) { +// el.classList.add("x"); +// } +// } else { +// if (el.classList.contains("x")) { +// el.classList.remove("x"); +// } +// } +// }; + + + + + + +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.ParentNode: a.GetParentNode(node[0]); + // a.ChildNode: a.getChildNode(node[0]); + + a.Container = node.querySelectorAll("div.li")[0]; + a.Label = node.querySelectorAll("span")[0]; + // a.Checked = a.IsChecked(); + // a.Checkbox = a.GetCheckbox(); + a.Value = node.getAttribute("data-bbtv-value"); +}; + + +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 + if (a.GetParentNode() != null) { + let uncheckedCount = 0; + a.GetParentNode().querySelectorAll("li").forEach(function(e) { + if (e.classList.contains("x")) { + return; + } + + uncheckedCount++; + }); + + a.setCheckbox(a.GetParentNode(), (uncheckedCount <= 0)); + } +}; + +BBTreeviewNode.prototype.Collapse = function() { + const a = this; + + 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; + + 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.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.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.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.isTag = function(el, tagName) { + return (el.tagName.toLowerCase() == tagName); +}; + +BBTreeviewNode.prototype.parentsUntilTagName = function(el, tagName) { + const a = this; + + let node = el; + + while (true) { + 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"); @@ -455,4 +698,4 @@ BBTreeview.prototype.setNodeCheckbox = function(el, value) { el.classList.remove("x"); } } -}; \ No newline at end of file +}; diff --git a/bbtreeviewnode.js b/bbtreeviewnode.js new file mode 100644 index 0000000..5e41c02 --- /dev/null +++ b/bbtreeviewnode.js @@ -0,0 +1,4 @@ +/** + * BBTreeview + * @version v0.1.0.223 (2023/09/08 2027) + */ diff --git a/demo-test.html b/demo-test.html index c27ac33..84b0ec9 100644 --- a/demo-test.html +++ b/demo-test.html @@ -10,66 +10,156 @@ - + + -
+ + +
+ +
+ +
+
+
+ +

Create demo treeview with checkboxes

+ + +
+
+ +

Clear treeview

+ + +
+
+ +

Remove the "Program Files" treenode

+ + +
+ + +
+ + +