/* *+------------------------------------------------------------------------+ *| Licensed Materials - Property of IBM *| BI and PM: prmt *| (C) Copyright IBM Corp. 2002, 2020 *| *| US Government Users Restricted Rights - Use, duplication or *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *| *+------------------------------------------------------------------------+ */ //TREE CONTROL // oPane: the HTML element where the tree will be rendered // oSubmit: the form control to submit selections to the server // bRequired: is this a required field [true|false] // bMultiSelect: can the user pick more than one value [true|false] // sRef: the name of this object // oImgTest: the image object used for validation handling // oErrorFeedback: object used to provide validation feedback // sCVId // sStyle // sTextDir // sPromptName: the name of the prompt associated with the tree. This is used as a cache key prefix CInnerTree.prototype = new CTree; function CInnerTree(oPane, oSubmit, bRequired, bMultiSelect, sRef, oImgTest, oErrorFeedback, sCVId, sStyle, sTextDir, sPromptName, oPromptControl) { this.setCVId(sCVId); this.m_style = sStyle; this.m_sTextDir = sTextDir; //html div element where adornments will be rendered this.m_oOuterPane = oPane; //html element where the tree will be rendered this.m_oPane = null; var v_sCustomDir = cssParser( sStyle, "direction", true ); var v_sFinalDir = ((v_sCustomDir == "ltr" || v_sCustomDir == "rtl") ? v_sCustomDir : PRMT_BidiUtils.lookupDirection(oPane)); this.m_sDirection = ( v_sFinalDir == "rtl" ? "RTL" : ""); //create a root node for the tree //new nodes are added by calling the appendChild method for each node this.m_oRoot = new CInnerTreeNode(null, tntRoot, true, 'root', 'root', false); this.m_oRoot.m_oTree = this; this.m_oRoot.setTreeRef(K_PRMT_sEMPTY); this.m_oSubmit = oSubmit; this.m_bRequired = bRequired; //determine the selection mode for the tree if (bMultiSelect == false) { this.m_iSelectionMode = SINGLE_TREE_SELECTION; this.m_sSelectTreeUI = NORMAL_TREE; } else { this.m_iSelectionMode = DISCONTIGUOUS_TREE_SELECTION; this.m_sSelectTreeUI = CHECKBOX_TREE; } //check the state of the control? //this needs to happen after the nodes are added this.m_bValid = false; this.m_sRef = sRef; //maintain a list of selections this.m_sTreeProcessResult = K_PRMT_sEMPTY; this.m_oErrorFeedback = oErrorFeedback; //../prompting/images for handling errors this.m_oImgCheck = oImgTest; if (this.m_oImgCheck != null) { this.m_oImgErrorFalse= new Image(); this.m_oImgErrorFalse.src = ERROR_TIMED_SMALL_OFF; this.m_oImgErrorTrue = new Image(); this.m_oImgErrorTrue.src = ERROR_TIMED_SMALL; } this.m_bShowRootNode = false; this.m_bLoadOnTheFly = false; this.m_iIsLoading = 0; this.m_bForceSelectionAtLowestLevel = false; this.m_bAllowSelectionToggle = true; this.m_oAnchorNode = null; this.m_bAllowDragDrop = false; this.m_fOnDragStartFunc = null; this.m_fOnDragFunc = null; this.m_fOnDragEndFunc = null; this.m_fOnContextMenu = null; this.m_bTrackSelectionOrder = false; this.m_aSelectionOrder = []; this.m_fSingleClickFunc = null; this.m_fDoubleClickFunc = null; this.m_bHideAdornments = false; this.m_bMustChangeDefault = false; this.m_bHideOuterTable = false; this.m_bRecursiveSelect = true; this.m_bPromptTree = false; this.m_iMaxValueCount = 5000; this.m_bShowPreviousValues = true; this.m_aAllSelections = null; this.m_iContainerWidth = null; this.m_iContainerHeight = null; this.m_bNodesCanHaveChildren = true; this.m_bIsDisabled = false; this.m_bHasBeenDrawn = false; this.m_oLastSelectedNode = null; //skin folder this.m_sSkin = (typeof getPromptSkin != K_PRMT_sUNDEFINED ? getPromptSkin() : K_PRMT_sDEFAULTSKIN); if (typeof gDispatcher != K_PRMT_sUNDEFINED) // Try to find global dispatcher object first { this.m_oDispatcher = gDispatcher; } else if (typeof CDispatcher != K_PRMT_sUNDEFINED) { this.m_oDispatcher = new CDispatcher(); } else { this.m_oDispatcher = null; } this.m_sServerPath = this.getGateway(); // DOM objects used to create child nodes. this.m_oTREELINE = document.createElement("IMG"); this.m_oTREELINE.src = PROMT_IMAGES + "blank.gif"; this.m_oTREELINE.alt = ""; this.m_oTREELINE.className = "clsTreeLineIcon"; this.m_oTREELINE.align = gsCTREE_middle; this.m_oTREELINE.setAttribute(gsCTREE_treeRef, gsCTREE_img); this.m_oDIVnewElement = document.createElement("DIV"); this.m_oDIVGroupElement = document.createElement("DIV"); this.m_oDIVGroupElement.setAttribute(K_PRMT_ARIA_ROLE,K_PRMT_TREE_ROLE_GROUP); this.m_oNOBR = document.createElement("NOBR"); this.m_oNOBR.setAttribute(gsCTREE_treeRef, gsCTREE_nobr); this.m_oIcon = document.createElement("IMG"); this.m_oIcon.setAttribute(gsCTREE_treeRef, gsCTREE_img); this.m_oIndicatorSPAN = document.createElement("SPAN"); this.m_oIndicatorSPAN.style.paddingLeft = 3; this.m_oIndicatorIMG = document.createElement("IMG"); this.m_oIndicatorIMG.align = gsCTREE_middle; this.m_oTextSPAN = document.createElement("SPAN"); this.m_oToggleIMG = document.createElement("IMG"); this.m_oToggleIMG.align = gsCTREE_middle; this.m_oToggleIMG.onclick = null; this.m_oToggleIMG.src = (this.m_sDirection == "RTL" ? TREE_L_ONLY_RTL : TREE_L_ONLY); this.m_oCheckIMG = document.createElement("IMG"); this.m_oCheckIMG.align = gsCTREE_middle; /*RTC 364636: BUG: [WA][IE11] Tree Checkbox checkmarks do not update correctly*/ var isIE11 = !!navigator.userAgent.match(/Trident.*rv\:11\./); this.m_oCheckDIV = isIE11? createCheckBoxTable() : document.createElement("DIV"); var checkBoxInputParent = isIE11? this.m_oCheckDIV.getElementsByTagName('div')[0] : this.m_oCheckDIV; var v_oCheckInput = document.createElement("INPUT"); v_oCheckInput.type = "checkbox"; v_oCheckInput.tabIndex = -1; v_oCheckInput.className = "dijitCheckBoxInput"; checkBoxInputParent.appendChild(v_oCheckInput); this.m_oLabelSPAN = document.createElement("SPAN"); this.m_oAncestry = null; if (sPromptName) { this.setAllowStateCache(SYSTEMPROPERTY_TREE_CACHE_ENABLED, sPromptName); } if (oPromptControl) { this.savePromptControlRef(oPromptControl); } } function createCheckBoxTable() { var table = document.createElement("table"); var tr = document.createElement("tr"); var td = document.createElement("td"); var div = document.createElement("div"); td.appendChild(div); tr.appendChild(td); table.appendChild(tr); return table; }; // * CInnerTree.prototype = new CPromptControl(); // Set this to the tree's parameter name if this is a prompt control tree // getPromptValues OM function will be called automatically if this is a prompting tree CInnerTree.prototype.redrawNodeToggle = function(node, nodeId) { var newToggleIcon = document.getElementById(nodeId + gsCTREE_toggle + node.getTreeHierarchy()); if (newToggleIcon != null) { this.detailToogleIcon(node, newToggleIcon); } }; CInnerTree.prototype.drawLoading = function(node, nodeId) { var theElement = document.getElementById(nodeId); if (!theElement && node.getNodeType() == TREE_ROOT && this.getRootNodeShowing() == false) { theElement = this.m_oPane; } if (theElement != null) { var newDivContainer = document.createElement("DIV"); newDivContainer.className = CLS_TREE_LEVEL; newDivContainer.id = this.getName() + node.getTreeRef() + "loading"; newDivContainer.style.width = "100%"; var newNobrContainer = document.createElement("NOBR"); this.drawTreeLines(node, newNobrContainer, node.getLevel() + 1); if (!(node.getNodeType() == TREE_ROOT && node.getTree().getRootNodeShowing() == false && node.getMoreData() != true)) { var newLIcon = document.createElement("IMG"); newLIcon.align = gsCTREE_middle; newLIcon.src = (this.m_sDirection == "RTL" ? TREE_L_ONLY_RTL : TREE_L_ONLY); newNobrContainer.appendChild(newLIcon); } var newStateIcon = document.createElement("IMG"); newStateIcon.align = gsCTREE_middle; newStateIcon.src = TREE_LOADING; newNobrContainer.appendChild(newStateIcon); var newLabelContainer = document.createElement("SPAN"); newLabelContainer.className = CLS_TREE_NODE_UNSELECTED + K_PRMT_sSP + CLS_TREE_TEXT; //We need the localized string for "Loading..." here if (typeof PMT_TRE_TREE_LOADING != K_PRMT_sUNDEFINED) { var newStateText = document.createTextNode(PMT_TRE_TREE_LOADING); newLabelContainer.appendChild(newStateText); newLabelContainer.title = PMT_TRE_TREE_LOADING; } newNobrContainer.appendChild(newLabelContainer); newDivContainer.appendChild(newNobrContainer); theElement.appendChild(newDivContainer); } }; CInnerTree.prototype.drawMoreData = function(node, nodeId) { var theElement = document.getElementById(nodeId); if (!theElement && node.getNodeType() == TREE_ROOT && this.getRootNodeShowing() == false) { theElement = this.m_oPane; } var childrenContainer = (theElement.getAttribute("role") == "tree"? theElement : theElement.firstChild.nextSibling); if (theElement != null && childrenContainer != null && (childrenContainer.getAttribute("role") == "group" || childrenContainer.getAttribute("role") == "tree")) { var newDivContainer = document.createElement("DIV"); newDivContainer.className = CLS_TREE_LEVEL; newDivContainer.id = this.getName() + node.getTreeRef() + "moredata"; newDivContainer.style.width = "100%"; var newNobrContainer = document.createElement("NOBR"); this.drawTreeLines(node, newNobrContainer, node.getLevel() + 1); var newLIcon = document.createElement("IMG"); newLIcon.align = gsCTREE_middle; newLIcon.src = (this.m_sDirection == "RTL" ? TREE_L_ONLY_RTL : TREE_L_ONLY); newNobrContainer.appendChild(newLIcon); var newStateIcon = document.createElement("IMG"); newStateIcon.align = gsCTREE_middle; newStateIcon.src = TREE_MORE_DATA; newNobrContainer.appendChild(newStateIcon); var newLabelContainer = document.createElement("SPAN"); newLabelContainer.className = CLS_TREE_NODE_UNSELECTED + K_PRMT_sSP + CLS_TREE_TEXT_LINK; //We need the localized string for "More" here if (typeof PMT_TRE_MORE != K_PRMT_sUNDEFINED) { var newStateText = document.createTextNode(PMT_TRE_MORE); newLabelContainer.appendChild(newStateText); newLabelContainer.title = PMT_TRE_MORE; } newLabelContainer.id = this.getName() + node.getTreeRef() + "moredatalabel"; newLabelContainer.setAttribute(gsCTREE_tree, this.getName()); newLabelContainer.setAttribute(gsCTREE_treeRef, node.getTreeRef()); newLabelContainer.tabIndex = 0; PRMTUtils.f_addEvent(newLabelContainer, "click", getMoreDataForTreeNode); PRMTUtils.f_addEvent(newLabelContainer, "keydown", getMoreDataForTreeNode); PRMTUtils.f_addEvent(newLabelContainer, "keypress", getMoreDataForTreeNode); newNobrContainer.appendChild(newLabelContainer); newDivContainer.appendChild(newNobrContainer); childrenContainer.appendChild(newDivContainer); } }; CInnerTree.prototype.drawTreeLines = function(node, newElement, drawToLevel) { // put in appropriate spacers if (drawToLevel > 1) { for (var n = 1; n < drawToLevel; n++) { var spacerIcon = this.m_oTREELINE.cloneNode(true); var oParent = node.getParentAtLevel(n); if (oParent.isLastSibling() == true && oParent.getParent().getMoreData() != true) { //if the parent was last spacerIcon.className = spacerIcon.className + " clsTreeLineIconSpace"; } newElement.appendChild(spacerIcon); } } }; CInnerTree.prototype.drawOuterTable = function() { if (this.m_oOuterPane != null) { var sId = this.m_sRef; var sStyle = this.getStyle(); var HTMLOut = "
" + ""; if (this.getHideAdornments() != true) { HTMLOut += ""; } HTMLOut += "" + "" + "
" + ""; if (this.getRequired() == true) { HTMLOut += "" + "" + ""; } // put the tree in the tab order relative to tree's position in the page (tabindex=-1) HTMLOut += "" + "" + "" + "
" + "
" + "" + "" + "" + "" + ""; } if (this.getSelectionMode() != SINGLE_TREE_SELECTION) { HTMLOut += "" + "" + ""; } HTMLOut += "
"; if (this.getHideAdornments() != true) { HTMLOut += "
"; if (this.getSelectTreeUI() != CHECKBOX_TREE || this.getSelectionMode() != DISCONTIGUOUS_TREE_SELECTION) { HTMLOut += "" + PMT_UIM_SELECTALL + " "; } HTMLOut += "" + PMT_UIM_DESELECTALL + "" + "
" + "
"; this.m_oOuterPane.innerHTML = HTMLOut; if (this.getErrorFeedbackWidget() == null) { this.setErrorFeedbackWidget(document.getElementById("feedback_tree" + sId)); } if (this.getImgCheck() == null) { this.setImgCheck(document.getElementById("imgTest_tree" + sId)); if (this.getImgCheck() != null) { this.setImgErrorFalse(ERROR_TIMED_SMALL_OFF); this.setImgErrorTrue(ERROR_TIMED_SMALL); } } } }; CInnerTree.prototype.createElementIndicator = function(node, treeName, treeRef) { // create indicator span var newElementIndicator = this.m_oIndicatorSPAN.cloneNode(true); newElementIndicator.id = treeName + treeRef + gsCTREE_indicatorSpan; newElementIndicator.setAttribute(gsCTREE_treeRef, treeRef); newElementIndicator.setAttribute(gsCTREE_dragRef, treeRef.toString()); newElementIndicator.setAttribute(gsCTREE_dragTree, treeName); newElementIndicator.setAttribute(gsCTREE_tree, treeName); // create the indicator image var newElementIndicatorImage = this.m_oIndicatorIMG.cloneNode(true); newElementIndicatorImage.id = treeName + treeRef + gsCTREE_indicator; newElementIndicatorImage.setAttribute(gsCTREE_treeRef, treeRef); newElementIndicatorImage.setAttribute(gsCTREE_dragRef, treeRef.toString()); newElementIndicatorImage.setAttribute(gsCTREE_dragTree, treeName); newElementIndicatorImage.setAttribute(gsCTREE_tree, treeName); // set the image newElementIndicatorImage.src = node.getIndicator(); // add this into the span newElementIndicator.appendChild(newElementIndicatorImage); return newElementIndicator; }; CInnerTree.prototype.draw = function(node, oParentElement) { if (node.getTree().getDisabled() == true) { return false; } var treeRef = node.getTreeRef(); var treeName = this.getName(); //if the node is the root node, removes the old root node so that the entire tree is redrawn //this takes care of the case where a loading tree is replaced with real data if (node.getNodeType() == TREE_ROOT) { var rootNode = document.getElementById(treeName); if (rootNode != null) { oParentElement.removeChild(rootNode); } oParentElement.setAttribute(gsCTREE_treeRef, treeRef); oParentElement.setAttribute(gsCTREE_tree, treeName); } // clone outer container DIV (it's much faster than create a new one) var nodeElement = this.m_oDIVnewElement.cloneNode(true); PRMTUtils.f_addEvent( nodeElement, "dragstart", dragStartOnNode ); PRMTUtils.f_addEvent( nodeElement, "drag", dragOnNode ); PRMTUtils.f_addEvent( nodeElement, "dragend", dragEndOnNode ); nodeElement.setAttribute(gsCTREE_treeRef, treeRef); nodeElement.setAttribute(gsCTREE_tree, treeName); if (treeRef == K_PRMT_sEMPTY) { nodeElement.setAttribute(K_PRMT_ARIA_ROLE, K_PRMT_TREE_ROLE_TREE); } nodeElement.id = treeName + treeRef; if (!(node.getNodeType() == TREE_ROOT && this.getRootNodeShowing() == false)) { this.drawNode(node, nodeElement); } // ****************************************************************** // deal with children // ****************************************************************** oParentElement.appendChild(nodeElement); this.drawNodeChildren (node, nodeElement); this.m_bHasBeenDrawn = true; }; /** * Draws the icon + / - that acts as a toogle for the branch * */ CInnerTree.prototype.drawToogleIcon = function(node) { var newToggleIcon = this.m_oToggleIMG.cloneNode(true); newToggleIcon.src = PROMT_IMAGES + "blank.gif"; return this.detailToogleIcon(node, newToggleIcon); }; CInnerTree.prototype.detailToogleIcon = function(node, newToggleIcon) { // text for high contrast var newToggleText = this.m_oTextSPAN.cloneNode(true); newToggleText.className= K_PRMT_TREE_TOGGLE_TEXT; newToggleText.setAttribute(K_PRMT_ARIA_ROLE, K_PRMT_ARIA_ROLE_PRESENTATION); var toggleTextContent = ""; if (node.canHaveChildren() == true) { if (node.isOpen() == true) { newToggleIcon.className = K_PRMT_TREE_TOGGLE_OPENED + this.m_sDirection; newToggleIcon.title = PMT_TRE_COLLAPSE; newToggleIcon.alt = PMT_TRE_COLLAPSE; toggleTextContent = "-"; } else { newToggleIcon.className= K_PRMT_TREE_TOGGLE_CLOSED + this.m_sDirection; newToggleIcon.title = PMT_TRE_EXPAND; newToggleIcon.alt = PMT_TRE_EXPAND; toggleTextContent = "+"; } newToggleIcon.tabIndex = -1; newToggleIcon.onclick = toggle; newToggleText.onclick = toggle; } else { newToggleIcon.className= K_PRMT_TREE_TOGGLE_LEAF; newToggleIcon.src = PROMT_IMAGES + "blank.gif"; newToggleIcon.alt = ""; newToggleIcon.onclick = null; } var toggleTextNode= document.createTextNode(toggleTextContent); newToggleText.appendChild(toggleTextNode); newToggleIcon.setAttribute(gsCTREE_treeRef, gsCTREE_img); return [newToggleIcon, newToggleText]; }; /** * Draws the checkbox * */ CInnerTree.prototype.drawNodeCheckboxIcon = function(node) { var newCheckBox = this.m_oCheckDIV.cloneNode(true); updateCheckboxClass(newCheckBox, node); newCheckBox.setAttribute(gsCTREE_treeRef, gsCTREE_checkbox); //set up events if ((node.getTree().getForceSelectionAtLowestLevel() == true && node.getNodeType() == TREE_ITEM) || (node.getTree().getForceSelectionAtLowestLevel() == false)) { PRMTUtils.f_addEvent(newCheckBox.firstChild, "click", selectNode); } return newCheckBox; }; /** * Draws the label Node label * */ CInnerTree.prototype.drawNodeLabel = function(node, treeName, treeRef) { var nodeElementLabelContainer = this.m_oLabelSPAN.cloneNode(true); nodeElementLabelContainer.id = treeName + treeRef + gsCTREE_labelText; this.updateLabelClass(nodeElementLabelContainer, getClassName(node, this), node); nodeElementLabelContainer.setAttribute(gsCTREE_treeRef, treeRef); nodeElementLabelContainer.setAttribute(gsCTREE_dragRef, treeRef.toString()); nodeElementLabelContainer.setAttribute(gsCTREE_dragTree, treeName); nodeElementLabelContainer.setAttribute(gsCTREE_tree, treeName); nodeElementLabelContainer.setAttribute(K_PRMT_ARIA_ROLE, K_PRMT_TREE_ROLE_TREEITEM); node.m_oLabelText = nodeElementLabelContainer; if (node.isFirst()) { nodeElementLabelContainer.tabIndex = 0; this.m_lastFocus = nodeElementLabelContainer; } var labelText = document.createTextNode( G_IsBidiEnabled && this.m_sTextDir ? PRMT_BidiUtils.enforceBidiDirection(node.getName(), this.m_sTextDir) : node.getName() ); nodeElementLabelContainer.appendChild(labelText); updateLabelAriaChecked(nodeElementLabelContainer, node); var sStyle = this.getStyle(); nodeElementLabelContainer.style.color= cssParser(sStyle,"color",true); nodeElementLabelContainer.style.backgroundColor= cssParser(sStyle,"background-color",true); nodeElementLabelContainer.style.fontFamily= cssParser(sStyle,"font-family",true); nodeElementLabelContainer.style.fontSize= cssParser(sStyle,"font-size",true); nodeElementLabelContainer.style.fontWeight= cssParser(sStyle,"font-weight",true); nodeElementLabelContainer.style.fontStyle= cssParser(sStyle,"font-style",true); nodeElementLabelContainer.style.fontVariant= cssParser(sStyle,"font-variant",true); nodeElementLabelContainer.style.textAlign= cssParser(sStyle,"text-align",true); nodeElementLabelContainer.style.textVariant= cssParser(sStyle,"text-variant",true); nodeElementLabelContainer.style.textIndent= cssParser(sStyle,"text-indent",true); nodeElementLabelContainer.style.textTransform= cssParser(sStyle,"text-transform",true); nodeElementLabelContainer.setAttribute(gsCTREE_treeRef, treeRef); nodeElementLabelContainer.setAttribute(gsCTREE_dragRef, treeRef.toString()); nodeElementLabelContainer.setAttribute(gsCTREE_dragTree, treeName); nodeElementLabelContainer.setAttribute(gsCTREE_tree, treeName); nodeElementLabelContainer.setAttribute("onfocus","this.classname='" + CLS_TREE_NODE_HOVER + " " + CLS_TREE_TEXT + "';"); nodeElementLabelContainer.setAttribute("onblur","this.classname='" + CLS_TREE_NODE_UNSELECTED + " " + CLS_TREE_TEXT + "';"); return nodeElementLabelContainer; }; /** * Node structure *
* * * [ checkbox ] * * [ indicator ] * * * * *
*/ CInnerTree.prototype.drawNode = function(node, nodeElement) { var treeRef = node.getTreeRef(); var treeName = this.getName(); nodeElement.className = CLS_TREE_LEVEL; nodeElement.setAttribute(gsCTREE_dragRef, treeRef.toString()); nodeElement.setAttribute(gsCTREE_dragTree, treeName); nodeElement.setAttribute(K_PRMT_ARIA_ROLE, K_PRMT_ARIA_ROLE_PRESENTATION); // var newNobr = this.m_oNOBR.cloneNode(true); //var newNobr = this.m_oDIVnewElement.cloneNode(true); newNobr.setAttribute(gsCTREE_treeRef, gsCTREE_nobr); newNobr.setAttribute(gsCTREE_tree, treeName); newNobr.setAttribute(K_PRMT_ARIA_ROLE, K_PRMT_ARIA_ROLE_PRESENTATION); newNobr.setAttribute("style", "white-space: nowrap;"); nodeElement.appendChild(newNobr); this.drawTreeLines(node, newNobr, node.getLevel()); // add [ indicator : ] var nodeElementIndicator = null; if (node.getIndicator() != null) { nodeElementIndicator = createElementIndicator(node,treeName,treeRef); } // create var nodeElementText = this.m_oTextSPAN.cloneNode(true); nodeElementText.id = treeName + treeRef + gsCTREE_label; nodeElementText.setAttribute(gsCTREE_treeRef, treeRef); nodeElementText.setAttribute(gsCTREE_dragRef, treeRef.toString()); nodeElementText.setAttribute(gsCTREE_dragTree, treeName); nodeElementText.setAttribute(gsCTREE_tree, treeName); nodeElementText.setAttribute(K_PRMT_ARIA_ROLE, K_PRMT_ARIA_ROLE_PRESENTATION); nodeElementText.title = (node.getTooltip() != false? node.getTooltip() : node.getName()); if (G_IsBidiEnabled && this.m_sTextDir) { nodeElementText.title = PRMT_BidiUtils.enforceBidiDirection(nodeElementText.title, this.m_sTextDir); } // create node icon -> var nodeElementIcon = this.m_oIcon.cloneNode(true); nodeElementIcon.id = treeName + treeRef + gsCTREE_icon; nodeElementIcon.setAttribute(gsCTREE_dragRef, treeRef.toString()); nodeElementIcon.setAttribute(gsCTREE_dragTree, treeName); nodeElementIcon.setAttribute(K_PRMT_ARIA_ROLE, K_PRMT_ARIA_ROLE_PRESENTATION); nodeElementIcon.src = PROMT_IMAGES + "blank.gif"; //getIconSrc(node); nodeElementIcon.className = "clsTreeNodeIcon"; nodeElementIcon.alt = ""; nodeElementIcon.align = gsCTREE_middle; var newToggleIcon = null; if (node.getNodeType() == TREE_ROOT) { nodeElementText.onclick = function() {return false;}; } else { var newToggleElems = this.drawToogleIcon(node); newToggleIcon = newToggleElems[0]; newToggleIcon.id = treeName + treeRef + gsCTREE_toggle + node.getTreeHierarchy(); newNobr.appendChild(newToggleIcon); newNobr.appendChild(newToggleElems[1]); if ((node.getTree().getForceSelectionAtLowestLevel() == true && node.getNodeType() == TREE_ITEM) || (node.getTree().getForceSelectionAtLowestLevel() == false)) { nodeElementText.tabIndex = -1; PRMTUtils.f_addEvent(nodeElementText, "click", selectNode.bind(this)); if (node.getTree().getSingleClickFunc() != null) { PRMTUtils.f_addEvent( nodeElementText, "click", singleClickCaller ); } if (node.getTree().getDoubleClickFunc() != null) { PRMTUtils.f_addEvent( nodeElementText, "dblclick", doubleClickCaller ); } nodeElementText.onmouseover = treeNodeMouseOver; nodeElementText.onmouseout = treeNodeMouseOut; PRMTUtils.f_addEvent( nodeElementText, "contextmenu", contextMenuCaller ); } //add a checkbox for multiselect trees if (this.getSelectionMode() != SINGLE_TREE_SELECTION && this.getSelectTreeUI() == CHECKBOX_TREE) { var newCheckBoxIcon = this.drawNodeCheckboxIcon(node); newCheckBoxIcon.id = treeName + treeRef + gsCTREE_checkbox; newCheckBoxIcon.firstChild.id = treeName + treeRef + gsCTREE_checkbox + "Input"; newNobr.appendChild(newCheckBoxIcon); } } // add icon nodeElementText.appendChild(nodeElementIcon); // add the indicator if there is one if (nodeElementIndicator != null) { nodeElementText.appendChild(nodeElementIndicator); } // aria-expanded attribute */ CInnerTree.prototype.updateAriaLabelContainer = function(oNode, sTreeName, ariaExpanded) { var labelContainer = document.getElementById(sTreeName + oNode.getTreeRef() + gsCTREE_labelText); if (labelContainer) { labelContainer.setAttribute(K_PRMT_TREE_STATE_EXPANDED, ariaExpanded); } }; CInnerTree.prototype.updateLabelClass = function(labelElem, className, node) { labelElem.className = className + " " + CLS_TREE_TEXT; // update aria-ckecked for the single selection tree, for multiple selection is done in the updateCheckbox function if (!(this.getSelectionMode() != SINGLE_TREE_SELECTION && this.getSelectTreeUI() == CHECKBOX_TREE) && node) { updateLabelAriaChecked(labelElem, node) } }; /* * override cancelBub => PRMTUtils.F_StopEvent to avoid duplication of * several functions which only difference is using cancelBub instead of * PRMTUtils.F_StopEvent */ function cancelBub(evt) { return PRMTUtils.F_StopEvent.apply(this, arguments); } // get the UINode and TreeNode which are the event target function getTargetNodeInfo(evt) { return getUINodeNodeInfo(getUINode(evt)); } function getUINodeNodeInfo(uiNode) { var result = {}; result.uiNode = uiNode; var uiNodeTreeRef = uiNode.getAttribute(gsCTREE_treeRef).toString(); //get the tree id result.tree = uiNode.getAttribute(gsCTREE_tree).toString(); //get tree Node result.node = getTreeNode(result.tree, uiNodeTreeRef); return result; } function selectNode(evt) { //get the event in a cross-browser fashion evt = (evt) ? evt : ((event) ? event : null); if ((evt != null) && (evt.keyCode != null) && (evt.keyCode != 13) && (evt.keyCode != 0)) { return false; } //cancel any text selection clearSelection(); //prevent the event from bubbling to other elements PRMTUtils.F_StopEvent(evt); //get UI Node var uiNode = getUINode(evt); var uiNodeTreeRef = uiNode.getAttribute(gsCTREE_treeRef).toString(); //get the tree object var tree = uiNode.getAttribute(gsCTREE_tree).toString(); //get tree Node var node = getTreeNode(tree, uiNodeTreeRef); var oTree = node.getTree(); oTree.f_moveFocus(null, node); oTree.processNodeSelection(node, tree, evt.ctrlKey, evt.shiftKey); if (oTree.m_oTreeControl) { oTree.m_oTreeControl.cacheControlValue(); } return false; } /** * Process node selection, is called by click and keydown(SPACE) event handlers * */ CInnerTree.prototype.processNodeSelection = function(node, tree, ctrlKey, shiftKey) { //handle multiple select if (this.getSelectionMode() != SINGLE_TREE_SELECTION) { if ((ctrlKey == false) && (shiftKey == false) && (this.getSelectTreeUI() != CHECKBOX_TREE)) { this.clearPreviousSelections(); } var normalTreeNeedsRedraw = ((this.getSelectTreeUI() == NORMAL_TREE) && (ctrlKey == false) && (shiftKey == false)); var unselectNode = ((this.getSelectTreeUI() == CHECKBOX_TREE) || ((this.getSelectTreeUI() == NORMAL_TREE) && ((this.getAllowSelectionToggle() == true) || ((this.getAllowSelectionToggle() == false) && (ctrlKey == true))))); if (normalTreeNeedsRedraw) { this.getRootNode().setSelected(false); if (this.getTrackSelectionOrder()) { this.clearSelectionOrder(); } } //setSelected var nodeWasSelected = node.isSelected(); if ((this.getSelectTreeUI() == NORMAL_TREE) && (shiftKey == true)) { var anchorNode = this.getAnchorNode(); if (anchorNode != null && node.getRootNode().hasSelectedChildren()) { if (node.getParent() == anchorNode.getParent()) { var anchorNodeIndex = anchorNode.getIndex(); var nodeIndex = node.getIndex(); var iCurrentNode = anchorNodeIndex; var iIncrement = ((anchorNodeIndex > nodeIndex)? - 1 : 1); //select all of the children between the anchor node and the selected node while (iCurrentNode != nodeIndex + iIncrement) { var siblingNode = node.getParent().m_oChildren[iCurrentNode]; siblingNode.setSelected(true); var oLabel = siblingNode.getLabel(tree); this.updateLabelClass(oLabel, getClassName(siblingNode, this), siblingNode); redrawChildren(siblingNode, tree); iCurrentNode += iIncrement; } } } } if (nodeWasSelected == true) { if (unselectNode) { node.setSelected(false); this.setLastSelectedNode(null); this.removeFromPrevSelArray( node.getValue(), node.getName() ); } } else { node.setSelected(true); this.setLastSelectedNode(node); } node.updateNodeSelection(); node.updateParent(); this.updateLabelClass(node.getLabel(tree), getClassName(node, this), node); this.checkData(); if (normalTreeNeedsRedraw) { this.redraw(); this.checkData(); } else { redrawChildren(node, tree); redrawParents(node, tree); } if (unselectNode && nodeWasSelected) { this.setAnchorNode(null); } else { this.setAnchorNode(node); } } else { //single select remove all other selections this.clearPreviousSelections(); if (node.isSelected() == true && this.getAllowSelectionToggle() == true) { this.getRootNode().setSelected(false); this.setLastSelectedNode(null); } else { this.getRootNode().setSelected(false); node.setSelected(true); this.setLastSelectedNode(node); } node.updateParent(); this.redraw(); this.checkData(); } }; function redrawChildren(node,tree) { //has the child node been rendered? //draw the nodes if they haven't been rendered if (node.getRendered() == true) { var children = node.getChildren(); var oTree = node.getTree(); var childrenContainer = document.getElementById(tree + node.getTreeRef() + "children"); // when redrawing first level (by selecting "More") the container Id has not the "children" suffix if (childrenContainer === null) { childrenContainer = document.getElementById(tree + node.getTreeRef()); } for (var j = 0; j < children.length; j++) { var oChild = children[j]; var labelElem = oChild.getLabel(tree); if (labelElem == null) { if (j > 0) { oTree.redrawNodeToggle(children[j - 1], tree + children[j - 1].getTreeRef()); } oTree.draw(oChild, childrenContainer); if (node.isOpen() == false) { document.getElementById(tree + oChild.getTreeRef()).style.display = "none"; } } else { oTree.updateLabelClass(labelElem, getClassName(oChild, oTree), oChild); if (oTree.getSelectionMode() != SINGLE_TREE_SELECTION) { if (oTree.getSelectTreeUI() == CHECKBOX_TREE) { var checkbox = oChild.getCheckbox(tree); if (checkbox) { updateCheckboxClass(checkbox, oChild); } } } } redrawChildren(oChild,tree); } } } function redrawParents(node, tree) { var parentNode = node.getParent(); if (parentNode != null) { var labelElem = parentNode.getLabel(tree); if (labelElem != null) { var v_oTree = parentNode.getTree(); v_oTree.updateLabelClass(labelElem, getClassName(parentNode, v_oTree), parentNode); if (node.getTree().getSelectionMode() != SINGLE_TREE_SELECTION) { if (parentNode.getTreeRef() != null && parentNode.getTreeRef().length != 0) { if (node.getTree().getSelectTreeUI() == CHECKBOX_TREE) { var checkbox = parentNode.getCheckbox(tree); updateCheckboxClass(checkbox, parentNode); } redrawParents(parentNode, tree); } } } } } function dragStartOnNode(evt) { //get the event in a cross-browser fashion evt = (evt) ? evt : ((event) ? event : null); //cancel any text selection clearSelection(); //prevent the event from bubbling to other elements PRMTUtils.F_StopEvent(evt); var dragRef = evt.srcElement.getAttribute(gsCTREE_dragRef); if (typeof dragRef == K_PRMT_sSTRING && dragRef.length != 0) { var uiNode = getUINode(evt); if (uiNode) { //get the tree object var tree = uiNode.getAttribute(gsCTREE_dragTree).toString(); //get tree Node var node = getTreeNode(tree, dragRef); var treeObj = node.getTree(); if (!node.isSelected()) { if ((evt.ctrlKey == false) && (evt.shiftKey == false)) { treeObj.getRootNode().setSelected(false); treeObj.clearPreviousSelections(); if (treeObj.getTrackSelectionOrder()) { treeObj.clearSelectionOrder(); } } //select all the children node.setSelected(true); //update the parent node.updateParent(); treeObj.updateLabelClass(node.getLabel(), getClassName(node, treeObj). node); if ((evt.ctrlKey == false) && (evt.shiftKey == false)) { treeObj.redraw(); treeObj.checkData(); } } var selectedNodes = treeObj.getSelectedFolderNodes(); selectedNodes = selectedNodes.concat(treeObj.getSelectedLeafNodes()); var selNodesStr = tree + "~~~~~"; for (var i = 0; i < selectedNodes.length; i++) { if (i > 0) { selNodesStr += "~~~"; } selNodesStr += selectedNodes[i].getTreeRef(); } event.dataTransfer.setData("Text", selNodesStr); if (treeObj.getOnDragStart() != null) { var dragStartFunction = treeObj.getOnDragStart(); dragStartFunction(evt); } } } } ///////////////////// //utility functions /** * find the DIV enclosing element for the node where the event occurred */ function getUINode (evt, uiNode) { if (!uiNode) { //get the element that trapped the event in a cross-browser fashion uiNode = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null); } while ( uiNode && !(uiNode.tagName == "DIV" && uiNode.getAttribute(gsCTREE_tree) != null) ) { uiNode = uiNode.parentNode; } return uiNode; } //return plus or minus icons for the given node function getToggleSrc(node) { if (node.isOpen() == true) { if (node.isLastSibling() == true && node.getParent().getMoreData() != true) { return TREE_L_MINUS; } else { return TREE_T_MINUS; } } else { if (node.isLastSibling() == true && node.getParent().getMoreData() != true) { return TREE_L_PLUS; } else { return TREE_T_PLUS; } } } function treeNodeMouseOver(evt) { //get the event in a cross-browser fashion evt = (evt) ? evt : ((event) ? event : null); //cancel any text selection clearSelection(); //prevent the event from bubbling to other elements PRMTUtils.F_StopEvent(evt); //get UI Node var uiNode = getUINode(evt); var uiNodeTreeRef = uiNode.getAttribute(gsCTREE_treeRef).toString(); //get the tree object var tree = uiNode.getAttribute(gsCTREE_tree).toString(); //get tree Node var node = getTreeNode(tree, uiNodeTreeRef); window.status = K_PRMT_sEMPTY; var v_oTree = node.getTree(); if (v_oTree) v_oTree.treeNodeShowFocus(node, tree); } CInnerTree.prototype.treeNodeShowFocus = function(node, tree) { if (node.getNodeTypeObject().getSelectable() && node.isSelected() == false && node.hasSelectedChildren() == false) { this.updateLabelClass(node.getLabel(tree), CLS_TREE_NODE_HOVER, node); } }; CInnerTree.prototype.treeNodeHideFocus = function(node, tree) { if (node.isSelected() == false && node.hasSelectedChildren() == false) { this.updateLabelClass(node.getLabel(tree), CLS_TREE_NODE_UNSELECTED, node); } }; function treeNodeMouseOut(evt) { //get the event in a cross-browser fashion evt = (evt) ? evt : ((event) ? event : null); //cancel any text selection clearSelection(); //prevent the event from bubbling to other elements PRMTUtils.F_StopEvent(evt); //get UI Node var uiNode = getUINode(evt); var uiNodeTreeRef = uiNode.getAttribute(gsCTREE_treeRef).toString(); //get the tree object var tree = uiNode.getAttribute(gsCTREE_tree).toString(); //get tree Node var node = getTreeNode(tree, uiNodeTreeRef); window.status = K_PRMT_sEMPTY; var v_oTree = node.getTree(); if (v_oTree) v_oTree.treeNodeHideFocus(node, tree); } ///////////////////////////////// // Tree node object // oParentTreeNode: the parent node - null for the root node // oTreeNodeType: the type of node, a TreeNodeType object (e.g. folder/leaf) // bOpenState: if this is a container, whether the the default state is open or closed [true|false] // name: the display value for the tree node // value: the use value for the tree node // bSelected: whether this node has been selected or not //Tree nodes function CInnerTreeNode(oParentTreeNode, oTreeNodeType, bOpenState, sName, value, bSelected) { if (oTreeNodeType) { this.init(oParentTreeNode, oTreeNodeType, bOpenState, sName, value, bSelected); } } CInnerTreeNode.prototype = new CTreeNode(); CInnerTreeNode.prototype.isFirst = function () { var v_bResult = false; if ((this.getParent() != null) && (this.getParent() == this.getRootNode()) && (this.getTreeRef() == this.getParent().m_oChildren[0].getTreeRef())) { v_bResult = true; } return v_bResult; }; CInnerTreeNode.prototype.isFirstSibling = function () { var v_bResult = false; if ((this.getParent() != null) && (this.getTreeRef() == this.getParent().m_oChildren[0].getTreeRef())) { v_bResult = true; } return v_bResult; }; CInnerTreeNode.prototype.isLastSibling = function () { var v_bResult = false; if ((this.getParent() != null) && (this.getTreeRef() == this.getParent().m_oChildren[this.getParent().getChildrenLength() - 1].getTreeRef())) { v_bResult = true; } return v_bResult; }; CInnerTreeNode.prototype.getNextSibling = function () { var v_oResult = null; if (! this.isLastSibling()) { v_oResult = this.getParent().m_oChildren[this.getIndex() + 1]; } return v_oResult; }; CInnerTreeNode.prototype.getPreviousSibling = function () { var v_oResult = null; if (! this.isFirstSibling()) { v_oResult = this.getParent().m_oChildren[this.getIndex() - 1]; } return v_oResult; }; CInnerTreeNode.prototype.getLabel = function (sTreeRef) { if (!this.m_oLabelText) { this.m_oLabelText = document.getElementById(sTreeRef + this.getTreeRef() + gsCTREE_labelText); } return this.m_oLabelText; }; CInnerTreeNode.prototype.getLabelContainer = function (treeName) { return document.getElementById(treeName + this.getTreeRef() + gsCTREE_labelText); }; CInnerTreeNode.prototype.getNodeLabel = function () { var v_oTree = this.getTree(); var v_sTreeRef = v_oTree.getName(); if (!this.m_oLabelText) { this.m_oLabelText = document.getElementById(sTreeRef + this.getTreeRef() + gsCTREE_labelText); } return this.m_oLabelText; }; //boolean: returns whether the node has children or not CInnerTreeNode.prototype.hasChildren = function () { return(this.getChildrenLength() > 0); }; CInnerTreeNode.prototype.updateNodeSelection = function () { var v_oTree = this.getTree(); if (v_oTree.getSelectTreeUI() == NORMAL_TREE) { if (v_oTree.getSelectionMode() == CONTIGUOUS_TREE_SELECTION && this.isSelected() == false && this.getNodeType() == TREE_FOLDER && this.getChildrenLength() == this.getSelectedChildrenCount()) { this.m_bSelected = true; } var labelElem = this.getLabel(this.getTree().getName()); if (labelElem != null) { v_oTree.updateLabelClass(labelElem, getClassName(this, v_oTree), this); } } else { var checkbox = this.getCheckbox(v_oTree.getName()); if (checkbox != null) { updateCheckboxClass(checkbox, this); } } }; //open: specifies whether the children of a container node should be displayed CInnerTreeNode.prototype.isClosed = function () { return !this.m_bOpen; }; //return the child at the appropriate position CInnerTreeNode.prototype.getFirstChild = function () { var v_oResult = null; if ( this.getChildrenLength() > 0 ) { v_oResult = this.m_oChildren[0]; } return v_oResult; }; //return the child at the appropriate position CInnerTreeNode.prototype.getLastChild = function () { var v_oResult = null; if ( this.getChildrenLength() > 0 ) { v_oResult = this.m_oChildren[this.getChildrenLength() - 1]; } return v_oResult; }; var TREE_IMG = { 'TREE_L': { 'MINUS': TREE_L_MINUS, 'PLUS' : TREE_L_PLUS, 'ONLY' : TREE_L_ONLY }, 'TREE_T': { 'MINUS': TREE_T_MINUS, 'PLUS' : TREE_T_PLUS, 'ONLY' : TREE_T_ONLY } }; // overrides parent method to create a new node of the same class CInnerTreeNode.prototype.createNewNode = function(treeNode, tntGeneric,name, value, isSelected) { // ( oParentTreeNode, oTreeNodeType, bOpenState, sName, value, bSelected ) new CInnerTreeNode(treeNode, tntGeneric, false, jsDecodeStr(name), jsDecodeStr(value), isSelected); }; function updateCheckboxClass(checkbox, node) { var checkBoxClass = K_PRMT_sEMPTY; var checked = true; var ariaChecked = "true"; //get the current state switch (node.getState()) { case NODE_UNSELECTED: checkBoxClass = K_PRMT_CSS_CHECKBOX; checked = false; ariaChecked = "false"; break; case NODE_PARTIAL: checkBoxClass = K_PRMT_CSS_CHECKBOX_PARTIAL; ariaChecked = "mixed"; break; case NODE_SELECTED: checkBoxClass = K_PRMT_CSS_CHECKBOX_CHECKED; break; } checkbox.className = checkBoxClass; checkbox.firstChild.checked = checked; checkbox.firstChild.setAttribute("checked", checked); updateLabelAriaChecked(node.getLabel(node.getTree().getName()), node, ariaChecked); } /** * */ function updateLabelAriaChecked(labelElem, node, ariaChecked) { if (typeof ariaChecked == K_PRMT_sUNDEFINED) { ariaChecked = node2AriaChecked(node); } if (labelElem) { if (labelElem[K_PRMT_ARIA_CHECKED]) { labelElem[K_PRMT_ARIA_CHECKED] = ariaChecked; } else { labelElem.setAttribute(K_PRMT_ARIA_CHECKED, ariaChecked); } } } /** * Maps the aria-checked to the node state : NODE_UNSELECTED => "false", NODE_PARTIAL => "mixed", NODE_SELECTED => "true" */ function node2AriaChecked(node) { if (node && node.getState) { var nodeState = node.getState(); return (nodeState == NODE_UNSELECTED? "false" :(nodeState == NODE_PARTIAL? "mixed":"true")); } } function updateToggleIcon(oNode, sTreeName) { //update the icons var icon = document.getElementById(sTreeName + oNode.getTreeRef() + gsCTREE_icon); if (icon) { //icon.src = getIconSrc(oNode); var toggleIcon = document.getElementById(sTreeName + oNode.getTreeRef() + gsCTREE_toggle + oNode.getTreeHierarchy()); //toggleIcon.src = getToggleSrc(oNode); toggleIcon.className = getToggleClassName(oNode); toggleIcon.title = getToggleTitle(oNode); var toggleText = ((toggleIcon.className == K_PRMT_TREE_TOGGLE_OPENED + oNode.m_oRoot.m_oTree.m_sDirection) ? "-" : "+"); var v_oTextSpanNode = toggleIcon.nextSibling; if (v_oTextSpanNode.textContent) { v_oTextSpanNode.textContent = toggleText; } else { //support IE v_oTextSpanNode.firstChild.data = toggleText; } } } //return plus or minus icons for the given node function getToggleClassName(node) { if (node.isOpen() == true) { return ( K_PRMT_TREE_TOGGLE_OPENED + node.m_oRoot.m_oTree.m_sDirection ); } else { return ( K_PRMT_TREE_TOGGLE_CLOSED + node.m_oRoot.m_oTree.m_sDirection ); } }