try { // cache bg imgs in IE

 document.execCommand("BackgroundImageCache", false, true);

} catch(err) {}

toolboxObj = function() {
	this.currentTool = "zoom";// Set default tool
	this.tool = [];
	this.enableInfoDiv = true;

}

toolboxObj.prototype.getNewData = function() {
	this.init();
	if (chart.exportData) {
		this.chartData = getParsedData();
		this.spacing = (d.yX / d.cDS0.length);
	}
}

toolboxObj.prototype.resize = function(){
	this.chartArea = document.getElementById("cht");
	this.origin = chart.getPos(this.chartArea);
	this.infoDiv = document.getElementById("infoDiv");
	with (this.infoDiv.style) { // dynamic position
		top = this.origin.y + 'px';
		left = this.origin.x + 'px';
	}
}

// init Toolbox
toolboxObj.prototype.init = function() {
	// Get Coords of Chart
	this.chartArea = document.getElementById("cht");
	this.origin = chart.getPos(this.chartArea);
	this.origin.x = 0;
	
	if(isIE){
		this.origin.x = 18;
	}
	
	this.regionX = {x0:1, x1:d.yX}; // d.yX is the width of the x axis, or x pos of y axis
	this.regionY = [{y0:0, y1:chart.upperHeight}];
	
	this.divZoom = document.getElementById("divZoom"); // vertical crosshair
	this.divZoomH = document.getElementById("divZoomH");// horizontal crosshair
	this.container = document.getElementById('chartContainer');
	
	// setup legend
	this.infoDiv = document.getElementById("infoDiv");
	this.infoDivToggle = document.getElementById('infoDivToggle');
	
	// Fix for Safari/Mozilla - Add events to Div instead of the actual chart area
	if (typeof(document.all) == "undefined") {
		this.divMoz = document.getElementById("mozWin");
		//with (this.divMoz.style) { // dynamic position
			//top = this.origin.y + 'px';
			//left = this.origin.x + 'px';
		//}
		addEvent(document.body, "mousemove", userAction); // ie needs this.
		addEvent(this.divMoz, "selectstart", cancelEvent);
	} else {
		// i.e works much better like this
		addEvent(document.body, "mousemove", userAction); // ie needs this.
		addEvent(this.chartArea, "selectstart", cancelEvent);
	}
	
	// Some reference vars for the Trendlines
	this.outLeft = function(x0){ return x0 <= this.regionX.x0 + this.origin.x; }
	this.outRight = function(x0){ return x0 >= this.regionX.x1 + this.origin.x; }
	this.outTop = function(y0){ return y0 <= this.regionY[0].y0 + this.origin.y}
	this.outBottom = function(y0){ return y0 >= this.regionY[0].y1 + this.origin.y;}	
	
	this.tool["zoom"] =	new zoomObj();
	this.tool["zoom"].init();
}

// Update Price Legend
toolboxObj.prototype.updateLegend = function(x0, x1, ixStart, ixStop) {
	try {
		var html = [];
		
		if(this.outLeft(mouse.x) || this.outRight(mouse.x - 3) || this.outTop(mouse.y) || this.outBottom(mouse.y) || this.enableInfoDiv != true){
			this.infoDiv.style.visibility = 'hidden';
			this.divZoom.style.visibility = 'hidden';
			return;
		} else {
			this.infoDiv.style.visibility = 'visible';
			this.divZoom.style.visibility = 'visible';
		}
		
		if (chart.symbol0 && chart.symbol0 != 'off' && chart.symbol1 && chart.symbol1 != 'off') {
			var df = ''+this.chartData[0][ixStart].df;
			if (df.indexOf('>0:') > -1) {
				df = df.replace('>0:', '>12:');
			}
			html.push('<div class="roll_date">'+df+'</div>');
			html.push('<div class="partyBlock" style="background:#2d84b3"></div> <span class="percent">'+this.chartData[0][ixStart].cF+'%</span><br />');
			html.push('<div class="partyBlock" style="background:#b01a1a"></div> <span class="percent">'+this.chartData[1][ixStart].cF+'%</span>');
		} else {
			if (chart.symbol0 == '14077617' || chart.symbol0 == '13471326') {
				var color = '2d84b3';
			} else if (chart.symbol0 == '14077598' || chart.symbol0 == '13471307') {
				var color = 'b01a1a';
			}
			
			html.push('<div class="roll_date">'+this.chartData[0][ixStart].df+'</div>');
			html.push('<div class="partyBlock" style="background:#'+color+'"></div> <span class="percent">'+parseInt(this.chartData[0][ixStart].cF*100)+'%</span>');
		}
		
		this.infoDiv.innerHTML = html.join('');
	} catch(e) {}
}

toolboxObj.prototype.ToggleInfoDiv = function(){
	if(this.enableInfoDiv || toolbox.chartData[0].length < 2){
		this.enableInfoDiv = false;
		this.divZoom.style.visibility = 'hidden';
		this.infoDiv.style.visibility = 'hidden';
		this.infoDivToggle.src = '../common/images/infoDivToggle.gif';
	} else {
		this.enableInfoDiv = true;
		this.divZoom.style.visibility = 'visible';
		this.infoDiv.style.visibility = 'visible';
		this.infoDivToggle.src = '../common/images/infoDivToggleOver.gif';
	}
}

toolboxObj.prototype.MouseOverInfoDivToggle = function(state){
	if (!state && !this.enableInfoDiv) {
		this.infoDivToggle.src = '../common/images/infoDivToggle.gif';
	} else {
		this.infoDivToggle.src = '../common/images/infoDivToggleOver.gif';
	}
}

// ----------------------------------------------------------
// Trendline Features
// ----------------------------------------------------------
// check boundry
toolboxObj.prototype.checkCoords = function(cX, cY) {
	return (cY > this.regionY[0].y0 &&
	cY < this.regionY[0].y1 &&
	cX > this.regionX.x0 &&
	cX < this.regionX.x1
	);
}

toolboxObj.prototype.checkRollCoords = function(cX, cY) {
	return (cY > this.regionY[0].y0 &&
	cX > this.regionX.x0);
}

toolboxObj.prototype.checkPositiveCoords = function() {
	for (var x=0; x < arguments.length; x++) {
		if (arguments[x] < 0){
			return false;
		}
	}
	return true;
}

function cancelEvent() {
	if (window.event.preventDefault){window.event.preventDefault()};
	if (window.event.stopPropagation){window.event.stopPropagation()}
	window.event.cancelBubble = true;
	window.event.returnValue = false;
	return false;
}

// quick util for finding array key
toolboxObj.prototype.getSnapIndex = function(xIn) {
	this.dataKey = Math.floor((xIn - this.spacing) / this.spacing);
	
	while (xIn > (d.xDS[this.dataKey]+(this.spacing / 2))) {
		this.dataKey++;
	}
	
	if (typeof(d.cDS0[this.dataKey]) == "undefined"){
		return ((xIn < 300 || d.cDS0.length == 0)?0:d.cDS0.length - 1)
	}
	
	return this.dataKey;
}

// ----------------------------------------------------------
// Zoom
// ----------------------------------------------------------
function zoomObj() {
	this.isCrosshair = false;
	this.isBeingDragged = false;
	this.divZoom = document.getElementById("divZoom"); // vertical crosshair
	this.divZoomH = document.getElementById("divZoomH");// horizontal crosshair
	
	var chH = chart.upperHeight;
	
	this.init = function() {
		this.indexStart = 0;
		this.indexStop = null;
		this.isBeingDragged = false;
		
		if (toolbox.currentTool == "normal") {
			this.divZoom.style.visibility = "hidden";
			this.divZoomH.style.visibility = "hidden";
		} else {
			this.divZoomH.style.visibility = "hidden";
			this.divZoom.style.top = toolbox.origin.y + "px";
			this.divZoom.style.width = "1px";
			this.divZoom.style.height = chH + "px";
			this.divZoom.style.background = "#999999";
			
			if (!toolbox.enableInfoDiv || toolbox.enableInfoDiv != true) {
				this.divZoom.style.visibility = "hidden";
				toolbox.infoDiv.style.visibility = "hidden";
			}
		}
	}
	
	var x0, x1;
	var mmXold = 0;
	
	this.roll = function(xIn){
		
		this.indexStop = toolbox.getSnapIndex(xIn);
		
		try {
			this.draw(toolbox.chartData[0][this.indexStop].x);
			toolbox.updateLegend(toolbox.chartData[0][this.indexStop].x , false, this.indexStop);

			mmXold = toolbox.chartData[0][this.indexStop].x;
		} catch(e) {}
	}

	this.draw = function(x0, x1){
		
		this.x2 = x0;
		
		if (chart.width - x0 > 138) {
			toolbox.infoDiv.style.left = (x0 + 28) + 'px';
		} else {
			toolbox.infoDiv.style.left = (x0 - 84) + 'px';
		}
		
		this.divZoom.style.left = x0 + 18 + "px";
	}
}

// UTIL Functions
// ----------------------------------------------------------
// EVENT HANDLERS
// ----------------------------------------------------------
function userAction(what, who){
	try { // needed for actions before toolbox is fully inited
		var yOffset = toolbox.origin.y;
		toolbox.tool["zoom"].roll(mouse.x);
	} catch(err) {  }
	
	return false;
}

function addEvent(obj, eventType, afunction, isCapture) {
	if (obj.addEventListener) { // W3C DOM
		obj.addEventListener(eventType, afunction, isCapture);
		return true;
	} else if (obj.attachEvent) { // is ie
		return obj.attachEvent("on"+eventType, afunction);
	} else {
		return false;
	}
}

function getParsedData() {
	var data = [];
	
	for (var s = 0; s < 2; s++) {
		
		data[s] = [];
		
		for (var i = 0; i < d['cDS'+s].length; i++) {
			data[s][i] = {
				c: d['cDS'+s][i],
				d: d.dDS[i],
				x: d.xDS[i],
				df: formatD((d.dDS[i] - 25569) * 86400000),
				cF: formatPrice(d['cDS'+s][i])
			};
		}
	}
	
	return data;
}

function formatD(value) {
	if (chart.duration > 29) {
		value = value + (chart.tzO * 60 * 60 * 1000 * 5);
	}
	var t =  new Date(value);
	var day = t.getDate();
	var mon = t.getMonth();
	var year = t.getFullYear();
	var formatDatemo = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
	if (year && parseInt(year) > 1950) {
		try{
			if (chart.duration < 10) {
				
				//var offset = chart.tzO;
				
				if (year == 2008 && mon < 10) {
					value = value + (1000 * 60 * 60);
					var t =  new Date(value);
				}
				
				var h = t.getUTCHours();
				var minute = t.getUTCMinutes() + '';
				var day = t.getUTCDate();
				var mon = t.getUTCMonth();
				
				if (minute > 56) {
					
					var offset = 60 - minute;
					
					t = new Date(value + (offset * 60 * 1000));
					
					var h = t.getUTCHours();
					var minute = t.getUTCMinutes() + '';
					var day = t.getUTCDate();
					var mon = t.getUTCMonth();
				}
				
				var utc = chart.tzO;
				var utcHour = h;
				
				if (utcHour > 11) {
					if (utcHour > 12) {
						utcHour = (utcHour - 12);
					}
					
					var ampm = 'PM';
				} else {
					var ampm = 'AM';
				}
				
				if (minute == '0' || minute == '01') {
					minute = '00';
				}
				
				if(minute.length < 2){
					minute = '0' + minute;
				}
				
				return formatDatemo[mon]+' '+day+', '+year+ '<br />' +utcHour+':'+minute+ ' '+ampm + ' ET';
			} else {
				return formatDatemo[mon]+' '+day+', '+year;
			}
		}catch(e){
			return formatDatemo[mon]+' '+day+', '+year;
		}
	} else {
		return '--';
	}
}

function formatPrice(value,sig) {
	value = value * 100;
	
	if(value > 98.5){
		return 100;
	}
	
	var sig = 0;

	if (value) {
		value = String(value.toFixed(sig));
		if (value.length < 7 && value.indexOf(".") > -1 || sig == 4) {
			return value;
		} else {
			x = value.split('.');
			x1 = x[0];
			x2 = x.length > 1 ? '.' + x[1] : '';

			if (x1.length > 3) {
				var rgx = /(\d+)(\d{3})/;
				while (rgx.test(x1)) {
					x1 = x1.replace(rgx, '$1' + ',' + '$2');
				}
			}
			
			value = x1 + x2;
			
			if (!value || value < 1 || value == 'NaN') {
				value = '0';
			}
			
			return value;
		}
	} else {
		return '0';
	}
}

// ------------------------------------------------------------
// mouse stuff
// ------------------------------------------------------------
var mouse = [];mouse.x = 0;mouse.y = 0;

var m_xOff, m_yOff, m_ev, m_isStandard;

// some browser stuff
var agent = navigator.appName.toLowerCase();

var isSafari = false;
var isNav6 = false;
var isIE = false;
if (agent.indexOf('safari') != -1) {
	isSafari = true;
} else if (agent.indexOf('gecko') > -1) {
	if (agent.indexOf('netscape') > -1) {
		isNav6 = true
	}
} else if (agent.indexOf('internet explorer') > -1) {
	isIE = true;
}



if (window.addEventListener) {
	window.addEventListener("mousemove",watchMouseCoords,true);
} else { // check safari
	document.attachEvent("onmousemove",watchMouseCoords);
}

function watchMouseCoords(e) {
	
	if (isSafari) {
		m_ev = event;
	} else {
		m_ev = e;
	}
	
	if (isNav6) { // need to catch the various implementations of scrollTop
		m_yOff = window.pageYOffset;
		m_xOff = window.pageXOffset;
	} else {
		isStandard = (document.compatMode && document.compatMode == "CSS1Compat") ? true : false;
		
		if (isStandard) {
			m_yOff = document.documentElement.scrollTop;
		} else {
			m_yOff = document.body.scrollTop;
		}
		if (isStandard) {
			m_xOff = document.documentElement.scrollLeft;
		} else {
			m_xOff = document.body.scrollLeft;
		}
		
		m_xOff = document.documentElement.scrollLeft;
		m_yOff = document.documentElement.scrollTop;
	}
	
	mouse.x = m_ev.clientX + m_xOff - 18;
	mouse.y = m_ev.clientY + m_yOff;
	
	if (mouse.callback) { mouse.callback() }
}

// callback function is executed onmousemove in mouse.js.
mouse.callback = function(){
	userAction("move", "callback");
};