/*
 * All java script logic for the application. 
 *
 * The code relies on the jQuery JS library to
 * be also loaded.
 */
// application initialization on dom ready
var DOMUtils = { 
	_listeners : []
};
DOMUtils.registerBehaviors = function(listener){
	var index = jQuery.inArray(listener,DOMUtils._listeners);
	if( index < 0 ) {
		DOMUtils._listeners.push(listener);
	}
};
DOMUtils.unregisterBehaviors = function(listener){
	var index = jQuery.inArray(listener,DOMUtils._listeners);
	if( index > -1 ) {
		DOMUtils._listeners.splice(index,1);
	}
};
DOMUtils.enhanceDOM = function (root) {
	var base = root || document.body;
	
	// Enable ContentAsset banners
	jQuery('.presentify',base).presentify({itemCSS:'.contentasset'});
	
	// Enable base functionality
	app.init(base);
		 
	// sub menu-drop down reveal code
	jQuery('#main-nav li:has(a.top-cat)').mouseenter(function(){
		var that = jQuery(this);
		var ddLeft = that.offset().left;
		var pLeft = jQuery('#main-nav').offset().left;
		var pWidth = jQuery('#main-nav').width();
		var numCols = that.find('.dropnav ul').size();
		var ddWidth = 180*numCols;
		
		var maxLeft = pLeft+pWidth-ddWidth-20;// 20 is padding on dropnav div
		
		that.find('.dropnav').css({width:ddWidth});
		if( ddLeft>=maxLeft ) {
			that.find('.dropnav').css({marginLeft:(maxLeft-ddLeft)});
		}
		that.find('.dropnav').css({zIndex:'103',display:'block'}).animate({opacity:1,queue:false},500);//,function(){Cufon.refresh(that.find('a.top-cat')[0])});
		that.addClass('selected');
		Cufon.refresh(that.find('a.top-cat')[0]);
	}).mouseleave(function(){
		var that = jQuery(this);
		that.removeClass('selected');
		that.find('.dropnav').css({zIndex:'102'}).hide();//,function(){Cufon.refresh(that.find('a.top-cat')[0])});
		Cufon.refresh(that.find('a.top-cat')[0]);
	});
	
	// Header/sign in/OrderStatus rollover behavior
    jQuery('#sign-on',base).mouseenter(function(){
    	jQuery('.sign-on-container').show();
	});
    jQuery('.sign-on-container',base).mouseleave(function(){
		jQuery('.sign-on-container').hide();
	});
    jQuery('#order-status-link',base).mouseenter(function(){
    	jQuery('.order-status-container').show();
	});
    jQuery('.order-status-container',base).mouseleave(function(){
		jQuery('.order-status-container').hide();
	});
	
	// Home page behavior
	jQuery('.carousel.oneproduct',base).carouselify({itemWidth:700,batchSize:1,hitBox:'.carousel-container .product-module'});
	jQuery('.carousel.twoproduct',base).carouselify({itemWidth:350,batchSize:2,hitBox:'.carousel-container .product-module'});
	jQuery('.carousel.threeproduct',base).carouselify({itemWidth:233,batchSize:3,hitBox:'.carousel-container .product-module'});
	jQuery('.carousel.fourproduct',base).carouselify({itemWidth:175,batchSize:4,hitBox:'.carousel-container .product-module'});
	
	// General dialog functions
	jQuery('.dialogify').dialogify();
	
	// Header/minicart rollover behavior
	jQuery('#minicart',base).mouseenter(function(){
		jQuery('#minicartcontent').show();
	}).mouseleave(function(){
		jQuery('#minicartcontent').hide();
	});
    
    // product detail enhancements
	PDPUtils.enhanceDOM(base);
	
	// search results enhancements
	SRPUtils.enhanceDOM(base);
	
	jQuery("#main .thumb_view li").mouseenter(function(){
		jQuery(this).addClass('hover');
	}).mouseleave(function(){
		jQuery(this).removeClass('hover');
	}).click(function(){
		var image = jQuery(".product_image img");
		var src = image[0].src;
		var origSrc = image.data("origSrc");
		var myAltSrc = jQuery("img",this).data("altSrc");
		if( src == myAltSrc ) {
			image[0].src = origSrc;
		} else {
			image[0].src = myAltSrc;
		}
	});
};

function LoadSpecs() {
	//alert("We need to have Zack remove JS from the product descriptions.");
}

var app = (function(jQuery){

	if (!jQuery) {
		alert("jQuery is not loaded yet!");
		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
		clearDivHtml	: "<div class=\"clear\"><!-- W3C Clearing --></div>",
		currencyCodes	: {}, // holds currency code/symbol for the site

		// default dialog box settings
		dialogSettings: {
			autoOpen: false,
			bgiframe: true,
				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: "pretty fancy",
				top: 15,
				left: 5
		},

		// global form validator settings
		validatorSettings: {
			errorClass : 'error_message',
			errorElement: 'span',
			
		    onfocusout: function(element) {
				// Remove anything pre-existing to let validator create/modify from scratch
				//jQuery(element).parents('.formfield_container').find('.error_message').remove();
				//jQuery(element).parents('.formfield_container').find('.error_label').removeClass('error_label').addClass('labeltext');
				//alert(element.name);
				if ( !this.checkable(element) ) {
					this.element(element);
				}
			}
		},

		// app initializations called from jQuery(document).ready at the end of the file
		init: function(base) {
			var root = base || document.body;
			
			// register initializations here
			// quick view dialog div
			if( jQuery("#QuickViewDialog").size()==0 )
				jQuery("<div/>").attr("id", "QuickViewDialog").html(" ").appendTo(document.body);

			// micicart object initialization
			app.minicart.init();
			
			// initialize form validator customizations
			app.validator();

			// extract hidden data and turn them into jQuery data objects
			app.hiddenData();
			
//			// renders horizontal/vertical carousels for product slots
//			jQuery('#horicarousel').jcarousel({
//	        	scroll: 1
//		    }); 
//
//		    jQuery('#vertcarousel').jcarousel({
//		        scroll: 1,
//				vertical: true
//		    });	

			// Add call to Demandware Javascript function for Active Merchandising
			// capture recommendation of each product when it becomes visible in the carousel on Page Load
			if (jQuery('.carousel.oneproduct .carousel-container .captureproductid').text() != "") {
				for (var i = 0 ; i < 1; i++) {
					var pid = jQuery('.carousel.oneproduct .carousel-container .captureproductid:eq(' + i + ')').text();
					dw.ac.capture({id:pid, type:dw.ac.EV_PRD_RECOMMENDATION});
				}
			}
			
			if (jQuery('.carousel.twoproduct .carousel-container .captureproductid').text() != "") {
				for (var i = 0 ; i < 2; i++) {
					var pid = jQuery('.carousel.twoproduct .carousel-container .captureproductid:eq(' + i + ')').text();
					dw.ac.capture({id:pid, type:dw.ac.EV_PRD_RECOMMENDATION});
				}
			}
			
			if (jQuery('.carousel.threeproduct .carousel-container .captureproductid').text() != "") {
				for (var i = 0 ; i < 3; i++) {
					var pid = jQuery('.carousel.threeproduct .carousel-container .captureproductid:eq(' + i + ')').text();
					dw.ac.capture({id:pid, type:dw.ac.EV_PRD_RECOMMENDATION});
				}
			}	
			
			if (jQuery('.carousel.fourproduct .carousel-container .captureproductid').text() != "") {
				for (var i = 0 ; i < 4; i++) {
					var pid = jQuery('.carousel.fourproduct .carousel-container .captureproductid:eq(' + i + ')').text();
					dw.ac.capture({id:pid, type:dw.ac.EV_PRD_RECOMMENDATION});
				}
			}
		},
	
		// 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('bad response, parser error='+request+", options.url="+options.url);
							}
							
							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) {


				//jQuery(options.selector).load(options.url, options.data, options.callback);

				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('bad response, parser error');
							}

							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 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);

			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+" .addtocart_button:last").html(a2cBtnLabel) : '');
			}});
		},

		// sub name space app.minicart.* provides functionality around the mini cart
		minicart: {
			state : 0, // flag, whether cart is open or not
			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").hover(function(e){(app.minicart.isShow() ? '': 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()', 30 );
				});

				// register close button event
				jQuery('#minicartcontent #minicartclose').click(function() {
					// reset all the events bindings
					app.minicart.reset();
					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;
				}
					
				// show the item
				jQuery('#minicartcontent').show();//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 );
			},


			// adds a product to the mini cart
			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;
					}
					
					if(req.indexOf('NoInventory_NoInventory') > 0)
					{
						//alert("no Inventory");
						//Dialog.alertNoButtons(req.responseText.replace('NoInventory_NoInventory', ''), {windowParameters: {className: '',height: 400, width: 500}, okLabel: 'Close'});
						//return false;
						req = req.replace('NoInventory_NoInventory', '');
					}
					// replace the content
					//jQuery('#QuickViewDialog').html(req);

					// 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();
						minicartShow(req);
						jQuery('#QuickViewDialog').fadeTo('fast',1.0);
						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
				}
			},

			// hook which can be replaced by individual pages/page types (e.g. cart)
			suppressSlideDown: 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: {

			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;
					}
				);

				// click binding for quick view
				//jQuery(options.buttonLinkSelector).click(function(e) {
				//	app.quickView.show({url: this.href, source: "quickview"});
				//	return false;
				//});

				/*
				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.createDialog({id: 'QuickViewDialog', options: {
			    	height: 530,
			    	width: 800,
			    	dialogClass: 'quickview',
			    	title: 'Product Quickview',
			    	resizable: false
				}});

			    jQuery('#QuickViewDialog').dialog('open');
			    app.getProduct({containerId: "QuickViewDialog", source: options.source, url: options.url, label: options.label});
			},
			// close the quick view dialog
			close: function() {
				jQuery('#QuickViewDialog').dialog('close');
			}
		},


		createDialog: function(options) {
			var opts = jQuery.extend({}, app.dialogSettings, options.options);
			jQuery('#'+options.id).dialog(opts);
		},


		tooltip: function(options) {
			if (options.id.charAt(0) !== '#') {
				options.id = "#"+options.id;
			}
			jQuery(options.id).tooltip(jQuery.extend({}, app.tooltipSettings, options.options));
		},

		// 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));
		},
		showBusy : function(className) {
			var clazz = "busy";
			if (className) clazz += " " + className;
			return jQuery("<div class=\"" + clazz + "\"/>");
		},

		/*
		 *	Opens a new window with the provided url and dimension. Used
		 *	for Scene7 and other situations.
		 *
		 *	@param url the url to open
		 *	@param width the window width
		 *	@param height the window height
		 */
		openPopup: function( url, width, height ) {
			if (url != null) {
				if (width != null && height != null) {
					window.open(url, "", "width=" + width +", height=" + height +", scrollbars=no, resizable=yes");
				}
				else {
					window.open(url, "", "scrollbars=no, resizable=yes");
				}
			}
		},


		validator: function() {
			// override default required field message
			jQuery.validator.messages.required = function($1, ele, $3) {
				var the_dta = jQuery(ele).data("data");
				if( the_dta==null ) return "";
				var article = "a";
				if( the_dta[0]=='A' ||the_dta[0]=='E' ||the_dta[0]=='I' ||the_dta[0]=='O' ||the_dta[0]=='U' ){
					article = "an";
				}
				return 'Please enter '+article+' '+the_dta;
			};

			// 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 span and append it to its immediate previous sibling
		hiddenData : function() {
			jQuery.each(jQuery(".hidden"), function() {
				jQuery(this).prev().data("data", jQuery(this).html());
			});
		},

		// sub namespace app.producttile.* contains utility functions for product tiles
		producttile : {
			// initializes all product tiles contained in the current page
			initAll: function() {
				// bind quick view button toggling and click
				var quickViewOptions = {
					buttonSelector: "div.producttile div.quickview-button",
					imageSelector: "div.producttile div.image",
					buttonLinkSelector: "div.producttile div.quickview-button a"
				};
				//app.quickView.bindEvents(quickViewOptions);
				
				// prepare swatch palettes and thumbnails
				jQuery("div.producttile div.swatches div.hidden").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.hidden").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;
				});
				
				// thumb nail toggling
				jQuery("div.producttile div.swatches div.palette a.swatch").bind("mouseover mouseout", function(e) {
					var swatch = jQuery(this);
					app.producttile.toggleVariationThumbnail(swatch);
				});
				
				// color swatch selection
				jQuery("div.producttile div.swatches div.palette a.swatch").click(function(e) {
					var swatch = jQuery(this);
					app.producttile.selectVariation(swatch);
					// omit following the swatch link
					return false;
				});
			},

			// 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()[3]).find(".productimage img");
				var newImg = swatch.children("img.hiddenthumbnail");
				if(!currentImg || !newImg) return;
				
				// get the anchors
				var nameAnchor = swatch.parents(".producttile").find(".name a");
				var quickViewAnchor = swatch.parents(".producttile").find(".quickview-button a");
				
				// change the link url to the detail page and quick view
				var newUrl = swatch.attr("href");
				nameAnchor.attr("href", newUrl);
				quickViewAnchor.attr("href", newUrl);
				
				// remove all current markers
				jQuery(swatch.parents()[0]).find("a.swatch").removeClass("selected");
				
				// mark swatch as selected
				swatch.addClass("selected");
				// we just remove the markers at the images; the actual elements
				// are correct, since they were already swapped by mouse over
				currentImg.removeClass("temp original");
				newImg.removeClass("temp original");
			},

			// 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()[3]).find(".productimage img");
				var newImg = swatch.children("img.hiddenthumbnail");
				if(!newImg || !currentImg) return;
					
				// we do nothing in case the swatch is already selected
				if(swatch.hasClass("selected")) return;
				
				if(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 : {
			multiUpdate : function(elemId, url, mapping) {
				var element = jQuery(elemId);
				jQuery.ajax({
					dataType: "html",
					url		: url,
					cache	: true,

					success: function(response, textStatus) {
						var responseNode = jQuery(response);
						var entries = mapping.split(",");
						for( var i=0, ii=entries.length; i<ii; i++ ) {
							var sourceTarget = entries[i].split(":");
							if( sourceTarget.length == 1 ) {
								jQuery(sourceTarget[0]).html(responseNode.find(sourceTarget[0]).html());
							} else if( sourceTarget == 2 ) {
								jQuery(sourceTarget[1]).html(responseNode.find(sourceTarget[0]).html());
							}
						}
					},

					error: function(request, textStatus, error) {
						if (textStatus === "parsererror") {								
							alert('bad response, parser error');
						}
					}
				});
				
			},
			
			// 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() {
				var currentCookie = document.cookie;
				document.cookie = "Enabled=true";
				var cookieValid = document.cookie;
				var result = false;

				if(cookieValid.indexOf("Enabled=true") != -1) {
					result = true;
				}

				document.cookie = currentCookie;
				return result;
			}
		},

		// 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({
						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("destroy");
				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("Server connection failed!");
				   }
				});
			}
		}
	}
})(jQuery);

jQuery.fn.refineFilter = function( action, options ) {
	var that = this;
	var enable = function() {
		that.each(function(){
			var self = jQuery(this);
			self.removeAttr("disabled");
			self.removeClass("unorderable");
			if( jQuery.browser.msie && jQuery.browser.version<7 ) {
				jQuery(this.parentNode).css({
					'background-color':'#666',
					'color':'#aaa'
				});
			}	else {
				if( jQuery(this.parentNode).css('opacity')!= "1" )
					jQuery(this.parentNode).css({'opacity':'1'});
			}
		});
		return this;
	};
	var disable = function() {
		that.each(function(){
			var self = jQuery(this);
			self.attr("disabled","disabled");
			self.addClass("unorderable");
			if( jQuery.browser.msie && jQuery.browser.version<7 ) {
				jQuery(this.parentNode).css({
					'background-color':'auto',
					'color':'auto'
				});
			}	else {
				if( jQuery(this.parentNode).css('opacity')!= '0.4' )
					jQuery(this.parentNode).css({'opacity':'0.4'});
			}	
		});
		return this;
	};
	switch( action ){
	case 'enable':
		enable( options );
		break;
	case 'disable':
		disable( options );
		break;
	default:
		break;
	}
};

var PDPUtils = {
	currentSubCategory : 'empty',
	_visibleRows : null,
	
	scrollify : function(wrappedset) {
		if( jQuery('#productlist tr:visible',wrappedset[0]).size()<=5 ) {
			wrappedset.find(".scrollable").addClass("noscroll");
		} else {
			wrappedset.find(".scrollable").removeClass("noscroll");
		}	
	},

	expandSection : function(expandosection, callback) {
		/*Currently closed*/
		/*Check for gender-hand, return if there is no current selection*/
		var selGenderHandElement = jQuery('#pdpVarAttrDiv .gender-hand li.selected')[0];
		if( selGenderHandElement==null ) {
			if( expandosection.parents('.shafts').size()<1 ) 
				return false;
		}
		jQuery('.addtocartbar div.callout').hide('fast');
		var esection = expandosection;
		var ecallback = callback;
		PDPUtils.fixMissingColumns();
		var options = {'width':'940px'};
		if( jQuery.browser.msie && jQuery.browser.version<8 ) {
			options['marginLeft'] = "-400px";
		}
		expandosection.stop().animate(options,function(){
			//PDPUtils.scrollify(jQuery(this));
			expandosection.addClass('expanded-section');
			jQuery(this).find('.scrollable').show();
			expandosection.removeClass('expandable-section');
			if( ecallback ) ecallback();
			expandosection.css({left:"0px"});
		});//.find('.scrollable').fadeIn('normal');
	},

	compressSection : function(expandosection) {
		/*Currently open*/
		expandosection.find('.scrollable').hide();//,function(){
		PDPUtils.unfixMissingColumns();
		var options = {'width':'569px'};
		if( jQuery.browser.msie && jQuery.browser.version<8 ) {
			options['marginLeft'] = "0px";
		}

		expandosection.css({overflow:'visible'});
		expandosection.stop().animate({'width':'569px','visibility':'visible'},function(){
			if( jQuery('.gender-hand li.selected')[0]==null ) {
				// Make sure that the first callout has the gender/hand message
				jQuery(jQuery('.addtocartbar div.callout')[0]).addClass('nogenderhand');
			} else {
				// Make sure that the first callout has the press the + button message
				jQuery(jQuery('.addtocartbar div.callout')[0]).removeClass('nogenderhand');
			}
			jQuery('.addtocartbar div.callout').show('fast');
			
			expandosection.removeClass('expanded-section');
			expandosection.addClass('expandable-section');
			 
			expandosection.css({overflow:'visible'});
		});//});
	},
	resetAllAttributeRefinements : function() {
		jQuery('#productdetail-box .refinement_category li.selected').removeClass('selected');
		jQuery('#productdetail-box .refinement_category li').addClass('unorderable').css({'opacity':'0.4'}).attr("disable","disable");	
//		PDPUtils.greyVariantAttributes();
	},
	resetSubcategorySpecificRefinements : function( subcatName ) {
//		var startTime = new Date();
		// Swap subcat specific column visibility
		if( subcatName.indexOf('Sets')>-1 ) {
			jQuery('#pdpVarAttrDiv div.v1258').show();
			jQuery('#productlist td.v1258').show();
			jQuery('#pdpVarAttrDiv div.v1267').hide();
			jQuery('#productlist td.v1267').hide();
		} else {
			jQuery('#pdpVarAttrDiv div.v1258').hide();
			jQuery('#productlist td.v1258').hide();
			jQuery('#pdpVarAttrDiv div.v1267').show();
			jQuery('#productlist td.v1267').show();

			if( subcatName.indexOf('Individual')>-1 ) {
				jQuery('#pdpVarAttrDiv li.v1267:has(a:contains("Iron"))').show();
				jQuery('#pdpVarAttrDiv li.v1267:has(a:contains("Wedge"))').hide();
			} else {
				jQuery('#pdpVarAttrDiv li.v1267:has(a:contains("Iron"))').hide();
				jQuery('#pdpVarAttrDiv li.v1267:has(a:contains("Wedge"))').show();
			}
		}
//		var endTime = new Date();
//		alert("resetSubcategorySpecificRefinements:"+(endTime.getTime()-startTime.getTime())+"ms");
	},
	filterSubcategory : function(el, origEl) {
		//alert('FILTER SUBCATEGORY!');
		var attrValue = jQuery(el).text();
		// If we already have the tab active, then forget about it
		if (PDPUtils.currentSubCategory != attrValue){
			// Don't change the gender hand ...
			// Cler all attribute refinements
			PDPUtils.resetAllAttributeRefinements();

			PDPUtils.resetSubcategorySpecificRefinements(attrValue);
			
			// Hide all rows except ones with this subcat
			PDPUtils.showSubcategorySpecificRows( attrValue );
			
			PDPUtils.currentSubCategory = attrValue;
			
			PDPUtils.filterForCurrentGenderHandSelection();
			
			// Hide the link
			if( jQuery('li.selected .vGenderHand').length>0 ) {
				PDPUtils.updateSearchResultsText();
			} else {
				jQuery('#productdetail-box .callout').hide();
			}

			if( !origEl ) PDPUtils.filterRefinemetOptions();
		} else {
			// Hide all rows except ones with this subcat
			PDPUtils.showSubcategorySpecificRows(attrValue);
		}
		PDPUtils.oddifyRows();
	},
	showSubcategorySpecificRows : function( subcategory ) {
	},
	/* Find all rows which have a td containing "subcat" */
	rowsForSubcategory : function( subcat ) {
		var rows = jQuery("#productlist tr");
		
		return rows;
	},
	visibleRows : function() {
		if( PDPUtils._visibleRows ) return PDPUtils._visibleRows;
		var startTime = new Date();
		var rows = [];
		jQuery('#productlist tr').each(function(){
			if(jQuery(this).css('display')!='none') {
				rows.push(this);
			}
		});
		PDPUtils._visibleRows = jQuery(rows);
		var endTime = new Date();
		return PDPUtils._visibleRows;
	},
	filterForCurrentGenderHandSelection : function(overlay) {
		// Check all gender/hands and update unorderable as needed

	},
	filterVariants : function(el, mutuallyExclude) {
		var that = jQuery(el);
		var ele = that.parents('li');
		if( ele && ele.size()>0 && ele.hasClass('unorderable') ) return false;

		var attrID = el.className.split(" ")[0];
		var attrValue = el.id;
		var mux = !!mutuallyExclude;
		
		// Check if selected
		var wasChecked = jQuery('#'+attrValue).parents('li').hasClass('selected');
		var isChecked = !wasChecked;
		
		var newID = null;
		if( !wasChecked && mux ) {
			jQuery('#'+attrValue).parents('li').siblings().removeClass('selected');
			// Look for associated product list
			newID = "productlist"+attrValue.split("-")[1];

			// And copy it in
			jQuery('#productlist').html(jQuery('#'+newID).html());
			PDPUtils._visibleRows = null;
			jQuery('#'+attrValue).parents('li').addClass('selected');
			that = jQuery('#'+attrValue);
			PDPUtils.clearAllRefinements();
			PDPUtils.enhanceDOM(jQuery('#expando')[0]);
		} else if(attrID=='vGenderHand') {
			jQuery('#'+attrValue).parents('li').removeClass('selected');
			PDPUtils.resetAllAttributeRefinements();
		} else {
			ele.toggleClass('selected');
			jQuery('#productlist tr').show();
			PDPUtils.applyRefinementsToProductGrid();
			jQuery('#productdetail-box .callout').hide();
		}
		
		// PJP_JS
		// Add new hook to simplify CSS element collection
		// if any 'li' is selected, then add 'filtered' to .var-attr
		var ul = that.parents('ul');
		if( ul.find('li.selected').size()>0 ) {
			ul.addClass('filtered');
		} else {
			ul.removeClass('filtered');
		}
				
		// Make sure gender hand is selected before we expose the grid
		// Otherwise, close it
		var expandosection = jQuery('#expando');
		if( attrID == 'vGenderHand' && isChecked ) {
			// GenderHand already selected, so open the grid
			PDPUtils.expandSection(expandosection, function(){
				var sorts = jQuery('#options-header .asc,#options-header .des');
				if( sorts.size()==0 ){
					// Comes from server sorted
					//PDPUtils.sortRows('natural-sort','asc');
				} else {
					PDPUtils._visibleRows = null;
					PDPUtils.oddifyRows(jQuery('#productlist')[0]);
				}
				PDPUtils.filterRefinemetOptions(attrID,wasChecked);
			});
		} else if( attrID == 'vGenderHand' && jQuery('.gender-hand li.selected')[0]==null ) {
			jQuery("#productdetail-box .callout").hide();
			PDPUtils.compressSection(expandosection);
			PDPUtils._visibleRows = null;
		} else {
			PDPUtils._visibleRows = null;
			PDPUtils.oddifyRows(jQuery('#productlist')[0]);
			PDPUtils.filterRefinemetOptions(attrID,wasChecked);
		}
		PDPUtils.updateSearchResultsText();
		return false;
	},
	clearAllAttributeRefinements : function() {
		PDPUtils._visibleRows=null; 
		PDPUtils.clearAllRefinements(true); 
		jQuery('.refinement_category li').removeClass('selected');
		PDPUtils.updateSearchResultsText(); 
	},
	clearAllRefinements : function(isFirstCall) {
		// Show all productlist rows
		jQuery('#productlist tr').show();

		// Hide all refinements
		if( !isFirstCall ) PDPUtils.resetAllAttributeRefinements();
		if( !jQuery('#main').hasClass('shafts') ) {
			// Hide non-applicable productlist rows for gender-hand
			PDPUtils.filterRefinemetOptions();
		}
		PDPUtils.oddifyRows();
	},
	hideNonconformingRowsForAttribute : function( attrID ) {
		jQuery('#productlist tr:has(td.NA.'+attrID+')').hide();
	},
	applyRefinementsToProductGrid : function() {
//		var startTime = new Date();
		// We start with all visible, so we hide the "unchcecked ones"
		var varAttrs = jQuery('#pdpVarAttrDiv li.selected a').parents('ul').find('a');
		var unselectedSiblings = varAttrs.map(function(){
			if( this.parentNode.className.indexOf('selected')<0 )
				return this;
		});
		
		var usSize = unselectedSiblings.size();
		if( usSize > 0 ) {
			// Hide unselected
			unselectedSiblings.each(function(){
				var trs = jQuery('#productlist td.'+this.id).map(function(){
					return this.parentNode;
				});
				jQuery(trs).hide();
			});
		}
//		PDPUtils.oddifyRows(jQuery('#productlist')[0]);
//		PDPUtils.updateSearchResultsText();
//		var endTime = new Date();
//		alert(endTime.getTime()-startTime.getTime()+"ms: apply");
	},
	updateSearchResultsText : function(){
		var totalRows = jQuery(".productlist-store tr").length;
		 
		var visibleRows = PDPUtils.visibleRows().length;
		if( totalRows> 0 ) {
			jQuery('#productdetail-box .callout .results').text(visibleRows+ " of "+totalRows+ " items match your selections.");
			jQuery('#productdetail-box .callout').show();
			if( visibleRows==0 ) {
				jQuery('#productdetail-box .callout').addClass("zero-results");
			} else {
				jQuery('#productdetail-box .callout').removeClass("zero-results");
			}
		} else {
			jQuery('#productdetail-box .callout').hide();
		}
	},
	/* This function sets up the refinement check boxes based on what is visible in the table */
	filterRefinemetOptions : function(clickedAttributeID, waschecked){
		var visibleRows = PDPUtils.visibleRows();
		
		// Ignore if the table is not visible
		if( visibleRows.size()<1 ) {
			return;
		} else {
			//var genderHandID = jQuery('.refine_attributes .vGenderHand.selected').attr("id");

			// For each variation attribute element
			jQuery('#pdpVarAttrDiv .refinement_category').each( function(){
				var attributeID = this.id;
								
				// Never act on the row we are checking
				if( !waschecked && clickedAttributeID==attributeID ) {
					return;
				}
				
				// If the variation attribute value is not selected
				jQuery("a",this).each(function(){
					// Only if unselected ...
					if( this.parentNode.className.indexOf('selected')>-1 ) return;

					var innerElement = jQuery(this);
					
					var attributeValue = this.id;//va
					var selector = 'td.'+ attributeValue;
					if (visibleRows.find(selector).length < 1) {
								innerElement.parents('li').addClass('unorderable').css({'opacity':0.4}); // PJP_API
					} else {
						//PDPUtils.greyVariantAttributes();							
						innerElement.parents('li').removeClass('unorderable').removeAttr('disabled').css({'opacity':1.0}); // PJP_API
					}
				});
			});
		} 
	},
	
	unfixMissingColumns : function(){
		jQuery('#options-header .v54').css('width',null);
		jQuery('#options-header .v1656').css('width',null);
		jQuery('#options-header .v1644').css('width',null);
		jQuery('#options-header .v3').css('width',null);
		jQuery('#options-header .vCondition').css('width',null);
		jQuery('#options-header .pricings').css('width',null);
	},
	fixMissingColumns : function(){
		jQuery('#options-header td:empty').each( function(){
			var ie = $(this);
			var className = ie.attr('class');
			jQuery('#productlist td.'+className).css({display:'none'});
			jQuery(this).css({display:'none'});
			if( className.indexOf( 'v1664' )>-1 ) {
				jQuery('#productlist td.v54').css({width:'295px'});
				jQuery('#options-header td.v54').css({width:'295px'});
			} else if( className.indexOf( 'v1644' )>-1 ) {
				jQuery('#productlist td.v1656').css({'padding-left':'5px','width':'270px'}); 
				jQuery('#options-header td.v1656').css({width:'273px'});
				jQuery('#productlist td.v3').css({width:'204px'});
				jQuery('#options-header td.v3').css({width:'204px'});
				jQuery('#productlist td.vCondition').css({width:'244px'});
				jQuery('#options-header td.vCondition').css({width:'244px'});
				jQuery('#productlist td.pricings').css({width:'168px'});
				jQuery('#options-header td.pricings').css({width:'178px'});
			} else if( className.indexOf( 'v1656' )>-1 ) {
				jQuery('#productlist td.v1644').css({'padding-left':'5px','width':'270px'});
				jQuery('#options-header td.v1644').css({width:'273px'});
				jQuery('#productlist td.v3').css({width:'204px'});
				jQuery('#options-header td.v3').css({width:'204px'});
				jQuery('#productlist td.vCondition').css({width:'244px'});
				jQuery('#options-header td.vCondition').css({width:'244px'});
				jQuery('#productlist td.pricings').css({width:'168px'});
				jQuery('#options-header td.pricings').css({width:'178px'});
			}
		});
	},
	formatNumber : function(number,digits) {
		var digs = digits || 10;
		var num = ""+number;
		var out = "";
		var dif = digs-num.length;
		while( dif > 0 ) {
			out+="0";
			dif--;
		}
		return out+num;
	},
	sortBy : function( el ) {
		var descending = jQuery(el).parents('td').hasClass('des');
		var colName = jQuery(el).parents('td')[0].className.split(' ')[0];
		PDPUtils.sortRows(colName,descending ? 'des' : 'asc');
	},

	sortRows : function( column, direction ) {
		var table = jQuery('#productlist').remove();
		var cName = column;
		
		if( cName=='v1258' && PDPUtils.currentSubCategory!='Iron Sets' ) {
			cName = 'v1267';
		}
		
		var columnValues = jQuery.map(table.find('td.'+cName),function(node){
			return out = node.className.split(" ")[2];
		});
		
		// unique it first 
		var uniqueValues = PDPUtils.unique(columnValues);
		
		// sort on unique values - on smaller set
		var sortedValues = uniqueValues.sort();

		if( direction=='asc' ) {
			jQuery('#options-header td.'+column).addClass('des');
			jQuery('#options-header td.'+column).removeClass('asc');
		} else {
			sortedValues.reverse();
			jQuery('#options-header td.'+column).addClass('asc');
			jQuery('#options-header td.'+column).removeClass('des');
		}
		
		jQuery('#options-header td.'+column).siblings().removeClass('des');
		jQuery('#options-header td.'+column).siblings().removeClass('asc');

		// unique it
		//sortedValues = PDPUtils.unique(sortedValues);
		
		var _table = jQuery("<table id='productlist' />").addClass("productlist");
		
		// Remove all rows and replace them by text value
		var signature;

		jQuery.each(sortedValues, function(val){
			signature = 'td.'+cName+'.'+this;	
			
			var rows2 = table.find(signature);
			_table.append(rows2.parent());		

		});

		
		jQuery('div.scrollable').append(_table[0]);
		PDPUtils._visibleRows = null;
		PDPUtils.oddifyRows(_table[0]);
		
		// Allows for selection of variant rows for add to cart
		jQuery('#productlist tr').rolloverify().click(function(){
			jQuery(this).toggleClass("selected").siblings().removeClass("selected");
			if( jQuery(this).hasClass("selected") ) {
				var sku = this.id.split("-")[1];
				jQuery(".selectedSKU").html("<span class='bold'>Product SKU:</span> <span class='sku'>"+sku+"</span>");
				PDPUtils.enableAddToCart();
			} else {
				PDPUtils.disableAddToCart();
				jQuery(".selectedSKU").html("");
			}
		});
	},
	activateGrid : function(){
		// Allows for selection of variant rows for add to cart
		jQuery('#productlist tr').rolloverify().click(function(){
			jQuery(this).toggleClass("selected").siblings().removeClass("selected");
			if( jQuery(this).hasClass("selected") ) {
				var sku = this.id.split("-")[1];
				jQuery(".selectedSKU").html("<span class='bold'>Product SKU:</span> <span class='sku'>"+sku+"</span>");
				PDPUtils.enableAddToCart();
			} else {
				PDPUtils.disableAddToCart();
				jQuery(".selectedSKU").html("");
			}
		});
	},
	unique : function(inArray) {
		var arr = inArray || [];
		var result = [];
		for( var i=0, ii=arr.length; i<ii; i++ ) {
			if( !PDPUtils.contains(result, arr[i]) ) {
				result.push(arr[i]);
			}
		}
		return result;
	},

	contains : function(arr, elem) {
		var inArr = arr || [];
		for( var i=0, ii=inArr.length; i<ii; i++ ) {
			if( inArr[i]==elem ) return true;
		}
		return false;
	},

	enableAddToCart : function() {
		jQuery("#main div.addtocart .addtocartBtn").attr("disabled", null);
		jQuery("#main div.addtocart").removeClass("disabled"); 
	},

	disableAddToCart : function() {
		jQuery("#main div.addtocart .addtocartBtn").attr("disabled", "disabled");
		jQuery("#main div.addtocart").addClass("disabled"); 
	},
	
	oddifyRows : function( table ) {
		var visRows = PDPUtils.visibleRows();
		visRows.filter(':odd').removeClass('odd').addClass('odd');
		visRows.filter(':even').removeClass('odd');
	},

	addSelectionToCart : function(wrappedSet, cgid) {
		PDPUtils.disableAddToCart();
		// Look at each one, collect id's and add each to the cart with quantity 1
		var pids = "";
		for( var i=0, ii=wrappedSet.length; i<ii; i++ ) {
			pids+=wrappedSet[i].id.split('-')[1];
			if( i<(ii-1) ) pids+="|";
		}
		if( pids.length==0 ) return false;
		pids = "pid=" + pids + "&Quantity=1";
		if( cgid ) {
			pids += "&cgid="+cgid;
		}
		pids = encodeURI(pids);

		app.createDialog({id:'QuickViewDialog',options:{
			width:700,height:600,dialogClass:"minicart",title:"Items Added to Your Cart",bgiframe:true,draggable:false,autoResize:true
		}});

		jQuery('#QuickViewDialog').load(app.minicart.url,pids);
		jQuery('#QuickViewDialog').empty().append(app.showProgress());

		jQuery('#QuickViewDialog').dialog('open');

		wrappedSet.removeClass("selected");
		
		return false;
	},
	replaceSelectedVariantToCart : function(vid,pid) {
		PDPUtils.disableAddToCart();
		var pids = "vid="+vid+"&pid=" + pid;

		pids = encodeURI(pids);
		app.createDialog({id:'QuickViewDialog',options:{
			width:'700px',dialogClass:"minicart",title:"Items Added to Your Cart",resizable:false
		}});
		jQuery('#QuickViewDialog').load(app.minicart.url,pids);
		jQuery('#QuickViewDialog').empty().append(app.showProgress());

		jQuery('#QuickViewDialog').dialog('open');

		return false;
	},
	addSelectedVariantToCart : function(pid,cgid) {
		var qty = jQuery('#productQty').val()||"1";
		var pids = "pid=" + pid + "&Quantity="+qty;
		if( cgid ) {
			pids += "&cgid="+cgid;
		}
		pids = encodeURI(pids);
		app.createDialog({id:'QuickViewDialog',options:{
			width:'700px',dialogClass:"minicart",title:"Items Added to Your Cart",resizable:false
		}});
		jQuery('#QuickViewDialog').load(app.minicart.url,pids);
		jQuery('#QuickViewDialog').empty().append(app.showProgress());

		jQuery('#QuickViewDialog').dialog('open');

		return false;
	},
	
	showProductToolTip: function( element ){
		if (element) {
			var toolTipDiv = $('.image_container .productDetailToolTip');
			//if the tool tip div does not exist we just create it
			if (toolTipDiv.size()==0) {
				var imageDiv = $('.image_container').append('<div class="productDetailToolTip"></div>');
				toolTipDiv = $('.image_container .productDetailToolTip');
			}
			var productToolTip = $(element).find('div.productToolTip');
			if (productToolTip.size()>0) {
				toolTipDiv.html(productToolTip.html()).show();
			}
		}
	},

	hideProductToolTip: function( ){
		var toolTipDiv = $('.image_container .productDetailToolTip');
		//if the tool tip div does not exist we just create it
		if (toolTipDiv.size()>0) {
			toolTipDiv.hide();
		}
	},

	enhanceDOM : function(root) {
		var base = root||document.body;
		
		//PDPUtils.clearAllRefinements();
		//if( jQuery("#tabs").length>0 ) {
		//	PDPUtils.currentSubCategory = jQuery(jQuery("#tabs a")[0]).text();
		//}
		//PDPUtils.filterForCurrentGenderHandSelection(true);
		jQuery('li.unorderable',base).css({'opacity':0.4}).attr('disabled','disabled');
		
		// Opens/closes the variant list
		jQuery('td.plusBtn', base).click(function(){
			var expandosection = jQuery('#expando');
			if( expandosection.hasClass('expandable-section') ) {
				PDPUtils.expandSection(expandosection, function(){PDPUtils.oddifyRows(jQuery('#productlist')[0]);});
			} else {
				PDPUtils.compressSection(expandosection);
			}
			return false;
		});
		
		// Allows for selection of variant rows for add to cart
		jQuery('#productlist tr',base).rolloverify().click(function(){
			jQuery(this).toggleClass("selected").siblings().removeClass("selected");
			if( jQuery(this).hasClass("selected") ) {
				PDPUtils.enableAddToCart();
				var sku = this.id.split("-")[1];
				jQuery(".selectedSKU").html("<span class='bold'>Product SKU:</span> <span class='sku'>"+sku+"</span>");
			} else {
				PDPUtils.disableAddToCart();
				jQuery(".selectedSKU").html("");
			}
		});
		
		// Make unorderable variation attribtues look disabled (PJP_API changed friday)
		//jQuery('.unorderable',base).fadeTo("fast",0.4);
	
		// Filterables
		jQuery('.filterable',base).click(function(){
			if( jQuery(this).hasClass('vGenderHand') ) {
				PDPUtils.filterVariants(this,true);
			} else {
				var enableAdditionalFiltering = false;
				//if vGender attribute is present we check if any of the values was already selected
				//if not we don't allow additional filtering
				if (jQuery('.vGenderHand.filterable').length>0 ) {
					jQuery('.vGenderHand.filterable').each( function(i) {
						if (jQuery(this).parent('li').hasClass('selected')) {
							enableAdditionalFiltering = true;
						}
					})
				} else {
					enableAdditionalFiltering = true;
				}
				if (enableAdditionalFiltering) {
					PDPUtils.filterVariants(this);
				} else {
					alert('Additional filtering is not allowed until you have chosen your Gender/Hand.');
				}
			}
			return false;
		});
	}
};

var SRPUtils = {};
SRPUtils.enhanceDOM = function(root){
	// init all refinement bindings
	var base = root||document.body;
	
	if(app.search) app.search.updateRefineBindings(base);
	
	// init refinement toggling
//	jQuery("#search-refinements div.navgroup h3",base).click(function(e) {
//		jQuery(this).toggleClass("collapsed");
//		jQuery(this).nextAll("div.refine_attributes").toggle();
//	});
	
	// Search result page behavior
	jQuery('.click-box',base).mouseenter(function(){
		jQuery(this).parents('.product-module').addClass('hover');
	}).mouseleave(function(){
		jQuery(this).parents('.product-module').removeClass('hover');
	});
};

jQuery.fn.enhancify = function() {
	if( this.size()>0 )
		DOMUtils.enhanceDOM(this[0]);
	
	return this;
}

jQuery.fn.carouselify = function(_options){
	var options = {itemWidth:175,batchSize:4,hitBox:'.carousel-container .product-module'};
	jQuery.extend(options,_options);

	this.each(function(){
		var that = this;
		jQuery(options.hitBox,that).rolloverify().click(function(){
			var href = jQuery('a',this).attr('href');
			location.href = href;
			return false;
		});
		jQuery(this).find('.carousel-next').click(function(){
			// Look for numProducts .end.text() and .begin.text()
			var begin = jQuery('.begin',that).text()-0;
			var end = jQuery('.end',that).text()-0;
			var old_begin = begin;
			// get min(begin+4,end)
			var numProducts = jQuery('.total',that).text()-0;
			if( end+options.batchSize>numProducts ) {
				end = numProducts;
				// hide arrows (if needed)
				jQuery(this,that).css({visibility:'hidden'});
			} else {
				end+=options.batchSize;
			}
			begin = end-options.batchSize+1;
			// push over 175*(old-new)
			var change = "-="+((begin-old_begin)*options.itemWidth)+"px";
			jQuery('.carousel-container',that).animate({marginLeft:change},'normal');	
			// update new begin and end
			jQuery('.carousel-nav .begin',that).text(begin);
			jQuery('.carousel-nav .end',that).text(end);
			
			// show arrows (if needed)
			if( begin > 1)
				jQuery('.carousel-prev',that).css({visibility:'visible'});
			
			// Add call to Demandware Javascript function for Active Merchandising
			// capture recommendation of each product when it becomes visible in the carousel
			for (var i = begin - 1 ; i < end; i++) {
				var pid = jQuery('.carousel-container .captureproductid:eq(' + i + ')').text();
				dw.ac.capture({id:pid, type:dw.ac.EV_PRD_RECOMMENDATION});
			}
			
			return false;
		});
		
		jQuery(this).find('.carousel-prev').click(function(){
			// Look for numProducts .end.text() and .begin.text()
			var begin = jQuery('.begin',that).text()-0;
			var end = jQuery('.end',that).text()-0;
			var old_begin = begin;
			// get min(begin+4,end)
			var numProducts = jQuery('.total',that).text()-0;
			if( (begin-options.batchSize)<1 ) {
				begin = 1;
				// hide arrows (if needed)
				jQuery(this,that).css({visibility:'hidden'});
			} else {
				begin-=options.batchSize;
			}
			end = begin+options.batchSize-1;
			// push over 175*(old-new)
			var change = "+="+((old_begin-begin)*options.itemWidth)+"px";
			jQuery('.carousel-container',that).animate({marginLeft:change},'normal');
			// update new begin and end
			jQuery('.carousel-nav .begin',that).text(begin);
			jQuery('.carousel-nav .end',that).text(end);
			
			// show arrows (if needed)
			if( end < numProducts )
				jQuery('.carousel-next',that).css({visibility:'visible'});
			
			// Add call to Demandware Javascript function for Active Merchandising
			// capture recommendation of each product when it becomes visible in the carousel
			for (var i = begin - 1 ; i < end; i++) {
				var pid = jQuery('.carousel-container .captureproductid:eq(' + i + ')').text();
				dw.ac.capture({id:pid, type:dw.ac.EV_PRD_RECOMMENDATION});
			}
			
			return false;	
		});	
	});
};
jQuery.fn.rolloverify = function(_options) {
	var defaults = {toggleClass:'hover'};
	jQuery.extend(defaults,_options);
	
	this.mouseenter(function(){
		jQuery(this).addClass(defaults.toggleClass);
	}).mouseleave(function(){
		jQuery(this).removeClass(defaults.toggleClass);
	});
	
	return this;
};
jQuery.fn.dialogify = function(_options) {
	var optionsD = {dialogId:'QuickViewDialog'};
	var options;
	jQuery.extend(optionsD,_options);
	this.each(function(){
		var that = jQuery(this);
		var relParams = that.attr("rel")||"";
		var params = relParams.split("|");
		var key, value;
		options = {};
		for( var i=0,ii=params.length; i<ii; i++ ){
			var parts = params[i].split("=");
			if( parts.length==2 ) {
				var key = parts[0];
				var value = parts[1];
				
				if( key=='width' || key=='height' ) value = value-0;
				if( key=='resizable')
					if( value=='true') { value = true; } 
					else { value = false; }
				
				options[key]=value; 
			}
		}
		var title = that.attr("title");
		if( title && title.length>0 ) {
			options['title']=title;
		}
		var href = that.attr("href");
		var defaults = {
		    	width: 660,
				height: 440,
		    	resizable: false,
		    	bgiframe:true,
		    	draggable:false
		};
		jQuery.extend(defaults,options);
		
		that.click(function(){
			app.createDialog({id: optionsD.dialogId, options: defaults});
			
			if( optionsD.content ) {
				jQuery('#'+optionsD.dialogId).html(optionsD.content);
			} else {
				jQuery('#'+optionsD.dialogId).load(href,function(){});
				jQuery('#'+optionsD.dialogId).empty().append(app.showProgress());
			}
			
			jQuery('#'+optionsD.dialogId).dialog('open');
			
			jQuery('.ui-dialog-titlebar-close').click(function(){
				jQuery('.ui-dialog-content').dialog('destroy');
			});
			return false;
		});
	});
	
	return this;
};

function minicartShow(content) {
	app.createDialog({id: 'QuickViewDialog', options: {
    	height: 441,
    	width: 660,
    	dialogClass: 'minicart',
    	title: 'Items Added to Your Cart',
    	resizable: false
	}});
	
	// indicate progress
	jQuery("#content").fadeTo("normal",0.4);

	jQuery('#QuickViewDialog').html(content);

	jQuery('#QuickViewDialog').dialog('open');
}

function toggleLoginRadio( el ) {
	if( el && el.id=="create_account_radio" ) {
		if( el.checked ) {
			jQuery('.checkoutSave').show('normal');
		} else {
			jQuery('.checkoutSave').hide('normal');

		}
	} else if( el && el.id=="guest_checkout_radio" ) {
		if( el.checked ) {
			jQuery('.checkoutSave').hide('normal');
		} else {
			jQuery('.checkoutSave').show('normal');

		}
	}
}
var presentify = {
	showNextContentAsset : function () {
		var next = jQuery(presentify.selectedContentAsset).next()[0];
		var nextPageBtn = jQuery(presentify.selectedPageBtn).next()[0];
		if( next==null ) {
			next = jQuery(presentify.selectedContentAsset).siblings(presentify.itemCSS)[0];
			nextPageBtn = jQuery(presentify.selectedPageBtn).siblings('.pageBtn')[1];
		}
		var zIndex = jQuery(presentify.selectedContentAsset).css('z-index');
		if( zIndex<2 ) {
			zIndex=20;
			jQuery(presentify.selectedContentAsset).css({zIndex:zIndex});
		}
		if(!next) {
			return;
		}
		jQuery(next).css({zIndex:zIndex-1}).show();
		jQuery(presentify.selectedContentAsset).fadeOut('slow');

		jQuery(presentify.selectedPageBtn).removeClass('current');
		presentify.selectedContentAsset = next;
		presentify.selectedPageBtn = nextPageBtn;
		//jQuery(presentify.selectedContentAsset).fadeIn('slow');
		jQuery(presentify.selectedPageBtn).addClass('current');
		presentify.timer = setTimeout(presentify.showNextContentAsset,6000);
	}
};
jQuery.fn.presentify = function(_options){
	var defaults = {itemCSS:'.contentasset'};
	jQuery.extend(defaults,_options);
	
	presentify.itemCSS = defaults.itemCSS;
	
	// Look for children and set up the pagination
	var contentassets = this.find(defaults.itemCSS);
	if( contentassets==null || contentassets.size()==0 ) return;
	var height = jQuery(contentassets[0]).height();
	this.height(height);
	var numAssets = contentassets.size();
	contentassets.hide();
	presentify.selectedContentAsset = contentassets[0];
	this.prepend('<div class="pagination" />');
	var pageDiv = this.find('.pagination');
	jQuery(presentify.selectedContentAsset).show();
	var playPauseBtn = jQuery("<a class='pageBtn pause'>Pause</a>").click(function(){
		var that = jQuery(this);
		if( that.hasClass('pause') ) {
			clearTimeout(presentify.timer);
			that.removeClass('pause');
			that.addClass('play');
			that.text('Play');
		} else {
			that.removeClass('play');
			that.addClass('pause');
			that.text('Pause');
			presentify.showNextContentAsset();
		}
	});
	pageDiv.append(playPauseBtn);
	contentassets.each(function(index){
		var that = this;
		jQuery(this).css({position:'absolute',zIndex:10-index}).mouseenter(function(){
			clearTimeout( presentify.timer );
		}).mouseleave(function(){
			if( pageDiv.find('.pause').size()==1 ) {
				clearTimeout( presentify.timer );
				presentify.timer = setTimeout(presentify.showNextContentAsset,6000);
			}
		});
		var link = jQuery("<a class='pageBtn'>"+(index+1)+"</a>&nbsp;").click(function(){
			if( that == presentify.selectedContentAsset ) return false;
			var zIndex = jQuery(presentify.selectedContentAsset).css('z-index');
			if( zIndex<2 ) {
				zIndex=20;
				jQuery(presentify.selectedContentAsset).css({zIndex:zIndex});
			}
			jQuery(that).css({zIndex:zIndex-1}).show();
			jQuery(presentify.selectedContentAsset).fadeOut('slow');
			presentify.selectedContentAsset = that;
			//jQuery(presentify.selectedContentAsset).fadeIn('slow');
			jQuery(this).addClass('current').siblings().removeClass('current');
			presentify.selectedPageBtn = this;
			
			return false;
		});
		pageDiv.append(link);
	});
	presentify.selectedPageBtn = this.find('.pageBtn')[1];
	jQuery(presentify.selectedPageBtn).addClass('current');
	presentify.timer = setTimeout(presentify.showNextContentAsset,6000);
}

function updateMiniCart(el, pid) {
	var parentRow = "#"+jQuery(el).parents("tr.tablerow")[0].id;
	var form = jQuery(el).parents('form');
	var name = el.name;
	var PID = pid;
	form.ajaxSubmit({ 
		url:form.attr('action')+"?"+name+"="+PID,
		success:function(responseText){
			var node = jQuery(responseText);
			//jQuery(parentRow).html(node.find(parentRow).html());
			//jQuery(".cart").html(node.find(".cart").html());
			//jQuery('.cartordertotals').html(node.find('.cartordertotals').html());
			//initBehaviors(jQuery(parentRow)[0]);
		}
	});
	return false;
}

function updateMiniCartMini(el, pid) {
	//var parentRow = "#"+jQuery(el).parents("tr.tablerow")[0].id;
	var form = jQuery(el).parents('form');
	var name = el.name;
	var PID = pid;
	form.ajaxSubmit({ 
		url:form.attr('action')+"?"+name+"="+PID,
		success:function(responseText){
			var node = jQuery(responseText);
			//jQuery(parentRow).html(node.find(parentRow).html());
			//jQuery(".cart").html(node.find(".cart").html());
			//jQuery('.cartordertotals').html(node.find('.cartordertotals').html());
			//initBehaviors(jQuery(parentRow)[0]);
		}
	});
	return false;
}

jQuery.fn.extend({
	filterFont: function(callback) {
		if(jQuery.browser.msie)
			jQuery(this).get(0).style.removeAttribute('filter');
		if(callback != undefined)
			callback.call(this);
		return this;
	}		
});