/*
 * 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

    // default dialog box settings
    dialogSettings: {
        bgiframe: true,																									// this is required mainly for IE6 where
        autoOpen: false,																								// drop downs bleed into dialogs!!! it depends on
        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',
        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() {
      jQuery("<div/>").attr("id", "QuickViewDialog").html(" ").appendTo(document.body);									// register initializations here -  quick view dialog div
	  jQuery("<div/>").attr("id", "BonusProductDialog").html(" ").appendTo(document.body);								// bonus product dialog div
      jQuery("<div/>").attr("class", "sizingdiv").html(" ").appendTo(document.body);
      
      this.minicart.init();																								// micicart object initialization
      this.execUjs();																									// execute unobtrusive js code

      // renders horizontal/vertical carousels for product slots
      jQuery('#horicarousel').jcarousel({
            scroll: 1,
            itemVisibleInCallback: app.captureCarouselRecommendations
        });

        jQuery('#vertcarousel').jcarousel({
            scroll: 1,
            vertical: true,
            itemVisibleInCallback: app.captureCarouselRecommendations
        });
    },

    // 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
        if (!options.reqName || !this.currentRequests[options.reqName]) {											// progress and let go null 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) {
		                if (jQuery.browser.msie) {
		                	jQuery(options.selector).html(response); 												//jQuery(options.selector)[0].innerHTML = response;
		                } else {
		                	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 a2cBtnLabel = options.label || null;

      jQuery("#"+cId).html(app.showProgress("productloader"));														// show small loading image
      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){
        (a2cBtnLabel != null ? jQuery("#"+cId+" .addtocartbutton:last").html(a2cBtnLabel) : '');					// update the Add to cart button label if one provided
      }});
    },

    // 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() {
        app.minicart.reset();																						// reset all the existing event bindings
        jQuery(".minicarttotal").hover(function(e){(app.minicart.isShow() ? '': app.minicart.slide());});			// bind hover event to the cart total link at the top right corner
        jQuery(".minicarttotal").click(function(){window.location.href = jQuery('.mccheckout').attr('href');})		//send clicks on the cart total link to the basket
        jQuery('.minicartcontent').mouseenter(function(e) {
        		clearTimeout(app.minicart.timer);
        		app.minicart.timer = null;
        })
        .mouseleave(function(e) {
        		clearTimeout(app.minicart.timer);
        		app.minicart.timer = null;
        		app.minicart.timer = setTimeout( 'app.minicart.close()', 30 );										// after a time out automatically close it
        });

        // register close button event
        jQuery('.minicartcontent .minicartclose').click(function() {    
        	app.minicart.reset();
        	app.minicart.close(0);																					// reset all the events bindings
        });
      },

      // 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);
        app.minicart.init();				// bind all the events
	        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').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 );
      },

   // popup dialog replaces standard mini cart slide behavior for ATC actions
      addPop: function(addedPID) {
	        if(app.minicart.suppressAddPop && app.minicart.suppressAddPop()) { return; }
	        if (!jQuery('.justAdded').size() > 0) {
	        	jQuery('body').append('<div class=\'justAdded\'></div>');
	        } else {
	        	jQuery('.justAdded').html('');
	        }
		//prepare popup html
        var currentItems = jQuery('.cartquantity').html();
        var currentTotal = jQuery('.ordersubtotal .value').html();
        var popText ="has been added to your cart.";
        var bonusItem = (jQuery(".bonusproductalert").empty().html() || jQuery(".bonusproductalert").html() == null || jQuery(".bonusproductalert").html() == "null") ? '' : jQuery(".bonusproductalert").html() + ' Please visit your cart to add your Bonus item(s).';
        var qtyItemsAdded = '';
        //var qtyItemsAdded = jQuery('.quantityinput').val();
        //if this product is a bundle page retrieve the quantity from the product cache instead of page element
	        if (app.ProductCache && app.ProductCache.subProducts.length > 0) {
		        jQuery.each(app.ProductCache.subProducts, function() { 
		        	if (this.selectedOptions.pid == addedPID) { qtyItemsAdded = this.selectedOptions.Quantity; }
		        });
	        } else {
	        	qtyItemsAdded = app.ProductCache.selectedOptions.Quantity;
	        }
        
        var currentAddedDescription = '';
	        if (addedPID == 'multi') {
	        	currentAddedDescription = 'multi';
	        } else {
		        jQuery('.checkoutminicart .summaryproduct').each( function() {
		    		if (jQuery(this).children('.prodid').html() == addedPID) {
		    			currentAddedDescription = jQuery(this).find('.name a').html() + '</span> ';
						return false;
					}
		        });
	        }
        
		/*if (currentAddedDescription == 'multi') {
			jQuery('.justAdded').append('<div class=\"currentdescpop\"><span>Multiple products</span> '+ popText + '</div>');
		} else {*/
	        if (qtyItemsAdded == "") {
				jQuery('.justAdded').append('<div class=\"currentdescpop\"><span>' + currentAddedDescription + popText + '</div>');	        	
	        } else if (qtyItemsAdded == "1") {
				jQuery('.justAdded').append('<div class=\"currentdescpop\"><span>1 ' + currentAddedDescription + popText + '</div>');
	        } else {
	        	currentAddedDescription = jQuery.trim(currentAddedDescription.toString());									//trim & stringify
	        	//if the product name doesn't end with an S, add one
	        	if (currentAddedDescription.charAt(currentAddedDescription.length - 1) != 's') { currentAddedDescription = currentAddedDescription + 's'; }
	        	jQuery('.justAdded').append('<div class=\"currentdescpop\"><span>'+ qtyItemsAdded + ' ' + currentAddedDescription + popText + '</div>');
	        }
		/*}*/

        jQuery('.justAdded').append('<div class=\"currentitemspop\">your cart now has ' + currentItems + ' items.</div>');
        jQuery('.justAdded').append('<div class=\"currenttotalpop\">cart total: <strong>' + currentTotal + '</strong></div>');
        jQuery('.justAdded').append('<div class=\"viewcartpop\"><a href=\"' + app.URLs.popcartshow + '\">View Cart</a></div>');
        if ( jQuery(".bonusproductalert").html() != null || jQuery(".bonusproductalert").html() != "null" ) {
        	jQuery('.justAdded').append('<div class=\"currentitemspop\" style=\"margin-top:1em;text-transform:lowercase;\"><strong>' + bonusItem + '</strong></div>');
        }
        jQuery('.justAdded').append('<div class=\"buttonspop\"><div onclick=\"javascript:jQuery(\'.justAdded\').dialog(\'close\')\" class=\"cntShopping\">Continue Shopping</div><div class="chkOut" onclick=\"javascript:window.location.href=\'' + app.URLs.popcartshow + '\';\">Check Out</div></div>');
        jQuery('.justAdded').dialog({bgiframe:true, autoOpen:false, buttons:{}, modal:false, overlay: {opacity:0.5,background:"black"}, height:365, width:322, title:'', hide:"normal", resizable:false});
        jQuery('.justAdded').dialog('open');

        jQuery(document).bind('click', closePopHandler);

      },
   // popup dialog replaces standard mini cart slide behavior for ATC actions
      addPopWishList: function(SystemVars) {
    	var addedPID = SystemVars.pid;
    	var _Quantity = "" + SystemVars.Quantity;
        	if(app.minicart.suppressAddPop && app.minicart.suppressAddPop()) { return; }
	        if (!jQuery('.justAdded').size() > 0) {
	        	jQuery('body').append('<div class=\'justAdded\'></div>');
	        } else {
	        	jQuery('.justAdded').html('');
	        }
		//prepare popup html
        var currentItems = jQuery('.cartquantity').html();
        var currentTotal = jQuery('.ordersubtotal .value').html();
        var qtyItemsAdded = '';
        //if this product is a bundle page retrieve the quantity from the product cache instead of page element
	        if (app.ProductCache && app.ProductCache.subProducts.length > 0) {
		        jQuery.each(app.ProductCache.subProducts, function() {
		        	if (this.selectedOptions.pid == addedPID) { qtyItemsAdded = this.selectedOptions.Quantity; }
		        });
	        } else {
	        	qtyItemsAdded = app.ProductCache.selectedOptions.Quantity;
	        }
        //Start Modified Add to Wishlist call Check Wishlist if product exists for enhancement ticket #[5719] & #[12178]
        wishlistURLPart = app.URLs.wishlist.substring(0 , app.URLs.wishlist.search(/-Show/i));
        wishlistValidateExistenceURL = wishlistURLPart + "-CheckWishlistProducts";
        wishlistValidateExistenceURL = app.util.appendParamToURL(wishlistValidateExistenceURL, "pid", addedPID);
        wishlistValidateExistenceURL = app.util.appendParamToURL(wishlistValidateExistenceURL, "quantity", _Quantity);
        var wishListDescription = '';
        
        jQuery.ajax({
            type     : "POST",
            url    	 : wishlistValidateExistenceURL,
            cache    : true,
            success  : function( msg ){
			        	_y_addToWishList = true;
			        	var _notificationMsg = "";
			        	var _totalCurrentAndAdded = 0;
			        	var _plid = "";
			        	if( msg != 'NONE' ){
			        		_msgParts = msg.split("---");
			        		_currentQuantity = parseFloat( _msgParts[1] );
			        		_plid = _msgParts[2];
			        		p_Quantity = parseFloat( _Quantity );
			        		_notificationMsg = "This Item already Existed in your Wishlist.\n";
			        		if( _currentQuantity == 15 ){
			        			_notificationMsg += "You already have 15 of this item on your wishlist, You can't add some more.\n";
			        			_wishListDescription = '<div class=\"currentdescpop\" id=\"wishListNotification\">'+_notificationMsg+'</div>';
				        		jQuery('.justAdded').append( _wishListDescription );
				        		jQuery('#wishListNotification').css("textTransform","none");
				        		jQuery('.justAdded').dialog({bgiframe: true, autoOpen: false, buttons: {}, modal: false, overlay: {opacity: 0.5,background: "black"}, height: 310, width: 322, title: '', hide: "normal", resizable: false});
						        jQuery('.justAdded').dialog('open');
			        		} else {
				        		_totalCurrentAndAdded = _currentQuantity + p_Quantity ;
				        		if( _totalCurrentAndAdded > 15 ){
				        			var _resultOverLimit = p_Quantity - (parseFloat(_totalCurrentAndAdded) - 15);
				        			_notificationMsg += "You have "+_currentQuantity+" of this item on your wishlist. You can only add "+_resultOverLimit+" more for this product. ";
				        			_totalCurrentAndAdded = 15;
				        		}
				        		_notificationMsg += "\nWould you like to proceed?";
			        		}
			        		_y_addToWishList = false;
			        	}
			        	if( _notificationMsg != "" ){
			        		if( _totalCurrentAndAdded > 0 ){
				        		_wishListDescription = '<div class=\"currentdescpop\" id=\"wishListNotification\">'+_notificationMsg+'</div>';
				        		jQuery('.justAdded').append( _wishListDescription );
				        		jQuery('.justAdded').append('<div class=\"buttonspop_wish\"><div class=\"cntShopping_wish\" id=\"proceedAddToWishList\">Continue</div></div>');
				        		jQuery('.justAdded').dialog({bgiframe: true, autoOpen: false, buttons: {}, modal: false, overlay: {opacity: 0.5,background: "black"}, height: 310, width: 322, title: '', hide: "normal", resizable: false});
						        jQuery('.justAdded').dialog('open');
						        jQuery('#wishListNotification').css("textTransform","none");
						        jQuery('#proceedAddToWishList').css("width","57px");
						        jQuery('#proceedAddToWishList').css("backgroundPosition","-4px -405px");
						        jQuery('#proceedAddToWishList').css("marginLeft","100px");
						        jQuery('#proceedAddToWishList').click(function(){
						            jQuery('.justAdded').html('');
						        	wishListDescription = jQuery('.productname').html();
						        	var _wishListDescription = '<div class=\"currentdescpop\"><span>' + _totalCurrentAndAdded + ' ';// + wishListDescription + '</span> ::COUNT:: been added to your wish List.</div>';
										if (wishListDescription.charAt(wishListDescription.length - 1) != 's'){
								        		wishListDescription = wishListDescription + 's';
										}
									wishListDescription += '</span> have';
									_wishListDescription += wishListDescription + ' been added to your wish List.</div>';
						        	jQuery('.justAdded').append( _wishListDescription );
							        jQuery('.justAdded').append('<div class=\"buttonspop_wish\"><a id="wiewwishlist" href=\"' + app.URLs.wishlist+ '\">View Wish List</a><div onclick=\"javascript:jQuery(\'.justAdded\').dialog(\'close\')\" class=\"cntShopping_wish\">Continue Shopping</div></div>');
							        _addWishlistURLPart = app.URLs.wishlist.substring(0 , app.URLs.wishlist.search(/-Show/i));
							        _addWishlistValidateExistenceURL = _addWishlistURLPart + "-ProceedToAdd";
							        _addWishlistValidateExistenceURL = app.util.appendParamToURL(_addWishlistValidateExistenceURL, "plid", _plid);
							        _addWishlistValidateExistenceURL = app.util.appendParamToURL(_addWishlistValidateExistenceURL, "pid", addedPID);
							        _addWishlistValidateExistenceURL = app.util.appendParamToURL(_addWishlistValidateExistenceURL, "Quantity", _totalCurrentAndAdded);
							        jQuery.ajax({
						                type	 : "POST",
						                url      : _addWishlistValidateExistenceURL,
						                cache    : true,
						                data   	 : addedPID,
						                success  : function(_msg){},
						                error  	 : function(){ alert("Unable To add Item to Wishlist..."); }
						            });
							        return false;
						        });
			        		}
			        	}
			        	if( _y_addToWishList ){
		        			wishListDescription = jQuery('.productname').html();
						    var _wishListDescription = '<div class=\"currentdescpop\"><span>' + _Quantity + ' ';// + wishListDescription + '</span> ::COUNT:: been added to your wish List.</div>';
							if( _Quantity != "0" ){
								wishListDescription = jQuery.trim(wishListDescription);
								if(  _Quantity != "1"  ){
								   	if (wishListDescription.charAt(wishListDescription.length - 1) != 's')
								   		wishListDescription = wishListDescription + 's';
								   	wishListDescription += '</span> have';
							    } else {
									wishListDescription += '</span> has';
							    }
								_wishListDescription += wishListDescription + ' been added to your wish List.</div>';
						       	jQuery('.justAdded').append( _wishListDescription );
						        jQuery('.justAdded').append('<div class=\"buttonspop_wish\"><a id="wiewwishlist" href=\"' + app.URLs.wishlist+ '\">View Wish List</a><div onclick=\"javascript:jQuery(\'.justAdded\').dialog(\'close\')\" class=\"cntShopping_wish\">Continue Shopping</div></div>');
						        jQuery('.justAdded').dialog({bgiframe: true, autoOpen: false, buttons: {}, modal: false, overlay: {opacity: 0.5,background: "black"}, height: 310, width: 322, title: '', hide: "normal", resizable: false});
						        jQuery('.justAdded').dialog('open');
						        _addWishlistURLPart = app.URLs.wishlist.substring(0 , app.URLs.wishlist.search(/-Show/i));
						        _addWishlistValidateExistenceURL = _addWishlistURLPart + "-AddAjax";
						        _addWishlistValidateExistenceURL = app.util.appendParamToURL(_addWishlistValidateExistenceURL, "pid", addedPID);
						        _addWishlistValidateExistenceURL = app.util.appendParamToURL(_addWishlistValidateExistenceURL, "Quantity", _Quantity);
						        jQuery.ajax({
					                type   : "POST",
					                url    : _addWishlistValidateExistenceURL,
					                cache  : true,
					                data   : addedPID,
					                success: function(_msg){},
					                error  : function(){ alert("Unable To add Item to Wishlist..."); }
					            });
							}
			        	}
			        },
            error  : function(){
			        	errMsg = jQuery('.productname').html();
			        	errMsg = '<div class=\"currentdescpop\"><span> An Error Has been encountered</span></div>';
			        	jQuery('.justAdded').append( errMsg );
			        	jQuery('.justAdded').dialog({bgiframe: true, autoOpen: false, buttons: {}, modal: false, overlay: {opacity: 0.5,background: "black"}, height: 310, width: 322, title: '', hide: "normal", resizable: false});
				        jQuery('.justAdded').dialog('open');
			        }
          });
        
        _postBackAjax = function(){
        	jQuery.ajax({
                type   : "POST",
                url    : app.minicart.wishlistaddurl+'?Quantity='+_Quantity+'&pid='+addedPID,
                cache  : true,
                data   : addedPID,
                success: handlerFunc,
                error  : errFunc
              });
        }
        jQuery(document).bind('click', closePopHandler);

      },
      
      // 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) {
        var postdata = postdata;																					// get the data of the form as serialized string
        var addButtons = [];																						// get button reference
        var addButton = null;																						// the button to update

        // 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)  {
          if (addButton != null) { addButton.src = previousImageSrc; }												// hide progress indicator
          	jQuery('#minicart').html(req);																			// replace the content
          	app.minicart.init();																					// bind all the events
          if(app.minicart.suppressSlideDown && app.minicart.suppressSlideDown()) {
            // do nothing the hook 'MiniCart.suppressSlideDown()' should have done the refresh
          } else {
        	  /*app.minicart.slide(); - original minicart behavior*/
				if (app.ProductCache && app.ProductCache.selectedOptions.pid && app.ProductCache.selectedOptions.pid != '' && app.ProductCache.subProducts.length == 0) { 
					app.minicart.addPop(app.ProductCache.selectedOptions.pid);										//fire added popup for single products
				} else if (app.ProductCache && app.ProductCache.subProducts.length > 0){
					app.minicart.addPop(postdata.pid);					
				} //do nothing if product cache does not exist (ex: playwall)

            if (callback) callback();
          }
          	// fire the BonusDiscountLineItemCheck event so we can check if there is a bonus discount line item
			jQuery(document).trigger(jQuery.Event("BonusDiscountLineItemCheck"));
        }

        // handles add to cart error
        var errFunc = function(req) { if (addButton != null) { addButton.src = previousImageSrc; } } 				// hide progress indicator
        	app.minicart.close();																					// closes a previous mini cart

        // add the product
        jQuery.ajax({
                type	: "POST",
                url		: app.minicart.url,
                cache	: true,
                data  	: postdata,
                success : handlerFunc,
                error   : errFunc
              });
      },
    
      // callback - call back function/handler
      addwishlist: function(progressImageSrc, _postdata, callback) {
        var postdata = _postdata.pid;																				// get the data of the form as serialized string
        var addButtons = [];																						// get button reference
        var addButton = null;																						// the button to update
        	if (addButtons.length == 1)  { addButton = addButtons[0]; }												// it is an array of buttons, but we need only one all other combinations are strange so far
        var previousImageSrc = null;

        // show progress indicator
        if (addButton != null) {
          previousImageSrc = addButton.src;
          addButton.src = progressImageSrc;
        }

        // handles successful add to cart
        var handlerFunc = function(req)  {
          if (addButton != null) { addButton.src = previousImageSrc; }												 // hide progress indicator
          																											 //jQuery('#minicart').html(req); -  replace the content
          app.minicart.init();																						 // bind all the events
         /* if(app.minicart.suppressSlideDown && app.minicart.suppressSlideDown()) {
          	//do nothing  the hook 'MiniCart.suppressSlideDown()' should have done the refresh
            } else {
        	  app.minicart.slide();	-	original minicart behavior*/
				if (app.ProductCache && app.ProductCache.selectedOptions.pid && app.ProductCache.selectedOptions.pid != '' && app.ProductCache.subProducts.length == 0) { 
					app.minicart.addPopWishList(_postdata);															//fire added popup for single products
				} else if (app.ProductCache && app.ProductCache.subProducts.length > 0) {
					app.minicart.addPopWishList(_postdata);					
				} //do nothing if product cache does not exist (ex: playwall)
            if (callback) callback();
          //}
        }

        // handles add to cart error
        var errFunc = function(req) { if (addButton != null) { addButton.src = previousImageSrc; } }     				// hide progress indicator   
        	app.minicart.close();																						// closes a previous mini cart

        // add the product - Comment this Add-Ajax pipeline to allow validation before adding product to Wishlist for enhancement ticket #[5719] & #[12178]
        	/*jQuery.ajax({
                type	: "POST",
                url		: app.minicart.wishlistaddurl+'?Quantity='+_Quantity+'&pid='+postdata,
                cache	: true,
                data	: postdata,
                success : handlerFunc,
                error   : errFunc
              });*/
      },
      
      orderStatusLoading: function(progressImageSrc) { jQuery('#od').html("<div><img src="+progressImageSrc+"></div>Loading...Please wait..."); },
      orderStatus: function(customerno, pagingurl, source, view) {
        var customerno = customerno;
	    var statusurl = pagingurl? app.minicart.orderstatusurlpaging : app.minicart.orderstatusurl;
        	statusurl += '?customerno='+customerno+'&source='+source+'&view='+view;

        var handlerFunc = function(req)  { jQuery('#orders').html(req);}												// handles success -  replace the content
	    var errFunc = function(req) {}																					//handles error - jQuery('#t1').html(req);
        jQuery.ajax({
                type  	: "json",
                url     : statusurl,
                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
          /*jQuery('#nav .sitesearch').css('display','block');															// sometimes infinitely thus changed it to fadeOut
            jQuery('#nav .store_locator').css('display','block');   jQuery('#nav .highlight_two').css('display','block');
            jQuery('#nav .highlight_three').css('display','block'); jQuery('#header .headerbar').css('display','block');*/
        }
      },
      suppressSlideDown: function() { return false; },																	// hook which can be replaced by individual pages/page types (e.g. cart)
      suppressAddPop: function() { return false; }																		// hook which can be replaced by individual pages/page types (e.g. cart)
    },

    // close quick view dialog if open and refresh the page
    refreshCart: function() {
      app.quickView.close();
      location.href = location.href;																					// refresh without posting
    },

    // Product quick view object
    quickView: {
      // 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;
          }
        );

        // 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: 533,
            width: 685,
            dialogClass: 'quickview',
            resizable: false
        }});

          jQuery('#QuickViewDialog').dialog('open');
          app.getProduct({containerId: "QuickViewDialog", source: options.source, url: options.url, label: options.label});
      },
      close: function() { jQuery('#QuickViewDialog').dialog('close'); }													// close the quick view dialog
    },
	// Bonus product view object
	bonusProductsView: {
		// show bonus product view dialog and send request to the server to get the bonus products
		// options.url - bonus product url
		show: function(options) {
			app.createDialog({id: 'BonusProductDialog', options: {
		    	height: 530,
		    	width: 630,
		    	dialogClass: 'quickview',
		    	resizable: false
			}
		});
		    jQuery('#BonusProductDialog').dialog('open');	
		    jQuery("#" + "productresultarea").hide();
			app.ajax.load({selector: "#BonusProductDialog", url: options.url, callback: function(responseText, textStatus){}});				
		},
		close: function() { jQuery('#BonusProductDialog').dialog('close'); }		// close the Bonus product view dialog
	},
    // 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));
    },

    // 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).attr("id", 'loadingImg'));
    },

    // validation plugin intialization
    validator: function() { 
      // override default required field message
      jQuery.validator.messages.required = function($1, ele, $3) { 	
    	 AddError(ele);	
    	 hasErrors();
		 jQuery(ele).blur(function(){
    		 AddError(ele);
    		 hasErrors();
    	 });
		
		 function hasErrors(){
			 if(jQuery("ul#errorList >li").length > 0){														  // check if the error list has items
				 jQuery("#errorSummary").show('fast');
				 location.href = location.href.replace("#errorSummary","").replace("#","") + "#errorSummary"; // Addtional Script to focus the Error/Warning Message Ticket #[7124]
			 } else {
				 jQuery("#errorSummary").hide('fast');
				 location.href = location.href.replace("#errorSummary","").replace("#","") + "#"; 			 // Addtional Script to focus the Error/Warning Message Ticket #[7124]
			 }
		 }

    	 function AddError(ele){
    		 var id = jQuery(ele).attr("id"); 																// ID of the element
    		 var labelID = jQuery(ele).attr("id") + "_1";    												// ID of the span that was defined in the inputfield.isml
    		 var field = id.substring(id.lastIndexOf("_")+1);
    		 var labelText = jQuery("#"+labelID).text().substring(0,jQuery("#"+ labelID).text().lastIndexOf(":"));			//Error Label
    		 	jQuery("#li_" + field).remove();   															//remove the existing list	 
	    		 if (jQuery(ele).attr("value") != ""){
	     			jQuery("#" + labelID).removeClass("errorlabel");										//remove errorlabel class from the label 
	     		 } else {
	     			if(!(id == 'dwfrm_login_username2' || id == 'dwfrm_login_password2' || labelID == 'dwfrm_changeemail_email_1' || labelID == 'dwfrm_changeemail_emailconfirm_1' || labelID == 'dwfrm_changepassword_password_1' || labelID == 'dwfrm_changepassword_passwordconfirm_1')) {
	     			 	jQuery("<li id='li_" + field+"'>" + labelText + "</li>").appendTo("ul#errorList");	//Add field to errorlist
	     			}
	     			jQuery("#" + labelID).addClass("errorlabel");											//add errorlabel class to label
	     		 }
    	 }
        return "";
      };

      /** Add phone validation method to jQuery validation plugin.
       * Text fields must have 'phone' css class to be validated as phone
       * phoneUS is copied from http://docs.jquery.com/Plugins/Validation/CustomMethods/phoneUS */
      jQuery.validator.addMethod("phone", function(phone_number, element) {
        var data   = jQuery(element).data("data");															// find out the country code
        var country = (data && data.country && data.country != "") ? data.country : "US"; 					// default to US phone validation
        var that = this;																					// preserve this instance
        var phoneCA,																						// country specific phone validation handlers
          phoneUS = phoneCA = function() {
            phone_number = phone_number.replace(/\s+/g, "");
            return that.optional(element) || phone_number.length > 9 && phone_number.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/);
          }
        window["eval"]("var phoneHandler = (typeof phone" + country + " != 'undefined') ? phone"+country+": null;");
          // call the country specific phone validation handler
        return (phoneHandler && typeof phoneHandler == "function" ? phoneHandler() : true);
      }, app.resources["INVALID_PHONE"]);

      // 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 { hiddenStr = window["eval"]("(" + hiddenStr + ")"); }									// try to parse it as a json
	          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) {																// for each field of type phone in the current form,
      var selectedCountry = this.options[this.selectedIndex].value;										// set its country as a data attribute to be used while
        jQuery(this).parents("form:first").find("input.phone").each(function() {						//doing phone field validation see app.validator addMethod.
          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() {
	      this.hiddenData();																			// process hidden data in the html markup and convert it into data object(s)
	      this.validator();																				// initialize form validator plugin
	      this.addCountryListener();																	// process country form fields and attach listeners
    },

    captureCarouselRecommendations : function(c, li, index, state) {									// capture recommendation of each product when it becomes visible in the carousel
      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 : {
      // initializes all product tiles contained in the current page
      initAll: function() {
        var quickViewOptions = {																		// bind quick view button toggling and click
        	buttonSelector: "div.producttile div.quickviewbutton",
            imageSelector: "div.producttile div.image",
            buttonLinkSelector: "div.producttile div.quickviewbutton 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																// mouseout took place when mouse actually left layer handle event now
	            if (reltg == tg) return;

          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) {
        var currentImg = jQuery(swatch.parents()[5]).find(".productimage img");								// get the new and the original image
        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(".quickviewbutton a");
        var imageAnchor = swatch.parents(".producttile").find(".productimage 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);
        	imageAnchor.attr("href", newUrl);

        // remove all current markers - jQuery(swatch.parents()[0]).find("a.swatch").removeClass("selected");
        jQuery("div.innerpalette a.swatch").removeClass("selected");
        swatch.addClass("selected");																		// mark swatch as 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()[5]).find(".productimage img");
        var newImg = swatch.children("img.hiddenthumbnail");
        	if(!newImg || !currentImg) return;
        	if(swatch.hasClass("selected")) return;															// we do nothing in case the swatch is already selected
	        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 : {
      // 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);
        }
      },
      loadedCSSFiles  : [],																			 // array to keep track of the dynamically loaded CSS files
      clearDynamicCSS : function() {																 // removes all dynamically loaded CSS files
        for(var i=0; i<app.util.loadedCSSFiles.length; i++) {
          app.util.unloadCSSFile(app.util.loadedCSSFiles[i]);
        }
      },
      unloadCSSFile : function(url) {																 // dynamically unloads a CSS file
        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]);
          }
        }
      },
      cookiesEnabled : function() {																	  // checks if cookies are enabled
        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) {
        if(jQuery("#dialogcontainer").length == 0) { jQuery(document.body).append("<div id=\"dialogcontainer\"></div>"); }		// create the dialog container if not present already
        	title = title || "Dialog";																							// set a default title - 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\" />");
        var post = jQuery("#dialogcontainer form").serialize();													// serialize the form and get the post url
        var url = jQuery("#dialogcontainer form").attr("action");												// post the data and replace current
	          jQuery.ajax({																						//content with response content
	           type    : "POST",
	           url	   : url,
	           data	   : post,
	           dataType: "html",
	           success : function(data){ jQuery("#dialogcontainer").empty().html(data); },
	           failure : function(data) { alert(app.resources["SERVER_ERROR"]); }
	        });
      }
    }
  }
})(jQuery);

// application initialization on dom ready
jQuery(document).ready(function(){ app.init(); });
var closePopHandler = function() {
	jQuery('.justAdded').dialog('close');
	jQuery(document).unbind('click', closePopHandler);
}
