/**
 * exmenu
 * Standards based unobtrusive exandable menus developed using jQuery
 *
 * @version 2.3.5
 * @author Andrew Ramsden <http://irama.org/web/dhtml/exmenu/>
 * @license GNU GENERAL PUBLIC LICENSE (GPL) <http://www.gnu.org/licenses/gpl.html>
 * @requires jQuery (tested with 1.3.1) <http://jquery.com/>
 * @requires jQuery jARIA plugin <http://outstandingelephant.com/jaria/>
 *
 * Changelog:
 *   * 2.3.1: preventDefault() added to event handler rather than returning false (allows event to continue bubbling up).
 *   * 2.3.2: tweak to allow page heading and nav item text to match regardles of leading or trailing whitespace.
 *   * 2.3.3: ARIA roles and states added.
 *   * 2.3.4: Codestyle consistency changes, added support for options passed with 'init'. Also added support for accessible CSS image replacement.
 *   * 2.3.5: Fixed a bug where on initialisation some toggle buttons had irrelevant information in the title text.
 */
/* config (edit away) */
jQuery.exmenu = {};

jQuery.exmenu.conf = {
	exmenuClass       : 'exmenu',
	simpleClass       : 'simple',
	parentClass       : 'parent',
	pageTitleSelector : 'h1#page-title',
	activeClass       : 'active',
	currentClass      : 'current',
	toggleClass       : 'toggle',
	closedClass       : 'closed',
	noLinkClass       : 'no-link',
	parentLinkClass   : 'parent-link',
	openToggleText    : '[-]',
	closedToggleText  : '[+]',
	openToggleTitle   : 'Close the %s submenu', // use %s to represent the name of the submenu
	closedToggleTitle : 'Open the %s submenu',
	clearPixelClass   : 'for-css-replacement'
};
/* end config */

/**
 * Default options, these can be overridden for each call to exmenu('init',options)
 */
jQuery.exmenu.defaultOptions = {
	topLevelCanToggle  : true,
	supportCSSImgReplace : false, // if you would like to replace the ascii control characters with images, set this to true
	                               // and ensure the path to a transparent image is also sent as an option. You should then
								   // style the clearPixel image to displace the text, so when images are disabled, the
								   // ascii characters become visible.
								   // See examples at http://irama.org/web/dhtml/compact/slideshow/ for more information.
	clearPixelImg        : 'displacement.png'
};


/* don't edit from here down unless you know what you are doing */
(function($) {// start closure
	
	xmMenuIds = [];
	xmMenuIdCount = 0;
	xmMatchCurrentText = '';
	xmCurrentMenu = null;
	
	// optional initialisation code
	$(document).ready(function() {
		$('.exmenu').exmenu();
	});
	
	$.fn.extend({
		exmenu: function() {
			
			action = (arguments.length > 0) ? arguments[0] : '' ;
			
			switch (action.toLowerCase()) {
				default: case '': case 'init':
					//xmTopLevelCanToggle = (Boolean)(arguments.length > 1) ? arguments[1] : true ;
					options = arguments[1] || {};
					$(this).each(function(){
						xmInitExMenu.apply(this, [options]);
					});
					return $(this);
				break;
				case 'setcurrent':
					xmMatchCurrentText = (arguments.length > 1) ? arguments[1] : '' ;
					$(this).each(xmSetCurrent);
					return $(this);
				break;
				case 'expandall': case 'openall':
					$(this).each(xmExpandAll);
					return $(this);
				break;
				case 'collapseall': case 'closeall':
					$(this).each(xmCollapseAll);
					return $(this);
				break;
			}
			
			
		}
	});
	
	
	
	function xmInitExMenu (options) {
		// Only ULs can be processed
			if (this.tagName != 'UL') {
				return $(this); // facilitate chaining
			}
			if ($(this).is('.'+$.exmenu.conf.activeClass)) {
				return $(this); // already active, return.
			}
		
		// ensure the container class is set
			if (!$(this).is($.exmenu.conf.exmenuClass)) {
				$(this).addClass($.exmenu.conf.exmenuClass);
			}
		
		// Merge runtime options with defaults
		// Note: The first argument sent to extend is an empty object to
		// prevent extend from overriding the default $.AKN.defaultOptions object.
			options = (typeof options == 'undefined')
				? $.exmenu.defaultOptions
				: $.extend({}, $.exmenu.defaultOptions, options)
			;
			$(this).data('options', options);
			$.exmenu.currentOptions = options;
		
		// each exmenu must have an unique id
			xmMatched = this;
		
		//for (xmEachMatched in xmMatched) {
			if (xmMatched.id === '') {
				if (typeof(console)!='undefined') {
					console.error('Failed to initialise exmenu "'+xmMatched.id+'": Selector matched, but each exmenu must have an unique id.');
				}
			} else {
				xmMenuIds[xmMenuIdCount++] = xmMatched.id;
			}

			xmMenuSelector = '#'+xmMatched.id;
			
			// setup all parent nodes
				if (options.topLevelCanToggle) {
					$(xmMenuSelector+' li').each(xmSetupLi);
				} else {
					// skip top level
					$(xmMenuSelector+' li li').each(xmSetupLi);
				}
				
			// add all toggle actions
				allToggles = $(xmMenuSelector+' .'+$.exmenu.conf.toggleClass)
					.click(xmToggleNode)
					.ariaRole('button')
				;
			
			// add clearPixel images if CSSImageReplacement mode is enabled
				if (options.supportCSSImgReplace !== false) {
					allToggles.prepend('<img src="'+options.clearPixelImg+'" alt="" class="'+$.compact.slideshow.conf.clearPixelClass+'" />');
				}
			
			// collapse all nodes
				$(xmMenuSelector+' li.'+$.exmenu.conf.parentClass)
					.addClass($.exmenu.conf.closedClass)
					.children('ul').ariaState('hidden','true')
				;
			
			// update toggle text and title
				$(xmMenuSelector+' li.'+$.exmenu.conf.parentClass+' a.'+$.exmenu.conf.toggleClass).each(xmSetupToggle);
			
			// expand to current node
				xmCurrentNode = $(xmMenuSelector+' li.'+$.exmenu.conf.currentClass);
				xmCurrentNode
					.removeClass($.exmenu.conf.closedClass)
					.children('ul').ariaState('hidden','false')
				;
				xmUpdateToggle(xmCurrentNode.children('.'+$.exmenu.conf.toggleClass).get());
			
			// expand parents of current node
				xmParentsOfCurrent = $(xmMenuSelector+' li.'+$.exmenu.conf.currentClass).parents('li.'+$.exmenu.conf.parentClass);
				xmParentsOfCurrent
					.removeClass($.exmenu.conf.closedClass)
					.children('ul').ariaState('hidden','false')
				;
				xmUpdateToggle(xmParentsOfCurrent.children('.'+$.exmenu.conf.toggleClass).get());
			
			// add active classes
				$(this).addClass($.exmenu.conf.activeClass);
				$(this).addClass($.exmenu.conf.exmenuClass);
			
			// check for h1
				xmTitle = $($.exmenu.conf.pageTitleSelector+':lt(1)').text();
				if (xmTitle != '') {
					$(this).exmenu('setCurrent', xmTitle);
				}
	};
	
	function xmSetupLi () {
		// if item is not linked, wrap item text in span
		if ( $(this).children('a').size() === 0 ) {


			xmTempChildren = $(this).children();
			$(this).children().remove();
			xmTempText = $(this).text();
			$(this).empty();
			$(this).append('<span class="'+$.exmenu.conf.noLinkClass+'">'+xmTempText+'</span>');
			$(this).append(xmTempChildren);
		}
		
		// if this is a parent, add parent class and toggle
		if ( $(this).find('li').size() > 0 ) {
			$(this).addClass($.exmenu.conf.parentClass);
			
			
			// is this a simple exmenu?
				if ($(this).parents('.exmenu.simple').size()>0) {
					// simple menu, add toggle directly to link
					$(this).children('a').addClass($.exmenu.conf.toggleClass);
				} else {
					// This class allows you to find links that have an
					// associated toggle (but aren't the toggle themselves).
					// These are the navigation links themselves
						$(this).children('a').addClass($.exmenu.conf.parentLinkClass);
						$(this).children('.'+$.exmenu.conf.noLinkClass).addClass($.exmenu.conf.parentLinkClass);
						
					// non-simple, add seperate toggle link
						$(this).prepend('<a href="#" class="'+$.exmenu.conf.toggleClass+'">'+$.exmenu.conf.closedToggleText+'</a> ');
				}
		}
	};
	
	function xmToggleNode (eventObj) {
		$(this).parent().toggleClass($.exmenu.conf.closedClass);
		
		if ($(this).parent().is('.'+$.exmenu.conf.closedClass)) {
			$(this).parent().children('ul').ariaState('hidden','true');
		} else {
			$(this).parent().children('ul').ariaState('hidden','false');	
		}
		
		// cache options
			$.exmenu.currentOptions = $(this).parents('.'+$.exmenu.conf.exmenuClass+':first').data('options');
		
		xmUpdateToggle(this);
		//return false;
		eventObj.preventDefault();
	};
	function xmUpdateToggle (xmThis) {
	
		options = $.exmenu.currentOptions;
		
		
		//if (!containerEl.is('.'+$.exmenu.conf.noLinkClass)) {
			
			if ($(xmThis).size() > 1) {
				xmThis = $(xmThis).get($(xmThis).size()-1);
			}
			
			
			xmMenuText = $(xmThis).siblings('a').text();
			xmMenuText = (xmMenuText!=='')?xmMenuText:$(xmThis).siblings('.'+$.exmenu.conf.noLinkClass).text();
			
			if ($(xmThis).parent().is('.'+$.exmenu.conf.closedClass)) {
				// node is now closed
					$(xmThis).text($.exmenu.conf.closedToggleText);
					$(xmThis).attr('title',$.exmenu.conf.closedToggleTitle.replace("%s", xmMenuText, "gi"));
					
				// add clearPixel images if CSSImageReplacement mode is enabled
					if (options.supportCSSImgReplace !== false) {
						$(xmThis).prepend('<img src="'+options.clearPixelImg+'" alt="" class="'+$.compact.slideshow.conf.clearPixelClass+'" />');
					}
			} else {
				// node is now open
					$(xmThis).text($.exmenu.conf.openToggleText);
					$(xmThis).attr('title',$.exmenu.conf.openToggleTitle.replace("%s", xmMenuText, "gi"));
				
				// add clearPixel images if CSSImageReplacement mode is enabled
					if (options.supportCSSImgReplace !== false) {
						$(xmThis).prepend('<img src="'+options.clearPixelImg+'" alt="" class="'+$.compact.slideshow.conf.clearPixelClass+'" />');
					}
			}
	};
	function xmSetupToggle() {
			return xmUpdateToggle(this);
	};
	
	xmSetCurrent = function () {
		if (xmMatchCurrentText == '') {
			// collapse all
			xmCollapseAll.apply(this);
		} else {
			xmCurrentMenu = this;
			xmNavElements = $(this).find('a, .'+$.exmenu.conf.noLinkClass).not('.'+$.exmenu.conf.toggleClass);
			for (xmN = 0; xmN < xmNavElements.size(); xmN++) {
				if (xmTestAndSetMenuItemAsCurrent(xmNavElements.get(xmN))) {
					break;
				}
			}
		}
	};
	
	xmTestAndSetMenuItemAsCurrent = function (xmNavElement) {		
		//console.log($(this).text().toLowerCase()+' ?= '+xmMatchCurrentText.toLowerCase());
		if ($.trim($(xmNavElement).text()).toLowerCase() == $.trim(xmMatchCurrentText).toLowerCase()) {
			// close all nodes
				xmCollapseAll.apply(xmCurrentMenu);
				
			// remove the previous current node(s)
				xmPreviousCurrent = $(xmCurrentMenu).find('.'+$.exmenu.conf.currentClass);
				xmPreviousCurrent.removeClass($.exmenu.conf.currentClass);
				xmUpdateToggle(xmPreviousCurrent.children('.'+$.exmenu.conf.toggleClass).get());							   
			
			// set new current node
				xmCurrentNode = $(xmNavElement).parent();
				xmCurrentNode.addClass($.exmenu.conf.currentClass);
			
			// open current
				xmCurrentNode
					.removeClass($.exmenu.conf.closedClass)
					.children('ul').ariaState('hidden','false')
				;
				xmUpdateToggle(xmCurrentNode.children('.'+$.exmenu.conf.toggleClass).get());
			
			// open direct parents of current
				xmCurrentParents = xmCurrentNode.parents('li.'+$.exmenu.conf.parentClass);
				xmCurrentParents
					.removeClass($.exmenu.conf.closedClass)
					.children('ul').ariaState('hidden','false')
				;
				xmUpdateToggle(xmCurrentParents.children('.'+$.exmenu.conf.toggleClass).get());
			
			return true;
		}
		return false;
	};
	
	xmCollapseAll = function () {
		// collapse all nodes
		$(this).find('li.'+$.exmenu.conf.parentClass)
			.addClass($.exmenu.conf.closedClass)
			.children('ul').ariaState('hidden','true')
		;
		xmUpdateToggle($(this).find('li.'+$.exmenu.conf.parentClass+' > .'+$.exmenu.conf.toggleClass).get());
	};
	xmExpandAll = function () {
		// expand all nodes
		$(this).find('li.'+$.exmenu.conf.parentClass)
			.removeClass($.exmenu.conf.closedClass)
			.children('ul').ariaState('hidden','false')
		;
		xmUpdateToggle($(this).find('li.'+$.exmenu.conf.parentClass+' > .'+$.exmenu.conf.toggleClass).get());
	};
	
	xmTestCurrent = function (xmTestText) {
		return ($.trim(xmTestText).toLowerCase() == this.findText.toLowerCase())?true:false;
	};
	

	
})(jQuery); // end closure
