diff --git a/bbtreeview.js b/bbtreeview.js index bdc8a3e..eb2a580 100644 --- a/bbtreeview.js +++ b/bbtreeview.js @@ -1,368 +1 @@ -/** - * BBTreeview - * @version v0.1.0.223 (2023/09/08 2027) - */ -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 - }, - 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; - - 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.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 += '
    '; - } - - html += '
    '; - 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; -}; +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},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=undefined,node=this.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.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+='
    '),html+='
    ',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}; \ No newline at end of file diff --git a/bbtreeview.min.css b/bbtreeview.min.css new file mode 100644 index 0000000..227ece5 --- /dev/null +++ b/bbtreeview.min.css @@ -0,0 +1,5 @@ +/** + * BBTreeview + * @version v0.1.0.223 (2023/09/08 2027) + */ + ul.bbtreeview{background-image:url(line.png);background-position:4px 8px;background-repeat:repeat-y;list-style:none;padding:0;margin:0 0 0 8px}ul.bbtreeview ul{background-image:url(line.png);background-position:4px 8px;background-repeat:repeat-y;list-style:none;margin:0 0 0 8px;padding:0}ul.bbtreeview li{background-position:0 calc((1.2em - 9px)/ 2);background-repeat:no-repeat;cursor:default;display:block;padding-left:14px;width:100%}ul.bbtreeview li.c{background-image:url(expand.png)}ul.bbtreeview li.e{background-image:url(collapse.png)}ul.bbtreeview li.hidden{display:none}ul.bbtreeview div.li{display:block;height:1.2em;padding-left:4px}ul.bbtreeview div.li.highlighted{background-color:rgb(169,201,249,.7)}ul.bbtreeview div.li>div.icon{background-position:0 center;background-repeat:no-repeat;display:inline-block;height:100%;width:calc(16px)}ul.bbtreeview div.li>div.folder{background-image:url(folder.png)}ul.bbtreeview li>div.li>div.checkbox{background-image:url(uncheckbox.png)}ul.bbtreeview li.x>div.li>div.checkbox{background-image:url(checkbox.png)}ul.bbtreeview div.li>span{-webkit-user-select:none;-ms-user-select:none;user-select:none;display:inline-block;height:1.2em;line-height:1.2em;overflow:hidden;padding-left:6px;text-overflow:ellipsis;vertical-align:top;white-space:nowrap} \ No newline at end of file diff --git a/bbtreeview.min.js b/bbtreeview.min.js new file mode 100644 index 0000000..6f1c112 --- /dev/null +++ b/bbtreeview.min.js @@ -0,0 +1,7 @@ +/** + * BBTreeview + * @version v0.1.0.223 (2023/09/08 2027) + */ +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},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=undefined,node=this.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.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+='
    '),html+='
    ',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;if(a.setCheckbox(a.Node,value),a.Node.querySelectorAll("li").forEach((function(e){a.setCheckbox(e,value)})),null!=a.GetParentNode()){let uncheckedCount=0;a.GetParentNode().querySelectorAll("li").forEach((function(e){e.classList.contains("x")||uncheckedCount++})),a.setCheckbox(a.GetParentNode(),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 index 46fcf68..2fb78e5 100644 --- a/bbtreeviewnode.js +++ b/bbtreeviewnode.js @@ -1,388 +1 @@ -/** - * BBTreeview - * @version v0.1.0.223 (2023/09/08 2027) - */ -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 - 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; - - 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 +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;if(a.setCheckbox(a.Node,value),a.Node.querySelectorAll("li").forEach((function(e){a.setCheckbox(e,value)})),null!=a.GetParentNode()){let uncheckedCount=0;a.GetParentNode().querySelectorAll("li").forEach((function(e){e.classList.contains("x")||uncheckedCount++})),a.setCheckbox(a.GetParentNode(),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/demo-test.html b/demo-test.html index a600979..2095022 100644 --- a/demo-test.html +++ b/demo-test.html @@ -7,12 +7,15 @@ - - + + - - - + + + + + + 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..bdc8a3e --- /dev/null +++ b/src/bbtreeview.js @@ -0,0 +1,368 @@ +/** + * BBTreeview + * @version v0.1.0.223 (2023/09/08 2027) + */ +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 + }, + 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; + + 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.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 += '
    '; + } + + html += '
    '; + 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/src/bbtreeviewnode.js b/src/bbtreeviewnode.js new file mode 100644 index 0000000..46fcf68 --- /dev/null +++ b/src/bbtreeviewnode.js @@ -0,0 +1,388 @@ +/** + * BBTreeview + * @version v0.1.0.223 (2023/09/08 2027) + */ +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 + 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; + + 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