var pseudoClassAttach, SearchBot, MessageHandler, ErrorHandler, FormValidator, CookieJar, IdiotBox;
var sortHeaders = { };
var Attach = { };

/* Global Functions
------------------------------------------------------------------------- */

	// Interstitial
	function showInterstitial(id) {
		tb_show("","#TB_inline?height=250&width=400&inlineId=" + id,"");
	}
	
	// showStoreLoader
	function showStoreLoader() {
		$(document.body).popup({isModal:true, isLoaderStore:true, fixCenter:true});
	}
	// Check user cookie and respond
	function recognizeUser() {
		if(CookieJar.getCookie('firstName')) {
			$('body').attr('id','registered');
			$('.uFirstName').text(CookieJar.getCookie('firstName'));
		}
		if(CookieJar.getCookie('username')) {
			$('.uUsername').val(CookieJar.getCookie('username')); 
		}
	}
	
	//Builds links to get to thickboxes
	function thickBoxLinkBuilder(properties) { 
	 	// attributes in the url causes problems, remove them.
		requested_path = location.href.replace(location.search, '');
		requested_path = requested_path.replace(location.hash, '');
		
		queryString = [];
		$.each(properties, function(index, value) { 
			if(index != 'targetLinkClass') { queryString.push(index + '=' + value) }
		});
		
		$('a.' + properties.targetLinkClass).attr('href', requested_path + '#TB_inline?' + queryString.join('&amp;'));
	}
	
	// So an iframe can change the parent's url
	function change_url(url) {
	    document.location=url;
	}	
	
	// Automates JavaScript inheritance, See PopupClass for example
	function inherit(subclass, superclass) {
		var temp = function() {};
		temp.prototype = superclass.prototype;
		subclass.prototype = new temp();
	}
	
/* PseudoClass - TESTED
------------------------------------------------------------------------- */
	function PseudoClass(autotarget) {
		this.targets = [];
		if((autotarget != undefined) && (autotarget == true)) {
			this.attach(true);
		}
	}
	PseudoClass.prototype.addTarget = function(target) {
		this.targets.push(target);
		return target;
	}
	PseudoClass.prototype.attach = function(autotarget) {
		var self = this;
		if((autotarget != undefined) && (autotarget == true)) {
			$('.js_pseudo_class').each(function(index, element) {
				self.byTarget(element);
			});
		}
		jQuery.each(self.targets, function(index, target) {
			self.byTarget(target);
		});
		self.targets = null;
	}
	PseudoClass.prototype.byTarget = function(target) {
		var children = $(target).children();
		if(children.length > 1) {
			$(children.get(0)).addClass('first-child');
			$(children.get(children.length - 1)).addClass('last-child');
		} else if(children.length == 1) { 
			$(children.get(0)).addClass('only-child');
		}
	}
	
/* MboxPropertyBuilderClass - TESTED
------------------------------------------------------------------------- */
	function MboxPropertyBuilderClass() {
		this.properties = {};
		this.property_delimiters = {};
		this.default_delimiter = ',';
	}
	MboxPropertyBuilderClass.prototype.set = function(key, value, options) {
		this.properties[key] = [];
		if(typeof value == "string") {
			this.properties[key].push(value);
		} else {
			var self = this;
			jQuery.each(value, function(index, value) {
				self.properties[key].push(value);
			});
		}
		if(options === undefined) {
			this.property_delimiters[key] = this.default_delimiter;
		} else {
			this.property_delimiters[key] = options.delimiter;
		}
	}
	MboxPropertyBuilderClass.prototype.appendValue = function(key, value) {
		if(typeof this.properties[key] != "object") {
			this.set(key, value);
		} else {
			this.properties[key].push(value);
		}
	}
	MboxPropertyBuilderClass.prototype.getAllFormattedProperties = function() {
		var properties = [];
		for(var key in this.properties) {
			var property = this.getFormattedProperty(key);
			properties.push(property);
		}
		return properties;
	}
	MboxPropertyBuilderClass.prototype.getFormattedProperty = function(key) {
		var key_equals = key + "=";
		if(this.properties[key] === undefined) {
			 return key_equals;
		} else {
			var self = this;
			jQuery.each(this.properties[key], function(index, value) {
				if(index == 0) {
					key_equals += value;
				} else {
					key_equals += self.property_delimiters[key] + value
				}
			});
			return key_equals;
		}
	}
	
/* PopupClass (Base Class) - TESTED
------------------------------------------------------------------------- */
	function PopupClass(link, launch_now) {
		if(link !== undefined) {
			if(typeof link == "string") {
				var link = $("#"+link);
			}
			this.href = link.attr('href');
			this.title = link.attr('title');
			this.properties = this.setProperties();
			if(launch_now !== undefined && launch_now == true) {
				return this.launch();
			}
		}
	}
	PopupClass.prototype.setProperties = function() {
		return { scrollbars:true, toolbar:false, status:false, width:800, height:600, resizable:true };	
	}
	PopupClass.prototype.boolToInt = function(bool) {
		return (bool ? 1 : 0);
	}
	PopupClass.prototype.buildPropertiesString = function() {
		var properties = "";
		for(var key in this.properties) {
			if(typeof this.properties[key] == "boolean") {
				this.properties[key] = this.boolToInt(this.properties[key]);
			}
			properties = properties + key + '=' + this.properties[key] + ',';
		}
		// return string minus the last comma
		return properties.substring(0, (properties.length - 1));
	}
	PopupClass.prototype.launch = function() {
		return window.open(this.href, this.title, this.buildPropertiesString());
	}
	
	/* Legal Popup (Inherits Popup Class) ------------------------------------ */
	LegalPopupClass = function(link, launch_now) {
		PopupClass.call(this, link, launch_now);
	}
	inherit(LegalPopupClass, PopupClass);
	LegalPopupClass.prototype.setProperties = function() {
		return { scrollbars:true, toolbar:false, status:false, width:360, height:300, resizable:true };	
	}
	
	/* PartView Popup (Inherits Popup Class) ------------------------------------ */
	PartViewPopupClass = function(link, launch_now) {
		PopupClass.call(this, link, launch_now);
	}
	inherit(PartViewPopupClass, PopupClass);
	PartViewPopupClass.prototype.setProperties = function() {
		return { scrollbars:false, toolbar:false, status:false, width:470, height:510, resizable:false };	
	}
	
/* AttachOnceClass - TESTED
------------------------------------------------------------------------- */
	function AttachOnceClass() {
		this.behavior($('.' + this.target_class));
		this.clean();	
	}
	AttachOnceClass.prototype.clean = function() {
		$('.' + this.target_class).removeClass(this.target_class);
	}
	AttachOnceClass.prototype.behavior = function() {
		// Will be overwritten.
	}
	AttachOnceClass.add = function(name, target_class, behavior) {
		Attach[name] = function() {
			this.target_class = target_class;
			AttachOnceClass.call(this);
		}
		inherit(Attach[name], AttachOnceClass);
		Attach[name].prototype.behavior = behavior;
	}
	
	/* PromptText Attacher --------------------------------- */
	AttachOnceClass.add('PromptText', 'js_promptText', function(jquery_selector) {
		jquery_selector.focus(function() {
			if($(this).val() == $(this).attr('title')) {
				$(this).val('');
			}
		});
		jquery_selector.blur(function resetField() {
			if(!$(this).val()) { 
				$(this).val($(this).attr('title'));
			}
		});
	});
	
	/* PartViewPopup Attacher ------------------------- */
	AttachOnceClass.add('PartViewPopup', 'js_partViewPopup', function(jquery_selector) {
		jquery_selector.click(function() {
			new PartViewPopupClass($(this), true);
			return false;
		});
	});
	
	/* LegalPopup Attacher -------------------------------- */
	AttachOnceClass.add('LegalPopup', 'js_legalPopup', function(jquery_selector) {
		jquery_selector.click(function() {
			new LegalPopupClass($(this), true);
			return false;
		});
	});	

	/* Clone and Insert Attacher -------------------------------- */
	AttachOnceClass.add('CloneAndInsert', 'js_clone_and_insert', function(jquery_selector) {
		// TODO: conside refactoring into a class
		jquery_selector.click(function() {
			var parent = $(this).parent();
			var insert = parent.find('.js_insert');
			var clone = parent.find('.js_clone').clone(true);
			var count = insert.children().length + 2;
			
			// Recursively make attributes unique in cloned html
			function uniquifyAttributes(children) {
				jQuery.each(children, function(index, child) {
					child = $(child);
					if(child.children()) {
						uniquifyAttributes(child.children());
					}
					jQuery.each(['name','id','for'], function(index, attribute) {
						if(child.attr(attribute)) {
							var unique = child.attr(attribute) + count;
							child.attr(attribute, unique);
						}
					});
				});
			}
			uniquifyAttributes(clone.children());
			
			clone.removeClass('js_clone').addClass('js_cloned').css('display','block').appendTo(insert);
			new Attach.RemoveClone();
			
			return false;
		});
	});		
	
	/* Remove Clone Attacher -------------------------------- */
	AttachOnceClass.add('RemoveClone', 'js_remove_clone', function(jquery_selector) {
		jquery_selector.click(function() {
			var clone = $(this).parent();
			clone.parent('.js_cloned').remove();
			return false;
		});
	});		
	

$(document).ready(function() {

	/* SearchBot
	------------------------------------------------------------------------- */
	SearchBot = {
		currentForm: null,
		searchBox: $('#searchBox'),
		animating: false,
		init: function() {
			SearchBot.currentForm = null;
			if($('body').hasClass('home')) {
				SearchBot.show('model');
			}
		},
		show: function(formName) {
			if(formName != SearchBot.currentForm && SearchBot.animating === false) {
				SearchBot.animating = true;
				var formSize 		= $('#' + formName).height();
				var targetFormTab	= $('.' + formName);
				var targetFormDiv	= $('#' + formName);
				if(SearchBot.currentForm !== null) {
					var currentFormTab = $('.' + SearchBot.currentForm);
					var currentFormDiv = $('#' + SearchBot.currentForm);
					currentFormTab.removeClass(SearchBot.currentForm + 'On');
					targetFormTab.addClass(formName + 'On');
					
					currentFormDiv.hide();
					targetFormDiv.css('height', formSize);					
					targetFormDiv.show();
					SearchBot.currentForm = formName; 
					SearchBot.toggleBlur(formName);
					SearchBot.animating = false;
				} else {
					targetFormTab.addClass(formName + 'On');
					targetFormDiv.css('height', formSize);
					targetFormDiv.show();
					SearchBot.currentForm = formName; 
					SearchBot.toggleBlur(formName);
					SearchBot.animating = false;
				}
			}
		},
		collapse: function() {
			if(SearchBot.searchBox.find('fieldset').hasClass('ERROR')) {
				ErrorHandler.removeAllErrors();
			}
			$('#' + SearchBot.currentForm).hide();
			$('.' + SearchBot.currentForm).removeClass(SearchBot.currentForm + 'On');
			SearchBot.currentForm = null;
		},
		toggleBlur: function(formName) { 
			switch(formName) { 
				case 'part': 	$('#fldSBPartNumber').focus();
								break;
				case 'model':	$('#fldSBModelNumber').focus();
								break;
			}
		}
	};

	/* MessageHandler
	------------------------------------------------------------------------- */	
	MessageHandler = { 
		types: ['success','info'],
		messages: {},
		headings: { 
			/* Override headings, if needed. Example...
			information: 'Here is some Information!'
			*/
		},
		defaultType: 'success',
		handlerErrors: { 
			messageTypeNotFound: "don't know that type of message"
		},
		init:function() { 
			/* Dynamically Create Array and Heading for Message Types */
			for(i = 0; i < MessageHandler.types.length; i++ ) { 	
				MessageHandler.messages[MessageHandler.types[i]] = [];
				if(MessageHandler.headings[MessageHandler.types[i]] === undefined) {
					MessageHandler.headings[MessageHandler.types[i]] = MessageHandler.types[i] + '.';
				}
			}
			return true;
		},
		addMessage:function(message,type) {
			if(type == undefined) { type = MessageHandler.defaultType; }
			MessageHandler.messages[type].push(message);
			return true;
		},
		hasMessages:function(type) { 
			if(type == undefined) { type = MessageHandler.defaultType; }
			return (MessageHandler.messages[type].length > 0 ? true : false);
		},
		displayMessages:function(type) {
			if(type == undefined) { type = MessageHandler.defaultType; }
			MessageHandler.page.removeMessages();
			ErrorHandler.removeActionErrors();
			
			/* Setup Message Heading */ 
			var typeFound = MessageHandler.messages.hasOwnProperty(type);
			var heading = ((typeFound) ? MessageHandler.headings[type] : MessageHandler.handlerErrors.messageTypeNotFound);
			heading = heading.substring(0,1).toUpperCase() + heading.substring(1, heading.length);
			
			/* Display Messages */
			MessageHandler.page.displayMessageTemplate(heading, type);
			if(typeFound) {
				for(i = 0; i < MessageHandler.messages[type].length; i++) {
					MessageHandler.page.displayMessage(MessageHandler.messages[type][i]);
				}
				MessageHandler.messages[type] = [];	 
			}
			return true;
		},
		page: {
			displayMessageTemplate:function(heading, type) {
				var messageTxt = '<div id="messageWrapper" style="margin-bottom: 20px;"><div id="messageContainer" class="moduleMessage '+type+'">' + '<h3>'+heading+'</h3>' + '<div class="messages"></div>' + '</div></div>';
				if($('#subContent').length > 0){
					$('#subContent').prepend(messageTxt);
				}
				else{
					$('#primaryContent h2').after(messageTxt);
				}
				return true;	
			},
			displayMessage:function(message) { 
				$('div.messages').append('<p>' + message + '</p>');
				return true;
			},
			removeMessages:function() {
				$('#messageWrapper').remove();
				return true;
			}
		}
	};

	/* ErrorHandler
	------------------------------------------------------------------------- */
	ErrorHandler = {
		fieldErrors: [],
		actionErrors: [],
		formErrorMessage: 'There were errors in the form',
		overlapTolerance:10,
		init: function() {
			ErrorHandler.fieldErrors = [];
			ErrorHandler.actionErrors = [];
		},
		addFieldError: function(fieldName,errorMessage,context) {
			context = context == undefined || context == '' ? $('#page') : $(context);
			ErrorHandler.fieldErrors.push({
				field: context.find('[name=' +  fieldName + ']'),
				fieldset: context.find('[name=' +  fieldName + ']').parents('fieldset'),
				errorMessage: errorMessage.replace("[","").replace("]","")
			});
		},
		addActionError: function(errorMessage) {
			ErrorHandler.actionErrors.push(errorMessage);
		},
		hasErrors: function() {
			if(ErrorHandler.hasFieldErrors() || ErrorHandler.hasActionErrors()) {
				return true;
			} else {
				return false;
			}
		},
		hasFieldErrors: function() {
			return (ErrorHandler.fieldErrors.length > 0 ? true : false);
		},
		hasActionErrors: function() {
			return (ErrorHandler.actionErrors.length > 0 ? true : false);
		},
		displayFieldErrors: function() {
			ErrorHandler.removeFieldErrors();
			var i = 0;
			var zipCodeId = 'zipCode'; 
			var errorFlagRightStyle = 'errorFlagRight';
			// First create the flag for each fieldset that contains a field error
			for(i = 0; i < ErrorHandler.fieldErrors.length; i++) {
			 	if(!ErrorHandler.fieldErrors[i].fieldset.hasClass('ERROR')) {
					if(ErrorHandler.fieldErrors[i].fieldset.hasClass('errorFlagOnLeft')) {
						ErrorHandler.fieldErrors[i].fieldset.addClass('ERROR').prepend('<div class="errorFlagLeft errorFlag png_fix"><p></p></div>');
					} else {
						if(ErrorHandler.fieldErrors[i].field[0]){
							
						if(zipCodeId == ErrorHandler.fieldErrors[i].field[0].id)
							errorFlagRightStyle = 'errorFlagRightZipCode';
						//Prevent blank messages
						if(ErrorHandler.fieldErrors[i].errorMessage.split(" ").join("") != "")
							ErrorHandler.fieldErrors[i].fieldset.addClass('ERROR').append('<div class=" ' + errorFlagRightStyle + ' errorFlag png_fix"><p></p></div>');
						if(ErrorHandler.fieldErrors[i].field[0].tagName.toLowerCase().indexOf("select") != -1){
							if($("#fldOtherIndustry", $(ErrorHandler.fieldErrors[i].field[0]).parent()).length == 0)
								ErrorHandler.fieldErrors[i].fieldset.find("." + errorFlagRightStyle).css("right", "-165px");
							else 
								ErrorHandler.fieldErrors[i].fieldset.find("." + errorFlagRightStyle).css("right", "-140px");
							$(ErrorHandler.fieldErrors[i].field[0]).change(function(event){
								var field = $(this).parent().find("." + errorFlagRightStyle);
								if(this.selectedIndex == 0){
									if(field.length > 0){
										field.css("display", "block");
										$(this).addClass("error");
									}
								} else{
									field.remove();
									$(this).removeClass("error");
								}
							});
						}
						
						
					}
					}
				}
			}
			
			// Populate each flag with its messages, highlight the field
			for(i = 0; i < ErrorHandler.fieldErrors.length; i++) {
				// Determine if the flag is on the right or left (default right)
				var errorFlagClass = (ErrorHandler.fieldErrors[i].fieldset.hasClass('errorFlagOnLeft')) ? 'errorFlagLeft' : 'errorFlagRight';
				if(errorFlagRightStyle == 'errorFlagRightZipCode'){
					errorFlagClass = errorFlagRightStyle;
				}


				// Add errors messages to the flag
				//if(ErrorHandler.fieldErrors[i].errorMessage != "")
				// Prevent blank messages
				if(ErrorHandler.fieldErrors[i].errorMessage.split(" ").join("") != "")
					ErrorHandler.fieldErrors[i].fieldset.find('div.' + errorFlagClass + ' p').append('<span class="errorMessage">' + ErrorHandler.fieldErrors[i].errorMessage + '</span>');
				// Highlight the field
				if(ErrorHandler.fieldErrors[i].errorMessage.split(" ").join("") != "")
					ErrorHandler.fieldErrors[i].field.addClass('error');

				// Re-position the flag because the height has changed
				var flagHeight = ErrorHandler.fieldErrors[i].fieldset.find('div.' + errorFlagClass).height() + 10;
				ErrorHandler.fieldErrors[i].fieldset.find('div.' + errorFlagClass).css('bottom', ErrorHandler.fieldErrors[i].fieldset.height()/2 - flagHeight/2);
				ErrorHandler.posFieldError(ErrorHandler.fieldErrors[i].fieldset);
			}
			//ErrorHandler.overlapCheck();
			
			// Clear the field errors array for next submission
			ErrorHandler.fieldErrors = [];
		},
		
		posFieldError : function(fieldSet){
			//this method was created in order to add Functionality to the liquid layout 
		},
		
		displayFieldErrorsLayout: function(){
			ErrorHandler.removeFieldErrors();
			
			var i = 0;
			var errorFlagRightStyle = 'errorFlagRightCommercial';
			// First create the flag for each fieldset that contains a field error
			for(i = 0; i < ErrorHandler.fieldErrors.length; i++) {
			 	if(!ErrorHandler.fieldErrors[i].fieldset.hasClass('ERROR')) {
			 		var styleById = ErrorHandler.fieldErrors[i].fieldset[0].parentNode.id;
						ErrorHandler.fieldErrors[i].fieldset.addClass('ERROR').append('<div class=" ' + errorFlagRightStyle + " " + styleById + ' errorFlag"><p></p></div>');
				}
			}
			
			// Populate each flag with its messages, highlight the field
			for(i = 0; i < ErrorHandler.fieldErrors.length; i++) {
				var errorFlagClass = errorFlagRightStyle;

				// Add errors messages to the flag
				if(ErrorHandler.fieldErrors[i].errorMessage != "")
					ErrorHandler.fieldErrors[i].fieldset.find('div.' + errorFlagClass + ' p').append('<span class="errorMessage">' + ErrorHandler.fieldErrors[i].errorMessage + '</span>');
				// Highlight the field
				ErrorHandler.fieldErrors[i].field.addClass('error');

				// Re-position the flag because the height has changed
				var flagHeight = ErrorHandler.fieldErrors[i].fieldset.find('div.' + errorFlagClass).height();
				ErrorHandler.fieldErrors[i].fieldset.find('div.' + errorFlagClass).css('bottom', ErrorHandler.fieldErrors[i].fieldset.height()/2 - flagHeight/2);
			}
			//ErrorHandler.overlapCheck();
			
			// Clear the field errors array for next submission
			ErrorHandler.fieldErrors = [];
		
		},
		
		overlapCheck: function() { 
			errorFlags = $('.errorFlag');
			errorFlags.each(function(a) { 
				topFlag = $(this);
				topFlag_top = topFlag.offset().top;
				topFlag_bottom = topFlag.offset().top + topFlag.height();
				errorFlags.each(function(b) {
					if(b > a) {
						bottomFlag_top = $(this).offset().top; 
						if((bottomFlag_top < (topFlag_bottom - ErrorHandler.overlapTolerance)) && (bottomFlag_top > topFlag_top)) {						
							// NOTE: Overlap classes has been removed from CSS.
							topFlag.addClass((((topFlag.hasClass('errorFlagRight') || topFlag.hasClass('errorFlagRightZipCode')) ? 'errorFlagRight_overlapped' : 'errorFlagLeft_overlapped')));
						}
					}
				});
			});
			
			// Make sure error flag are readable, if they overlap
			//z_index =21;
			//$('div.errorFlag').mouseover(function() { $(this).parents('fieldset').css('z-index',z_index); z_index++; }); 
		},
		displayActionErrors: function() {
			ErrorHandler.removeActionErrors();
			MessageHandler.page.removeMessages();
			$('#primaryContent h2').after('<div id="errorWrapper"><div id="actionErrorContainer" class="moduleActionError alert">' + '<h3>Error</h3>' + '<div class="actionErrors"></div>' + '</div></div>');
			for(var i = 0; i < this.actionErrors.length; i++) {
				$('div.actionErrors').append('<p>' + this.actionErrors[i] + '</p>');
			}
			// Clear the action errors array for next submission
			ErrorHandler.actionErrors = [];
			return true;
		},
		displayErrors: function() {
			if(ErrorHandler.hasFieldErrors()) {
				ErrorHandler.displayFieldErrors();
                //action errors should not be shown for feedbakc form
				if(null != FormValidator.form){
	                if (FormValidator.form.id != "feedback_form") ErrorHandler.addActionError(ErrorHandler.formErrorMessage);   
				}
			}
			if(ErrorHandler.hasActionErrors()) {
				ErrorHandler.displayActionErrors();
			}
		},
		displayErrorsLayout: function() {
			if(ErrorHandler.hasFieldErrors()) {
				ErrorHandler.displayFieldErrorsLayout();
				ErrorHandler.addActionError(ErrorHandler.formErrorMessage);
			}
			if(ErrorHandler.hasActionErrors()) {
				ErrorHandler.displayActionErrors();
			}
		},
		
		removeAllErrors: function() {
			ErrorHandler.removeFieldErrors();
			ErrorHandler.removeActionErrors();
			return true;
		},
		removeFieldErrors: function() {
			$('.ERROR').removeClass('ERROR');
			$('.error').removeClass('error');
			$('div.errorFlagLeft').remove();
			$('div.errorFlagRight').remove();
			$('div.errorFlagRightCommercial').remove();			
			$('div.errorFlagRightZipCode').remove();
			
			if (navigator.userAgent.toLowerCase().indexOf('msie 6') != -1)
			{
				$('fieldset shape').remove();
			}
			return true;
		},
		removeActionErrors: function() {
			$('#errorWrapper').remove();
			return true;
		}/*,
		removeFieldError: function(jObjField) {
			jObjField.removeClass('error').parents('fieldset').find('span.' + jObjField.attr('name')).remove();
			if(jObjField.parents('fieldset').find('span.errorMessage')) {
				jObjField.parents('fieldset').find('div.errorFlag').remove();
			}
		}*/
	};

	/* FormValidator
	------------------------------------------------------------------------- */
	FormValidator = {
		hasErrors: false,
		form: null,
		init: function() {
			FormValidator.hasErrors = false;
			FormValidator.form = null;
		},
		validate: function(form) {
			FormValidator.form = form;
			// Apply validation rules to each
			$(form).find('input:enabled,textarea:enabled,select:enabled').each(function() {
				for(var rule in FormValidator.validationRules) { if(FormValidator.validationRules.hasOwnProperty(rule)) {
					FormValidator.validationRules[rule]($(this));						
				}}
			});
			FormValidator.specialSymbols();
				
			if(FormValidator.hasErrors) {
				ErrorHandler.displayErrors();
				FormValidator.init();
				return false;
			} else {
				FormValidator.init();
				return true;
			}
		},
		helpers: {
			getLabel: function(oField) {
				// Correct Behavior
				if($('[for=' + oField.attr('id') + ']').length) {
					return $('[for=' + oField.attr('id') + ']').html().replace('*','')
				} 
				// Okay Behavior
				else if($('[for=' + oField.attr('name') + ']').length) {
					return $('[for=' + oField.attr('name') + ']').html().replace('*','')
				} 
				// Forgotten Behavior
				else { 
					return oField.attr('name')
				}
				//return ($('[for=' + oField.attr('name') + ']').length ? $('[for=' + oField.attr('name') + ']').html().replace('*','') : oField.attr('name'));
			}
		},
		specialSymbols: function(){
			var rexp = new RegExp("[^0-9a-zA-Z\-\*\ \.\']");
			var elements = $(".spec_symbols_validation:visible");
			for(var i = 0; i < elements.length; i++){
	    		var matches = rexp.exec($(elements[i]).val());
	    		if(matches){
					ErrorHandler.addFieldError($(elements[i]).attr("name"), 'Special symbols should be removed', FormValidator.form);
					FormValidator.hasErrors = true;    			    		
	    		}
			}
		},
		
		validationRules:{
			// Required fields
			/* USAGE: <input type="text" class="required" /> */
			required: function(field) {
				if(field.hasClass('required')) {
					switch (field.attr('type')) {
						case 'radio':
							if(!$("input[name='"+field.attr('name')+"']").is(':checked')) {
								ErrorHandler.addFieldError(field.attr('name'), 'Please provide a response to this question.', $('.firstRadioOption'));
								FormValidator.hasErrors = true;  
							}
							break;
						case 'checkbox':
							if(!field.attr('checked')) {
								if(field.hasClass('nicorTerms'))
									ErrorHandler.addFieldError(field.attr('name'), 'You must accept ' + field.attr('name') + ' Terms and Conditions to order this service.', FormValidator.form);
								else if (field.hasClass('returnsMessage'))
									ErrorHandler.addFieldError(field.attr('name'), 'Please provide a response to this question.', FormValidator.form);
								else if (field.hasClass('promoDetail'))
									ErrorHandler.addFieldError(field.attr('name'), 'We are sorry. You must accept the promotional conditions for this order.', FormValidator.form);
								else
									ErrorHandler.addFieldError(field.attr('name'), FormValidator.helpers.getLabel(field) + ' is required.', FormValidator.form);
								FormValidator.hasErrors = true;  
							}
							break;
						case 'text':
						default:
							if( !field.val() || field.val() == field.attr('title') || field.val().replace(/[' ']{1,}/,'') == '' ) {
								ErrorHandler.addFieldError(field.attr('name'), FormValidator.helpers.getLabel(field) + ' is required.', FormValidator.form);
								FormValidator.hasErrors = true; 
							} 
					}
				}
				return true;
			},
			// Minimum/Maximum characters
			/* USAGE: 
				<input type="text" class="minMax min_5 max_40" />
				.minMax - enables min/max validation (required)
				.min_X - minimum length	(optional if max_X present)
				.max_X - maximum length	(optional if min_x present)
			*/
			minMax: function(field) {
				if( field.hasClass('minMax') ) {
					var classes, minChar, maxChar;
					classes = field.attr('class').split(' ');
					for(var i = 0; i < classes.length; i++) {
						if(classes[i].match('min_')) { minChar = classes[i].replace('min_',''); }
						if(classes[i].match('max_')) { maxChar = classes[i].replace('max_',''); }
					}
					if(field.val() && field.val().length < minChar) {
					 	ErrorHandler.addFieldError(field.attr('name'), FormValidator.helpers.getLabel(field) + ' must be at least ' + minChar + ' characters.', FormValidator.form);
					 	FormValidator.hasErrors = true;
					}
					if(field.val() && field.val().length > maxChar) {
					 	ErrorHandler.addFieldError(field.attr('name'), FormValidator.helpers.getLabel(field) + ' must be less than ' + (parseInt(maxChar,10) + 1) + ' characters.', FormValidator.form);
					 	FormValidator.hasErrors = true;
					}
				}
				return true;
			},
            /*zip code validation*/
            zipPostalCode: function(field) {
				var zipCodeRegEx = /(^\d{5}$)|(^\d{5}-\d{4}$)/;
                if(field.hasClass('zipPostalCode')){
                	if (!field.val().match(zipCodeRegEx) || field.val() == '' || field.val() == '00000') {
                		ErrorHandler.addFieldError(field.attr('name'), FormValidator.helpers.getLabel(field) + ' is invalid.', FormValidator.form);
                		FormValidator.hasErrors = true;
                	}
                }
            },
            // Email address
			/* USAGE: <input type="text" class="email" /> */ 
			email: function(field) {
				var emailRegEx = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
				if( field.hasClass('email') && !field.val().match(emailRegEx) && field.val() !== '' ) {
				 	ErrorHandler.addFieldError(field.attr('name'), FormValidator.helpers.getLabel(field) + ' is invalid.', FormValidator.form);
				 	FormValidator.hasErrors = true;
				}
				return true;
			},
			invalidSymbol: function(field) { 
				var invalidSymbolRegExp = /[\)\(\*\<\>\{\}\[\]\!\$\%\^\&\+\=\?\;\"]/g;
				if( field.hasClass('invalidSymbol') && field.val().match(invalidSymbolRegExp) && field.val() !== '' ) {
				 	ErrorHandler.addFieldError(field.attr('name'), FormValidator.helpers.getLabel(field) + ' is invalid.', FormValidator.form);
				 	FormValidator.hasErrors = true;
				}
				return true;				
			},
			password: function(field) {
				var passwordRegEx = /(?=^.{6,15}$)(\w*(?=\w*\d)(?=\w*[a-zA-Z])\w*)/;
				if( field.hasClass('passwordVal') && !passwordRegEx.test(field.val())) {
					ErrorHandler.addFieldError(field.attr('name'), 'Password must include<br/>At least 6 characters, no more than 15.<br/>At least 1 letter (a - z)<br/>At least 1 number (0 - 9)<br/>No spaces<br/>No special characters (i.e. %$#!@*)<br/>Passwords are CaSe SEnSiTivE', FormValidator.form);
				 	FormValidator.hasErrors = true;
				}
				return true;
			},
			// Matching fields (confirm fields)
			/* USAGE:
				Apply class 'match' and 'match_FIELDNAME' to one of the two fields.
				<label for="emailAddress">Email address</label>
				<input type="text" class="match match_emailAddressConfirm" />

				<label for="emailAddressConfirm">Confirm email address</label>
				<input type="text" class="" />
			*/
			matching: function(field) {
				if( field.hasClass('match') ) {
					var classes, matchingField;
					classes = field.attr('class').split(' ');
					for(var i = 0; i < classes.length; i++) {
						if(classes[i].match('match_')) { matchingField = $('[name=' + classes[i].replace('match_','') + ']'); }
					}
					if(field.val() && field.val().toUpperCase() != matchingField.val().toUpperCase()) {
					 	ErrorHandler.addFieldError(field.attr('name'), FormValidator.helpers.getLabel(field) + ' does not match ' + FormValidator.helpers.getLabel(matchingField) + '.', FormValidator.form);
						ErrorHandler.addFieldError(matchingField.attr('name'), '', FormValidator.form);
					 	FormValidator.hasErrors = true;
					}
				}
				return true;
			},
			
			range : function(field){
				var from = "" , to ="", classes;
				var isDecimal_re = /^\s*(\+|-)?((\d+(\.\d+)?)|(\.\d+))\s*$/;
				
				
				if( field.hasClass('range')){
					
					classes = field.attr('class').split(' ');
					for(var i = 0; i < classes.length; i++) {
						if(classes[i].match('range_from_')){ from = parseInt(classes[i].replace('range_from_',''))};
						if(classes[i].match('range_to_')){to = parseInt(classes[i].replace('range_to_',''))};
					}
					
					if(from != "" || to != ""){
						if((parseInt(field.val()) < from) || (parseInt(field.val()) > to ) ||(!isDecimal_re.test(field.val()))){
							ErrorHandler.addFieldError(field.attr('name'), FormValidator.helpers.getLabel(field) + ' is not a valid range. (' + from + ' to ' + to + ')', FormValidator.form);
							FormValidator.hasErrors = true;
						} 
					}
				}
				return true;
			}
		}
	};

	/* Cookies
	------------------------------------------------------------------------- */

	CookieJar = { 
		cookies: {},
		init:function() { 
			return CookieJar.packageCookies();
		},
		// Pass This: { name:'cookie', value:'value', [expires:'365'], [domain:'domain'], [path:'path'], [secure:true] }  
		addCookie:function(newCookie) { 
			cookie = [];

			// Build the New Cookie Array
			$.each(newCookie, function(index, value) {	
				switch(index) {
					case 'name':	cookie[0] = value;
									break;
					case 'value':	cookie[0] = cookie[0] + "=" + $.trim(value); 
									break;
					case 'expires': dateObj = new Date();
									dateObj.setDate(dateObj.getDate() + parseInt(value));
									value = dateObj.toGMTString(); 
									cookie[1] = index + "=" + value;
									break;
					case 'path':	cookie[2] = index + "=" + value;	
									break;
					case 'domain':	cookie[3] = index + "=" + value;	
									break;		
					case 'secure':	if(value) { cookie[4] = index };
									break;
				}
			});
			
			// Remove Blanks in New Cookie Array
			var cleanCookie = new Array(); 
			for(i = 0; i < 5; i++) { if(cookie[i]) { cleanCookie.push(cookie[i]); } }

			// Submit New Cookie 
			document.cookie = cleanCookie.join(';') + ';';

			// Update Cookies Object and Return
			return (CookieJar.packageCookies()) ? true : false
		},
		getCookie:function(cookie) {
			return (CookieJar.cookies[cookie]) ? CookieJar.cookies[cookie] : false
		},
		updateCookie:function(cookie) {
			return (CookieJar.getCookie(cookie.name)) ? CookieJar.addCookie(cookie) : false 
		},
		tossCookie:function(cookie) {
			// Ready the Cookie Object to Remove
			oldCookie = {};
			oldCookie.name = cookie;
			oldCookie.value = CookieJar.getCookie(cookie);
			oldCookie.expires = '0';
			
			return CookieJar.updateCookie(oldCookie);
		},
		packageCookies:function() {
			// Stores Available Cookies as Object
			$.each(document.cookie.split(';'), function() {
				name = $.trim(this.split('=')[0]);
				value = this.split('=')[1];
				CookieJar.cookies[name] = value;
			});
			return true;
		}
	};

	/* Inits
	------------------------------------------------------------------------- */
	// Objects
		SearchBot.init();
		MessageHandler.init();
		ErrorHandler.init();
		FormValidator.init();
		CookieJar.init();
	// Site
		// Alphanumeric validation
		$('.alphanumeric').alphanumeric();
		$('.alpha').alpha();
		$('.numeric').numeric();
		$('.numericMasked').numeric({allow:"*"});
        //zip must be numeric
        $('.zipPostalCode').numeric();
        // Masked input
		$(".phone").mask("999-999-9999", { placeholder: ' ' });
		$(".inputDate").mask("99/99/9999", { placeholder: ' ' });
		// Thickbox
		$('a.closeBW').click(tb_close);
		
		// Sortable tables
		$('table.sortable th').each(function() { 
			if($(this).hasClass('noSort')) { sortHeaders[$('table.sortable th').index(this)] = { sorter: false }; }
            if($(this).hasClass('currency')) { sortHeaders[$('table.sortable th').index(this)] = { sorter: "currency" }; }
		});
		
		if(!$('table').hasClass('onPage')) {
            var tablesorterOptions = {cssAsc: 'sortAsc', cssDesc: 'sortDesc', headers: sortHeaders };

            if ($('table').hasClass('extractCellData')) {
                tablesorterOptions['textExtraction'] = function (node) {
                    var cells = $('.cellData', node);
                    if (cells.size() > 0) {
                        return cells[0].innerHTML;
                    } else {
                        return node.innerHTML;
                    }
                }
            }

			$('table.sortable').tablesorter(tablesorterOptions);
			if($('table.sortable').hasClass('initialSort')) {
				$('table.sortable').trigger('sorton',[[[0,0]]]);
			}
		}
		
	
	/* Event handlers
	------------------------------------------------------------------------- */
	// SearchBot
		// Show
		$('a.searchTab').click(function() { 
			SearchBot.show($(this).attr('href').split('#')[1]);
			return false; 
		});
		// Collapse
		$('#searchBox a.collapse').click(function() { 
			SearchBot.collapse();
			return false; 
		});
	// FormValidator
		// Validate on submit
		$('form').submit(function() {
			var validated = FormValidator.validate(this);
			if(validated === true) {
				if ($(this).hasClass('search'))	{
					showInterstitial('interstitialSearch');
				}
				if ($(this).hasClass('submitOnce')) {
					$(this).find('a.submit').unbind('click');		
				}
				if ($(this).hasClass('searchStore')){ 
					showStoreLoader();
				}
				
				if ($(this).hasClass('usesAjax')){ 
					return false;
				}
			}
			return validated;
		});
		$(':input.enterSubmit').keypress(function(e) {
			if(e.which == 13) { $(this).parents('form').submit(); }
		});
	// Site
        // Interstitial fix for back button bug (Insterstitial shows up when you hit back sometimes)
		tb_close();
		// Form submit buttons
		$('a.submit').click(function() {
			if(($(this).attr("title") == "Search") && (($(this).parents("form").find("#searchedPart").val() == "Enter part number") || ($(this).parents("form").find("#searchedPart").val() == "Enter model number")))
				return;
			$(this).parents('form').submit();
			return false; 
		});
		// Search 
		$('a.search').click(function() {
			if($("#productCategoryId").size() > 0){
				$(this).each(function(){
					$("#productCategoryId").css({"visibility":"hidden"});
				});
			}
			if($("#brandId").size() > 0){
				$(this).each(function(){
					$("#brandId").css({"visibility":"hidden"});
				});
			}
			
			$(document.body).popup({isModal:true, isLoader:true, fixCenter:true});
			//showInterstitial('interstitialSearch');
		});
				
		// Attach Class Observers
		new Attach.PartViewPopup();
		new Attach.LegalPopup();
		new Attach.PromptText();
		new Attach.CloneAndInsert();
		
		// Scrollable Sortable Tables
		$('.fauxScrollableHeader table.sortable th').click(function() { 
			if(!$(this).hasClass('noSort')) {
				var sortingHeader = $(this).hasClass('sortDesc') ? [[$('.fauxScrollableHeader table.sortable th').index(this), 1]] : [[$('.fauxScrollableHeader table.sortable th').index(this), 0]];
				var sortingTable = $(this).hasClass('sortDesc') ? [[$('.fauxScrollableHeader table.sortable th').index(this), 0]] : [[$('.fauxScrollableHeader table.sortable th').index(this), 1]];
				$('.fauxScrollableHeader table.sortable').trigger('sorton',[sortingHeader]);
				$('.fauxScrollableTable table.sortable').trigger('sorton',[sortingTable]);
				return false;
			}
		});

		/* INTERNET EXPLORER */
		if($.browser.msie) {
			// Makes indexOf for Arrays work in Internet Explorer.
			if(!Array.indexOf){
			    Array.prototype.indexOf = function(obj){
			        for(var i=0; i<this.length; i++){ if(this[i]==obj){ return i; } }
			        return -1;
			    }
			}
			// Clean up memory leaks
			$(window).bind('unload',function() {
				try {
					$('*').add(window).add(document).unbind();
				} catch(err) {}		
			});
		}
		
		// Cookie deletion on Logout
		$('.logoutButton').click(function() {
			CookieJar.addCookie({ name: 'loggedIn', value: 'false' });
			CookieJar.tossCookie('loggedIn');
		});

        $('.trimOnBlur').blur(function () {
            $(this).val(jQuery.trim($(this).val()));
        });
});


