/*
 * Version: 04-12-2008
 * CRUMBL.COM CORE JAVASCRIPT
 */

var dom = DOMAssistant;

/**
 * General Behaviour Class
 */
var Behaviour = {
	init : function () {
		Behaviour.apply();
	},
	
	apply : function () {
		$('.site a[rel=external]').each(
			function () {
				$(this).addEvent('mouseover', Tip.display);
				$(this).addEvent('mouseout', Tip.hide);				
				$(this).addEvent('focus', Tip.display);
				$(this).addEvent('blur', Tip.hide);
				
				$(this).addEvent('click', Track.go);
			}
		);
		
		$('.video dl a[rel=external]').each(
			function () {
				$(this).addEvent('click', Track.go);
			}
		);
	}
};

/**
 * Tip Class
 *
 * Used to display tooltips for article links.
 */
var Tip = {
	linkHeight : 20,			// Fallback height for link
	maxHeight : 235,			// Fallback maximum height for tooltip
	margin : 20,				// Margin around tooltip
	obj : null,					// Reference to tooltip element
	title : null,				// Original title value for current tooltip

	display : function () {
		if (!Tip.obj) {
			// Create tooltip element and store it for later use
			Tip.obj = $(document.body).create('span', { className : 'tip' }, false);
		}
	
		// Get title from source
		var title = this.getAttribute('title');
		if (typeof title != 'undefined') {
			if (title.length) {
				// Store original title and surpress current
				Tip.title = title;
				this.setAttribute('title', '');
				
				// Replace content of tooltip with new title
				Tip.obj.replaceContent(Tip.format(title));
				
				// Temporarily hide it so we can calculate the actual height
				Tip.obj.addClass('hide');
				$(this).addContent(Tip.obj);
				
				// Top or bottom?
				var pos = findPos(this);
				var scroll = getScrollingPosition();
				var viewport = getViewportDimensions();
				
				// Consider height of this and margin-top
				var height = this.clientHeight ? this.clientHeight : Tip.linkHeight;							
				var available = viewport.height - (pos.top + height + Tip.margin - scroll.top);
				
				// Calculate height of tooltip
				var expectedHeight = Tip.obj.clientHeight ? Tip.obj.clientHeight : Tip.maxHeight;
							
				if (available < expectedHeight) {
					Tip.obj.addClass('tip-top');
				}
								
				// Add seperate class to fix IE's z-index
				$(this).addClass('has-tip');
				
				// Remove hiding class to display the result
				Tip.obj.removeClass('hide');
			}
		}
	},
	
	hide : function () {
		if (Tip.obj) {
			if (Tip.obj.parentNode) {
				Tip.obj.remove();
			}			
			Tip.obj.removeClass('tip-top');
			this.setAttribute('title', Tip.title);
		}
		$(this).removeClass('has-tip');
	},
	
	format : function (str) {
		var chunks = str.match(/(.*?): (.*)/i);
		var formatted = '';
		if (chunks[1]) {
			formatted += '<strong>' + chunks[1] + '</strong>';	
		}		
		if (chunks[2]) {
			formatted += chunks[2];
		}
		return formatted;
	}
};


/**
 * Track Class
 *
 * Used to unobtrusively track clicked links
 */
var Track = {
	uri : '/track/',
	
	go : function () {
		var data = Track.getData(this);
		if (data.length) {
			var img = new Image();
			var now = new Date();
			img.src = Track.uri + data + '?' + now.getTime();
		}
		this.target = '_blank';
	},
	
	getData : function (obj) {
		var data = null;
		if (obj.id.length) {
			data = obj.id;
		}
		else {
			var parent = $(obj).ancestor('dl');
			if (parent.id) {
				data = parent.id;
			}
		}
		return data;
	}
};

/**
 * Helper Functions
 */
function findPos (obj) {
	var curtop = curleft = 0;
	if (obj.offsetParent) {
		do {
			curtop += obj.offsetTop;
			curleft += obj.offsetLeft;
		} 
		while (obj = obj.offsetParent);
	}
	return { top : curtop, left : curleft };
}

function getScrollingPosition () {
	var curtop = curleft = 0;
	
	if (typeof window.pageXOffset != 'undefined' && typeof window.pageYOffset != 'undefined') {
		curtop = window.pageYOffset;
		curleft = window.pageXOffset;
	}
	else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.scrollTop != 'undefined' && typeof document.documentElement.scrollLeft != 'undefined') {
		curtop = document.documentElement.scrollTop;
		curleft = document.documentElement.scrollLeft;
	}
	
	return { top : curtop, left : curleft };
}

function getViewportDimensions () {
	var curwidth = curheight = 0;
	
	// Standards compliant browsers	
	if (typeof window.innerWidth != 'undefined') {
		curwidth = window.innerWidth;
		curheight = window.innerHeight;
	}	
	// IE6+ in standards compliant mode
	else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0)	{
		curwidth = document.documentElement.clientWidth;
		curheight = document.documentElement.clientHeight;
	}
	// IE5.5 and older
	else {
	   curwidth = document.getElementsByTagName('body')[0].clientWidth;
	   curheight = document.getElementsByTagName('body')[0].clientHeight;
	}
	return { width : curwidth, height : curheight };
}

/*
 * Extend DOMAssistant
 * - parent(): gets parent element for given reference
 * - ancestor(): gets first ancestor element matching given nodeName
 */

dom.parenting = function () {
	return {
		publicMethods : [
			'parent',
			'ancestor'
		],
		
		parent : function () {
			var parentElement = this.parentNode;
			while (parentElement && parentElement.nodeType !== 1) {
				parentElement = parentElement.parentNode;
			}
			return parentElement;
		},
		
		ancestor : function (nodeName) {
			if (typeof nodeName == 'undefined') {
				return this.parent();
			}
		
			var parentElement = this.parentNode;
			while (parentElement && (parentElement.nodeName.toLowerCase() != nodeName.toLowerCase())) {
				parentElement = parentElement.parentNode;
			}
			return parentElement;
		}
	};	
}();
dom.attach(dom.parenting);

/**
 * OnDOMReady Functions
 */
dom.DOMReady('Behaviour.init()');