/* clickMenu - v0.1.6
 * Copyright (c) 2007 Roman Weich
 * http://p.sohei.org
 *
 * Changelog: 
 * v 0.1.6 - 2007-09-06
 *	-fix: having a link in the top-level menu would not open the menu but call the link instead
 * v 0.1.5 - 2007-07-07
 *	-change/fix: menu opening/closing now through simple show() and hide() calls - before fadeIn and fadeOut were used for which extra functions to stop a already running animation were created -> they were 
 *			buggy (not working with the interface plugin in jquery1.1.2 and not working with jquery1.1.3 at all) and now removed
 *	-change: removed option: fadeTime
 *	-change: now using the bgiframe plugin for adding iframes in ie6 when available
 * v 0.1.4 - 2007-03-20
 *	-fix: the default options were overwritten by the context related options
 *	-fix: hiding a submenu all hover- and click-events were unbound, even the ones not defined in this plugin - unbinding should work now
 * v 0.1.3 - 2007-03-13
 *	-fix: some display problems ie had when no width was set on the submenu, so on ie the width for each submenu will be explicitely set
 *	-fix: the fix to the ie-width-problem is a fix to the "ie does not support css min-width stuff" problem too which displayed some submenus too narrow (it looked just not right)
 *	-fix: some bugs, when user the was too fast with the mouse
 * v 0.1.2 - 2007-03-11
 *	-change: made a lot changes in the traversing routines to speed things up (having better memory usage now as well)
 *	-change: added $.fn.clickMenu.setDefaults() for setting global defaults
 *	-fix: hoverbug when a main menu item had no submenu
 *	-fix: some bugs i found while rewriting most of the stuff
 * v 0.1.1 - 2007-03-04
 *	-change: the width of the submenus is no longer fixed, its set in the plugin now
 *	-change: the submenu-arrow is now an img, not the background-img of the list element - that allows better positioning, and background-changes on hover (you have to set the image through the arrowSrc option)
 *	-fix: clicking on a clickMenu while another was already open, didn't close the open one
 *	-change: clicking on the open main menu item will close it
 *	-fix: on an open menu moving the mouse to a main menu item and moving it fastly elsewere hid the whole menu
 * v 0.1.0 - 2007-03-03
 */

(function($)
{
	var defaults = {
		onClick: function(){
			$(this).find('>a').each(function(){
				if ( this.href )
				{
					window.location = this.href;
				}
			});
		},
		arrowSrc: '',
		subDelay: 300,
		mainDelay: 10
	};

	$.fn.clickMenu = function(options) 
	{
		var shown = false;
		var liOffset = ( ($.browser.msie) ? 4 : 2 );

		var settings = $.extend({}, defaults, options);

		var hideDIV = function(div, delay)
		{
			//a timer running to show the div?
			if ( div.timer && !div.isVisible )
			{
				clearTimeout(div.timer);
			}
			else if (div.timer)
			{
				return; //hide-timer already running
			}
			if ( div.isVisible )
			{
				div.timer = setTimeout(function()
				{
					//remove events
					$(getAllChilds(getOneChild(div, 'UL'), 'LI')).unbind('mouseover', liHoverIn).unbind('mouseout', liHoverOut).unbind('click', settings.onClick);
					//hide it
					$(div).hide();
					div.isVisible = false;
					div.timer = null;
				}, delay);
			}
		};

		var showDIV = function(div, delay)
		{
			if ( div.timer )
			{
				clearTimeout(div.timer);
			}
			if ( !div.isVisible )
			{
				div.timer = setTimeout(function()
				{
					//check if the mouse is still over the parent item - if not dont show the submenu
					if ( !checkClass(div.parentNode, 'hover') )
					{
						return;
					}
					//assign events to all div>ul>li-elements
					$(getAllChilds(getOneChild(div, 'UL'), 'LI')).mouseover(liHoverIn).mouseout(liHoverOut).click(settings.onClick);
					//positioning
					if ( !checkClass(div.parentNode, 'main') )
					{
						$(div).css('left', div.parentNode.offsetWidth - liOffset);
					}
					//show it
					div.isVisible = true; //we use this over :visible to speed up traversing
					$(div).show();
					if ( $.browser.msie ) //fixing a display-bug in ie6 and adding min-width
					{
						var cW = $(getOneChild(div, 'UL')).width();
						if ( cW < 100 )
						{
							cW = 100;
						}
						$(div).css('width', cW);
					}
					div.timer = null;
				}, delay);
			}
		};

		//same as hover.handlehover in jquery - just can't use hover() directly - need the ability to unbind only the one hover event
		var testHandleHover = function(e)
		{
			// Check if mouse(over|out) are still within the same parent element
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
			// Traverse up the tree
			while ( p && p != this )
			{
				try
				{ 
					p = p.parentNode;
				}
				catch(e)
				{ 
					p = this;
				}
			}
			// If we actually just moused on to a sub-element, ignore it
			if ( p == this )
			{
				return false;
			}
			return true;
		};
		
		var mainHoverIn = function(e)
		{
			//no need to test e.target==this, as no child has the same event binded
			//its possible, that a main menu item still has hover (if it has no submenu) - thus remove it
			var lis = getAllChilds(this.parentNode, 'LI');
			var pattern = new RegExp("(^|\\s)hover(\\s|$)");
			for (var i = 0; i < lis.length; i++)
			{
				if ( pattern.test(lis[i].className) )
				{
					$(lis[i]).removeClass('hover');
				}
			}
			$(this).addClass('hover');
			if ( shown )
			{
				hoverIn(this, settings.mainDelay);
			}
		};

		var liHoverIn = function(e)
		{
			if ( !testHandleHover(e) )
			{
				return false;
			}
			if ( e.target != this )
			{
				//look whether the target is a direct child of this (maybe an image)
				if ( !isChild(this, e.target) )
				{
					return;
				}
			}
			hoverIn(this, settings.subDelay);
		};

		var hoverIn = function(li, delay)
		{
			var innerDiv = getOneChild(li, 'DIV');
			//stop running timers from the other menus on the same level - a little faster than $('>*>div', li.parentNode)
			var n = li.parentNode.firstChild;
			for ( ; n; n = n.nextSibling ) 
			{
				if ( n.nodeType == 1 && n.nodeName.toUpperCase() == 'LI' )
				{
					var div = getOneChild(n, 'DIV');
					if ( div && div.timer && !div.isVisible ) //clear show-div timer
					{
						clearTimeout(div.timer);
						div.timer = null;
					}
				}
			}
			//is there a timer running to hide one of the parent divs? stop it
			var pNode = li.parentNode;
			for ( ; pNode; pNode = pNode.parentNode ) 
			{
				if ( pNode.nodeType == 1 && pNode.nodeName.toUpperCase() == 'DIV' )
				{
					if (pNode.timer)
					{
						clearTimeout(pNode.timer);
						pNode.timer = null;
						$(pNode.parentNode).addClass('hover');
					}
				}
			}
			//highlight the current element
			$(li).addClass('hover');
			//is the submenu already visible?
			if ( innerDiv && innerDiv.isVisible )
			{
				//hide-timer running?
				if ( innerDiv.timer )
				{
					clearTimeout(innerDiv.timer);
					innerDiv.timer = null;
				}
				else
				{
					return;
				}
			}
			//hide all open menus on the same level and below and unhighlight the li item (but not the current submenu!)
			$(li.parentNode.getElementsByTagName('DIV')).each(function(){
				if ( this != innerDiv && this.isVisible )
				{
					hideDIV(this, delay);
					$(this.parentNode).removeClass('hover');
				}
			});
			//show the submenu, if there is one
			if ( innerDiv )
			{
				showDIV(innerDiv, delay);
			}
		};

		var liHoverOut = function(e)
		{
			if ( !testHandleHover(e) )
			{
				return false;
			}
			if ( e.target != this )
			{
				if ( !isChild(this, e.target) ) //return only if the target is no direct child of this
				{
					return;
				}
			}
			//remove the hover from the submenu item, if the mouse is hovering out of the menu (this is only for the last open (levelwise) (sub-)menu)
			var div = getOneChild(this, 'DIV');
			if ( !div )
			{
				$(this).removeClass('hover');
			}
			else 
			{
				if ( !div.isVisible )
				{
					$(this).removeClass('hover');
				}
			}
		};

		var mainHoverOut = function(e)
		{
			//no need to test e.target==this, as no child has the same event binded
			//remove hover
			var div = getOneChild(this, 'DIV');
			var relTarget = e.relatedTarget || e.toElement; //this is undefined sometimes (e.g. when the mouse moves out of the window), so dont remove hover then
			var p;
			if ( !shown )
			{
				$(this).removeClass('hover');
			}
			else if ( !div && relTarget ) //menuitem has no submenu, so dont remove the hover if the mouse goes outside the menu
			{
				p = findParentWithClass(e.target, 'UL', 'clickMenu');
				if ( p.contains(relTarget))
				{
					$(this).removeClass('hover');
				}
			}
			else if ( relTarget )
			{
				//remove hover only when moving to anywhere inside the clickmenu
				p = findParentWithClass(e.target, 'UL', 'clickMenu');
				if ( !div.isVisible && (p.contains(relTarget)) )
				{
					$(this).removeClass('hover');
				}
			}
		};

		var mainClick = function()
		{
			var div = getOneChild(this, 'DIV');
			if ( div && div.isVisible ) //clicked on an open main-menu-item
			{
				clean();
				$(this).addClass('hover');
			}
			else
			{
				hoverIn(this, settings.mainDelay);
				shown = true;
				$(document).bind('mousedown', checkMouse);
			}
			return false;
		};

		var checkMouse = function(e)
		{
			//is the mouse inside a clickmenu? if yes, is it an open (the current) one?
			var vis = false;
			var cm = findParentWithClass(e.target, 'UL', 'clickMenu');
			if ( cm )
			{
				$(cm.getElementsByTagName('DIV')).each(function(){
					if ( this.isVisible )
					{
						vis = true;
					}
				});
			}
			if ( !vis )
			{
				clean();
			}
		};

		var clean = function()
		{
			//remove timeout and hide the divs
			$('ul.clickMenu div.outerbox').each(function(){
				if ( this.timer )
				{
					clearTimeout(this.timer);
					this.timer = null;
				}
				if ( this.isVisible )
				{
					$(this).hide();
					this.isVisible = false;
				}
			});
			$('ul.clickMenu li').removeClass('hover');
			//remove events
			$('ul.clickMenu>li li').unbind('mouseover', liHoverIn).unbind('mouseout', liHoverOut).unbind('click', settings.onClick);
			$(document).unbind('mousedown', checkMouse);
			shown = false;
		};

		var getOneChild = function(elem, name)
		{
			if ( !elem )
			{
				return null;
			}
			var n = elem.firstChild;
			for ( ; n; n = n.nextSibling ) 
			{
				if ( n.nodeType == 1 && n.nodeName.toUpperCase() == name )
				{
					return n;
				}
			}
			return null;
		};

		var getAllChilds = function(elem, name)
		{
			if ( !elem )
			{
				return [];
			}
			var r = [];
			var n = elem.firstChild;
			for ( ; n; n = n.nextSibling ) 
			{
				if ( n.nodeType == 1 && n.nodeName.toUpperCase() == name )
				{
					r[r.length] = n;
				}
			}
			return r;
		};

		var findParentWithClass = function(elem, searchTag, searchClass)
		{
			var pNode = elem.parentNode;
			var pattern = new RegExp("(^|\\s)" + searchClass + "(\\s|$)");
			for ( ; pNode; pNode = pNode.parentNode )
			{
				if ( pNode.nodeType == 1 && pNode.nodeName.toUpperCase() == searchTag && pattern.test(pNode.className) )
				{
					return pNode;
				}
			}
			return null;
		};
		
		var checkClass = function(elem, searchClass)
		{
			var pattern = new RegExp("(^|\\s)" + searchClass + "(\\s|$)");
			if ( pattern.test(elem.className) )
			{
				return true;
			}
			return false;
		};
		
		var isChild = function(elem, childElem)
		{
			var n = elem.firstChild;
			for ( ; n; n = n.nextSibling ) 
			{
				if ( n == childElem )
				{
					return true;
				}
			}
			return false;
		};

	    return this.each(function()
		{
			//add .contains() to mozilla - http://www.quirksmode.org/blog/archives/2006/01/contains_for_mo.html
			if (window.Node && Node.prototype && !Node.prototype.contains)
			{
				Node.prototype.contains = function(arg) 
				{
					return !!(this.compareDocumentPosition(arg) & 16);
				};
			}
			//add class
			if ( !checkClass(this, 'clickMenu') )
			{
				$(this).addClass('clickMenu');
			}
			//add shadows
			$('ul', this).shadowBox();
			//ie6? - add iframes
			if ( $.browser.msie && (!$.browser.version || parseInt($.browser.version) <= 6) )
			{
				if ( $.fn.bgiframe )
				{
					$('div.outerbox', this).bgiframe();
				}
				else
				{
					/* thanks to Mark Gibson - http://www.nabble.com/forum/ViewPost.jtp?post=6504414&framed=y */
					$('div.outerbox', this).append('<iframe style="display:block;position:absolute;top:0;left:0;z-index:-1;filter:mask();' + 
									'width:expression(this.parentNode.offsetWidth);height:expression(this.parentNode.offsetHeight)"/>');
				}
			}
			//assign events
			$(this).bind('closemenu', function(){clean();}); //assign closemenu-event, through wich the menu can be closed from outside the plugin
			//add click event handling, if there are any elements inside the main menu
			var liElems = getAllChilds(this, 'LI');
			for ( var j = 0; j < liElems.length; j++ )
			{
				if ( getOneChild(getOneChild(getOneChild(liElems[j], 'DIV'), 'UL'), 'LI') ) // >div>ul>li
				{
					$(liElems[j]).click(mainClick);
				}
			}
			//add hover event handling and assign classes
			$(liElems).hover(mainHoverIn, mainHoverOut).addClass('main').find('>div').addClass('inner');
			//add the little arrow before each submenu
			if ( settings.arrowSrc )
			{
				$('div.inner div.outerbox', this).before('<img src="' + settings.arrowSrc + '" class="liArrow" />');
			}

			//the floating list elements are destroying the layout..so make it nice again..
			$(this).wrap('<div class="cmDiv"></div>').after('<div style="clear: both; visibility: hidden;"></div>');
	    });
	};
	$.fn.clickMenu.setDefaults = function(o)
	{
		$.extend(defaults, o);
	};
})(jQuery);

(function($)
{
	$.fn.shadowBox = function() {
	    return this.each(function()
		{
			var outer = $('<div class="outerbox"></div>').get(0);
			if ( $(this).css('position') == 'absolute' )
			{
				//if the child(this) is positioned abolute, we have to use relative positioning and shrink the outerbox accordingly to the innerbox
				$(outer).css({position:'relative', width:this.offsetWidth, height:this.offsetHeight});
			}
			else
			{
				//shrink the outerbox
				$(outer).css('position', 'absolute');
			}
			//add the boxes
			$(this).addClass('innerBox').wrap(outer).
					before('<div class="shadowbox1"></div><div class="shadowbox2"></div><div class="shadowbox3"></div>');
	    });
	};
})(jQuery);

/*
 * Superfish v1.3.4 - jQuery menu widget
 *
 * Copyright (c) 2007 Joel Birch
 *
 * Dual licensed under the MIT and GPL licenses:
 * 	http://www.opensource.org/licenses/mit-license.php
 * 	http://www.gnu.org/licenses/gpl.html
 */

/* YOU SHOULD DELETE THIS CHANGELOG TO REDUCE FILE SIZE:
 * v1.2.1 altered:  2nd July 07. added hide() before animate to make work for jQuery 1.1.3. See comment in 'over' function.
 * v1.2.2 altered:  2nd August 07. changed over function .find('ul') to .find('>ul') for smoother animations
 * 				    Also deleted the iframe removal lines - not necessary it turns out
 * v1.2.3 altered:  jquery 1.1.3.1 broke keyboard access - had to change quite a few things and set display:none on the
 *				    .superfish rule in CSS instead of top:-999em
 * v1.3	: 		    Pretty much a complete overhaul to make all original features work in 1.1.3.1 and above.
 *				    .superfish rule reverted back to top:-999em (which is better).
 * v1.3.1 altered:  'li[ul]' to $('li:has(ul)') to work with jQuery 1.2
 * v1.3.2: 			added onshow callback option as requested - 'this' keyword refers to revealed ul.
		   			fixed bug whereby multiple menus on a page shared options. Now each menu can have separate options.
					fixed IE6 and IE7 bug whereby under certain circumstances => 3rd tier menus appear instantly with text missing when revisited
 * v1.3.3: 			altered event attachment selectors for performance increase on menu setup.
 * v1.3.4: 			fixed pathClass bug as current path was not being restored. Still doesn't if using keyboard nav (will work on that).
 */

(function($){
	$.fn.superfish = function(o){
		var $sf = this,
			defaults = {
			hoverClass	: 'sfHover',
			pathClass	: 'overideThisToUse',
			delay		: 10,
			animation	: {opacity:'show'},
			speed		: 'fast',
			onshow		: function(){} // in your function, 'this' is the revealed ul
		},
			over = function(){
				clearTimeout(this.sfTimer);
				$(this)
				.showSuperfishUl(o)
				.siblings()
				.hideSuperfishUl(o);
			},
			out = function(){
				var $$ = $(this);
				if ( !$$.is('.'+o.bcClass) ) {
					this.sfTimer=setTimeout(function(){
						$$.hideSuperfishUl(o);
						var sf = $$.parents('ul.superfish:first')[0];
						if (!$('.'+o.hoverClass,sf).length) {
							over.call(sf.o.$currents.hideSuperfishUl(o));
						}
					},o.delay);
				}		
			};
		$.fn.extend({
			hideSuperfishUl : function(o){
				$('li.'+o.hoverClass,this)
				.andSelf()
					.removeClass(o.hoverClass)
					.find('>ul')
						.hide()
						.css('visibility','hidden');
				return this;
			},
			showSuperfishUl : function(o){
				return this
					.addClass(o.hoverClass)
					.find('>ul:hidden')
						.css('visibility','visible')
						.animate(o.animation,o.speed,function(){
							o.onshow.call(this);
						})
					.end();
			},
			applySuperfishHovers : function(){
				return this[($.fn.hoverIntent) ? 'hoverIntent' : 'hover'](over,out);
			}
		});
		
		return this
		.addClass('superfish')
		.each(function(){
			o = $.extend({bcClass:'sfbreadcrumb'},defaults,o);
			o = $.extend(o,{$currents:$('li.'+o.pathClass,this)});
			this.o = o;
			
			if (o.$currents.length) {
				o.$currents.each(function(){
					$(this)
					.addClass(o.hoverClass+' '+o.bcClass)
					.filter(':has(ul)')
						.removeClass(o.pathClass);
				});
			}
			
			var $sfHovAr=$('li:has(ul)',this)
				.applySuperfishHovers(over,out)
				.not('.'+o.bcClass)
					.hideSuperfishUl(o)
				.end();
			
			$('a',this).each(function(){
				var $a = $(this), $li = $a.parents('li');
				$a.focus(function(){
					over.call($li);
					return false;
				}).blur(function(){
					$li.removeClass(o.hoverClass);
				});
			});
		});
	};
	$(window).unload(function(){
		$('ul.superfish').each(function(){
			$('li:has(ul)',this).unbind('mouseover').unbind('mouseout');
			this.o = this.o.$currents = null; // clean up
		});
	});
})(jQuery);
