405 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			405 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| class BBTreeviewNode {
 | |
|   constructor(treeview, node) {
 | |
|     this.Treeview = treeview;
 | |
|     this.Node = node;
 | |
| 
 | |
|     // this.initialiseComponents();
 | |
|   }
 | |
| 
 | |
|   // initialiseComponents() {
 | |
|   //   const a = this;
 | |
| 
 | |
|   // }
 | |
| 
 | |
| 
 | |
|   get Checkbox() {
 | |
|     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];
 | |
|   }
 | |
| 
 | |
|   get ChildNode() {
 | |
|     const a = this;
 | |
| 
 | |
|     let result = a.Node.querySelectorAll("ul");
 | |
|     if (result.length <= 0) {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     return result[0];
 | |
|   }
 | |
| 
 | |
|   get ChildNodes() {
 | |
|     const a = this;
 | |
| 
 | |
|     const childNode = a.ChildNode;
 | |
|     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;
 | |
|   }
 | |
| 
 | |
|   get IsChecked() {
 | |
|     const a = this;
 | |
| 
 | |
|     if (!a.Treeview.Options.ShowCheckbox) {
 | |
|       return false;
 | |
|     }
 | |
| 
 | |
|     return a.Node.classList.contains("x");
 | |
|   }
 | |
| 
 | |
|   get Container() {
 | |
|     return this.Node.querySelectorAll("div.li")[0];
 | |
|   }
 | |
| 
 | |
|   get Hint() {
 | |
|     return this.Label.getAttribute("title");
 | |
|   }
 | |
| 
 | |
|   get ID() {
 | |
|     return this.Node.getAttribute("data-bbtv-id");
 | |
|   }
 | |
| 
 | |
|   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 Label() {
 | |
|     return this.Node.querySelectorAll("span")[0];
 | |
|   }
 | |
| 
 | |
|   get Name() {
 | |
|     return this.Label.textContent;
 | |
|   }
 | |
| 
 | |
|   get ParentID() {
 | |
|     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");
 | |
|   }
 | |
| 
 | |
|   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 Value() {
 | |
|     return this.Node.getAttribute("data-bbtv-value");
 | |
|   }
 | |
| 
 | |
| 
 | |
|   Check(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.ParentNode;
 | |
| 
 | |
|         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));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Collapse() {
 | |
|     const a = this;
 | |
| 
 | |
|     if (a.Node.classList.contains("e")) {
 | |
|       a.Node.classList.remove("e");
 | |
|       a.Node.classList.add("c");
 | |
|     }
 | |
| 
 | |
|     a.ChildNodes.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.ChildNodes.forEach(function(e) {
 | |
|       e.classList.remove("hidden");
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   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);
 | |
|   }
 | |
| 
 | |
|   InvalidateEvents() {
 | |
|     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.Checkbox.addEventListener("mousedown", function(e){
 | |
|         e.stopPropagation();
 | |
|         e.preventDefault();
 | |
| 
 | |
|         a.Check(!a.IsChecked);
 | |
|       });
 | |
| 
 | |
|       a.Checkbox.addEventListener("click", function(e){
 | |
|         e.stopPropagation();
 | |
|         e.preventDefault();
 | |
| 
 | |
|         // do nothing
 | |
|       });
 | |
| 
 | |
|       a.Checkbox.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();
 | |
|   }
 | |
| 
 | |
|   Toggle() {
 | |
|     const a = this;
 | |
| 
 | |
|     switch (a.IsExpanded) {
 | |
|       case true:
 | |
|         a.Collapse();
 | |
|         break;
 | |
|       case false:
 | |
|         a.Expand();
 | |
|         break;
 | |
|       default: break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| 
 | |
|   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(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");
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
| } | 
