function nodeRel(PKey, parentNode, childNode, relationType) { // private vars var m_PKey=PKey; var m_parentNode=parentNode; var m_childNode=childNode; var m_displayDom=document.createElement("div"); var m_pointsContainer=null; // this is required for deletion, to delete all points one after the other didn't work. var m_relationType=(relationType==null)?"main":relationType; var m_parentX=0; var m_parentY=0; var m_childX=0; var m_childY=0; var m_styleClass="defaultPoint"; var m_contextMenu=null; // properties function getPKey() { return(m_PKey); } function getParentNode() { return(m_parentNode); } function setParentNode(nodeObject) { m_parentNode=nodeObject; } function getChildNode() { return(m_childNode); } function setChildNode(nodeObject) { m_childNode=nodeObject; } function getRelationType() { return(m_relationType); } function isMain() { return(m_relationType=="main"); } if (arguments.length >= 1) { return(construct()); } else { this.fromXML=fromXML; return(this); } function construct() { m_displayDom.setAttribute("id","mmNodeRel_" + m_PKey); m_displayDom.appendChild(createPointsContainer()); m_styleClass=(m_relationType=="main")?"defaultPoint":"freePoint"; // exported functions m_displayDom.debugOut=debugOut; m_displayDom.getPKey=getPKey; m_displayDom.getParentNode=getParentNode; m_displayDom.setParentNode=setParentNode; m_displayDom.getChildNode=getChildNode; m_displayDom.setChildNode=setChildNode; m_displayDom.redraw=redraw; m_displayDom.erase=erase; m_displayDom.show=show; m_displayDom.hide=hide; m_displayDom.isMain=isMain; m_displayDom.toXML=toXML; m_displayDom.fromXML=fromXML; document.getElementById("nodeRels").appendChild(m_displayDom); return(m_displayDom); } function show(){ m_displayDom.style.display="block"; } function hide(){ m_displayDom.style.display="none"; } function createPointsContainer(){ m_pointsContainer=document.createElement("div"); m_pointsContainer.setAttribute("id","mmPointsContainer_" + m_PKey); m_pointsContainer.onclick=onPointsContainerClick; // m_pointsContainer.oncontextmenu=onPointsContainerRightClick; return(m_pointsContainer); } function onPointsContainerClick(event){ if (m_contextMenu==null) { var menuItems = new Array(); menuItems[0]=new menuItem(document.createTextNode("Delete Relation"),erase); m_contextMenu=new menuControl(menuItems,1); m_pointsContainer.appendChild(m_contextMenu); document.addSubscriber(m_contextMenu.hide,"clicked"); } else { m_contextMenu.toggleVisible(); } m_contextMenu.style.top=(event.clientY + window.scrollY) + "px"; m_contextMenu.style.left=(event.clientX + window.scrollX) + "px"; return(false); } function debugOut() { var output=("\nPKey: _"+ m_PKey + "_\np/c PKeys:_" + m_parentNode.getPKey() + "/"+ m_childNode.getPKey() +"_ (" + m_relationType + ")" ); return(output); } function redraw() { var parentEle=getParentNode(); var childEle=getChildNode(); var parentX=parentEle.offsetLeft + (parentEle.offsetWidth/2); var parentY=parentEle.offsetTop + (parentEle.offsetHeight/2); var childX=childEle.offsetLeft + (childEle.offsetWidth/2); var childY=childEle.offsetTop + (childEle.offsetHeight/2); // performance: only redraw the line if the corrdinates changed. and both nodes are visible if ( ((m_parentX!=parentX) || (m_parentY!=parentY) || (m_childX!=childX) || (m_childY!=childY)) && (childEle.style.display != "none") && (parentEle.style.display != "none")) { eraseLine(); drawLine(parentX,parentY,childX,childY,m_styleClass,m_pointsContainer); m_parentX=parentX; m_parentY=parentY; m_childX=childX; m_childY=childY; } } function eraseLine() { m_displayDom.removeChild(m_pointsContainer); m_pointsContainer=createPointsContainer(); m_displayDom.appendChild(m_pointsContainer); } function erase() { if (isMain()) { // new rootnode by deleting main relation. rootNode[rootNode.length]=getChildNode(); } getChildNode().deleteNodeRelation(m_displayDom); getParentNode().deleteNodeRelation(m_displayDom); m_displayDom.parentNode.removeChild(m_displayDom); } function toXML(){ var xmlEle=document.createElement('NODEREL'); xmlEle.setAttribute("pkey",m_PKey); xmlEle.setAttribute("parentnodepkey",m_parentNode.getPKey()); xmlEle.setAttribute("childnodepkey",m_childNode.getPKey()); xmlEle.setAttribute("relationtype",m_relationType); // including child nodes if this is the main relation if (isMain()) { xmlEle.appendChild(m_childNode.toXML()); } return(xmlEle); } function fromXML(inXML){ m_PKey=inXML.getAttribute("pkey"); m_relationType=inXML.getAttribute("relationtype"); if (m_relationType == "") { m_relationType="main"; } m_displayDom.setAttribute("id","mmNodeRel_" + m_PKey); var parentNodePKey=inXML.getAttribute("parentnodepkey"); var childNodePKey=inXML.getAttribute("childnodepkey"); m_parentNode=document.getElementById("mmNode_" + parentNodePKey); if (inXML.childNodes.length > 0){ // Main-Relation m_childNode=new node().fromXML(inXML.firstChild); } else { // free links don't create nodes m_childNode=document.getElementById("mmNode_" + childNodePKey); if (m_childNode==null) { alert("Error: Assertion failed,\ncan't backlink NodePKey _ " + childNodePKey + "_"); } } m_childNode.addNodeRelation(m_displayDom); m_parentNode.addNodeRelation(m_displayDom); return(construct()); } }