﻿//General 4-Tell plug-in code for all sites
//	NOTE: Do not edit this page! These are generic settings. 
//		All client and cart specific settings are controlled in a separate .js file
//		Check the page header for name and location

//Namespace for all 4-Tell code
(function( _4TellBoost, $, undefined ) {
	
	// General 4-Tell Web Service Settings
	var Service = {
		address:'www.4-Tell.biz/Boost2.0/',
		pageType: 'Home',
		productList: new Array(),
		productCount: 0,
		cartList: new Array(),
		cartCount: 0,
		blockList: new Array(),
		blockCount: 0,
		customerId: '',
		lastDivIDs: new Array() //used to make sure the same items are not in both divs
	};	 

	// Client Settings
	//   This constructor initializes the site structure
	//   See client/platform js file for custom settings
	//
	_4TellBoost.Site = function() {
		this.baseURL = '';
		this.alias = '';
		this.GA_UA = ''; //supplying UA number here will override the tracking type
		this.GATrackingType = 'none'; //valid types are 'none', 'pageTracker', '_gaq'
		this.GATrackID = '4TellRecs';
		this.rotateTopSellers = true;
		this.addCartMethod = '';
		this.addCartImage = '';
		this.addCartClass = 'addCartClass';
		this.priceClass = '';
		this.strikePriceClass = '';
		this.salePriceClass = '';
		this.pricePrefix = '';
		this.salePricePrefix = '';
		this.showLogo = true;
		this.includeBase = false;
		this.delay = false;
		
		for (var n in arguments[0]) { this[n] = arguments[0][n]; } //allow passed args to override
	};
	_4TellBoost.SiteInfo = new _4TellBoost.Site();
			
			
	// Page Settings
	//   This constructor initializes the tout structures
	//   See client/platform js file for custom settings
	//
	_4TellBoost.ToutSettings = function(toutNumber) {
		var tout = this; //allow inner functions to access this tout's properties
		
		this.id = toutNumber;
		this.enable = false;
		this.showCaption = true;
		this.showImage = true;
		this.showTitle = true;
		this.showPrice = true;
		this.showRatings = true;
		this.showBuyButton = true;
		this.inFrame = false;
		this.resultType =  0; //Cross-sell
		this.numItems = 1;
		this.startPos = 1;
		this.orientation = ''; //vertical or horizontal
		this.newDivID = '';
		this.divSelect = ''; // if class use '.' -- if id use '#'
		this.divPosition = ''; //valid settings are 'append', 'replace', 'above', or 'below'
		this.caption = 'Suggestions for you...'; // caption for div1
		this.captionStyle = '';
		this.productStyle = '';
		this.imageSize = ""; //query parameters appended to thumbnail request 
		this.wrapper = ''; //formatting html to wrap around the div
		this.toutType = ''; //fill with pageType-resultType for GA tracking	
		if (this.id === 1)		
			this.callback = '_4TellBoost.displayTout1';
		else
			this.callback = '_4TellBoost.displayTout2';
		
		
		this.setToutType = function(pageType) { //combine pageType and resultType for analytics
			
			if (!tout.enable) return; //nothing to do
			
			tout.toutType = pageType + '-';
			switch (tout.resultType)
			{
				case 0: //Cross-sell
					tout.toutType += 'Cross-sell';
					break;
				case 1: //Personalized
					tout.toutType += 'Personalized';
					break;
				case 2: //Blended
					tout.toutType += 'Blended';
					break;
				case 3: //Similar
					tout.toutType += 'Similar';
					break;
				case 4: //Top-sellers
					tout.toutType += 'Top-sellers';
					break;
				default:
					tout.toutType += tout.resultType;
					break;
			}
		};
		
		// Tout call-back display function 
		//   This controls the display of each tout on the page
		//   It is not called directly by external code
		//   Instead it is called by one of the two external call-backs below
		//
	  	this.displayDiv = function(data) {
			var validItems = 0;
	  		try {
	  			// If the data is passed in then proceed
				if (data) {
					var lastDivLoaded = false;
					if (Service.lastDivIDs.length > 0) lastDivLoaded = true;
					
					//set the main container
					var this4TellContainer = '';
					var locations = $(tout.divSelect);
					if (!locations || !(locations.length)) 
						return; //unable to locate div
						
					//get the last match if more than one	
					var location = null;
					$.each(locations, function() {
						location = $(this); 
					});
					if (tout.divPosition === 'append')
						this4TellContainer = location;
					else
						this4TellContainer = $("<div id='"+ tout.newDivID +"'></div>");
	
					//set the caption
					if (tout.showCaption) {
						var thisCaption = $("<div class='"+tout.captionStyle+"'>"+tout.caption+"</div>");
						thisCaption.appendTo(this4TellContainer);
					}
	
					//get the items array
					var items = data['GetRecDisplayListResult'];
					if (!items || !items.length) return; //no results
					
					var frameTarget = '';
					if (tout.inFrame) frameTarget = "target='_parent' ";

					var siteProtocol = ('https:' === document.location.protocol) ? 'https://' : 'http://';
					var siteBase = siteProtocol + _4TellBoost.SiteInfo.baseURL + '/'; 
					var spacerImg = '';
					if (_4TellBoost.SiteInfo.includeBase)
						spacerImg = siteBase;
					spacerImg += '/web/assets/images/spacer.gif';
						
					// Loop through each product
					$.each(items, function(i, itemdata) {
									
						if (validItems >= tout.numItems) return false; //finished
						
						if (lastDivLoaded) {  
							var found = false;
							for (var q=0; q < Service.lastDivIDs.length; q++) {
								if (Service.lastDivIDs[q] === itemdata.productID) {
									found = true;
									break;
								}
							}
							if (found)
								return true; //skip this item
						}
						else
							Service.lastDivIDs[validItems] = itemdata.productID;
						validItems++;
	
						// This is the main product container
						var prod = $("<div class='" + tout.productStyle + "' />");
						
						//construct page link
						var pageLink = '';
						if (_4TellBoost.SiteInfo.includeBase)
							pageLink = siteBase;
						pageLink += itemdata.pageLink;
						
						//setup onclick string
						var trackFunc = 'onclick="_4TellBoost.TrackClick(' + "'" + tout.toutType + "','" + itemdata.productID + "');" + '"';
							
						//product image
						if (tout.showImage) {
							// A wrapper for the image allows better size and position control
							var prodImage = $("<div class='productImage' />");					
							var img = $("<img class='productImageImg' />");
							img.attr("src", itemdata.imageLink + tout.imageSize);
							img.appendTo(prodImage);
							img.wrap("<a href='" + pageLink + "' " + frameTarget + trackFunc + ' ></a>');
							prodImage.appendTo(prod);
						}
						
						//product title
						if (tout.showTitle) {
							if (navigator.appName === 'Microsoft Internet Explorer')  //special handling for IE
								var prodTitle = $("<div class='productTitle productTitleIE'>" + itemdata.title + "</div>");
							else
								var prodTitle = $("<div class='productTitle'>" + itemdata.title + "</div>");
							prodTitle.appendTo(prod);
							prodTitle.wrap("<a class='home' href='" + pageLink + "' " + frameTarget + trackFunc + ' ></a>');
						}
						
						//product price
						if (tout.showPrice) {
							var priceClass = '';
							var price = '';
							var salePrice = '';
							if ((itemdata.salePrice) 
								&& (itemdata.salePrice !== "$0.00") 
								&& (itemdata.salePrice !== "$-1.00")
								&& (itemdata.salePrice !== itemdata.price)) { 
								//strike out the full price and add the sale price
								priceClass = _4TellBoost.SiteInfo.strikePriceClass;
								price = '<s>' + itemdata.price + '</s>'; 
								salePrice =  _4TellBoost.SiteInfo.salePricePrefix + itemdata.salePrice; 						}
							else {
								priceClass = _4TellBoost.SiteInfo.priceClass;
								price = _4TellBoost.SiteInfo.pricePrefix + itemdata.price;
								salePrice = '&nbsp';
							}
							$("<div class='" + priceClass + " productPrice'>" +  price
								+ "</div>").appendTo(prod);
							$("<div class='" + _4TellBoost.SiteInfo.salePriceClass 
								+ " productSalePrice'>" + salePrice + "</div>").appendTo(prod);
						}
						
						//product ratings
						if (tout.showRatings && itemdata.rating && (itemdata.rating !== "-1.0")) {
							var ratingLink = _4TellBoost.getRatingImage(itemdata.rating);
							if (ratingLink) {
								var ratingImageLink = '';
								if (_4TellBoost.SiteInfo.includeBase)
									ratingImageLink = siteBase;
								ratingImageLink += ratingLink;
								var rating = $("<div class='ratingImage'/>");					
								var img = $("<img class='ratingImageImg'/>");
								img.attr("src", ratingImageLink);
								img.appendTo(rating);
								rating.appendTo(prod);
							}
						}

						// buy-now button (add to cart)
						if (tout.showBuyButton) {
							var buyWrapper = $("<div class='productBuy' />");
							var buyBtn = $("<" + _4TellBoost.SiteInfo.addCartBtnAtts + ' ' + trackFunc + " />");
							if (_4TellBoost.SiteInfo.addCartImage) {
								var buyBtnImage = '';
								if (_4TellBoost.SiteInfo.includeBase)
									buyBtnImage = siteBase;
								buyBtnImage += _4TellBoost.SiteInfo.addCartImage;
								buyBtn.attr("src", buyBtnImage);
							}
							if (buyBtn)
								buyBtn.appendTo(buyWrapper);
							var newAddress = '';
							if (_4TellBoost.SiteInfo.includeBase)
								newAddress = siteBase;
							switch (_4TellBoost.SiteInfo.addCartMethod) {
								case '3dCartMoreDetails':
									newAddress += itemdata.pageLink;
									break;
								case '3dCartQuickCart':
								default:
									newAddress += '/add_cart.asp?quick=1&item_id=' + encodeURI(itemdata.productID);
									break;
							}
							buyBtn.wrap('<a href="' + newAddress + '"></a>'); //no frameTarget needed for buy buton
							buyWrapper.appendTo(prod);
						}
						// Insert the product into the main product container
						prod.appendTo(this4TellContainer);
					});
					if (_4TellBoost.SiteInfo.showLogo) { //powered by 4-Tell logo				
						var poweredBy4T = $("<div/>");	
						if (navigator.appName === 'Microsoft Internet Explorer') { //special handling for IE
							if (tout.orientation === 'horizontal') {									
								//one more product div to fix IE bug
								var prod = $("<div class='product4T' style='background: none;'/>");
								var img = $("<img src='" + spacerImg + "' width='200px' height='1px'/>");
								img.appendTo(prod);
								prod.appendTo(this4TellContainer);
							}
							poweredBy4T.attr("class", "product4T poweredByImage4T poweredByImage4Tie");
						}	
						else	
							poweredBy4T.attr("class", "product4T poweredByImage4T");
						
						// This is the image and gets wrapped by the link
						var logoImg4T = $("<img class='poweredByImageImg' />");
						logoImg4T.attr("src", siteProtocol + "www.4-tell.net/images/Poweredby4Tell.png");
						logoImg4T.appendTo(poweredBy4T);
						logoImg4T.wrap('<a href="http://www.4-Tell.com" target="_blank"></a>');
	  
						poweredBy4T.appendTo(this4TellContainer);
					}
					if (tout.divPosition === 'below')
						this4TellContainer.insertAfter(location);
					else if (tout.divPosition === 'above')
						this4TellContainer.insertBefore(location);
					else if (tout.divPosition === 'replace') {
						this4TellContainer.insertBefore(location);
						location.remove();
					}
					if (tout.wrapper.length) 
						this4TellContainer.wrap(tout.wrapper);
				}
			} catch (ex) { }
	  	};
	};
	
	// The following two touts are used to define display settings for up to two locations. 
	//   Page specific choices should be set in the get4TellPageSettings switch table 
	//   which is defined in the client specific settings
	//
	_4TellBoost.FirstTout = new _4TellBoost.ToutSettings(1); 
	_4TellBoost.SecondTout = new _4TellBoost.ToutSettings(2); 
		
	 
	_4TellBoost.getPageSettings = function(pageType) {}; //placeholder...defined by Client specific settings	
	_4TellBoost.getRatingImage = function(rating) {}; //placeholder...defined by Client specific settings	

  	
	// getServiceResults:
	//   This function sets the parameters to pass to the 4-Tell Boost web service to retrieve
	//   recommended product data. This function is called by get4TellRecommendations above 
	//
	function getServiceResults(tout, productIDs, cartIDs, blockIDs, numResults) {
		var operation		= 'rest/GetRecDisplayList';
					
		// Assemble the url to call
		var query			=	'?clientAlias=' + _4TellBoost.SiteInfo.alias
								+ '&productIDs=' + productIDs
								+ '&cartIDs=' + cartIDs
								+ '&blockIDs=' + blockIDs
								+ '&customerID=' + Service.customerId
								+ '&numResults=' + numResults
								+ '&startPosition=' + tout.startPos
								+ '&resultType=' + tout.resultType 
								+ '&format=json'
								+ '&callback=' + tout.callback;	
								
		call4TellRest(operation, query);
	};

	// call4TellRest:
	//   This function is a rest helper to form calls to the 4-Tell Boost web service 
	//
	function call4TellRest(operation, query) {
		var jsonUrl	= Service.address + operation + encodeURI(query);
		
		// Call the service, passing the results to the callback function
		(function() {
			var forTell = document.createElement('script'); forTell.type = 'text/javascript'; forTell.async = true;
			forTell.src = ('https:' === document.location.protocol ? 'https://' : 'http://') + jsonUrl;
			var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(forTell, s);
		})();
	};		
  		
	
  	//External Functions
		
	//Delay Handling (to allow rec call to occur after a page element finishes loading
	_4TellBoost.DelayHandler = {
		element: null,
		toutDiv: null,
		callback: null,
		params: null,
		lastContents: "",
		statrted: false,
		ended: false
	};
	
	_4TellBoost.delayUntilLoaded = function(element) {
		_4TellBoost.DelayHandler.element = $(element);
		_4TellBoost.DelayHandler.lastContents = _4TellBoost.DelayHandler.element.html();
		setInterval( function() {
			if (_4TellBoost.DelayHandler.ended) return; //completed
			var newContents = _4TellBoost.DelayHandler.element.html();
			if (_4TellBoost.DelayHandler.lastContents != newContents) { //change detected
				if (!_4TellBoost.DelayHandler.started) _4TellBoost.DelayHandler.started = true;
				_4TellBoost.DelayHandler.lastContents = newContents;
			}
			else {
				if (!_4TellBoost.DelayHandler.started) return; //still waiting			
				_4TellBoost.DelayHandler.ended = true; //changes completed
				if (_4TellBoost.DelayHandler.callback) 
					_4TellBoost.DelayHandler.callback.call();
				if (_4TellBoost.DelayHandler.ended) {
					var params = _4TellBoost.DelayHandler.params;
					_4TellBoost.completeRecCall(params.pageType, params.productIDs, params.inCart);
				}
			}
			
		}, 100); //check every 100ms
	}	
	
	// getRecommendations:
	//   This function sets the number and type of recommendations based on the type of page
	//   where they will be displayed. Page specific settings are defined above.
	// 
	_4TellBoost.getRecommendations = function (pageType, productIDs) {
				
		// Page type can be passed in the call or pre-loaded into the global setting
		if (pageType === 'Auto')
			pageType = Service.pageType;
		
		//get rid of invalid id label like [catalog_ids]
		if (productIDs.indexOf(']') > 0)  productIDs = "";
		
		//get page specific tout settings (see get4TellPageSettings above)
		var inCart = false;
		inCart = _4TellBoost.getPageSettings(pageType);
		
		if (!_4TellBoost.FirstTout.enable && !_4TellBoost.SecondTout.enable) return; //nothing to do
		
		if (_4TellBoost.SiteInfo.delay) 
			_4TellBoost.DelayHandler.params = {pageType: pageType, productIDs: productIDs, inCart: inCart};
		else
			_4TellBoost.completeRecCall(pageType, productIDs, inCart)
	};
	
	// completeRecCall:
	//   Function to complete the recommendation call from getRecommendations above.
	//	 this portion is split off so it can be delayed if needed to wait for other page elements to load
	// 
	_4TellBoost.completeRecCall = function (pageType, productIDs, inCart) {
		var cartIDs = '';
		var blockIDs = '';

		// Compile the list of product IDs
		// IDs can be sent in the call or pre-loaded into the array
		var pCount = Service.productCount;
		if (pCount > 0) {
			if (((pageType === 'Category') || (pageType === 'Search'))
				&& (pCount > 4))
				pCount = 4; //only use first 4 items for list results pages
			
			var firstItem = true;
			if (productIDs !== "") {
				firstItem = false; 
			}
			for (var i = 0; i < pCount; i++) {
				if (firstItem) firstItem = false;						
				else productIDs += ',';
				productIDs += Service.productList[i];
			}
		}
				
		// Compile the list of cart items
		if (Service.cartCount > 0) {
			var firstItem = true;
			for (var i = 0; i < Service.cartCount; i++) {
				if (firstItem) firstItem = false;						
				else cartIDs += ',';
				cartIDs += Service.cartList[i];
			}
		}
		//on cart pages, use cart IDs directly instead of as influencers
		if (inCart && (cartIDs !== '')) {			
			if (productIDs !== '')
				productIDs += ',';
			productIDs += cartIDs;
			cartIDs = '';
		}
				
		// Compile the list of block items
		if (Service.blockCount > 0) {
			var firstItem = true;
			for (var i = 0; i < Service.blockCount; i++) {
				if (firstItem) firstItem = false;						
				else blockIDs += ',';
				blockIDs += Service.blockList[i];
			}
		}
		
		var numResults = _4TellBoost.FirstTout.numItems + _4TellBoost.SecondTout.numItems; //get extra in case of overlap
		if (_4TellBoost.FirstTout.enable) {
			getServiceResults(_4TellBoost.FirstTout, productIDs, cartIDs, blockIDs, numResults);
		}
		if (_4TellBoost.SecondTout.enable) {
			getServiceResults(_4TellBoost.SecondTout, productIDs, cartIDs, blockIDs, numResults);
		}
	};	

	_4TellBoost.TrackClick = function (toutType, productID)
	{		
		if (_4TellBoost.SiteInfo.GA_UA.length > 0) {
			window._gaq = window._gaq || [];
			window._gaq.push(['_setAccount',_4TellBoost.SiteInfo.GA_UA]);
			window._gaq.push(['_trackEvent', _4TellBoost.SiteInfo.GATrackID, toutType, productID]);
		}
		
		/*else if (pageTracker)
				pageTracker._trackEvent(_4TellBoost.SiteInfo.GATrackID, toutType, productID); 
		else if (_gaq)
				_gaq.push(['_trackEvent', _4TellBoost.SiteInfo.GATrackID, toutType, productID]);
		*/
		
		else switch (_4TellBoost.SiteInfo.GATrackingType) {	
			case 'pageTracker':
				pageTracker._trackEvent(_4TellBoost.SiteInfo.GATrackID, toutType, productID); 
				break;
			case '_gaq':
				_gaq.push(['_trackEvent', _4TellBoost.SiteInfo.GATrackID, toutType, productID]);
				break;
			default:
				//do nothing
				break;
		}
	};
	
	_4TellBoost.addProductID = function (id) {
		if (!id || (id.substring(0, 1) === "[")) return;
		Service.productList[Service.productCount] = id;
		Service.productCount++;
	};

	_4TellBoost.addCartItem = function (id) {
		if (!id || (id.substring(0, 1) === "[")) return;
		Service.cartList[Service.cartCount] = id;
		Service.cartCount++;
	};
	
	_4TellBoost.addBlockItem = function (id) {
		if (!id || (id.substring(0, 1) === "[")) return;
		Service.blockList[Service.blockCount] = id;
		Service.blockCount++;
	};
	
	_4TellBoost.setCustomerId = function (id) {
		if (!id || (id.substring(0, 1) === "[")) return;
		Service.customerId = id;
	};
	
	_4TellBoost.setPageType = function (pageType) {
		if (!pageType) return;
		Service.pageType = pageType;
	};
	
	_4TellBoost.setItemCount = function (itemCount) { //total results for results list pages
		if (!itemCount || (itemCount.substring(0, 1) === "[")) return;
		_4TellBoost.Site.itemCount = itemCount;
	};
  	
  	//Call-back Functions
  	// The following functions are exposed to display the recommendation touts. 
  	// The separate call-back functions define witch tout data to use.

  	_4TellBoost.displayTout1 = function (data) {
  		_4TellBoost.FirstTout.displayDiv(data);
  	};
  	_4TellBoost.displayTout2 = function (data) {  
  		_4TellBoost.SecondTout.displayDiv(data);
  	};
  	
	
}( window._4TellBoost = window._4TellBoost || {}, jQuery )); 
//self-invoked namespace that protects $ and undefined internally


