/**
 * Anonymus function that runs imediately and extends the jQuery library 
 * with custom plugins
 * 
 * Wraps the plugins in an anonymus function that keeps 
 * the $ shortcut pointing to jQuery independent of 
 * any other external instances of it (like Prototype or MooTools)
 * 
 * @param {Object} $ reference to the jQuery object
 */
(function($){

	/**
	 * jQuery toggleHover plugin
	 * @author rcaliman@adobe.com
	 * @version 1.0
	 * 
	 * Bound to a trigger element this toggles on mouseover/mouseout
	 * the visibility of the specified target DOM element.
	 * 
	 * @param {Object} target DOM element to show/hide
	 * @param {Object} settings 
	 * 		object with custom defined settings for this plugin:
	 * 		@param {Number} zindexMin z-index CSS property applied to the trigger and target when hidden
	 * 		@param {Number} zindexMax z-index CSS property applied to the trigger and target when visible
	 */
	$.fn.toggleHover = function(target, settings){
		var defaults = {
			zindexMin: 0,
			zindexMax: 9000
		};
		
		var settings = $.extend({}, defaults, settings);
		
		var doHover = function(trigger, target){
			trigger.add(target)
				.bind('mouseover',function(){
					target.show().parent().css('z-index', settings.zindexMax);
				}).bind('mouseout',function(){
					target.hide().parent().css('z-index', settings.zindexOrig);
				});
		};
		
		/**
		 * Remember the target's original z-index property to assign when hovered out.
		 * If no z-index property exists, use the default minimum z-index specified in the defaults
		 * 
		 * @param {Object} target DOM element for which to extract z-index property
		 */
		var setupOrigZIndex = function(target){
			settings.zindexOrig = parseInt(target.css('z-index'),10) || defaults.zindexMin;	
		};
		
		if(target){
			_target = $(target);
			_trigger = this;
			setupOrigZIndex(_target);
			
			return doHover(_trigger, _target);
		}
		
		return this;
	};

	$.fn.hoverBlock = function(){
		var $this = $(this);
		var len = $this.length;
		
		
		for (var i=0; i < len; i++){
			$(this[i])
				.bind('mouseover', function(){
					return function(block){
						var $block = $(block);
						if($block.find('.hover').length < 1){
							var hoverBlock = getHoverBlock(block);
							var hoverEl = $('<div>').addClass('hover').append(hoverBlock);
							
							$block.addClass('hoverContainer').append(hoverEl).show();
						}
						
						else{
							$block.find('.hover').show();
						}
						$block.css('z-index',1000);
					}(this);
				})
				.bind('mouseout', function(){
					return function(block){
						$block = $(block);
						$block.find('.hover').hide();
						$block.css('z-index',1);
					}(this);
				});
		}
		
		function getHoverBlock(parentEl){
			//create a copy of the block contents
			var clone = parentEl.cloneNode(true);
			
			//container for the cloned content
			var $hoverBlock = $('<div>').addClass('hoverBlock');
			$hoverBlock.append(clone.childNodes);
			
			//copy the cloned nodes to the container
			
			
			return $hoverBlock;
		}
	};
	
	/**
	 * jQuery searchBoxBehavior plugin
	 * @author rcaliman@adobe.com
	 * @version 1.0
	 * 
	 * Toggle the visibility of default text value of an input element when the user clicks on it.
	 * Prevent submitting the parent form if the input has the default value;
	 * 
	 * @param {Object} settings 
	 * 		object with custom defined settings for this plugin:
	 * 		@param {String} validClass CSS class name to be applied to a valid input
	 * 		@param {Boolean} preventSubmit prevent submitting the parent form if the input not valid
	 */
	$.fn.searchBoxBehavior = function(settings){
		
		var defaults = {
			//CSS class name to be set when the input value is not default / whitespace
			validClass:"",
			//prevent submitting the parent form element if the input is blank or has the default value
			preventSubmit:true,
			//disable default behavior on focus.
			disableOnFocus:false
		};
		
		settings = $.extend({}, defaults, settings);		
		
		/**
		 * Check if the user input value is 
		 * not identical to the default and not whitespace
		 * 
		 * @return{Boolean}
		 */
		var isValidContent = function(){
			var content = $.trim(input.val());
			return (content.length>0 && content !== defaultVal);
		};
		
		
		//apply behavior only to text type inputs
		if ($(this).is(":text")){
			var input = this;
			var defaultVal = input.val();
			
			$(input)
				.bind('focus', function(){
					
					if(!settings.disableOnFocus) {
						//strip the default value from the input if present or take the user input
						var newVal = (input.val() === defaultVal)? "":input.val();

						input.val(newVal)
							.addClass(settings.validClass);
					}
				})
				.bind('blur',function(){
					if (!isValidContent()){
						input.val(defaultVal)
							 .removeClass(settings.validClass);
					}
				});
				
			if(settings.preventSubmit){
				this.parents('form')
					.bind('submit', function(){
						//prevent submitting the form
						return isValidContent();
					});
			}
		}
	};
	
	/**
	 * jQuery plugin for loading ADC accordion menu level markup.
	 * 
	 * The resource with the markup has the same name as the container's ID 
	 * and is located in the accordion data root folder variable
	 */		
	$.fn.handleAccordionData = function(){
		
		//location of the html to be loaded in the accordion menu
		var MARKUP_FOLDER = "/resources/html/accordion/";
		
		//'this' is the container for the accordion markup
		var $this = $(this);
		
		if($this.children().length < 1){
			
			//build the url for the markup resource according to the container's ID
			var href = MARKUP_FOLDER + $this.attr('id') + '.html';
			
			$.get(href, {}, function(data){
				$this.html(data).slideDown('fast');
			});
		}
		else{
			$this.slideDown('fast');
		}
	};
	
	/**
	 * jQuery showPrompt plugin 
	 * 
	 * @version 1.0
	 * 
	 * Toggles the visibility of any DOM element 
	 * and scrolls the window if the specified element is outside the current viewport
	 * 
	 * Based on jquery.scrollTo() plugin
	 */
	$.fn.showPrompt = function(e){
		this.fadeIn();
		var pos = this.offset();
		$.scrollTo(pos.top, 300);
		
		if(e && e.originalTarget){
			//get target position (the element that triggered the event)
			var tpos = $(e.originalTarget).offset();
		}
	};
	
	/**
	 * jQuery.ScrollTo - Easy element scrolling using jQuery.
	 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
	 * Dual licensed under MIT and GPL.
	 * Date: 3/9/2009
	 * @author Ariel Flesler
	 * @version 1.4.1
	 *
	 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
	 */
	(function($){var m=$.scrollTo=function(b,h,f){$(window).scrollTo(b,h,f)};m.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1};m.window=function(b){return $(window).scrollable()};$.fn.scrollable=function(){return this.map(function(){var b=this,h=!b.nodeName||$.inArray(b.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!h)return b;var f=(b.contentWindow||b).document||b.ownerDocument||b;return $.browser.safari||f.compatMode=='BackCompat'?f.body:f.documentElement})};$.fn.scrollTo=function(l,j,a){if(typeof j=='object'){a=j;j=0}if(typeof a=='function')a={onAfter:a};if(l=='max')l=9e9;a=$.extend({},m.defaults,a);j=j||a.speed||a.duration;a.queue=a.queue&&a.axis.length>1;if(a.queue)j/=2;a.offset=n(a.offset);a.over=n(a.over);return this.scrollable().each(function(){var k=this,o=$(k),d=l,p,g={},q=o.is('html,body');switch(typeof d){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px)?$/.test(d)){d=n(d);break}d=$(d,this);case'object':if(d.is||d.style)p=(d=$(d)).offset()}$.each(a.axis.split(''),function(b,h){var f=h=='x'?'Left':'Top',i=f.toLowerCase(),c='scroll'+f,r=k[c],s=h=='x'?'Width':'Height';if(p){g[c]=p[i]+(q?0:r-o.offset()[i]);if(a.margin){g[c]-=parseInt(d.css('margin'+f))||0;g[c]-=parseInt(d.css('border'+f+'Width'))||0}g[c]+=a.offset[i]||0;if(a.over[i])g[c]+=d[s.toLowerCase()]()*a.over[i]}else g[c]=d[i];if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],u(s));if(!b&&a.queue){if(r!=g[c])t(a.onAfterFirst);delete g[c]}});t(a.onAfter);function t(b){o.animate(g,j,a.easing,b&&function(){b.call(this,l,a)})};function u(b){var h='scroll'+b;if(!q)return k[h];var f='client'+b,i=k.ownerDocument.documentElement,c=k.ownerDocument.body;return Math.max(i[h],c[h])-Math.min(i[f],c[f])}}).end()};function n(b){return typeof b=='object'?b:{top:b,left:b}}})(jQuery);
})(jQuery);

/**
 * TabNavigator
 * Binds visibility state of targets by clicks on triggers
 * 
 * @param {Object} $
 * 				   reference to the jQuery object
 * 
 * @param {Object/Array} triggers 
 * 						 DOM objects that act as triggers of the tab navigator
 * @param {Object/Array} targets 
 *						 DOM objects that act as targets of the tab navigator
 * @param {Object} settings
 * 				   Object with user-defined settings that overwrite the defaults 
 */
var TabNavigator = function($){
	var defaults = {
		selectedClass:"selected" //CSS class for the selected trigger element
	};
	
	/**
	 * Method binds a click on the trigger element to the visibility of the corresponding target element.
	 * The trigger gets a "selected" 
	 */
	var bindTriggerToTarget = function(trigger, target){
		$(trigger).bind('click', function(e){
			
			selectTabPair(trigger, target);
			
			//prevent default browser behavior: follow link
			return false;
		});
	};
	
	/**
	 * Removes the "selected" class from all triggers
	 * 
	 * @return {void}
	 */
	var resetTriggers = function(){
		$triggers.removeClass(settings.selectedClass);
	};
	
	/**
	 * Hides all target elements
	 * 
	 * @return {void}
	 */
	var hideTargets = function(){
		$targets.hide();
	};
	
	/**
	 * Applies "selected" class to the trigger and shows the corresponding tab content.
	 */
	var selectTabPair = function(trigger, target){
		//remove selected class form all trigger elements
		resetTriggers();
		
		//hide all target elements
		hideTargets();
		
		//apply selected class to this trigger element
		$(trigger).addClass(settings.selectedClass);
		
		//display target element
		$(target).show();
	};
	
	return {
		init:function(){
			settings = $.extend({}, defaults, this.settings);

			$triggers = $(this.triggers);
			$targets = $(this.targets);
	
			//the number of triggers is different than the one for targets
			if ($triggers.length !== $targets.length){
				throw Error("$.fn.tabNavigator: incosistent ratio of triggers to targets.");
			}
			else{
				//bind the visibility tab trigger to the corresponding target via index
				$triggers.each(function(i){
					return bindTriggerToTarget(this, $targets[i]);
				});
				
				//select the default trigger/target pair
				selectTabPair($triggers[0], $targets[0])
			}
		
		}
	};
};
