/* Copyright Scand LLC http://www.scbr.com This version of Software is free for using in non-commercial applications. For commercial use please contact info@scbr.com to obtain license */ /*_TOPICS_ @0:Initialization @1:Selection control @2:Add/delete @3:Private @4:Node/level control @5:Checkboxes/user data manipulation @6:Appearence control */ /** * @desc: tree constructor * @param: htmlObject - parent html object or id of parent html object * @param: width - tree width * @param: height - tree height * @param: rootId - id of virtual root node * @type: public * @topic: 0 */ function dhtmlXTreeObject(htmlObject, width, height, rootId){ this._isOpera=(navigator.userAgent.indexOf('Opera')!= -1); if (typeof(htmlObject)!="object") this.parentObject=document.getElementById(htmlObject); else this.parentObject=htmlObject; this.xmlstate=0; this.mytype="tree"; this.smcheck=true; //smart checkboxes this.width=width; this.height=height; this.rootId=rootId; this.childCalc=null; this.def_img_x="18px"; this.def_img_y="18px"; this.style_pointer="pointer"; if (navigator.appName == 'Microsoft Internet Explorer') this.style_pointer="hand"; this._aimgs=true; this.htmlcA=" ["; this.htmlcB="]"; this.lWin=window; this.cMenu=0; this.mlitems=0; this.dadmode=0; this.slowParse=false; this.autoScroll=true; this.hfMode=0; this.nodeCut=0; this.XMLsource=0; this.XMLloadingWarning=0; this._globalIdStorage=new Array(); this.globalNodeStorage=new Array(); this._globalIdStorageSize=0; this.treeLinesOn=true; this.checkFuncHandler=0; this.openFuncHandler=0; this.dblclickFuncHandler=0; this.tscheck=false; this.timgen=true; this.dpcpy=false; this.imPath="treeGfx/"; this.checkArray=new Array("iconUnCheckAll.gif","iconCheckAll.gif","iconCheckGray.gif","iconUncheckDis.gif"); this.lineArray=new Array("line2.gif","line3.gif","line4.gif","blank.gif","blank.gif"); this.minusArray=new Array("minus2.gif","minus3.gif","minus4.gif","minus.gif","minus5.gif"); this.plusArray=new Array("plus2.gif","plus3.gif","plus4.gif","plus.gif","plus5.gif"); this.imageArray=new Array("leaf.gif","folderOpen.gif","folderClosed.gif"); this.cutImg= new Array(0,0,0); this.cutImage="but_cut.gif"; this.dragger= new dhtmlDragAndDropObject(); //create root this.htmlNode=new dhtmlXTreeItemObject(this.rootId,"",0,this); this.htmlNode.htmlNode.childNodes[0].childNodes[0].style.display="none"; this.htmlNode.htmlNode.childNodes[0].childNodes[0].childNodes[0].className="hiddenRow"; //init tree structures this.allTree=this._createSelf(); this.allTree.appendChild(this.htmlNode.htmlNode); this.allTree.onselectstart=new Function("return false;"); this.XMLLoader=new dtmlXMLLoaderObject(this._parseXMLTree,this); this.selectionBar=document.createElement("DIV"); this.selectionBar.className="selectionBar"; this.selectionBar.innerHTML=" "; //this.selectionBar.style.left=getAbsoluteLeft(this.allTree); if (this.allTree.offsetWidth>20) this.selectionBar.style.width=this.allTree.offsetWidth-20; this.selectionBar.style.display="none"; this.allTree.appendChild(this.selectionBar); /* this.selectionBox=document.createElement("DIV"); this.selectionBox.className="selectionBox"; this.selectionBox.innerHTML=" "; //this.selectionBar.style.left=getAbsoluteLeft(this.allTree); this.selectionBox.style.width=this.allTree.offsetWidth; this.selectionBox.style.height=this.allTree.offsetHeight; this.selectionBox.style.display="none"; this.allTree.appendChild(this.selectionBox);*/ return this; }; /** * @desc: tree node constructor * @param: itemId - node id * @param: itemText - node label * @param: parentObject - parent item object * @param: treeObject - tree object * @param: actionHandler - onclick event handler(optional) * @param: mode - do not show images * @type: private * @topic: 0 */ function dhtmlXTreeItemObject(itemId,itemText,parentObject,treeObject,actionHandler,mode){ this.htmlNode=""; this.acolor=""; this.scolor=""; this.tr=0; this.childsCount=0; this.tempDOMM=0; this.tempDOMU=0; this.dragSpan=0; this.dragMove=0; this.span=0; this.closeble=1; this.childNodes=new Array(); this.userData=new Object(); this.checkstate=0; this.treeNod=treeObject; this.label=itemText; this.parentObject=parentObject; this.actionHandler=actionHandler; this.images=new Array(treeObject.imageArray[0],treeObject.imageArray[1],treeObject.imageArray[2]); this.id=treeObject._globalIdStorageAdd(itemId,this); if (this.treeNod.checkBoxOff ) this.htmlNode=this.treeNod._createItem(1,this,mode); else this.htmlNode=this.treeNod._createItem(0,this,mode); this.htmlNode.objBelong=this; return this; }; /** * @desc: register node * @type: private * @param: itemId - node identificator * @param: itemObject - node object * @topic: 3 */ dhtmlXTreeObject.prototype._globalIdStorageAdd=function(itemId,itemObject){ if (this._globalIdStorageFind(itemId,1,1)) { d=new Date(); itemId=d.valueOf()+"_"+itemId; return this._globalIdStorageAdd(itemId,itemObject); } this._globalIdStorage[this._globalIdStorageSize]=itemId; this.globalNodeStorage[this._globalIdStorageSize]=itemObject; this._globalIdStorageSize++; return itemId; }; /** * @desc: unregister node * @type: private * @param: itemId - node identificator * @topic: 3 */ dhtmlXTreeObject.prototype._globalIdStorageSub=function(itemId){ for (var i=0; i0) { beforeNode=new Object; beforeNode.tr=parentObject.childNodes[0].tr.previousSibling; } for (ik=0; ik=2) { this._correctPlus(Nodes[parentObject.childsCount-2]); this._correctLine(Nodes[parentObject.childsCount-2]); } if (parentObject.childsCount!=2) this._correctPlus(Nodes[0]); if (this.tscheck) this._correctCheckStates(parentObject); } if (this.cMenu) this.cMenu.setContextZone(Nodes[Count].span,Nodes[Count].id); return Nodes[Count]; }; /** * @desc: create new node, next to existing * @type: public * @param: parentId - parent node id * @param: itemId - new node id * @param: itemText - new node text * @param: itemActionHandler - function fired on node select event (optional) * @param: image1 - image for node without childrens; (optional) * @param: image2 - image for closed node; (optional) * @param: image3 - image for opened node (optional) * @param: optionStr - options string (optional) * @param: childs - node childs flag (for dynamical trees) (optional) * @topic: 2 */ dhtmlXTreeObject.prototype.insertNewItem=function(parentId,itemId,itemText,itemActionHandler,image1,image2,image3,optionStr,childs){ var parentObject=this._globalIdStorageFind(parentId); if (!parentObject) return (-1); return this._attachChildNode(parentObject,itemId,itemText,itemActionHandler,image1,image2,image3,optionStr,childs); }; /** * @desc: parse xml * @type: private * @param: dhtmlObject - jsTree object * @param: node - top XML node * @param: parentId - parent node id * @param: level - level of tree * @topic: 2 */ dhtmlXTreeObject.prototype._parseXMLTree=function(dhtmlObject,node,parentId,level){ //alert("s"+dhtmlObject.parsCount+"-"+parentId); if (!dhtmlObject.parsCount) dhtmlObject.parsCount=1; else dhtmlObject.parsCount++; //alert("x"+dhtmlObject.parsCount+"-"+parentId); dhtmlObject.XMLloadingWarning=1; var nodeAskingCall=""; if (!node) { node=dhtmlObject.XMLLoader.getXMLTopNode("tree"); parentId=node.getAttribute("id"); dhtmlObject.parsingOn=parentId; dhtmlObject.parsedArray=new Array(); dhtmlObject.setCheckList=""; } if (node.getAttribute("order")) dhtmlObject._reorderXMLBranch(node); for(var i=0; i0) { for (var a=0; athis._getNodeLevel(nodeB,0)) { return this._moveNodeTo(itemObject,nodeA.parentObject); } else { // if (this._checkParenNodes(itemObject.id,d)) return; return this._moveNodeTo(itemObject,nodeB.parentObject,nodeB); } /* if ((!targetObject.tr.nextSibling)||(!targetObject.tr.nextSibling.nodem)) return this._moveNodeTo(itemObject,targetObject.parentObject); //move in middle of group else return this._moveNodeTo(itemObject,targetObject.parentObject,targetObject.tr.nextSibling.nodem); */ // debugger; } else return this._moveNodeTo(itemObject,targetObject); } /** * @desc: fix order of nodes in collection * @type: private * @param: target - parent item node * @param: zParent - before node * @topic: 2 */ dhtmlXTreeObject.prototype._fixNodesCollection=function(target,zParent){ var flag=0; var icount=0; var Nodes=target.childNodes; var Count=target.childsCount-1; if (zParent==Nodes[Count]) return; for (var i=0; i0))) if (!htmlNode.nocheckbox) { if (list) list+=","+htmlNode.id; else list=htmlNode.id; } var j=htmlNode.childsCount; for (var i=0; iz.childsCount)) return null; return z.childNodes[index].id; }; /** * @desc: retun child node identificator by index * @type: public * @param: itemId - parent node identificator * @param: index - index of child node * @return: node id * @topic: 1 */ dhtmlXTreeObject.prototype.getChildItemIdByIndex=function(itemId,index){ var z=this._globalIdStorageFind(itemId); if ((!z)||(index>z.childsCount)) return null; return z.childNodes[index].id; }; /** * @desc: set function called when drag-and-drop event occured * @param: aFunc - event handling function * @type: public * @topic: 0 * @event: onDrag * @eventdesc: Event occured after item was dragged and droped on another item, but before item moving processed. Event also raised while programmatic moving nodes. * @eventparam: ID of source item * @eventparam: ID of target item * @eventparam: if node droped as sibling then contain id of item before whitch source node will be inserted * @eventparam: source Tree object * @eventparam: target Tree object * @eventreturn: true - confirm drag-and-drop; false - deny drag-and-drop; */ dhtmlXTreeObject.prototype.setDragHandler=function(func){ if (typeof(func)=="function") this.dragFunc=func; else this.dragFunc=eval(func); }; /** * @desc: clear selection from node * @param: htmlNode - pointer to node object * @type: private * @topic: 1 */ dhtmlXTreeObject.prototype._clearMove=function(htmlNode){ if ((htmlNode.parentObject)&&(htmlNode.parentObject.span)) { htmlNode.parentObject.span.className='standartTreeRow'; if (htmlNode.parentObject.acolor) htmlNode.parentObject.span.style.color=htmlNode.parentObject.acolor; } this.selectionBar.style.display="none"; //this.selectionBox.style.display="none"; this.allTree.className="containerTableStyle"; }; /** * @desc: enable/disable drag-and-drop * @type: public * @param: mode - enabled/disabled * @topic: 0 */ dhtmlXTreeObject.prototype.enableDragAndDrop=function(mode){ this.dragAndDropOff=convertStringToBoolean(mode); if (this.dragAndDropOff) this.dragger.addDragLanding(this.allTree,this); }; /** * @desc: set selection on node * @param: node - pointer to node object * @type: private * @topic: 1 */ dhtmlXTreeObject.prototype._setMove=function(htmlNode,x,y){ if (htmlNode.parentObject.span) { //window.status=x; var a1=getAbsoluteTop(htmlNode); var a2=getAbsoluteTop(this.allTree); this.dadmodec=this.dadmode;//this.dadmode; this.dadmodefix=0; if (this.dadmodec==0) { htmlNode.parentObject.span.className='selectedTreeRow'; if (htmlNode.parentObject.scolor) htmlNode.parentObject.span.style.color=htmlNode.parentObject.scolor; } else{ htmlNode.parentObject.span.className='standartTreeRow'; if (htmlNode.parentObject.acolor) htmlNode.parentObject.span.style.color=htmlNode.parentObject.acolor; this.selectionBar.style.top=a1-a2+16+this.dadmodefix; this.selectionBar.style.left=5; this.selectionBar.style.display=""; } if (this.autoScroll) { //scroll down if ( (a1-a2-parseInt(this.allTree.scrollTop))>(parseInt(this.allTree.offsetHeight)-50) ) this.allTree.scrollTop=parseInt(this.allTree.scrollTop)+20; //scroll top if ( (a1-a2)<(parseInt(this.allTree.scrollTop)+30) ) this.allTree.scrollTop=parseInt(this.allTree.scrollTop)-20; } } }; /** * @desc: create html element for dragging * @type: private * @param: htmlObject - html node object * @topic: 1 */ dhtmlXTreeObject.prototype._createDragNode=function(htmlObject){ dhtmlObject=htmlObject.parentObject; if (this.lastSelected) this._clearMove(this.lastSelected); var dragSpan=document.createElement('div'); dragSpan.innerHTML=dhtmlObject.label; dragSpan.style.position="absolute"; dragSpan.className="dragSpanDiv"; return dragSpan; } ///DragAndDrop dhtmlXTreeObject.prototype._preventNsDrag=function(e){ if ((e)&&(e.preventDefault)) { e.preventDefault(); return false; } return false; } dhtmlXTreeObject.prototype._drag=function(sourceHtmlObject,dhtmlObject,targetHtmlObject){ if (this._autoOpenTimer) clearTimeout(this._autoOpenTimer); if (!targetHtmlObject.parentObject){ targetHtmlObject=this.htmlNode.htmlNode.childNodes[0].childNodes[0].childNodes[1].childNodes[0]; this.dadmodec=0; } this._clearMove(targetHtmlObject); var z=targetHtmlObject.parentObject.treeNod; z._clearMove(""); //if (z.lastSelected) z._setMove(z.lastSelected); if ((!this.dragMove)||(this.dragMove())) { var newID=this._moveNode(sourceHtmlObject.parentObject,targetHtmlObject.parentObject); z.selectItem(newID); } try{ } catch(e){ return; } } dhtmlXTreeObject.prototype._dragIn=function(htmlObject,shtmlObject,x,y){ if (!htmlObject.parentObject) { //this.selectionBox.style.display=""; //this.selectionBox.style.top=this.allTree.scrollTop; this.allTree.className="containerTableStyle selectionBox"; //if (this.htmlNode.childsCount==0) return htmlObject; //else return 0; } if ( (!this._checkParenNodes(shtmlObject.parentObject.id,htmlObject.parentObject,shtmlObject.parentObject))&&(htmlObject.parentObject.id!=shtmlObject.parentObject.id)) { htmlObject.parentObject.span.parentNode.appendChild(this.selectionBar); this._setMove(htmlObject,x,y); if (this._getOpenState(htmlObject.parentObject)<0) this._autoOpenTimer=window.setTimeout(new callerFunction(this._autoOpenItem,this),1000); this._autoOpenId=htmlObject.parentObject.id; return htmlObject; } else return 0; } dhtmlXTreeObject.prototype._autoOpenItem=function(e,treeObject){ treeObject.openItem(treeObject._autoOpenId); }; dhtmlXTreeObject.prototype._dragOut=function(htmlObject){ this._clearMove(htmlObject); if (this._autoOpenTimer) clearTimeout(this._autoOpenTimer); } /** * @desc: return next node * @type: private * @param: item - node object * @param: mode - inner flag * @return: next node or -1 * @topic: 2 */ dhtmlXTreeObject.prototype._getNextNode=function(item,mode){ if ((!mode)&&(item.childsCount)) return item.childNodes[0]; if (item==this.htmlNode) return -1; if ((item.tr)&&(item.tr.nextSibling)&&(item.tr.nextSibling.nodem)) return item.tr.nextSibling.nodem; return this._getNextNode(item.parentObject,true); }; /** * @desc: return last child of item (include all sub-child collections) * @type: private * @param: item - node object * @topic: 2 */ dhtmlXTreeObject.prototype._lastChild=function(item){ if (item.childsCount) return this._lastChild(item.childNodes[item.childsCount-1]); else return item; }; /** * @desc: return previous node * @type: private * @param: item - node object * @param: mode - inner flag * @return: previous node or -1 * @topic: 2 */ dhtmlXTreeObject.prototype._getPrevNode=function(node,mode){ if ((node.tr)&&(node.tr.previousSibling)&&(node.tr.previousSibling.nodem)) return this._lastChild(node.tr.previousSibling.nodem); if (node.parentObject) return node.parentObject; else return -1; };