From 7ee7cf4a1d48b01b98587055d5a7a39ec07bf511 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 10 Sep 2023 02:06:33 +0100 Subject: [PATCH] Initial commit --- bbtreeview.css | 72 +++++++++ bbtreeview.js | 386 +++++++++++++++++++++++++++++++++++++++++++++++ collapse.png | Bin 0 -> 185 bytes demo-test.html | 78 ++++++++++ expand.png | Bin 0 -> 199 bytes folder.png | Bin 0 -> 322 bytes line.png | Bin 0 -> 125 bytes src/collapse.png | Bin 0 -> 210 bytes src/expand.png | Bin 0 -> 232 bytes src/folder.svg | 44 ++++++ src/icon.svg | 62 ++++++++ 11 files changed, 642 insertions(+) create mode 100644 bbtreeview.css create mode 100644 bbtreeview.js create mode 100644 collapse.png create mode 100644 demo-test.html create mode 100644 expand.png create mode 100644 folder.png create mode 100644 line.png create mode 100644 src/collapse.png create mode 100644 src/expand.png create mode 100644 src/folder.svg create mode 100644 src/icon.svg diff --git a/bbtreeview.css b/bbtreeview.css new file mode 100644 index 0000000..7cd4bd9 --- /dev/null +++ b/bbtreeview.css @@ -0,0 +1,72 @@ +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: 0px 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, 0.7); +} +ul.bbtreeview div.li > div.icon { + background-position: 0px 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("folder.png"); +} +ul.bbtreeview li.x > div.li > div.checkbox { + background-image: url("folder.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.js b/bbtreeview.js new file mode 100644 index 0000000..686759e --- /dev/null +++ b/bbtreeview.js @@ -0,0 +1,386 @@ +/** + * 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.ChildNode; + } + + const nodeHtml = a.generateNodeHtml(_options); + + // Add node + a.appendHtml(parentNode, nodeHtml); + + const node = a.Find(_options.ID); + + // Events + node.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.getNode(e.target); + if (myNode == null) { + return; + } + + a.Toggle(myNode); + }); + + // node.Label.addEventListener("click", function(e){ + // e.stopPropagation(); + // e.preventDefault(); + + // }); + + // Highlighting + node.Container.addEventListener("mousedown", function(e){ + e.stopPropagation(); + e.preventDefault(); + + const myNode = a.getNode(e.target); + if (myNode == null) { + return; + } + + a.Container.querySelectorAll("div.highlighted").forEach(function(e) { + e.classList.remove("highlighted"); + }); + + myNode.Container.classList.add("highlighted"); + }); + + // Toggle + node.Container.addEventListener("dblclick", function(e){ + e.stopPropagation(); + e.preventDefault(); + + const myNode = a.getNode(e.target); + if (myNode == null) { + return; + } + + a.Toggle(myNode); + }); + + // Invalidate state + if (node.ParentNode != null) { + if (node.ParentNode.classList.contains("c")) { + node.Node.classList.add("hidden"); + } else if (node.ParentNode.classList.contains("e")) { + node.Node.classList.remove("hidden"); + } else { + node.ParentNode.classList.add("e"); + node.Node.classList.remove("hidden"); + } + } + + return true; +}; + +BBTreeview.prototype.Remove = function(id) { + const a = this; + + const node = a.Find(id); + if (node == null) { + return false; + } + + node.Node.parentNode.removeChild(node.Node); + + if (node.ParentNode != null) { + if (node.ParentNode.classList.contains("e")) { + node.ParentNode.classList.remove("e"); + } + + if (node.ParentNode.classList.contains("c")) { + node.ParentNode.classList.remove("c"); + } + } + + return true; +}; + + +BBTreeview.prototype.Default = function() { + return { + TreeviewOptions: { + ID: null, + ShowCheckbox: false + }, + TreeNodeOptions: { + ID: null, + ParentID: null, + Name: "", + Hint: "", + Icon: "folder", + Checked: false + } + }; +}; + + +BBTreeview.prototype.CollapseNode = function(node) { + const a = this; + + node.Node.classList.remove("e"); + node.Node.classList.add("c"); + + node.Items.forEach(function(e) { + e.classList.add("hidden"); + }); +}; + +BBTreeview.prototype.ExpandNode = function(node) { + const a = this; + + node.Node.classList.remove("c"); + node.Node.classList.add("e"); + + node.Items.forEach(function(e) { + e.classList.remove("hidden"); + }); +}; + +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 response = { + ID: id, + Node: node[0], + ParentNode: a.getParentNode(node[0]), + ChildNode: a.getChildNode(node[0]), + Container: node[0].querySelectorAll("div.li")[0], + Label: node[0].querySelectorAll("span")[0], + Items: a.getChildren(node[0]) + }; + + // console.log(response); + + return response; +}; +BBTreeview.prototype.Toggle = function(node) { + const a = this; + + if (node.Node.classList.contains("c")) { + a.ExpandNode(node); + } else if (node.Node.classList.contains("e")) { + a.CollapseNode(node); + } else { + // do nothing + } +}; + + +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 html = '
  • '; + html += '
    ' + + if (a.Options.ShowCheckbox) { + html += '
    '; + } + + html += '
    '; + html += '' + options.Name + ''; + html += '
    '; + html += ''; + html += '
  • '; + + return html; +}; + +BBTreeview.prototype.getChildNode = function(node) { + const a = this; + + let result = node.querySelectorAll("ul"); + if (result.length <= 0) { + return null; + } + + return result[0]; +}; + +BBTreeview.prototype.getChildren = function(node) { + const a = this; + + const childNode = a.getChildNode(node); + 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; +}; + +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(); + } + + return _options; +}; + +BBTreeview.prototype.getParentNode = function(node) { + const a = this; + + return a.parentsUntilTagName(node, "li"); +}; + +BBTreeview.prototype.isNullOrWhitespace = function(value) { + if (typeof (value) == "undefined") { + return true; + } + + if (value == null) { + return true; + } + + return (value.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) { + 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/collapse.png b/collapse.png new file mode 100644 index 0000000000000000000000000000000000000000..d8328c39a45ec05308f982efbee87006327b0937 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4?3?zm2ODh8@#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI66}TXMsm# zF#`kNArNL1)$nQn3aWd$IEF}EPEHUJ5eZ2!C@d^AOyFRg#Asl&*G84Wm1U8eb3i}< ZBZHzM*EO$=bs<1444$rjF6*2UngAnZG_n8y literal 0 HcmV?d00001 diff --git a/demo-test.html b/demo-test.html new file mode 100644 index 0000000..c27ac33 --- /dev/null +++ b/demo-test.html @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + +
    + + + + + + + \ No newline at end of file diff --git a/expand.png b/expand.png new file mode 100644 index 0000000000000000000000000000000000000000..72f77673d71288cf01f3f535c86b9a89891cf74f GIT binary patch literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4?3?zm2ODh8@#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6-k0X`wFXV0Epvu4e?bLUpATJ`_`|CK9O=H})~Nl6tH6euYvF*7r-UcI`d zzU(tlJ!gSOWHAE+-yslY6xHx*01E1Ox;TbNTux395fKSVFeof6G)&+q^ep6Ln53$( nsW_E;4zF1Iii=`ESq26>Kkm1NTc*zf>SOS9^>bP0l+XkKT>&~= literal 0 HcmV?d00001 diff --git a/folder.png b/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..8527862cf8e4e872637387de11b4c82e151fbf6d GIT binary patch literal 322 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1en@VcjqV~B-+@&XZqeO3<>51%-(rQzX!`_vT@ z9Dn|wKX5@YZR29DQ^z?a;^%+ab^OpV{qqM`A7Bwp{_**z5jlR|HgZoyB0Alcv(Jk=Kr*0a|Vuo zfBzo)@c1(Gfi6|G&Dujh7jm9{fIjn`(sh<}({61~E&x@h)g$ zjF@a>_~7{R-~a#p`S+vYVM%xNb!1@J z*w6hZkrl}2EbxddW?8eR=RK_O2U#}J9|A{9u3;Thx N44$rjF6*2Ung9~g97O;C literal 0 HcmV?d00001 diff --git a/src/collapse.png b/src/collapse.png new file mode 100644 index 0000000000000000000000000000000000000000..9307b79d1f608d5e82db1187e755032cc30502b1 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{!3Opi<85sBugD~Uq{1qucLCF%= zh?3y^w370~qEv?R@^Zb*yzJuS#DY}4{G#;P?`))iisC(89780gwoW+6+2A0+te!Q~ zERpxu_SS~dpPPAm zSsxT?tHa1`i*WFvci&0~*!k56JCT5^j44$rjF6*2UngFKl BNpJuF literal 0 HcmV?d00001 diff --git a/src/expand.png b/src/expand.png new file mode 100644 index 0000000000000000000000000000000000000000..8d92b45e2386e54cf45db3037b86df56d355b4cc GIT binary patch literal 232 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{!3Opi<85sBugD~Uq{1qucLCF%= zh?3y^w370~qEv?R@^Zb*yzJuS#DY}4{G#;P?`))iib_3Q9780gmQFaxc_=`@<-W?d z1jcDkOiekiE%@Fb%2TmTCEruhD(=(6%|{wjr_a0@8F6!;_pC`Z8WT*^DwC>LCh^}s z&9LG_zm&xro%z}qXQw^jmDz4*{_w)gbXlvo8Gm Z!tAZ6Y{q$@&<*GS22WQ%mvv4FO#ta(Q| + + + + + diff --git a/src/icon.svg b/src/icon.svg new file mode 100644 index 0000000..852332a --- /dev/null +++ b/src/icon.svg @@ -0,0 +1,62 @@ + + + + + + +