/*------------------------------------------------------------------------------

	Filename             thunder.client.js
	Detail               Standard process library
	Author:              thunder::tech inc.
	License:             CLIENT is defined as the owner of online property from which this file resides or this code is referenced in.
						 ADDITIONAL PARTY is defined as anyone other than thunder::tech or CLIENT.
						 No right is granted to CLIENT or ADDITIONAL PARTY to sell, distribute, modify or otherwise transfer the following source code without explicit written permission by thunder::tech.

------------------------------------------------------------------------------*/

var thunder = { client: { project: { utils: {} }, modify: {}, modes: {}, checks: {}, workarounds: {} } };

/*------------------------------------------------------------------------------

	thunder.client.modify
	Create dynamic interactivity by modifying existing markup

	Each method is documented using the following terms.
	hook: JQuery/CSS hook that activates the functionality on an element
	output: The change that the functionality results in; almost always in the form of a JQuery/CSS hook change

------------------------------------------------------------------------------*/

	// method thunder.client.modify.selfLabelFields()
	// hook: .thunder-self-labeled
	// uses existing value attribute as label
	// sets thunder.markup:label attribute
	// output: toggling .thunder-label-cleared
	thunder.client.modify.selfLabelFields = function()
	{
		// Auto-label search field
		$(".thunder-self-labeled").each(function(i)
		{
			this.setAttribute('thunder.markup:label',this.value)
		}).focus(function()
		{
			if(this.value==this.getAttribute('thunder.markup:label'))
			{
				this.value='';
				$(this).addClass('thunder-label-cleared');
			}
		}).blur(function()
		{
			if(this.value=='')
			{
				this.value=this.getAttribute('thunder.markup:label');
				$(this).removeClass('thunder-label-cleared');
			}
		});	
	};

	// method thunder.client.modify.treeMenu()
	// parameters
	// - wl:Boolean ? hide window layer objects when menu is active?
	// - classAsHook:Boolean ? use .thunder-nav or li for child items?
	// - treeMenuModes:Object - an array of modes
	// hook: .thunder-tree-menu
	// output: toggling .thunder-nav-on
	thunder.client.modify.treeMenu = function(wl, classAsHook, treeMenuModes)
	{
		$('.thunder-tree-menu').find(classAsHook===true ? '.thunder-nav' : 'li').not('.thunder-nav-separator').mouseenter(function()
		{
			$(this).addClass('thunder-nav-on');
			if(treeMenuModes) for(var treeMenuMode in treeMenuModes) treeMenuModes[treeMenuMode].over(this);
		}).mouseleave(function()
		{
			$(this).removeClass('thunder-nav-on');
			if(treeMenuModes) for(var treeMenuMode in treeMenuModes) treeMenuModes[treeMenuMode].out(this);
		});
		if(wl===true)
		{
			$('.thunder-tree-menu').mouseenter(function()
			{
				thunder.client.workarounds.windowLayer(false);
			}).mouseleave(function()
			{
				thunder.client.workarounds.windowLayer(true);
			});
		}
	};
	
	// mode interface for the treeMenuModes parameter of thunder.client.modify.treeMenu
	// hooks: .thunder-nav-heading, .thunder-nav-separator
	// additional output: adding and removing thunder-nav-separator-on
	thunder.client.modes.separatorTreeMenu = {
		over: function(obj)
		{
			$(obj).next('.thunder-nav-separator').addClass('thunder-nav-separator-on');
			$(obj).prev('.thunder-nav-separator').addClass('thunder-nav-separator-on');
		},
		out: function(obj)
		{
			$(obj).next('.thunder-nav-separator').removeClass('thunder-nav-separator-on');
			$(obj).prev('.thunder-nav-separator').removeClass('thunder-nav-separator-on');
		}
	}

	// mode interface for the treeMenuModes parameter of thunder.client.modify.treeMenu
	// hooks: .thunder-nav-heading, .thunder-nav-separator
	// additional output: enables separators by replacing image extension .* with -over.*, -left.*, and -right.*
	thunder.client.modes.imageTreeMenu = {
		over: function(obj)
		{
			$(obj).find('.thunder-nav-heading').each(function() { var i; i = obj.src; i = i.replace('.jpg', '-over.jpg'); i = i.replace('.gif', '-over.gif'); i = i.replace('.png', '-over.png'); obj.src = i; });
			$(obj).prev('.thunder-nav-separator').each(function() { var i; i = obj.src; i = i.replace('.jpg', '-left.jpg'); i = i.replace('.gif', '-left.gif'); i = i.replace('.png', '-left.png'); obj.src = i; });
			$(obj).next('.thunder-nav-separator').each(function() { var i; i = obj.src; i = i.replace('.jpg', '-right.jpg'); i = i.replace('.gif', '-right.gif'); i = i.replace('.png', '-right.png'); obj.src = i; });
		},
		out: function(obj)
		{
			$(obj).find('.thunder-nav-heading').each(function() { var i; i = obj.src; i = i.replace('-over.jpg', '.jpg'); i = i.replace('-over.gif', '.gif'); i = i.replace('-over.png', '.png'); obj.src = i; });
			$(obj).prev('.thunder-nav-separator').each(function() { var i; i = obj.src; i = i.replace('-left.jpg', '.jpg'); i = i.replace('-left.gif', '.gif'); i = i.replace('-left.png', '.png'); obj.src = i; });
			$(obj).next('.thunder-nav-separator').each(function() { var i; i = obj.src; i = i.replace('-right.jpg', '.jpg'); i = i.replace('-right.gif', '.gif'); i = i.replace('-right.png', '.png'); obj.src = i; });
		}
	}

	// mode interface for the treeMenuModes parameter of thunder.client.modify.treeMenu
	// properties:
	// - lineHeight - the height of each line to account for
	// - padEach - the padding of each line to account for
	// - padAlso - additional padding on the dropdown to account for
	// - transition - the time of the transition
	// hooks: .thunder-nav-spinner, .thunder-nav-item-double
	// additional output: controls height of .thunder-nav-spinner within .thunder-nav so that .thunder-nav-dropdown can be anchored to bottom
	thunder.client.modes.slideTreeMenu = {
		lineHeight: 17,
		padEach: 8,
		padAlso: 12,
		transition: 300,
		over: function(obj)
		{
			$(obj).children('.thunder-nav-spinner').animate({height: (($(obj).children('.thunder-nav-spinner').find('.thunder-nav-item-double').length * thunder.client.modes.slideTreeMenu.lineHeight) + ($(obj).children('.thunder-nav-spinner').children().children().length * (thunder.client.modes.slideTreeMenu.lineHeight + thunder.client.modes.slideTreeMenu.padEach))+thunder.client.modes.slideTreeMenu.padAlso)+'px'}, {duration: thunder.client.modes.slideTreeMenu.transition, queue: false});
		},
		out: function(obj)
		{
			$(obj).children('.thunder-nav-spinner').animate({height: '0px'}, {duration: thunder.client.modes.slideTreeMenu.transition, queue: false});
		}
	}

	// method thunder.client.modify.scrollFeature()
	// parameters
	// - scrollImageWidth
	// - scrollImageTime (ms)
	// - scrollImageAnimationTime (ms)
	// hook: .thunder-scroll-feature [total object], .thunder-scroll-viewport [overflow container], .thunder-scroll-left [click], .thunder-scroll-right [click]
	// output: controlling style.left
	// returns: object with control functions
	thunder.client.modify.scrollFeature = function(scrollImageWidth, scrollImageTime, scrollImageAnimationTime)
	{
		var _feature = {};
		_feature.counting = false;
		_feature.index = -1;
		_feature.direction = 1;
		_feature.precommence = function()
		{
			_feature.timeout = setTimeout(_feature.change, scrollImageTime);
			_feature.counting = true;
		}
		_feature.commence = function()
		{
			if(_feature.counting==true)
			{
				_feature.counting = false;
				clearTimeout(_feature.timeout);
			}
			_feature.change();
		}
		_feature.next = function() { _feature.direction = 1; _feature.commence(); }
		_feature.previous = function() { _feature.direction = -1; _feature.commence(); }
		_feature.change = function()
		{
			_feature.previndex = _feature.index;
			_feature.index += _feature.direction;
			if(_feature.index >= _feature.images.length) _feature.index = 0;
			if(_feature.index < 0) _feature.index = _feature.images.length - 1;
			if(_feature.previndex>=0)
			{
				if(_feature.direction>0)
					$(_feature.images[_feature.previndex]).animate({'left': 0 - scrollImageWidth}, {duration: scrollImageAnimationTime, queue: false});
				else
					$(_feature.images[_feature.previndex]).animate({'left': scrollImageWidth}, {duration: scrollImageAnimationTime, queue: false});
			}
			if(_feature.index>=0)
			{
				if(_feature.direction>0)
					_feature.images[_feature.index].style.left = scrollImageWidth + 'px';
				else
					_feature.images[_feature.index].style.left = '-' + scrollImageWidth + 'px';
				$(_feature.images[_feature.index]).animate({'left': 0}, {duration: scrollImageAnimationTime * 0.8, queue: false});
			}
			_feature.precommence();
		}
		_feature.images = $('.thunder-scroll-feature').children('.thunder-scroll-viewport').find('img');
		_feature.images.css('left', '-483px');
		if(_feature.images.length>0) { _feature.commence(); _feature.images[0].style.left = 0; }
		$('.thunder-scroll-feature').children('.thunder-scroll-left').click(_feature.previous);
		$('.thunder-scroll-feature').children('.thunder-scroll-right').click(_feature.next);
		return _feature;
	};

	// method thunder.client.modify.customSelector()
	// parameters
	// - outputToPreviousInput:Boolean - optionally outputs to previous input's value
	// Include <input> (hidden if not .thunder-combo) as previous to .thunder-selector
	//           input[type=hidden]
	//           ul.thunder-selector
	// hooks: .thunder-selector (usually on an unordered list),
	// .thunder-combo on input for a typeable combo menu
	//      thunder-combo only works if outputToPreviousInput==true
	//           input[type=text].thunder-combo
	//           ul.thunder-selector
	// output: toggling .thunder-selected on children

	thunder.client.modify.dropSelector = function(outputToPreviousInput)
	{
		$('.thunder-selector').children().mouseenter(function()
		{
			$(this).parent().children().removeClass('thunder-selected');
			$(this).addClass('thunder-selected');
			if(outputToPreviousInput) $(this).parent().prev('input').val(this.innerHTML);
		}).click(function()
		{
			if($(this).parent().hasClass('thunder-selector-open')==false)
			{
				$(this).parent().addClass('thunder-selector-open');
			}
			else
			{
				$(this).parent().removeClass('thunder-selector-open');
			}
		});
		$('.thunder-combo').focus(function()
		{
			$(this).next().addClass('thunder-selector-open');
		}).blur(function()
		{
			$(this).next().removeClass('thunder-selector-open');
		});
	};

	// method thunder.client.modify.tabSet()
	// hooks: .thunder-tab, .thunder-tab-window
	// correlator: (tab) thunder.markup:item="css-hook" e.g. #this-tab-window or .these-tab-windows
	// output: toggling .thunder-tab-on, .thunder-tab-window-on
	// parameters: c:Function; callback(s) where s:String is thunder.markup:item
	thunder.client.modify.tabSet = function(c)
	{
		$('.thunder-tab').click(function()
		{
			$('.thunder-tab').removeClass('thunder-tab-on');
			$('.thunder-tab-window').removeClass('thunder-tab-window-on');
			$(this).addClass('thunder-tab-on');
			$(this.getAttribute('thunder.markup:item')).addClass('thunder-tab-window-on');
			if(c) c(this.getAttribute('thunder.markup:item'));
		});
	}

	// method thunder.client.modify.linkOptions()
	// hook: .thunder-link-options
	// output: changes window.location to value attribute
	thunder.client.modify.linkOptions = function()
	{
		$('.thunder-link-options').change(function()
		{
			var u, i;
			for(i=0;i<this.options.length;i++)
			{
				if(this.options[i].selected==true) window.location = this.options[i].value;
			}
		});
	}

	// method thunder.client.modify.rollImages()
	// hook: .thunder-roll-over
	// output: modifies src to and and remove -over from .jpg, .gif, .png
	thunder.client.modify.rollImages = function()
	{
		$('.thunder-roll-over').mouseenter(function()
		{
			var i;
			i = this.src;
			i = i.replace('.jpg', '-over.jpg');
			i = i.replace('.gif', '-over.gif');
			i = i.replace('.png', '-over.png');
			this.src = i;
		}).mouseleave(function()
		{
			var i;
			i = this.src;
			i = i.replace('-over.jpg', '.jpg');
			i = i.replace('-over.gif', '.gif');
			i = i.replace('-over.png', '.png');
			this.src = i;
		});
	};

	// method thunder.client.modify.requireFields()
	// hooks: .thunder-required, .thunder-requiree
	// output: modifies the requiree's disabled property
	//			adds .thunder-requiree-met, .thunder-required-met when requirements met
	thunder.client.modify.requireFields = function()
	{
		var requireChecker = function()
		{
			var disableRequirees = false;
			$('.thunder-required').each(function()
			{
				if(thunder.client.checks.selfLabelFilled(this)==false)
				{
					disableRequirees = true;
					$(this).removeClass('thunder-required-met');
				}
				else
				{
					$(this).addClass('thunder-required-met');
				}
			});
			$('.thunder-requiree').each(function()
			{
				if(disableRequirees==true)
				{
					$(this).removeClass('thunder-requiree-met');
				}
				else
				{
					$(this).addClass('thunder-requiree-met');
				}
				this.disabled = disableRequirees;
			});
		};
		requireChecker();
		$('.thunder-required').change(requireChecker);
		$('.thunder-required').keypress(requireChecker);
	};

/*------------------------------------------------------------------------------

	thunder.client.checks
	Boolean conditional functions

------------------------------------------------------------------------------*/

	// method thunder.client.checks.selfLabelFilled(field):Boolean
	// works on both self-labeled via this script and non-self-labeled fields
	// returns: true if filled, false if empty
	thunder.client.checks.selfLabelFilled = function(field)
	{
		if(field.value===''||field.value==field.getAttribute('thunder.markup:label'))
		{
			return false;
		}
		else
		{
			return true;
		}
	}

/*------------------------------------------------------------------------------

	thunder.client.workarounds
	Browser-specific workarounds

------------------------------------------------------------------------------*/

	// is IE 6?
	thunder.client.workarounds.isIE6 = $.browser.msie && $.browser.version=="6.0";

	// method thunder.client.workarounds.windowLayer
	// b:Booolean ? show window layer objects : hide them
	thunder.client.workarounds.windowLayer = function(b)
	{
		if(thunder.client.workarounds.isIE6)
		{
			if(b==true)
			{
				$(document).find('select').css('visibility', 'visible');
			}
			else
			{
				$(document).find('select').css('visibility', 'hidden');
			}
		}
	}

	// method thunder.client.workarounds.alphaImages
	// replaces .png in image sources and background images with .gif
	thunder.client.workarounds.alphaImages = function(b)
	{
		if(thunder.client.workarounds.isIE6)
		{
			$(document).find('img').add('input').each(function(elementIndex, elementObject)
			{
				var elementSrc;
				elementSrc = elementObject.src;
				elementSrc = elementSrc.replace('.png', '.gif');
				elementObject.src = elementSrc;
				return true;
			});
			$(document).find('*').each(function(elementIndex, elementObject)
			{
				var elementBgi;
				elementBgi = $(elementObject).css('background-image');
				elementBgi = elementBgi.replace('.png', '.gif');
				$(elementObject).css('background-image', elementBgi)
				return true;
			});
		}
	}
