var graphModuleObject = Class.create({
	initialize: function(el){
	 	this.properties = eHA.elementToObjectLiteral(el);
	 	this.el = $(el);
	 	if($$("div.graphs.assetid-"+this.properties.assetid)[0]){
	 		this.graphsDiv = $$("div.graphs.assetid-"+this.properties.assetid)[0];
	 		this.graphsDiv.update(eHA.graph.preloader);
	 		this.loadData(function(){
	 			this.createForm();
	 			this.build();
	 			this.selectPage(1);
	 		}.bind(this),{graphs:'true'});
	 	}else{
	 		eHA.log.create("no graphs for this module");
	 	}
	},
 	loadData: function(callback,packedargs,waitForAJAX){
		if(typeof this.ajaxRequest!=="undefined" && this.isLoading){
			this.ajaxRequest.abort();
			eHA.log.create("aborting previous ajax request",2);
		}
		if(typeof waitForAJAX==="undefined"){
			var waitForAJAX = false;
		}
 		var parameters = {
 			childpagename: eHA.Site+"/eHA_Module_C/"+eHA.Site+"/Graph/json",
 			site: eHA.Site,
 			c: "eHA_Module_C",
 			cid: this.properties.assetid,
 			pagename: eHA.Site+"_default_Wrapper"
 		};
 		var formPackedargs = {};
 		if(typeof this.form!=="undefined"){
 			formPackedargs = this.form.serialize(true);
 			eHA.log.create("packedargs from form = "+Object.toQueryString(formPackedargs),3);
 		}
 		if(typeof packedargs!=="undefined"){
 			Object.extend(formPackedargs,packedargs);
 			parameters.packedargs = Object.toQueryString(formPackedargs);
 		}
 		var localObj = this;
 		var URL = "/cs/Satellite";
 		this.isLoading = true;
		this.ajaxRequest = new Ajax.Request(URL,
			{
				method:'get',
				parameters: parameters,
				onCreate: function(){
					if(waitForAJAX){
						// show loading graphic because there will now be a delay
						localObj.graphsDiv.down("div.pageContainer").update(eHA.graph.preloader);
					}
					eHA.log.create(parameters.cid+": AJAX request for JSON created", 3);
				},
				onSuccess: function(transport){
					eHA.log.create(parameters.cid+": AJAX request for JSON succeeded", 3);
				},
				onComplete: function(transport){
					this.isLoading = false;
					// add transport.responseText to this.properties
					eHA.log.create(parameters.cid+": AJAX request for JSON completed", 3);
					if(transport.responseText){
						eHA.log.create(parameters.cid+": attempting to evaluate JSON and add to graphModuleObject", 3);
						try{
							var metaData = transport.responseText.evalJSON(true);
							Object.extend(localObj.properties,metaData.configuration);
							localObj.properties.complete = true;
							if(typeof metaData.graphs!=="undefined"){
								if(typeof localObj.data==="undefined"){
									localObj.data = {};
								}
								Object.extend(localObj.data,metaData.graphs);
							}
						}catch(err){
							eHA.log.create(parameters.cid+":"+err.name+" - "+err.message, 1);
						}
					}else{
						eHA.log.create(parameters.cid+": problem with transport.responseText onComplete", 1);
					}
					if(typeof callback!=="undefined" && callback){
						callback();
					}
				}.bind(this),
				onFailure: function(){
					eHA.log.create(parameters.cid+": AJAX request for JSON resulted in failure", 1);
				}
			});
 	},
 	/**
	 * calculates page data, creates page container, selects first page
	 * @function
	 */
	build: function(){
		try{
			// clear old pages & navigation
 			if(this.graphsDiv.select("div.pageMeta")[0]){
 				this.graphsDiv.select("div.pageMeta").invoke("remove");
 			}
			if(this.graphsDiv.down("div.pageContainer")){
				this.graphsDiv.down("div.pageContainer").remove();
			}
			if(this.graphsDiv.down("div.pagination")){
				this.graphsDiv.down("div.pagination").remove();
			}
			if(this.graphsDiv.down("img.preloader")){
				this.graphsDiv.down("img.preloader").remove();
			}
			
			var itemLimit = this.properties.totalItems;
			var pageLimit = 1;
			
			if(typeof this.properties.itemsPerPage!=="undefined"){
				itemLimit = this.properties.itemsPerPage;
				pageLimit = Math.ceil(this.properties.totalItems/this.properties.itemsPerPage);
			}
			
			this.graphsDiv.insert({bottom:new Element("div",{className:"pageMeta"}).update("<p><strong>"+this.properties.totalItems+"</strong> Quality Graphs found</p>")});
			this.graphsDiv.insert({bottom:new Element("div",{className:"pageContainer"})});
			
			this.properties.numberOfPages = pageLimit;
			this.currentPageNumber = 0; // to ensure that jumps from page 1 to 1 always work on build
//			this.selectPage(1);
			
		}catch(err){
			eHA.log.create("problem building pages for graphs module ("+this.properties.assetid+"), "+err.message,1);
		}
	},
 	getData: function(startItem,endItem,pageNumber){
 		var dataOK = true;
 		var immediatePageOK = true;
 		var checkStartItem = startItem;
 		var checkEndItem = endItem;
		if(this.properties.itemsPerPage>0){
		  // expand returned results to 3 pages if possible (previous page, current page, next page)
			if((checkStartItem+2*this.properties.itemsPerPage)<this.properties.totalItems){
			  // set checkEndItem to 2 pages ahead (current page plus one)
				checkEndItem = (checkStartItem+2*this.properties.itemsPerPage);
			}else{
			  // set checkEndItem as far ahead as possible
			  checkEndItem = parseInt(this.properties.totalItems,10)+parseInt(1,10);
			}
			if(checkStartItem>this.properties.itemsPerPage){
			  // set checkStartItem to 1 page back
			  checkStartItem = checkStartItem - this.properties.itemsPerPage;
			}
		}
		eHA.log.create("checking items "+checkStartItem+" to "+checkEndItem,3);
 		for(var i=checkStartItem;i<checkEndItem;i++){
 			if(typeof this.data!=="undefined" && typeof this.data["item"+i]!=="undefined"){
 				// data is ok, don't affect boolean
 			}else{
 				if(i>=startItem && i<=endItem){
 					immediatePageOK = false;
 				}
 				dataOK=false;
 			}
 		}
 		
 		if(!immediatePageOK){
			eHA.log.create("need to delay page creation",2);
			this.loadData(function(){
				this.createPage(pageNumber,false);
			}.bind(this),{
				startItem:startItem,
				graphs:'true'
			},true);
 		}else{
 			eHA.log.create("no need to delay page creation",3);
 			if(!dataOK){
 				eHA.log.create("prefetching data for neighboring pages",3);
 				this.loadData(false,{
 					startItem:startItem,
 					graphs:'true'
 				});
 			}
 		}
 		

 		return immediatePageOK;
 	},
 	createPage: function(pageNumber,checkData){
		try{
	 		if(typeof checkData==="undefined"){
	 			var checkData = true;
	 		}
			if(this.graphsDiv.down("img.preloader")){
				this.graphsDiv.down("img.preloader").remove();
				eHA.log.create("removed loading graphic",3);
			}
			eHA.log.create("attempting to create page "+pageNumber+".  "+(checkData?"Will":"Will not")+" check data",3);
			var startItem=(pageNumber-1)*this.properties.itemsPerPage+1; //add one because index starts at 1
			var endItem = parseInt(this.properties.itemsPerPage,10)+parseInt(startItem,10)-1; 
			if(endItem>this.properties.totalItems){
				endItem = this.properties.totalItems;
			}
			
			if(this.properties.totalItems>=startItem){
				// create new pagination with selected page properly selected
				this.createPagination(pageNumber);
				
				// check to see if requesting more data from server is necessary
				var immediatePageOK = false;
				if(checkData){
					immediatePageOK = this.getData(startItem,endItem,pageNumber);
				}
				if(immediatePageOK || !checkData){
					eHA.log.create("proceeding with page creation",3);
					
					var thisUL = new Element("ul",{className:"page page"+pageNumber}).setOpacity(0);
					for(var i=startItem;i<(endItem+1) && typeof this.data["item"+i]!=="undefined";i++){
						var thisGraph = this.data["item"+i];
						var graphHTML  = eHA.graph.graphHTML(thisGraph);
						var thisLI = new Element("li",{className:"graph assetid-"+this.data["item"+i].assetid}).update(graphHTML);
						thisUL.insert({bottom:thisLI});
					}
					this.graphsDiv.down("div.pageContainer").insert({bottom:thisUL});
					
					// create graphs thumbnail to place in newly created UL-LI
					for(i=startItem;i<(endItem+1) && typeof this.data["item"+i]!=="undefined";i++){
						thisGraph = this.data["item"+i];
						
						if(typeof thisGraph.data!=="undefined"){
							var thumbnailLI = this.graphsDiv.down("li.assetid-"+thisGraph.assetid+" li.thumbnail");
							var thumbnailDimensions = thumbnailLI.getDimensions();
							var thumbnailHeight = Math.round(thumbnailDimensions.width*eHA.graph.thumbnailAspectRatio);
							var barchartDiv = new Element("div",{className:"barchart protochart"}).setStyle({width:thumbnailDimensions.width+"px",height:thumbnailHeight+"px"});
							var linechartDiv = new Element("div",{className:"linechart protochart"}).setStyle({width:thumbnailDimensions.width+"px",height:thumbnailHeight+"px"});
							thumbnailLI.update().insert({bottom:barchartDiv}).insert({bottom:linechartDiv});
							
							var barChartData = new Array();
							var lineChartData = new Array();
							var numericalData = Object.clone(thisGraph.data);
							if(typeof numericalData.yAxisLabels!=="undefined"){
								delete numericalData.yAxisLabels;
							}
							var dataKeys = Object.keys(numericalData);
							for(var j=0;j<dataKeys.length;j++){
								barChartData.push({data: [[j,thisGraph.data[dataKeys[j]].last()]], label: eHA.graph.labels[dataKeys[j]]});
								lineChartData.push({data: eHA.graph.addIndices(thisGraph.data[dataKeys[j]]), label: eHA.graph.labels[dataKeys[j]]});
							}
							new Proto.Chart(barchartDiv,barChartData,{
								bars: {show: true, barWidth: 1 },
								colors: eHA.graph.colorArray,
								yaxis: { min: 0, max: 105, tickSize: 10, tickFormatter:function(){ return ""; }},
								xaxis: { tickSize: 0.5, min: -3, max: 6, tickFormatter:function(){return "";}},
								grid: {labelMargin:0, tickColor: "#f7f7f7", backgroundColor:"#ffffff" }
							});
							
							new Proto.Chart(linechartDiv,lineChartData,{
								lines: {show: true},
								colors: eHA.graph.colorArray,
								yaxis: { min: 0, max: 105, tickSize: 10, tickFormatter:function(){ return ""; }},
								xaxis: { min: -1, max: thisGraph.data.yAxisLabels.length, tickFormatter:function(){return "";}},
								grid: {labelMargin:0, tickColor: "#f7f7f7", backgroundColor:"#ffffff" }
							});
						}
					}
					thisUL.appear({duration:eHA.graph.duration,afterSetup:function(){
						this.adjustPageContainer();
					}.bind(this)});
				}
				
			}else{
				eHA.log.create("requested page, "+pageNumber+", for graph module ("+this.properties.assetid+") is out of range!  Proceeding to page 1 instead",2);
				this.selectPage(1);
			}
			
		}catch(err){
			eHA.log.create("problem creating page for graphs module ("+this.properties.assetid+"), "+err.message,1);
		}
	},
	adjustPageContainer: function(){
		eHA.log.create("adjusting page container",3);
		var pageDimensions = this.graphsDiv.down("div.pageContainer ul.page").getDimensions();
		new Effect.Morph(this.graphsDiv.down("div.pageContainer"),{
			style:{
				height:pageDimensions.height+"px"
			},
			duration: 0.1
		});
	},
 	/**
	 * creates pagination for the graph pages.  visible page numbers roam for simplicity, always showing 3 pages max, prev & next, first & last
	 * @function
	 * @parameter {int} selectedPage
	 * @example
	 * output:
	 * "|< < 1 2 3 > >|"
	 * "|< < 2 3 4 > >|"
	 * "|< < 9 10 12 > >|"
	 */
	createPagination: function(selectedPage){
		 eHA.log.create("creating pagination",3);
		try{
			if(typeof selectedPage==="undefined"){
				selectedPage = 1;
			}
			var startPage = Math.round(selectedPage - ((eHA.graph.maxPagesToShow-1)/2));
			if(startPage<1){
				startPage = 1;
			}
			// clear old pagination
			if(this.graphsDiv.down("div.pagination")){
				this.graphsDiv.down("div.pagination").remove();
			}
			
			var paginationDiv = new Element("div",{className:"pagination"});
			var paginationUL = new Element("ul");
			
			var firstLink = new Element("a",{href:""}).update("First").observe("click",function(event){
				event.stop();
				this.selectPage(1);
			}.bind(this));
			var firstLI = new Element("li",{className:"first"}).update(firstLink);
			paginationUL.insert({bottom:firstLI});
			
			var prevLink = new Element("a",{href:""}).update("Previous").observe("click",function(event){
				event.stop();
				if(this.graphsDiv.down("div.pagination li.sel a")){
					var selectedPage = this.graphsDiv.down("div.pagination li.sel a").innerHTML;
					if(selectedPage>1){
						this.selectPage(selectedPage - 1);
					}
				}
			}.bind(this));
			var prevLI = new Element("li",{className:"previous"}).update(prevLink);
			paginationUL.insert({bottom:prevLI});
			
			for(var i=startPage;i<=this.properties.numberOfPages && i<(parseInt(startPage,10)+parseInt(eHA.graph.maxPagesToShow,10));i++){
				var pageLink = new Element("a",{href:""}).update(i).observe("click",function(event){
					event.stop();
					this.selectPage(event.element().innerHTML);
				}.bind(this));
				var pageLIclass = "pageButton"+i;
				if(typeof selectedPage!=="undefined" && i===parseInt(selectedPage,10)){
					pageLIclass += " sel";
				}
				var pageLI = new Element("li",{className:pageLIclass}).update(pageLink);
				paginationUL.insert({bottom:pageLI});
			}
			
			var nextLink = new Element("a",{href:""}).update("Next").observe("click",function(event){
				event.stop();
				if(this.graphsDiv.down("div.pagination li.sel a")){
					var selectedPage = this.graphsDiv.down("div.pagination li.sel a").innerHTML;
					if(selectedPage<this.properties.numberOfPages){
						this.selectPage(parseInt(selectedPage,10) + 1);
					}
				}
			}.bind(this));
			var nextLI = new Element("li",{className:"next"}).update(nextLink);
			paginationUL.insert({bottom:nextLI});
			
			var lastLink = new Element("a",{href:""}).update("Last").observe("click",function(event){
				event.stop();
				this.selectPage(this.properties.numberOfPages);
			}.bind(this));
			var lastLI = new Element("li",{className:"last"}).update(lastLink);
			paginationUL.insert({bottom:lastLI});
			
			paginationDiv.update(paginationUL);
			this.graphsDiv.insert({bottom:paginationDiv});
		}catch(err){
			eHA.log.create("problem creating pagination for graphs module ("+this.properties.assetid+"), "+err.message,1);
		}
	},
 	readQueryString:function(queryObject){
 		var oldFormOptions={};
 		if(typeof this.oldFormOptions!=="undefined"){
 			oldFormOptions = this.oldFormOptions;
 		}
 		var pageNumber = queryObject.page;
 		delete queryObject.page;
 		this.oldFormOptions = queryObject;
 		
 		// if query string (without page number) is different, must execute search and change page
 		// later by using a callback
 		if(Object.toQueryString(oldFormOptions)!==Object.toQueryString(queryObject)){
 			this.executeForm(queryObject,function(){
 				this.changePage(pageNumber);
 				this.populateForm();
 			}.bind(this));
 		}else{
 			// otherwise, just change page number
 			this.changePage(pageNumber);
 		}
 		
 		// if there is no form and no pagination, remove hash
 		if(this.noHash){
 			SWFAddress.setValue("");
 		}

 	},
 	selectPage: function(pageNumber){
 		
 		if(typeof this.properties.showPagination!=="undefined" && 
 				(
 					(!this.properties.showPagination || this.properties.showPagination==="false") && 
 					(typeof this.form!=="undefined")
 				)
 			)
 		{
 			this.noHash = true;
 		}else{
 			this.noHash = false;
 		}
 		
 		// get queryString from forms, add/change page number
 		var formOptions = this.form.serialize(true);
 		Object.extend(formOptions,{page:pageNumber,graphs:'true'});
 		if(this.executions===1){ // selectPage is called once onload, so checking for 1 instead of 
 			// this is the first time the form is being executed, setValue of hash to the default
 			// form options.
 			SWFAddress.setValue("/"+this.properties.assetid+"/?"+Object.toQueryString(this.defaultFormOptions));
 		}
 		this.executions++;
 		SWFAddress.setValue("/"+this.properties.assetid+"/?"+Object.toQueryString(formOptions));
 	},
	changePage: function(pageNumber){
		try{
			if(typeof this.currentPageNumber!=="undefined" && this.currentPageNumber===pageNumber){
				eHA.log.create("requested page, "+pageNumber+", is already showing",3);
			}else{
				this.currentPageNumber = pageNumber;
				if(this.graphsDiv.select("ul.page")[0]){
					this.graphsDiv.select("ul.page").invoke("remove");
				}
				this.createPage(pageNumber);
			}
			
			// create new pagination with selected page properly selected
			//this.createPagination(pageNumber);
		}catch(err){
			eHA.log.create("problem selecting page for graphs module ("+this.properties.assetid+"), "+err.message,1);
		}
	},
 	executeForm: function(queryObject,callback){
 		eHA.log.create("executing graph module search form",3);
		if(typeof this.data!=="undefined"){
			delete this.data;
			eHA.log.create("clearing old graph module data",3);
		}
		
		this.loadData(function(){
			this.build();
			if(typeof callback!=="undefined"){
				callback();
			}
		}.bind(this), queryObject,true);
 	},
 	populateForm: function(){
 		for(option in this.oldFormOptions){
 			if(typeof this.form[option]!=="undefined"){
 				this.form[option].setValue(this.oldFormOptions[option]);
 			}
 		}
 	},
	createForm: function(){
		try{
			this.form = new Element("form",{method:"",action:"",name:"assetid-"+this.properties.assetid,id:"assetid-"+this.properties.assetid});
			
			var formContents = "";
			
			if(this.properties.showCategoryDropdown && this.properties.showCategoryDropdown!=="false"){
				formContents += "<div class='categoryDropdown'>";
				formContents += "<label for='categoryDropdown-"+this.properties.assetid+"'>Category:</label>";
				formContents += "<select id='categoryDropdown-"+this.properties.assetid+"' name='category'>";
				formContents += "<option value='null'>All</option>";
				for(var i=0;i<this.properties.category.length;i++){
					formContents += "<option value='"+this.properties.category[i].id+"'>"+this.properties.category[i].name+"</option>";
				}
				formContents += "</select>";
				formContents += "</div>";
			}
			if(this.properties.showTitleSearch && this.properties.showTitleSearch!=="false"){
				formContents += "<div class='titleSearch'>";
				formContents += "<label for='titleSearch-"+this.properties.assetid+"'>Title:</label><input type='text' id='titleSearch-"+this.properties.assetid+"' name='title' />";
				formContents += "</div>";
			}
			if(this.properties.showKeywordSearch && this.properties.showKeywordSearch!=="false"){
				formContents += "<div class='keywordSearch'>";
				formContents += "<label for='keywordSearch-"+this.properties.assetid+"'>Keywords:</label><input type='text' id='keywordSearch-"+this.properties.assetid+"' name='keyword' />";
				formContents += "</div>";
			}
			if(this.properties.showSortOrder && this.properties.showSortOrder!=="false"){
				formContents += "<div class='sortOrder'>";
				formContents += "<label for='sortOrder-"+this.properties.assetid+"'>Sort Order:</label>";
				formContents += "<select id='sortOrder-"+this.properties.assetid+"' name='sortOrder'>";
				formContents += "<option value='graph_title.ascending'>Alphabetical</option>";
				formContents += "<option value='graph_title.descending'>Reverse Alphabetical</option>";
				formContents += "</select>";
				formContents += "</div>";
			}
			
			if(formContents.length>0){
				formContents += "<div class='submit'>";
				formContents += "<input type='submit' class='submit' name='submit' id='submit-"+this.properties.assetid+"' value='Submit' />";
				formContents += "<input type='reset' class='reset' name='reset' id='reset-"+this.properties.assetid+"' value='Reset' />";
				formContents += "</div>";
				
				this.form.update(formContents);
				
				$$("div.graphModule.assetid-"+this.properties.assetid+" h3")[0].insert({after:this.form});
				
 		 		this.defaultFormOptions = this.form.serialize(true);
 				this.defaultFormOptions.page = 1;
 				this.defaultFormOptions.graphs = 'true';
 				this.executions = 0;


 				this.form.observe("submit",function(event){
 					event.stop();
 					eHA.log.create(this.properties.assetid+": form submitted",3);
 					this.selectPage(1);
 				}.bind(this));
				
			}
			
		}catch(err){
			eHA.log.create("problem creating graphs module form, "+this.properties.assetid+".  "+err.message,1);
		}
	}
});



var graphObject = Class.create({
	initialize: function(assetid){
		try{
			this.properties = {};
			this.properties.assetid = assetid;
			if($$("div.protochart-wrapper.snapshotChart")[0]){
				this.snapshotChartWrapper = $$("div.protochart-wrapper.snapshotChart")[0];
				this.snapshotChartWrapper.insert({bottom:eHA.graph.preloader.clone(true)});
			}
			if($$("div.protochart-wrapper.fullChart")[0]){
				this.fullChartWrapper = $$("div.protochart-wrapper.fullChart")[0];
				this.fullChartWrapper.insert({bottom:eHA.graph.preloader.clone(true)});
			}
			
			this.loadData(function(){
				this.readData();
				this.createSnapshotGraph();
				this.createFullGraph();
			}.bind(this));
		}catch(err){
			eHA.log.create("problem initializing graphObject (assetid="+this.properties.assetid+") - "+err.message,1);
		}
	},
	readData: function(){
		this.snapshotChartData = new Array();
		this.fullChartData = new Array();
		var numericalData = Object.clone(this.data);
		if(typeof numericalData.yAxisLabels!=="undefined"){
			delete numericalData.yAxisLabels;
		}
		var dataKeys = Object.keys(numericalData);
		for(var j=0;j<dataKeys.length;j++){
			this.snapshotChartData.push({data: [[j,this.data[dataKeys[j]].last()]], label: eHA.graph.labels[dataKeys[j]]});
			this.fullChartData.push({data: eHA.graph.addIndices(this.data[dataKeys[j]]), label: eHA.graph.labels[dataKeys[j]]});
		}
	},
	createSnapshotGraph: function(){
		var snapshotChart = new Element('div',{className:"protochart"}).setOpacity(0);
		var snapshotYAxisLabel = new Element('h6',{className:"yAxisLabel"}).update("%");
		var snapshotXAxisLabel = new Element('h6',{className:"xAxisLabel"}).update("Most Recent Available Data");
		
		this.snapshotChartWrapper.down("img.preloader").remove();
		this.snapshotChartWrapper.insert({bottom:snapshotYAxisLabel}).insert({bottom:snapshotChart}).insert({bottom:snapshotXAxisLabel});
		
		new Proto.Chart(snapshotChart,this.snapshotChartData,{
				bars: {show: true, barWidth: 1 },
				colors: eHA.graph.colorArray,
				yaxis: { min: 0, max: 105, tickSize: 10, tickFormatter: function(number){ return (number%20===0)?number:""; }},
				xaxis: { tickSize: 0.5, min: -3, max: 6, tickFormatter:function(){return "";}},
				legend:{show:true},
				grid: {labelMargin:10, tickColor: "#f7f7f7", backgroundColor:"#ffffff"}
			});
		var fadeHandler1;
		var fadeHandler2;
		var appearHandler1;
		var appearHandler2;
		var thisLegend = $(snapshotChart).up().down("div.ProtoChart-legend");
		var thisLegendBG = $(snapshotChart).up().down("div.ProtoChart-legend-bg");
		$(snapshotChart).observe("mouseover",function(event){
			if(typeof appearHandler1!=="undefined" && typeof appearHandler1.cancel!=="undefined"){
				appearHandler1.cancel();
			}
			if(typeof appearHandler2!=="undefined" && typeof appearHandler2.cancel!=="undefined"){
				appearHandler2.cancel();
			}
			fadeHandler1 = new Effect.Fade(thisLegend,{duration:eHA.graph.duration});
			fadeHandler2 = new Effect.Fade(thisLegendBG,{duration:eHA.graph.duration});
		}).observe("mouseout",function(event){
			if(typeof fadeHandler1!=="undefined" && typeof fadeHandler1.cancel!=="undefined"){
				fadeHandler1.cancel();
			}
			if(typeof fadeHandler2!=="undefined" && typeof fadeHandler2.cancel!=="undefined"){
				fadeHandler2.cancel();
			}
			appearHandler1 = new Effect.Appear(thisLegend,{duration:eHA.graph.duration});
			appearHandler2 = new Effect.Appear(thisLegendBG,{duration:eHA.graph.duration});
		});
		snapshotChart.appear({duration:eHA.graph.duration});
	},
	createFullGraph: function(){
		try{
			var fullChart = new Element('div',{className:"protochart"}).setOpacity(0);
			var fullYAxisLabel = new Element('h6',{className:"yAxisLabel"}).update("%");
			var fullXAxisLabel = new Element('h6',{className:"xAxisLabel"}).update("Quarterly Performance");
			
			this.fullChartWrapper.down("img.preloader").remove();
			this.fullChartWrapper.insert({bottom:fullYAxisLabel}).insert({bottom:fullChart}).insert({bottom:fullXAxisLabel});
			
			new Proto.Chart(fullChart,this.fullChartData,{
				lines: {show:true},
				points: {show:true},
				colors: eHA.graph.colorArray,
				yaxis: { min: 0, max: 105, tickSize: 10, tickFormatter: function(number){ return (number%20===0)?number:""; }},
				xaxis: { ticks:eHA.graph.addIndices(this.data.yAxisLabels), min: -1, max: this.data.yAxisLabels.length},
				legend:{show:true},
				grid: {labelMargin:10, tickColor: "#f7f7f7", backgroundColor:"#ffffff"},
				mouse: {track:true,fixedPosition:false,trackFormatter:eHA.graph.trackFormatter}
			});
			var fadeHandler1;
			var fadeHandler2;
			var fadeHandler3;
			var appearHandler1;
			var appearHandler2;
			var appearHandler3;
			var thisLegend = $(fullChart).up().down("div.ProtoChart-legend");
			var thisLegendBG = $(fullChart).up().down("div.ProtoChart-legend-bg");
			$(fullChart).observe("mouseover",function(event){
				if(typeof appearHandler1!=="undefined" && typeof appearHandler1.cancel!=="undefined"){
					appearHandler1.cancel();
				}
				if(typeof appearHandler2!=="undefined" && typeof appearHandler2.cancel!=="undefined"){
					appearHandler2.cancel();
				}
				if(typeof appearHandler3!=="undefined" && typeof appearHandler3.cancel!=="undefined"){
					appearHandler3.cancel();
				}
				fadeHandler1 = new Effect.Fade(thisLegend,{duration:eHA.graph.duration});
				fadeHandler2 = new Effect.Fade(thisLegendBG,{duration:eHA.graph.duration});
				if($(fullChart).up().down("div.mouseValHolder")){
					fadeHandler3 = new Effect.Appear($(fullChart).up().down("div.mouseValHolder"),{duration:eHA.graph.duration});
				}
			}).observe("mouseout",function(event){
				if(typeof fadeHandler1!=="undefined" && typeof fadeHandler1.cancel!=="undefined"){
					fadeHandler1.cancel();
				}
				if(typeof fadeHandler2!=="undefined" && typeof fadeHandler2.cancel!=="undefined"){
					fadeHandler2.cancel();
				}
				if(typeof fadeHandler3!=="undefined" && typeof fadeHandler3.cancel!=="undefined"){
					fadeHandler3.cancel();
				}
				appearHandler1 = new Effect.Appear(thisLegend,{duration:eHA.graph.duration});
				appearHandler2 = new Effect.Appear(thisLegendBG,{duration:eHA.graph.duration});
				if($(fullChart).up().down("div.mouseValHolder")){
					appearHandler3 = new Effect.Fade($(fullChart).up().down("div.mouseValHolder"),{duration:eHA.graph.duration});
				}
			});
			
			fullChart.appear({duration:eHA.graph.duration});
		}catch(err){
			eHA.log.create("problem creating full graph (assetid="+this.properties.assetid+") - "+err.message,1);
		}
	},
 	loadData: function(callback,packedargs){
 		var parameters = {
 			childpagename: eHA.Site+"/eHA_Graph_C/"+eHA.Site+"/Graph/json",
 			site: eHA.Site,
 			c: "eHA_Graph_C",
 			cid: this.properties.assetid,
 			pagename: eHA.Site+"_default_Wrapper"
 		};
 		if(typeof packedargs!=="undefined"){
 			parameters.packedargs = Object.toQueryString(packedargs);
 		}
 		var localObj = this;
 		var URL = "/cs/Satellite";
		new Ajax.Request(URL,
			{
				method:'get',
				parameters: parameters,
				onCreate: function(){
					eHA.log.create(parameters.cid+": AJAX request for JSON created", 3);
				},
				onSuccess: function(transport){
					eHA.log.create(parameters.cid+": AJAX request for JSON succeeded", 3);
				},
				onComplete: function(transport){
					// add transport.responseText to this object
					eHA.log.create(parameters.cid+": AJAX request for JSON completed", 3);
					if(transport.responseText){
						eHA.log.create(parameters.cid+": attempting to evaluate JSON and add to graphObject", 3);
						try{
							var metaData = transport.responseText.evalJSON(true);
							Object.extend(localObj,metaData);
							localObj.properties.complete = true;
							if(typeof metaData.graphs!=="undefined"){
								if(typeof localObj.data==="undefined"){
									localObj.data = {};
								}
								Object.extend(localObj.data,metaData.graphs);
							}
						}catch(err){
							eHA.log.create(parameters.cid+":"+err.name+" - "+err.message, 1);
						}
					}else{
						eHA.log.create(parameters.cid+": problem with transport.responseText onComplete", 1);
					}
					if(typeof callback!=="undefined" && callback){
						callback();
					}
				},
				onFailure: function(){
					eHA.log.create(parameters.cid+": AJAX request for JSON resulted in failure", 1);
				}
			});
 	}
});


/**
 * @namespace
 */
eHA.graph = {
	/**
	 * initiates graphModule and graphObject depending on what's available
	 * @function
	 */
	init: function(){
		this.preloader = new Element("img",{src:eHA.resourcepath+"images/wide-preloader.gif",alt:"please wait",className:"preloader"});
		if($$("div.graphModule")[0]){
			this.graphModuleObjects = {};
			$$("div.graphModule").each(function(element){
				var graphModuleID = eHA.elementToObjectLiteral(element).assetid;
				this.graphModuleObjects[graphModuleID] = new graphModuleObject(element);
			}.bind(this));
			
			// adding SWFaddress listeners
			
			 // EXTERNAL_CHANGE is used for back button
			 SWFAddress.addEventListener(SWFAddressEvent.EXTERNAL_CHANGE, function(event){
					eHA.log.create("SWFAddress event: "+Object.toJSON(event), 3);
					if(typeof event.pathNames!=="undefined"){
						if(typeof this.graphModuleObjects[event.pathNames[0]]!=="undefined" && typeof event.parameters!=="undefined"){
							this.graphModuleObjects[event.pathNames[0]].readQueryString(event.parameters);
						}
					}
				 }.bind(this));

			 SWFAddress.addEventListener(SWFAddressEvent.INTERNAL_CHANGE, function(event){
					eHA.log.create("SWFAddress event: "+Object.toJSON(event), 3);
					if(typeof event.pathNames!=="undefined"){
						if(typeof this.graphModuleObjects[event.pathNames[0]]!=="undefined" && typeof event.parameters!=="undefined"){
							this.graphModuleObjects[event.pathNames[0]].readQueryString(event.parameters);
						}
					}
				 }.bind(this));
			
		}else{
			if($$("div.protochart-wrapper")[0]){
				this.graphObjects = {};
				this.graphObjects[eHA.assetid] = new graphObject(eHA.assetid);
			}
		}
	},
	dateFormat: "yyyy-MM-dd HH:mm:ss",
	maxPagesToShow: 3,
	duration: 0.5,
	thumbnailAspectRatio: 0.75,
	colorArray: ['#dfdcd5','#fec141','#02254a'],
	labels: {
		national: "National Average",
		state: "State Average",
		region: "Region Average",
		hospital: "Hospital Average"
	},
	/**
	 * makes sure that rendermode is added to URL
	 * @function
	 * @returns theURL
	 */
	formatURL: function(obj){
		var theURL = obj.url;
		var pageQueryParams = window.location.href.toQueryParams();
		if(typeof pageQueryParams.rendermode!=="undefined"){
			if(theURL.indexOf("?")!==-1){
				var urlQueryParams = theURL.toQueryParams();
				Object.extend(urlQueryParams,{rendermode:pageQueryParams.rendermode});
				theURL = theURL.split("?")[0] +"?"+ Object.toQueryString(urlQueryParams);
			}
			theURL = theURL +"?"+ Object.toQueryString({rendermode:pageQueryParams.rendermode});
		}
		return theURL;
	},
	trackFormatter: function(val){
		return val.y+"%";
	},
	graphHTML: function(obj){
		var thisURL = this.formatURL(obj);
		var graphHTML  = "<ul>";
		graphHTML += "<li class='thumbnail'>Graph not available</li>";
		var graphTitle = "Quality Measure";
		if(typeof obj.title!=="undefined"){
			graphTitle = obj.title.strip();
		}
		graphHTML += "<li class='title'><a href='"+thisURL+"'>"+graphTitle+"</a></li>";
		graphHTML += (typeof obj.description!=="undefined")?"<li class='description'>"+obj.description.substring(0,200)+"</li>":"";
		graphHTML += "</ul>";
		return graphHTML;
	},
	/**
	 * takes an array and creates a new array with all of the same values, except that
	 * each item becomes a new array, length 2.  In the new array, the first item is the index,
	 * the second item is the value.
	 * <br />
	 * This is necessary in order to feed data to ProtoChart
	 * @function
	 */
	addIndices: function(arr1){
		var returnArray = new Array();
		for(var i=0;i<arr1.length;i++){
			returnArray.push([i,arr1[i]]);
		}
		return returnArray;
	}

};

