var rgraph;
var canvas;
var startingNode = 0;

var Log = {
	elem: $('log'),
	write: function(text, cursor) {
		if(!this.elem) this.elem = $('log');
		this.elem.set('html', text);
	}
};

function start() {
	warnIfIE(); 
	var multiple = gup('m');
	if(!multiple) multiple = true;	// true to indicate that we should be grouping neurons together
	else if (multiple == 0) multiple = false;
	if(multiple) Config.fontSize = 100; 	// 100%
	else Config.fontSize = 75;		// 75%
	setMultiple(multiple);
	init(multiple);
	var center = gup('c');
	if(!center) center = 'BAG';
	centerNode(center);
	centerEvidence(true);
}

// Keeps the graph centered regardless of the size of the window
function resize() {
	var size = Window.getSize();
	var leftOffset = $('left').getSize().x;
	var topOffset = $('title').getSize().y + $('searchnet').getSize().y + $('options').getSize().y + $('searchgenes').getSize().y - $('netresults').getSize().y;
	var h = Math.floor((size.y - 0) / 1);
	var w = Math.floor((size.x - leftOffset) / 1);
	var newStyles = { 'height': h, 'width' : w };
	$('infovis').setStyles(newStyles);
	$('left').setStyle('height', newStyles.height);  // Need to set the height to get proper scrollbars
	$('netresults').setStyle('height', Math.floor((size.y - topOffset) / 1));
	var legend = $('legend');
	legend.setStyle('left', size.x - legend.getSize().x);
	legend.setStyle('top', size.y - legend.getSize().y);
	centerEvidence();
	canvas.resize(w,h);
	rgraph.refresh();
	rgraph.controller.onAfterCompute(); 
}

function centerEvidence(hide) {
	var size = Window.getSize();
	var leftOffset = $('left').getSize().x;
	var h = Math.floor((size.y - 0) / 1);
	var w = Math.floor((size.x - leftOffset) / 1);
	$('evidenceFrame').setStyle('height', h - 70);
	$('evidenceFrame').setStyle('width', w - 70);
	$('evidenceFrame').setStyle('left', leftOffset + 35);
	$('evidenceFrame').setStyle('top', 35);
	$('evidenceContent').setStyle('height', h-70);
	$('evidenceContent').setStyle('width', w-70);
	if (hide) {
		changeDisplay('evidenceFrame', 'none');
	}
}

function dispErr(msg) {
	$('error').innerHTML = msg;
}

function genNeuronAndLinks(id, id2) {
	$('neuronlink').setProperty('href', 'http://www.wormatlas.org/neurons/Individual Neurons/' + id + 'mainframe.htm');
	$('moreinfo').innerHTML = "<a href='http://www.wormatlas.org/neurons/Individual Neurons/" + id + "mainframe.htm' target='_blank'>WormAtlas</a> - <a href=http://scholar.google.com/scholar?q=caenorhabditis+elegans+%2B" + id2 +  "  target='_blank'>Google Scholar</a> - <a href='http://wormbase.org/db/ontology/anatomy?name=" + id2 + ";open=show_Expr_pattern'  target='_blank'>WormBase</a>";
	$('addgenedatalink').innerHTML = "<a href='javascript:void(0)' onclick=openForm('addgene');>Add gene expression data for <b>" + id2 + "</b></a>";
	$('addphysdatalink').innerHTML = "<a href='javascript:void(0)' onclick=openForm('addphys');>Add physiology data for <b>" + id2 + "</b></a>";
	$('addlofdatalink').innerHTML = "<a href='javascript:void(0)' onclick=openForm('addlof');>Add loss-of-function data for <b>" + id2 + "</b></a>";
	$('addgofdatalink').innerHTML = "<a href='javascript:void(0)' onclick=openForm('addgof');>Add gain-of-function data for <b>" + id2 + "</b></a>";
}

function dispNeuronAndLinks(id) {
	$('neuronimg').setProperty('src', 'img/' + id + '.png');
	if(id == 'AS') genNeuronAndLinks('ASn', id);
	else if(id == 'DA') genNeuronAndLinks('DAN', id);
	else if(id == 'DB') genNeuronAndLinks('DBN', id);
	else if(id == 'DD') genNeuronAndLinks('DDN', id);
	else if(id == 'VC') genNeuronAndLinks('VCN', id);
	else if(id == 'MUS') genNeuronAndLinks('muscle', 'muscle');	
	else genNeuronAndLinks(id.toUpperCase(), id);
}

function toggleOptions() {
	var oldOptionsHeight = $('options').getSize().y;
	toggleDisplay('optionsTable');
	$('netresults').setStyle('height', Math.floor($('netresults').getSize().y - $('options').getSize().y + oldOptionsHeight) - 1);
}

function openForm(class2) {
	toggleDisplay(class2 + "formdiv"); 
	changeDisplay(class2 + "datasuccess", "none");
	$(class2 + "datasubmitting").innerHTML = "";
	$(class2 + "submitbutton").disabled = false;
}

function submitData(type) {
	if (type == 'addgene') {
		if ($('gene').value.length == 0) {
			$('addgeneerror').setProperty('class', 'error');
			return false;
		}
	}
	$(type + 'submitbutton').disabled = true;
	$(type + 'cell').value = $('cnode').value;
	$(type + 'mult').value = getMultiple();
	$(type + 'form').target = 'upload_target';
	$(type + 'datasubmitting').innerHTML = 'Submitting...';
	return true;
}

function rebalanceScrollingRegions() {
	var space = $('netresults').getSize();
	if (Math.abs($('genesresults').getSize().y - space.y) > 1) {
		$('netresults').setStyle('height', Math.floor(space.y/2));
		$('genesresults').setStyle('height', Math.floor(space.y/2));
		$('genesresults').setStyle('width', space.x);
	}
}

function submitOnEnter(myfield,e) {
	var keycode;
	if (window.event) keycode = window.event.keyCode;
	else if (e) keycode = e.which;
	else return true;
	if (keycode == 13) {
	  if (myfield.name == 'goi' || myfield.name == 'goi2') {
	      changeDisplay('genesresults', '');
	      rebalanceScrollingRegions();
	      if($('goi').value == '') {
		$('genesresults').innerHTML = '<span class=error>Please enter a gene to find cells which express it.</span>';
	      } else {
		if ($('goi2').value == '') {
		  $('genesresults').innerHTML = 'Searching for cells that express <i><b>' + $('goi').value + '</b></i>...';
		} else {
		  $('genesresults').innerHTML = 'Searching for cells that express <i><b>' + $('goi').value + '</b></i> and are pre-synaptic to cells that express <nobr><i><b>' + $('goi2').value  + '</b></i>...</nobr>';
		}
		lookupGene($('goi').value, $('goi2').value);
	      }
	  } else {
  	    centerNode($('cnode').value);
          }
  	  return false;
	} else
	  return true;
}

function updateURL(c,m) {
	//name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
	var regexS = "([^#]*)#*";
	//var regexS = "[\\#&]"+name+"=([^&]*)";
	var regex = new RegExp( regexS );
	var results = regex.exec( window.location.href );
	window.location.href = results[1] + "#c=" + c + "&m=" + m;
}

function getMultiple() {
	var v = document.getElementsByName('multiple');
	for (var i = 0; i < v.length; i++) {
		if(v[i].checked) return (v[i].value);
	}
}

function setMultiple(m) {
	var v = document.getElementsByName('multiple');
	if(m == 1) {
		v[0].checked = true;
		v[1].checked = false;
	} else if(m == 0) {
		v[1].checked = true;
		v[0].checked = false;
	}
}

function findPath(src, dest) {
	if(GraphUtil.getNode(rgraph.graph, dest)) {
		makeGETRequest2("findpath.php", "s=" + src + "&e=" + dest + "&m=" + getMultiple(), 'receiveDataResponse', 'results');
		$("dnode").value = dest;
		$("results").innerHTML = "<b><font color=red>Searching for paths...</font></b> <i>(max 1 minute)</i>";
	} else {
		dispErr("No cell named <b>" + dest + "</b> in this network");
	}
}

function receiveDataResponse(req, loc) {
  if(req.responseText == "") 
    $(loc).innerHTML = "<font color=red><b>Request timed out :(</b></font>"
  else 
    $(loc).innerHTML = req.responseText;
  return true;
}

function fetchExtraData(cell) {
	if (cell != 'BAG' || (cell == 'BAG' && (gup('c') == 'BAG') || gup('c') == '' || $('cnode').value.toUpperCase() == 'BAG')) {
		fetchData(cell, 'all');
	}
}

function fetchData(cell, type) {
	makeGETRequest2("fetchData.php", "c=" + cell + "&m=" + getMultiple() + "&t=" + type, 'receiveDataResponse', type+'data');
}

function showEvidence(cell, gene, multiple, isoform, comment, authors, title, journal, year, figure_id) {
	var curGene = $('geneWithFigure').innerHTML;
	var curCell = $('cellWithFigure').innerHTML;
	if (curGene == gene && curCell == cell) {
		toggleDisplay('evidenceFrame');
	} else {
		$('geneWithFigure').innerHTML = gene;
		$('cellWithFigure').innerHTML = cell;
		changeDisplay('evidenceFrame', '');
	}
	var figtitle = "Expression of <i>" + gene + "</i>";
	if (isoform != "") {
		figtitle += " (" + isoform + ")";
	}
	figtitle += " in " + cell;
	$('evidenceTitle').innerHTML = figtitle;
	if (figure_id > 0) {
		$('evidenceFigure').innerHTML = "<img src=viewEvidenceFigure.php?id=" + figure_id + ">";
	} else {
		$('evidenceFigure').innerHTML = "";
	}
	$('evidenceComment').innerHTML = "<b>" + comment + "</b>";
	$('evidenceCitation').innerHTML = printCitation(authors, title, journal, year);
}

function showFunctionalEvidence(cell, multiple, toptitle, type, method, gene, background, phenotype, effect, relative, comment, authors, title, journal, year, figure_id) {
	var curGene = $('geneWithFigure').innerHTML;
	var curCell = $('cellWithFigure').innerHTML;
	if (curGene == type+method+phenotype+effect && curCell == cell) {
		toggleDisplay('evidenceFrame');
	} else {
		$('geneWithFigure').innerHTML = type+method+phenotype+effect;
		$('cellWithFigure').innerHTML = cell;
		changeDisplay('evidenceFrame', '');
	}
	var figtitle = toptitle + '&nbsp;(' + cell + ')';
	$('evidenceTitle').innerHTML = figtitle;
	if (figure_id > 0) {
		$('evidenceFigure').innerHTML = "<img src=viewEvidenceFigure.php?id=" + figure_id + ">";
	} else {
		$('evidenceFigure').innerHTML = "";
	}
	$('evidenceComment').innerHTML = "<b>" + comment + "</b>";
	$('evidenceCitation').innerHTML = printCitation(authors, title, journal, year);
}

function showPhysEvidence(cell, multiple, type, observable, method, background, stimulus, response, relative, comment, authors, title, journal, year, figure_id) {
	var curGene = $('geneWithFigure').innerHTML;
	var curCell = $('cellWithFigure').innerHTML;
	if (curGene == observable+stimulus+response && curCell == cell) {
		toggleDisplay('evidenceFrame');
	} else {
		$('geneWithFigure').innerHTML = observable+stimulus+response;
		$('cellWithFigure').innerHTML = cell;
		changeDisplay('evidenceFrame', '');
	}
	var figtitle = "In <i>" + background + "</i>, " + stimulus + " " + response + "s " + observable + " in " + cell + " relative to <i>" + relative + "</i>";
	$('evidenceTitle').innerHTML = figtitle;
	if (figure_id > 0) {
		$('evidenceFigure').innerHTML = "<img src=viewEvidenceFigure.php?id=" + figure_id + ">";
	} else {
		$('evidenceFigure').innerHTML = "";
	}
	$('evidenceComment').innerHTML = "<b><br>Type: " + type + "<br>Method: " + method + "<p>" + comment + "</b>";
	$('evidenceCitation').innerHTML = printCitation(authors, title, journal, year);
}

function printCitation(authors, title, journal, year) {
	var str = authors + " ";
	if (year > 0) {
		str += year + ". ";
	} else {
		year = "";
	}
	str += "<a target='blank' href=http://scholar.google.com/scholar?as_q=" + escape(title) + "&as_authors=" + escape(authors) + "&as_publication=" + escape(journal) + "&as_ylo=" + escape(year) + "&as_yhi=" + escape(year) + ">" + title + "</a>. <i>" + journal + "</i>.";
	return str;
}

function lookupGene(gene1, gene2) {
	gene1 = gene1.toLowerCase();
	gene2 = gene2.toLowerCase();
	makeGETRequest2("searchGeneExpression.php", "g1=" + gene1 + "&g2=" + gene2 + "&m=" + getMultiple(), 'receiveDataResponse', 'genesresults');
	return false;
}

function centerNode(id) {
	id = id.toUpperCase();
	if(GraphUtil.getNode(rgraph.graph, id)) {
		changeDisplay('evidenceFrame', 'none');
		dispErr("&nbsp;");
		dispNeuronAndLinks(id);
		$("cnode").value = id;
		var dest = $("dnode").value;
		dest = dest.toUpperCase();
		if(dest != "" && dest != id) findPath(id, dest);
		else $("alldata").innerHTML = "Loading data...";
		updateURL(id, getMultiple());
		rgraph.onClick(id);
	} else {
		dispErr("No cell named <b>" + id + "</b> in this network");
	}
	return false;
}

function moreLines(checked) {
	if(checked) Config.showOnlyCenterEdges = false;
	else Config.showOnlyCenterEdges = true;
	rgraph.refresh();
	rgraph.controller.onAfterCompute();	
}

function generateBackgroundCanvas() {
	var backgroundCanvas = {
	'styles': {
            'fillStyle': '#444',
            'strokeStyle': '#444'
        },
        //Add the initialization and plotting functions.
        'impl': {
            'init': $empty,
            'plot': function(canvas, ctx) {
                var times = Config.drawConcentricCircles, d = Config.levelDistance;
                var pi2 = Math.PI*2;
                for(var i=1; i<=times; i++) {
                    ctx.beginPath();
                    ctx.arc(0, 0, i * d, 0, pi2, true);
                    ctx.stroke();
                    ctx.closePath();
                }
            }
        }
	};
	return backgroundCanvas;
}

function zoom(step) {
	canvas.setScale(step);
	var backgroundCanvas = generateBackgroundCanvas();
	canvas.refresh(backgroundCanvas);
	Log.write("zooming");
	rgraph.refresh();
	rgraph.controller.onAfterCompute();
}

function showMultiple(flag) {
	var json = getJson(flag);
	//load weighted graph.
	if(flag) Config.fontSize = 100; // 100%
	else Config.fontSize = 75;		// 75%
	rgraph.loadGraphFromJSON(json, startingNode);
	GraphPlot.clearLabels(rgraph);
	rgraph.refresh();
	rgraph.controller.onBeforeCompute(GraphUtil.getNode(rgraph.graph, rgraph.root));
	rgraph.controller.onAfterCompute();
	if(flag) centerNode('BAG');
	else centerNode('RIVL');
}

/*
var dragging, currX, currY;

function canvasPressed(event) {
	dragging = true;
	currX = event.pageX;
	currY = event.pageY;
}

function canvasDragged(event) {
	if(!dragging) return;
	var deltaX = event.pageX - currX;
	var deltaY = event.pageY - currY;
	canvas.move(deltaX, deltaY);
	rgraph.refresh();
	rgraph.controller.onAfterCompute();
}

function canvasReleased(event) {
	dragging = false;
}
*/

function drawEdgeDecoration(canvas, node, child, type, weight) {
	var pos = node.pos.toComplex();
	var posChild = child.pos.toComplex();

	canvas.getCtx().globalCompositeOperation = 'destination-over'; // don't draw over nodes!
    	canvas.path('fill', function(ctx) {
        	ctx.save();
        	ctx.translate(posChild.x,posChild.y);
        	var o = parseFloat(posChild.y-pos.y);
        	var a = parseFloat(posChild.x-pos.x);
        	if(a!=0){
        		var rad = Math.atan2(o,a);
			var w = Math.sqrt(weight) / Math.sqrt(2);
            		ctx.rotate(rad);
			if(type == "syn") {
				ctx.fillStyle = "#BBC9D9";
				ctx.moveTo(-20, 0); 		// upper-right (if dest is to right of src)
				ctx.lineTo(-20-11*w,-4*w);	// upper-left  (negative y is up, negative x is to the left)
				ctx.lineTo(-20-11*w, 4*w);	// lower-left
				ctx.lineTo(-20, 0);		// lower-right
			} else if (type == "gap") {
				ctx.fillStyle = "#FFBF00";
				ctx.moveTo(-20,-8*w);		// upper-right (if dest is to right of src)
				ctx.lineTo(-20-4*w,-8*w);	// upper-left  (negative y is up, negative x is to the left)
				ctx.lineTo(-20-4*w, 8*w);	// lower-left
				ctx.lineTo(-20, 8*w);		// lower-right
			}
			ctx.fill();
		}
        	ctx.restore();
	});
}

// flag used to indicate whether to load the multiple-cell or single-cell form of the JSON file
function init(flag) {
	//computes page layout (not a library function, used to adjust some css thingys on the page)
	Infovis.initLayout();
	//Stores canvas current lineWidth property value
	var lineW;
	var strokeS;
    	var fillS;

	Config.showOnlyCenterEdges = true;
	Config.hideEdgesWhenAnimating = false;
	Config.interpolation = 'linear';  // polar or linear
	Config.drawConcentricCircles = 7;
	Config.levelDistance = 240;  // distance between concentric circles
	Config.animationTime = 1000; // in ms
	Config.allowVariableNodeDiameters = true;  	// Uses first data set object value property (i.e node.data[0].value)
	Config.nodeRangeDiameters = {  	//Set node diameters range. For variable node weights.
		min: 10,
		max: 40
	};
	//The interval of the values of the first object of your dataSet array. A superset of the values can also be specified.
	Config.nodeRangeValues = {
		min: 1,
		max: 10
	};
	Config.fps = 30;

	var json = getJson(flag);

    	//Take width and height of the main container.
    	var infovis = $('infovis');
    	var w = infovis.offsetWidth, h = infovis.offsetHeight;
    	//Create a new canvas instance.
    	canvas = new Canvas('mycanvas', {
        	//Where to inject the canvas. Any div container will do.
        	'injectInto':'infovis',
        	//width and height for canvas. Default's to 200.
        	'width': w,
        	'height': h,
        	//Canvas styles
        	'styles': {
            		'fillStyle': '#009f3c', 	// node color - doesn't have any effect now that 2-colored nodes work
            		'strokeStyle': '#772277'	// edge color
	        },
        	//Add a background canvas for plotting
        	//concentric circles.
        	'backgroundCanvas': {
            		//Add Canvas styles for the bck canvas.
            		'styles': {
                		'fillStyle': '#444',
                		'strokeStyle': '#444'
            		},
            		//Add the initialization and plotting functions.
			'impl': {
                		'init': $empty,
                		'plot': function(canvas, ctx) {
                    			var times = Config.drawConcentricCircles, d = Config.levelDistance;
                    			var pi2 = Math.PI*2;
                    			for(var i=1; i<=times; i++) {
                        			ctx.beginPath();
                        			ctx.arc(0, 0, i * d, 0, pi2, true);
                        			ctx.stroke();
                        			ctx.closePath();
                    			}
                		}
            		}
        	}   
    	});
	
	/*
	$('mycanvas').setProperty('onmousedown', "canvasPressed(event);");
	$('mycanvas').setProperty('onmousemove', "canvasDragged(event);");
	$('mycanvas').setProperty('onmouseup', "canvasReleased(event);");
	*/
	
	rgraph= new RGraph(canvas,  {
	  	//Use onBeforePlotLine and onAfterPlotLine controller
	  	//methods to adjust your canvas lineWidth
	  	//parameter in order to plot weighted edges on 
	  	//your graph. You can also change the color of the lines.
	  	onBeforePlotLine: function(adj) {
	  		lineW = canvas.getCtx().lineWidth;
			strokeS = canvas.getCtx().strokeStyle;
			fillS = canvas.getCtx().fillStyle;
			
	  		canvas.getCtx().lineWidth = 2; // The weight specified in the JSON file is used to set the size of the edge decoration, not the LineWidth
			if(adj.data.type1 == "syn" && !adj.data.type2) {
				canvas.getCtx().strokeStyle = "#BBC9D9";
				canvas.getCtx().fillStyle = "#BBC9D9";
			} else if (adj.data.type1 == "gap" && !adj.data.type2) {
				canvas.getCtx().strokeStyle = "#FFBF00";
				canvas.getCtx().fillStyle = "#FFBF00";
			} else if (adj.data.type1 && adj.data.type2) {
				canvas.getCtx().strokeStyle = "#BBC9D9";
				canvas.getCtx().fillStyle = "#FFBF00";
			} else if (adj.data.type1 == "blank") {
				canvas.getCtx().strokeStyle = "#222222";	
				canvas.getCtx().fillStyle = "#222222";
			}
	  	},
	  	
	  	onAfterPlotLine: function(adj) {
            var context = canvas.getCtx();
			var node;
			var child;
			
			//canvas.getCtx().lineWidth = adj.data.weight
			if(adj.data.from1) { 
				node = GraphUtil.getNode(rgraph.graph, adj.data.from1);
				child = GraphUtil.getNode(rgraph.graph, adj.data.to1);
				drawEdgeDecoration(canvas, node, child, adj.data.type1, adj.data.weight11);
				if(adj.data.weight12 != 0) {
					node = GraphUtil.getNode(rgraph.graph, adj.data.to1);
					child = GraphUtil.getNode(rgraph.graph, adj.data.from1);
					drawEdgeDecoration(canvas, node, child, adj.data.type1, adj.data.weight12);
				}
			}
			if(adj.data.from2) {
				node = GraphUtil.getNode(rgraph.graph, adj.data.from2);
				child = GraphUtil.getNode(rgraph.graph, adj.data.to2);
				drawEdgeDecoration(canvas, node, child, adj.data.type2, adj.data.weight21);
				if(adj.data.weight22 != 0) {
					node = GraphUtil.getNode(rgraph.graph, adj.data.to2);
					child = GraphUtil.getNode(rgraph.graph, adj.data.from2);
					drawEdgeDecoration(canvas, node, child, adj.data.type2, adj.data.weight22);
				}
			}
			
	  		canvas.getCtx().lineWidth = lineW;
			canvas.getCtx().strokeStyle = strokeS;
			canvas.getCtx().fillStyle = fillS;
	  	},
		
		onBeforePlotNode: function(node) {
			if(node.data[1].key == 'type') {
				if(node.data[1].value.indexOf('se') != -1) canvas.addNodeColor('#E99AC2'); //ffff74
				if(node.data[1].value.indexOf('in') != -1) canvas.addNodeColor('#F45E3A'); //9a9aff
				if(node.data[1].value.indexOf('mo') != -1) canvas.addNodeColor('#9865CA'); //ff7b7b
				if(node.data[1].value.indexOf('mu') != -1) canvas.addNodeColor('#009f3c'); //green
				if(node.data[1].value.indexOf('bm') != -1) canvas.addNodeColor('#009f3c'); //green
				if(node.data[1].value.indexOf('gln') != -1) canvas.addNodeColor('#009f3c'); //green
				if(node.data[1].value.indexOf('mc') != -1) canvas.addNodeColor('#009f3c'); //green
			}
		},
		
		onAfterPlotNode: function(node) {
			canvas.clearNodeColors();
		},
	  	
	  	onBeforeCompute: function(node) {
	  		Log.write("centering " + node.name + "...");
			var preSynTitle = "";
			var preSynData = "";
			var postSynTitle = "";
			var postSynData = "";
			var gapJuncTitle = "";
			var gapJuncData = "";
			var preSynCnt = 0;
			var postSynCnt = 0;
			var gapJuncCnt = 0;

			GraphUtil.eachAdjacency(node, function(adj) {
				var child = adj.nodeTo;
				if (adj.data.from1 == node.name && adj.data.type1 == "syn") {
					preSynData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">" 
						+ child.name + "</a> (" + adj.data.weight11 + ")</li>";
					preSynCnt++;
				} else if (adj.data.weight12 && adj.data.to1 == node.name && adj.data.type1 == "syn") {
					preSynData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">" 
						+ child.name + "</a> (" + adj.data.weight12 + ")</li>";
					preSynCnt++;				
				} 
				if (adj.data.from2 == node.name && adj.data.type2 == "syn") {
					preSynData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">" 
						+ child.name + "</a> (" + adj.data.weight21 + ")</li>";
					preSynCnt++;
				} else if (adj.data.weight22 && adj.data.to2 == node.name && adj.data.type2 == "syn") {
					preSynData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">" 
						+ child.name + "</a> (" + adj.data.weight22 + ")</li>";
					preSynCnt++;
				}
				
				if (adj.data.to1 == node.name && adj.data.type1 == "syn") {
					postSynData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">"
						+ child.name + "</a> (" + adj.data.weight11 + ")</li>";
					postSynCnt++;				
				} else if (adj.data.weight12 && adj.data.from1 == node.name && adj.data.type1 == "syn") {
					postSynData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">"
						+ child.name + "</a> (" + adj.data.weight12 + ")</li>";
					postSynCnt++;
				} 
				if (adj.data.to2 == node.name && adj.data.type2 == "syn") {
					postSynData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">"
						+ child.name + "</a> (" + adj.data.weight21 + ")</li>";
					postSynCnt++;				
				} else if (adj.data.weight22 && adj.data.from2 == node.name && adj.data.type2 == "syn") {
					postSynData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">"
						+ child.name + "</a> (" + adj.data.weight22 + ")</li>";
					postSynCnt++;
				}
				
				if (adj.data.from1 == node.name && adj.data.type1 == "gap") {
					gapJuncData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">"
						+ child.name + "</a> (" + adj.data.weight11 + ")</li>";
					gapJuncCnt++;
				} else if (adj.data.weight12 && adj.data.to1 == node.name && adj.data.type1 == "gap") {
					gapJuncData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">"
						+ child.name + "</a> (" + adj.data.weight12 + ")</li>";
					gapJuncCnt++;
				} 
				if (adj.data.from2 == node.name && adj.data.type2 == "gap") {
					gapJuncData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">"
						+ child.name + "</a> (" + adj.data.weight21 + ")</li>";
					gapJuncCnt++;
				} else if (adj.data.weight22 && adj.data.to2 == node.name && adj.data.type2 == "gap") {
					gapJuncData += "<li> &nbsp; <a class=nav onclick=\"centerNode('" + child.id + "');\">"
						+ child.name + "</a> (" + adj.data.weight22 + ")</li>";
					gapJuncCnt++;
				}
			});
			preSynTitle = "<b>Pre-synaptic to " + preSynCnt + " cells</b> (# of synapses)";
			postSynTitle = "<br><b>Post-synaptic to " + postSynCnt + " cells</b>";
			gapJuncTitle = "<br><b>Gap-junctioned with " + gapJuncCnt + " cells</b>";
			
			$('content').innerHTML = preSynTitle + preSynData + postSynTitle + postSynData + gapJuncTitle + gapJuncData;

			fetchExtraData(node.name);
	  	},
	  	
		//Assign html to each label and some effects.	
		onCreateLabel: function(domElement, node) {
			var elem = $(domElement);
			elem.setOpacity(1).set('tween', { duration: 300 }).set('html', node.name).addEvents({
				'mouseenter': function() {
					elem.tween('opacity', 1);
				},
			
				'mouseleave': function() {
					elem.tween('opacity', 1);  // Used to be 0.6
				},
			
				'click': function() {
					centerNode(node.id);
				}
			});
		},
	
		onPlaceLabel: function(domElement, node) {
			domElement.innerHTML = '';
			domElement.innerHTML = node.name;
			var str = node.name + ' - ';
			if(node.data[1].key == 'type') {
				if(node.data[1].value.indexOf('se') != -1) str += 'sensory ';
				if(node.data[1].value.indexOf('in') != -1) str += 'inter ';
				if(node.data[1].value.indexOf('mo') != -1) str += 'motor';
				if(node.data[1].value.indexOf('mu') != -1) str += 'muscle';
				if(node.data[1].value.indexOf('bm') != -1) str += 'basement membrane';
				if(node.data[1].value.indexOf('gln') != -1) str += 'gland cell';
				if(node.data[1].value.indexOf('mc') != -1) str += 'marginal cell';
			}
			domElement.title = str;
			//var left = parseInt(domElement.style.left);
			//var top = parseInt(domElement.style.top);
			//domElement.style.width = '';
			//domElement.style.height = '';
			//var w = domElement.offsetWidth;
			//var h = domElement.offsetHeight;
			//domElement.style.left = (left) + 'px';
			//domElement.style.top = (top) + 'px';
		},
	
		onAfterCompute: function() {
			Log.write("");
		}
	  	
	});
	  
	//load weighted graph.
	rgraph.loadGraphFromJSON(json, startingNode);
	//compute positions and plot = refresh.
	rgraph.refresh();
	rgraph.controller.onBeforeCompute(GraphUtil.getNode(rgraph.graph, rgraph.root));
	rgraph.controller.onAfterCompute();
	
}

