/****************************SCRIPT POUR LE TREEVIEW DE LA BASE DE DONNEE************************/ /**To avoid name collision with others scripts, all variables and functions are in the TreeviewIT_DB namespace*/ var TreeviewIT_DB = {}; TreeviewIT_DB.ATTRIBUTE_TAG = "Attribute"; TreeviewIT_DB.ATTRIBUTE_NAME_ATTR = "name"; TreeviewIT_DB.ATTRIBUTE_VALUE_ATTR = "value"; /************************************************ XMLChildrenRequest Children request XML data object */ /* Construtor*/ TreeviewIT_DB.XMLChildrenRequest = function(attributes){ this.attributes = attributes; //associative array } /* Constants */ TreeviewIT_DB.XMLChildrenRequest.prototype.version = 1; TreeviewIT_DB.XMLChildrenRequest.prototype.TAG = "ChildrenRequest"; TreeviewIT_DB.XMLChildrenRequest.prototype.VERSION_ATTR = "version"; /* ToElement returns DOM element. 'doc' is a DOM document. */ TreeviewIT_DB.XMLChildrenRequest.prototype.toElement = function(doc){ var elem = doc.createElement(this.TAG); elem.setAttribute(this.VERSION_ATTR, this.version); for(var key in this.attributes){ var attrElem = doc.createElement(TreeviewIT_DB.ATTRIBUTE_TAG); attrElem.setAttribute(TreeviewIT_DB.ATTRIBUTE_NAME_ATTR, key); attrElem.setAttribute(TreeviewIT_DB.ATTRIBUTE_VALUE_ATTR, this.attributes[key]); elem.appendChild(attrElem); } return elem; } /************************************************ /** XMLChildrenResponse constructor attributes : - version - nodes (xmlnodes) */ TreeviewIT_DB.XMLChildrenResponse = function(){ } /** XMLChildrenResponse constants*/ TreeviewIT_DB.XMLChildrenResponse.prototype.TAG = "ChildrenResponse"; TreeviewIT_DB.XMLChildrenResponse.prototype.VERSION = "version"; /** Parses a DOM element as XMLChildrenResponse.*/ TreeviewIT_DB.XMLChildrenResponse.getInstance = function(elem){ var response = new TreeviewIT_DB.XMLChildrenResponse(); if(elem.getAttribute(TreeviewIT_DB.XMLChildrenResponse.prototype.VERSION) != 1){ throw "invalid version"; } response.version = elem.getAttribute(TreeviewIT_DB.XMLChildrenResponse.prototype.VERSION) response.nodes = new Array();//array of xmltreenode for(var i=0; i< elem.childNodes.length; i++){ var node = elem.childNodes[i]; if(node.nodeType == 1){ response.nodes.push(TreeviewIT_DB.XMLTreeNode.getInstance(node)); } } return response; } /************************************************ /** XMLTreeNode constructor. attributes - text - attributes - imageOpen - imageClosed - URL - URLTargetFrame - hasChildren - defaultOpen - children */ TreeviewIT_DB.XMLTreeNode = function(text, attributes){ this.text = text; this.attributes = attributes; } /** TreeNode constants.*/ TreeviewIT_DB.XMLTreeNode.prototype.TAG = "Node"; TreeviewIT_DB.XMLTreeNode.prototype.TEXT = "text"; TreeviewIT_DB.XMLTreeNode.prototype.IMAGE_OPEN = "openIcon"; TreeviewIT_DB.XMLTreeNode.prototype.IMAGE_CLOSED = "closedIcon"; TreeviewIT_DB.XMLTreeNode.prototype.URL = "URL"; TreeviewIT_DB.XMLTreeNode.prototype.URL_TARGET_FRAME = "URLTargetFrame"; TreeviewIT_DB.XMLTreeNode.prototype.HAS_CHILDREN = "hasChildren"; TreeviewIT_DB.XMLTreeNode.prototype.DEFAULT_OPEN = "isOpenByDefault"; /** Parses a DOM element and creates a XMLTreeNode object.*/ TreeviewIT_DB.XMLTreeNode.getInstance = function(elem){ var XMLTreeNode = TreeviewIT_DB.XMLTreeNode; if(elem.nodeType != 1){ throw "Invalid "; } var xmlNode = new TreeviewIT_DB.XMLTreeNode(); var attributes = new Array(); var xmlChildren = new Array(); var child = elem.firstChild; while(child!=null){ if(child.nodeName == TreeviewIT_DB.ATTRIBUTE_TAG){ attributes[child.getAttribute(TreeviewIT_DB.ATTRIBUTE_NAME_ATTR)]= child.getAttribute(TreeviewIT_DB.ATTRIBUTE_VALUE_ATTR); }else if(child.nodeName == this.prototype.TAG){ xmlChildren.push(TreeviewIT_DB.XMLTreeNode.getInstance(child)); }else{ throw "Invalid node"; } child = TreeviewIT_DB.nextSiblingElement(child); } xmlNode.text = elem.getAttribute(XMLTreeNode.prototype.TEXT); xmlNode.imageOpen = elem.getAttribute(XMLTreeNode.prototype.IMAGE_OPEN); xmlNode.imageClosed = elem.getAttribute(XMLTreeNode.prototype.IMAGE_CLOSED); xmlNode.URL = elem.getAttribute(XMLTreeNode.prototype.URL); xmlNode.URLTargetFrame = elem.getAttribute(XMLTreeNode.prototype.URL_TARGET_FRAME); xmlNode.hasChildren = (elem.getAttribute(XMLTreeNode.prototype.HAS_CHILDREN)=="false") ? false : true; xmlNode.defaultOpen = (elem.getAttribute(XMLTreeNode.prototype.DEFAULT_OPEN)=="false") ? false : true; xmlNode.attributes = attributes; xmlNode.children = xmlChildren; return xmlNode; } /**********************************************/ TreeviewIT_DB.Listener = function(){ }; TreeviewIT_DB.Listener.openNode = function(){ this.node.openNode(); } TreeviewIT_DB.Listener.closeNode = function(){ this.node.closeNode(); } /************************************************ TreeNode constructor. elem is the
HTML element. Properties: - treeView : the treeview object - elem : the
element of the node - hasChildren - children (new): the TreeNode objects - isExpanded - expImgElem (expand element) - iconImgElem - attributes - text - imageOpen - imageClosed - URL - URLTargetFrame - hasChildren - defaultOpen - isExpanded - isRoot (boolean) methods : getImageOpen() getImageClosed() */ TreeviewIT_DB.TreeNode = function(treeView, elem){ this.treeView = treeView; this.elem = elem; //
element. this.isRoot = false; } TreeviewIT_DB.TreeNode.prototype.getImageOpen = function(){ return (this.imageOpen !=null) ? this.imageOpen : this.treeView.defaultImageOpen; } TreeviewIT_DB.TreeNode.prototype.getImageClosed = function(){ return (this.imageClosed !=null) ? this.imageClosed : this.treeView.defaultImageClosed; } TreeviewIT_DB.TreeNode.prototype.openNode = function(){ //check if node var node = this; if(!this.hasChildren){ alert("Bug: has no children (openNode)"); //to do : remove + symbol return; } if(this.children == null){ this.isExpanded=true; //require this.expImgElem.src = this.treeView.waitImgSrc; //retrieves nodes (may be empty) var attributes = this.attributes; //prepare callback var callback = function(response){ if(response.nodes.length>0){ node.displayChildren(response.nodes); node.isExpanded=true; node.expImgElem.src=node.treeView.minusImgSrc; node.expImgElem.onclick=TreeviewIT_DB.Listener.closeNode; node.iconImgElem.src=node.getImageOpen(); node.iconImgElem.onclick=TreeviewIT_DB.Listener.closeNode; }else{ //hide expander node.expImgElem.src=this.treeView.emptyImgSrc; node.expImgElem.onclick=null; node.expImgElem.style.cursor = ""; node.iconImgElem.onclick=null; node.iconImgElem.style.cursor = ""; } } TreeviewIT_DB.query(attributes, this.treeView.script, callback); } else{ //display nodes this.isExpanded=true; this.expImgElem.src=this.treeView.minusImgSrc; this.expImgElem.onclick=TreeviewIT_DB.Listener.closeNode; this.iconImgElem.src=this.getImageOpen(); this.iconImgElem.onclick=TreeviewIT_DB.Listener.closeNode; for(var i in this.children){ this.children[i].elem.style.display="block"; } } } TreeviewIT_DB.Listener.closeNode = function(){ var node = this.node; if(!node.hasChildren){ //to do : remove + symbol return; } if(node.children == null){ alert("node.children=null ??"); } else{ node.isExpanded=false; node.expImgElem.src=node.treeView.plusImgSrc; node.expImgElem.onclick=TreeviewIT_DB.Listener.openNode; node.iconImgElem.src=node.getImageClosed(); node.iconImgElem.onclick=TreeviewIT_DB.Listener.openNode; for(var i in node.children){ var nodeElem = node.children[i].elem; nodeElem.style.display="none"; } } } TreeviewIT_DB.TreeNode.prototype.displayChildren = function(xmlnodes){ var parentNode = this; var treeView = this.treeView; for(var j=0; j < xmlnodes.length; j++){ var xmlnode = xmlnodes[j]; var nodeElem = document.createElement("div"); var node = new TreeviewIT_DB.TreeNode(treeView, nodeElem); if(!this.isExpanded){ nodeElem.style.display = "none"; } if(parentNode.isRoot){ nodeElem.className = "primaryNode"; }else{ nodeElem.className = "subNode"; } //if hasChildren and nodes don't match => nodes has priority node.parentNode = parentNode; node.treeView = parentNode.treeView; node.text = xmlnode.text; node.imageOpen = xmlnode.imageOpen; node.imageClosed = xmlnode.imageClosed; node.URL = xmlnode.URL; node.URLTargetFrame = xmlnode.URLTargetFrame; //by default, a node has children. node.hasChildren = (xmlnode.hasChildren != null && xmlnode.children.length < 1) ? xmlnode.hasChildren : true ; node.defaultOpen = xmlnode.defaultOpen; node.attributes = xmlnode.attributes; //not expanded if no information on nodes are send by server node.isExpanded = (xmlnode.children.length > 0 && node.defaultOpen); node.children = null; //content all the TreeNode children //update parent node if(parentNode.children == null){ parentNode.children = new Array(); } parentNode.children.push(node); //node table var tableElem = document.createElement("table"); tableElem.className = "tvNodeTable"; //tableElem.cellPadding = 0; tableElem.cellSpacing = 0; //bug IE 7 //var rowElem = document.createElement("tr"); //tableElem.appendChild(rowElem); var rowElem = tableElem.insertRow(0); rowElem.vAlign="top"; //expander image var expCellElem = document.createElement("td"); var expImgElem = document.createElement("img"); expImgElem.className="tvExpander"; expImgElem.style.cursor = "pointer"; var expImgSrc; if(!node.hasChildren){ expImgSrc = treeView.emptyImgSrc; expImgElem.style.cursor = ""; }else if(node.isExpanded){ expImgSrc = treeView.minusImgSrc; expImgElem.onclick = TreeviewIT_DB.Listener.closeNode; }else{ expImgSrc = treeView.plusImgSrc; expImgElem.onclick = TreeviewIT_DB.Listener.openNode; } expImgElem.node = node; expImgElem.src = expImgSrc; expCellElem.appendChild(expImgElem); rowElem.appendChild(expCellElem); node.expImgElem = expImgElem; //image (icon) : var iconCellElem = document.createElement("td"); var iconImgElem = document.createElement("img"); iconImgElem.className="tvIcon"; if(node.hasChildren){ iconImgElem.style.cursor = "pointer"; } var iconImgSrc; if(!node.hasChildren){ //closed not clicable iconImgSrc = node.getImageClosed(); //iconImgElem.onclick = ""; }else if(node.isExpanded){ //open iconImgSrc = node.getImageOpen(); iconImgElem.onclick = TreeviewIT_DB.Listener.closeNode; }else{ //closed iconImgSrc = node.getImageClosed(); iconImgElem.onclick = TreeviewIT_DB.Listener.openNode; } iconImgElem.node = node; iconImgElem.src = iconImgSrc; iconCellElem.appendChild(iconImgElem); node.iconImgElem = iconImgElem; rowElem.appendChild(iconCellElem); //text : var textCellElem = document.createElement("td"); textCellElem.className = "nodeText"; if(node.URL !=null){ var aElem = document.createElement("a"); aElem.href = node.URL; if(node.URLTargetFrame !=null){ aElem.target = node.URLTargetFrame; } aElem.innerHTML = node.text; textCellElem.appendChild(aElem); }else{ textCellElem.innerHTML = node.text; } rowElem.appendChild(textCellElem); nodeElem.appendChild(tableElem); if(xmlnode.children != null){ node.displayChildren(xmlnode.children); } //nodeElem.appendChild(textNode); parentNode.elem.appendChild(nodeElem); } } function debugXML(elem){ alert(xmlContent(elem)); } /** * Tree View object attributes: - loadingMessage - waitImgSrc - minusImgSrc - plusImgSrc - emptyImgSrc - id - attributes - script - rootNode (virtual root node) - defaultImageOpen - defaultImageClosed */ TreeviewIT_DB.TreeView = function(params){ treeView = this; //params reading treeView.id = params.id; treeView.loadingMessage = (params.loadingMessage != null) ? params.loadingMessage : " Loading..."; treeView.root = params.root; //object with text, icon, URL, URLTargetFrame treeView.defaultImageOpen = params.defaultImageOpen; treeView.defaultImageClosed = params.defaultImageClosed; treeView.minusImgSrc = params.minusImgSrc; treeView.waitImgSrc = params.waitImgSrc; treeView.plusImgSrc = params.plusImgSrc; treeView.emptyImgSrc = params.emptyImgSrc; var rootAttributes = params.attributes; var mon_action = params.mon_action; treeView.script = params.script; //process document.write("
"+treeView.loadingMessage+"
"); var tvElem = document.getElementById(treeView.id); //prepare callback var callback = function(response){ tvElem.innerHTML=""; //delete loading //display the root elem if asked if(treeView.root !=null && treeView.root.text !=null){ //node table var tableElem = document.createElement("table"); tableElem.className = "tvNodeTable"; tableElem.cellSpacing = 0; var rowElem = tableElem.insertRow(0); rowElem.vAlign="top"; //image (icon) : var iconCellElem = document.createElement("td"); var iconImgElem = document.createElement("img"); iconImgElem.className="tvIcon"; iconImgElem.src = (treeView.root.icon != null) ? treeView.root.icon : treeView.defaultImageOpen; iconCellElem.appendChild(iconImgElem); rowElem.appendChild(iconCellElem); //text : var textCellElem = document.createElement("td"); textCellElem.className = "nodeText"; if(treeView.root.URL !=null){ var aElem = document.createElement("a"); aElem.href = this.root.URL; if(treeView.root.URLTargetFrame !=null){ aElem.target = treeView.root.URLTargetFrame; } aElem.innerHTML = treeView.root.text; textCellElem.appendChild(aElem); }else{ textCellElem.innerHTML = treeView.root.text; } rowElem.appendChild(textCellElem); tvElem.appendChild(tableElem); } var rootNode = new TreeviewIT_DB.TreeNode(treeView, tvElem); rootNode.isRoot = true; rootNode.isExpanded = true; //rootNode.hasChildren = true; treeView.rootNode = rootNode; rootNode.displayChildren(response.nodes); } //query TreeviewIT_DB.query(rootAttributes, treeView.script, callback); } /**Asynchronous query. *Return without value. *Call callback with reponse element *if script is null, the same page is called. */ TreeviewIT_DB.query = function(attributes, script, callback){ //prepare request var request = new TreeviewIT_DB.XMLChildrenRequest(attributes); var doc = TreeviewIT_DB.newDoc(); var elem = request.toElement(doc); doc.appendChild(elem); //send request var xmlhttp = TreeviewIT_DB.getHTTPObject(); xmlhttp.onreadystatechange = function (){ if(xmlhttp.readyState == 4){ if(xmlhttp.status!=200){ alert("Problem retrieving XML data"); } try{ //alert("Server response: "+xmlhttp.responseText); var responseElem = xmlhttp.responseXML.documentElement; var response = TreeviewIT_DB.XMLChildrenResponse.getInstance(responseElem); callback(response); }catch(e){ var text = xmlhttp.responseText; alert("Error:\n bad server response: "+e+"\nData:"+text); } } } if(script!=null){ xmlhttp.open("POST", script, true); }else{ xmlhttp.open("POST", location.href, true); } //alert("Server send: "+TreeviewIT_DB.xmlContent(doc)); xmlhttp.send(doc); } //--------- //DOM TOOLS //--------- /** Returns the next sibling element of a given node.*/ TreeviewIT_DB.nextSiblingElement = function(node){ var next = node.nextSibling; while(next!=null && next.nodeType!=1){ next = next.nextSibling; } return next; } /** Returns a new DOM document (works in IE and Firefox).*/ TreeviewIT_DB.newDoc = function(){ if (document.implementation && document.implementation.createDocument) { return document.implementation.createDocument("", "", null); } else if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLDOM"); } else { alert('Your browser can\'t handle this script'); return; } } /** Returns the XML HTTP Request object (works in IE and Firefox).*/ TreeviewIT_DB.getHTTPObject = function() { var xmlhttp; if(window.XMLHttpRequest) { //pour ffox et mozilla try { xmlhttp = new XMLHttpRequest(); } catch(e) { xmlhttp = false; } } else if(window.ActiveXObject) { //pour ie try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { xmlhttp = false; } } } return xmlhttp; } /** Serializes an XML DOM object into a string.*/ TreeviewIT_DB.xmlContent = function(xmlObj) { if(xmlObj.xml){ return xmlObj.xml; } else { var serializer = new XMLSerializer(); return serializer.serializeToString(xmlObj); } }