
// initialise all the script objects
$(document).ready(function() { 
	slide.init();
	dropMenus.init();
	inputClearing.init();
	regForm.init();
	enqForm.init();
	addFlashyBits.init();
	emailCookie.init();
	googStyle.init();
	heritageBanner.init();
	bespokeBanner.init();
	lightBoxEnable.init();
	
	watchProductStyle.init();
});

var watchProductStyle = {
	
	altIcon: '/static-images/video-icon-hover.gif',
	vidRef: 'p.subVideo',
	listRef: 'ul.watchTextList',
	
	init: function(){
		if($(this.vidRef).length > 0) { this.doWatchVideoStyling(); }
		if($(this.listRef).length > 0) { this.doWatchListStyling(); }
	},
	
	doWatchVideoStyling:function() {

		var obj = this;
			
		$(this.vidRef).each(function(s, e) {
			$(e).find('img').eq(0).addClass('dispOff');
			$(e).find('img').eq(0).after('<img class="dispOn" src="' + obj.altIcon + '" alt="" style="display: none;"/>');
			$(e).find('a').eq(0).mouseenter(function() {
				$(e).find('img.dispOff').eq(0).css({'display':'none'});
				$(e).find('img.dispOn').eq(0).css({'display':'inline'});
			});
			$(e).find('a').eq(0).mouseleave(function() {
				$(e).find('img.dispOff').eq(0).css({'display':'inline'});
				$(e).find('img.dispOn').eq(0).css({'display':'none'});
			});		
		});

	},
	
	doWatchListStyling:function() {
	
		$(this.listRef).each(function(s, e) {

			var listArr = Array();
			$(e).find('li').each(function(t, f) {
				if((t+1)%2 == 0) {
					$(f).after('<li class="divider">&nbsp;</li>');
				}
			});
		});
	}
}


var lightBoxEnable = {
	grouping:'.lbox',
	item:'a[rel="imageshow"]',
	
	init:function() {
	
		$('a[rel="imageshow"]').colorbox({transition:'fade', speed:500, current:''});
		
		if($('#colorbox_target').length < 1) {
			$('body').append('<div style="display: none"><div id="colorbox_target" style="width: 680px; padding-top: 5px; padding-left: 6px;height: 400px;"><div id="colorbox_target_video"></div></div></div>'); // originally "580", "400"
		}
		
		$('div.subVideo a').colorbox({
			inline:true, 
			href: "#colorbox_target",
			onComplete:function(){ 
				var flashvars = { 
				
					file:$(this).attr('href'), 
					autostart:true, 
					'plugins':'googlytics-1'/*,
					skin: '/flash/bekle/bekle.xml'*/
				}
				var params = { wmode:'transparent', allowfullscreen:'true', allowscriptaccess:'always' }, attributes = {};
				swfobject.embedSWF("/javascript/player.swf", 'colorbox_target_video', "674", "400", "9.0.0", false, flashvars, params, attributes);	
			}
		});	
	}
}

var heritageBanner = {
	init: function(){
		if($('#heritageBanner').length < 1) return;
		
		$('#heritageBanner').html('<div id="heritageFlashInner"></div>');
		
		var flashvars = {}, params = { wmode:"opaque" }, attributes = {};
		swfobject.embedSWF('/flash/heritage.swf', "heritageFlashInner", 695, 250, "9.0.0", false, flashvars, params, attributes);	
	}
}


var bespokeBanner = {
	init: function(){
		if($('#bespokeBanner').length < 1) return;
		$('#bespokeBanner').html('<div id="bespokeFlashInner"></div>');
		var flashvars = {}, params = { wmode:"opaque" }, attributes = {};
		swfobject.embedSWF('/flash/bespokeBanner.swf', "bespokeFlashInner", 695, 250, "9.0.0", false, flashvars, params, attributes);	
	}
}

// modify the google 404 search
var googStyle = {
	init:function(){
		if($('div#goog-fixurl').length < 1) return;
		$('div#goog-fixurl input#goog-wm-sb').attr({'value':'Submit'});
	}
}


// pass email address value from newsletter form to register form then remove cookie
var emailCookie = {
	init:function(){
		if($('form#newsletter').length > 0) {
			$('form#newsletter').submit(function(e) {
				$.cookie('emailAddress', $('#newsletterEmail').val(), { path: '/' });
			});
		}
		
		if($('form#register').length > 0 && $.cookie('emailAddress') != null) {
			if($('form input#username').length > 0) {
				$('form input#username').val($.cookie('emailAddress'));
				$.cookie('emailAddress', null, { path: '/' });
			}
		}
	}
}

// add flash to homepage (and eventually hubs)
var addFlashyBits = {

	init:function(){
		if($('#pageContainer').length != 1) return;
		
		if($('body.tmpHome').length > 0) { this.addFlash('home'); } 
		else if ($('div.content.jewellery').length > 0) { this.addFlash('jewellery'); } 
		else if ($('div.content.watches-and-clocks').length > 0) { this.addFlash('watches'); } 
		else if ($('div.content.engagement-rings').length > 0) { this.addFlash('engagement'); } 
		else if ($('div.content.antique-and-period').length > 0) { this.addFlash('antique'); } 
		else if ($('div.content.gifts').length > 0) { this.addFlash('gifts'); } 
		else if ($('div.content.brands').length > 0) { this.addFlash('brands'); }
	},
	
	addFlash:function(page) {
		
		filename = false, width = false, height = false;
		if(page == 'home') {
			filename = '/flash/home.swf';
			width = 990;
			height = 610;
		} else if(page == 'jewellery') {
			filename = '/flash/hub-jewellery.swf';
			width = 990;
			height = 420;
		} else if(page == 'antique') {
			filename = '/flash/hub-antique.swf';
			width = 990;
			height = 420;
		} else if(page == 'watches') {
			filename = '/flash/hub-watches.swf';
			width = 990;
			height = 420;
		} else if(page == 'brands') {
			filename = '/flash/hub-brands.swf';
			width = 990;
			height = 420;
		} else if(page == 'gifts') {
			filename = '/flash/hub-gifts.swf';
			width = 990;
			height = 420;
		} else if(page == 'engagement') {
			filename = '/flash/hub-engagement.swf';
			width = 990;
			height = 420;
		}
		
		$('#pageContainer').append('<div id="pageFlash"><div id="pageFlashInner">&nbsp;</div></div>');
		
		var flashvars = {}, params = { wmode:"opaque" }, attributes = {};
		swfobject.embedSWF(filename, "pageFlashInner", width, height, "9.0.0", false, flashvars, params, attributes);		
	
	},
	
	// NOTE: eventually these items should be flash and this function can be removed
	addBG:function(page) {
		bgImg = false, bgPos = false;
		if(page == 'jewellery') {
			bgImg = 'url(/static-images/jewellery-bg.jpg)';
			bgPos = '0 38px';
		} else if(page == 'watches') {
			//bgImg = 'url(/static-images/watches-and-clocks-bg.jpg)';
			bgImg = 'url(/flash/patek-watches-static.jpg)';
			bgPos = '0 38px';
		} else if(page == 'engagement') {
			bgImg = 'url(/static-images/engagement-rings-bg.jpg)';
			bgPos = '0 38px';
		} else if(page == 'antique') {
			bgImg = 'url(/static-images/antique-and-period-jewellery-bg.jpg)';
			bgPos = '0 38px';
		} else if(page == 'gifts') {
			bgImg = 'url(/static-images/gifts-bg.jpg)';
			bgPos = '0 38px';
		} else if(page == 'brands') {
			bgImg = 'url(/static-images/brands-bg.jpg)';
			bgPos = '0 38px';
		}
		
		$('div.content').css({'background-image':bgImg, 'background-position':bgPos});
	
	}
}

// little device independent script to clear/reset values and colours in input fields - add fields to check to the .each iteration
var inputClearing = {
	init:function(){
		$.each(['form#search', 'form#newsletter'], function(s, e){ // add all the forms/sub elements of forms to check here
			if($(e).length > 0) {
				$(e).find('input[type=text]').focus(function() {
					if(!$(this).data('fv')) { $(this).data('fv', { value: $(this).attr('value'), colour: $(this).css('color') }); }
					if($(this).attr('value') == $(this).data('fv').value) { $(this).attr({value:''}); }
					$(this).css({'color':'#fff'});
				});	
				$(e).find('input[type=text]').blur(function() {
					if($(this).attr('value') == '' || $(this).attr('value') == $(this).data('fv').value) { $(this).attr({'value':$(this).data('fv').value}); }
					$(this).css({'color':$(this).data('fv').colour});
				});				
			}
		});
	}
}


//validation for the registration form - moved here to avoid unecessary inline code
var regForm = {
	
	formID:'register',
	
	init:function(){
	
		if($('#'+regForm.formID).length < 1) return;
		regForm.doVadlidate();
		// allow html link to do the form submission - might want to change this to a submit button?
		$('#'+regForm.formID).find('p#submit').click(function(e) {
			$('#'+regForm.formID).submit();
			e.preventDefault();
		});
	},
	
	doVadlidate:function(){
		$('#'+regForm.formID).validate({
			//set the rules for the field names
			rules: {
				title: "required",
				forename: {
					required: true, 
					maxlength: 100
				},
				surname: {
					required: true,
					maxlength: 100
				},
				username: {
					required: true,
					email: true,
					maxlength: 100
				},
				password: {
					required: true,
					minlength: 8,
					maxlength: 10
				},
				confirmpassword: {
					required: true,
					minlength: 8,
					equalTo: "#password"
				},
				privacyAgreement: "required",
				optin_t1_m1: "required"
			},
			//set messages to appear inline
			messages: 
			{
				title: "Please select your title",
				forename: 
				{ 
					required: "Please enter your forename",
					maxlength: "Your forename must be less than 100 characters"
				},
				surname:
				{ 
					required: "Please enter your surname",
					maxlength: "Your surname must be less than 100 characters"
				},
				username: 
				{
					required: "Please enter your email address",
					email: "Please enter a valid E-mail address",
					maxlength: "Your E-Mail must be less than 100 characters"
				},
				password: 
				{
					required: "Please enter your password",
					minlength: "Your password must be at least 8 characters long",
					maxlength: "Your password must be 10 characters or less"
				},
				confirmpassword: 
				{
					required: "Please confirm your password",
					minlength: "Your password must be at least 8 characters long",
					equalTo: "Please enter the same password as above"
				},
				privacyAgreement: "Please confirm if you agree to our Privacy Policy &amp; Terms and Conditions",
				optin_t1_m1: "Please confirm if you are happy to receive emails from us"
			},
			
			errorPlacement: function(error, element) {
				// do some custom rules on the error message based on type...
				if(element.attr('id') == 'forename') { error.addClass('left'); } 
				else if(element.attr('id') == 'surname') { error.addClass('right'); }
				element.parent().append(error);
			}
		});	
				
		// check if confirmation password is still valid after password changed
		$("#password").blur(function() {
			$("#confirmpassword").valid();
		});
	
		// Check if the Brochure request checkbox has been checked
		// if it has been checked add '.required' to the class else remove it
		$(function() {
			function brochureAddress() {
				var $this = $(this);
				var addLine1 = $('#add_1');
				var pCode = $('#postcode');
				var addTown = $('#town');
				var addCounty = $('#county');
				if ($this.is(":checked")) {
					addLine1.addClass("required");
					pCode.addClass("required");
					addTown.addClass("required");
					addCounty.addClass("required");
				} else {
					addLine1.removeClass("required");
					pCode.removeClass("required");
					addTown.removeClass("required");
					addCounty.removeClass("required");
					}
			}

		// also display the '*' next to the mandatory address fields on checked checkbox.
			function mandatoryFields() {
				var $this = $(this);
				var mandatoryAdd1 = $('#mandatoryAdd1');
				var mandatoryTown = $('#mandatoryTown');
				var mandatoryCounty = $('#mandatoryCounty');
				var mandatoryPcode = $('#mandatoryPcode');
				if ($this.is(":checked")) {
					mandatoryAdd1.addClass("mandatory");
					mandatoryTown.addClass("mandatory");
					mandatoryCounty.addClass("mandatory");
					mandatoryPcode.addClass("mandatory");
				} else {
					mandatoryAdd1.removeClass("mandatory");
					mandatoryTown.removeClass("mandatory");
					mandatoryCounty.removeClass("mandatory");
					mandatoryPcode.removeClass("mandatory");
				}
			}
			
						$(':checkbox[id="crmid_1"]')
						.click(brochureAddress)
						$(':checkbox[id="crmid_1"]')
						.click(mandatoryFields)
		});
	}
}


//validation for the enquiry form - moved here to avoid unecessary inline code
var enqForm = {
	
	formID:'enquiry',
	
	init:function(){
	
		if($('#'+enqForm.formID).length < 1) return;
		enqForm.doVadlidate();
		// allow html link to do the form submission - might want to change this to a submit button?
		$('#'+enqForm.formID).find('p#submit').click(function(e) {
			$('#'+enqForm.formID).submit();
			e.preventDefault();
		});
	},

	doVadlidate:function(){
		$("#message").charCounter(250);
		$('#'+enqForm.formID).validate({
			//set the rules for the field names
			rules: {
				title: "required",
				firstname: {
					required: true, 
					maxlength: 100
				},
				surname: {
					required: true,
					maxlength: 100
				},
				email: {
					required: true,
					email: true,
					maxlength: 100
				},
				primaryPhone: {
					required: true,
					minlength: 8,
					maxlength: 25
				},
				message: {maxlength: 250},
				addressLine1: {maxlength: 100},
				addressLine2: {maxlength: 100},
				town: {maxlength: 100},
				county: {maxlength: 100},
				country: {maxlength: 100},
				postcode: {maxlength: 10},
				mobileNumber: {maxlength: 25}
			},
			//set messages to appear inline
			messages: 
			{
				title: "Please select your title",
				firstname: 
				{ 
					required: "Please enter your forename",
					maxlength: "Your forename must be less than 100 characters"
				},
				surname:
				{ 
					required: "Please enter your surname",
					maxlength: "Your surname must be less than 100 characters"
				},
				email: 
				{
					required: "Please enter your email address",
					email: "Please enter a valid E-mail address",
					maxlength: "Your E-Mail must be less than 100 characters"
				},
				primaryPhone: 
				{
					required: "Please enter your Main Contact Number",
					minlength: "Your number must be at least 8 characters long",
					maxlength: "Your number must be 25 characters or less"
				},
				message: "Your Enquiry must be 250 characters or less",
				addressLine1: "Address line 1 must be 100 characters or less",
				addressLine2: "Address line 2 must be 100 characters or less",
				town: "Town must be 100 characters or less",
				county: "County must be 100 characters or less",
				country: "Country must be 100 characters or less",
				postcode: "Postcode must be 10 characters or less",
				mobileNumber: "Mobile Number must be 25 characters or less"
			},
			
			errorPlacement: function(error, element) {
				// do some custom rules on the error message based on type...
				if(element.attr('id') == 'firstname') { error.addClass('left'); } 
				else if(element.attr('id') == 'surname') { error.addClass('right'); }
				element.parent().append(error);
			}
			
		});	
	}
}

/* drop menu with timeout on mouseleave, cancelled immediately on mouseenter so that only one menu is shown at any one time */
var dropMenus = {
	obj: new Array(),
	tOut: null,
	conf:{
		centreMenus:true,		// if true, centre menu to parent, else align left by default (css) amount
		centreOffset:4,			// adjust the centred item offset to account for padding/margin issues
		timeoutDelay: 800		// time before menu closes on mouseleave
	},
	init:function(){
	
		if($('div#prodNav ul li').length < 1 || $('body.tmpHome').length > 0) return;
		
		$('div#prodNav ul li div').each(function(s, e){

			dropMenus.centreItem($(e));
			
			$(e).parent().data('preselected', { value: $(e).parent().hasClass('selected') });
			
			$(e).parent().find('a').eq(0).mouseenter(function(ev) { dropMenus.enter($(e)); });
			$(e).mouseenter(function(ev) { dropMenus.enter($(e)); });
			
			$(e).parent().find('a').eq(0).mouseleave(function(ev) { dropMenus.leave($(e)); });
			$(e).mouseleave(function(ev) { dropMenus.leave($(e)); });			
			
		});
	},
	
	enter:function(elem){

		if(dropMenus.tOut != null) {
			clearTimeout(dropMenus.tOut);
			dropMenus.tOut = null;
			$('div#prodNav ul li div').each(function(s, e) {
				if(!$(e).parent().data('preselected').value) { $(e).parent().removeClass('selected'); }
			});
		}
		
		$('div#prodNav ul li div').css({zIndex:950, display: 'none'});
		elem.css({zIndex:951, display:'block'});
		elem.parent().addClass('selected');	
	
	},
	
	leave:function(elem) {
	
		dropMenus.tOut = setTimeout(function(){
			elem.css({zIndex:951, display:'none'});
			if(!elem.parent().data('preselected').value) { elem.parent().removeClass('selected'); }
		}, dropMenus.conf.timeoutDelay);	
	
	},
	
	centreItem:function(elem){
		if(dropMenus.conf.centreMenus == true) {
			var offsetLeft = Math.floor(parseInt(elem.parent().width(), 10)/2 - parseInt(elem.width(), 10)/2)+dropMenus.conf.centreOffset;
			elem.css({'left': offsetLeft});
		}
	}
}


/*#########################################################################################################################*\
#	Function: slide
#	How to pass in the data, including examples of master
#	<div id="scrollNavData">
#		<div class="row">
#			<h2 class="group"><a href="/group-path/">Group name</a></h2>
#			<ul class="items">
#
#				<li><a href="/url/path/" class="hideLabel">Item name</a> [<span class="img">/image-path/</span>]</li>
#				<li><a href="/url/path/" class="hideLabel">Item name</a> [<span class="img">/image-path/</span>]</li>
#			</ul>
#			<div class="override">imgMaxX=80||imgMaxY=50</div>
#		</div>
#		<div class="row">
#			<h2 class="group"><a href="/group-path/ class="alignRight"">Group name</a></h2>
#			<ul class="items">
#				<li><a href="/url/path/">Item name</a> [<span class="img">/image-path/</span>]</li>
#				<li><a href="/url/path/">Item name</a> [<span class="img">/image-path/</span>]</li>
#			</ul>
#		</div>
#		<div class="config">panelCloses=true||menuStyle=tabs||panelSpeed=1000</div>
#	</div>
\*#########################################################################################################################*/



var slide = {
	openHeight:0, 				// take a height from the slider when open
	openOuterHeight:0, 			// take a height from the container of the slider when open
	obj: new Array(),			// container object for our data
	scrolling: false,			// are we currently scrolling? store the fact here!
	
	// defines how data is passed
	dataEl: { 
		el: '#scrollNavData',
		row:'div.row',
		group:'h2 a',
		item:'li', 				// the name and link are stored in "li a", the image and caption in "li img"
		config:'.config',		// the class name of the config element
		delimit:'||',			// the parameter delimiter for passing in configuration variables
		override:'.override'	// container for override data - e.g. to control image sizes for individual sets
	},
	
	// configuration - anything below this can be configured in the data config section
	conf:{
		visibleSet: 0,				// set 0 is initially visible
		slID:'scrollNav', 			// allows a custom ID to be given to the nav
		numItems:8, 				// number of items visible on screen at once
		panelWidth:872,				// width of the visible containers
		itemWidth:109,				// should be panelWidth / numItems, ie width of container for each list item
		forceItemHeight:140,		// set the height of the image container
		forceItemWidth:109,			// set the width of the image container
		forceLabelWidth:95,			// set the width of the labels
		
		menuStyle:'navbar',			// full width nav bar or tabs
		hideAllLabels:false,		// labels can be individually hidde with a class of hideLabel or the whole lot can be turned on or off from here
		
		slideSpeed:1600,			// speed of left/right slide
		switchFade:true,			// when the category menus are switched should they fade trasition (true) or just switch immediately
		switchFadeDelay:'fast',		// if a switch fade transition is used this cotrols the speed
		
		imgMaxX: 100,				// max width the image will grow to
		imgMaxY: 100,				// max height the image will grow to
		imgMinX: 70,				// min width the image will grow to
		imgMinY: 70,				// min height the image will grow to
		minOpac: 0.6,				// min opacity level
		maxOpac: 1.0,				// max opacity level
		rszSpdUp: 'fast',			// value passed to animate as speed to grow image
		rszSpdDwn: 'fast',			// value passed to animate as speed to shrink image
		imgMarginTopOffset: 8, 		// allows padding between top of image and container if required
		imgMarginLeftOffset: 4, 	// allows padding between top of image and container if required
		labelTopOffset: 8,			// label is positioned at img max height + labelTopOffset
		
		panelCloses:true,			// set to false to keep the panel open, useful for debugging
		initClose: true,			// if true the menu closes on page load after X time
		initTimeOut: 1000,			// delay before menu initially closes		
		initTimeOutObj: null,		// timeout object is stored/cleared here
		normalTimeOut: true,		// subsequent delay before closing panel
		normalTimeOutObj: null,		// object to store timeout
		normalTimeDelay: 600,		// delay length to wait before panel closes
		panelSpeed:400				// speed at which the panel opens/closes
	},
	
	// allows widths, numitems and image dimensions to be set individually (height will default to the tallest as it must be standard)
	// the following can be added as overrides:
	// numItems, panelWidth, itemWidth, forceItemWidth, hideAllLabels, imgMaxX, imgMaxY, imgMinX, imgMinY, imgMarginTopOffset, imgMarginLeftOffset, forceLabelWidth

	sizes:{
	
	},
		
	//showText:true,				// use to suppress text display for items in sub menus - this should be a property of the data row
	
	init:function(){
		if($(slide.dataEl.el + ' ' + slide.dataEl.row).length < 1) return;

		// populate our data object
		slide.popData();
		
		// build our navigation
		slide.setup(slide.build());
		
	},

	// once the html is built configure initial view
	setup:function(out){
		
		// add html to dom
		$('#scrollNavPlaceholder div.target').before(out).remove(); 
		
		$('#' + slide.conf.slID + ' div.slider').each(function(x, el) {
			//force width to item container if passed as a config value
			$.each(['ul li', 'ul li a'], function(s, e) {
				$(el).find(e).width(parseInt(slide.obj[x].override.forceItemWidth, 10));
			});
			
			// set width of item absolutely positioned containers based on image max width
			$(el).find('.item span.img').css({'width': parseInt(slide.obj[x].override.imgMaxX, 10)});
			
			// set label widths
			$(el).find('.item span.text').css({'width': parseInt(slide.obj[x].override.forceLabelWidth, 10)});
		
			// center item lists (to account for any that have less than #numItems)
			var getWidth = parseInt($(el).find('div.container ul li').eq(0).width(), 10);
			var getLabelWidth = parseInt($(el).find('div.container ul li span.text').eq(0).width(), 10);
			
			$(el).find('ul').each(function(s, e) {
				var mLeft = ( parseInt((slide.obj[x].override.panelWidth - (parseInt($(e).find('li').length * getWidth, 10)))/2, 10)  );
				$(e).css({marginLeft:mLeft});
			});
		
			// set initial opacity and position for images within their container so they don't jump around, jump around, jump up, jump or get down
			var startPosLeft = parseInt(slide.obj[x].override.imgMarginLeftOffset, 10) + parseInt((slide.obj[x].override.imgMaxX-slide.obj[x].override.imgMinX)/2, 10);
			
			$(el).find('.item img').css({opacity:slide.conf.minOpac, marginLeft:startPosLeft});
			
			var imgLeftOffset = Math.floor((getWidth - parseInt(slide.obj[x].override.imgMaxX, 10))/2);
			var labelLeftOffset = Math.floor((getWidth - parseInt(getLabelWidth, 10))/2);
			var labelTopOffset = parseInt(slide.obj[x].override.imgMaxY, 10) + slide.conf.labelTopOffset;
			
			$(el).find('.item span.img').css({'left':imgLeftOffset});
			$(el).find('.item span.text').css({'left':labelLeftOffset, 'top':labelTopOffset});

			var startPosTop = parseInt(slide.obj[x].override.imgMarginTopOffset, 10) + parseInt((slide.obj[x].override.imgMaxY-slide.obj[x].override.imgMinY)/2, 10);
			$(el).find('.item img').css({marginTop:startPosTop});		

			// add mouse enter/leave events for images
			$(el).find('.item').mouseenter(function(e){
				slide.animItem(
					$(this).find('img').eq(0), 
					slide.obj[x].override.imgMaxX, 
					slide.obj[x].override.imgMaxY, 
					slide.obj[x].override.imgMarginTopOffset, 
					slide.obj[x].override.imgMarginLeftOffset, 
					slide.conf.rszSpdUp, 
					slide.conf.maxOpac
				);
			});
			$(el).find('.item').mouseleave(function(e){
				slide.animItem(
					$(this).find('img').eq(0), 
					slide.obj[x].override.imgMinX, 
					slide.obj[x].override.imgMinY, 
					parseInt(slide.obj[x].override.imgMarginTopOffset, 10) + parseInt((slide.obj[x].override.imgMaxY-slide.obj[x].override.imgMinY)/2, 10), 
					parseInt(slide.obj[x].override.imgMarginLeftOffset, 10) + parseInt((slide.obj[x].override.imgMaxX-slide.obj[x].override.imgMinX)/2, 10), 
					slide.conf.rszSpdDwn, 
					slide.conf.minOpac
				);
			});	
			
		});

		// set uniform height of labels per container (to account for long, wrapping labels) and track label heights to adjust container to fit
		var labelMinHeight = 1000;
		var labelMaxHeight = 0;
		$('#' + slide.conf.slID + ' div.slider ul').each(function(s, e) {
			//var labelHeight = 0;
			var currentLabelMaxHeight = 0;
			$(e).find('.item span.text').each(function(x, el) {
				var currentHeight = parseInt($(el).height(), 10);
				//var currentHeight = (parseInt($(el).height(), 10) + parseInt($(el).css('padding-top'), 10) + parseInt($(el).css('padding-bottom'), 10));
				
				if(currentHeight > currentLabelMaxHeight) { currentLabelMaxHeight = parseInt(currentHeight, 10); }
			});
			$(e).find('.item span.text').each(function(x, el) {
				var currentHeight = parseInt($(el).height(), 10);
				//var currentHeight = (parseInt($(el).height(), 10) + parseInt($(el).css('padding-top'), 10) + parseInt($(el).css('padding-bottom'), 10));

				if(currentHeight < labelMinHeight) { labelMinHeight = parseInt(currentHeight, 10); }
			});
			$(e).find('.item span.text').css({'height':currentLabelMaxHeight});
			labelMaxHeight = currentLabelMaxHeight > labelMaxHeight ? currentLabelMaxHeight : labelMaxHeight;
		});	
		
		// if labelMax less than labelMin then we have some multiple line labels and need to grow the menu to accomodate these
		if(labelMaxHeight - labelMinHeight > 0) {
			var labelPadding = parseInt($('#' + slide.conf.slID + ' div.slider ul .item span.text').eq(0).css('padding-top'), 10) + parseInt($('#' + slide.conf.slID + ' div.slider ul .item span.text').eq(0).css('padding-bottom'), 10);
			slide.conf.forceItemHeight = (parseInt(slide.conf.forceItemHeight, 10) + (labelMaxHeight - labelMinHeight) + labelPadding+ slide.conf.imgMarginTopOffset);
		}
		
		//force height to item containers if passed as a config value - div.hider, div.slider, div.container ul li, div.container ul a, div.container ul a span.img
		if(slide.conf.forceItemHeight != null) {
			$.each(['div.hider', 'div.slider', 'div.container ul li', 'div.container ul a', 'div.container ul a span.img'], function(s, e){
				$('#' + slide.conf.slID + ' ' + e).height(parseInt(slide.conf.forceItemHeight, 10));
			});			
		}
		
		// get height
		slide.openHeight = $('#' + slide.conf.slID + ' div.scrollNavInner').eq(0).height();
		slide.openOuterHeight = $('#' + slide.conf.slID).eq(0).height();
		
		// select set 0 initially
		$('#' + slide.conf.slID + ' .topNavTarget li').eq(slide.conf.visibleSet).addClass('selected');
		slide.switchSliders(slide.conf.visibleSet);
		
		// add mouse enter/leave events for slider container and set initial closing action
		if(slide.conf.panelCloses != false) {
			//$('#' + slide.conf.slID + ' div.scrollNavWrapper').eq(0).mouseenter(function(){ slide.toggle('open'); });
			//$('#' + slide.conf.slID).eq(0).mouseleave(function(){ slide.toggle('close'); });
			if(slide.conf.initClose) { slide.conf.initTimeOutObj = setTimeout(function(){ slide.toggle('close', true) }, slide.conf.initTimeOut); } else {
				// set mouse events here if init close doesn't fire the first time
				this.setPanelMouseEvents();
			}
		}

		// add top navigation controls
		slide.switchCat();
		
		// fix IE7 bug that renders absolutely positioned children of a link parent unclickable... this just emulates the click in js
		$('#' + slide.conf.slID + ' div.scrollNavInner div.container li a').click(function(e) { location.href = $(this).attr('href'); });
		
	},
	
	setPanelMouseEvents:function() {
	
		$('#' + slide.conf.slID + ' div.scrollNavWrapper').eq(0).mouseenter(function(){ slide.toggle('open'); });
		$('#' + slide.conf.slID).eq(0).mouseleave(function(){ slide.toggle('close'); });
	
	},
	
	// attach events to the top nav to switch categories
	switchCat:function() {
	
		$('#' + slide.conf.slID + ' div.topNavTarget a').each(function(s, e) {
			$(e).mouseenter(function(ev) {
				if(!$(this).parent().hasClass('selected')) {
					$('#' + slide.conf.slID + ' div.topNavTarget a').parent().addClass('greyed');
					$('#' + slide.conf.slID + ' div.topNavTarget a').parent().removeClass('selected');
					$(this).parent().addClass('selected');
					slide.switchSliders(s);
				}
			});
			$(e).click(function(ev) {
				//ev.preventDefault();
				$(this).blur();
			});
		});
	},
	
	// when there are multiple categories this allows them to be switched from the top nav
	switchSliders:function(num) {

		$('#' + slide.conf.slID + ' div.scrollNavInner div.slider').each(function(s, e) {
			if(s != num && $(e).css('visibility') == 'visible') {
				$(e).css({'visibility': 'hidden', 'display' : 'block'});
				
				if(slide.conf.switchFade) { $(e).fadeOut(slide.conf.switchFadeDelay); } 
				else { $(e).css({'visibility': 'hidden'}); }
			}
		
			if(s == num && $(e).css('visibility') == 'hidden') {
				$(e).css({'visibility': 'visible', 'display' : 'none'});
				
				if(slide.conf.switchFade) { $(e).fadeIn(slide.conf.switchFadeDelay); }
				else { $(e).css({'display': 'block'}); }
			}
		});
	
		slide.conf.visibleSet = num;
		
		// once the set is switched, ensure we check/attach the scroller nav
		slide.attachNav(num);
	},
	
	// attach event to previous and next buttons to trigger scroll
	attachNav:function(num){
		
		$('#' + slide.conf.slID + ' div.scrollNavInner div.prev').remove();
		$('#' + slide.conf.slID + ' div.scrollNavInner div.next').remove();		
		
		//if(slide.obj[slide.conf.visibleSet].items.length > slide.conf.numItems) {
		if(slide.obj[num].items.length > slide.obj[num].override.numItems) {
			// attach scroll controls
			$('#' + slide.conf.slID + ' div.scrollNavInner').prepend('<div class="prev">Previous</div>').append('<div class="next">Next</div>');
			$('#' + slide.conf.slID + ' div.prev').eq(0).click(function(e){ slide.slideTo('prev', num, true); });			
			$('#' + slide.conf.slID + ' div.next').eq(0).click(function(e){ slide.slideTo('next', num, true); });
		}
	},
	
	// scroll left and right
	slideTo:function(dir, num, clickEv) {
		
		if(clickEv && slide.scrolling == true) { return; }
		
		var s = $('#' + slide.conf.slID + ' div.slider').eq(num);
		var newPos = (dir == 'next' ? parseInt(s.position().left-slide.obj[num].override.panelWidth, 10) : parseInt(s.position().left+slide.obj[num].override.panelWidth, 10) );
		
		if(dir == 'next' && parseInt(newPos + s.width(), 10) <= 0) { return; }
		if(dir == 'prev' && s.position().left >= 0) { return; }

		slide.scrolling = true;
		s.stop().animate({ left:newPos }, slide.conf.slideSpeed, "swing", function() { slide.scrolling = false; });		

	},

	// build top nav for menu based on switch statement - default is navbar
	buildNav:function(){
		var output = '';
		switch (slide.conf.menuStyle) {
			case 'navbar':
				// build the top nav for the homepage - will have to look at how we do this for sub pages later
				output += '		<div class="topBorder">&nbsp;</div>' + "\n";
				output += '		<div class="topNavTarget">' + "\n"; // don't apply styles to this, it's just a hook for the js
				output += '		<div class="topNav">' + "\n";
				output += '			<div class="topNavInner">' + "\n";
				output += '				<ul class="navbar">' + "\n";
				for(var i in slide.obj) {
					output += '<li' + (i == 0 ? ' class="first"' : '') + '><a href="' + slide.obj[i].groupLink + '">' + slide.obj[i].group + '</a></li>';
				} 
				output += '				</ul>' + "\n";
				output += '			</div>' + "\n";
				output += '		</div>' + "\n";
				output += '		</div>' + "\n";
			break;
			case 'tabs':
				output += '		<div class="topNavTarget">' + "\n"; // don't apply styles to this, it's just a hook for the js
				output += '		<ul class="tabNav clrNM">' + "\n";
				for(var i in slide.obj) {
					output += '			<li class="' + slide.obj[i].align + '">' + "\n";
					output += '				<a href="' + slide.obj[i].groupLink + '">' + "\n";
					output += '					<span>' + slide.obj[i].group.replace(/ /g, '&nbsp;') + '</span>' + "\n";
					output += '				</a>' + "\n";
					output += '			</li>' + "\n";
				}
				output += '		</ul>' + "\n";
				output += '		</div>' + "\n";
			break;
		}
		return output;
	},

	// build initial html
	build:function() {
		
		var customScrollNavClass = (slide.conf.menuStyle == 'tabs' ? ' tabStyle' : '');
			
		var output = '';
		output += '	<div id="' + slide.conf.slID + '" class="scrollNav">' + "\n";
		output += '	<div class="scrollNavWrapper">' + "\n";
		
		output += slide.buildNav();

		output += '		<div class="scrollNavInner' + customScrollNavClass + '">' + "\n";
		//output += '			<div class="prev">Previous</div>' + "\n";
		
		output += '			<div class="hider">' + "\n";
		
		for(var i in slide.obj) {
			output += '				<div class="slider set' + i + '" style="width: ' + parseInt(	Math.ceil(slide.obj[i].items.length/slide.obj[i].override.numItems) * slide.obj[i].override.panelWidth, 10) + 'px;">' + "\n";
			output += '					<div class="container">' + "\n";
			output += '						<ul>' + "\n";
			
			for(var x in slide.obj[i].items) {
				if(x > 0 && x%slide.obj[i].override.numItems == 0) {
					output += '						</ul>' + "\n";
					output += '					</div>' + "\n";	
					output += '					<div class="container">' + "\n";
					output += '						<ul>' + "\n";
				}
				
				output += '							<li class="item">' + "\n";
				output += '								<a href="' + slide.obj[i].items[x].link + '">';
				output += '<span class="img"><img src="' + slide.obj[i].items[x].img + '" alt="' + slide.obj[i].items[x].name + '" title="' + slide.obj[i].items[x].name + '" height="' + slide.obj[i].override.imgMinY + '" width="' + slide.obj[i].override.imgMinX + '" /></span>';
				output += (slide.obj[i].items[x].hideLabel || slide.obj[i].override.hideAllLabels ? '' : '<span class="text">' + slide.obj[i].items[x].name) + '</span>';
				output += '								</a>' + "\n";
				output += '							</li>' + "\n";
			}

			output += '						</ul>' + "\n";
			output += '					</div>' + "\n";			
			output += '				</div>' + "\n";	
		}
					
		output += '			</div>' + "\n";
		//output += '			<div class="next">Next</div>' + "\n";
		output += '		</div>' + "\n";
		//output += '		<div class="topBorder">&nbsp;</div>' + "\n";
		output += '	</div>' + "\n";
		output += '	</div>' + "\n";
	
		return output;
	},
	
	// populate an object with some data to build the nav
	popData:function() {
		$(slide.dataEl.el + ' ' + slide.dataEl.row).each(function(s, e) {
			var gAlign = ($(e).find(slide.dataEl.group).eq(0).hasClass('alignRight') ? 'right' : 'left');
			slide.obj[s] = {
				offsetLeft:0,
				num:s,
				group:$(e).find(slide.dataEl.group).eq(0).html(),
				groupLink:$(e).find(slide.dataEl.group).eq(0).attr('href'),
				items:new Array(),
				align:gAlign
			};
			gAlign = null;
			
			// override styles for sizes
			slide.obj[s].override = new Array();
			if($(e).find(slide.dataEl.override).length > 0) {
				var tmpArr = $(e).find(slide.dataEl.override).text();
				tmpArr = $.trim(tmpArr).split(slide.dataEl.delimit);	
				
				var sizeArr = new Array();
				for(var i in tmpArr) {
					var tmpKey = tmpArr[i].split('=')[0];
					var tmpVal = tmpArr[i].split('=')[1];
					tmpKey = $.trim(tmpKey);
					tmpVal = $.trim(tmpVal);
					
					
					sizeArr[i] = {
						key:tmpArr[i].split('=')[0],
						value:tmpArr[i].split('=')[1]
					}					
				}

				for(var i in sizeArr) {
					slide.obj[s].override[sizeArr[i].key] = sizeArr[i].value;
				}
				tmpArr = null;
			}

			$(e).find(slide.dataEl.item).each(function(x, y) {
				
				var textElem = $(y).find('a');
				var hideLabel = textElem.hasClass('hideLabel') ? true : false;
				var imgElem = $(y).find('span.img');
				
				slide.obj[s].items[x] = {
					name:textElem.text(),
					link:textElem.attr('href'),
					img:imgElem.text(),
					hideLabel:hideLabel
				};
				
				textElem, hideLabel, imgElem = null;
			});
		});
		 
		// now check for additional configuration settigs passed with the data
		if($(slide.dataEl.el + ' ' + slide.dataEl.config).length > 0) {
			var tmpArr = $(slide.dataEl.el + ' ' + slide.dataEl.config).text();
			tmpArr = $.trim(tmpArr).split(slide.dataEl.delimit);

			var confArr = new Array();
			for(var i in tmpArr) {
				var tmpKey = tmpArr[i].split('=')[0];
				var tmpVal = tmpArr[i].split('=')[1];
				tmpKey = $.trim(tmpKey);
				tmpVal = $.trim(tmpVal);

				confArr[i] = {
					key:tmpArr[i].split('=')[0],
					value:tmpArr[i].split('=')[1]
				}
			}
			
			for(var i in confArr) {
				if(typeof("slide.conf[confArr[i].key]") != 'undefined') { // allows null or false values, e.g. 0
					slide.conf[confArr[i].key] = confArr[i].value;
				}	
			}
		}
		
		// now populate individual lists based on override data -> conf data -> defaults
		var out = '';
		for(var i in slide.obj) {
			$.each(['numItems', 'panelWidth', 'itemWidth', 'forceItemWidth', 'hideAllLabels', 'imgMaxX', 'imgMaxY', 'imgMinX', 'imgMinY', 'imgMarginTopOffset', 'imgMarginLeftOffset', 'forceLabelWidth'], function(s, e) {
				if(typeof(slide.obj[i].override[e]) == "undefined" && typeof(slide.conf[e]) != "undefined"){
					slide.obj[i].override[e] = slide.conf[e];
				}
			});
		}		
		
		// now dump the data element
		$(slide.dataEl.el).remove();
	},
	
	// grow or shrink our items
	animItem: function(elem, width, height, marginTop, marginLeft, speed, opac) {
		
		elem.stop().animate(
			{
				width: width,
				height: height, 
				marginTop: marginTop, 
				marginLeft: marginLeft,
				opacity: opac
			}, speed, 'linear'
		);
	},
	
	// figure out the heights required to open or close the whole panel
	toggle:function(act, initial) {
		
		if(slide.conf.initTimeOutObj != null) {
			clearTimeout(slide.conf.initTimeOutObj);
			slide.conf.initTimeOutObj = null;
		}

		var height = (act == 'open' ? slide.openHeight+'px' : '0px');
		//var padding = (act == 'open' ? '0px' : slide.openHeight+'px');
		var padding = (act == 'open' ? slide.openOuterHeight+'px' : (parseInt(slide.openOuterHeight, 10) - parseInt(slide.openHeight, 10))+'px');
		
		if(act == 'open') {
			if(slide.conf.normalTimeOutObj != null) {
				clearTimeout(slide.conf.normalTimeOutObj);
				slide.conf.normalTimeOutObj = null;
			}
		}
		if(initial || act == 'open') {
			slide.toggleDoSizing(height, padding, act, initial);
		} else {
			slide.conf.normalTimeOutObj = setTimeout( function(){
				slide.toggleDoSizing(height, padding, act, initial);
			}, slide.conf.normalTimeDelay);
		}
	},
	
	// do the open/close panel animation 
	toggleDoSizing:function(height, padding, act, initial){
		if(initial) {
			this.setPanelMouseEvents();
		}
		var callback = (act == 'open' ? '' : function(){ 
			$('#' + slide.conf.slID).find('ul.navbar li').removeClass('selected').removeClass('greyed'); 
		});
		$('div.scrollNav div.scrollNavInner').eq(0).stop().animate({ height: height }, slide.conf.panelSpeed, 'linear', callback );
	}	
}

