📄 tree-node.js
字号:
} if(tmp){ var attrVal = tmp.replace(/'/g, "\\'"); // FIXME javascript code is broken here content.push(" " + attrName + "='" + attrVal + "'"); } } content.push(">"); // for backward compatibility - put node content inside <span class="label"></span> if(this.config.tree.config.prevCompatible){ content.push("<span class='label'>"); } if(this.data.label){ content.push(this.data.label); } if(this.config.tree.config.prevCompatible){ content.push("</span>"); } content.push("</td></tr></tbody></table></div>"); if(this.data.isSelected){ this.select(); } if(this.hasSubtree()){ content.push("<div class='tree' id='"); content.push("zpTree"); content.push(this.config.tree.id); content.push("Node"); content.push(this.id); content.push("ChildrenContainer"); content.push("'"); content.push("></div>"); // class='tree tree-lined' } this.fireEvent("afterCreate"); return content.join("");};/** * Determine if this node has subtree. * @return true if node has subtree, false - in other case * @type boolean */Zapatec.Tree.Node.prototype.hasSubtree = function(){ return this.data.children != null;};/** * @private * Actually some heavy work on creating element - getting references to its elements, putting icons etc. * This method is called only when node is shown. */Zapatec.Tree.Node.prototype.afterCreate = function(){ if(this.isCreated){ return false; } this.labelContainer = document.getElementById(this.labelContainerId); if( this.data.collapsedIcon || this.data.expandedIcon || this.data.fetchingIcon || this.data.elementIcon ){ this.iconElement = this.labelContainer.childNodes[0].childNodes[0].childNodes[0].childNodes[1]; } if(this.hasSubtree()){ this.signElement = this.iconElement ? this.iconElement.previousSibling : this.labelContainer.childNodes[0].childNodes[0].childNodes[0].childNodes[0]; this.childrenContainer = this.labelContainer.nextSibling; } if(this.config.tree.config.putBackReferences && this.getLinkToLabelElement()){ Zapatec.Utils.createProperty(this.labelElement, "zpTreeNode", this); } if( this.data.collapsedIcon || this.data.expandedIcon || this.data.fetchingIcon || this.data.elementIcon ){ if(this.iconElement && this.iconElement.childNodes.length != 0){ var tmp = [ this.iconElement.childNodes[0], this.iconElement.childNodes[1], this.iconElement.childNodes[2] ]; if(this.hasSubtree()){ for(var ii = 0; ii < 2; ii++){ var tmpIcon = tmp[ii]; if(!tmpIcon){ continue; } if(tmpIcon.className.indexOf("collapsedIcon") >= 0){ this.collapsedIcon = tmpIcon; } else if(tmpIcon.className.indexOf("expandedIcon") >= 0){ this.expandedIcon = tmpIcon; } else if(tmpIcon.className.indexOf("fetchingIcon") >= 0){ this.fetchingIcon = tmpIcon; } } } else { this.elementIcon = tmp[0]; } this.putIcons(); } } this.isCreated = true; this.putLines(); if(this.data.isExpanded || this.config.tree.expandToLevelNum > this.config.level){ this.expand(); } else { this.collapse(); } if(this.config.tree.config.putCheckboxes){ var tmp = this.labelContainer.childNodes[0].childNodes[0].childNodes[0]; this.checkboxContainer = tmp.childNodes[tmp.childNodes.length - 2]; } if(this.data.isSelected){ this.select(); } if(this.config.tree.config.createWholeDOM){ this.createChildren(); }};Zapatec.Tree.Node.prototype.getLinkToLabelElement = function(){ if(this.config.isRootNode){ return null; } if(this.labelElement){ return this.labelElement; } this.labelElement = this.labelContainer.childNodes[0].childNodes[0].childNodes[0].lastChild; return this.labelElement;};/** * @private * Create childnodes for this branch */Zapatec.Tree.Node.prototype.createChildren = function(){ if( !this.hasSubtree() || this.hasSubtree() && this.isChildrenCreated == true ){ return null; } // if this tree has "quick" option or this is root node - then child nodes are not created yet if(this.config.tree.config.quick || this.config.isRootNode){ this.initChildren(); } var content = []; // create all nodes for(var ii = 0; ii < this.children.length; ii++){ content.push(this.children[ii].create()); } // add HTML to child container Zapatec.Transport.setInnerHtml({html: content.join(""), container: this.childrenContainer}); // put flag this.isChildrenCreated = true; if(this.config.tree.config.createWholeDOM){ for(var ii = 0; ii < this.children.length; ii++){ this.children[ii].afterCreate(); } }};/** * @private init child nodes - create Zapatec.Tree.Node instances for each record * in this.data.children and store this instances into this.children */Zapatec.Tree.Node.prototype.initChildren = function(){ if(!this.data.children){ return null; } for(var ii = 0; ii < this.data.children.length; ii++){ this.children.push(new Zapatec.Tree.Node({ tree: this.config.tree, parentNode: this, level: this.config.level + 1, source: this.data.children[ii], sourceType: "json", eventListeners: this.config.eventListeners })); }};/** * Determine if this is first node in parent branch * @return true is this node is first node in parent branch, false otherwise * @type boolean */Zapatec.Tree.Node.prototype.isFirstNodeInBranch = function(){ return this.config.isRootNode || this.labelContainer.parentNode.firstChild == this.labelContainer;};/** * Determine if this is LAST node in parent branch * @return true is this node is last node in parent branch, false otherwise * @type boolean */Zapatec.Tree.Node.prototype.isLastNodeInBranch = function(){ return this.config.isRootNode || this.labelContainer.parentNode.lastChild == this.labelContainer || this.labelContainer.parentNode.lastChild == this.childrenContainer;};/** * Function to control checkbox state. * @param value [boolean] if true - turn checkbox on. false - turn checkbox off. */Zapatec.Tree.Node.prototype.checkboxChanged = function(value){ if(typeof(value) == 'undefined'){ value = !this.data.isChecked; } this.data.isChecked = value; if(this.isCreated){ this.checkboxContainer.className = "checkboxContainer " + (this.data.isChecked ? "checkboxChecked" : "checkboxUnchecked"); } if(this.hasSubtree() && this.config.tree.config.dependantCheckboxes){ // turn on/off all child nodes var toCheck = this.data.isChecked; for(var ii = 0; ii < this.children.length; ii++){ this.children[ii].checkboxChanged(toCheck); } } if(this.config.parentNode && !this.config.parentNode.config.isRootNode){ this.config.parentNode.updateCheckbox(); }};/** * @private * helper function to mark dependant checkboxes. */Zapatec.Tree.Node.prototype.updateCheckbox = function(){ if(this.config.isRootNode){ return; } if(!this.config.tree.config.dependantCheckboxes){ return; } var stats = this.getChildrenStats(); if(stats.hasChecked && !stats.hasUnchecked){ // if all child nodes are checked this.data.isChecked = true; if(this.isCreated){ this.checkboxContainer.className = "checkboxContainer checkboxChecked"; } } else if(stats.hasChecked && stats.hasUnchecked){ // has either checked or unchecked this.data.isChecked = null; if(this.isCreated){ this.checkboxContainer.className = "checkboxContainer checkboxHalfChecked"; } } else if(!stats.hasChecked && stats.hasUnchecked){ // if all children are unchecked this.data.isChecked = false; if(this.isCreated){ this.checkboxContainer.className = "checkboxContainer checkboxUnchecked"; } } if(this.config.parentNode && !this.config.parentNode.config.isRootNode){ this.config.parentNode.updateCheckbox(); }};/** * @private * Helper function to determine node checked state. * @return returns object with 2 keys: * hasChecked: if true - node has at least one checked subnode or it is * checked itself (if it has no subchildren) * hasUnchecked: if true - node has at least one unchecked subnode or it is * unchecked itself (if it has no subchildren) * @type Object */Zapatec.Tree.Node.prototype.getChildrenStats = function(){ var res = { hasChecked: false, hasUnchecked: false } if(this.hasSubtree() && this.data.children.length > 0){ for(var ii = 0; ii < this.children.length; ii++){ var stats = this.children[ii].getChildrenStats(); res.hasChecked = res.hasChecked || stats.hasChecked; res.hasUnchecked = res.hasUnchecked || stats.hasUnchecked; if(res.hasChecked && res.hasUnchecked){ break; } } } else { res.hasChecked = this.data.isChecked; res.hasUnchecked = !this.data.isChecked; } return res;}/** * @private * Put classes to node to display tree lines correctly */Zapatec.Tree.Node.prototype.putLines = function(){ if(this.config.isRootNode){ return null; } // remove all tree lines this.labelContainer.className = this.labelContainer.className.replace(/tree-lines-./, ""); if(this.isFirstNodeInBranch()){ if(this.isLastNodeInBranch()){ // this is single node in branch if(this.config.level == 1){ // single node in root node this.labelContainer.className += " tree-lines-s"; } else { // single node in non-root node this.labelContainer.className += " tree-lines-b"; } } else { // there is other nodes in branch if(this.config.level == 1){ // top node in root node this.labelContainer.className += " tree-lines-t"; } else { // top node in non-root node this.labelContainer.className += " tree-lines-c"; } } } else if(this.isLastNodeInBranch()){ // last node always (except when it is single node) has tree-lines-b this.labelContainer.className += " tree-lines-b"; } else { // all other nodes in the middle this.labelContainer.className += " tree-lines-c"; } if(this.hasSubtree()){ // if tree has subtree if(this.isLastNodeInBranch()){ // and this is last node - do not display left line this.childrenContainer.className = this.childrenContainer.className.replace(/\btree-lined\b/, ""); } else { // otherwise - display left line this.childrenContainer.className += " tree-lined"; } }};/** * @private * Put icons for node depending on its state */Zapatec.Tree.Node.prototype.putIcons = function(){ if(!this.isCreated){ return null; } if(this.expandedIcon || this.collapsedIcon || this.fetchingIcon || this.elementIcon){ if(this.fetchingIcon){ this.fetchingIcon.style.display = this.isFetching ? "block" : "none"; } if(this.expandedIcon){ this.expandedIcon.style.display = !this.data.isExpanded || this.isFetching ? "none" : "block"; } if(this.collapsedIcon){ this.collapsedIcon.style.display = this.data.isExpanded || this.isFetching ? "none" : "block"; } } if(this.signElement){ if(this.isFetching){ this.signElement.className = this.signElement.className.replace(/\b(plus|minus)\b/, "fetching");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -