/*****************************************************************************************************************
 *
 * @title	Navver
 * @date 	February 23, 2008
 * @author	Shanker Kaura
 *
 *
 * Section 0) Revision history
 * ---------------------------
 * February 22, 2008		ver 1.0
 * March 3, 2008			ver 1.1
 *	-added ability to have subnavs ONLY display on current page (ie. not on rollover)
 *  -modified window.location.href to use .pathname (so we have better url parameter handling)
 *  -can now add a start page (or any other page) where all subnavs show up on rollover
 *
 * Section 1) Usage Instructions
 * -----------------------------
 * [on every page that will have the shared menu]
 * 0) have a div tag on your page with unique id where you want navver to be
 * 1) include jquery.js
 * 2) include jquery.metadata.js
 * 3) include structure.js (or whatever the file is containing your nav structure -- see section 3)
 * 4) include jquery.navver.js
 * 5) include your CSS style sheet with the definitions required for navver (see section 6)
 * 6) call as follows: $('#menu').navver(); (where #menu is the id from step 0)
 *
 *
 *
 * Section 2) Sample file
 * ----------------------
 * Here is a sample HTML file (complete -- ie. use as a template if desired)
 *
 * <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 * <html>
 * 	<head>
 * 		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 * 		<title>I Love Navver</title>
 *
 * 		<script src="js/jquery.js" type="text/javascript"></script>
 * 		<script src="js/jquery.metadata.js" type="text/javascript"></script>
 * 		<script src="js/structure.js" type="text/javascript"></script>
 * 		<script src="js/jquery.navver.js" type="text/javascript"></script>
 *
 * 		<script type="text/javascript">
 *	 		$(document).ready(function(){
 * 				$('#menu').navver();
 * 			});
 * 		</script>
 * 	
 * 		<link rel="stylesheet" type="text/css" href="css/style.css" />
 * 	</head>
 * 	<body>
 * 		<div id="menu"></div>
 * 	</body>
 * </html> 
 * 
 *
 *
 * Section 3) structure.js
 * -------------------------
 * structure.js is a file which will start as follows:
 *		var structure = [{}];
 
 * In between the curly brackets is where you will define your navigation.  See the following examples:
 *   
 * --example 1 -- text only navigation
 * -----------------------------------
 *	var structure = [{
 *			'href' : 'index.html',
 *			'text' : 'A something or another',
 *			'subnav':[{
 *					'href' : 'a1.html',
 *					'text' : 'a1'
 *				},{
 *					'href' : 'a2.html',
 *					'text' : 'a2'
 *				},{
 *					'href' : 'a3.html',
 *					'text' : 'a3'
 *			}]
 *		},{
 *			'href' : 'b.html',
 *			'text' : 'c something or another'
 *		},{
 *			'href' : 'c1.html',
 *			'text' : 'b something',
 *			'subnav':[{
 *					'href' : 'c1.html',
 *					'text' : 'b1'
 *				},{
 *					'href' : 'c2.html',
 *					'text' : 'b2'
 *			}]
 *	}];
 *
 *
 * --example 2 -- image only navigation
 * ------------------------------------
 *  var structure = [{
 * 		href : 'index.html',
 * 		text : 'A something or another',
 * 		images : {regular:'images/nav_a.jpg', over:'images/nav_a_over.jpg', current:'images/nav_a_current.jpg'},
 * 		subnav:[{
 * 				href : 'a1.html',
 * 				text : 'a1',
 * 				images : {regular:'images/nav_a1.jpg', over:'images/nav_a1_over.jpg', current:'images/nav_a1_current.jpg'}
 * 			},{
 * 				href : 'a2.html',
 * 				text : 'a2',
 * 				images : {regular:'images/nav_a2.jpg', over:'images/nav_a2_over.jpg', current:'images/nav_a2_current.jpg'}
 * 			},{
 * 				href : 'a3.html',
 * 				text : 'a3',
 * 				images : {regular:'images/nav_a3.jpg', over:'images/nav_a3_over.jpg', current:'images/nav_a3_current.jpg'}
 * 		}]
 * 	},{
 * 		href : 'b.html',
 * 		text : 'c something or another',
 * 		images : {regular:'images/nav_c.jpg', over:'images/nav_c_over.jpg', current:'images/nav_c_current.jpg'},
 * 	},{
 * 		href : 'c1.html',
 * 		text : 'b something',
 * 		images : {regular:'images/nav_b.jpg', over:'images/nav_b_over.jpg', current:'images/nav_b_current.jpg'},
 * 		subnav:[{
 * 				href : 'c1.html',
 * 				text : 'b1',
 * 				images : {regular:'images/nav_b1.jpg', over:'images/nav_b1_over.jpg', current:'images/nav_b1_current.jpg'}
 * 			},{
 * 				href : 'c2.html',
 * 				text : 'b2',
 * 				images : {regular:'images/nav_b2.jpg', over:'images/nav_b2_over.jpg', current:'images/nav_b2_current.jpg'}
 * 		}]
 * }];
 *
 *
 *
 * Section 4) navver options
 * -------------------------
 * showSubnavs			true (default)
 * 						false
 *
 * staticSubnavs		true				leave subnav on at all times for current page
 *						false (default)		only show subnav when nav is hovered over
 *
 * horizontalMainnav	true				main navigation will go from left to right (ie. horizontal)
 *						false (default)		main navigation will go from top to bottom (ie. vertical)
 *
 * horizontalSubnav		true				sub navigation will go from left to right (ie. horizontal)
 *						false (default)		sub navigation will go from top to bottom (ie. vertical)
 *
 * To use these options call navver as follows:
 * 		$('#menu').navver({
 *			staticSubnavs: true,
 *			horizontalMainnav: true,
 *			horizontalSubnav: true
 * 		});
 *
 *
 *
 * Section 5) navver output
 * ------------------------
 * Here is the output of navver into your dom (this is not complete -- it only outlines classes that 
 * the user is able to set via css styling:
 * 
 * <ul id="nav" class="mainnav">
 * 		<li class="mainnav_link"></li>
 *		<li class="mainnav_link">
 *			<ul class="subnav">
 *				<li class="subnav_link"></li>
 *				<li class="subnav_link"></li>
 *				. 
 *				.
 *				.
 * 				<li class="subnav_link"></li>
 *			</ul>
 *		</li>
 *		.
 *		.
 *		.
 *		<li class="mainnav_link"></li>
 * </ul>
 *
 *
 *
 * Section 6) CSS
 * --------------
 * MUST BE DEFINED IN STYLE SHEET:
 * 	.subnav_link			--	define width and height
 * 	.mainnav_link 			--	define width and height
 *
 * OPTIONAL DEFINITIONS (required for textual menu)
 * 	.mainnav_link_over		--	over state of main navigation links
 *	.mainnav_link_current	--	current state of main navigation links
 *	.subnav_link_over		--	over state of subnav links
 *	.subnav_link_current	--	current state of subnav links
 *
 * OPTIONAL DEFINITIONS (100% optional, but may cause unexpected behaviour -- untested)
 *	.mainnav
 *	.subnav
 *
 *
 *
 * Section 7) Wishlist/todo
 * ------------------------
 * 1) since we know the configuration of the menu code (ie the s variable), we should optimize all dom selectors (ie. exact vs. searching)
 * 2) would be cool to make the subnav selection recursive
 * 3) right now the code is procedural: we should use object-oriented style coding (ie. right now we parse mainnav --> subnav --> mainnav again)
 *    it would be more appropriate to have references to hover function in mainnav and just modify them instead of parsing all mainnav_links a 2nd time
 *    problem: I haven't figured out how to apply object oriented principles to jquery
 ****************************************************************************************************************/


$.fn.navver = function (options) {
	options = jQuery.extend({
		showSubnavsOnRollover: true,
		staticSubnavs: false,
		horizontalMainnav: false,
		horizontalSubnav: false,
		overrideAndShowAllSubnavs: '',
		showAllSubnavsOnRoot: false,
		subnavLinkWidth: '125'
	  }, options);

	var showSubnavs = options.showSubnavsOnRollover; // whether subnav should be displayed or not (on rollover)
	var staticSubnavs = options.staticSubnavs; // whether subnav for current page should always be shown
	var horizontalMainnav = options.horizontalMainnav; // false implies vertical
	var horizontalSubnav = options.horizontalSubnav; // false implies vertical
	var navStructure = options.structure; // variable to parse for structural definition (defined above)
	var injectionTagID = this; // tag to inject nav into
	var overrideAndShowAllSubnavs = options.overrideAndShowAllSubnavs; // a page that allows for all subnavs to be displayed on rollover (ie. a start page)
	var showOnRoot = options.showAllSubnavsOnRoot; // display subnavs as rollovers on root page (on or off)
	var subnavLinkWidth = options.subnavLinkWidth;

		var subnavSizes = new Array(navStructure.length);
	
	// we're going to dynamically create the menu based on the structure defined above (ie. the navStructure variable)
	var s = '<ul id="nav" class="mainnav">\n';

	for (var i = 0; i < navStructure.length; i++){
		var item = navStructure[i];
		// alert(item.images.constructor == Object);
		// console.log(item.subnav != undefined && item.subnav.constructor == Array);

		// if there are images then we must inject the appropriate image into the menu and also
		// record the over, current, regular image states for use later, however if not, then we
		// only need to record the href
		if (item.images.constructor == Object){
			s += '<li class="mainnav_link {href:\'' + item.href + '\', img_regular:\'' + item.images.regular + '\', img_over:\'' + item.images.over + '\', img_current:\'' + item.images.current + '\'}"><a href="' + item.href + '"><img src="' + item.images.regular + '" alt="' + item.text + '" title="' + item.text + '" /></a>\n';
		} else {
			s += '<li class="mainnav_link {href:\'' + item.href + '\'}"><a href="' + item.href + '">' + item.text + '</a>\n';
		}

		subnavSizes[i] = 0;
		// if there is a subnav defined then we need to parse accordingly
		if (item.subnav != undefined && item.subnav.constructor == Array){
			s += '<ul class="subnav" id="subnav' + i + '">\n';
			subnavSizes[i] = item.subnav.length;
		
			// same as before with the images being defined...
			for (var j = 0; j < item.subnav.length; j++){
				var subItem = item.subnav[j];
				if (subItem.images.constructor == Object){
					s += '<li class="subnav_link {href:\'' + subItem.href + '\', img_regular:\'' + subItem.images.regular + '\', img_over:\'' + subItem.images.over + '\', img_current:\'' + subItem.images.current + '\'}"><a href="' + subItem.href + '"><img src="' + subItem.images.regular + '" alt="' + subItem.text + '" /></a></li>\n';
				} else {
					s += '<li class="subnav_link {href:\'' + subItem.href + '\'}"><a href="' + subItem.href + '">' + subItem.text + '</a></li>\n';
				}
			}

			s += '</ul></li>\n';
		} else s += '</li>';
	}
	s += '</ul>\n'; // close the string
	// inject the string into dom into user-defined div tag
	$(injectionTagID).html(s);

	// get the current url for use in later areas
	// todo: eliminate parameters
	var url = window.location.href;
	var currentURL = url.substring(url.lastIndexOf('/') + 1);
	/*
	if (url.indexOf('?') == -1){
		currentURL = url.substring(url.lastIndexOf('/') + 1); // what about parameters passed with url?
	} else {
		// currentURL = url.substring(url.lastIndexOf('/') + 1, url.indexOf('?'));
		currentURL = url.substring(url.lastIndexOf('/') + 1);
	}
	*/
	var matchingOverridePage = (currentURL == overrideAndShowAllSubnavs) ? true : false;
	
	var isRoot = (currentURL == '') ? true : false;
	
	// custom css to assist with proper display
	var ulOffset = 0; // needed to correct css with ul tag
	$('.subnav').css({display: 'none'}); // hide all subnavs (since we only want to show them when we scroll over appropriate mainnav link)
	$('#nav').css({marginLeft: ulOffset + 'px'}); // adjust navigation offset due to ul
	$('#nav, #nav li ul').css({listStyleType:'none'}); // remove bullets
	$('#nav img').css({border:'none'});
	// end custom css

	
	// go through every mainnav link and...
	var subnavIndex = 0;
	$("#nav > .mainnav_link").each(function(){
		// find out if an image is being used or it's text based
		var imgTag = $(this).find(' > a > img');
		var subnav = $(this).find(' > .subnav:first'); // only get first subnav (since there should only be one)
		
		// find out if this link is the same as the current page -- yes? then add appropriate 'current' class
		// console.log('metadata: ' + $(this).metadata().href);
		// console.log('current: ' + currentURL);
		if (($(this).metadata().href).indexOf(currentURL) == 0 || currentURL.indexOf($(this).metadata().href) == 0){
			// console.log('CURRENT PAGE FOUND');
			// but only continue if this isn't the root page and we need to have rollovers on first page
			// why? because it is root, there isn't a current page defined
			
			/* \\  && !showOnRoot */
			if (!isRoot) { 
				if (imgTag.length > 0){
					var img_current = $(this).metadata().img_current;
					imgTag.attr({src:img_current});
				} else{
					$(this).addClass('mainnav_link_current');
				}
			}
			
			// if user has chosen static subnavs then we will apply the 'alwaysOn' class to the current link
			// and also remove the display:none property so it is visible by default
			if (staticSubnavs) {
				subnav.addClass('alwaysOn');
				subnav.css({display:''});
			}

			if (isRoot && showOnRoot) {
				subnav.removeClass('alwaysOn');
				subnav.css({display:'none'});
			}
		}


	
		// get raw dimensions for processing later
		// used primarily for positioning subnav
		var mainnav_top = $(this).offset().top;
		var mainnav_left = $(this).offset().left;
		var mainnav_width = $(this).width();
		var mainnav_height = $(this).height();

		
		// apply horizontal mainnav styling and adjust positioning for subnav
		if (horizontalMainnav) {
			$(this).css({float:'left'});
			mainnav_top += mainnav_height;
			mainnav_left += ulOffset;
		} else {
			mainnav_left += mainnav_width + ulOffset;
		}
		
		
		// adjust subnav_links if horizontal subnav links are requested
		if (horizontalSubnav) subnav.find('.subnav_link').css({float:'left'});
		
		
		// apply positioning to subnav
		/*
		$('.subnav').css({
			position: 'absolute',
			top: mainnav_top + 'px',
			left: mainnav_left + 'px'
		});
		*/
		
		$('.subnav').css({
			position: 'absolute'
		});
		
		if (navigator.appName == "Microsoft Internet Explorer") // this is a hack... not very re-usable
			$('.subnav').css({
				top: mainnav_top + 'px',
				marginLeft: '-130px'
			});
		
		// fix ie6 nav problem -- each subnav needs unique id

		var subnavWidth = subnavSizes[subnavIndex] * subnavLinkWidth;
		$('#subnav' + subnavIndex).css({
			width: (subnavWidth + 'px')
		});
		subnavIndex++;
	}); // end of parsing mainnav_link(s)
	
	$('.subnav_link').each(function(){
		// find out if an image is being used or it's text based
		var imgTag = $(this).find(' > a > img');

		// if the current page has not already been found (ie. it is not a mainnav link)
		// and the subnav_link IS the current page then add the appropriate css classes
		// ie. add a 'current' class to both the current subnav_link and its parent (mainnav_link)
		// use short-circuit evaluation to determine if we should chck the url of the current subnav_link 
		// console.log($(this).metadata().href + "      " + currentURL);
		if ($(this).metadata().href == currentURL || currentURL.indexOf($(this).metadata().href) == 0){ 
			// console.log('subnav link is current page');
			// need to consider when images are being used vs. text
			if (imgTag.length > 0){
				// since images are being used, load up the current image
				var img_current = $(this).metadata().img_current;
				imgTag.attr({src:img_current});
				
				// and also change the parent navigation pic as well
				var parent_imgTag = $(this).parent().parent().find(' > a > img');
				var parent_img_current = $(this).parent().parent().metadata().img_current;
				parent_imgTag.attr({src:parent_img_current});
			} else {  
				// since we are text based, just add the appropriate classes
				$(this).addClass('subnav_link_current');
				$(this).parent().parent().addClass('mainnav_link_current');
			}
			
			// if static subnavs is requested, then we need to make sure that the parent
			// nav is alwaysOn and is visible by default
			if (staticSubnavs){
				$(this).parent().addClass('alwaysOn');
				$(this).parent().css({display:''});
			}
		}

		
		// check to see if the current subnav_link is the current page
		var subNavLinkIsCurrent = ($(this).metadata().href == currentURL);
		
		// set hover events for subnav_link(s)
		if (!subNavLinkIsCurrent){
			$(this).hover(
				// over function
				function(){
					// if images are being used, then set the appropriate image,
					// otherwise add the appropriate css class
					if (imgTag.length > 0){
						var img_over = $(this).metadata().img_over;
						
						imgTag.attr({src:img_over});
					} else 
						$(this).addClass('subnav_link_over');	
				},
				// out function
				function(){
					// if images are being used, then se the appropriate image,
					// otherwise add the appropriate class
					if (imgTag.length > 0){
						var img_regular = $(this).metadata().img_regular;
						imgTag.attr({src:img_regular});
					} else
						$(this).removeClass('subnav_link_over');			
				}
			);
		}
	});
	
	
	
	// we need to reparse all mainnav_links since the current page may be
	// a subnav -- thus we have to delay setting hover actions until all
	// css is finalized (this took a lot of work to figure out ie. where to put this block of code)
	$("#nav > .mainnav_link").each(function(){
		// find out if an image is being used or it's text based
		var imgTag = $(this).find(' > a > img');
		// note to me: currently using imgTag.length to determine if img exists, however, this probably isn't the right way, but I have to still figure out
		// how javascript organizes dom elements (ie. taxonomy)
		
		var subnav = $(this).find(' > .subnav:first'); // only get first subnav (since there should only be one)

		// set hover events for mainnav_link
		if (!subnav.hasClass('alwaysOn')){
			// find out if this mainnav_link is the current page
			var linkIsCurrent = $(this).metadata().href == currentURL;
			var img_over, img_regular;
			
			// if this is the current page and we're using images then set the appropriate pics to use 
			// in the hover function below
			if (linkIsCurrent && imgTag.length > 0){
				img_over = $(this).metadata().img_current;
				img_regular = img_over;
			} else {
				// since it isn't the current page, we use the default pics
				img_over = $(this).metadata().img_over;
				img_regular = $(this).metadata().img_regular;
			}
			
			
			// hover function
			$(this).hover(
				// over function
				function(){
					// if we're using images then set the appropriate over image
					// otherwise just add the appropriate css class
					if (imgTag.length > 0) imgTag.attr({src:img_over});
					else $(this).addClass('mainnav_link_over'); 
					
					subnav.css({zIndex:'99'}); // set the subnav to the highest z-index so it's always visible on hover
					if (showSubnavs || matchingOverridePage || (isRoot && showOnRoot)) subnav.show();
				},
				// out function
				function(){ 
					// if we're using images then set the appropriate regular image
					// otherwise just remove the appropriate css class
					if (imgTag.length > 0) imgTag.attr({src:img_regular});
					else $(this).removeClass('mainnav_link_over');

					if (showSubnavs || matchingOverridePage || (isRoot && showOnRoot)) subnav.hide();
				}
			);
		}
	}); // end of parsing mainnav_link(s)
	
	return this; // to comply with jQuery standards -- return ourselves

}