/*
 * All java script logic for the application.
 *
 * The code relies on the jQuery JS library to
 * be also loaded.
 */

var app = (function(jQuery){

	if (!jQuery) {
		alert(app.resources["MISSING_LIB"]);
		return null;
	}

	// Global dw private data goes here

	// dw scope public
	return {
		URLs			: {}, // holds dw specific urls, check htmlhead.isml for some examples
		resources		: {},  // resource strings used in js
		constants		: {}, // platform constants, initialized in htmlhead.isml
		containerId		: "content",
		ProductCache	: null,  // app.Product object ref to the current/main product
		clearDivHtml	: "<div class=\"clear\"><!-- W3C Clearing --></div>",
		currencyCodes	: {}, // holds currency code/symbol for the site
		preventInitDropdowns	: false,	// whether the MSDropDown plugin should be automatically loaded

		// default dialog box settings
		dialogSettings: {
				bgiframe: true, // this is required mainly for IE6 where drop downs bleed into dialogs!!! it depends on
				autoOpen: false,
				buttons: {},
				modal: true,
				overlay: {
		    		opacity: 0.5,
		     		background: "black"
				},
		    	height: 530,
		    	width: 800,
		    	title: '',
		    	// show: "slow", This is causing dialog to break in jquery 1.3.2 rel, show: "slide" works but not desired
		    	hide: "normal",
		    	resizable: false
		},

		// default tooltip settings
		tooltipSettings: {
				delay: 0,
				showURL: false,
				extraClass: "tooltipshadow tooltipshadow02",
				top: 15,
				left: 5
		},

		// global form validator settings
		validatorSettings: {
			errorClass : 'errorclient',
			errorElement: 'span',
			ignore:'.validignore',
			onsubmit:false,
		    onfocusout: function(element) {
				if ( !this.checkable(element) ) {
					this.element(element);
				}
			}

		},

		// app initializations called from jQuery(document).ready at the end of the file
		init: function() {
			// register initializations here

			// quick view dialog div
			jQuery("<div/>").attr("id", "QuickViewDialog").html(" ").appendTo(document.body);

			// micicart object initialization
			this.minicart.init();

			// renders horizontal/vertical carousels for product slots
			jQuery('#horicarousel, .horicarousel').jcarousel({
	        	scroll: 1,
				itemVisibleInCallback: app.captureCarouselRecommendations
		    });

		    jQuery('#vertcarousel').jcarousel({
		        scroll: 1,
				vertical: true,
				itemVisibleInCallback: app.captureCarouselRecommendations
		    });

			// execute unobtrusive js code
			this.execUjs();

		    jQuery('#vertcarousel').css('overflow-y','hidden');
		    app.producttile.initAll();

		    // start the custom carousel
			this.customcarousel.init();
		},

		// sub namespace app.ajax.* contains application specific ajax components
		ajax: {
			Success: "success",
			currentRequests: {}, // request cache

			// ajax request to get json response
			// @param - reqName - String - name of the request
			// @param - async - boolean - asynchronous or not
			// @param - url - String - uri for the request
			// @param - data - name/value pair data request
			// @param - callback - function - callback function to be called
			getJson: function(options) {
				var thisAjax = this;

				// do not bother if the request is already in progress
				// and let go null reqName
				if (!options.reqName || !this.currentRequests[options.reqName]) {
					this.currentRequests[options.reqName] = true;
					if(options.async == "undefined") options.async = true;
					// make the server call
					jQuery.ajax({
						contentType: "application/json; charset=utf-8",
						dataType: "json",
						url		: options.url,
						cache	: true,
						async	: options.async,
						data	: options.data,

						success: function(response, textStatus) {
							thisAjax.currentRequests[options.reqName] = false;

							if (!response.Success) {
								// handle failure
							}

							options.callback(response, textStatus);
						},

						error: function(request, textStatus, error) {
							if (textStatus === "parsererror") {
								alert(app.resources["BAD_RESPONSE"]);
							}

							options.callback({Success: false, data:{}});
						}
					});
				}
			},

			// ajax request to load html response in a given container
			// @param - reqName - String - name of the request
			// @param - url - String - uri for the request
			// @param - data - name/value pair data request
			// @param - callback - function - callback function to be called
			// @param - selector - string - id of the container div/span (#mycontainer) - it must start with '#'
			load: function(options) {

				var thisAjax = this;

				// do not bother if the request is already in progress
				// and let go null reqname
				if (!options.reqName || !this.currentRequests[options.reqName]) {
					this.currentRequests[options.reqName] = true;
					// make the server call
					jQuery.ajax({
						dataType: "html",
						url		: options.url,
						cache	: true,
						data	: options.data,

						success: function(response, textStatus) {
							thisAjax.currentRequests[options.reqName] = false;

							if (options.selector) {
								jQuery(options.selector).html(response);
							}

							(options.callback != undefined ? options.callback(response, textStatus): null)
						},

						error: function(request, textStatus, error) {
							if (textStatus === "parsererror") {
								alert(app.resources["BAD_RESPONSE"]);
							}

							options.callback(null, textStatus);
						}
					});
				}
			}
		},

		// loads a product into a given container div
		// params
		// 		containerId - id of the container div, if empty then global app.containerId is used
		//		source - source string e.g. search, cart etc.
		//		label - label for the add to cart button, default is Add to Cart
		//		url - url to get the product
		//		id - id of the product to get, is optional only used when url is empty
		getProduct: function(options) { // id, source, start
			var cId 		= options.containerId || app.containerId;
			var source 		= options.source || "";
			var quickviewSimplified	= options.quickviewSimplified || false;
			var a2cBtnLabel = options.label || null;

			// show small loading image
			jQuery("#"+cId).html(app.showProgress("productloader"));

			var productUrl = options.url ? options.url : app.util.appendParamToURL(app.URLs.getProductUrl, "pid", options.id);

			productUrl = app.util.appendParamToURL(productUrl, "source", source);
			if (quickviewSimplified)
			{
				productUrl = app.util.appendParamToURL(productUrl, "quickviewSimplified", "true");
			}

			app.ajax.load({selector: "#"+cId, url: productUrl, callback: function(responseText, textStatus){
				// update the Add to cart button label if one provided
				(a2cBtnLabel != null ? jQuery("#"+cId+" .addtocartbutton:last").html(a2cBtnLabel) : '');
			}});
		},

		// sub name space app.minicart.* provides functionality around the mini cart
		minicart: {
			url   : '',  // during page loading, the Demandware URL is stored here
			timer : null, // timer for automatic close of cart item view

			// initializations
			init: function() {
				// reset all the existing event bindings
				app.minicart.reset();

				// bind hover event to the cart total link at the top right corner
				jQuery(".minicarttotal").click(function(e) {(app.minicart.isShow() ? app.minicart.close(): app.minicart.slide());});

				jQuery('.minicartcontent')
				.mouseenter(function(e) {
					clearTimeout(app.minicart.timer);
					app.minicart.timer = null;
				})
				.mouseleave(function(e) {
					clearTimeout(app.minicart.timer);
					app.minicart.timer = null;
					// after a time out automatically close it
					app.minicart.timer = setTimeout( 'app.minicart.close()', 6000 );
				});

				// register close button event
				jQuery('.minicartcontent .minicartclose').click(function() {
					app.minicart.close(0);
				});
			},

			// returns a boolean if a minicart is visible/shown or hidden
			isShow: function() {
				return jQuery('.minicartcontent').css('display') == 'none' ? false : true;
			},

			// reset minicart
			reset: function() {
				jQuery(".minicarttotal").unbind("hover");
				jQuery('.minicartcontent').unbind("mouseenter").unbind("mouseleave");
				jQuery('.minicartcontent .minicartclose').unbind("click");
			},

			// shows the given content in the mini cart
			show: function(html) {
				jQuery('#minicart').html(html);

				// bind all the events
				app.minicart.init();

				if(app.minicart.suppressSlideDown && app.minicart.suppressSlideDown()) {
					// do nothing
					// the hook 'MiniCart.suppressSlideDown()' should have done the refresh
				}
				else {
					app.minicart.slide();
				}
			},

			// slide down and show the contents of the mini cart
			slide: function() {
				if(app.minicart.suppressSlideDown && app.minicart.suppressSlideDown()) {
					return;
				}
				// add open class
				jQuery('#minicart').addClass('open');

				// show the item
				jQuery('#minicart .minicartContentTop').attr('style', 'width:' + (jQuery('.minicartcontent').outerWidth() - jQuery('.minicarttotal').outerWidth() - 9 ) + 'px');
				jQuery('.minicartcontent').slideDown('slow');//show("slide", { direction: "up" }, 1000);

				clearTimeout(app.minicart.timer);
				app.minicart.timer = null;

				// after a time out automatically close it
				app.minicart.timer = setTimeout( 'app.minicart.close()', 6000 );
				return false;
			},

			reload: function(url)
			{
				var successFunc = function (request) {
					jQuery('#minicart').html(request);
					app.minicart.init();
				}

				jQuery.ajax({
					type	: "POST",
					url		: url,
					cache	: true,
					success	: successFunc
				});
			},

			// adds a product to the mini cart
			// @params
			// progressImageSrc - source/url of the image to show when the item is being added to the cart
			// postdata - form data containing the product information to be added to mini-cart
			// callback - call back function/handler
			add: function(progressImageSrc, postdata, callback)
			{
				// get the data of the form as serialized string
				var postdata = postdata;

				// get button reference
				var addButtons = [];

				// the button to update
				var addButton = null;

				// it is an array of buttons, but we need only one all
				// other combinations are strange so far
				if (addButtons.length == 1)	{
					addButton = addButtons[0];
				}

				var previousImageSrc = null;

				// show progress indicator
				if (addButton != null) {
					previousImageSrc = addButton.src;
					addButton.src = progressImageSrc;
				}

				// handles successful add to cart
				var handlerFunc = function(req)	{
					// hide progress indicator
					if (addButton != null) {
						addButton.src = previousImageSrc;
					}

					// replace the content
					jQuery('#minicart').html(req);

					// bind all the events
					app.minicart.init();



					// display the addtocart popup
					jQuery.ajax({
						type	: "POST",
						url		: app.URLs.cartSummaryPopup,
						data	: postdata,
						success	: function(data)
						{
							if (app.minicart.suppressAddToCartPopup && app.minicart.suppressAddToCartPopup()) {
								// do nothing
								// the hook 'MiniCart.suppressAddToCartPopup()' should have done the refresh
								return;
							}

							jQuery("#addtocartpopup").html(data);

							jQuery("#addtocartpopup").dialog('option', "title", app.resources["ADDED_PRODUCTS_TO_CART"].replace("{0}", postdata.Quantity));
							jQuery("#addtocartpopup").dialog('open');

							var ul = jQuery('.addtocartpopup_recommendations');
						    var lis = ul.find('li');

						    // Move ratings div after pricing for all product tiles
						    lis.each(function() {
							    var $rating = $('div.BVCustomerRatings', this).eq(0);
							    var $pricing = $('div.pricing', this).eq(0);
							    // Move ratings div after pricing
							    $rating.insertAfter($pricing);
						    });

						    // Need to apply carousel inside this event, as long as heights
						    // and widths of carousel items are not known before the dialog
						    // div becomes visible.
						    ul.jcarousel({
						       	scroll: 1,
						       	itemVisibleInCallback: app.captureCarouselRecommendations
						    });

							// Provide that the heights of pricing and product name divs
							// are the same for all producttiles.
						    var maxPricingHeight = 0;
						    var maxNameHeight = 0;
					    	lis.each(function() {
								var pricingHeight = $('div.pricing', this).height();
								var nameHeight = $('div.name', this).height();
								if (pricingHeight > maxPricingHeight) {
									maxPricingHeight = pricingHeight;
								}
								if (nameHeight > maxNameHeight) {
									maxNameHeight = nameHeight;
								}
					    	});
					    	lis.each(function() {
					    		$('div.pricing', this).height(maxPricingHeight);
					    		$('div.name', this).height(maxNameHeight);
					    	});

					    	jQuery("#addtocartpopup").dialog('option', 'position', ['center','center']);
						}
					});


					if (callback) callback();
				}

				// handles add to cart error
				var errFunc = function(req) {
					// hide progress indicator
					if (addButton != null) {
						addButton.src = previousImageSrc;
					}				}

				// closes a previous mini cart
				app.minicart.close();

				// add the product
				jQuery.ajax({
								type	: "POST",
								url		: app.minicart.url,
								cache	: true,
								data	: postdata,
								success	: handlerFunc,
								error	: errFunc
							});
			},

			// closes the mini cart with given delay
			close: function(delay) {
				if ( app.minicart.timer != null || delay == 0) {
					clearTimeout( app.minicart.timer );
					app.minicart.timer = null;
					jQuery('.minicartcontent').fadeOut(); // hide with "slide" causes to fire mouse enter/leave events sometimes infinitely thus changed it to fadeOut
					// remove open class
					jQuery('#minicart').removeClass('open');
				}
			},

			// hook which can be replaced by individual pages/page types (e.g. cart)
			suppressSlideDown: function() {
				return false;
			},
			suppressAddToCartPopup: function() {
				return false;
			}
		},

		// close quick view dialog if open and refresh the page
		refreshCart: function() {
			app.quickView.close();

			// refresh without posting
			location.href = location.href;
		},

		// Product quick view object
		quickView: {
			timer1 : '',
			// bind browser events
			// options
			// buttonSelector - css selector for the quickview button
			// imageSelector - css selector for product image
			// buttonLinkSelector - css selector for quickview button link (a tag)
			// productNameLinkSelector - css selector for product name link (a tag)
			bindEvents: function(options) {
				// hide quickview buttons
				jQuery(options.buttonSelector).hide();
				// hovering
				/*jQuery(options.imageSelector).hover(
					function(e) {
						jQuery(this).children(options.buttonSelector).show();
						return false;
					},
					function(e) {
						jQuery(this).children(options.buttonSelector).hide();
						return false;
					}
				);*/
					// regular execution
				jQuery.each(jQuery(options.imageSelector), function () {
					var img = jQuery(this);
					var parent = img.parents(".bcFaceProduct");
					if (parent.length > 0) {
						parent.find("button.quickview").unbind().bind("click", function() {
							var linkUrl = img.find("a#productUrl")
							var url;
							if(linkUrl.size()>=1) {
								url = linkUrl.attr("href");
								app.quickView.show({url: url, source: "quickview", el: this});
							}
							return false;
						});
					} else {
						img.unbind().hover(function(e) {
							var linkUrl = jQuery(this).find("a#productUrl");
							var url;
							if(linkUrl.size()>=1) {
								url = linkUrl.attr("href");
								app.quickView.show({url: url, source: "quickview", el: this});
							}
							return false;
						});

						jQuery(options.imageSelector).mouseleave(function(){
							if(app.quickView.timer1 != null) {
								clearTimeout(app.quickView.timer1);
							}
						});
					}
				});

				if (options.bundleLinkSelector)
				{
					jQuery(options.bundleLinkSelector).unbind();

					jQuery(options.bundleLinkSelector).hover(function(e) {
						var url = jQuery(this).attr("href");
						if(typeof(url) != 'undefined' && url != null) app.quickView.show({url: url, source: "quickview", el: this});
						return false;
					});

					jQuery(options.bundleLinkSelector).mouseleave(function(){
						if(app.quickView.timer1 != null) {
							clearTimeout(app.quickView.timer1);
						}
					});
				}

				/*
				To make bookmarking and browser back-button work correctly the browser URL needs
				to change. To force that change we do a full-page load (not AJAX) when going from
				search result page to product detail page.
				The implementation supports loading the product detail content with AJAX: just
				uncomment this code block to bind the event handler.

				// click binding for name link
				if(options.productNameLinkSelector) {
					jQuery(options.productNameLinkSelector).click(function(e) {
						app.getProduct({url: this.href, source: "search"});
						return false;
					});
				}
				*/
			},

			// show quick view dialog and send request to the server to get the product
			// options.source - source of the dialog i.e. search/cart
			// options.url - product url
			show: function(options) {
				app.quickView.timer1 = setTimeout(function() {

					// check if element is still there and if not - don't show quickview
					// this can happen if the element disappears and in this case the onmouseleave event is not fired (onmouseleave prevents this function from calling)
					if (jQuery(options.el).offset().top < 1 && jQuery(options.el).offset().left < 1)
						return;

					app.createDialog({id: 'QuickViewDialog', options: {
						modal: false,
				    	height: 'auto',
				    	width: 'auto',
				    	dialogClass: 'quickview',
				    	draggable : false,
				    	position: [0,0],
				    	resizable: false
					}});

					// if the page is opened with HTTPS, make sure the QuickView uses HTTPS also, otherwise the it breaks in some cases
					if (document.location.href.indexOf('https://') > -1) {
						options.url = options.url.replace('http://', 'https://');
					}

					var qvSimplified = false;
					if (jQuery(options.el).parents('.producttile').hasClass('quickviewSimplified'))
					{
						qvSimplified = true;
					}

				    app.getProduct({containerId: "QuickViewDialog", source: options.source, url: options.url, label: options.label, quickviewSimplified: qvSimplified});
				    //jQuery(options.el).parent('.producttile').append(jQuery('.quickview'));
				    //jQuery('.quickview ').attr('style',  jQuery('.quickview ').attr('style')+'top:0;');
				    if (jQuery(options.el).parents('#rightcolumn').length > 0) {
				    	var this_offset = jQuery(options.el).parents('.producttile').offset();
					    jQuery('#QuickViewDialog').dialog("option", "position", [this_offset.left - 124, this_offset.top - jQuery(window).scrollTop()]);
					    jQuery('#QuickViewDialog').dialog('open');
				    } else if (jQuery(options.el).parents('.bcFaceProduct').length > 0) {
				    	var this_offset = jQuery(options.el).parents('.bcFaceProduct').find('.producttile').offset();
				    	jQuery('#QuickViewDialog').dialog("option", "position", [this_offset.left - 124, this_offset.top - jQuery(window).scrollTop() - 27]);
					    jQuery('#QuickViewDialog').dialog('open');
					} else if( jQuery('#pdpBundleDiv').length == 0 ){
				    	var this_offset = jQuery(options.el).parents('.producttile').offset();
					    jQuery('#QuickViewDialog').dialog("option", "position", [this_offset.left - 54, this_offset.top - jQuery(window).scrollTop()]);
					    jQuery('#QuickViewDialog').dialog('open');
				    } else {
					    var this_offset = jQuery(options.el).parents('.productsetdetail .productname').offset();
					    jQuery('#QuickViewDialog').dialog("option", "position", [this_offset.left - 54, this_offset.top - jQuery(window).scrollTop()]);
					    jQuery('#QuickViewDialog').dialog('open');
				    }

				    jQuery(document.body).mouseup(function(e){
				        if(!jQuery(e.target).parents('#QuickViewDialog').length > 0 && !app.producttile.mouse_is_inside) app.quickView.close();
				    });
				}, 1000);

			},
			// close the quick view dialog
			close: function() {
				jQuery('#QuickViewDialog').dialog('close');
				clearTimeout(app.quickView.timer1);
			}
		},

		// helper method to create a dialog with the given options
		// options - dialog box options along with id of the container
		createDialog: function(options) {
			jQuery('#'+options.id).dialog(jQuery.extend({}, app.dialogSettings, options.options));
		},

		// shows tooltip popup
		// options
		// id - id of the container
		// options - tooltip popup options
		tooltip: function(options) {
			if (options.id.charAt(0) !== '#') {
				options.id = "#"+options.id;
			}
			jQuery(options.id).tooltip(jQuery.extend({}, app.tooltipSettings, options.options));
		},

		/**
		 * Unobtrusively build tooltips on the page.
		 * it looks for a tooltip class anchor which contains a div with tooltip-body class as the body container.
		 */
		tooltipDefault: function () {
			 jQuery(document).ready(function() {
				jQuery(".tooltip").tooltip(jQuery.extend({}, app.tooltipSettings, {
						bodyHandler: function() {
							return jQuery(this).children(".tooltip-body").html();
						}
					}
				));
			 });
		},

		drawer : function () {
			jQuery.each(jQuery('.drawer:not(.accordion) .drHeaderWrapper'), function () {

				jQuery(this).unbind().click(function () {
		 	 	 	var parent = jQuery(this).parents('.drawer');
		 	 	 	if (parent.hasClass('open')) {
			 	 	 	parent.addClass('close').removeClass('open').children('.drContent').hide('fast');
			 	 	 	jQuery(this).children('.drHeader').children('.backtotop').hide();
		 	 	 	} else {
			 	 	 	parent.addClass('open').removeClass('close').children('.drContent').show('fast');
			 	 	 	jQuery(this).children('.drHeader').children('.backtotop').show();
		 	 	 	}
		 	 	 	return false;
		 	 	});


				jQuery(this).parents('.drawer.close').children('.drContent').hide();
				jQuery(this).children('.drHeader').children('.backtotop').hide();
				jQuery(this).children('.drHeader').children('.backtotop').click(function () {
					jQuery('html,body').animate({ scrollTop: 0 }, 'slow');
					return false;
				});
				jQuery(this).parents('.drawer.open').children('.drContent').attr('style', 'display:block;');
			});
		},
		
		accordion : function () {
			jQuery.each(jQuery('.drawer.accordion .drHeaderWrapper'), function () {

				jQuery(this).unbind().click(function () {
		 	 	 	var parent = jQuery(this).parents('.drawer');
		 	 	 	if (parent.hasClass('open')) {
			 	 	 	parent.addClass('close').removeClass('open').children('.drContent').hide('fast');
		 	 	 	} else {
		 	 	 		parent.parents('.accordions').children('.accordion.open').addClass('close').removeClass('open').children('.drContent').hide('fast');
			 	 	 	parent.addClass('open').removeClass('close').children('.drContent').show('fast');
		 	 	 	}
		 	 	 	return false;
		 	 	});

				jQuery(this).parents('.drawer.accordion.close').children('.drContent').hide();
				jQuery(this).parents('.drawer.accordion.open').children('.drContent').attr('style', 'display:block;');
			});
		},

		// renders a progress indicator on the page; this function can be used
		// to indicate an ongoing progress to the user; the optional parameter "className"
		// can be used to attach an additional CSS class to the container
		showProgress : function(className) {
			var clazz = "loading";
			if (className) clazz += " " + className;
			return jQuery("<div class=\"" + clazz + "\"/>").append(jQuery("<img/>").attr("src", app.URLs.loadingSmallImg));
		},

		// validation plugin intialization
		validator: function() {

			// override default required field message
			jQuery.validator.messages.required = function($1, ele, $3) {
				return "";
			};

			jQuery.validator.messages.email = function($1, ele, $3) {
				return "";
			};
			jQuery.validator.messages.rangelength = function($1, ele, $3) {
				return "";
			}

			/**
			 * Add positive number validation method to jQuery validation plugin.
			 * Text fields must have 'positivenumber' css class to be validated as positivenumber
			 * it validates a number and throws error if it is below 0 or if it is not a number.
			 */
			jQuery.validator.addMethod("positivenumber", function(value, element) {
				if (value == '') return true;
				return /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value) && Number(value) >= 0;
			}, ""); // "" should be replaced with error message if needed

			// register form validator for form elements
			// except for those which are marked "suppress"
			jQuery.each(jQuery("form:not(.suppress)"), function() {
				jQuery(this).validate(app.validatorSettings);
			});
		},

		/**
		 * grab anything inside a hidden dom element and append it to its immediate previous sibling
		 * as data attribute i.e. jQuery().data("data", hiddenStr)
		 * if the hidden data specifies json in the class then this routine would attempt to
		 * convert the hidden data into json object before adding it as data attribute.
		 * after adding the data, the hidden span/element is removed from the DOM.
		 */
		hiddenData : function() {
			jQuery.each(jQuery(".hidden"), function() {
				var hiddenStr = jQuery(this).html();

				if (hiddenStr === "") {
					return;
				}

				// see if its a json string
				if (jQuery(this).hasClass("json")) {
					// try to parse it as a json
					try {
						hiddenStr = window["eval"]("(" + hiddenStr + ")");
					}
					catch(e) {}
				}

				jQuery(this).prev().data("data", hiddenStr);

				jQuery(this).remove();
			});
		},

		/**
		 * Process country drop downs and attach a change listener so that phone field
		 * can be validated properly based on the currently selected country.
		 */
		addCountryListener: function() {
			var countryHandler = function(e) {
				var selectedCountry = this.options[this.selectedIndex].value;
				// for each field of type phone in the current form, set its country as a data attribute
				// to be used while doing phone field validatiaon see app.validator addMethod.
				jQuery(this).parents("form:first").find("input.phone").each(function() {
					var data = jQuery(this).data("data");
					var currentData = (data && typeof data == 'object') ? data : {};
					currentData.country = selectedCountry;
					jQuery(this).data("data", currentData);
				});
			}
			jQuery("select.country").change(countryHandler).each(countryHandler);
		},

		/**
		 * Unobtrusive js api calls go here.
		 */
		 execUjs: function() {
			// process hidden data in the html markup and cnnvert it into data object(s)
			this.hiddenData();

			// initialize form validator plugin
			this.validator();

			// process country form fields and attach listeners
			this.addCountryListener();

			// process tooltips on the page
			this.tooltipDefault();

			// apply styling to dropdowns
			if (!this.preventInitDropdowns) {
				this.initDropdowns();
			}

			// process drawers on the page
			this.drawer();
			this.accordion();

		},

		// capture recommendation of each product when it becomes visible in the carousel
		captureCarouselRecommendations : function(c, li, index, state) {
			jQuery(li).find(".captureproductid").each(function() {
				dw.ac.capture({id:this.innerHTML, type:dw.ac.EV_PRD_RECOMMENDATION});
			});
		},

		// sub namespace app.producttile.* contains utility functions for product tiles
		producttile : {
			mouse_is_inside: false,
			isOpen : false,
			timer : '',
			initColors: function () {

				// mark the nonorderable variants - place a white "X" on them
				jQuery(".swatches a.swatch.nonorderable").each(function(i, item)
				{
					if (jQuery(item).find("img.nonorderablemask").length < 1)
					{
						jQuery(item).append("<img class='nonorderablemask' src='" + app.URLs.swatchInactive + "' />");
					}
				});

				// dialog on mouse over swatch
				var hoveredSwatch;
				jQuery("a.swatchpopup").bind('mouseenter', function(e) {

					app.producttile.mouse_is_inside = false;
					app.producttile.closeColor();
					app.producttile.mouse_is_inside = true;

					hoveredSwatch = jQuery(this);

					if (jQuery("#selectcolordialog").length < 1) {
						var selectcolordialog_html = "<div id='selectcolordialog'><div id='selectcolordialog_description'></div><img id='selectcolordialog_image' alt='' /><div id='selectcolordialog_outofstock'>" + app.resources["OUTOFSTOCK"] + "</div><div class='clear'></div><button class='secondary' id='selectcolordialog_btnselect'><span>" + app.resources["PRODUCTTILE_SWATCHPOPUP_SELECT"] + "</span></button></div>";
						jQuery("#container").append(selectcolordialog_html);

						var selectcolordialog = jQuery("#selectcolordialog");

						jQuery(selectcolordialog).dialog({
							autoOpen	: false,
							resizable	: false,
							draggable	: false,
							width		: 170,
							dialogClass	: 'selectcolordialog'
						});

						jQuery('#selectcolordialog_btnselect').click(function()
						{
							app.producttile.mouse_is_inside = false;
							app.producttile.closeColor();

							// fire the click handlers
							jQuery(hoveredSwatch).trigger('click');
						});
					}

					var selectcolordialog = jQuery("#selectcolordialog");

					var variantJSON = jQuery(this).data("productjson");

					jQuery('#selectcolordialog_image').attr('src', '');		// remove the old image first to avoid displaying the wrong image, while the new one is loading
					jQuery('#selectcolordialog_image').attr('src', variantJSON.images.small.httpURL);
					jQuery('#selectcolordialog_description').html(variantJSON.custom.colourDescription);
					jQuery(selectcolordialog).dialog("option", "title", variantJSON.custom.colourName);

					if (jQuery(hoveredSwatch).hasClass("nonorderable") || jQuery(hoveredSwatch).parents("li").hasClass('nonorderable')) {
						jQuery('#selectcolordialog_outofstock').show();
					} else {
						jQuery('#selectcolordialog_outofstock').hide();
					}

					var this_offset = jQuery(this).offset();

					jQuery(selectcolordialog).dialog("option", "position", [this_offset.left, this_offset.top + 21 - jQuery(window).scrollTop()]);
					jQuery(selectcolordialog).dialog("open");

					jQuery('.selectcolordialog').hover(function(){
				        app.producttile.mouse_is_inside = true;
				    }, function(){
				    	app.producttile.mouse_is_inside = false;
				    	app.producttile.closeColor();
				    });

					jQuery(hoveredSwatch).mouseleave(function() {
						app.producttile.mouse_is_inside =  false;
						app.producttile.timer = setTimeout('if (!app.producttile.mouse_is_inside) app.producttile.closeColor();', 300)
					});

					return false;
				});


				// all available colors dialog
				jQuery("a.morecolors").bind('mouseover', function(e)
				{
					app.producttile.closeColor();

					app.producttile.mouse_is_inside = true;
					jQuery(".ui-dialog.morecolorsdialog").html('');

					if (jQuery("#morecolorsdialog").length < 1)
					{
						if (!jQuery(this).hasClass("isQuickView"))
						{
							// we are on a category/compare page and swatches are standard A links (no LIs)
							var morecolorsdialog_html = "<div id='morecolorsdialog'><div id='morecolorsdialog_description'>"
								+ app.resources["PRODUCTTILE_CLICKSWATCH"]
								+ "</div><div class='innerpalette'></div>"
								+ "</div>";

							jQuery("#container").append(morecolorsdialog_html);

							// get the list of swatch links
							var swatchLinks = jQuery(this).parent().find("div.innerpalette a.swatch").each(function(i, originalLink)
							{
								var newLink = jQuery(originalLink).clone();
								jQuery(newLink).data('productjson', jQuery(originalLink).data('productjson'));

								jQuery(newLink).bind('click', function()
								{
									jQuery(this).parent().find("a.swatch").removeClass("selected");
									jQuery(this).addClass("selected");
									jQuery(originalLink).trigger('click');
									return false;
								});

								jQuery(newLink).appendTo("#morecolorsdialog .innerpalette");
							});
						}
						else
						{
							// we are on a product page (quickview) and swatches are LIs
							var morecolorsdialog_html = "<div id='morecolorsdialog'><div id='morecolorsdialog_description'>"
								+ app.resources["PRODUCTTILE_CLICKSWATCH"]
								+ "<div class='variationattributes'><div class='color'><ul class='swatchesdisplay'></ul></div></div>"
								+ "</div></div>";

							jQuery("#container").append(morecolorsdialog_html);

							// get the list of swatch links
							var swatchLinks = jQuery(this).parents(".swatches").find("a.swatch").each(function(i, originalLink)
							{
								var newLI = jQuery(originalLink).parent().clone();

								var newLink = jQuery(newLI).find("a.swatch");
								jQuery(newLink).addClass("clearfix");
								jQuery(newLink).data('productjson', jQuery(originalLink).data('productjson'));

								jQuery(newLink).html("&nbsp;");
								jQuery(newLink).bind('click', function()
								{
									jQuery('#QuickViewDialog .pdpFullDetailsLink a').attr('href', jQuery(this).attr('href'));
									jQuery('#QuickViewDialog .productimages .productimage a').attr('href', jQuery(this).attr('href'));
									jQuery(this).parents("ul.swatchesdisplay").find("li").removeClass("selected");
									jQuery(this).parent().addClass("selected");

									jQuery(originalLink).trigger('click');
									return false;
								});
								jQuery(newLink).bind('mouseover', function()
								{
									jQuery(originalLink).trigger('mouseover');
								});
								jQuery(newLink).bind('mouseout', function()
								{
									jQuery(originalLink).trigger('mouseout');
								});

								jQuery(newLI).appendTo("#morecolorsdialog ul.swatchesdisplay");
							});
						}


						var morecolorsdialog = jQuery("#morecolorsdialog");

						jQuery(morecolorsdialog).dialog({
							autoOpen	: false,
							resizable	: false,
							draggable	: false,
							width		: 230,
							minHeight	: 0,
							dialogClass	: 'morecolorsdialog'
						});

						jQuery('.ui-dialog.morecolorsdialog').hover(function(){
					        app.producttile.mouse_is_inside = true;
					    });

						jQuery('.ui-dialog.morecolorsdialog, a.morecolors').mouseleave(function() {
							app.producttile.mouse_is_inside =  false;
							app.producttile.timer = setTimeout(function() { if (!app.producttile.mouse_is_inside) app.producttile.closeColor(); }, 300)
						});
					}


					var morecolorsdialog = jQuery("#morecolorsdialog");

					var this_offset = jQuery(this).offset();
					var dialogWidth = $(morecolorsdialog).parents('.ui-dialog:first').width();

					var offsetLeft = ((jQuery('body').innerWidth() - this_offset.left) > dialogWidth) ? this_offset.left : jQuery('body').innerWidth() - dialogWidth;

					jQuery(morecolorsdialog).dialog("option", "title", app.resources["PRODUCTTILE_ALLAVAILABLECOLORS"]);
					jQuery(morecolorsdialog).dialog("option", "position", [offsetLeft, this_offset.top + 27 - jQuery(window).scrollTop()]);
					jQuery(morecolorsdialog).dialog("open");

					return false;
				});
			},

			closeColor: function () {
				if (!app.producttile.mouse_is_inside) {
					clearTimeout(app.producttile.timer);
					jQuery("#selectcolordialog").dialog("close");
					jQuery("#morecolorsdialog").dialog("close");
				}
			},

			// initializes all product tiles contained in the current page
			initAll: function() {
				// bind quick view button toggling and click
				var quickViewOptions = {
					buttonSelector: "div.producttile div.quickviewbutton",
					imageSelector: "div.producttile div.image",
					buttonLinkSelector: "div.producttile div.quickviewbutton a",
					bundleLinkSelector: ".bundleinstance .productsetdetail .productname a"
				};
				app.quickView.bindEvents(quickViewOptions);
				// bind quick view after ajax request.
				jQuery(document).ajaxComplete(function () {
					var quickViewOptions = {
						buttonSelector: "div.producttile div.quickviewbutton",
						imageSelector: "div.producttile div.image",
						buttonLinkSelector: "div.producttile div.quickviewbutton a",
						bundleLinkSelector: ".bundleinstance .productsetdetail .productname a"
					};
					app.quickView.bindEvents(quickViewOptions);
				});

				// prepare swatch palettes and thumbnails
				jQuery("div.producttile div.swatches div.invisible").hide();
				jQuery("div.producttile div.swatches a.swatch img.hiddenthumbnail").hide();

				// show the palette
				jQuery("div.producttile div.swatches > a").click(function(e) {
					var cont = jQuery(this).parent().find("div.palette");
					cont.show().focus();
					return false;
				});

				// hide the palette
				jQuery("div.producttile div.swatches div.invisible").mouseout(function(e) {
					// fix for event bubbling (http://www.quirksmode.org/js/events_mouse.html)
					if(!e) var e = window.event;
					var tg = (window.event) ? e.srcElement : e.target;
					if(tg.nodeName != 'DIV') return;
					var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
					while(reltg != tg && reltg.nodeName != 'BODY')
						reltg = reltg.parentNode
					if (reltg == tg) return;

					// mouseout took place when mouse actually left layer
					// handle event now
					jQuery(this).hide();
					return false;
				});

				// color swatch selection
				jQuery("div.producttile div.swatches div.palette a.swatch").bind('click', function(e) {
					var swatch = jQuery(this);
					app.producttile.selectVariation(swatch);
					// omit following the swatch link
					return false;
				});

				this.initColors();

			},

			// selects a certain variation in a product tile, replaces the current image with
			// the correct variation image, changes the link to the detail
			// page and the quick view
			selectVariation : function(swatch) {

				// get the new and the original image
				var currentImg = jQuery(swatch).parents(".producttile").find(".productimage img");
				var newImg = jQuery(swatch).children("img.hiddenthumbnail");
				if(!newImg.length || !currentImg.length) return;

				// replace the image
				jQuery(currentImg).attr('src', jQuery(newImg).attr('src'));

				// update the main image link
				var mainImgLink = jQuery(swatch).parents(".producttile").find(".productimage a");
				jQuery(mainImgLink).attr('href', jQuery(swatch).attr('href'));

				// update the main link
				var mainLink = jQuery(swatch).parents(".producttile").find(".name a");
				jQuery(mainLink).attr('href', jQuery(swatch).attr('href'));
				//jQuery(mainLink).text(jQuery(swatch).attr('title'));

				// mark as selected
				jQuery(jQuery(swatch).parent()).find("a.swatch").removeClass("selected");
				swatch.addClass("selected");
			},

			// shows the thumb nail of a product; this function is used to
			// temporally display a new image and restore the original one
			toggleVariationThumbnail : function(swatch) {
				// get the new and the original image
				var currentImg = jQuery(swatch).parents(".producttile").find(".productimage img");
				var newImg = jQuery(swatch).children("img.hiddenthumbnail");
				if(!newImg.length || !currentImg.length) return;

				// we do nothing in case the swatch is already selected
				if(jQuery(swatch).hasClass("selected")) return;

				if(jQuery(currentImg).hasClass("temp")) {
					// current image is just a temp image
					// restore original and reset temp image
					var currentCopy = currentImg.clone().hide().removeClass("temp").addClass("hiddenthumbnail");
					var newCopy = newImg.clone().show().removeClass("original hiddenthumbnail");
					currentImg.replaceWith(newCopy[0]);
					newImg.replaceWith(currentCopy[0]);
				} else {
					// we create copies of each image, replace
					// the current with the copies and mark them with classes
					var currentCopy = currentImg.clone().hide().addClass("original hiddenthumbnail");
					var newCopy = newImg.clone().show().addClass("temp").removeClass("hiddenthumbnail");
					currentImg.replaceWith(newCopy[0]);
					newImg.replaceWith(currentCopy[0]);
				}
			}
		},

		// sub namespace app.util.* contains utility functions
		util : {
			// disables browser auto completion for the given element
			disableAutoComplete : function(elemId) {
				jQuery("#"+elemId).attr("autocomplete", "off");
			},

			// trims a prefix from a given string, this can be used to trim
			// a certain prefix from DOM element IDs for further processing on the ID
			trimPrefix : function(str, prefix) {
				return str.substring(prefix.length);
			},

			// appends the parameter with the given name and
			// value to the given url and returns the changed url
			appendParamToURL : function(url, name, value) {
				var c = "?";
				if(url.indexOf(c) != -1) {
					c = "&";
				}
				return url + c + name + "=" + encodeURIComponent(value);
			},

			// dynamically loads a CSS file
			loadCSSFile : function(url) {
				var elem = document.createElement("link");
				elem.setAttribute("rel", "stylesheet");
				elem.setAttribute("type", "text/css");
				elem.setAttribute("href", url);

				if(typeof elem != "undefined") {
					document.getElementsByTagName("head")[0].appendChild(elem);
					app.util.loadedCSSFiles.push(url);
				}
			},

			// array to keep track of the dynamically loaded CSS files
			loadedCSSFiles : [],

			// removes all dynamically loaded CSS files
			clearDynamicCSS : function() {
				for(var i=0; i<app.util.loadedCSSFiles.length; i++) {
					app.util.unloadCSSFile(app.util.loadedCSSFiles[i]);
				}
			},

			// dynamically unloads a CSS file
			unloadCSSFile : function(url) {
				var candidates = document.getElementsByTagName("link");
				for(var i=candidates.length; i>=0; i--) {
					if(candidates[i] && candidates[i].getAttribute("href") != null && candidates[i].getAttribute("href").indexOf(url) != -1) {
						candidates[i].parentNode.removeChild(candidates[i]);
					}
				}
			},

			// checks if cookies are enabled
			cookiesEnabled : function() {
				// first we'll split this cookie up into name/value pairs
				// note: document.cookie only returns name=value, not the other components
				var all_cookies = document.cookie.split( ';' );
				var temp_cookie = '';
				var cookie_name = '';
				var cookie_value = '';
				var cookie_found = false; // set boolean t/f default f

				for ( i = 0; i < all_cookies.length; i++ )
				{
					// now we'll split apart each name=value pair
					temp_cookie = all_cookies[i].split( '=' );

					// and trim left/right whitespace while we're at it
					cookie_name = temp_cookie[0].replace(/^\s+|\s+$/g, '');

					// if the extracted name matches the session cookie name
					if ( cookie_name == 'sid' )
					{
						// we need to handle case where cookie has no value but exists (no = sign, that is):
						if ( temp_cookie.length > 1 )
						{
							cookie_value = unescape( temp_cookie[1].replace(/^\s+|\s+$/g, '') );
						}

						if (cookie_value.length > 0)
						{
							cookie_found = true;
							break;
						}
					}
					temp_cookie = null;
					cookie_name = '';
				}
				return cookie_found;
			},

			// helper functions for handling cookies (from http://www.quirksmode.org/js/cookies.html)
			createCookie: function(name, value, days) {
				if (days) {
					var date = new Date();
					date.setTime(date.getTime()+(days*24*60*60*1000));
					var expires = "; expires="+date.toGMTString();
				}
				else var expires = "";
				document.cookie = name+"="+value+expires+"; path=/";
			},

			readCookie: function(name) {
				var nameEQ = name + "=";
				var ca = document.cookie.split(';');
				for(var i=0;i < ca.length;i++) {
					var c = ca[i];
					while (c.charAt(0)==' ') c = c.substring(1,c.length);
					if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
				}
				return null;
			},

			eraseCookie: function(name) {
				createCookie(name,"",-1);
			},

			/**
			 * IE 6 multiple button submit issue work around.
			 * when a form has multiple buttons of submit type, then IE 6 submits all of them
			 * whenever form is submitted. e.g. Remove on cart page would remove the wrong item
			 * (always first item in the cart) because IE 6 submits all form data which includes all
			 * remove links!!!
			 * the workaorund is to disable all buttons except the one which is being clicked.
			 * it should only be called for IE 6 (check out htmlhead.isml for usage)
			 */
			ie6ButtonFix: function() {
				jQuery('button').click(function(){
		        	// disable all buttons
		        	jQuery(this.form).find('button').attr("disabled", true);
		        	// enable the one being clicked
		            jQuery(this).attr("disabled", false);
			    });
			}
		},

		// sub namespace app.dialog.* provides convenient functions to handle dialogs
		// note, that this code relies on single dialog modals (multi dialog, e.g. modal in modal is not supported)
		dialog : {
			// opens a dialog using the given url
			open : function(url, title) {
				// create the dialog container if not present already
				if(jQuery("#dialogcontainer").length == 0) {
					jQuery(document.body).append("<div id=\"dialogcontainer\"></div>");
				}

				// set a default title
				title = title || "Dialog";

				// finally load the dialog, set the dialog title
				app.ajax.load({
					selector: "#dialogcontainer",
					url: url,
					callback: function() {
						app.dialog.checkOpen();
						app.dialog.setTitle(title);
					}
				});
			},

			// initializes the dialog with common dialog actions, like closing upon canceling
			// use this function in the dialog rendering template to re-bind common actions
			// upon dialog reload
			init : function() {
				jQuery(document).ready(function() {
					// binds the action to all buttons defining an action through the "name" attribute
					jQuery("#dialogcontainer button").each(function() {
						jQuery(this).click(function() {
							var action = jQuery(this).attr("name");
							if(action) {
								app.dialog.submit(action);
							}
							return false;
						});
					});

					// cancel button binding
					jQuery("#dialogCancelBtn").click(function() {
						app.dialog.close();
						return false;
					});
				});
			},

			// sets the title of the dialog
			setTitle : function(title) {
				jQuery("#dialogcontainer").dialog("option", "title", title);
			},

			// checks, if the dialog is in the state "open" and sets the state if not presently set
			// this function is implicitly called by app.dialog.open(url, title) in order to initialize
			// the dialog properly; use this function to recover the "open" state of a dialog
			checkOpen : function() {
				if(!jQuery("#dialogcontainer").dialog("isOpen"))
				{
					jQuery("#dialogcontainer").dialog({
						bgiframe: true,
						autoOpen: false,
						modal: true,
						overlay: {
				    		opacity: 0.5,
				     		background: "black"
						},
				    	height: 425,
				    	width: 460,
				    	resizable: false
					});
					jQuery("#dialogcontainer").dialog("open");
				}
			},

			// closes the dialog and triggers the "close" event for the dialog
			close : function() {
				jQuery("#dialogcontainer").dialog("close");
				jQuery(document.body).trigger("dialogClosed");
			},

			// attaches the given callback function upon dialog "close" event
			onClose : function(callback) {
				if(callback != undefined) {
					jQuery(document.body).bind("dialogClosed", callback);
				}
			},

			// triggers the "apply" event for the dialog
			triggerApply : function() {
				jQuery(document.body).trigger("dialogApplied");
			},

			// attaches the given callback function upon dialog "apply" event
			onApply : function(callback) {
				if(callback != undefined) {
					jQuery(document.body).bind("dialogApplied", callback);
				}
			},

			// triggers the "delete" event for the dialog
			triggerDelete : function() {
				jQuery(document.body).trigger("dialogDeleted");
			},

			// attaches the given callback function upon dialog "delete" event
			onDelete : function(callback) {
				if(callback != undefined) {
					jQuery(document.body).bind("dialogDeleted", callback);
				}
			},

			// submits the dialog form with the given action
			submit : function(action) {
				// set the action
				jQuery("#dialogcontainer form").append("<input name=\"" + action + "\" type=\"hidden\" />");

				// serialize the form and get the post url
				var post = jQuery("#dialogcontainer form").serialize();
				var url = jQuery("#dialogcontainer form").attr("action");

				// post the data and replace current content with response content
		  		jQuery.ajax({
				   type: "POST",
				   url: url,
				   data: post,
				   dataType: "html",
				   success: function(data){
		  				jQuery("#dialogcontainer").empty().html(data);
				   },
				   failure: function(data) {
					   alert(app.resources["SERVER_ERROR"]);
				   }
				});
			}
		},

		// Custom carousel
		customcarousel: {
			currentIndex: 1,
			itemsCount: 0,
			init: function() {
				app.customcarousel.itemsCount = jQuery(".custom-carousel .custom-carousel-item").length;
				if(app.customcarousel.itemsCount > 0) {
					app.customcarousel.createNavigation();
					app.customcarousel.bindEvents();
				}
				jQuery(".custom-carousel .custom-carousel-item-"+app.customcarousel.currentIndex).css("display","block");
				jQuery(".custom-carousel .custom-carousel-item-"+app.customcarousel.currentIndex).animate({
				    opacity: 1
				}, 1000, function() {
				    // Animation complete.
				});
			},

			createNavigation: function(){
				var currentHtml = jQuery(".custom-carousel").html();
				var navigation = "";
				navigation += '<div class="custom-carousel-buttons">';

				if (app.customcarousel.itemsCount > 1) {
					for(var i=1;i<=app.customcarousel.itemsCount;i++) {
						navigation += '<div class="custom-carousel-button-'+i+' custom-carousel-button"></div>';
					}
				}

				navigation += '</div>';
				jQuery(".custom-carousel").html(currentHtml+navigation);
				jQuery(".custom-carousel-button-"+app.customcarousel.currentIndex).addClass("selected");
			},


			bindEvents: function() {
				var navigationButtons = jQuery(".custom-carousel .custom-carousel-button");
				for(var i=0;i<navigationButtons.length;i++) {
					jQuery(navigationButtons[i]).click(function(){
						if(!jQuery(this).hasClass("selected")) {
							jQuery(".custom-carousel .custom-carousel-button-"+app.customcarousel.currentIndex).removeClass("selected");
							jQuery(".custom-carousel .custom-carousel-item").css({"display":"none","opacity":"0"});
							var buttonClasses = jQuery(this).attr("class")
							var buttonIDposition = buttonClasses.indexOf('custom-carousel-button-')+23;
							if(buttonIDposition<23) alert("ERROR: Perhaps, wrong HTML structure!");
							app.customcarousel.currentIndex = buttonClasses.charAt(buttonIDposition);
							jQuery(".custom-carousel .custom-carousel-button-"+app.customcarousel.currentIndex).addClass("selected");
							jQuery(".custom-carousel .custom-carousel-item-"+app.customcarousel.currentIndex).css("display","block");
							jQuery(".custom-carousel .custom-carousel-item-"+app.customcarousel.currentIndex).animate({
							    opacity: 1
							}, 1000, function() {
							    // Animation complete.
							});
						}
					});
				}
			}
		},
		
		initDDHooks: {
			init: function(e) {
				e.onActions = {onOpen: 'app.initDDHooks.open', onClose: 'app.initDDHooks.close'};
			},
			
			open: function (ddSelect) {
				var id = ddSelect.ddProp.id;
				var select = jQuery('#'+id); 
				jQuery('#'+id+'_msdd a.selected').focus();
				select.focus().bind("keyup", app.initDDHooks.selectKeyupEvent).bind("change", app.initDDHooks.selectChangeEvent);
			},
						
			close: function (ddSelect) {
				var id = ddSelect.ddProp.id;
				jQuery('#'+id).unbind('keyup', app.initDDHooks.selectKeyupEvent).unbind('change', app.initDDHooks.selectChangeEvent);
				if (jQuery('#'+id+'_msdd a.selected').text() != jQuery('#'+id+'_titletext span').text()) {
					ddSelect.set('selectedIndex', jQuery('#'+id).attr("selectedIndex"));
				};
			},

			selectChangeEvent: function () {
				var select = jQuery(this);
				var id = select.attr('id');
				jQuery('#'+id+'_msdd a').removeClass('selected');
				jQuery('#'+id+'_msa_'+select.attr("selectedIndex")).addClass('selected').focus();
				select.focus();
			},
			
			selectKeyupEvent: function (e) {
				if (e.keyCode != 38 && e.keyCode != 40) {
					if (e.keyCode != 13) {
						jQuery(this).change();
					} else {
						jQuery('#'+jQuery(this).attr('id')+'_msdd a.selected').click();
						return false;
					};
				};
			}
		},
		
		initDropdowns: function(container) {
			if (container != undefined && container.length > 0) {
				var selects = jQuery(container).find("select");
			} else {
				var selects = jQuery("body select");
			}

			jQuery(selects).msDropDown({onInit: this.initDDHooks.init, mainCSS: 'dd3'});

			jQuery(document).ajaxComplete(function () {
				jQuery.each(jQuery(selects), function () {
					if (jQuery(this).parent().length > 0 && !jQuery(this).parent().hasClass('ddOutOfVision')) {
						jQuery(this).msDropDown({onInit: this.initDDHooks.init, mainCSS: 'dd3', zIndex: 999});
					};
				})
			});
		},

		containerPosition: function() {
			var navigationContainerWidth = jQuery('#navigation').width();
			var navigationHalf = parseInt(navigationContainerWidth/2);

			jQuery("#navigation ul").children("li").children("div").each(function(i, element){

				var menuContainer = jQuery(element);
				var parentPosition = menuContainer.parents('li').position().left;
				var menuContainerWidth = menuContainer.width();
				var linkWidth = menuContainer.parents('li').find('a:first').width();
				var linkHalfWidth = parseInt(linkWidth/2);
				var leftOffssetHolder = 28;

				if ( parentPosition <= navigationHalf ) {
					if ( menuContainerWidth > navigationHalf ) {
						menuContainer.css("left", "63px");
					}
					menuContainer.find(".bgholder").css('left', parentPosition-leftOffssetHolder-63+linkHalfWidth);
				} else {
					if ( menuContainerWidth > navigationHalf ) {
						menuContainer.css("right", "58px");
					}
					menuContainer.find(".bgholder").css('left', parentPosition-menuContainer.position().left-leftOffssetHolder+linkHalfWidth);
				}
			});
		}
	}
})(jQuery);

// application initialization on dom ready
jQuery(document).ready(function(){
	app.init();
});

