/*

Dropdown

One-liner: Adds animation and mouseleave delays to dropdown menus

Usage: $('.menu').tso_dropdown({debug: true, eventDelay: 200});

Requirements: 
jQuery framework- http://jquery.com/
CSS to style menu
CSS for dropdown menu - http://htmldog.com/articles/suckerfish/dropdowns/
tso-debug.js

Notes:
n/a

*/
$(document).ready(function () {
	$('#header').tso_dropdown();	
});

$.fn.tso_dropdown = function(options) {
	
	// Configuration
	var defaults = {
			debug: false,
			hoverDelay: 50,
			eventDelayOff: 500,
			transitionLength: 100
	};
	var config = $.extend(defaults, options);
	
	// Allow debugging if required
	var __debug = new tso_debug();
	__debug.on = config.debug;
	__debug.log('Dropdown called');		
	
	// Document dimensions are used to prevent the dropdown menu extending beyond the viewable area
	config.viewportWidth  = $(window).width(); // Init
		
	// If the window is resized or scroleld reset the viewport dimensions
	$(window).resize(function(){
		config.viewportWidth  = $(window).width();
		__debug.log(config.viewportWidth);
	}).scroll(function(){
		config.viewportWidth  = $(window).width();
		__debug.log(config.viewportWidth);
	});
	
	// show/hide functions
	function showSubMenu(){
		// Load DOM objects into memory if referenced many times to reduce page calls
		var $subMenu = $(this).find('ul:first');
		var $parentMenu = $subMenu.parents('ul.menu:first');
		var numParentMenus = $subMenu.parents('ul.menu').length; // ratio of widths to add to calculation		
				
		// Reposition subMenu to left if it will break window bounds
		// Note: the width of submenus must be set and in pixels, not em
		if ($subMenu && $subMenu.css('width')) {
			
			// Find the CSS properties of the menu for manipulation
			var subMenuWidth = parseInt($subMenu.css('width').match(/[0-9]*/)[0]);
			var expectedFullWidth =  $(this).offset().left + (numParentMenus * subMenuWidth);
			
			if (expectedFullWidth > config.viewportWidth && numParentMenus > 1) {				
				// The submenu will extent beyond the viewport, position it to the left			
				__debug.log("Submenu will extend outside of the viewport, go left. Position will be:", expectedFullWidth);				
				
				// move menu to left
				$subMenu.css({left: -subMenuWidth}); 				
			} else {
				// set menu to default right position
				(numParentMenus > 1) ? $subMenu.css({left: subMenuWidth}) : $subMenu.css({left: 0});				
			}	
		} 
		
		// Expand subMenu animation
		$subMenu
		.animate({
			opacity: 'show'
		}, config.transitionLength, function() {
			$(this)
			.closest('li')
			.children('a')
			.addClass('hover'); // Add highlighting to active navigation levels
		}).end();		
		
		return this;
	}
	
	function hideSubMenu() {
		__debug.log('hideSubMenu');
		
		// Hide the subMenu
		$(this).find('ul:first').hide().end()
	    .closest('li')
		.children('a')
		.removeClass('hover');		 
		__debug.log('remove subMenu parent link highlighting');	
		
		return this;
	}
	
	// Hover intent config
	var hoverConfig = {    
		interval: config.hoverDelay,
		over: showSubMenu, // function = onMouseOver callback (REQUIRED)    
		timeout: config.eventDelayOff, // number = milliseconds delay before onMouseOut    
		out: hideSubMenu // function = onMouseOut callback (REQUIRED)    
	};
	
	return this.each(function () {
		
		$(this)
		.find('li')
		.hoverIntent(hoverConfig) // hoverIntent functions control expand/collapse 
		.children('a') // allow users to tab onto the menu (keyboard accessibility)
		.focus(function(event) {
			showSubMenu.apply($(this).parent()); // Amend the context of the function request
			__debug.log('Focus')
		})
		.blur(function() {
			
			
			
			// Find if the user has tabbed onto a sibling or onto the previous level menu
			if (!($(this).parent().prev('li') || $(this).parent().next('li'))) {
				console.log('close the menu');
			}
			// If previous level menu run the hideSubMenu on the item that blurred
				//hideSubMenu.apply($(this).parent());
			
			__debug.log('Blur');
		});
	});
}

/*

Debug

One-liner: Console logging object, outputs to Firebug console

Usage:
var debug = new tso_debug();
debug.on = true;
debug.log('Line ' + x + ' run');

Requirements: 
Firefox with firebug installed

Notes:
n/a

*/

var tso_debug = function() {
	this.on = false; // default logging is turned off
};

// object methods
tso_debug.prototype = {
	
	// logging method, take upto 255 args
	log: function() {
		// only log if debugging turned on
		if (this.on === true) {
			for (var i=0; i < arguments.length; i++){
				console.log(arguments[i]);
			}			
		}
	}	
};

