From 43edb319d4139813256780d7be0f0d9de7fcf325 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 8 Jan 2024 21:41:43 +0000 Subject: [PATCH] Changed to using class --- bbtreeview.js | 392 ---------------- bbtreeview.min.js | 7 - bbtreeviewnode.js | 408 ----------------- build.bat | 17 + .../bbtreeview.min.css | 0 build/bbtreeview.min.js | 7 + bbtreeview.css => src/bbtreeview.css | 0 src/bbtreeview.js | 397 +++++++++++++++++ src/bbtreeviewnode.js | 418 ++++++++++++++++++ src/version.txt | 4 + 10 files changed, 843 insertions(+), 807 deletions(-) delete mode 100644 bbtreeview.js delete mode 100644 bbtreeview.min.js delete mode 100644 bbtreeviewnode.js create mode 100644 build.bat rename bbtreeview.min.css => build/bbtreeview.min.css (100%) create mode 100644 build/bbtreeview.min.js rename bbtreeview.css => src/bbtreeview.css (100%) create mode 100644 src/bbtreeview.js create mode 100644 src/bbtreeviewnode.js create mode 100644 src/version.txt diff --git a/bbtreeview.js b/bbtreeview.js deleted file mode 100644 index fa5bb92..0000000 --- a/bbtreeview.js +++ /dev/null @@ -1,392 +0,0 @@ -/** - * BBTreeview - * @version v0.1.1.006 (2023/09/27 2218) - */ -function BBTreeview(options) -{ - const a = this; - - a.initialise(options); -}; - -BBTreeview.prototype.AddItem = function(options) { - const a = this; - const _options = a.getOptions(options); - - // Don't add duplicate - if (a.Find(_options.ID) != null) { - return false; - } - - // Check parent exists - let parentNode = null; - if (_options.ParentID != null) { - parentNode = a.Find(_options.ParentID); - if (parentNode == null) { - return false; - } - } - - if (parentNode == null) { - parentNode = a.Container; - } else { - parentNode = parentNode.GetChildNode(); - } - - const nodeHtml = a.generateNodeHtml(_options); - - // Add node - a.appendHtml(parentNode, nodeHtml); - - const node = a.Find(_options.ID); - - // Setup events - node.SetupEvents(); - - return true; -}; - -BBTreeview.prototype.Remove = function(id) { - const a = this; - - const node = a.Find(id); - if (node == null) { - return false; - } - - node.Remove(); - - return true; -}; - -BBTreeview.prototype.Default = function() { - return { - TreeviewOptions: { - ID: null, - ShowCheckbox: false, - ShowSelection: true, - EnablePullUp: false, - ShowIcon: true - }, - TreeNodeOptions: { - ID: null, - ParentID: null, - Name: "", - Hint: "", - Value: "", - Icon: "folder", - Checked: false, - Tag: null - } - }; -}; - -BBTreeview.prototype.Clear = function() { - const a = this; - - a.initialise(a.Options); -}; - -BBTreeview.prototype.CollapseAll = function() { - const a = this; - - a.GetAllNodes().forEach(function(e) { - e.Collapse(); - }); -}; - -BBTreeview.prototype.ExpandAll = function() { - const a = this; - - a.GetAllNodes().forEach(function(e) { - e.Expand(); - }); -}; - -BBTreeview.prototype.CheckAll = function(value) { - const a = this; - - if (!a.Options.ShowCheckbox) { - return; - } - - a.GetAllNodes().forEach(function(e) { - e.Check(value); - }); -}; - -BBTreeview.prototype.Find = function(id) { - const a = this; - - if (a.Container == null){ - console.log("BBTreeview container not found"); - return; - } - - const node = a.Container.querySelectorAll("li[data-bbtv-id='" + id + "']"); - if (node.length <= 0) { - return null; - } - - let treenode = new BBTreeviewNode(this); - treenode.Load(node[0]); - - // console.log(treenode); - - return treenode; -}; - -BBTreeview.prototype.FindByName = function(value) { - const a = this; - - let response = []; - a.GetAllNodes().forEach(function(e) { - if (e.Name != value) { - return; - } - - response.push(e); - }); - - return response; -}; - -BBTreeview.prototype.FindByValue = function(value) { - const a = this; - - let response = []; - a.GetAllNodes().forEach(function(e) { - if (e.Value != value) { - return; - } - - response.push(e); - }); - - return response; -}; - -BBTreeview.prototype.GetAllNodes = function() { - const a = this; - - const node = a.Container.querySelectorAll("li"); - if (node.length <= 0) { - return []; - } - - let response = []; - node.forEach(function(e) { - const id = e.getAttribute("data-bbtv-id"); - if (a.isNullOrWhitespace(id)) { - return; - } - - const myNode = a.Find(id); - if (myNode == null) { - return; - } - - response.push(myNode); - }); - - return response; -}; - -BBTreeview.prototype.GetCheckedNodes = function() { - const a = this; - - let response = []; - a.GetAllNodes().forEach(function(e) { - if (!e.Checked) { - return; - } - - response.push(e); - }); - - return response; -}; - -BBTreeview.prototype.GetCheckedValues = function() { - const a = this; - - let response = []; - a.GetCheckedNodes().map(function(e) { - response.push(e.Value); - }); - - return response; -}; - - -BBTreeview.prototype.GetCheckedTags = function() { - const a = this; - - let response = []; - a.GetCheckedNodes().map(function(e) { - response.push(e.Tag); - }); - - return response; -}; - -BBTreeview.prototype.GetSelectedNode = function() { - const a = this; - - let response = null; - a.GetAllNodes().forEach(function(e) { - if (e.Highlighted) { - response = e; - - return false; - } - }); - - return response; -}; - -BBTreeview.prototype.initialise = function(options) { - var a = this; - - a.Options = Object.assign(a.Default().TreeviewOptions, options); - - a.Container = null; - - let treeview = document.getElementsByTagName("body")[0].querySelectorAll(a.Options.ID); - if (treeview.length <= 0) { - return; - } - - if (treeview[0] == null) { - return; - } - - a.Container = treeview[0]; - - a.Container.innerHTML = ""; - - a.Container = a.Container.querySelectorAll("ul.bbtreeview")[0]; -}; - -BBTreeview.prototype.appendHtml = function(el, html) { - let node = document.createElement('template'); - node.innerHTML = html; - - node = node.content.firstChild; - - el.appendChild(node); -}; - -BBTreeview.prototype.generateID = function() { - return "treeviewItem" + (Math.floor(Math.random() * 1000001) + 100).toString(); -}; - -BBTreeview.prototype.generateNodeHtml = function(options) { - const a = this; - - let tag = ""; - if (!a.isNullOrWhitespace(options.Tag)) { - tag = encodeURIComponent(JSON.stringify(options.Tag)); - } - - let html = '
  • '; - html += '
    ' - - if (a.Options.ShowCheckbox) { - html += '
    '; - } - - if (a.Options.ShowIcon) { - html += '
    '; - html += '' + options.Name + ''; - } else { - html += '' + options.Name + ''; - } - - html += '
    '; - html += ''; - html += '
  • '; - - return html; -}; - -BBTreeview.prototype.getNode = function(el) { - const a = this; - - let node = null; - if (a.isTag(el, "li")) { - node = el; - } else { - node = a.parentsUntilTagName(el, "li"); - } - - const id = node.getAttribute("data-bbtv-id"); - - if (a.isNullOrWhitespace(id)) { - return null; - } - - return a.Find(id); -}; - -BBTreeview.prototype.getOptions = function(options) { - const a = this; - - let _options = Object.assign(a.Default().TreeNodeOptions, options); - - if (_options.ID == null) { - _options.ID = a.generateID(); - } - - if (_options.Tag == null) { - _options.Tag = ""; - } - - return _options; -}; - -BBTreeview.prototype.isNullOrWhitespace = function(value) { - if (typeof (value) == "undefined") { - return true; - } - - if (value == null) { - return true; - } - - return (value.toString().trim().length <= 0); -}; - -BBTreeview.prototype.isTag = function(el, tagName) { - return (el.tagName.toLowerCase() == tagName); -}; - -BBTreeview.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; -}; diff --git a/bbtreeview.min.js b/bbtreeview.min.js deleted file mode 100644 index 2731a75..0000000 --- a/bbtreeview.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * BBTreeview - * @version v0.1.1.006 (2023/09/27 2218) - */ -function BBTreeview(options){const a=undefined;this.initialise(options)}BBTreeview.prototype.AddItem=function(options){const a=this,_options=a.getOptions(options);if(null!=a.Find(_options.ID))return!1;let parentNode=null;if(null!=_options.ParentID&&(parentNode=a.Find(_options.ParentID),null==parentNode))return!1;parentNode=null==parentNode?a.Container:parentNode.GetChildNode();const nodeHtml=a.generateNodeHtml(_options);a.appendHtml(parentNode,nodeHtml);const node=undefined;return a.Find(_options.ID).SetupEvents(),!0},BBTreeview.prototype.Remove=function(id){const a=undefined,node=this.Find(id);return null!=node&&(node.Remove(),!0)},BBTreeview.prototype.Default=function(){return{TreeviewOptions:{ID:null,ShowCheckbox:!1,ShowSelection:!0,EnablePullUp:!1,ShowIcon:!0},TreeNodeOptions:{ID:null,ParentID:null,Name:"",Hint:"",Value:"",Icon:"folder",Checked:!1,Tag:null}}},BBTreeview.prototype.Clear=function(){const a=this;a.initialise(a.Options)},BBTreeview.prototype.CollapseAll=function(){const a=undefined;this.GetAllNodes().forEach((function(e){e.Collapse()}))},BBTreeview.prototype.ExpandAll=function(){const a=undefined;this.GetAllNodes().forEach((function(e){e.Expand()}))},BBTreeview.prototype.CheckAll=function(value){const a=this;a.Options.ShowCheckbox&&a.GetAllNodes().forEach((function(e){e.Check(value)}))},BBTreeview.prototype.Find=function(id){const a=this;if(null==a.Container)return void console.log("BBTreeview container not found");const node=a.Container.querySelectorAll("li[data-bbtv-id='"+id+"']");if(node.length<=0)return null;let treenode=new BBTreeviewNode(this);return treenode.Load(node[0]),treenode},BBTreeview.prototype.FindByName=function(value){const a=undefined;let response=[];return this.GetAllNodes().forEach((function(e){e.Name==value&&response.push(e)})),response},BBTreeview.prototype.FindByValue=function(value){const a=undefined;let response=[];return this.GetAllNodes().forEach((function(e){e.Value==value&&response.push(e)})),response},BBTreeview.prototype.GetAllNodes=function(){const a=this,node=a.Container.querySelectorAll("li");if(node.length<=0)return[];let response=[];return node.forEach((function(e){const id=e.getAttribute("data-bbtv-id");if(a.isNullOrWhitespace(id))return;const myNode=a.Find(id);null!=myNode&&response.push(myNode)})),response},BBTreeview.prototype.GetCheckedNodes=function(){const a=undefined;let response=[];return this.GetAllNodes().forEach((function(e){e.Checked&&response.push(e)})),response},BBTreeview.prototype.GetCheckedValues=function(){const a=undefined;let response=[];return this.GetCheckedNodes().map((function(e){response.push(e.Value)})),response},BBTreeview.prototype.GetCheckedTags=function(){const a=undefined;let response=[];return this.GetCheckedNodes().map((function(e){response.push(e.Tag)})),response},BBTreeview.prototype.GetSelectedNode=function(){const a=undefined;let response=null;return this.GetAllNodes().forEach((function(e){if(e.Highlighted)return response=e,!1})),response},BBTreeview.prototype.initialise=function(options){var a=this;a.Options=Object.assign(a.Default().TreeviewOptions,options),a.Container=null;let treeview=document.getElementsByTagName("body")[0].querySelectorAll(a.Options.ID);treeview.length<=0||null!=treeview[0]&&(a.Container=treeview[0],a.Container.innerHTML='',a.Container=a.Container.querySelectorAll("ul.bbtreeview")[0])},BBTreeview.prototype.appendHtml=function(el,html){let node=document.createElement("template");node.innerHTML=html,node=node.content.firstChild,el.appendChild(node)},BBTreeview.prototype.generateID=function(){return"treeviewItem"+(Math.floor(1000001*Math.random())+100).toString()},BBTreeview.prototype.generateNodeHtml=function(options){const a=this;let tag="";a.isNullOrWhitespace(options.Tag)||(tag=encodeURIComponent(JSON.stringify(options.Tag)));let html='
  • ';return html+='
    ',a.Options.ShowCheckbox&&(html+='
    '),a.Options.ShowIcon?(html+='
    ',html+=''+options.Name+""):html+=''+options.Name+"",html+="
    ",html+="",html+="
  • ",html},BBTreeview.prototype.getNode=function(el){const a=this;let node=null;node=a.isTag(el,"li")?el:a.parentsUntilTagName(el,"li");const id=node.getAttribute("data-bbtv-id");return a.isNullOrWhitespace(id)?null:a.Find(id)},BBTreeview.prototype.getOptions=function(options){const a=this;let _options=Object.assign(a.Default().TreeNodeOptions,options);return null==_options.ID&&(_options.ID=a.generateID()),null==_options.Tag&&(_options.Tag=""),_options},BBTreeview.prototype.isNullOrWhitespace=function(value){return void 0===value||(null==value||value.toString().trim().length<=0)},BBTreeview.prototype.isTag=function(el,tagName){return el.tagName.toLowerCase()==tagName},BBTreeview.prototype.parentsUntilTagName=function(el,tagName){const a=this;let node=el;for(;void 0!==node.parentNode&&(node=node.parentNode,void 0!==node);){if(a.isTag(node,"ul")&&node.classList.contains("bbtreeview"))return null;if(a.isTag(node,tagName))break}return node}; - -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),a.Node.querySelectorAll("li").forEach((function(e){a.setCheckbox(e,value)}));let parentNode=a.GetParentNode();if(null!=parentNode)if(a.Treeview.Options.EnablePullUp)for(;;){const parentChecked=parentNode.querySelectorAll("li.x").length>0;if(a.setCheckbox(parentNode,parentChecked),parentNode=a.Treeview.getNode(parentNode),parentNode=parentNode.GetParentNode(),null==parentNode)break}else{let uncheckedCount=0;parentNode.querySelectorAll("li").forEach((function(e){e.classList.contains("x")||uncheckedCount++})),a.setCheckbox(parentNode,uncheckedCount<=0)}},BBTreeviewNode.prototype.Collapse=function(){const a=this;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;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");return void 0===checkboxes?null:checkboxes[0]},BBTreeviewNode.prototype.GetChildNode=function(){const a=undefined;let result=this.Node.querySelectorAll("ul");return result.length<=0?null:result[0]},BBTreeviewNode.prototype.GetChildNodes=function(){const a=undefined,childNode=this.GetChildNode();if(null==childNode)return[];let nodes=childNode.querySelectorAll("li");if(nodes.length<=0)return[];let result=[];return nodes.forEach((function(e){void 0!==e.parentNode&&e.parentNode==childNode&&result.push(e)})),result},BBTreeviewNode.prototype.GetTag=function(){const a=this;let tag=a.Node.getAttribute("data-bbtv-tag");return a.Treeview.isNullOrWhitespace(tag)?null:JSON.parse(decodeURIComponent(tag))},BBTreeviewNode.prototype.GetParentID=function(){const a=undefined,parentNode=this.GetParentNode();return null==parentNode?null: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;return!!a.Treeview.Options.ShowCheckbox&&a.Node.classList.contains("x")},BBTreeviewNode.prototype.IsExpanded=function(){const a=this;return!!a.Node.classList.contains("e")||!a.Node.classList.contains("c")&&null},BBTreeviewNode.prototype.IsHighlighted=function(){const a=undefined;return this.Container.classList.contains("highlighted")},BBTreeviewNode.prototype.Remove=function(){const a=this;null!=a.GetParentNode()&&(a.GetParentNode().classList.contains("e")&&a.GetParentNode().classList.remove("e"),a.GetParentNode().classList.contains("c")&&a.GetParentNode().classList.remove("c")),a.Node.parentNode.removeChild(a.Node)},BBTreeviewNode.prototype.SetupEvents=function(){const a=this;a.Node.addEventListener("click",(function(e){if(e.stopPropagation(),e.preventDefault(),!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);null!=myNode&&myNode.Toggle()})),a.Container.addEventListener("dblclick",(function(e){e.stopPropagation(),e.preventDefault();const myNode=a.Treeview.getNode(e.target);null!=myNode&&myNode.Toggle()})),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()})),a.GetCheckbox().addEventListener("dblclick",(function(e){e.stopPropagation(),e.preventDefault()}))),a.Container.addEventListener("mousedown",(function(e){e.stopPropagation(),e.preventDefault();const myNode=a.Treeview.getNode(e.target);null!=myNode&&(a.Treeview.Container.querySelectorAll("div.highlighted").forEach((function(e){e.classList.remove("highlighted")})),a.Treeview.Options.ShowSelection&&myNode.Container.classList.add("highlighted"))})),a.invalidateCollapsible()},BBTreeviewNode.prototype.Toggle=function(){const a=this;switch(a.IsExpanded()){case!0:a.Collapse();break;case!1:a.Expand()}},BBTreeviewNode.prototype.initialise=function(){const a=this},BBTreeviewNode.prototype.invalidateCollapsible=function(){const a=this;null!=a.GetParentNode()&&(a.GetParentNode().classList.contains("c")?a.Node.classList.add("hidden"):(a.GetParentNode().classList.contains("e")||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;for(;void 0!==node.parentNode&&(node=node.parentNode,void 0!==node);){if(a.isTag(node,"ul")&&node.classList.contains("bbtreeview"))return null;if(a.isTag(node,tagName))break}return node},BBTreeviewNode.prototype.setCheckbox=function(el,value){value?el.classList.contains("x")||el.classList.add("x"):el.classList.contains("x")&&el.classList.remove("x")}; \ No newline at end of file diff --git a/bbtreeviewnode.js b/bbtreeviewnode.js deleted file mode 100644 index 62c1916..0000000 --- a/bbtreeviewnode.js +++ /dev/null @@ -1,408 +0,0 @@ -/** - * 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"); - } - } -}; \ No newline at end of file diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..d19fa8a --- /dev/null +++ b/build.bat @@ -0,0 +1,17 @@ +del bbtreeview.min.js +del bbtreeview.min.tmp +del build/bbtreeview.min.js + +cd src + +type version.txt >> ../bbtreeview.min.js + +"C:\B\Portable Files (dev)\Google Closure Compiler\closure-compiler-v20231112.jar" --js *.js --js_output_file ../bbtreeview.min.tmp + +cd.. + +type bbtreeview.min.tmp >> bbtreeview.min.js + +move bbtreeview.min.js build/bbtreeview.min.js + +del bbtreeview.min.tmp \ No newline at end of file diff --git a/bbtreeview.min.css b/build/bbtreeview.min.css similarity index 100% rename from bbtreeview.min.css rename to build/bbtreeview.min.css diff --git a/build/bbtreeview.min.js b/build/bbtreeview.min.js new file mode 100644 index 0000000..1afd2a7 --- /dev/null +++ b/build/bbtreeview.min.js @@ -0,0 +1,7 @@ +/** + * BBTreeview + * @version v0.1.2.011 (2024/01/07 0208) + */ +class BBTreeview{constructor(e){this.initialiseComponents(e)}initialiseComponents(e){this.Options=Object.assign(this.DefaultOptions.Treeview,e)}get Container(){let e=document.getElementsByTagName("body");return e.length<=0?null:(e=e[0].querySelectorAll(this.Options.ID),e.length<=0||(e[0].innerHTML='',e[0].querySelectorAll("ul.bbtreeview"),e.length<=0)?void 0:e[0])}get DefaultOptions(){return{Treeview:{ID:null,ShowCheckbox:!1,ShowSelection:!0,EnablePullUp:!1,ShowIcon:!0},TreeNode:{ID:null,ParentID:null,Name:"",Hint:"",Value:"",Icon:"folder",Checked:!1,Tag:null}}}AddItem(e){const t=this,n=t.getOptions(e);if(null!=t.Find(n.ID))return!1;let l=null;if(null!=n.ParentID&&(l=t.Find(n.ParentID),null==l))return!1;if(l=null==l?t.Container:l.GetChildNode(),null==l)return!1;const i=t.generateNodeHtml(n);t.appendHtml(l,i);t.Find(n.ID);return!0}Remove(e){const t=this.Find(e);return null!=t&&(t.Remove(),!0)}Clear(){this.initialiseComponents(this.Options)}CollapseAll(){this.GetAllNodes().forEach((function(e){e.Collapse()}))}ExpandAll(){this.GetAllNodes().forEach((function(e){e.Expand()}))}CheckAll(e){this.Options.ShowCheckbox&&this.GetAllNodes().forEach((function(t){t.IsChecked=e}))}Find(e){if(null==this.Container)return void console.log("BBTreeview container not found");const t=this.Container.querySelectorAll("li[data-bbtv-id='"+e+"']");if(t.length<=0)return null;let n=new BBTreeviewNode(this);return n.Load(t[0]),n}FindByName(e){let t=[];return this.GetAllNodes().forEach((function(n){n.Name==e&&t.push(n)})),t}FindByValue(e){let t=[];return this.GetAllNodes().forEach((function(n){n.Value==e&&t.push(n)})),t}GetAllNodes(){const e=this,t=e.Container.querySelectorAll("li");if(t.length<=0)return[];let n=[];return t.forEach((function(t){const l=t.getAttribute("data-bbtv-id");if(e.isNullOrWhitespace(l))return;const i=e.Find(l);null!=i&&n.push(i)})),n}GetCheckedNodes(){let e=[];return this.GetAllNodes().forEach((function(t){t.Checked&&e.push(t)})),e}GetCheckedValues(){let e=[];return this.GetCheckedNodes().map((function(t){e.push(t.Value)})),e}GetCheckedTags(){let e=[];return this.GetCheckedNodes().map((function(t){e.push(t.Tag)})),e}GetSelectedNode(){let e=null;return this.GetAllNodes().forEach((function(t){if(t.Highlighted)return e=t,!1})),e}appendHtml(e,t){let n=document.createElement("template");n.innerHTML=t,n=n.content.firstChild,e.appendChild(n)}generateID(){return"treeviewItem"+(Math.floor(1000001*Math.random())+100).toString()}generateNodeHtml(e){const t=this;let n="";t.isNullOrWhitespace(e.Tag)||(n=encodeURIComponent(JSON.stringify(e.Tag)));let l='
  • ';return l+='
    ',t.Options.ShowCheckbox&&(l+='
    '),t.Options.ShowIcon?(l+='
    ',l+=''+e.Name+""):l+=''+e.Name+"",l+="
    ",l+="",l+="
  • ",l}getNode(e){const t=this;let n=null;n=t.isTag(e,"li")?e:t.parentsUntilTagName(e,"li");const l=n.getAttribute("data-bbtv-id");return t.isNullOrWhitespace(l)?null:t.Find(l)}getOptions(e){const t=this;let n=Object.assign(t.DefaultOptions.TreeNode,e);return null==n.ID&&(n.ID=t.generateID()),null==n.Tag&&(n.Tag=""),n}isNullOrWhitespace(e){return void 0===e||(null==e||e.toString().trim().length<=0)}isTag(e,t){return e.tagName.toLowerCase()==t}parentsUntilTagName(e,t){const n=this;let l=e;for(;void 0!==l.parentNode&&(l=l.parentNode,void 0!==l);){if(n.isTag(l,"ul")&&l.classList.contains("bbtreeview"))return null;if(n.isTag(l,t))break}return l}} + +class BBTreeviewNode{constructor(e){const t=this;t.Treeview=e,t.ID=null,t.Node=null,t.Container=null,t.Label=null,t.Value=null,t.Name="",t.Hint="",t.ParentID=null,t.IsChecked=!1,t.Highlighted=!1,t.Tag=null,t.initialiseComponents()}initialiseComponents(){}get IsChecked(){return!!this.Treeview.Options.ShowCheckbox&&this.Node.classList.contains("x")}set IsChecked(e){const t=this;t.setCheckbox(t.Node,e),t.Node.querySelectorAll("li").forEach((function(n){t.setCheckbox(n,e)}));let n=t.ParentNode;if(null!=n)if(t.Treeview.Options.EnablePullUp)for(;;){const e=n.querySelectorAll("li.x").length>0;if(t.setCheckbox(n,e),n=t.Treeview.getNode(n),n=n.GetParentNode(),null==n)break}else{let e=0;n.querySelectorAll("li").forEach((function(t){t.classList.contains("x")||e++})),t.setCheckbox(n,e<=0)}}get IsExpanded(){return!!this.Node.classList.contains("e")||!this.Node.classList.contains("c")&&null}get IsHighlighted(){return this.Container.classList.contains("highlighted")}get Tag(){let e=this.Node.getAttribute("data-bbtv-tag");return this.Treeview.isNullOrWhitespace(e)?null:JSON.parse(decodeURIComponent(e))}get ParentNodeID(){const e=this.ParentNode;return null==e?null:e.getAttribute("data-bbtv-id")}get ParentNode(){return this.parentsUntilTagName(this.Node,"li")}Load(e){const t=this;t.ID=e.getAttribute("data-bbtv-id"),t.Node=e,t.Container=e.querySelectorAll("div.li")[0],t.Label=e.querySelectorAll("span")[0],t.Value=e.getAttribute("data-bbtv-value"),t.Name=t.Label.textContent,t.Hint=t.Label.getAttribute("title"),t.ParentID=t.ParentNodeID,t.IsChecked=t.IsChecked,t.Highlighted=t.IsHighlighted,t.Tag=t.Tag,t.initialiseComponents_Events()}Collapse(){const e=this;e.Node.classList.contains("e")&&(e.Node.classList.remove("e"),e.Node.classList.add("c")),e.GetChildNodes().forEach((function(e){e.classList.add("hidden")}))}Expand(){const e=this;e.Node.classList.contains("c")&&(e.Node.classList.remove("c"),e.Node.classList.add("e")),e.GetChildNodes().forEach((function(e){e.classList.remove("hidden")}))}GetCheckbox(){if(!this.Treeview.Options.ShowCheckbox)return null;const e=this.Node.querySelectorAll("div.icon.checkbox");return void 0===e?null:e[0]}GetChildNode(){let e=this.Node.querySelectorAll("ul");return e.length<=0?null:e[0]}GetChildNodes(){const e=this.GetChildNode();if(null==e)return[];let t=e.querySelectorAll("li");if(t.length<=0)return[];let n=[];return t.forEach((function(t){void 0!==t.parentNode&&t.parentNode==e&&n.push(t)})),n}Remove(){const e=this;null!=e.ParentNode&&(e.ParentNode.classList.contains("e")&&e.ParentNode.classList.remove("e"),e.ParentNode.classList.contains("c")&&e.ParentNode.classList.remove("c")),e.Node.parentNode.removeChild(e.Node)}Toggle(){const e=this;switch(e.IsExpanded){case!0:e.Collapse();break;case!1:e.Expand()}}initialiseComponents_Events(){const e=this;e.Node.addEventListener("click",(function(t){if(t.stopPropagation(),t.preventDefault(),!e.isTag(t.target,"li"))return;if(t.offsetX<0||t.offsetX>16||t.offsetY<0||t.offsetY>16)return;const n=e.Treeview.getNode(t.target);null!=n&&n.Toggle()})),e.Container.addEventListener("dblclick",(function(t){t.stopPropagation(),t.preventDefault();const n=e.Treeview.getNode(t.target);null!=n&&n.Toggle()})),e.Treeview.Options.ShowCheckbox&&(e.GetCheckbox().addEventListener("mousedown",(function(t){t.stopPropagation(),t.preventDefault(),e.IsChecked=!e.IsChecked})),e.GetCheckbox().addEventListener("click",(function(e){e.stopPropagation(),e.preventDefault()})),e.GetCheckbox().addEventListener("dblclick",(function(e){e.stopPropagation(),e.preventDefault()}))),e.Container.addEventListener("mousedown",(function(t){t.stopPropagation(),t.preventDefault();const n=e.Treeview.getNode(t.target);null!=n&&(e.Treeview.Container.querySelectorAll("div.highlighted").forEach((function(e){e.classList.remove("highlighted")})),e.Treeview.Options.ShowSelection&&n.Container.classList.add("highlighted"))})),e.invalidateCollapsible()}invalidateCollapsible(){const e=this;null!=e.ParentNode&&(e.ParentNode.classList.contains("c")?e.Node.classList.add("hidden"):(e.ParentNode.classList.contains("e")||e.ParentNode.classList.add("e"),e.Node.classList.remove("hidden")))}isTag=function(e,t){return e.tagName.toLowerCase()==t};parentsUntilTagName(e,t){const n=this;let s=e;for(;void 0!==s.parentNode&&(s=s.parentNode,void 0!==s);){if(n.isTag(s,"ul")&&s.classList.contains("bbtreeview"))return null;if(n.isTag(s,t))break}return s}setCheckbox(e,t){t?e.classList.contains("x")||e.classList.add("x"):e.classList.contains("x")&&e.classList.remove("x")}} \ No newline at end of file diff --git a/bbtreeview.css b/src/bbtreeview.css similarity index 100% rename from bbtreeview.css rename to src/bbtreeview.css diff --git a/src/bbtreeview.js b/src/bbtreeview.js new file mode 100644 index 0000000..bbffd40 --- /dev/null +++ b/src/bbtreeview.js @@ -0,0 +1,397 @@ +class BBTreeview { + constructor(options) { + const a = this; + + a.initialiseComponents(options); + } + + + initialiseComponents(options) { + var a = this; + + a.Options = Object.assign(a.DefaultOptions.Treeview, options); + } + + + get Container() { + const a = this; + + let result = document.getElementsByTagName("body"); + if (result.length <= 0) { + return null; + } + + result = result[0].querySelectorAll(a.Options.ID); + if (result.length <= 0) { + return; + } + + result[0].innerHTML = ""; + + result[0].querySelectorAll("ul.bbtreeview"); + if (result.length <= 0) { + return; + } + + return result[0]; + } + + get DefaultOptions() { + return { + Treeview: { + ID: null, + ShowCheckbox: false, + ShowSelection: true, + EnablePullUp: false, + ShowIcon: true + }, + TreeNode: { + ID: null, + ParentID: null, + Name: "", + Hint: "", + Value: "", + Icon: "folder", + Checked: false, + Tag: null + } + }; + } + + AddItem(options) { + const a = this; + const _options = a.getOptions(options); + + // Don't add duplicate + if (a.Find(_options.ID) != null) { + return false; + } + + // Check parent exists + let parentNode = null; + if (_options.ParentID != null) { + parentNode = a.Find(_options.ParentID); + if (parentNode == null) { + return false; + } + } + + if (parentNode == null) { + parentNode = a.Container; + } else { + parentNode = parentNode.GetChildNode(); + } + + if (parentNode == null) { + return false; + } + + const nodeHtml = a.generateNodeHtml(_options); + + // Add node + a.appendHtml(parentNode, nodeHtml); + + const node = a.Find(_options.ID); + + return true; + } + + Remove(id) { + const a = this; + + const node = a.Find(id); + if (node == null) { + return false; + } + + node.Remove(); + + return true; + } + + Clear() { + const a = this; + + a.initialiseComponents(a.Options); + } + + CollapseAll() { + const a = this; + + a.GetAllNodes().forEach(function(e) { + e.Collapse(); + }); + } + + ExpandAll() { + const a = this; + + a.GetAllNodes().forEach(function(e) { + e.Expand(); + }); + } + + CheckAll(value) { + const a = this; + + if (!a.Options.ShowCheckbox) { + return; + } + + a.GetAllNodes().forEach(function(e) { + e.IsChecked = value; + }); + } + + Find(id) { + const a = this; + + if (a.Container == null){ + console.log("BBTreeview container not found"); + return; + } + + const node = a.Container.querySelectorAll("li[data-bbtv-id='" + id + "']"); + if (node.length <= 0) { + return null; + } + + let treenode = new BBTreeviewNode(this); + treenode.Load(node[0]); + + return treenode; + } + + FindByName(value) { + const a = this; + + let response = []; + a.GetAllNodes().forEach(function(e) { + if (e.Name != value) { + return; + } + + response.push(e); + }); + + return response; + } + + FindByValue(value) { + const a = this; + + let response = []; + a.GetAllNodes().forEach(function(e) { + if (e.Value != value) { + return; + } + + response.push(e); + }); + + return response; + } + + GetAllNodes() { + const a = this; + + const node = a.Container.querySelectorAll("li"); + if (node.length <= 0) { + return []; + } + + let response = []; + node.forEach(function(e) { + const id = e.getAttribute("data-bbtv-id"); + if (a.isNullOrWhitespace(id)) { + return; + } + + const myNode = a.Find(id); + if (myNode == null) { + return; + } + + response.push(myNode); + }); + + return response; + } + + GetCheckedNodes() { + const a = this; + + let response = []; + a.GetAllNodes().forEach(function(e) { + if (!e.Checked) { + return; + } + + response.push(e); + }); + + return response; + } + + GetCheckedValues() { + const a = this; + + let response = []; + a.GetCheckedNodes().map(function(e) { + response.push(e.Value); + }); + + return response; + } + + + GetCheckedTags() { + const a = this; + + let response = []; + a.GetCheckedNodes().map(function(e) { + response.push(e.Tag); + }); + + return response; + } + + GetSelectedNode() { + const a = this; + + let response = null; + a.GetAllNodes().forEach(function(e) { + if (e.Highlighted) { + response = e; + + return false; + } + }); + + return response; + } + + appendHtml(el, html) { + let node = document.createElement('template'); + node.innerHTML = html; + + node = node.content.firstChild; + + el.appendChild(node); + } + + generateID() { + return "treeviewItem" + (Math.floor(Math.random() * 1000001) + 100).toString(); + } + + generateNodeHtml(options) { + const a = this; + + let tag = ""; + if (!a.isNullOrWhitespace(options.Tag)) { + tag = encodeURIComponent(JSON.stringify(options.Tag)); + } + + let html = '
  • '; + html += '
    ' + + if (a.Options.ShowCheckbox) { + html += '
    '; + } + + if (a.Options.ShowIcon) { + html += '
    '; + html += '' + options.Name + ''; + } else { + html += '' + options.Name + ''; + } + + html += '
    '; + html += ''; + html += '
  • '; + + return html; + } + + getNode(el) { + const a = this; + + let node = null; + if (a.isTag(el, "li")) { + node = el; + } else { + node = a.parentsUntilTagName(el, "li"); + } + + const id = node.getAttribute("data-bbtv-id"); + + if (a.isNullOrWhitespace(id)) { + return null; + } + + return a.Find(id); + } + + getOptions(options) { + const a = this; + + let _options = Object.assign(a.DefaultOptions.TreeNode, options); + + if (_options.ID == null) { + _options.ID = a.generateID(); + } + + if (_options.Tag == null) { + _options.Tag = ""; + } + + return _options; + } + + isNullOrWhitespace(value) { + if (typeof (value) == "undefined") { + return true; + } + + if (value == null) { + return true; + } + + return (value.toString().trim().length <= 0); + } + + isTag(el, tagName) { + return (el.tagName.toLowerCase() == tagName); + } + + parentsUntilTagName(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; + } + +} \ No newline at end of file diff --git a/src/bbtreeviewnode.js b/src/bbtreeviewnode.js new file mode 100644 index 0000000..ae01e68 --- /dev/null +++ b/src/bbtreeviewnode.js @@ -0,0 +1,418 @@ +class BBTreeviewNode { + constructor(treeview) { + const a = this; + + a.Treeview = treeview; + + a.ID = null; + a.Node = null; + + a.Container = null; + a.Label = null; + a.Value = null; + + a.Name = ""; + a.Hint = ""; + + a.ParentID = null; + a.IsChecked = false; + a.Highlighted = false; + a.Tag = null; + + a.initialiseComponents(); + } + + + initialiseComponents() { + const a = this; + } + + + get IsChecked() { + const a = this; + + if (!a.Treeview.Options.ShowCheckbox) { + return false; + } + + return a.Node.classList.contains("x"); + } + + set IsChecked(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.ParentNode; + 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)); + } + } + + get IsExpanded() { + const a = this; + + if (a.Node.classList.contains("e")) { + return true; + } + + if (a.Node.classList.contains("c")) { + return false; + } + + return null; + } + + get IsHighlighted() { + const a = this; + + return (a.Container.classList.contains("highlighted")); + } + + get Tag() { + const a = this; + + let tag = a.Node.getAttribute("data-bbtv-tag"); + if (a.Treeview.isNullOrWhitespace(tag)) { + return null; + } + + return JSON.parse(decodeURIComponent(tag)); + } + + get ParentNodeID() { + const a = this; + + const parentNode = a.ParentNode; + if (parentNode == null) { + return null; + } + + return parentNode.getAttribute("data-bbtv-id"); + } + + get ParentNode() { + const a = this; + + return a.parentsUntilTagName(a.Node, "li"); + } + + + Load(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.ParentNodeID; + a.IsChecked = a.IsChecked; + a.Highlighted = a.IsHighlighted; + a.Tag = a.Tag; + + a.initialiseComponents_Events(); + } + + Collapse() { + 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"); + }); + } + + Expand() { + 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"); + }); + } + + GetCheckbox() { + 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]; + } + + GetChildNode() { + const a = this; + + let result = a.Node.querySelectorAll("ul"); + if (result.length <= 0) { + return null; + } + + return result[0]; + } + + GetChildNodes() { + 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; + } + + Remove() { + const a = this; + + if (a.ParentNode != null) { + if (a.ParentNode.classList.contains("e")) { + a.ParentNode.classList.remove("e"); + } + + if (a.ParentNode.classList.contains("c")) { + a.ParentNode.classList.remove("c"); + } + } + + a.Node.parentNode.removeChild(a.Node); + } + + Toggle() { + const a = this; + + switch (a.IsExpanded) { + case true: + a.Collapse(); + break; + case false: + a.Expand(); + break; + default: break; + } + } + + + initialiseComponents_Events() { + 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.IsChecked = !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(); + } + + invalidateCollapsible() { + const a = this; + + // Invalidate state + if (a.ParentNode == null) { + return; + } + + if (a.ParentNode.classList.contains("c")) { + a.Node.classList.add("hidden"); + } else if (a.ParentNode.classList.contains("e")) { + a.Node.classList.remove("hidden"); + } else { + a.ParentNode.classList.add("e"); + a.Node.classList.remove("hidden"); + } + } + + isTag = function(el, tagName) { + return (el.tagName.toLowerCase() == tagName); + } + + parentsUntilTagName(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; + } + + setCheckbox(el, value) { + if (value) { + if (!el.classList.contains("x")) { + el.classList.add("x"); + } + } else { + if (el.classList.contains("x")) { + el.classList.remove("x"); + } + } + } + +} \ No newline at end of file diff --git a/src/version.txt b/src/version.txt new file mode 100644 index 0000000..2b80535 --- /dev/null +++ b/src/version.txt @@ -0,0 +1,4 @@ +/** + * BBTreeview + * @version v0.1.2.011 (2024/01/07 0208) + */