/*------------------------------------------------------------------------------

	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 ie7 = (document.all && !window.opera && window.XMLHttpRequest) ? true : false;
var thunder = { client: { 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?
	// - treeMenuModes:Object - an array of modes
	// hook: .thunder-menu. .menu-item
	// output: toggling .item-on
	thunder.client.modify.treeMenu = function (wl, treeMenuModes) {
	    $('.thunder-menu').find('.menu-item').not('.item-separator').mouseenter(function () {
	        $(this).addClass('item-on');

	        if ($("body").hasClass("project-home")) {
	            var curItem = $(this);
	            $(".rollover", curItem).height($(".rollover", curItem).data("origHeight"));

	            if (ie7 && $(curItem).hasClass("cleveland")) { $(".engage").css("visibility", "hidden"); }
	            $("a img:first", this).stop(true, false).animate({ opacity: 0, height: $("a img:first", curItem).data("origHeight") + 30 }, 250);
	            $(".rollover", this).stop(true, false).animate({ opacity: 1, height: $(".rollover", curItem).data("origHeight") + 30 }, 250, function () {
	                $(".menu-ddbubble", curItem).css("display", "block");
	                $(".menu-ddbubble", curItem).stop(true, true).animate({ opacity: 1 }, 250);
	                $(this).css("height", "auto");
	            });
	            $(".menu-ddbubble .menu-item").mouseenter(function () {
	                $(this).css("background-position", $("a", this).position().left - 15 + "px 5px");
	            });
	        } else {
	            $(".rollover", this).stop(true, false).animate({ opacity: 1 }, 250);
	            $("img:first", this).stop(true, false).animate({ opacity: 0 }, 250);
	        }
	        if (treeMenuModes) for (var treeMenuMode in treeMenuModes) if (treeMenuModes[treeMenuMode].over) treeMenuModes[treeMenuMode].over(this);
	    }).mouseleave(function () {
	        $(this).removeClass('item-on');

	        if ($("body").hasClass("project-home")) {
	            var curItem = $(this);

	            if (ie7 && $(curItem).hasClass("cleveland")) { $(".engage").css("visibility", "visible"); }
	            $("a img:first", this).stop(true, false).animate({ opacity: 1, height: $("a img:first", curItem).data("origHeight") }, 250, function () { $(this).css("height", "auto"); $(this).siblings(".rollover").css("height", "auto").height('-=30'); });
	            $(".rollover", this).stop(true, false).animate({ opacity: 0, height: $("a img:first", curItem).data("origHeight") }, 250);
	            $(".menu-ddbubble", curItem).stop(true, true).animate({ opacity: 0 }, 250, function () { $(".menu-ddbubble", curItem).css("display", "none"); });
	        } else {
	            $(".rollover", this).stop(true, false).animate({ opacity: 0 }, 250);
	            $("img:first", this).stop(true, false).animate({ opacity: 1 }, 250);
	        }
	        if (treeMenuModes) for (var treeMenuMode in treeMenuModes) if (treeMenuModes[treeMenuMode].out) treeMenuModes[treeMenuMode].out(this);
	    }).each(function () {
	        if (treeMenuModes) for (var treeMenuMode in treeMenuModes) if (treeMenuModes[treeMenuMode].init) treeMenuModes[treeMenuMode].init(this);
	        return true;
	    });
	    if (wl === true) {
	        $('.thunder-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: .item-heading, .item-separator
	// additional output: adding and removing item-separator-on
	thunder.client.modes.fadeHeadingsTreeMenu = {
		transitionIn: 300,
		transitionOut: 100,
		over: function(obj)
		{
			$(obj).find('.menu-item-heading-over').animate({opacity: 1}, {duration: thunder.client.modes.fadeHeadingsTreeMenu.transition, queue: false});
		},
		out: function(obj)
		{
			$(obj).find('.menu-item-heading-over').animate({opacity: 0}, {duration: thunder.client.modes.fadeHeadingsTreeMenu.transition, queue: false});
		},
		init: function(obj)
		{
			$(obj).find('.menu-item-heading-over').css({opacity: 0});
		}
	}

	// mode interface for the treeMenuModes parameter of thunder.client.modify.treeMenu
	// hooks: .thunder-dropdown
	// additional output: adding and removing item-separator-on
	thunder.client.modes.fadeDropdownsTreeMenu = {
		transitionIn: 300,
		transitionOut: 100,
		over: function(obj)
		{
			$(obj).data('mayHide', false);
			$(obj).find('.menu-dropdown').removeClass('menu-dropdown-hidden').animate({opacity: 1}, {duration: thunder.client.modes.fadeHeadingsTreeMenu.transition, queue: false});
		},
		out: function(obj)
		{
			$(obj).data('mayHide', true);
			$(obj).find('.menu-dropdown').animate({opacity: 0}, {duration: thunder.client.modes.fadeHeadingsTreeMenu.transition, queue: false, complete: function(){ if($(obj).data('mayHide')==true) { $(this).addClass('menu-dropdown-hidden'); $(this).data('mayHide', false); } } });
		},
		init: function(obj)
		{
			$(obj).data('mayHide', false);
			$(obj).find('.menu-dropdown').css({opacity: 0});
		}
	}

	// mode interface for the treeMenuModes parameter of thunder.client.modify.treeMenu
	// hooks: .item-heading, .item-separator
	// additional output: adding and removing item-separator-on
	thunder.client.modes.separatorTreeMenu = {
		over: function(obj)
		{
			$(obj).next('.item-separator').addClass('item-separator-on');
			$(obj).prev('.item-separator').addClass('item-separator-on');
		},
		out: function(obj)
		{
			$(obj).next('.item-separator').removeClass('item-separator-on');
			$(obj).prev('.item-separator').removeClass('item-separator-on');
		}
	}

	// mode interface for the treeMenuModes parameter of thunder.client.modify.treeMenu
	// hooks: .item-heading, .item-separator
	// additional output: enables separators by replacing image extension .* with -over.*, -left.*, and -right.*
	thunder.client.modes.imageTreeMenu = {
		over: function(obj)
		{
			$(obj).find('.item-heading').each(thunder.client.utils.imageToOver);
			$(obj).prev('.item-separator').each(function() {thunder.client.utils.imageChanger('','-left')();});
			$(obj).next('.item-separator').each(function() {thunder.client.utils.imageChanger('', '-right')();});
		},
		out: function(obj)
		{
			$(obj).find('.item-heading').each(thunder.client.utils.imageFromOver);
			$(obj).prev('.item-separator').each(thunder.client.utils.imageChanger('-left', ''));
			$(obj).next('.item-separator').each(thunder.client.utils.imageChanger('-right', ''));
		}
	}

	// 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: .item-spinner, .item-item-double
	// additional output: controls height of .item-spinner within .menu-item so that .item-dropdown can be anchored to bottom
	thunder.client.modes.slideTreeMenu = {
		lineHeight: 17,
		padEach: 8,
		padAlso: 12,
		transition: 300,
		over: function(obj)
		{
			$(obj).children('.item-spinner').animate({height: (($(obj).children('.item-spinner').find('.sub-item-double').length * thunder.client.modes.slideTreeMenu.lineHeight) + ($(obj).children('.item-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('.item-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, scrollCallback)
	{
		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;
			_feature.scrollNow();
		}
		_feature.changeTo = function(newIndex)
		{
			clearTimeout(_feature.timeout);
			_feature.previndex = _feature.index;
			_feature.index = newIndex;
			if(_feature.index >= _feature.images.length) _feature.index = 0;
			if(_feature.index < 0) _feature.index = _feature.images.length - 1;
			if(_feature.index != _feature.previndex) _feature.scrollNow();
		}
		_feature.scrollNow = function()
		{
			if(scrollCallback) scrollCallback(_feature);
			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 * .95, queue: false});
			}
			_feature.precommence();
		}
		_feature.images = $('.thunder-scroll-feature').children('.thunder-scroll-viewport').find('img');
		_feature.images.css('left', '-'+scrollImageWidth+'px');
		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(thunder.client.utils.imageToOver).mouseleave(thunder.client.utils.imageFromOver);
	};

	// 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.utils
	Simple utility functions

------------------------------------------------------------------------------*/

	// deselects text; from www.kirupa.com/forum/showthread.php?t=348048
	thunder.client.utils.deselect = function()
	{
		if(document.selection && document.selection.empty)
		{
			document.selection.empty();
		}
		else if(window.getSelection)
		{
			sel=window.getSelection();
			if(sel && sel.removeAllRanges) sel.removeAllRanges();
		}
	}

	// returns a function that changes an image suffix
	thunder.client.utils.imageChanger = function(a, b)
	{
		return function()
		{
			var i;
			i = this.src;
			i = i.replace(a+'.jpg', b+'.jpg');
			i = i.replace(a+'.gif', b+'.gif');
			i = i.replace(a+'.png', b+'.png');
			this.src = i;
		};
	};
	
	thunder.client.utils.imageToOver = thunder.client.utils.imageChanger('', 'over');
	thunder.client.utils.imageFromOver = thunder.client.utils.imageChanger('over', '');

/*------------------------------------------------------------------------------

	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

------------------------------------------------------------------------------*/

	// detect browser
	thunder.client.workarounds.isIE6 = $.browser.msie && $.browser.version=="6.0";
	thunder.client.workarounds.isIE7 = $.browser.msie && $.browser.version=="7.0";

	thunder.client.workarounds.labelAsBrowser = function()
	{
		if($.browser.msie) $('body').addClass('using-ie');
		if(thunder.client.workarounds.isIE6) $('body').addClass('using-ie-6');
		if(thunder.client.workarounds.isIE7) $('body').addClass('using-ie-7');
	}

	// 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()
	{
		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;
			});
		}
	}







        var BrowserDetect = {
            init: function () {
                this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
                this.version = this.searchVersion(navigator.userAgent)
				|| this.searchVersion(navigator.appVersion)
				|| "an unknown version";
                this.OS = this.searchString(this.dataOS) || "an unknown OS";
            },
            searchString: function (data) {
                for (var i = 0; i < data.length; i++) {
                    var dataString = data[i].string;
                    var dataProp = data[i].prop;
                    this.versionSearchString = data[i].versionSearch || data[i].identity;
                    if (dataString) {
                        if (dataString.indexOf(data[i].subString) != -1)
                            return data[i].identity;
                    }
                    else if (dataProp)
                        return data[i].identity;
                }
            },
            searchVersion: function (dataString) {
                var index = dataString.indexOf(this.versionSearchString);
                if (index == -1) return;
                return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
            },
            dataBrowser: [
			{
			    string: navigator.userAgent,
			    subString: "Chrome",
			    identity: "Chrome"
			},
			{ string: navigator.userAgent,
			    subString: "OmniWeb",
			    versionSearch: "OmniWeb/",
			    identity: "OmniWeb"
			},
			{
			    string: navigator.vendor,
			    subString: "Apple",
			    identity: "Safari",
			    versionSearch: "Version"
			},
			{
			    prop: window.opera,
			    identity: "Opera"
			},
			{
			    string: navigator.vendor,
			    subString: "iCab",
			    identity: "iCab"
			},
			{
			    string: navigator.vendor,
			    subString: "KDE",
			    identity: "Konqueror"
			},
			{
			    string: navigator.userAgent,
			    subString: "Firefox",
			    identity: "Firefox"
			},
			{
			    string: navigator.vendor,
			    subString: "Camino",
			    identity: "Camino"
			},
			{		// for newer Netscapes (6+)
			    string: navigator.userAgent,
			    subString: "Netscape",
			    identity: "Netscape"
			},
			{
			    string: navigator.userAgent,
			    subString: "MSIE",
			    identity: "Explorer",
			    versionSearch: "MSIE"
			},
			{
			    string: navigator.userAgent,
			    subString: "Gecko",
			    identity: "Mozilla",
			    versionSearch: "rv"
			},
			{ 		// for older Netscapes (4-)
			    string: navigator.userAgent,
			    subString: "Mozilla",
			    identity: "Netscape",
			    versionSearch: "Mozilla"
			}
		],
            dataOS: [
			{
			    string: navigator.platform,
			    subString: "Win",
			    identity: "Windows"
			},
			{
			    string: navigator.platform,
			    subString: "Mac",
			    identity: "Mac"
			},
			{
			    string: navigator.userAgent,
			    subString: "iPhone",
			    identity: "iPhone/iPod"
			},
			{
			    string: navigator.platform,
			    subString: "Linux",
			    identity: "Linux"
			}
		]

        };

        BrowserDetect.init();

        window.$.client = { os: BrowserDetect.OS, browser: BrowserDetect.browser };
