/**
 * @author Ry Racherbaumer (rracherbaumer@vsapartners.com)
 * @version 1.0
 */
// create a div for the tooltip
var tooltipDiv = $('<div id="tooltip"/>')
	.append($('<div class="l"/>'))
	.append($('<div class="content"/>')
		.append($('<p/>')))
	.append($('<div class="r"/>'))
	.append($('<div class="b"/>')
		.append($('<div class="bl"/>'))
		.append($('<div class="bbl"/>'))
		.append($('<div class="bc"/>'))
		.append($('<div class="bbr"/>'))
		.append($('<div class="br"/>')));

var isIE6 = $.browser.msie && parseInt($.browser.version) === 6;
var $iframe;
if(isIE6) {
	$iframe = $('<iframe id="ie6-iframe-fix" src="" scrolling="no" frameborder="0" />');
}

$(document).ready(function() {
	$('body').append(tooltipDiv);
	//prepare iframe to prevent select boxes showing through
	if(isIE6) {
		$('body').append($iframe);
	}

});


(function($) {

 	$.fn.tooltip = function(options) {
		var opts = $.extend({}, $.fn.tooltip.defaults, options);
		tooltipDiv.width(opts.width);
		return this.each(function() {
			$(this).bind('mouseover',
				function(){
					var id = this.id;
					var h = id.indexOf('-');
					var row = id.substring(1,h);
					var col = id.substring(h+1);
					var colHead = $($('table.'+opts.tableClass+' thead tr td')[col-1]).text();
					//check for sup on header and remove
					if(colHead.indexOf('(') != -1) {
						sup = colHead.slice(colHead.indexOf('('), colHead.indexOf(')') + 1);
						colHead = colHead.replace(sup, '')
					}					
					var rowHead = $($('table.'+opts.tableClass+' tbody tr th')[row-1]).text();
					var cellVal = $($($('table.'+opts.tableClass+' tbody tr')[row-1]).children()[col]).text();					
					var _tableCaption = $('table.'+opts.tableClass+' caption');					
					var valPrepend = '';
					if(_tableCaption.hasClass('dollar')) {
						valPrepend = '$';
					} else if(_tableCaption.hasClass('approx')) {
						valPrepend = '&#126;';
					}
					var valAppend = '';
					if(_tableCaption.hasClass('million')) {
						valAppend = ' million';
					} else if(_tableCaption.hasClass('billion')) {
						valAppend = ' billion';
					} else if(_tableCaption.hasClass('employees')) {
						valAppend = ' employees';
					} else if(_tableCaption.hasClass('percent')) {
						valAppend = '%';
					}
					var sup = '';
					if (cellVal.indexOf('(') != -1) {
						sup = cellVal.slice(cellVal.indexOf('('), cellVal.indexOf(')') + 1);
						cellVal = cellVal.replace(sup, '')
					}

					//put together the content inside the tooltip
					var content = '';
					//special exception for Contributions as a Percent of GE Net Income
					if($('#percent-net-table').length !== 0) {
						//get other row heads
						var $rheads = $('#percent-net-table tbody th');
						var _r2head = $($rheads[1]).html();
						var _r3head = $($rheads[2]).html();
						//get other values
						var $rows = $('#percent-net-table tbody tr');
						var _r2val = $($rows[1]).children('td')[col-1].innerHTML;
						var _r3val = $($rows[2]).children('td')[col-1].innerHTML;

						content = colHead;// + '<span style="font-weight: normal;position: relative; top: -0.3em;color:' + opts.rowColors[row - 1] + '">' + sup + '</span>';
						content += '<span style="display:block;margin-top:5px;color:' + opts.rowColors[row - 1] + '">' + rowHead + ':</span>';
						content += cellVal;
							
						content += '<span style="display:block;margin-top:5px;color:' + opts.rowColors[row - 1] + '">' + _r2head + ':</span>';
						content += _r2val + valAppend;
						content += '<span style="display:block;margin-top:5px;color:' + opts.rowColors[row - 1] + '">' + _r3head + ':</span>';
						content += _r3val;
						content += '</span>';
					} else {
						content = colHead + '<br /><span style="color: ' + opts.rowColors[row - 1] + '">';
						content += '(' + rowHead + ')</span><br />' + valPrepend + cellVal + valAppend + '<span style="font-weight: normal;position: relative; top: -0.3em;color: '+ opts.rowColors[row - 1] +'">' + sup + '</span>';	
					}	
					$('.content p', tooltipDiv).css('color', opts.rowColors[row - 1]);
					$('.content p', tooltipDiv).html(content);
					$('.content', tooltipDiv).width(opts.width - 4);
					$('.r,.l', tooltipDiv).height($('.content', tooltipDiv).height());
					$('.b .bbl,.b .bbr', tooltipDiv).width((opts.width - 26) / 2);
					var imageOffset = $('.' + opts.imageClass).offset({
						border: true,
						padding: true
					});
					var areaCoords = $(this).attr('coords');
					var c1 = areaCoords.indexOf(',');
					var c2 = areaCoords.indexOf(',', c1 + 1);
					var ie6Adj = jQuery.browser.msie && jQuery.browser.version < 7.0 ? 14 : 0;
					var areaOffset = {
						left: parseInt(areaCoords.substring(0, c1)),
						top: (parseInt(areaCoords.substring(c1 + 1, c2)) + ie6Adj)
					};
					//insert iframe to prevent select boxes showing through
					if(isIE6) {
						$iframe.css({
							width: opts.width - 4
							,height: tooltipDiv.height() - 50
							,top: imageOffset.top + areaOffset.top - tooltipDiv.height() - 5
							,left: imageOffset.left + areaOffset.left - (tooltipDiv.width() / 2) + 4
							,visibility: 'visible'
						});

					}			
					tooltipDiv.css({
						top: imageOffset.top + areaOffset.top - tooltipDiv.height() - 5,
						left: imageOffset.left + areaOffset.left - (tooltipDiv.width() / 2) + 2,
						visibility: 'visible'
						,zIndex: 200
					});
				});
			$(this).bind('mouseout',
				function(){
					tooltipDiv.css('visibility','hidden');
					//iframe to prevent select boxes showing through
					if (isIE6) {
						$iframe.css('visibility', 'hidden');
					}
				});
		});
	};
	$.fn.tooltip.defaults = {
		// width of the tooltip - must be divisible by 2
		width: 110,
		tableClass:'metric-table',
		imageClass:'metric-image',
		rowColors: ['#711371','#3B73B9','#EE3324','#08A5E1','#76B900','#E4B366']
	};
})(jQuery);

/**
 * @author Ry Racherbaumer
 */
(function($) {
	var $this = [], targetEl = [], cloneEl = [], boxEl = [], that = [];
	var options = [], targetData = [], preload = [], shadowEl = [];
	var targetElStyle = [];
	var targetEventAction;
	var count = 0;
	function createBox(index) {
		if (options[index].cloneElement !== '') {
			if (options[index].cloneElement !== 'this' && ($(options[index].cloneElement, $this[index]).length === 0 || $(options[index].cloneElement).length === 0)) {
				if (console) console.log('BOXER: cloneElement does not exist!');
				return false;
			} else {
				if (options[index].cloneElement === 'this') {
					cloneEl[index] = $this[index].clone();
				} else if ($(options[index].cloneElement, $this[index]).length === 0) {
					cloneEl[index] = $(options[index].cloneElement).clone();
				} else {
					cloneEl[index] = $(options[index].cloneElement, $this[index]).clone();
				}
				if (options[index].cloneRemoveElements.length > 0) {
					$.each(options[index].cloneRemoveElements, function(i, value){
						$(value, cloneEl[index]).remove();
					});
				}
				boxEl[index] = cloneEl[index];
			}
		} else {
			boxEl[index] = $('<div/>');
		}
		if (options[index].copyElement) {
			if (options[index].copyElement.indexOf('attr-') === 0) {
				var attrName = options[index].copyElement.substring(5);
				var attrVal = targetEl[index].attr(attrName);
				if (options[index].copyElementAttributeReplace.length > 0) {
					attrVal = attrVal.replace('r','i');
				}
				if (attrName === 'id') {
					attrVal = '#'+attrVal;
				} else {
					attrVal = '.'+attrVal;
				}				
				if ($(attrVal).length > 0) {
					boxEl[index].append($(attrVal).clone());
				}
			} else if ($(options[index].copyElement).length > 0) {
				boxEl[index].append($(options[index].copyElement));
			}			
		}
	}
	function styleBox(index) {
		boxEl[index].css({position:'absolute','z-index':1002});
		if (options[index].boxStyle) boxEl[index].css(options[index].boxStyle);
		if (options[index].boxClass) boxEl[index].addClass(options[index].boxClass);
	}
	function removeBox(index) {
		if (boxEl[index]) {
			boxEl[index].remove();
			if (options[index].targetEvent === 'click') {
				targetEl[index].unbind('click', targetEventAction);
				targetEl[index].bind(options[index].targetEvent, {index: index}, targetEventAction);
			} else {
				targetEl[index].unbind('mouseenter', targetEventAction);
				targetEl[index].bind('mouseenter', {index: index}, targetEventAction);
				if (options[index].targetEvent === 'hover') targetEl[index].bind('mouseleave', {index: index}, removeBoxEvent);
			}
			boxEl[index] = null;
		}
	}
	function positionBox(index) {
		if (isNaN(parseInt(boxEl[index].css('top')))) boxEl[index].css('top', 0);
		if (isNaN(parseInt(boxEl[index].css('left')))) boxEl[index].css('left', 0);
		if (options[index].positionElement !== '' && ($(options[index].positionElement, $this[index]).length > 0 || $(options[index].positionElement).length > 0)) {
			var positionElement, positionOffset, addOffsetTop, addOffsetLeft;
			if ($(options[index].positionElement, $this[index]).length > 0) {
				positionElement = $(options[index].positionElement, $this[index]);
				positionOffset = positionElement.offset();
			} else {
				positionElement = $(options[index].positionElement);
				positionOffset = positionElement.offset();
			}
			if (options[index].positionAlign === 'top') {
				addOffsetTop = positionOffset.top;
				addOffsetLeft = positionOffset.left;
			} else if (options[index].positionAlign === 'bottom') {
				addOffsetTop = positionOffset.top + positionElement.height();
				addOffsetLeft = positionOffset.left;
			} else if (options[index].positionAlign === 'topright') {
				addOffsetTop = positionOffset.top;
				addOffsetLeft = positionOffset.left + positionElement.width();
			} else if (options[index].positionAlign === 'bottomright') {
				addOffsetTop = positionOffset.top + positionElement.height();
				addOffsetLeft = positionOffset.left + positionElement.width();
			}
			boxEl[index].css('top', parseInt(boxEl[index].css('top')) + addOffsetTop);
			boxEl[index].css('left', parseInt(boxEl[index].css('left')) + addOffsetLeft);			
		} else {
			var targetOffset = targetEl[index].offset();
			var addOffsetTop, addOffsetLeft;
			if (options[index].positionAlign === 'top') {
				addOffsetTop = targetOffset.top;
				addOffsetLeft = targetOffset.left;
			} else if (options[index].positionAlign === 'bottom') {
				addOffsetTop = targetOffset.top + targetEl[index].height();
				addOffsetLeft = targetOffset.left;
			} else if (options[index].positionAlign === 'topright') {
				addOffsetTop = targetOffset.top;
				addOffsetLeft = targetOffset.left + targetEl[index].width();
			} else if (options[index].positionAlign === 'bottomright') {
				addOffsetTop = targetOffset.top + targetEl[index].height();
				addOffsetLeft = targetOffset.left + targetEl[index].width();
			}
			boxEl[index].css('top', parseInt(boxEl[index].css('top')) + addOffsetTop);
			boxEl[index].css('left', parseInt(boxEl[index].css('left')) + addOffsetLeft);
		}
	}
	function createBoxShadow(index, animate, animateStyle) {
		shadowEl[index] = $('<div/>');
		shadowEl[index].css({
			position: 'absolute',
			backgroundColor: options[index].shadowColor,
			zIndex: 1001,
			width: boxEl[index].width(),
			height: boxEl[index].height(),
			top: (boxEl[index].offset().top + options[index].shadowOffset[1]),
			left: (boxEl[index].offset().left + options[index].shadowOffset[0])
		});		
		if (animate === true) {
			var shadowAnimation = {};
			for (p in animateStyle) {
				if (p === 'top') shadowAnimation.top = parseInt(animateStyle.top) + options[index].shadowOffset[1];
				else if (p === 'left') shadowAnimation.left = parseInt(animateStyle.left) + options[index].shadowOffset[0];
				else if (p === 'height') shadowAnimation.height = parseInt(animateStyle.height);
				else if (p === 'width') shadowAnimation.width = parseInt(animateStyle.width);
				else if (p === 'opacity' && parseFloat(animateStyle.opacity) > 0) {
					shadowEl[index].css('opacity', 0);
					shadowAnimation.opacity = options[index].shadowOpacity;
				}
			}
			shadowEl[index].appendTo($(document.body));
			shadowEl[index].animate(shadowAnimation, options[index].animationDelay);
		} else {
			shadowEl[index].css({
				opacity: options[index].shadowOpacity				
			});
			shadowEl[index].appendTo($(document.body));
		}
	}
	function removeBoxShadow(index, animate, animateStyle) {
		if (animate === true) {
			var shadowAnimation = {};
			for (p in animateStyle) {
				if (p === 'top') shadowAnimation.top = parseInt(animateStyle.top) + options[index].shadowOffset[1];
				else if (p === 'left') shadowAnimation.left = parseInt(animateStyle.left) + options[index].shadowOffset[0];
				else if (p === 'height') shadowAnimation.height = parseInt(animateStyle.height);
				else if (p === 'width') shadowAnimation.width = parseInt(animateStyle.width);
			}
			shadowAnimation.opacity = 0;
			shadowEl[index].animate(shadowAnimation, options[index].removeAnimationDelay, function(){
				shadowEl[index].remove();
			});
		} else {
			if (shadowEl[index]) shadowEl[index].stop().remove();
		}
	}
	function getElementPosition(el, context, fallback) {
		if (context !== undefined && $(el, context).length > 0) {
			return $(el, context).offset();
		} else if ($(el).length > 0 ){
			return $(el).offset();
		} else {
			if (fallback !== undefined)	return fallback.offset();
			else return {top:0,left:0};
		}
	}
	function loadBoxContent(index) {
		if (options[index].boxContent !== '') {
			boxEl[index].append(options[index].boxContent);
		} else if (options[index].boxContentDataURL !== '') {
			if (!preload[index]) {
				if (targetEl[index].attr('id')) {
					targetData[index] = $.extend({}, options[index].boxContentData, {
						id: targetEl[index].attr('id')
					});
				} else {
					targetData[index] = options[index].boxContentData;
				}
				$.get(options[index].boxContentDataURL, targetData[index], function(data, textStatus) {
					preload[index] = data;
					boxEl[index].append(preload[index]);
				});
			} else {
				boxEl[index].append(preload[index]);
			}
		}
	}
	function removeBoxEvent(event) {
		var index = event.data.index;
		var px = event.pageX;
		var py = event.pageY;		
		if (event.data.box) {
			var tx = targetEl[index].offset().left;
			var ty = targetEl[index].offset().top;
			var tw = targetEl[index].width();
			var th = targetEl[index].height();
			if ((px >= tx && px <= (tx + tw)) && (py >= ty && py <= (ty + th))) {
				boxEl[index].unbind('mouseleave', removeBoxEvent);
				targetEl[index].bind('mouseleave', {index:index}, removeBoxEvent);
				return;
			}
		} else {
			var bx = boxEl[index].offset().left;
			var by = boxEl[index].offset().top;
			var bw = boxEl[index].width();
			var bh = boxEl[index].height();
			if ((px >= bx && px <= (bx + bw)) && (py >= by && py <= (by + bh))) {
				targetEl[index].unbind('mouseenter', targetEventAction);
				targetEl[index].unbind('mouseleave', removeBoxEvent);
				boxEl[index].bind('mouseleave', {index:index,box:true}, removeBoxEvent);
				return;
			}
		}
		if (options[index].targetClass) targetEl[index].removeClass(options[index].targetClass);
		if (targetElStyle[index]) {
			if (options[index].targetStyleAnimate === true) {
				targetEl[index].stop();
				targetEl[index].animate(targetElStyle[index], options[index].targetStyleAnimationDelay);
			} else {
				targetEl[index].css(targetElStyle[index]);
			}
		}		
		if (options[index].removeAnimationStyle) {
			var removeAnimationStyle = {}, removeAnimationEndPosition;
			if (options[index].removeAnimationEndPositionElement !== '') removeAnimationEndPosition = getElementPosition(options[index].removeAnimationEndPositionElement, $this[index], boxEl[index]);
			else if (options[index].animationEndPositionElement !== '') removeAnimationEndPosition = getElementPosition(options[index].animationEndPositionElement, $this[index], boxEl[index]);
			else removeAnimationEndPosition = getElementPosition(boxEl[index]);
			if (!options[index].removeAnimationStyle.top || isNaN(parseInt(options[index].removeAnimationStyle.top)) || parseInt(options[index].removeAnimationStyle.top) === 0) {
				removeAnimationStyle = $.extend({}, options[index].removeAnimationStyle, {
					top: removeAnimationEndPosition.top
				});
			} else {
				removeAnimationStyle = $.extend({}, options[index].removeAnimationStyle, {
					top: (parseInt(options[index].removeAnimationStyle.top) + removeAnimationEndPosition.top)
				});
			}
			if (!options[index].removeAnimationStyle.left || isNaN(parseInt(options[index].removeAnimationStyle.left)) || parseInt(options[index].removeAnimationStyle.left) === 0) {
				removeAnimationStyle = $.extend({}, (removeAnimationStyle ? removeAnimationStyle : options[index].removeAnimationStyle), {
					left: removeAnimationEndPosition.left
				});
			} else {
				removeAnimationStyle = $.extend({}, (removeAnimationStyle ? removeAnimationStyle : options[index].removeAnimationStyle), {
					left: (parseInt(options[index].removeAnimationStyle.left) + removeAnimationEndPosition.left) + 'px'
				});
			}
			boxEl[index].animate(removeAnimationStyle, options[index].removeAnimationDelay, function(){
				removeBox(index);
			});
			if (shadowEl[index]) removeBoxShadow(index, true, removeAnimationStyle);
		} else {
			if (shadowEl[index]) removeBoxShadow(index, false);
			removeBox(index);
		}
	}
	function targetEventAction(event) {
		var index = event.data.index;
		if (boxEl[index]) {
			if (options[index].targetEvent === 'hover') {
				boxEl[index].stop().remove();
				boxEl[index] = null;
			} else return;
		}
		if (options[index].targetEvent === 'click') {
			targetEl[index].unbind('click', targetEventAction);
			targetEl[index].bind('click', function(event){event.preventDefault();})				
		}
		createBox(index);
		styleBox(index);
		positionBox(index);
		if (options[index].targetEvent === 'click' || options[index].targetEvent === 'hoverclick') boxEl[index].bind('click', {index:index}, removeBoxEvent(index));
		boxEl[index].appendTo($(document.body));
		if (options[index].targetClass) targetEl[index].addClass(options[index].targetClass);
		if (options[index].targetStyle) {
			if (!targetElStyle[index]) {
				targetElStyle[index] = {};
				for (p in options[index].targetStyle) {
					eval('targetElStyle[index].' + p + ' = targetEl[index].css("' + p + '")');
				}
			}
			if (options[index].targetStyleAnimate === true) {
				targetEl[index].stop();
				if (targetElStyle[index]) targetEl[index].css(targetElStyle[index]);
				targetEl[index].animate(options[index].targetStyle, options[index].targetStyleAnimationDelay);
			} else {
				targetEl[index].css(options[index].targetStyle);
			}				
		}
		if (options[index].animate === true) {
			var animationStyle = {}, animationEndPosition;
			if (options[index].animationEndPositionElement !== '') {
				animationEndPosition = getElementPosition(options[index].animationEndPositionElement, $this[index], targetEl[index]);
				if (!options[index].animationStyle.top || isNaN(parseInt(options[index].animationStyle.top)) || parseInt(options[index].animationStyle.top) === 0) {
					animationStyle = $.extend({}, options[index].animationStyle, {
						top: animationEndPosition.top + 'px'
					});
				} else {
					animationStyle = $.extend({}, options[index].animationStyle, {
						top: (parseInt(options[index].animationStyle.top) + animationEndPosition.top)
					});
				}
				if (!options[index].animationStyle.left || isNaN(parseInt(options[index].animationStyle.left)) || parseInt(options[index].animationStyle.left) === 0) {
					animationStyle = $.extend({}, (animationStyle ? animationStyle : options[index].animationStyle), {
						left: animationEndPosition.left + 'px'
					});
				} else {
					animationStyle = $.extend({}, (animationStyle ? animationStyle : options[index].animationStyle), {
						left: (parseInt(options[index].animationStyle.left) + animationEndPosition.left)
					});
				}
				boxEl[index].animate(animationStyle, options[index].animationDelay, function() {
					loadBoxContent(index);
				});
				if (options[index].shadow === true) createBoxShadow(index, true, animationStyle);
			} else {
				if (options[index].animationStyle.top && !isNaN(parseInt(options[index].animationStyle.top))) {
					animationStyle = $.extend({}, options[index].animationStyle, {
						top: (parseInt(options[index].animationStyle.top) + boxEl[index].offset().top)
					});
				} else {
					animationStyle = $.extend({}, options[index].animationStyle, {
						top: boxEl[index].offset().top
					});
				}
				if (options[index].animationStyle.left && !isNaN(parseInt(options[index].animationStyle.left))) {
					animationStyle = $.extend({}, (animationStyle ? animationStyle : options[index].animationStyle), {
						left: (parseInt(options[index].animationStyle.left) + boxEl[index].offset().left)
					});
				} else {
					animationStyle = $.extend({}, (animationStyle ? animationStyle : options[index].animationStyle), {
						left: boxEl[index].offset().left
					});
				}				
				boxEl[index].animate(animationStyle, options[index].animationDelay, function() {
					loadBoxContent(index);			
				});
				if (options[index].shadow === true) createBoxShadow(index, true, animationStyle);
			}
		} else {				
			if (options[index].shadow === true) createBoxShadow(index, false);
			loadBoxContent(index);
		}
		if (options[index].targetEvent === 'click') event.preventDefault();
	}
 	$.fn.boxer = function(option) {
		var opts = $.extend({}, $.fn.boxer.defaults, option);
		return this.each(function(index) {
			$this[count] = $(this);
			options[count] = opts;
			if (options[count].targetElement === '') {
				targetEl[count] = $(this);
			} else {
				targetEl[count] = $(options[count].targetElement, $this[count]);
			}
			if (targetEl[count].length === 0) {
				if (console) console.log('BOXER: You must specify a valid target element!');
			} else {
				if (options[count].targetEvent === 'click') {
					targetEl[count].bind(options[count].targetEvent, {index:count}, targetEventAction);
				} else if (options[count].targetEvent === 'hover' || options[count].targetEvent === 'hoverclick') {
					targetEl[count].bind('mouseenter', {index:count}, targetEventAction);
					if (options[count].targetEvent === 'hover') {
						targetEl[count].bind('mouseleave', {index:count}, removeBoxEvent);
					}
				}
				if (options[count].boxContentDataURL !== '') {
					if (targetEl[count].attr('id')) {
						targetData[count] = $.extend({}, options[count].boxContentData, {
							id: targetEl[count].attr('id')
						});
					} else {
						targetData[count] = options[count].boxContentData;
					}
				}
				if (options[count].boxContentDataURL !== '' && options[count].boxContentDataPreload === true) {
					var truecount = count;
					$.get(options[count].boxContentDataURL, targetData[count], function(data, textStatus) {
						preload[truecount] = data;
					});
				}
			}
			count++;			
		});
	};
	$.fn.boxer.defaults = {
		targetElement: '',
		targetEvent: 'click',
		cloneElement: '',
		cloneRemoveElements: [],
		copyElement: null,
		copyElementAttributeReplace: null,
		positionElement: '',
		positionAlign: 'top',
		animate: false,
		animationStyle: '',
		animationEndPositionElement: '',		
		animationDelay: 500,
		boxStyle: null,
		boxClass: null,
		boxContent: '',
		boxContentDataURL: '',
		boxContentData: {},
		boxContentDataPreload: true,
		removeAnimationStyle: null,
		removeAnimationDelay: 500,
		removeAnimationEndPositionElement: '',
		targetClass: null,
		targetStyle: null,
		targetStyleAnimate: false,
		targetStyleAnimationDelay: 500,
		shadow: true,
		shadowColor: '#000',
		shadowOpacity: 0.4,
		shadowOffset: [3,3]
	};
})(jQuery);
