PathwayDiagramPane = function() {};

Object
		.extend(
				PathwayDiagramPane.prototype,
				{
					// Configuration
					imgwww : "", // could get images from another server
					basedir : "/entitylevelview/pathway_diagram_statics/",
					diagramhighlitesurl : '/cgi-bin/entitylevelview/diagramhighlites',
					maxz : 4, // max zoom level
					z : 1, // zoom level
					dz : 1, // default zoom multiplier
					dx : 25, // the number of pixels to move the image (left-right)
					dy : 25, // the number of pixels to move the image (up-down)
					tilewidth : 200, // standard width of each tile
					tileheight : 200, // standard height of each tile
					highliteBorderThickness : 5,
					thumbnailw : 100,
					thumbnailh : 100,

					// Class/object variables set dynamically
					db : null,
					current_instance_id : null,
					focus_species_id : null,
					focus_pathway_id : null,
					representedInstances : null,
					highlitedCoordinates : new Array(),
					orderedRepresentedInstances : new Array(),
					nodes : null, // EntityVertex db_id
					refdbnodes : null, // ReferenceEntity db_id
					dbnodes : null, // PhysicalEntity db_id
					complexnodes : null, // complex nodes (PhysicalEntity)
					node2highlite : new Object(),
					dbidOfNodeBeingHighlited : null,
					transientHighliteIdCache : new Hash(),
					imgdir : null, // image home directory (where the images live)
					imgw : null,
					imgh : null,
					imgx : 0, // absolute image width
					imgy : 0, // absolute image height
					ntilesx : 0, // number of tiles (x)
					ntilesy : 0, // number of tiles (y)
					starty : 0, // default starting position of image (y)
					startx : 0, // default starting position of image (x)
					inLoadTransientHighlites : false,
					iDiffX : 0,
					iDiffY : 0,
					iOrigLeft : null,
					iOrigTop : null,
					viewportRight : null,
					viewportTop : null,
					viewportBottom : null,
					highlitesInViewportOnly : true,
					zoomChange : null,
					iThumbDiffX : 0,
					iThumbDiffY : 0,
					expressionPainter : null,
					currentExperiment : 0,
					
					paintExpressionData : 0,
					noHitBG : "RGB(170,170,170)", // Used to colour nodes that have no hits in 
					// data inputted for expression painter.
					cpbg : "RGB(240,240,240)", // Background used for table displaying expression levels
					// of complex participating molecules.
					complexCellLength : 50, // length/width of cells representing component proteins for 
					// complex expression painter display.
					zoomFactor : 1, //zoomFactor 1 corresponds to zoom level (z) 1, 0.5 -> 2, 0.25 -> 3, 0.125 -> 4, 0.0625 -> 5
					currentCplxNode : null, // keep track of which node popup is displayed for so data can be reused if repainting required
					// Event that is fired when a diagram node is clicked.
					// Subscribe to this event if you
					// want to react somehow to the user clicking the node. This
					// is e.g. how PathwayBrowser
					// is informed that the node has been clicked.
					diagramNodeClickedEvent : new YAHOO.util.CustomEvent(
							"DiagramNodeClickedEvent", this),

					menuItemClickedEvent : new YAHOO.util.CustomEvent(
							"menuItemClickedEvent", this),
							
					diagramLoadedEvent : new YAHOO.util.CustomEvent(
							"diagramLoadedEvent", this),

					// Event that is fired when zoom level is changed.
					zoomChange : new YAHOO.util.CustomEvent('zoom level change'),
					actorDiffX : 0,
					actorDiffY : 0,
					xOrigin : 0,
					yOrigin : 0,
<<<<<<< PathwayDiagramPane.js
<<<<<<< PathwayDiagramPane.js
					interaction : null,
					mytip : null,
=======
					speciesComparator: null,
=======
					complexpopupZ:50,
					speciesdata:null,
					displayComparison:0,
					defaultBackgroundColour : 'rgb(174,174,174)',
>>>>>>> 1.66
					controlPanel : null,
					fiDisplay : null,
					oContextMenu : null,
					tipZ : 21, //z index of tip displayed when node moused over.
					miCanvasMargin : 500, /* Leave a margin around diagram so that interactors are displayed even if they are not on diagram */
					intactSearchUrl : "http://www.ebi.ac.uk/intact/search/do/search?searchString=EBIINTERACTION",
>>>>>>> 1.41

					// Initialise
					init : function() {
						this.oContextMenu = new ContextMenu();
						this.oContextMenu.init(this.db);
						this.controlPanel = new ControlPanel();
						this.controlPanel.init(null);

						this.init_handlers();
						if (this.db && this.focus_species_id
								&& this.focus_pathway_id) {
							this.setImgDir();
							this.loadOrderedCoordinates();
						}
						this.expressionPainter = new ExpressionPainter();
						this.expressionPainter.init(15);
<<<<<<< PathwayDiagramPane.js
<<<<<<< PathwayDiagramPane.js
=======
						this.speciesComparator = new SpeciesComparator();
						this.speciesComparator.init();
						this.controlPanel = new ControlPanel();
						this.controlPanel.init();
=======
>>>>>>> 1.66
						this.fiDisplay = new FIDisplay();
<<<<<<< PathwayDiagramPane.js
						this.fiDisplay.init(this.intactSearchUrl);

>>>>>>> 1.41
=======
						this.fiDisplay.init(this.intactSearchUrl, this.miCanvasMargin);
>>>>>>> 1.66
					},
					// Set up the handlers for various events
					init_handlers : function() {
						var t = this;
						YAHOO.util.Event.addListener('clipwindow', 'mousedown',
								this.engage, this, true);
<<<<<<< PathwayDiagramPane.js
						YAHOO.util.Event.addListener('clipwindow', 'mouseover',
								function() {
									YAHOO.util.Event.addListener(document,
											'keypress', this.keypresshandler,
											this, true);
								}, this, true);
=======
>>>>>>> 1.41
						YAHOO.util.Event.addListener('clipwindow', 'mousemove',
								this.handleMoveOverCanvas, this, true);
						YAHOO.util.Event.addListener('clipwindow', 'mouseout',
								function() {
									YAHOO.util.Event.removeListener(document,
											'keypress', this.keypresshandler)
								}, this, true);
						YAHOO.util.Event.addListener('thumbwindow',
								'mousedown', this.engageThumb, this, true);
						YAHOO.util.Event.addListener('thumbnail', 'mousedown',
								this.engageThumbnail, this, true);
						// Add listeners for right & left experiment browser
						// arrows
						YAHOO.util.Event
								.addListener(
										'experimentrightarrow',
										'mousedown',
										function() {
											this.currentExperiment++;
											if (this.currentExperiment > (this.expressionPainter.columnCount - 1)) {
												this.currentExperiment = 0;
											}
											this.displayExpressionLevels();
											this.updateComplexPopup();
										}, this, true);
						YAHOO.util.Event
								.addListener(
										'experimentleftarrow',
										'mousedown',
										function() {
											this.currentExperiment--;
											if (this.currentExperiment < 0) {
												this.currentExperiment = this.expressionPainter.columnCount - 1;
											}
											this.displayExpressionLevels();
											this.updateComplexPopup();
										}, this, true);
						YAHOO.util.Event
								.addListener(
										'experimentclose',
										'mousedown',
										function() {
											this.currentExperiment = 0;
											this.paintExpressionData = 0;
											$("canvasoverlay")
													.getElementsBySelector(
															'div.expressiontips')
													.invoke('remove');
											var complexpopup = $("ficanvas").getElementsBySelector('div.cplxcompstip');
											if(complexpopup){
												complexpopup.invoke('remove');
											}
											this.expressionPainter = null;
											this.expressionPainter = new ExpressionPainter();
											this.expressionPainter.init(15);
											this.expressionPainter
													.setExpressionVisibility("hidden");
											this.fiDisplay.resetQueryTerminals();
										}, this, true);
						YAHOO.util.Event.addListener($("speciesclose"), "mousedown", this.onSpeciesComparisonClose, this, true);
						this.oContextMenu.menuItemClickedEvent.subscribe(this.onCtxMenuItemClick.bind(this), this);
						this.init_slider();
						this.bindListenersToMapNavigationArrow();
						this.controlPanel.tableBuiltEvent.subscribe(this.interactionTableBuiltHandler.bind(this));
						this.controlPanel.rowClickedEvent.subscribe(this.interactionEntryClickedHandler.bind(this));
						this.controlPanel.displayInteractorsButtonClickedEvent.subscribe(this.displayInteractorsButtonClickedHandler.bind(this));
					},
					init_slider : function() {
						var Event = YAHOO.util.Event, Dom = YAHOO.util.Dom, lang = YAHOO.lang, slider, bg = "slider-bg", thumb = "slider-thumb", valuearea = "slider-value", textfield = "slider-converted-value";
						var topConstraint = 0;
						var bottomConstraint = 60;
						var scaleFactor = 20;
						var keyIncrement = 20;
						var tickSize = 20;
						var t = this;
						// Even though the init is done when DOM is ready we
						// still need to put the
						// following in a separate onDOMReady as otherwise the
						// slide thumb would "jump"
						// outside its normal path.
						YAHOO.util.Event.onDOMReady( function() {
							slider = YAHOO.widget.Slider.getVertSlider(bg,
									thumb, topConstraint, bottomConstraint,
									tickSize);

								t.zoomChange.subscribe(t._setZoomLevel.bind(t),
										slider);
								slider.getRealValue = function() {
									return Math.round(this.getValue()
											/ scaleFactor + 1);
								}
								slider.setRealValue = function(value) {
									slider.setValue((value - 1) * scaleFactor);
								}
								slider.subscribe("change", function(
										offsetFromStart) {
									var actualValue = slider.getRealValue();
									// Update the title attribute on the
									// background. This helps assistive
										// technology to communicate the state
										// change
										Dom.get(bg).title = "slider value = "
												+ actualValue;
										t.zoomChange.fire(actualValue);
									});
								slider.setRealValue(t.z);
							});
					},
					_setZoomLevel : function(type, zl, slider) {
						log(type + ", " + zl + ", " + slider);
						this.removeImageTiles();
						this.setZoomLevel(zl);
						slider.setRealValue(zl);
					},
					// Set up the handlers for navigation arrows
					bindListenersToMapNavigationArrow : function() {
						if ($('uparrow') && $('leftarrow') && $('rightarrow')
								&& $('downarrow')) {
							Event.observe('uparrow', 'click',
									this.animatedReposition.bind(this, 0, 100));
							Event.observe('leftarrow', 'click',
									this.animatedReposition.bind(this, 100, 0));
							Event
									.observe('rightarrow', 'click',
											this.animatedReposition.bind(this,
													-100, 0));
							Event
									.observe('downarrow', 'click',
											this.animatedReposition.bind(this,
													0, -100));
						}
					},
					// select image to drag
					engage : function(oEvent) {
						/* Put this in to stop a display bug infirefox on linux where holding the left
						 * mouse button down and dragging would result in glitches, including staying
						 * in drag mode when left mouse button was released.
						 */
						if(oEvent.preventDefault){
							oEvent.preventDefault();
						}else {
							oEvent.returnValue = false; 
						}
						var oCanvas = $("canvas");
						var oClipwindow = $("clipwindow");
						// calculate offset
						this.iDiffX = oEvent.clientX - oCanvas.offsetLeft;
						this.iDiffY = oEvent.clientY - oCanvas.offsetTop;
						// change cursor to hand
						oClipwindow.style.cursor = "move";
						// setup event handlers
						YAHOO.util.Event.addListener(document.body,
								"mousedown", this.mousedown, this, true);
						YAHOO.util.Event.addListener(document.body,
								"mousemove", this.move, this, true);
						YAHOO.util.Event.addListener(document.body, "mouseup",
								this.drop, this, true);
						/* disable mousemovehandler as it makes Safari noticably
						 * sluggish.
						 */
						YAHOO.util.Event.removeListener('clipwindow',
								'mousemove', this.handleMoveOverCanvas);
					},
					// Drag image
					move : function(oEvent) {
						var oCanvas = $("canvas");
						// set new position
						oCanvas.style.left 	= oEvent.clientX - this.iDiffX;
						oCanvas.style.top 	= oEvent.clientY - this.iDiffY;
						// refresh screen
						this.reposition(0, 0);
					},
					mousedown : function(oEvent) {
						if (Event.element(oEvent).tagName == "IMG") {
							Event.stop(oEvent);
						}
					},
					// stop dragging image
					drop : function(oEvent) {
						var oClipwindow = $("clipwindow");
						// turn off events
						YAHOO.util.Event.removeListener(document.body,
								"mousemove", this.move);
						YAHOO.util.Event.removeListener(document.body,
								"mouseup", this.drop);
						YAHOO.util.Event.removeListener(document.body,
								"mousedown", this.mousedown);
						// Re-instate mousemovehandler.
						YAHOO.util.Event.addListener('clipwindow', 'mousemove',
								this.handleMoveOverCanvas, this, true);
						// change cursor back to normal
						oClipwindow.style.cursor = "default";
					},
					handleMoveOverCanvas : function(oEvent) {
						//log("handleMoveOverCanvas()");
						var oClipwindow = $("clipwindow");
						var cwPos = Position.cumulativeOffset(oClipwindow);
						var clipWindowX = YAHOO.util.Event.getPageX(oEvent)
								- cwPos[0];
						var clipWindowY = YAHOO.util.Event.getPageY(oEvent)
								- cwPos[1];
						var oCanvas = $("canvas");
						var cPos = this.getPositionByStyle(oCanvas);
						var canvasX = (-cPos[0] + clipWindowX)
								/ this.zoomFactor;
						var canvasY = (-cPos[1] + clipWindowY)
								/ this.zoomFactor;
						var node = this.findNodeAtCoordinate(canvasX, canvasY);
						if (node != null) {
							this.handleHighliteMouseover(oEvent, node.id);
						}else{
							// Add a check to see if menu displayed before destroying.
							this.oContextMenu.destroyMenuIfNecessary();
							this.hideToolTipsIfNecessary(canvasX, canvasY);
						}
					},
					hideToolTipsIfNecessary : function(canvasX, canvasY){
						if($("canvasoverlay")){
						var localX = canvasX * this.zoomFactor;
						var localY = canvasY * this.zoomFactor;
						var tipList = $("canvas").getElementsBySelector('div.tip');
						for ( var tipIndex = 0; tipIndex < tipList.length ; tipIndex++) {
							var tip = tipList[tipIndex];
							if ((localX > tip.offsetLeft )
									&& (localX < tip.offsetLeft + tip.clientWidth)
									&& (localY > tip.offsetTop )
									&& (localY < tip.offsetTop + tip.clientHeight)) {
								
							}else{
								tip.setStyle({visibility: "hidden"});
							}
						}
						}
					},
					// select thumbnail window to move
					engageThumb : function(oEvent) {
						if(oEvent.preventDefault){
							oEvent.preventDefault();
						}else {
							oEvent.returnValue = false;
						}
						var oThumbwindow = $("thumbwindow");
						// calculate offset
						this.iThumbDiffX = oEvent.clientX
								- oThumbwindow.offsetLeft;
						this.iThumbDiffY = oEvent.clientY
								- oThumbwindow.offsetTop;
						// change cursor to hand
						oThumbwindow.style.cursor = "move";
<<<<<<< PathwayDiagramPane.js
=======
						
>>>>>>> 1.66
						// setup event handlers
						YAHOO.util.Event.addListener(document.body,
								"mousemove", this.moveThumb, this, true);
						YAHOO.util.Event.addListener(document.body, "mouseup",
								this.releaseThumb, this, true);

					},
					// Drag thumbnail window
					moveThumb : function(oEvent) {
						if(oEvent.preventDefault){
							oEvent.preventDefault();
						}else {
							oEvent.returnValue = false;
						}
						var oThumbwindow = $("thumbwindow");
						// set new position
						oThumbwindow.style.left = oEvent.clientX
								- this.iThumbDiffX;
						oThumbwindow.style.top = oEvent.clientY
								- this.iThumbDiffY;
						var oThumbnail = $("thumbnail");
						var offsetTopsum = 0;
						var offsetLeftsum = 0;
						var offsetParent = oThumbwindow.offsetParent;

						while (offsetParent != null) {
							if (!(offsetParent == undefined)) {
								offsetTopsum = offsetTopsum
										+ offsetParent.offsetTop;
								offsetLeftsum = offsetLeftsum
										+ offsetParent.offsetLeft;
							}
							offsetParent = offsetParent.offsetParent;
						}

						if ((oEvent.clientX > offsetLeftsum && oEvent.clientX < (offsetLeftsum + oThumbnail.clientWidth))
								&& (oEvent.clientY > offsetTopsum)
								&& oEvent.clientY < (offsetTopsum + oThumbnail.clientHeight)) {
						} else {
							/* 
							 * Prevent the thumbwindow from being dragged outside thumbnail by detecting 
							 * when its coordinates are outside the bounds of the thumbnail. When this 
							 * happens reposition the thumb window so that it is at the thumbnail edge
							 * closest to it.
							 */
							if(oEvent.clientX < offsetLeftsum){
								oThumbwindow.style.left = "0px";
							}else if(oEvent.clientX > (offsetLeftsum + oThumbnail.clientWidth)){
								oThumbwindow.style.left = oThumbnail.clientWidth - oThumbwindow.clientWidth;
							}
							
							if(oEvent.clientY < offsetTopsum){
								oThumbwindow.style.top = "0px";
							}else if(oEvent.clientY > (offsetTopsum + oThumbnail.clientHeight)){
								oThumbwindow.style.top = oThumbnail.clientHeight - oThumbwindow.clientHeight;
							}
							this.moveImage();
							// turn off events
							YAHOO.util.Event.removeListener(document.body,
									"mousemove", this.moveThumb);
							YAHOO.util.Event.removeListener(document.body,
									"mouseup", this.releaseThumb);
							oThumbwindow.style.cursor = "default";
						}
					},
					// stop draging thumbnail window
					releaseThumb : function(oEvent) {
						var oThumbwindow = $("thumbwindow");
						var oThumbnail = $("thumbnail");
						var offsetTopsum = 0;
						var offsetLeftsum = 0;
						var offsetParent = oThumbwindow.offsetParent;

						while (offsetParent != null) {
							if (!(offsetParent == undefined)) {
								offsetTopsum = offsetTopsum
										+ offsetParent.offsetTop;
								offsetLeftsum = offsetLeftsum
										+ offsetParent.offsetLeft;
							}
							offsetParent = offsetParent.offsetParent;
						}

						// turn off events
						YAHOO.util.Event.removeListener(document.body,
								"mousemove", this.moveThumb);
						YAHOO.util.Event.removeListener(document.body,
								"mouseup", this.releaseThumb);
						oThumbwindow.style.cursor = "default";

						if ((oEvent.clientX > offsetLeftsum && oEvent.clientX < (offsetLeftsum + oThumbnail.clientWidth))
								&& (oEvent.clientY > offsetTopsum)
								&& oEvent.clientY < (offsetTopsum + oThumbnail.clientHeight)) {
							// change position of main image
							this.moveImage();
							if (this.highlitesInViewportOnly)
								this.reposition(0, 0);
								this.showDiagramsForVisibleComplexAndSetNodesIfNecessary();
						} else {
							// 		oThumbwindow.clientHeight + ", " + oEvent.clientX + ", " + oEvent.clientY);
							oThumbwindow.style.left = (oThumbnail.clientWidth / 2)
									- (oThumbwindow.clientWidth / 2);
							oThumbwindow.style.top = (oThumbnail.clientHeight / 2)
									- (oThumbwindow.clientHeight / 2);
							this.moveImage();
						}
					},
					// Move thumbnail to mouse click position.
					engageThumbnail : function(oEvent) {
						var oThumbwindow = $("thumbwindow");
						var offsetTopsum = 0;
						var offsetLeftsum = 0;
						var offsetParent = oThumbwindow.offsetParent;

						while (offsetParent != null) {
							if (!(offsetParent == undefined)) {
								offsetTopsum = offsetTopsum
										+ offsetParent.offsetTop;
								offsetLeftsum = offsetLeftsum
										+ offsetParent.offsetLeft;
							}
							offsetParent = offsetParent.offsetParent;
						}

						var baseY = offsetTopsum
								+ (oThumbwindow.clientHeight / 2);
						var baseX = offsetLeftsum
								+ (oThumbwindow.clientWidth / 2);
						oThumbwindow.style.left = oEvent.clientX - baseX;
						oThumbwindow.style.top = oEvent.clientY - baseY;
						this.moveImage();
						if (this.highlitesInViewportOnly)
							this.reposition(0, 0);
						this
								.showDiagramsForVisibleComplexAndSetNodesIfNecessary();
					},

					// reposition main image to match location of thumbwindow
					moveImage : function() {
						var oThumbwindow = $("thumbwindow");
						var oCanvas = $("canvas");
						// get current position of thumbwindow
						var iThumbX = parseInt(oThumbwindow.style.left);
						var iThumbY = parseInt(oThumbwindow.style.top);
						// calculate position of main image
						var tx = ((this.imgx / this.thumbnailw) * iThumbX)
								- (((this.imgx / this.thumbnailw) * iThumbX) % 1); // change
																					// position
																					// (left)
						var ty = ((this.imgy / this.thumbnailh) * iThumbY)
								- (((this.imgy / this.thumbnailh) * iThumbY) % 1); // change
																					// position
																					// (top)
						// set image position
						oCanvas.style.left = tx * -1 + "px";
						oCanvas.style.top = ty * -1 + "px";
						// refresh screen
						this.fetchtile();
					},
					scrollToNode : function(dbid) {
						var tn = this.dbnodes[dbid];
						var n = this.nodes[tn];
						if (n) {
							this.centreOnCoordinate(n.x, n.y);
						}
					},
					// register event handler(s)
					//
					// Don't do it wholesale - set it only when mouseovering the
					// clip window. Otherwise you'll have all sorts of
					// weird effects i.e. not being able to type into a text
					// box.
					// Safari 3.1.1 doesn't seem to recognise arrow keys any
					// more. Bizarre.
					keypresshandler : function(oEvent) {
						if (!oEvent) {
							return;
						}
						// stop event performing default action
						if (!oEvent.preventDefault) {
							oEvent.preventDefault = function() {
								this.returnValue = false;
							};
						} else {
							oEvent.preventDefault();
						}
						var key;
						if (oEvent.keyCode) {
							key = oEvent.keyCode; // IE key value
						} else if (oEvent.charCode) {
							key = oEvent.charCode; // W3C DOM key value
						} else if (oEvent.which) {
							key = oEvent.which; // other browsers key value
						}
						if (key == 38 || key == 63232) { // up
							this.reposition(0, +1);
						} else if (key == 40 || key == 63233) { // down
							this.reposition(0, -1);
						} else if (key == 37 || key == 63234) { // left
							this.reposition(+1, 0);
						} else if (key == 39 || key == 63235) { // right
							this.reposition(-1, 0);
						} else if (key == 43) {
							this.zoom(-1);
						} else if (key == 45) {
							this.zoom(+1);
						} 
						return true;
					},
					// load chosen image into page
					reloadimage : function() {
						//log("reloadimage");
						// setup and populate tiled image
						this.initcanvas();
						this.fetchtile();
					},
					// function: populates the canvas div with empty image tiles
					initcanvas : function() {
						// calculate image (scaled to zoom level)
						var scaling = 1 / Math.pow(2, (this.z - 1));
						this.imgx = Math.floor(this.imgw * scaling);
						this.imgy = Math.floor(this.imgh * scaling);

						// calculate number of tiles needed (x & y)
						var modx = this.imgx % this.tilewidth;
						var mody = this.imgy % this.tileheight;
						this.ntilesx = (this.imgx - modx) / this.tilewidth;
						this.ntilesy = (this.imgy - mody) / this.tileheight;
						if (this.imgx - modx < this.imgx) {
							this.ntilesx++
						}
						;
						if (this.imgx < this.tilewidth) {
							this.ntilesx = 1
						}
						;
						if (this.imgy - mody < this.imgy) {
							this.ntilesy++
						}
						;
						if (this.imgy < this.tileheight) {
							this.ntilesy = 1
						}
						;

						// calculate size of image in tiles
						var maxx = this.ntilesx * this.tilewidth;
						var maxy = this.ntilesy * this.tileheight;

						// decide on position of image when first displayed
						// (middle and center)
						this.startx = -(this.imgx / 2)
								+ (this.iClipWidth() / 2);
						this.starty = -(this.imgy / 2)
								+ (this.iClipHeight() / 2);

						// place enlarged thumb image in the background and set
						// the size
						var oCanvas = $('canvas');
						// Add fi canvas 
						var fiCanvas = $('ficanvas');
						if(fiCanvas){
							fiCanvas.remove();
							fiCanvas = undefined;
						}
						if(!fiCanvas){
							fiCanvas = Element.extend(document.createElement('div'));
							fiCanvas.id = "ficanvas";
							fiCanvas.setStyle( {
								top: (-1*this.miCanvasMargin)+ "px",
								left: (-1*this.miCanvasMargin) +"px",
								width: (maxx+(2*this.miCanvasMargin)) + "px",
								height: (maxy+(2*this.miCanvasMargin)) + "px",
								zIndex: 21
							});
							oCanvas.appendChild(fiCanvas);
						}
						var underlay = $("canvasunderlay");
						if (!underlay) {
							underlay = Element.extend(document
									.createElement('div'));
							underlay.id = "canvasunderlay";
							oCanvas.appendChild(underlay);
						}
						$A(underlay.childNodes).invoke('remove');
						var tiles = $("tiles");
						if (!tiles) {
							tiles = Element.extend(document
									.createElement('div'));
							tiles.id = "tiles";
							tiles.setStyle( {
								position : "absolute",
								top : "0px",
								left : "0px"
							});
							oCanvas.appendChild(tiles);
						}
						var entitydiagrams = $("entitydiagrams");
						if (!entitydiagrams) {
							entitydiagrams = Element.extend(document
									.createElement('div'));
							entitydiagrams.id = "entitydiagrams";
							entitydiagrams.setStyle( {
								position : "absolute",
								top : "0px",
								left : "0px",
								display : "none"
							});
							oCanvas.appendChild(entitydiagrams);
						}
						$A(entitydiagrams.childNodes).invoke('remove');
						var overlay = $("canvasoverlay");
						if (!overlay) {
							overlay = Element.extend(document
									.createElement('div'));
							overlay.id = "canvasoverlay";
							overlay.setStyle( {
								position : "absolute",
								top : "0px",
								left : "0px",
								zIndex: "20"
							});
							oCanvas.appendChild(overlay);
						}

						$A(overlay.childNodes).invoke('remove');
						oCanvas.style.width = (maxx+this.miCanvasMargin) + "px";
						oCanvas.style.height = (maxy+this.miCanvasMargin) + "px";
					},
					positionThumbnail : function() {
						var oThumbnailframe = $("thumbnailframe");
						if (this.imgw > 0) {
							oThumbnailframe.show();
							var oClipwindow = $("clipwindow");
							var pos = Position.cumulativeOffset(oClipwindow);
							var oThumbnail = $("thumbnail");
							// calculate dimensions of thumbnail
							var largest = (this.imgw > this.imgh) ? this.imgw
									: this.imgh;
							var ratio = 100 / largest;
							var thumbnail = this.imgwww + this.imgdir
									+ "/thumb.png";
							this.thumbnailh = (Math.ceil(ratio * this.imgh));
							this.thumbnailw = (Math.ceil(ratio * this.imgw));
							// log("thumbnailw = " + this.thumbnailw + ",
							// thumbnailh = " + this.thumbnailh);
							// log("imgw = " + this.imgw + ", imgh = " +
							// this.imgh);
							oThumbnail.style.backgroundImage = "url("
									+ thumbnail + ")";
							oThumbnail.style.width = this.thumbnailw + "px";
							oThumbnail.style.height = this.thumbnailh + "px";
							oThumbnailframe.style.width = (this.thumbnailw + 5)
									+ "px";
							oThumbnailframe.style.height = (this.thumbnailh + 5)
									+ "px";
						} else {
							oThumbnailframe.hide();
						}
					},
					// populate canvas with tiled images. Create the tile divs if necessary.
					fetchtile : function() {
						var oCanvas = $("canvas");
						var oTiles = $("tiles");
						var iX = parseInt(oCanvas.style.left) || 0;
						var iY = parseInt(oCanvas.style.top) || 0;
						// find the top left tile in the clip
						var iTileX = Math.floor(-iX / this.tilewidth);
						var iTileY = Math.floor(-iY / this.tileheight);
						// correction in case we are at the top left corner of
						// the whole image already
						if (iTileX < 0)
							iTileX = 0;
						if (iTileY < 0)
							iTileY = 0;
						// determine bottom and right edge of the area to tile
						var rightEdge = -iX + this.iClipWidth();
						var bottomEdge = -iY + this.iClipHeight();
						for ( var ty = iTileY; ty * this.tileheight < bottomEdge; ty++) {
							for ( var tx = iTileX; tx * this.tilewidth < rightEdge; tx++) {
								if (tx >= 0 && tx < this.ntilesx && ty >= 0
										&& ty < this.ntilesy) {
									var iTileId = tx + "x" + ty;
									var oTile = $(iTileId);
									if (!oTile) {
										oTile = Element.extend(document
												.createElement("div"));
										oTile.setAttribute("id", iTileId);
										oTile.className = "tile";
										oTile
												.setStyle( {
													top : (ty * this.tileheight + "px"),
													left : (tx * this.tilewidth + "px")
												});
										oTiles.appendChild(oTile);
									}
									var uri = "url(" + this.imgwww
											+ this.imgdir + "/" + this.z + "/"
											+ iTileId + ".png)";
									// log(uri);
									if (oTile.style.backgroundImage != uri) {
										oTile.style.backgroundImage = uri;
									}
								}
							}
						}
					},
					// move image back to the center of the viewing area
					recentre : function() {
						var oCanvas = $("canvas");
						oCanvas.style.left = this.startx + "px";
						oCanvas.style.top = this.starty + "px";
						this.reposition(0, 0);
					},
					// move image
					reposition : function(fx, fy) {
						// get current image position
						var oCanvas = $("canvas");
						var iX = parseInt(oCanvas.style.left);
						var iY = parseInt(oCanvas.style.top);

						if (isNaN(iX) || isNaN(iY)) {
							return;
						}
						// change image position values
						iX += Math.round(this.dx * fx);
						iY += Math.round(this.dy * fy);
						// set image position values
						oCanvas.style.top = iY + "px";
						oCanvas.style.left = iX + "px";
						// change position/size of thumbnail window according to
						// new image position
						var iTw = Math.round((this.iClipWidth() / this.imgx)
								* this.thumbnailw); // change size of box
													// (width)
						var iTh = Math.round((this.iClipHeight() / this.imgy)
								* this.thumbnailh); // change size of box
													// (height)
						var iTx = Math
								.round((this.thumbnailw / this.imgx) * iX); // change
																			// position
																			// of
																			// box
																			// (left)
						var iTy = Math
								.round((this.thumbnailh / this.imgy) * iY); // change
																			// position
																			// of
																			// box
																			// (top)
						if (isNaN(iTx) || isNaN(iTy)) {
							return;
						}
						// set thumbnail window (red box) values
						var oThumbnail = $("thumbwindow"); // select thumbnail
															// div
						oThumbnail.style.left = -iTx + "px"; // set left :
																// negate value
																// so box moves
																// in opposite
																// direction
						oThumbnail.style.top = -iTy + "px"; // set top : negate
															// value so box
															// moves in opposite
															// direction
						oThumbnail.style.width = iTw + "px"; // set width
						oThumbnail.style.height = iTh + "px"; // set height
						//
						this.viewportLeft = -iX / this.zoomFactor;
						this.viewportTop = -iY / this.zoomFactor;
						this.viewportRight = (-iX + this.iClipWidth())
								/ this.zoomFactor;
						this.viewportBottom = (-iY + this.iClipHeight())
								/ this.zoomFactor;
						// refresh screen image tiles
						this.fetchtile();
						this
								.showDiagramsForVisibleComplexAndSetNodesIfNecessary();
						// Required for "lazy" highliting of things in viewport
						// only
						if (this.highlitesInViewportOnly) {
							this.highliteCachedNodes();
						}
					},
					iClipWidth : function() {
						return $('clipwindow').getWidth();
					},
					iClipHeight : function() {
						return $('clipwindow').getHeight();
					},
					zoom : function(fz) {
						// For some reason passing this.z to 'fire' seems to turn it into string.
						this.z = parseInt(this.z) + this.dz * fz;
						this.zoomChange.fire(this.z);
					},
					setZoomLevel : function(zl) {
						// change zoom level
						this.z = zl;
						// set min and max zoom levels
						if (this.z < 1) {
							this.z = 1;
						} else if (this.z > this.maxz) {
							this.z = this.maxz;
						}
						this.zoomFactor = this.calculateZoomFactor(this.z);
						// find current position
						var oCanvas = $("canvas");
						var iX = parseInt(oCanvas.style.left);
						var iY = parseInt(oCanvas.style.top);
						if (isNaN(iX) || isNaN(iY)) {
							//log("No canvas coordinates yet.");
							return;
						}
						// old image size
						var iOldX = this.imgx;
						var iOldY = this.imgy;
						// reload image
						this.reloadimage();
						// new image size
						var iNewX = this.imgx;
						var iNewY = this.imgy;
						// find pixel from image in central point of viewer
						var iPixOldX = ((iX) * -1) + (this.iClipWidth() / 2);
						var iPixOldY = ((iY) * -1) + (this.iClipHeight() / 2);
						// find where pixel has moved to in next image
						var iPixNewX = (iNewX / iOldX) * iPixOldX;
						var iPixNewY = (iNewY / iOldY) * iPixOldY;
						// change position values according to degree of
						// movement of pixel
						var iNewPosX = (((iPixNewX - iPixOldX) * -1) - (((iPixNewX - iPixOldX) * -1) % 1))
								+ iX;
						var iNewPosY = (((iPixNewY - iPixOldY) * -1) - (((iPixNewY - iPixOldY) * -1) % 1))
								+ iY;
						// set new position
						oCanvas.style.left = iNewPosX + "px";
						oCanvas.style.top = iNewPosY + "px";
						// refresh page with new position
						this.reposition(0, 0);
						if (!this.highlitesInViewportOnly) {
							this.highliteCachedCoordinates();
						}
						if (this.paintExpressionData == 1) {
							this.displayExpressionLevels();
						}
<<<<<<< PathwayDiagramPane.js
<<<<<<< PathwayDiagramPane.js
=======
						if(this.speciesComparator.displayComparison == 1){
							this.speciesComparator.paintExistingComparison(this.nodes, this.focus_pathway_id, this.zoomFactor);
=======
						if(this.displayComparison == 1){
							this.paintExistingComparison(this.nodes, this.focus_pathway_id, this.zoomFactor);
>>>>>>> 1.66
						}
						// Clear the mi overlay of displayed interactors and redraw, scaling for new 
						// zoom level.
						this.fiDisplay.clearDisplay();
						this.fiDisplay.displayAll(this.zoomFactor);

>>>>>>> 1.41
					},
					calculateZoomFactor : function(zl) {
						return 1 / Math.pow(2, (zl - 1));
					},
					centreOnCoordinate : function(x, y) {
						//log("centreOnCoordinate(" + x + ", " + y + ")");
						x *= this.zoomFactor;
						y *= this.zoomFactor;
						var canvas = $('canvas');
						var cx = -parseInt(canvas.getStyle('left'))
								+ this.iClipWidth() / 2;
						var cy = -parseInt(canvas.getStyle('top'))
								+ this.iClipHeight() / 2;
						var dx = cx - x;
						var dy = cy - y;
						if ((dx != 0) || (dy != 0)) {
							this.animatedReposition(dx, dy);
						}
					},
<<<<<<< PathwayDiagramPane.js
=======
					displayNodeHighlight: function(x, y, w, h, keepPrevious) {
						var margin = 10;
						var borderwidth = 5;
						var overlay = $("canvasoverlay");
						if (!keepPrevious) {
							alert("Removing highlite");
							overlay.getElementsBySelecter('div.hl').invoke('remove');
						}
						var hlw = (w + margin + (borderwidth*2)) * this.zoomFactor;
						var hlh = (h + margin + (borderwidth*2)) * this.zoomFactor;
						x = this.zoomFactor * (x + w / 2) - hlw / 2;
						y = this.zoomFactor * (y + h / 2) - hlh / 2;
						w = hlw;
						h = hlh;
						if(YAHOO.env.ua.ie > 0){
							w +=2*this.highliteBorderThickness;
							h +=2*this.highliteBorderThickness;
						}
						var hl = Element.extend(document.createElement('div'));
						hl.className = 'hl';
						hl.setStyle({position:"absolute",
									top:y - margin - borderwidth, 
									left:x - margin - borderwidth, 
									width:w + (margin*2), 
									height:h + (margin*2), 
									zIndex: 2,
									border: borderwidth +"px solid rgb(255,0,0)"
									});
						overlay.appendChild(hl);
						
					
					},
>>>>>>> 1.66
					highliteCoordinate : function(x, y, w, h, keepPrevious) {
						//log("EntityLevelView.highliteCoordinate()");
<<<<<<< PathwayDiagramPane.js
						var oCO = $("canvasunderlay");
						if (!keepPrevious) {
							$A(oCO.childNodes).invoke('remove');
						}
						var hlw = 200;
						x = this.zoomFactor * (x + w / 2) - hlw / 2;
						y = this.zoomFactor * (y + h / 2) - hlw / 2;
						w = hlw;
						h = hlw;
						var hl = Element.extend(document.createElement('img'));
						oCO.appendChild(hl);
						hl.src = "/entitylevelview/icons/hlbg.png";
						hl.setStyle( {
							position : "absolute",
							top : y + "px",
							left : x + "px",
							width : w + "px",
							height : h + "px",
							display : 'none'
						});
						new Effect.Grow(hl);
						// oCO.appendChild(hl);
=======
						this.displayNodeHighlight(x,y,w,h, keepPrevious)						
>>>>>>> 1.66
					},
					clearHighlites : function() {
						this.highlitedCoordinates.map( function(n) {
							n.isHighlited = false;
						});
						this.highlitedCoordinates.length = 0;
						var oCO = $("canvasunderlay");
						if (oCO) {
							$A(oCO.childNodes).invoke('remove');
						}
<<<<<<< PathwayDiagramPane.js
=======
						
						if($("canvasoverlay")){
						$("canvasoverlay").getElementsBySelector("div.hl").invoke('remove');
						}
>>>>>>> 1.66
						var to = $("thumbnailoverlay");
						if (to) {
							$A(to.childNodes).invoke('remove');
						}
						
						
					},
					loadOrderedCoordinates : function(callforward) {
						var sUrl = this.imgdir + '/orderedcoordinates.json';
						var callback = {
							scope : this,
							customevents : {
								onSuccess : function(eventType, args) {
//									
							var o = eval('(' + args[0].responseText + ')');
									this.handleCoordinates(o);
									// Fire this event to let PathwayBrowser know
									// the diagram is ready and that the expression
									// painter now has everything it needs to 
									// paint the diagram correctly.
									this.diagramLoadedEvent.fire();
									if (callback.callforward)
										callback.callforward();
								},
								onFailure : function(eventType, args) {
									//log(args[0].statusText);
								this.orderedRepresentedInstance = [];
								this.reloadimage();
								this.recentre();
								if (callback.callforward)
									callback.callforward();
							}
							}
						};
						if (callforward)
							callback.callforward = callforward;
						if (this.focus_pathway_id != null) {
							YAHOO.util.Connect.asyncRequest('GET', sUrl,
									callback);
						} else if (callback.callforward) {
							callback.callforward();
						}
					},
					handleCoordinates : function(o) {
						log("handleCoordinates");
						this.setImgDir();
						this.imgw = o.width;
						this.imgh = o.height;
						this.positionThumbnail();
						this.orderedRepresentedInstances = o.coordinates;
						this
								.processOrderedRepresentedInstances(this.orderedRepresentedInstances);
						this.reloadimage();
						this.recentre();
					},
					processOrderedRepresentedInstances : function(
							orderedRepresentedInstances) {
						this.representedInstances = new Object();
						this.nodes = new Object();
						this.dbnodes = new Object();
						this.refdbnodes = new Object();
						for ( var i = 0, l = orderedRepresentedInstances.length; i < l; ++i) {
							var n = orderedRepresentedInstances[i];
							this.representedInstances[n.id] = n;
							var coords = n.coords;
							for ( var j = 0, m = coords.length; j < m; ++j) {
								coords[j].userObject = n;
								this.nodes[coords[j].id] = coords[j];
								this.dbnodes[n.id] = coords[j].id;
								this.refdbnodes[n.refid] = coords[j].id;
							}
						}
					},
					/*
					 * reset variables when no pathway selected. This can happen when switching to a species that does not
					 * have a pathway orthologous to the currently displayed one.
					 */
					noPathwaySelected : function(){
						this.removeImageTiles();
						this.focus_pathway_id=null;
						var oThumbnailframe = $("thumbnailframe");
						oThumbnailframe.hide();
						this.setImgDir();
						this.representedInstances = new Object();
						this.nodes = new Object();
						this.dbnodes = new Object();
						this.refdbnodes = new Object();
						this.imgw = 0;
					},
					highliteNodesWithId : function(dbids, keepPrevious) {
						//log("highliteNodesWithId\t" + dbids);
						keepPrevious || this.clearHighlites();
						if (this.nodes != null) {
							var l = dbids.length;
							if (l > 100) {
								l = 100;
								// log("Highliting 1st " + l + " nodes only from
								// total " + dbids.length);
							}
							for ( var i = 0; i < l; ++i) {
								var n = this.nodes[dbids[i]];
								if (n != null) {
									this.cacheHighlitedCoordinate(n);
									this.highliteCoordinate(n.x, n.y, n.w, n.h,
											true);
									this.highliteThumbCoordinate(n.x, n.y);
								} else {
									log("No node with id " + dbids[i]);
								}
							}
						} else {
							log("No coordinate data!");
						}
					},
					highliteNodeWithId : function(dbid, keepPrevious) {
					
							if (this.nodes != null) {

							var n = this.nodes[dbid];
							if (n != null) {
								keepPrevious || this.clearHighlites();
								this.cacheHighlitedCoordinate(n);
								this.highliteCoordinate(n.x, n.y, n.w, n.h,
										true);
								this.highliteThumbCoordinate(n.x, n.y);
							} else {
								log("No node with DB_ID " + dbid);
							}
						} else {
							log("No coordinate data!");
						}
					},
					highliteNode : function(node) {
						//log("EntityLevelView.highliteNode()");
						var oCO = $("canvasunderlay");
						var hlw = 200;
						var x = this.zoomFactor * (node.x + node.w / 2) - hlw
								/ 2;
						var y = this.zoomFactor * (node.y + node.h / 2) - hlw
								/ 2;
						var w = hlw;
						var h = hlw;
						var node_id = 'hl_' + node.id;
						var hl = Element.extend(document.createElement('img'));
						hl.id = node_id;
						hl.src = "/entitylevelview/icons/hlbg.png";
						oCO.appendChild(hl);
						node.isHighlited = true;
						hl.setStyle( {
							position : "absolute",
							top : y + "px",
							left : x + "px",
							width : w + "px",
							height : h + "px"
						});
						return hl;
					},
					highliteNodeIfInViewPort : function(node) {
						if (this.isInViewPort(node)) {
<<<<<<< PathwayDiagramPane.js
							var oCO = $("canvasunderlay");
							var hlw = 200;
							var x = this.zoomFactor * (node.x + node.w / 2)
									- hlw / 2;
							var y = this.zoomFactor * (node.y + node.h / 2)
									- hlw / 2;
							var w = hlw;
							var h = hlw;
							var node_id = 'hl_' + node.id;
							var hl = $(node_id);
							if (hl == null) {
								var hl = Element.extend(document
										.createElement('img'));
								hl.id = node_id;
								hl.src = "/entitylevelview/icons/hlbg.png";
								oCO.appendChild(hl);
								node.isHighlited = true;
							}
							hl.setStyle( {
								position : "absolute",
								top : y + "px",
								left : x + "px",
								width : w + "px",
								height : h + "px"
							});
							return hl;
=======
							this.displayNodeHighlight(node.x,node.y, node.w, node.h, true);
>>>>>>> 1.66
						}
					},
					highliteInViewportAndCache : function(node, keepPrevious) {
						if (!node.isHighlited) {
							keepPrevious || this.clearHighlites();
							if (this.highlitesInViewportOnly) {
								this.highliteNodeIfInViewPort(node);
							} else {
								this.highliteNode(node);
							}
							this.highliteThumbCoordinate(node.x, node.y);
							this.cacheHighlitedNode(node);
						}
					},
					highliteNodesWithInstanceId : function(dbid, keepPrevious) {
						if (this.representedInstances != null) {
							var n = this.representedInstances[dbid];
							if (n != null) {
								keepPrevious || this.clearHighlites();
								var coords = n.coords;
								for ( var i = 0; i < coords.length; i++) {
									this.highliteInViewportAndCache(coords[i],
											true);
								}
							} else {
								log("No node with DB_ID " + dbid);
							}
						} else {
							//alert("No coordinate data!");
						}
					},
					cacheHighlitedCoordinate : function(coords) {
						this.highlitedCoordinates.push(coords);
					},
					cacheHighlitedNode : function(node) {
						this.highlitedCoordinates.push(node);
					},
					highliteCachedCoordinates : function() {
						for ( var i = 0; i < this.highlitedCoordinates.length; i++) {
							var coords = this.highlitedCoordinates[i];
							if (coords.userObject != null) {
								this.highliteNode(coords);
							} else {
								this.highliteCoordinate(coords.x, coords.y,
										coords.w, coords.h, true);
							}
						}
					},
					highliteCachedNodes : function() {
						var t1 = new Date().getTime();
						var c = 0;
						for ( var i = 0; i < this.highlitedCoordinates.length; i++) {
							var node = this.highlitedCoordinates[i];
							var hl = this.highliteNodeIfInViewPort(node);
							if (hl != null)
								c++;
						}
						var t2 = new Date().getTime();
						// log("Highlited " + c + " nodes in " + (t2 - t1)/1000
						// + "s");
					},
					highliteThumbCoordinate : function(x, y) {
						x = Math.round(x / this.imgw * this.thumbnailw - 1);
						y = Math.round(y / this.imgh * this.thumbnailh - 1);
						var node_id = 'thl_' + Math.round(x / 2) + '_'
								+ Math.round(y / 2);
						var thl = $(node_id);
						if (thl == null) {
							thl = Element.extend(document.createElement('div'));
							thl.innerHTML = "&nbsp;";
							thl.id = node_id;
							thl.className = "thumbhighlite";
							thl.setStyle( {
								position : "absolute",
								top : (y - 1) + "px",
								left : (x - 1) + "px",
								width : "3px",
								height : "3px"
							});
							$("thumbnailoverlay").appendChild(thl);
						}
					},
					getPositionByStyle : function(obj) {
						return [ parseInt(obj.style.left),
								parseInt(obj.style.top) ];
					},
					findNodeAtCoordinate : function(x, y) {
						var tolerance = 10;
						// log("findNodeAtCoordinate: " + x + ", " + y);
						for ( var id in this.nodes) {
							var node = this.nodes[id];
							if ((x > node.x - tolerance)
									&& (x < node.x + node.w + tolerance)
									&& (y > node.y - tolerance)
									&& (y < node.y + node.h + tolerance)) {
								return node;
							}
						}
					},
					highlitePathwayComponents : function(dbid) {
						var ol = this
								.overlayElementWithTimeIndicator($("clipwrapper"));
						var t = this;
						new Ajax.Request(
								'/cgi-bin/entitylevelview/pathwaycomponents', {
									parameters : {
										'ID' : dbid,
										'DB' : this.db
									},
									method : 'get',
									onSuccess : function(transport) {
										var rtxt = transport.responseText;
										var a = eval(rtxt);
										t.clearHighlites();
										a.map( function(id) {
											t.highliteNodesWithInstanceId(id,
													true);
										});
										t.centreOnCoordinate(
												t.highlitedCoordinates[0].x,
												t.highlitedCoordinates[0].y);
									},
									onFailure : function(transport) {
										//alert(transport.statusText);
									},
									onComplete : function(transport) {
										if (ol)
											ol.remove();
									}
								});
					},
<<<<<<< PathwayDiagramPane.js
=======
					onSpeciesComparisonClose : function(){
						this.displayComparison = 0;
						$("canvasoverlay").getElementsBySelector(
						'div.comparetips').invoke('remove');
						$("speciescomparisonpanel").style.display = "none";
					},
					paintSpeciesComparison: function(speciesdata){
						/*this.speciesComparator.paintComparison(this.nodes, this.focus_pathway_id, 
								comparisons, this.zoomFactor)*/
						this.paintComparison(this.nodes, this.focus_pathway_id, 
										speciesdata, this.zoomFactor)
					},
					paintExistingComparison : function(nodes, pathwayId, zoomFactor){
						
						if(this.speciesdata == null){
							alert("No comparison data found.");
							return;
						}
						this.paintComparison(nodes, pathwayId, this.speciesdata, zoomFactor);
					},
					paintComparison : function(nodes, pathwayId, speciesdata, zoomFactor){
						comparisons = speciesdata.comparisons;
						$("canvasoverlay").getElementsBySelector(
						'div.comparetips').invoke('remove');
						var w=0;
						var h=0;
						for ( var nodeitem in nodes) {
							try{
							if (nodeitem) {
								if(nodes[nodeitem].cls != "ReactionVertex"){
								var tip = Element.extend(document
										.createElement('div'));
								tip.className = 'comparetips';
								tip.id = "comparetip_" + nodeitem;
								var node = nodes[nodeitem];
								
									w = node.w;
									h = node.h;
									var nw, nh = 5;
									nw = w - 1;
									nh = h - 1;
									if (zoomFactor == 1) {
										tip.innerHTML = node.userObject.name;
										tip.innerHTML = tip.innerHTML
										.replace(/\[.*/, "");
										tip.innerHTML = tip.innerHTML.replace(/\:/g,": ");

									}
									nw = nw * zoomFactor;
									nh = nh * zoomFactor;
									tip.setStyle( {
										position: "absolute",
										width : nw + "px",
										height : nh + "px",
										fontSize : "10px",
										fontWeight: "bold",
										textAlign : "center"
									});
									$("canvasoverlay").appendChild(tip);
									var border_w = 5;
									nh = tip.getHeight();

									var nodex = nodes[nodeitem].x;
									var nodey = nodes[nodeitem].y;
									nodex = nodex * zoomFactor
									- border_w
									- (nw - w * zoomFactor)
									/ 2;
									nodey = nodey * zoomFactor
									- border_w
									- (nh - h * zoomFactor)
									/ 2;
									var fontcolour="black";
									var backgroundcolour=this.defaultBackgroundColour;
									var matched=0;
									if (node.userObject.cls == "EntityWithAccessionedSequence") {
									for(var compIndex=0; compIndex < comparisons.length; compIndex++){
										if(node.userObject.refid == comparisons[compIndex].refid){
											if(comparisons[compIndex].other=="1"){
												backgroundcolour = "yellow";
												fontcolour = "black";
											}else{
												fontcolour = "white";
												backgroundcolour = "blue";
											}
											tip.setStyle( {
												left : nodex + 5
												+ "px",
												top : nodey + 5
												+ "px",
												height : nh + "px",
												color: fontcolour,
												backgroundColor: backgroundcolour
											});
											matched=1;
										}
									}
									// if the EWAS was not matched with data returned from the server
									// colour it grey. Should this happen ?
									if(matched == 0){
										tip.setStyle( {
											left : nodex + 5
											+ "px",
											top : nodey + 5
											+ "px",
											height : nh + "px",
											color: fontcolour,
											backgroundColor: this.noHitBG
										});
										
									}
									}else
									if(node.userObject.cls == "SimpleEntity"){
										// 8 is the multiplier for firefox on linux.
										var dimAdjustment = 8 * zoomFactor;
										tip.innerHTML = "<img src=\"/entitylevelview/icons/circle.png\" width=\"" + (nw+dimAdjustment) + 
										"px\" height=\"" + (nh+dimAdjustment)	+ "px\" />";
										if(zoomFactor == 1){
										tip.innerHTML = tip.innerHTML + "<div align=\"center\" style=\"vertical-align:middle;width:"  + (nw+dimAdjustment) 
										+ ";height:" + (nh+dimAdjustment) +	";color:black;position:absolute;left: " + 0 + ";top: " + 0 + ";\">"+
										node.userObject.name.replace(/\[.*/, "") + "</div>";
										
										}
										
										// 3 is the ideal location adjustment for linux firefox.
										var locadjustment = 3;
									     locadjustment +=  (1* (1 - zoomFactor ));
										if(zoomFactor == 1){
											// 2 is the ideal location adjustment modifier for 
											// linux firefox at maximum zoom
											locadjustment -=2;
										}
										tip
										.setStyle( {
											left : nodex + locadjustment
													+ "px",
											top : nodey +locadjustment 
													+ "px",
											height : (nh) + "px"
										});
									} else if (node.userObject.cls == "Complex") {
										
										tip.setStyle( {
										background : 'rgb(0,0,0)'
										});
										
										tip.setStyle( {
											left : nodex + 5 + "px",
											top : nodey + 5 + "px",
											height : nh + "px"
										});

										tip.style.color = "white";
									}
									else{
									tip.setStyle( {
													left : nodex + 5
													+ "px",
													top : nodey + 5
													+ "px",
													height : nh + "px",
													color: fontcolour,
													background: this.defaultBackgroundColour
												});
									}
									backgroundcolour = this.defaultBackgroundColour;
							}
							}
							}catch(ex){
							}
						}
						this.displayComparison = 1;
						this.speciesdata = speciesdata;
						this.placeSpeciesComparisonPanel(speciesdata.name);
				},
				placeSpeciesComparisonPanel : function(name){
					var availableWidth = $("clipwindow").getWidth();
					var browserWidth = $("speciescomparisonpanel").getWidth();
					if(name && name != null){
						$("speciesname").innerHTML = name;
					}else{
						$("speciesname").innerHTML = "Species Comparison";
					}
					$("speciescomparisonpanel").style.left = ((availableWidth/2) - (browserWidth/2))+"px";
					$("speciescomparisonpanel").style.visibility = "visible";
					$("speciescomparisonpanel").style.display = "block";
				},
>>>>>>> 1.66
					handleHighliteMouseover : function(event, dbid) {
						
						// Determing is complex pupup is displayed and if so dont display
						// tooltip for complex.
						var cplxpopdisplayed = $("ficanvas")
						.getElementsBySelector(
						'div.cplxcompstip');

						if(cplxpopdisplayed.length > 0 
								&& (this.currentCplxNode != null 
										&& cplxpopdisplayed[0].style.visibility == "visible")){
							if(dbid == this.currentCplxNode.id){
								return;
							}else{
								if(!event.target){
									event.target = event.srcElement;
								}
								var node = this.nodes[dbid];
								var eX = event.target.offsetLeft;
								var eY = event.target.offsetTop;
								// 	1 is index of close button div element
								var tX = cplxpopdisplayed[1].offsetLeft;
								var tY = cplxpopdisplayed[1].offsetTop;
								var margin = 20;

								if(((tX) > (node.x - margin)) 
										&& ((tX +cplxpopdisplayed[1].clientWidth ) < (node.x+node.w+margin)) 
										&& ((tY)>(node.y-margin)) 
										&& ((tY + cplxpopdisplayed[1].clientHeight ) < (node.y + node.h+margin))){
									return;
								}
							}
						}
                       
						var id = "tip_" + dbid;
						var tipList = $("canvas").getElementsBySelector('div.tip');
						for(var tipIndex=0; tipIndex < tipList.length; tipIndex++){
								tipList[tipIndex].setStyle({visibility: "hidden"});
						}
<<<<<<< PathwayDiagramPane.js
						if($(id)){
							var existingTip = document.getElementById(id);
							if(existingTip){
							var node = this.nodes[dbid];
                            existingTip.innerHTML = node.userObject.name;
							// If expression painter displayed, update the tooltip
							// with expression data value.
                            if(this.expressionPainter && this.expressionPainter.refIdMapping){
                                  var matchedEntity = this.expressionPainter.refIdMapping[node.userObject.refid];
                                         if (matchedEntity) {
                                                existingTip.innerHTML += ". Id : " + matchedEntity.id + ". Level: " + matchedEntity.data[this.currentExperiment];

                                         }
                                }
								existingTip.setStyle({visibility : "visible",
<<<<<<< PathwayDiagramPane.js
											display: "", zIndex : 2});
							
=======
											display: "", zIndex : this.tipZ});
>>>>>>> 1.41
							}
						}else
						if (!$(id)) {
=======
						{
>>>>>>> 1.66
							// For some reason Safari often ignores the request to remove the popups on mouseout.
							// Hence the need to "manually" remove them here.
							var tip = $(id);
							if(tip){
								tip.remove();
							}
							tip = Element.extend(document
									.createElement('div'));
							tip.className = 'tip';
							tip.id = id;
							var node = this.nodes[dbid];
							var w = node.w;
							var h = node.h;
							var nw, nh;
							
							if (node.cls == "ReactionVertex") {
								nw = 100;
								nh = 100;
							} else {
								nw = 2.5 * w;
								nh = 2 * h;
							}
							tip.innerHTML = node.userObject.name;
							if(this.expressionPainter && this.expressionPainter.refIdMapping){
							var matchedEntity = this.expressionPainter.refIdMapping[node.userObject.refid];
							if (matchedEntity) {
								tip.innerHTML += ". Id : " 
									+ matchedEntity.id + ". Level: " 
									+ matchedEntity.data[this.currentExperiment];
								}
							}
							tip.setStyle( {
								width : nw + "px",
								display : 'none'
							});
							$("canvas").appendChild(tip);
						
							var t = this;						
							Event.observe(tip, 'mousedown', function(event) {
								
								Event.stop(event);
								var ctrl = event.ctrlKey;
								if ((event.button == 0
										|| event.button == 1) && ctrl == false) {
									t.highliteNodeWithId(dbid,
											false);
									t.diagramNodeClickedEvent
											.fire(node);
<<<<<<< PathwayDiagramPane.js
								}
=======
								} else if (event.button == 2 || (event.button == 0 && ctrl ==true)) {
									/*if (t.paintExpressionData == 1) {
										if(node.userObject.cls == "Complex" ){
											var components = t
													.complexHasComponents(
															node.userObject.id,
															"check");
											if (components.length > 0) {
												t.currentCplxNode = node;
												t.displayComplexPopup();
											} // components.length > 0
										} // cls==complex
									} // expressiondata == 1
									else if(t.displayComparison == 1){
										if(node.userObject.cls == "Complex" ){
											t.currentCplxNode = node;
											t.displayComplexPopupForSpeciesComparison();
										} // cls==complex
									}//displaycomparison==1 
									else{*/
										if(t.fiDisplay.currentlyDisplayed[node.id]){
											node.interactors = "hide";
										}else{
											node.interactors = "display";
										}
										node.expressionDisplayed = t.paintExpressionData;
node.displayComparison = t.displayComparison;										t.createMenu(node);
									 
									//}
								}// end event button 2
>>>>>>> 1.41
								}); // end observe
							var border_w = 5;
							nh = tip.getHeight();
							var x = node.x;
							var y = node.y;
							x = x * this.zoomFactor - border_w
									- (nw - w * this.zoomFactor) / 2;
							y = y * this.zoomFactor - border_w
									- (nh - h * this.zoomFactor) / 2;
						
							tip.setStyle( {
								left : x + "px",
								top : y + "px",
								opacity : 0.85,
								height : nh + "px",
								border : border_w + "px solid #DCDCDC",
<<<<<<< PathwayDiagramPane.js
								background : "#DCDCDC",
								zIndex : 10
=======
								background : "#DCDCDC",
<<<<<<< PathwayDiagramPane.js
								zIndex : this.tipZ
>>>>>>> 1.41
=======
								zIndex : 30
>>>>>>> 1.66
							});
							new Effect.Appear(tip, {
								duration : 0.5,
								to : 0.85
							});
							/* The bringElementIntoViewPort function is what causes the diagram to scroll to bring the whole of a tooltip
							 into view. I found this annoying as diagrams can be quite busy and merely moving the
							 cursor around could cause the diagram to 'skid' away. Also, it can interfere with the
							 other pathways feature. When the new diagram is loaded the view will be over the centre
							 of the pathway and will then scroll to focus on the selected node. If the cursor is over
							 a node it will 'catch' and stop the view from focusing on the node selected by the user */
//							this.bringElementIntoViewPort(tip);
						
						}
					},
<<<<<<< PathwayDiagramPane.js
                    displayTip : function(dbid, w, h, name, x,y, offsetX, offsetY){
=======
					clearFIOverlay: function(){
						/*
						 * Get a list of expressiontips for proteins. When the fioverlay is cleared need to 
						 * redisplay these.
						 */
						var exptips = $("canvasoverlay")
						.getElementsBySelector(
								'div.proteinexpressiontip');
						if(exptips && exptips.length > 0){
							for(var i=0; i<exptips.length;i++){
								exptips[i].style.display="";
							}
						}
						this.fiDisplay.cleanUp();
					},
					displayFIOverlay : function(node, oResponse){
						this.fiDisplay.displayFIOverlay(node, oResponse, this.zoomFactor);
						this.controlPanel.colourRows(node.userObject.id, node.id)
					},
					applyConfidenceColours: function(confthreshold, exceedColour, belowColour){
						this.fiDisplay.colourInteractionsBasedOnThreshold(confthreshold, exceedColour, belowColour);
					},
					resetColours:function(){
						this.fiDisplay.resetColours();
					},
					
					createMenu : function(node, hide){
						this.oContextMenu.displayMenu(node);
					},
					/*
					 * The control panel can display a table of interactions for proteins in the
					 * pathway. This table is constructed dynamically. If interactors are already
					 * displayed in the diagram we need to colour the relevant rows in the table
					 * accordingly and this is done after the table is constructed.
					 * 
					 */
					interactionTableBuiltHandler : function(){
						try{
							/* 
							 * Need to check for as if currentlyDisplayed is empty nodeVertexId
							 * is assigned value of "each" which is not a valid index for this.nodes
							 */
							//if(this.fiDisplay.currentlyDisplayed && this.fiDisplay.currentlyDisplayed.length > 0){
								for(nodeVertexId in this.fiDisplay.currentlyDisplayed){
									var node = this.nodes[nodeVertexId];
									if(node){
										this.controlPanel.colourRows(node.userObject.id, node.id);
									}
								}
							//}
						}catch(err){
							alert("There was a problem colouring entries in the interaction table: " 
									+ err.description);
						}
						this.controlPanel.showTable();
					},
					/*
					 * Handles the event when the user left clicks on a query protein (protein in Reactome pathway) in the 
					 * interaction table view. Move view to that protein, display interactors for that protein.
					 */
					interactionEntryClickedHandler : function(eventType, args){
						var pid = args[0]; // protein id = node.userObject.id
						var vid = args[1]; // Vertex id = node.id
						this.scrollToNode(pid);
					    this.highliteNodeWithId(this.dbnodes[pid], false);
					    this.diagramNodeClickedEvent.fire(this.nodes[this.dbnodes[pid]]);
						var node = this.nodes[vid];
						if(node){
							var args = new Array();
							args[0] = node;
							pba.onDiagramNodeClick(null, args, null);
						}
					},
					displayInteractorsButtonClickedHandler:function(eventType, args){
						var pid = args[0]; // protein id = node.userObject.id
						var vid = args[1]; // Vertex id = node.id
						var node = this.nodes[vid];
						var args = new Array();
						args[0] = pid;
						args[1] = vid;
						/*
						 * Move view to node in diagram before displaying
						 */
						this.interactionEntryClickedHandler(null, args);
						/* 
						 * If interactors already displayed then hide interactors and change colour
						 * or row
						 */
						if(this.fiDisplay.currentlyDisplayed[vid]){
							this.fiDisplay.hideInteractors(node);
							var colour = "white";
							this.controlPanel.colourRows(node.userObject.id, node.id, colour);
						}else{
							// Only call this if interactors not already displayed.
							this.displayInteractors(node);
						}
					},
					displayInteractors:function(node){
						var t = this;
						var callback = {
							success: function(oResponse){
							if(oResponse.responseText.length == 0){
								$("clipwindow").style.cursor = "default";					
								alert("No interactors found for query protein in current interaction"
										+ " data source.");
								return;
							}
							var data = eval("(" + oResponse.responseText +")");
							
							// Keep track of which nodes the user has selected. Even if
							// no interactors for current interaction data source there might
							// be interactors found in another datasource when the user switches.
							var alreadySelected = false;
							for(var i=0; i< t.fiDisplay.currentFINodes.length; i++){
								if(t.fiDisplay.currentFINodes[i].id == node.id){
									alreadySelected = true;
								    break;
								}
							}
							if(alreadySelected == false){
								t.fiDisplay.currentFINodes.push(node);
							}
							pba.displayFIOverlay(node, data.queryresults[0]);
							
							if(data.queryresults.length ==0){
								$("clipwindow").style.cursor = "default";					
								alert("No interactors found in selected data source.");
								return;
							}
							$("clipwindow").style.cursor = "default";					
						},
						failure: function(oResponse){
							//t.currentFINodes = new Array();
							$("clipwindow").style.cursor = "default";					
						},
						complete: function(oResponse){
							$("clipwindow").style.cursor = "default";
						}
					};
						var dblistid = $("dblistid");
						var id = $("dblistid").value;
						// Method stores the retrieval method to be used on server. 
						// 1 indicates a REST request
						// 2 for SOAP
						// 3 for local request for user uploaded data.
						var method = $(id).service;
						var label = id.replace(/Option/,"");
						var si = $(id).si;
						$("clipwindow").style.cursor = "wait";					
						if(method == "1"){
							YAHOO.util.Connect
							.asyncRequest(
									'POST',
									"/ReactomeGWT/entrypoint/elv/PSICQUICProxyServlet",
									callback,
									'refid='
									+ node.userObject.refid
								
									+ '&retrievalmethod=1'
									+ '&si='
									+ si
							);
						}else if(method == "3"){
							YAHOO.util.Connect
							.asyncRequest(
										'POST',
										"/ReactomeGWT/entrypoint/elv/PSICQUICProxyServlet",
										callback,
												'label=' + label
												+ '&refid='	+ node.userObject.refid
												+ '&retrievalmethod=3'
											);
						}
					},
					
					getCurrentFINodes : function(){
						return this.fiDisplay.currentFINodes;
					},
    				 disableContextMenu: function(element) {
				        element.oncontextmenu = function() {
				        return false;
				        }
				    },
				    displayComplexPopup : function(){
				    	    var tip = $("ficanvas").getElementsBySelector('div.cplxcompstip');
				    	    var cplxNameDiv = null;
				    	    var closeTip = null;
				    	    var newlyCreated = false;
				    	    // Check if cplx tip has already been created. If not, create new one.
				    	    if( tip.length == 0){				    	    	
				    	    	tip = Element
									.extend(document
											.createElement('div'));
				    	    	cplxNameDiv = Element.extend(document.createElement('div'));
				    	    	closetip = Element.extend(document.createElement('div'));
				    	    	closetip.className = 'cplxcompstip';
								closetip.id = "cplxclosetip";
								closetip.title = "Close Window";
								closetip.style.cursor = "pointer";
								closetip.innerHTML = "<img src=\"/entitylevelview/icons/whiteclose.png\" width=\"12\" height=\"12\" />";
								tip.className = 'cplxcompstip cplxcompstipid';
								tip.id = "cplxcompstipid";
								cplxNameDiv.className = 'cplxcompstip';
								cplxNameDiv.id = 'cplxnamedivid';
								newlyCreated = true;
				    	    }else{
				    	    	tip = tip[0];
				    	    	cplxNameDiv = document.getElementById('cplxnamedivid');
				    	    	closetip = document.getElementById('cplxclosetip');
				    	    	
				    	    }
							var node = this.currentCplxNode;
							var components = this.complexnodes[node.userObject.id];
							var cc = 3; // column count
										// : how many
										// cells to
										// display in a
										// single row
							var compCount = components.length;
							var rc = Math
									.ceil(compCount
											/ cc); // row
													// count
					
							var cellWidth = 50;
							var height = (cellWidth * Math.min(3, rc))+2;
							var width = (cc * cellWidth)+10;
							var y = node.y;
							var x = node.x;
							var borderWidth = 10;
							var rBlue = "rgb(176,196,222)"; // Reactome blue
							
							// use unscaled coords for tooltip as displayTooltip
							// function
							// applies zoom
				
							var unscaledLeft = ((x - (width / 2) + this.miCanvasMargin));
							var unscaledTop = ((y - (height / 2) + this.miCanvasMargin));
							var left = ((x - (width / 2) + this.miCanvasMargin)) * this.zoomFactor;
							var top = ((y - (height / 2) + this.miCanvasMargin)) * this.zoomFactor;
							
							tip.setStyle( {
										left : left
												+ "px",
										top : top
												+ "px",
										height : height
												+ "px",
										width : width
												+ "px",
										background : this.cpbg,
										visibility : "visible",
										border: borderWidth + "px",
										borderColor: rBlue,
										zIndex : this.complexpopupZ,
										
										borderStyle:"solid"
									});
							var compsTable = "<div id=\"cplxtablediv\" style=\" width:" 
								+ width + "px; height:" + height + "px; overflow:auto;margin:mvxx\">";
							compsTable += "<table id=\"cplxpopuptable\"  onMouseOver=\"pba.pathwayDiagramPane.displayComplexTableTip(event," 
								+ unscaledLeft +"," 
								+ unscaledTop +", " 
								+ cellWidth 
								+")\">";
							var ieOffset = 0;
							var ieNameDivMod = 0;
							if(navigator.appName == "Microsoft Internet Explorer"){
								if(rc <= 3){
									compsTable = compsTable.replace("mvxx", "-10px");
									ieOffset = 10;
								}
								else{
									compsTable = compsTable.replace("mvxx", "0px");
									ieNameDivMod = 10;
								}
							}

							closetip
							.setStyle( {
								position:"absolute",
								left : (left+width+9-(ieOffset*2))
										+ "px",
								top : (top)
										+ "px",
										zIndex : this.complexpopupZ,
								height :12
										+ "px",
								width : 12
										+ "px"
							
							});
							cplxNameDiv.setStyle({
										left : left
												+ "px",
										top : (top+height+borderWidth-ieOffset)
												+ "px",
										width : (width + (ieNameDivMod*2))
												+ "px",
										background : rBlue,
										zIndex : this.complexpopupZ,
										border: borderWidth + "px",
										borderColor: rBlue,
										borderStyle:"solid",
										overflow:'hidden',
										textAlign : 'center',
										color : 'black'
									});

							cplxNameDiv.innerHTML = node.userObject.name;
							var cinc=0;
							for ( var ri = 0; ri < rc; ri++) { // row index
								compsTable += "<tr>";
								for ( var ci = 0; ci < cc; ci++) { // column index
									// If we have generated all tiles fill remainder of row
									// with empty space.
									if ((cinc) >= compCount) {
										var colspan = (rc*cc) - cinc;
										compsTable += "<td  colspan=\""+ colspan + "\" id=\""
											+ p.dbid
											+ "\" width="
											+ cellWidth
											+ " height="
											+ cellWidth
											+ " style=\"background-color:" + this.cpbg 
											+ ";border-style:outset;border-width:2px;border-color:" 
											+ this.cpbg + ";\">";
									compsTable += "</td>";
										break;
									}
									var p = components[cinc];
									cinc++;
									var colour = this.expressionPainter.refIdMapping[p.refdbid];
									if(!colour){
										colour = this.noHitBG;
									}else{

										var rgb = colour.dataColours.data[this.currentExperiment];

										colour = 
										'rgb('
										+ this.expressionPainter.colourSpectrum[rgb].rgb[0]
										+ ','
										+ this.expressionPainter.colourSpectrum[rgb].rgb[1]
										+ ','
										+ this.expressionPainter.colourSpectrum[rgb].rgb[2]
										+ ')';
									}
									compsTable += "<td id=\""
											+ p.dbid + ":" + p.name + ":" +p.refdbid
											+ "\" width="
											+ cellWidth
											+ " height="
											+ cellWidth
											+ " style=\"background-color: " 
											+ colour 
											+ ";border-style:outset;border-width:2px;border-color:" 
											+ this.cpbg + ";\">";
											// p.name;
											compsTable += "</td>";
								}
								compsTable += "</tr>";
							}
							compsTable += "</table>";
							compsTable += "</div>";
							tip.innerHTML = compsTable;
							if(newlyCreated == true){
								$("ficanvas")
									.appendChild(tip);
								$("ficanvas")
									.appendChild(closetip);
								$("ficanvas").appendChild(cplxNameDiv);
								YAHOO.util.Event.addListener("cplxclosetip",
									"mousedown", this.closetipHandler, this, true);
								YAHOO.util.Event.addListener('cplxcompstipid', 'mouseout',
									this.cplxmouseout, this, true);
								YAHOO.util.Event.addListener('cplxcompstipid', 'mouseover',
									this.cplxmouseover, this, true);
							}else{
								tip.setStyle({visibility: "visible", display:""});
								closetip.setStyle({visibility: "visible", display : ""});
								cplxNameDiv.setStyle({visibility: "visible", display:""});
							}
							this.cplxpopupdisplayed = true;
				    },
				    displayComplexPopupForSpeciesComparison : function(){
			    	    var tip = $("ficanvas").getElementsBySelector('div.cplxcompstip');
			    	    var cplxNameDiv = null;
			    	    var closeTip = null;
			    	    var newlyCreated = false;
			    	    // Check if cplx tip has already been created. If not, create new one.
			    	    if( tip.length == 0){				    	    	
			    	    	tip = Element
								.extend(document
										.createElement('div'));
			    	    	cplxNameDiv = Element.extend(document.createElement('div'));
			    	    	closetip = Element.extend(document.createElement('div'));
			    	    	closetip.className = 'cplxcompstip';
							closetip.id = "cplxclosetip";
							closetip.title = "Close Window";
							closetip.style.cursor = "pointer";
							closetip.innerHTML = "<img src=\"/entitylevelview/icons/whiteclose.png\" width=\"12\" height=\"12\" />";
							tip.className = 'cplxcompstip cplxcompstipid';
							tip.id = "cplxcompstipid";
							cplxNameDiv.className = 'cplxcompstip';
							cplxNameDiv.id = 'cplxnamedivid';
							newlyCreated = true;
			    	    }else{
			    	    	tip = tip[0];
			    	    	cplxNameDiv = document.getElementById('cplxnamedivid');
			    	    	closetip = document.getElementById('cplxclosetip');
			    	    	
			    	    }
						var node = this.currentCplxNode;
						var components = this.complexnodes[node.userObject.id];
						var cc = 3; // column count
									// : how many
									// cells to
									// display in a
									// single row
						var compCount = components.length;
						var rc = Math
								.ceil(compCount
										/ cc); // row
												// count
				
						var cellWidth = 50;
						var height = (cellWidth * Math.min(3, rc))+2;
						var width = (cc * cellWidth)+10;
						var y = node.y;
						var x = node.x;
						var borderWidth = 10;
						var rBlue = "rgb(176,196,222)"; // Reactome blue
						
						// use unscaled coords for tooltip as displayTooltip
						// function
						// applies zoom
			
						var unscaledLeft = ((x - (width / 2) + this.miCanvasMargin));
						var unscaledTop = ((y - (height / 2) + this.miCanvasMargin));
						var left = ((x - (width / 2) + this.miCanvasMargin)) * this.zoomFactor;
						var top = ((y - (height / 2) + this.miCanvasMargin)) * this.zoomFactor;
						
						tip.setStyle( {
									left : left
											+ "px",
									top : top
											+ "px",
									height : height
											+ "px",
									width : width
											+ "px",
									background : this.cpbg,
									visibility : "visible",
									border: borderWidth + "px",
									borderColor: rBlue,
									zIndex : this.complexpopupZ,
									borderStyle:"solid"
								});
						var compsTable = "<div id=\"cplxtablediv\" style=\" width:" 
							+ width + "px; height:" + height + "px; overflow:auto;margin:mvxx\">";
						compsTable += "<table id=\"cplxpopuptable\"  onMouseOver=\"pba.pathwayDiagramPane.displayComplexTableTip(event," 
							+ unscaledLeft +"," 
							+ unscaledTop +", " 
							+ cellWidth 
							+")\">";
						var ieOffset = 0;
						var ieNameDivMod = 0;
						if(navigator.appName == "Microsoft Internet Explorer"){
							if(rc <= 3){
								compsTable = compsTable.replace("mvxx", "-10px");
								ieOffset = 10;
							}
							else{
								compsTable = compsTable.replace("mvxx", "0px");
								ieNameDivMod = 10;
							}
						}

						closetip
						.setStyle( {
							position:"absolute",
							left : (left+width+9-(ieOffset*2))
									+ "px",
							top : (top)
									+ "px",
									zIndex : this.complexpopupZ,
							height :12
									+ "px",
							width : 12
									+ "px"
						
						});
						cplxNameDiv.setStyle({
									left : left
											+ "px",
									top : (top+height+borderWidth-ieOffset)
											+ "px",
									width : (width + (ieNameDivMod*2))
											+ "px",
									background : rBlue,
									zIndex : this.complexpopupZ,
									border: borderWidth + "px",
									borderColor: rBlue,
									borderStyle:"solid",
									overflow:'hidden',
									textAlign : 'center',
									color : 'black'
								});

						cplxNameDiv.innerHTML = node.userObject.name;
						var cinc=0;
						for ( var ri = 0; ri < rc; ri++) { // row index
							compsTable += "<tr>";
							for ( var ci = 0; ci < cc; ci++) { // column index
								// If we have generated all tiles fill remainder of row
								// with empty space.
								if ((cinc) >= compCount) {
									var colspan = (rc*cc) - cinc;
									compsTable += "<td  colspan=\""+ colspan + "\" id=\""
										+ p.dbid
										+ "\" width="
										+ cellWidth
										+ " height="
										+ cellWidth
										+ " style=\"background-color:" + this.cpbg 
										+ ";border-style:outset;border-width:0px;border-color:" 
										+ this.cpbg + ";\">";
									compsTable += "</td>";
									break;
								}
								var p = components[cinc];
								cinc++;
								
								/* Start of species comparison specific code */
								colour = "blue";
								for(var speciesEntityIndex =0; speciesEntityIndex < this.speciesdata.comparisons.length; 
									speciesEntityIndex++){
									if(this.speciesdata.comparisons[speciesEntityIndex].refid == p.refdbid
											&& this.speciesdata.comparisons[speciesEntityIndex].other == 1){
										colour = "yellow";
										break;
									}
								}
								
								/* End of species comparison specific code */
								
								compsTable += "<td id=\""
										+ p.dbid + ":" + p.name + ":" +p.refdbid
										+ "\" width="
										+ cellWidth
										+ " height="
										+ cellWidth
										+ " style=\"background-color: " 
										+ colour 
										+ ";border-style:outset;border-width:2px;border-color:" 
										+ this.cpbg + ";\">";
										compsTable += "</td>";
							}
							compsTable += "</tr>";
						}
						compsTable += "</table>";
						compsTable += "</div>";
						tip.innerHTML = compsTable;
						
						if(newlyCreated == true){
							$("ficanvas")
								.appendChild(tip);
							$("ficanvas")
								.appendChild(closetip);
							$("ficanvas").appendChild(cplxNameDiv);
							YAHOO.util.Event.addListener("cplxclosetip",
								"mousedown", this.closetipHandler, this, true);
							YAHOO.util.Event.addListener('cplxcompstipid', 'mouseout',
								this.cplxmouseout, this, true);
							
							YAHOO.util.Event.addListener('cplxcompstipid', 'mouseover',
								this.cplxmouseover, this, true);
						}else{
							tip.setStyle({visibility: "visible", display:""});
							closetip.setStyle({visibility: "visible", display : ""});
							cplxNameDiv.setStyle({visibility: "visible", display:""});
						}
						this.cplxpopupdisplayed = true;
				    },

					cplxmouseover : function(e){	
						YAHOO.util.Event.removeListener('clipwindow', 'mousemove');
					},
					cplxmouseout : function(e){			
						YAHOO.util.Event.addListener('clipwindow', 'mousemove',
								this.handleMoveOverCanvas, this, true);
					},
					// Called by left/right arrows of experiment browser in order
					// to update cells of table if displayed.
					updateComplexPopup: function(){
						var overlay = $("canvasoverlay");
						var table = $("ficanvas").getElementsBySelector('div.cplxcompstip');
						if(table.length > 0 && table[0].style.visibility == "visible"){
							
							this.displayComplexPopup();
						}
					},
					displayComplexTableTip : function(e, x , y, cellWidth){
						if(e.target){

						}else if(e.srcElement){
							e.target = e.srcElement;
						}
						var data = e.target.id.split(":");
						var dbid = data[0];
						var name = data[1];
 						var refdbid = data[2];
						var cellIndex = e.target.cellIndex;

						var rowIndex = e.target.parentNode.rowIndex;
						var scrollbar = document.getElementById('cplxtablediv');
						
						// calc position of tooltip by using cell/row indexes.
						// add to x,y pos of
						// complex popup.
						var xTip = x;
						
						var offsetX = ((cellIndex * cellWidth) - (cellWidth/2));
						// Use scroll position to adjust position of tooltip to
						// account for scrolling
						// down through list.
                     
						
                        var yTip = y;
                        // 3 is a 'magic' number that lines the tooltips up over
						// the cells in the complex
                        // popup table.
                        var offsetY = (((rowIndex* cellWidth)) - scrollbar.scrollTop) + (cellWidth/3); 

						
						// if there is no name then most likely an empty cell
						// has been moused over.
						if(name){
							this.displayTip(dbid, cellWidth * 1.3, cellWidth * 1.3, name, xTip, yTip, offsetX, offsetY, refdbid);
						}
					},
					closetipHandler : function(e){
						document.getElementById('cplxcompstipid').setStyle({visibility: "hidden"});
						document.getElementById('cplxclosetip').setStyle({visibility: "hidden"});
						document.getElementById('cplxnamedivid').setStyle({visibility: "hidden"});
					},
					onCtxMenuItemClick : function(type, args, me) {
						if(args[1] == "participatingmols"){
							var refdbid = args[0];
							// Hard code db for use with manually drawn diagram. Replace with
							// this.db
							window.open("http://www.reactome.org/cgi-bin/eventbrowser?DB="
								+ this.db + "&ID=" + refdbid);		
						}else if(args[1] == "displayinteractors"){
							var node = args[0];
							this.displayInteractors(node);
						}else if(args[1] == "hideinteractors"){
							var node = args[0];
							this.fiDisplay.hideInteractors(node);
							var colour = "white";
							this.controlPanel.colourRows(node.userObject.id, node.id,  colour);
						} else if(args[1] == "displaycomponents"){
							var node = args[0];
							if (this.paintExpressionData == 1) {
								if(node.userObject.cls == "Complex" ){
									var components = this
											.complexHasComponents(
													node.userObject.id,
													"check");
									if (components.length > 0) {
										this.currentCplxNode = node;
										this.displayComplexPopup();
									} // components.length > 0
								} // cls==complex
							} // expressiondata == 1
							else if(this.displayComparison == 1){
								if(node.userObject.cls == "Complex" ){
									this.currentCplxNode = node;
									this.displayComplexPopupForSpeciesComparison();
								} // cls==complex
							}//displaycomparison==1
						}
						else{
							this.menuItemClickedEvent.fire(args[0], args[1]);
						}
					},
                    displayTip : function(dbid, w, h, name, x,y, offsetX, offsetY, refdbid){
>>>>>>> 1.41
						var id = "tip_" + dbid;
							// For some reason Safari often ignores the request
							// to remove the popups on mouseout.
							// Hence the need to "manually" remove them here.
							$("ficanvas").getElementsBySelector('div.tip')
									.invoke('remove');
							var tip = Element.extend(document
									.createElement('div'));
							tip.className = 'tip';
							tip.id = id;
							var nw, nh;
								nw = 2.5 * w;
								nh = 2 * h;
							tip.innerHTML = name;
							if (this.paintExpressionData == 1){
							var matchedEntity = this.expressionPainter.refIdMapping[refdbid];
								if(matchedEntity){
									tip.innerHTML += ". Id : " + matchedEntity.id + ". Level: " + matchedEntity.data[this.currentExperiment];
								}
							}
							
							tip.setStyle( {
								width : nw + "px",
								display : 'none'
							});
							Event.observe(tip, 'mousedown', function(event) {
								  //Event.stop(event);								
								  //window.open("http://www.reactome.org");
								  var tokens = event.target.id.split("_",2);
								  var localid = tokens[1];
								 // Hard coded db for use with manual diagrams. Replace test_reactome_31_pathway_diagram with 'this.db'
								  window.open("http://www.reactome.org/cgi-bin/eventbrowser?DB="
											+ this.db + "&ID=" + localid);
							}.bind(this));
							$("ficanvas").appendChild(tip);
							// FIX:this was 5
						var border_w = 10;
						nh = tip.getHeight();
						x = (x*this.zoomFactor) + offsetX - (w/2);
						y = (y*this.zoomFactor) + offsetY;
						
						tip.setStyle( {
							left : x + "px",
							top : y + "px",
							opacity : 0.85,
							height : nh + "px",
							border : border_w + "px solid #DCDCDC",
							background : "#DCDCDC",
							zIndex:this.complexpopupZ+1
						});
						new Effect.Appear(tip, {
							duration : 0.5,
							to : 0.85
						});
					},
					 
<<<<<<< PathwayDiagramPane.js
=======
					placeExperimentBrowser : function(){
						var availableWidth = $("clipwindow").getWidth();
						var browserWidth = $("experimentbrowser").getWidth();
						$("experimentbrowser").style.left = ((availableWidth/2) - (browserWidth/2))+"px";
						$("experimentbrowser").style.visibility = "visible";
					},
					displayExpressionLevels : function(scale) {
						document.body.style.cursor = "wait";
						try{
						var i = 0;
						var colourIndex = 0;
						this.paintExpressionData = 1;
						if (this.focus_pathway_id != null) {
							$("canvasoverlay").getElementsBySelector(
									'div.expressiontips').invoke('remove');
							
							this.placeExperimentBrowser();
							if (scale) {
								this.expressionPainter.displayKey(scale);
							} else {
								this.expressionPainter.displayKey(1);
							}
						
							for ( var nodeitem in this.nodes) {
								if (nodeitem && nodeitem != "undefined") {
									var tip = Element.extend(document
											.createElement('div'));
									tip.className = 'expressiontips';
									tip.id = "expressiontip_" + nodeitem;
									var node = this.nodes[nodeitem];
									if (node.cls != "ReactionVertex") {
										var w = node.w;
										var h = node.h;
										var nw, nh = 5;
										nw = w +1;
										nh = h +1;
										if (this.zoomFactor == 1) {
											tip.innerHTML = node.userObject.name;
											tip.innerHTML = tip.innerHTML
													.replace(/\[.*/, "");
											tip.innerHTML = tip.innerHTML.replace(/\:/g,": ");
												
										}
										nw = nw * this.zoomFactor;
										nh = nh * this.zoomFactor;
										tip.setStyle( {
											width : nw + "px",
											height : nh + "px",
											fontSize : "10px",
											textAlign : "center"
										});
										$("canvasoverlay").appendChild(tip);
										var border_w = 5;
										nh = tip.getHeight();

										var nodex = this.nodes[nodeitem].x;
										var nodey = this.nodes[nodeitem].y;
										nodex = nodex * this.zoomFactor
												- border_w
												- (nw - w * this.zoomFactor)
												/ 2;
										nodey = nodey * this.zoomFactor
												- border_w
												- (nh - h * this.zoomFactor)
												/ 2;

										colourIndex++;
										if(node.userObject.cls == "SimpleEntity"){
											// 8 is the multiplier for firefox on linux.
											var dimAdjustment = 8 * this.zoomFactor;
											tip.innerHTML = "<img src=\"/entitylevelview/icons/circle.png\" width=\"" + (nw+dimAdjustment) + 
											"px\" height=\"" + (nh+dimAdjustment)	+ "px\" />";
											if(this.zoomFactor == 1){
												tip.innerHTML = tip.innerHTML + "<div align=\"center\" style=\"vertical-align:middle;width:"  + (nw+dimAdjustment) 
												+ ";height:" + (nh+dimAdjustment) +	";color:white;position:absolute;left: " + 0 + ";top: " + 0 + ";\">"+
												node.userObject.name.replace(/\[.*/, "") + "</div>";
											}
											
											// 3 is the ideal location adjustment for linux firefox.
											var locadjustment = 3;
										     locadjustment +=  (1* (1 - this.zoomFactor ));
											if(this.zoomFactor == 1){
												// 2 is the ideal location adjustment modifier for 
												// linux firefox at maximum zoom
												locadjustment -=2;
											}
											tip
											.setStyle( {
												left : nodex + locadjustment
														+ "px",
												top : nodey +locadjustment 
														+ "px",
												height : (nh) + "px"
											});
										}else
										if (node.userObject.cls != "Complex") {
											// Check if we have this entity matches something in the input data.
											var matchedEntity = this.expressionPainter.refIdMapping[node.userObject.refid];
											if (matchedEntity) {
												//var rgb = this.expressionPainter.dataColours[colourIndex];
												if(this.zoomFactor ==1){
													tip.innerHTML += ". Id : " + matchedEntity.id + ". Level: " + matchedEntity.data[this.currentExperiment];
												}
												tip.className = tip.className + " proteinexpressiontip"
												var rgb = matchedEntity.dataColours.data[this.currentExperiment];
												tip
														.setStyle( {
															left : nodex + 5
																	+ "px",
															top : nodey + 5
																	+ "px",
															height : nh + "px",
															
															background : 'rgb('
																	+ this.expressionPainter.colourSpectrum[rgb].rgb[0]
																	+ ','
																	+ this.expressionPainter.colourSpectrum[rgb].rgb[1]
																	+ ','
																	+ this.expressionPainter.colourSpectrum[rgb].rgb[2]
																	+ ')'
														});
												// check if queryterminal overlay exists.
												this.processFITerminal(node, tip);

											} else {
												// No match so set to grey.
												tip
														.setStyle( {
															left : nodex + 5
																	+ "px",
															top : nodey + 5
																	+ "px",
															height : nh + "px",
															background : this.noHitBG
														});
												tip.style.color="white";
											}
										} else { // its a complex
											var components = this
													.complexHasComponents(
															this.nodes[nodeitem].userObject.id,
															"check");
											if (components.length > 0) {
												//tip.style.backgroundImage = "url(/icons/complex.png)";
												tip.setStyle( {
													background : 'rgb(0,0,0)'
												});
											} else {
												tip
														.setStyle( {
															background : this.noHitBG
														});
											}
											tip.setStyle( {
												left : nodex + 5 + "px",
												top : nodey + 5 + "px",
												height : nh + "px"
											});
											tip.style.color = "white";
										}
									   $("experimentname").innerHTML="Experiment: " + this.expressionPainter.columnNames[this.currentExperiment];
									} 
									tip.style.zIndex=20;
								}
							}
							 
						} // end if(focus pathway != null)
						}catch(ex){
					//		alert("There was a problem overlaying expression data: " + ex.description);
						}
						document.body.style.cursor = "default";
					},
					
					/*
					 * if a queryterminal (from mi overlay) exists for this node, modify its appearance
					 * and hide expression tip.
					 */
					processFITerminal : function(node, expressiontip){
						var queryTerminal = $("queryterminal_" + node.id);
						if(queryTerminal){
						
							queryTerminal.className = 'proteincolour queryTerminal queryComponents'+node.id + " expressiontips";
							queryTerminal.style.background = expressiontip.style.background;
							queryTerminal.innerHTML = expressiontip.innerHTML;
							expressiontip.style.display = "none";
						}
					},
					complexHasComponents : function(index, check) {
						var complex = this.complexnodes[index];
						var components = new Array();
						if(complex){
						for ( var cptI = 0; cptI < complex.length; cptI++) {
							var cpt = this.expressionPainter.refIdMapping[complex[cptI].refdbid];
							// set = null if no hit in refIdMapping?
							if (cpt) {							
								components[cptI] = complex[cptI];
								// if check is defined we just want to see if
								// the complex has any hits in the input data.
								// Dont spend more time collecting components.
								// Used to determine the colour of a complex.
								if (check)
									return components;
							}
						}
						}
						
						return components;
					},
					
					getComplexComponents : function(scale) {
						var idstring = "complexidlist=";
						for ( var nodeitem in this.dbnodes) {
							if (nodeitem) {
								var currentnode = this.nodes[this.dbnodes[nodeitem]];
								if (currentnode.userObject.cls == "Complex") {
									idstring = idstring + "," + nodeitem;
								}
							}
						}
						idstring = idstring.replace(/^complexidlist=,/,
								"complexidlist=");
						idstring = idstring.replace(/,$/, "");
						
						var callback = {
							scope : this,
							customevents : {
								onSuccess : function(eventType, args) {			
						
								var o = eval('(' + args[0].responseText + ')');
								this.complexnodes = new Object();
								for ( var nodeitem = 0; nodeitem < o.clxs.length; nodeitem++) {
									this.complexnodes[o.clxs[nodeitem].dbid] = o.clxs[nodeitem].cpts;
								}
								this.displayExpressionLevels(scale);								
							},
							onFailure : function(eventType, args) {						
								document.body.style.cursor = "default";
							}
							}
						};

						YAHOO.util.Connect.asyncRequest('POST',
								"/ReactomeGWT/entrypoint/elv/ComplexComponentsServlet",
								callback, idstring
										+ "&class=EntityWithAccessionedSequence");

					},
					getComplexComponentsForSpeciesComparison : function(speciesdata) {
						var idstring = "complexidlist=";
						for ( var nodeitem in this.dbnodes) {
							if (nodeitem) {
							   
								var currentnode = this.nodes[this.dbnodes[nodeitem]];
								if (currentnode.userObject.cls == "Complex") {
									idstring = idstring + "," + nodeitem;
								}
							}
						}
						idstring = idstring.replace(/^complexidlist=,/,
								"complexidlist=");
						idstring = idstring.replace(/,$/, "");
						
						
						var callback = {
							scope : this,
							customevents : {
								onSuccess : function(eventType, args) {			
						
								var o = eval('(' + args[0].responseText + ')');
								this.complexnodes = new Object();
								for ( var nodeitem = 0; nodeitem < o.clxs.length; nodeitem++) {
									if(o.clxs[nodeitem].cpts.size && o.clxs[nodeitem].cpts.size() > 1){
										this.complexnodes[o.clxs[nodeitem].dbid] = o.clxs[nodeitem].cpts;
									
									}else{
										this.complexnodes[o.clxs[nodeitem].dbid] = new Array();
										this.complexnodes[o.clxs[nodeitem].dbid][0] = o.clxs[nodeitem].cpts; 
									
									}
									
								}
							
								this.paintSpeciesComparison(speciesdata);								
							},
							onFailure : function(eventType, args) {						
								
							}
							}
						};

						YAHOO.util.Connect.asyncRequest('POST',
								"/ReactomeGWT/entrypoint/elv/ComplexComponentsServlet",
								callback, idstring
										+ "&class=EntityWithAccessionedSequence");

					},
<<<<<<< PathwayDiagramPane.js
>>>>>>> 1.41
=======

>>>>>>> 1.66
					getParticipatingMolecules : function(complexId){
						var idstring = "complexidlist=";
						for ( var nodeitem in this.dbnodes) {
							if (nodeitem) {
							
								var currentnode = this.nodes[this.dbnodes[nodeitem]];
								if (currentnode.userObject.cls == "Complex") {
									idstring = idstring + "," + nodeitem;
								}
							}
						}
						idstring = idstring.replace(/^complexidlist=,/,
								"complexidlist=");
						idstring = idstring.replace(/,$/, "");
						
						var callback = {
							scope : this,
							customevents : {
								onSuccess : function(eventType, args) {							
								var o = eval('(' + args[0].responseText + ')');
								this.complexnodes = new Object();
								for ( var nodeitem = 0; nodeitem < o.clxs.length; nodeitem++) {
									this.complexnodes[o.clxs[nodeitem].dbid] = o.clxs[nodeitem].cpts;
								}
								this.displayExpressionLevels(scale);								
							},
							onFailure : function(eventType, args) {						
							}
							}
						};

						YAHOO.util.Connect.asyncRequest('POST',
								"/ReactomeGWT/entrypoint/elv/ComplexComponentsServlet",
								callback, idstring
										+ "&class=EntityWithAccessionedSequence");
						
					},
					bringElementIntoViewPort : function(el) {
						el = $(el);
						var dims = Element.getDimensions(el);
						var ex = parseInt(el.getStyle('left'));
						var ey = parseInt(el.getStyle('top'));
						var canvas = $('canvas');
						var cx = parseInt(canvas.getStyle('left'));
						var cy = parseInt(canvas.getStyle('top'));
						var dx = 0;
						if (ex < -cx) {
							dx = -cx - ex;
						} else if ((ex + dims.width) > (-cx + this.iClipWidth())) {
							dx = (-cx + this.iClipWidth()) - (ex + dims.width);
						}
						var dy = 0;
						if (ey < -cy) {
							dy = -cy - ey;
						} else if ((ey + dims.height) > (-cy + this
								.iClipHeight())) {
							dy = (-cy + this.iClipHeight())
									- (ey + dims.height);
							dy -= 10;
						}
						if ((dx != 0) || (dy != 0)) {
							this.animatedReposition(dx, dy);
						}
					},
					handleHighliteMouseout : function(event, dbid) {
					},
					animatedReposition : function(x, y) {
						if(isNaN(x) || isNaN(y)){
							return;
						}
						new Effect.Move2($("canvas"), {
							x : x,
							y : y,
							obj : this
						});
					},
					processHighlites : function(highlites) {
						if (highlites) {
							if (highlites.length > 1000) {
								this
										.highliteNodesWithIdsWithPeriodicalExecutioner(highlites);
							} else {
								this
										.highliteNodesForRepresentedInstanceIds(highlites);
								if (((highlites.length == 1) || (this.highlitedCoordinates.length == 1))
										&& this.highlitedCoordinates.length > 0) {
									this.centreOnCoordinate(
											this.highlitedCoordinates[0].x,
											this.highlitedCoordinates[0].y);
								}
							}
						} else {
							this.clearHighlites();
						}
					},
					showDiagramsForVisibleComplexAndSetNodesIfNecessary : function() {
						if ($("entitydiagrams")
								&& $("entitydiagrams").visible()) {
							this.showDiagramsForVisibleComplexAndSetNodes();
						}
					},
					showDiagramsForVisibleComplexAndSetNodes : function() {
						var coords = this.findVisibleComplexAndSetNodes();
						coords.each( function(n) {
							showDiagramForNode(n);
						});
					},
					showDiagramForNode : function(node) {
						var id = "diagram_" + node.userObject.id + "_" + node.x
								+ "_" + node.y;
						if (!$(id)) {
							var x = this.zoomFactor * node.x;
							var y = this.zoomFactor * node.y;
							/*
							 * For some reason, have to make images a bit wider
							 * in order to cover the underlying node completely.
							 */
							var w = this.zoomFactor * node.w + 1;
							var h = this.zoomFactor * node.h + 1;
							var imgsrc = this.imgdir + '/entitydiagrams/'
									+ node.userObject.id + '.png';
							var img = Element.extend(document
									.createElement('img'));
							img.id = id;
							img.setStyle( {
								position : "absolute",
								top : y + "px",
								left : x + "px",
								width : w + "px",
								height : h + "px"
							});
							img.src = imgsrc;
							$("entitydiagrams").appendChild(img);
						}
					},
					findVisibleComplexAndSetNodes : function() {
						var canvas = $('canvas');
						var x1 = -parseInt(canvas.getStyle('left'))
								/ this.zoomFactor;
						var y1 = -parseInt(canvas.getStyle('top'))
								/ this.zoomFactor;
						var x2 = (-parseInt(canvas.getStyle('left')) + this
								.iClipWidth())
								/ this.zoomFactor;
						var y2 = (-parseInt(canvas.getStyle('top')) + this
								.iClipHeight())
								/ this.zoomFactor;
						return this
								.findNodesInArea(x1, y1, x2, y2)
								.findAll(
										function(n) {
											return ((n.userObject.cls == "Complex")
													|| (n.userObject.cls == "DefinedSet") || (n.userObject.cls == "CandidateSet"));
										});
					},
					resetExpressionKey : function(scale) {
						
						if (this.expressionPainter != null
								&& this.paintExpressionData == 1
								&& this.focus_pathway_id != null) {
						
							this.expressionPainter.clearSpectrum();
							this.expressionPainter.displayKey(scale);
						}
					},

					findNodesInArea : function(x1, y1, x2, y2) {
						var out = new Array();
						for ( var j = 0, l = this.orderedRepresentedInstances.length; j < l; ++j) {
							var coords = this.orderedRepresentedInstances[j].coords;
							for ( var i = 0; i < coords.length; i++) {
								if ((x2 > coords[i].x)
										&& (x1 < coords[i].x + coords[i].w)
										&& (y2 > coords[i].y)
										&& (y1 < coords[i].y + coords[i].h)) {
									out.push(coords[i]);
								}
							}
						}
						return out;
					},
					getVisibleArea : function() {
						var canvas = $('canvas');
						var x = -parseInt(canvas.getStyle('left'))
								/ this.zoomFactor;
						var y = -parseInt(canvas.getStyle('top'))
								/ this.zoomFactor;
						var w = this.iClipWidth() / this.zoomFactor;
						var h = this.iClipHeight() / this.zoomFactor;
						return {
							"x" : x,
							"y" : y,
							"w" : w,
							"h" : h
						};
					},
					isAnyNodeVisible : function(nodeArray) {
						var r = getVisibleArea();
						var x1 = r.x;
						var x2 = r.x + r.w;
						var y1 = r.y;
						var y2 = r.y + r.h;
						for ( var i = 0, l = nodeArray.length; i < l; ++i) {
							var n = nodeArray[i];
							if ((x2 > n.x) && (x1 < n.x + n.w) && (y2 > n.y)
									&& (y1 < n.y + n.h)) {
								return true;
							}
						}
						return false;
					},
					transientlyHighliteNode : function(node) {
						//log("transientlyHighliteNode x = " + node.x + ", y = " + node.y);
						var x = this.zoomFactor * node.x;
						var y = this.zoomFactor * node.y;
						var w = this.zoomFactor * node.w;
						var h = this.zoomFactor * node.h;
						if (YAHOO.env.ua.ie > 0) {
							w += 2 * this.highliteBorderThickness;
							h += 2 * this.highliteBorderThickness;
						}
						x -= this.highliteBorderThickness;
						y -= this.highliteBorderThickness;
						var thl = Element.extend(document.createElement('div'));
						thl.innerHTML = "&nbsp;";
						thl.id = "thl_" + node.id;
						thl.className = "transienthighlite";
						thl.setStyle( {
							position : "absolute",
							top : y + "px",
							left : x + "px",
							width : w + "px",
							height : h + "px"
						});
						$("canvasoverlay").appendChild(thl);
						// Thumb
						x = node.x / this.imgw * this.thumbnailw - 1;
						y = node.y / this.imgh * this.thumbnailh - 1;
						var t_thl = Element.extend(document
								.createElement('div'));
						t_thl.innerHTML = "&nbsp;";
						t_thl.id = "t_thl_" + node.id;
						t_thl.className = "thumbtransienthighlite";
						t_thl.setStyle( {
							position : "absolute",
							top : (y - 1) + "px",
							left : (x - 1) + "px",
							width : "3px",
							height : "3px"
						});
						$("thumbnailoverlay").appendChild(t_thl);
					},
					removeTransientHighlites : function() {
						this.dbidOfNodeBeingHighlited = null;
						if ($("canvasoverlay") != null) {
							$A(
									$("canvasoverlay").getElementsByClassName(
											"transienthighlite")).map(
									function(e) {
										e.remove();
									});
							$A(
									$("thumbnailoverlay")
											.getElementsByClassName(
													"thumbtransienthighlite"))
									.map( function(e) {
										e.remove();
									});
						}
					},
					removeTransientHighliteFromNode : function(node) {
						this.removeTransientHighliteFromNodeWithId(node.id);
					},
					removeTransientHighliteFromNodeWithId : function(id) {
						var thl = $("thl_" + id);
						if (thl) {
							thl.remove();
						}
						var t_thl = $("t_thl_" + id);
						if (t_thl) {
							t_thl.remove();
						}
					},
					transientlyHighliteNodesForRepresentedInstance : function(i) {
						var t = this;
						i.coords.map( function(n) {
							t.transientlyHighliteNode(n);
						});
					},
					removeTransientlyHighliteFromNodesForRepresentedInstance : function(
							i) {
						var t = this;
						i.coords.map( function(n) {
							t.removeTransientHighliteFromNode(n);
						});
					},
					transientlyHighliteNodesForRepresentedInstanceId : function(
							id) {
						this.removeTransientHighlites();
						if (this.current_instance_id == id)
							return;
						if (this.representedInstances == null)
							return;
						var i = this.representedInstances[id];
						if (i) {
							this
									.transientlyHighliteNodesForRepresentedInstance(i);
							// centreOnCoordinate(i.coords[0].x, i.coords[0].y);
						} else if (this.transientHighliteIdCache[id]) {
							this
									.transientlyHighliteNodesWithIds(this.transientHighliteIdCache[id]);
							// if (this.transientHighliteIdCache[id][0])
							// centreOnNodeWithId(this.transientHighliteIdCache[id][0]);
						} else {
							this.loadTransientHighlites(id);
						}
					},
					removeTransientlyHighliteFromNodesForRepresentedInstanceId : function(
							id) {
						var i = this.representedInstances[id];
						if (i) {
							this
									.removeTransientlyHighliteFromNodesForRepresentedInstance(i);
						} else if (this.transientHighliteIdCache[id]) {
							//log(this.transientHighliteIdCache[id]);
							this
									.removeTransientHighlitesFromNodesWithIds(this.transientHighliteIdCache[id]);
						}
					},
					highliteNodesForRepresentedInstance : function(i,
							keepPrevious) {
						if (!keepPrevious)
							clearHighlites();
						var t = this;
						i.coords.map( function(n) {
							t.highliteInViewportAndCache(n, true);
						});
					},
					highliteNodesForRepresentedInstanceId : function(id,
							keepPrevious) {
						var i = this.representedInstances[id];
						if (i)
							this.highliteNodesForRepresentedInstance(i,
									keepPrevious);
					},
					highliteNodesForRepresentedInstanceIds : function(ids,
							keepPrevious) {
						if (!keepPrevious)
							this.clearHighlites();
						for ( var j = 0, l = ids.length; j < l; ++j) {
							var i = this.representedInstances[ids[j]];
							if (i) {
								this.highliteNodesForRepresentedInstance(i,
										true);
							} else {
								//log("No representedInstance with id "+ids[j]);
							}
						}
					},
					transientlyHighliteNodesWithIds : function(ids) {
						var t = this;
						ids.map( function(id) {
							var n = t.nodes[id];
							if (n != null)
								t.transientlyHighliteNode(n)
						});
					},
					removeTransientHighlitesFromNodesWithIds : function(ids) {
						var t = this;
						ids.map( function(id) {
							t.removeTransientHighliteFromNodeWithId(id)
						});
					},
					isInViewPort : function(n) {
						//log(this.viewportRight+">"+n.x+","+this.viewportLeft +"<"+(n.x+n.w)+","+this.viewportBottom+">"+n.y+","+this.viewportTop+"<"+(n.y+n.h));
						return ((this.viewportRight > n.x)
								&& (this.viewportLeft < n.x + n.w)
								&& (this.viewportBottom > n.y) && (this.viewportTop < n.y
								+ n.h));
					},
					anyInViewPort : function(nodes) {
						for ( var i = 0, l = nodes.length; i < l; ++i) {
							if (this.isInViewPort(nodes[i]))
								return true;
						}
						return false;
					},
					/*
					 * The point of this is to do the highliting is small chunks so that the browser
					 * doesn't get "tired" with the process and suggest to kill it.
					 */
					highliteWithPeriodicalExecutioner : function(nodeArray) {
						var c = 0;
						var step = 500;
						var t = this;
						new PeriodicalExecuter( function(pe) {
							var t1 = new Date().getTime();
							for ( var i = c; i < c + step; ++i) {
								if (i >= nodeArray.length) {
									pe.stop();
									break;
								} else {
									var node = nodeArray[i];
									t.highliteInViewportAndCache(node, true);
								}
							}
							var t2 = new Date().getTime();
							// log("PeriodicalExecuter "+c+" ran for "+(t2 -
							// t1)/1000 + "s");
								c += step;
							}, 1);
					},
					/*
					 * The point of this is to do the highliting is small chunks so that the browser
					 * doesn't get "tired" with the process and suggest to kill it.
					 */
					highliteNodesWithIdsWithPeriodicalExecutioner : function(
							idArray) {
						this.clearHighlites();
						var c = 0;
						var step = 1000;
						var t = this;
						new PeriodicalExecuter(
								function(pe) {
									var t1 = new Date().getTime();
									for ( var i = c; i < c + step; ++i) {
										if (i >= idArray.length) {
											pe.stop();
											break;
										} else {
											var node = t.representedInstances[idArray[i]];
											if (node != null) {
												t
														.highliteNodesForRepresentedInstance(
																node, true);
											} else {
												//log("No node: Idx: " + i + ", DB_ID:" + idArray[i]);
											}
										}
									}
									var t2 = new Date().getTime();
									// log("PeriodicalExecuter "+c+" ran for
									// "+(t2 - t1)/1000 + "s");
									c += step;
								}, 1);
					},
					centreOnNodeWithId : function(node_id) {
						var node = this.nodes[node_id];
						if (node) {
							this.centreOnCoordinate(node.x, node.y);
						} else {
							log("No node with id " + node_id);
						}
					},
					getNodesWithIds : function(ids) {
						var out = [];
						for ( var i = 0, l = ids.length; i < l; ++i) {
							var n = this.nodes[ids[i]];
							if (n != null) {
								out.push(n);
							}
						}
						return (out);
					},
					/* not used */
					getNodesWithRepresentedInstanceIds : function(ids) {
						var out = [];
						for ( var i = 0, l = ids.length; i < l; ++i) {
							var n = this.representedInstances[ids[i]];
							if (n != null) {
								var coords = n.coords;
								for ( var j = 0, m = coords.length; j < m; ++j) {
									out.push(coords[j]);
								}
							}
						}
						return (out);
					},
					loadTransientHighlites : function(dbid) {
						if (!this.inLoadTransientHighlites) {
							this.dbidOfNodeBeingHighlited = dbid;
							this.inLoadTransientHighlites = true;
							var t = this;
							new Ajax.Request(
									this.diagramhighlitesurl + '?DB=' + this.db
											+ '&FOCUS_SPECIES_ID='
											+ this.focus_species_id + '&ID='
											+ dbid,
									{
										method : 'get',
										onSuccess : function(transport) {
											var rtxt = transport.responseText;
											var o = eval(rtxt);
											t.transientHighliteIdCache[dbid] = o.highlites;
											if (t.dbidOfNodeBeingHighlited == dbid)
												t
														.transientlyHighliteNodesWithIds(o.highlites);
										},
										onComplete : function() {
											t.inLoadTransientHighlites = false;
										}
									});
						}
					},
					removeImageTiles : function() {
						//log("removeImageTiles()");
						var tiles = $("tiles");
						if (tiles) {
							//for ( var i = 0, l = tiles.childNodes.length; i < l; ++i) {
							for ( var i = tiles.childNodes.length -1 ; i >-1; i--) {
								/*
								 * Some more black magic - have to remove the tiles from the end in order to be 
								 * able to remove them all (or most of them). Ones which have become 'undefined'
								 * nevertheless show up on screen so that zoomed-out diagram contains tiles from 
								 * previous zoom level.
								 */
								var c = tiles.childNodes[i];
								if (typeof (c) != 'undefined') {
									$(c).remove();
								}
							}
						}
					},
					setImgDir : function() {
						this.imgdir = this.basedir + this.db + "/"
								+ this.focus_species_id + "/"
								+ this.focus_pathway_id;
					},
					changeFocusPathway : function(pathway_id) {
						if (this.focus_species_id != null) {
<<<<<<< PathwayDiagramPane.js

=======
							// Clear the mi overlay when changing pathways.
							// An alternative would be to check if new pathway shares proteins with
							// old pathway that the user has overlayed interactors for and overlay
							// these interactors in new pathway.
							if(this.fiDisplay != null){
								this.fiDisplay.cleanUp();
								this.fiDisplay = new FIDisplay();
								this.fiDisplay.init(this.intactSearchUrl, this.miCanvasMargin);
							}
							if(this.controlPanel != null){
								this.controlPanel.hideTable();
							}
>>>>>>> 1.41
							this.removeImageTiles();
							this.focus_pathway_id = pathway_id;
							this.setImgDir();
							this.loadOrderedCoordinates();
<<<<<<< PathwayDiagramPane.js

	

					}
=======
					}
>>>>>>> 1.41
			},
			onTransientHighliteRequest : function(type, args) {
				//log("onTransientHighliteRequest " + args);
					this.transientlyHighliteNodesForRepresentedInstanceId(args[0]);
				},
				onTransientHighliteRemovalRequest : function(type) {
					//log("onTransientHighliteRemovalRequest");
					this.removeTransientHighlites();
				}
				});

/*
 * Extend scriptaculous' Effect.Move so that the tiles get created/populated
 * upon move. This is what the reposition(0,0) is for. OK, undoubtedly things
 * could be done more efficiently.
 */
Effect.Move2 = Class.create();
Object.extend(Object.extend(Effect.Move2.prototype, Effect.Move.prototype), {
	update : function(position) {
		this.element
				.setStyle( {
					left : Math.floor(this.options.x * position
							+ this.originalLeft) + 'px',
					top : Math.floor(this.options.y * position
							+ this.originalTop) + 'px'
				});
		this.options.obj.reposition(0, 0);
	}
});

/*
 * Overload diagram highlighting related methods if the browser is old IE which
 * doesn't support transparency.
 */
if ((YAHOO.env.ua.ie > 0) && (YAHOO.env.ua.ie < 7)) {
	Object.extend(PathwayDiagramPane.prototype, {
		highliteNode : function(node) {
			var oCO = $("canvasoverlay");
			var x = this.zoomFactor * node.x;
			var y = this.zoomFactor * node.y;
			var w = this.zoomFactor * node.w;
			var h = this.zoomFactor * node.h;
			if (YAHOO.env.ua.ie > 0) {
				w += 2 * this.highliteBorderThickness;
				h += 2 * this.highliteBorderThickness;
			}
			x -= this.highliteBorderThickness;
			y -= this.highliteBorderThickness;
			var node_id = 'hl_' + node.id;
			var hl = Element.extend(document.createElement('div'));
			hl.innerHTML = "&nbsp;";
			hl.id = node_id;
			hl.className = "highlite";
			hl.setStyle( {
				position : "absolute",
				top : y + "px",
				left : x + "px",
				width : w + "px",
				height : h + "px"
			});
			Event.observe(hl, 'mouseover', this.handleHighliteMouseover
					.bindAsEventListener(this, node.id));
			Event.observe(hl, 'mouseout', this.handleHighliteMouseout
					.bindAsEventListener(this, node.id));
			Event.observe(hl, 'mousemove', this.handleHighliteMouseover
					.bindAsEventListener(this, node.id));
			$("canvasoverlay").appendChild(hl);
			node.isHighlited = true;
			return hl;
		},
		highliteCoordinate : function(x, y, w, h, keepPrevious) {
			//log("EntityLevelView.highliteCoordinate()");
			x *= this.zoomFactor;
			y *= this.zoomFactor;
			w *= this.zoomFactor;
			h *= this.zoomFactor;
			var oCO = $("canvasoverlay");
			if (YAHOO.env.ua.ie > 0) {

				w += 2 * this.highliteBorderThickness;
				h += 2 * this.highliteBorderThickness;
			}
			x -= this.highliteBorderThickness;
			y -= this.highliteBorderThickness;
			var tmp = '<div class="highlite" style="position:absolute;top:' + y
					+ ';left:' + x + ';width:' + w + 'px;height:' + h
					+ 'px;" onmouseover=""><!-- --></div>';
			if (keepPrevious) {
				oCO.innerHTML += tmp;
			} else {
				oCO.innerHTML = tmp;
			}
		},
		highliteNodeIfInViewPort : function(node) {
			if (this.isInViewPort(node)) {
				var oCO = $("canvasoverlay");
				var x = this.zoomFactor * node.x;
				var y = this.zoomFactor * node.y;
				var w = this.zoomFactor * node.w;
				var h = this.zoomFactor * node.h;
				if (YAHOO.env.ua.ie > 0) {
					w += 2 * this.highliteBorderThickness;
					h += 2 * this.highliteBorderThickness;
				}
				x -= this.highliteBorderThickness;
				y -= this.highliteBorderThickness;
				var node_id = 'hl_' + node.id;
				var hl = $(node_id);
				if (hl == null) {
					var hl = Element.extend(document.createElement('div'));
					hl.innerHTML = "&nbsp;";
					hl.id = node_id;
					hl.className = "highlite";
					Event.observe(hl, 'mouseover', this.handleHighliteMouseover
							.bindAsEventListener(this, node.id));
					Event.observe(hl, 'mouseout', this.handleHighliteMouseout
							.bindAsEventListener(this, node.id));
					Event.observe(hl, 'mousemove', this.handleHighliteMouseover
							.bindAsEventListener(this, node.id));
					$("canvasoverlay").appendChild(hl);
				}
				hl.setStyle( {
					position : "absolute",
					top : y + "px",
					left : x + "px",
					width : w + "px",
					height : h + "px"
				});
				return hl;
			}
		},
		clearHighlites : function() {
			this.highlitedCoordinates.map( function(n) {
				n.isHighlited = false;
			});
			this.highlitedCoordinates.length = 0;
			var oCO = $("canvasoverlay");
			if (oCO) {
				oCO.innerHTML = '';
				var to = $("thumbnailoverlay");
				to.innerHTML = '';
			}
		}
	});
	YAHOO.util.Event
			.onDOMReady( function() {
				if ($('iedialogcontainer') != null) {
					var iedialog = new YAHOO.widget.SimpleDialog(
							"iedialog",
							{
								width : "300px",
								fixedcenter : true,
								visible : false,
								draggable : false,
								close : true,
								text : "This page works better with Internet Explorer 7, Firefox or Safari.",
								constraintoviewport : true
							});
					iedialog.setHeader("Note");
					iedialog.render("iedialogcontainer");
					iedialog.show();
				}
			});
	
}

/*
 * Global functions
 */
function log(msg) {
	var oLog = $("log");
	if (oLog != null) {
		//oLog.innerHTML += msg + "<BR/>\n";
		oLog.innerHTML = msg + "<BR/>\n" + oLog.innerHTML;
	}
}

function clearLog() {
	var oLog = $("log");
	if (oLog != null) {
		oLog.innerHTML = "";
	}
}
