// web analytics globals with default values
var gWAEnabled = false;
var gWAAccount = "";
var gWACatId = -1;

function recalc() {
	if(!(document.all || document.getElementById)) return;
	
	var total = 0;
	var savings = 0;
	var fsEligibleSubtotal = 0;
	var dsDollarsEligibleSubtotal = 0;
	
	for(var i = 0; i < productDataSet.length; i++) {
		var product = productDataSet[i];
		var szCheckEltId = 'chkPid' + product.pid;
		var eltCheck = gE(szCheckEltId);
		var szQtyEltId = 'qty' + product.pid;
		var eltQty = gE(szQtyEltId);
		
		if (eltQty != null) cleanQty(eltQty);
			
		if((eltCheck != null) && (eltCheck.checked)) {
			var quantity = Math.abs(parseInt(eltQty.value));
			
			if(!isNaN(quantity)) {
				var price = 0;
				
				if (product.salespricelimit > 0) {
					if (quantity > product.salespricelimit) {
						// (promo pricing) + (non promo pricing)
						price = ((product.salespricelimit * product.effective) + ((quantity - product.salespricelimit) * product.overlimitprice));
						// calculate savings w/promo pricing first
						savings = (product.salespricelimit * (product.base - product.effective));
						// now calculate everything beyond the promo qty
						savings += ((quantity - product.salespricelimit) * (product.base - product.overlimitprice));
					}
				}
				
				if (price == 0) {
					price = (quantity * product.effective);
					savings += (quantity * (product.base - product.effective));
				}
				
				total += price;
				
				if(product.dsDollarsEligible) {
					dsDollarsEligibleSubtotal = dsDollarsEligibleSubtotal + price;
				}
				//savings = savings + (quantity * (product.base - price));
				if(product.fsEligible) {
					fsEligibleSubtotal = fsEligibleSubtotal + price;
				}
			}
		}
	}

	try {
		gE("txtSubTotal").innerHTML = '$' +  numberFormat(total);
		gE("txtSavings").innerHTML = '$' + numberFormat(savings);
		gE("txtDollars").innerHTML = '$' + numberFormat(0.05 * dsDollarsEligibleSubtotal);
	} catch(e) {}

}

/* Function to recalculate the total price whenever user changes group purchase qty. */
function recalcGP(p_oQty)
{
	try
	{
		if (gproductDataSet)
		{
			var l_oProduct = gproductDataSet[0];
			var l_nBase = l_oProduct.base;
			var l_nPrice = l_oProduct.effective;
			var l_nQty;
			if(isNaN(p_oQty.value))
			{
				p_oQty.value=1;
			}		
			l_nPrice = (p_oQty.value * l_nPrice);
			l_nBase = (p_oQty.value * l_nBase);	
			
			if(gE("rprice"))		
				gE("rprice").innerHTML = '$' + numberFormat(l_nPrice);
			if(gE("sprice"))
				gE("sprice").innerHTML = '$' + numberFormat(l_nBase);
			if(gE("dprice"))
				gE("dprice").innerHTML = '$' + numberFormat(l_nPrice);
		}
	}		
	catch(e){}
}

function cleanQty(eltQty)
{
	var val = eltQty.value;
	var clean='';
	if (val)
	{
		for(var i = 0; i < val.length; i++)
			if(!isNaN(val.charAt(i)))
				clean = clean + val.charAt(i);
		eltQty.value = clean;
	}
}

function addhandlers() 
{
	try
	{
		//do not need these event handlers for your list ver3
		if (document.frmYourList && gE("YLCntr") == null && gE("YLMiniCntr") == null){
			var elts = document.frmYourList.elements;		
			for(var i = 0; i < elts.length; i++){
				var elt = elts[i];
				if(elt.name.substring(0,3) == 'qty'){
					elt.onkeyup = function() {recalc();};
					elt.onchange = function() {recalc();}; 
				}
				if(elt.name == 'chkPid'){
					elt.onclick = function() {recalc();}; 
				}
			}	
			recalc();
		}
		var elt = gE('anOrder');
		if((elt != undefined) && (elt != null)) {
		elt.onclick = function() {TrackAddToBagClickForWA(elt);}; 
		}
		/* 
			Attach handler to vpack group purchase module to update the price total 
			whenever user changes group purchase qty.
		*/
		if (document.frmVPackModule)
		{
			var elts = document.frmVPackModule.elements;
			for(var i = 0; i < elts.length; i++)
			{
				var elt = elts[i];			
				if(elt.name == 'VPackQTY')
				{
					elt.onkeyup = function() {recalcGP(this);};
					elt.onchange = function() {recalcGP(this);}; 
				}		
			}
		}
	}
	catch(e)
	{
		alert(e);
	}
}

/* Tracking the add to bag button click for the Web Analytics reporting */
function TrackAddToBagClickForWA(p_oControl) {
	if(!gWAEnabled) return;
	if(!(document.all || document.getElementById)) return;
	var productsForWATrx = new Array();
	
	for(var i = 0; i < productDataSet.length; i++) {
		var product = productDataSet[i];
		var check = gE('chkPid' + product.pid);
		var qty = gE('qty' + product.pid);
		if (qty != null) cleanQty(qty);
			
		if((check != null) && (check.checked)) {
			var quantity = 1;
			if(qty)
				quantity = Math.abs(parseInt(qty.value));
			productsForWATrx[productsForWATrx.length] = new productDataForWA(product.pid, product.effective, quantity, product.site);
		}
	}
	if(productsForWATrx.length > 0)
		trackYLAddToBag(p_oControl, productsForWATrx);
}

/*
Description: tracks "AddToBag" button click for Web Analytics reporting
 p_oControl - trigger object (AddToBag button)
 products - array of productDataForWA objects.
*/
function trackYLAddToBag(p_oControl, productsForWATrx) {
	if(!gWAEnabled) return;
	if(!(document.all || document.getElementById)) return;
	if(productsForWATrx.length == 0) return;
	
	try
	{
		var l_szProducts;
		l_szProducts = "";
		
		for(var i = 0; i < productsForWATrx.length; i++)
		{
			var l_oProduct = productsForWATrx[i];
			l_szProducts = l_szProducts + ";" + l_oProduct.pid + ";" + l_oProduct.price + ";" + l_oProduct.quantity + ";;eVar5=" + l_oProduct.site + ",";
		}
		l_szProducts = l_szProducts.substring(0, l_szProducts.length - 1);
		var s = s_gi(gWAAccount);
		s.linkTrackVars = 'events,eVar3,eVar5,eVar25,products';
		s.linkTrackEvents = 'event13';
		s.events = 'event13';
		s.products = l_szProducts;
		if (gWACatId == 60 || gWACatId == 9730 || gWACatId == 59875 || gWACatId == 103804 || gWACatId == 60880)
		{
			s.eVar3 = 'Home Page'; 
			s.eVar25 = 'Add to Cart from YL on Homepage';
			s.tl(p_oControl,'o','Add to Cart from YL on Homepage');
		}
		else
		{
			s.eVar3 = 'Your List'; 
			s.eVar25 = 'Add to Cart from YL page';
			s.tl(p_oControl,'o','Add to Cart from YL page');
		}
	}
	catch(e){/* catching the error here so as to avoid throwing errors to the user from external script.*/}
}

/* Javascript object to hold group purchase price details */
function vpGproductData(base, effective)
{	
	this.base = base;
	this.effective = effective;
}


function productData(pid, base, effective, fsEligible, dsDollarsEligible, nSalesPriceLimit, nOverLimitPrice, site) {
	this.pid = pid;
	this.base = base;
	this.effective = effective; // price_effective (includes tpr price)
	this.fsEligible = fsEligible;
	this.dsDollarsEligible = dsDollarsEligible;
	this.salespricelimit = nSalesPriceLimit; // limit for tpr promotions
	this.overlimitprice = nOverLimitPrice; // price after tpr limit has been reached
	this.site = site;
	return this;
}

//custom object for Web Anaytics tracking
function productDataForWA(pid, price, quantity, site) {
	this.pid = pid;
	this.price = price
	this.quantity = quantity
	this.site = site;
	return this;
} 
	
function cartData(otcSubtotal, fsHurdle, dollarsPct, fsShortText) {
	this.otcSubtotal = otcSubtotal;
	this.fsHurdle = fsHurdle;
	this.dollarsPct = dollarsPct;
	this.fsShortText = fsShortText;
}

function doListDelete(pid, itemstatus)	{
	document.frmYourList.hdnSubmitted.value = '';
	document.frmYourList.hdnFormAction.value = 'FormActionDelete';
	document.frmYourList.product.value = pid;
	document.frmYourList.productstatus.value = itemstatus;
	document.frmYourList.submit();
}
	
function doSplit() {
	document.frmYourList.hdnSubmitted.value = '';
	document.frmYourList.hdnFormAction.value = 'FormActionOrganize';
	document.frmYourList.submit();
}

function doPrivacyCheck() {
	document.frmYourList.hdnSubmitted.value = '';
	document.frmYourList.hdnFormAction.value = 'FormActionPrivacyCheck';
	document.frmYourList.submit();
}

// Ensure that each number printed as a string 
// is in 0.00 format
function numberFormat(amount) {
	var rawNumStr = round(amount) + '';
	rawNumStr = (rawNumStr.charAt(0) == '.' ? '0' + rawNumStr : rawNumStr);
	if (rawNumStr.charAt(rawNumStr.length - 3) == '.') {
		return rawNumStr
	}
	else if (rawNumStr.charAt(rawNumStr.length - 2) == '.') {
		return rawNumStr + '0';
	}
	else { return rawNumStr + '.00'; }
}

// Round all passed numbers to two 
// decimal places (hundredths place)
function round(number,decPlace) {
	decPlace = (!decPlace ? 2 : decPlace);
	return Math.round(number * Math.pow(10,decPlace)) / Math.pow(10,decPlace);
}

function gE(id) {
	if (document.all){
		return document.all[id];
	}
	else if (document.getElementById){
		return document.getElementById(id);
	}
}

/////////////////////////////////////////////////////////////////
/////////////// Your List Enhancements - Start //////////////////
/////////////////////////////////////////////////////////////////
var LISTITEM_FLAGS = {DEAD: 2, ONSALE: 4, FSA: 8, EFS: 16, DSDOLLARS: 32, VOLUMEDISCOUNT: 64, AUTODELIVERY: 128, OUTOFSTOCK: 256, BTY: 512, PRIVATE:1024};
var LISTITEM_PROPS = {ID: "id", NAME: "name", TCATNAME: "tCatName", TCATID: "tCatId", PCATNAME: "pCatName", PCATID: "pCatId", BRANDNAME: "brandName", BPRICE: "bPrice", EPRICE: "ePrice", SAVINGS: "savings", TPRPRICE: "tprPrice", TPRQTYLMT: "tprQtyLimit", LASTPURCHASEDATE: "lastPurchaseDate", RATING: "rating", ISONSALE: "isOnSale", ISDEAD: "isDead", ISOUTOFSTOCK: "isOutOfStock", ISPRIVATE: "isPrivate", FSAELIGIBLE: "fsaEligible", EFSELIGIBLE: "efsEligible", DSDOLLARELIGIBLE: "dsDollarEligible", VOLUMEDISCOUNTELIGIBLE: "volumeDiscountEligible", AUTODELIVERABLE: "autoDeliverable", SELECTED: "selected", BTY: "isBeauty"};
var LISTITEM_FILTERS = {ALL: "all", FSA: "FSA", VOLUMEDISCOUNT: "VolumeDiscount", AUTODELIVERY: "AutoDelivery"};
var SITE_DSCM = "0";
var SITE_BTY = "1";

var gYLHandler;
var gCheckedItemsCache = new Object();
var gSortImages = new Object();
var gImageURLs = new Object();
var isIE = (navigator.appName == "Microsoft Internet Explorer");
var gListItems = new Array();

window.onunload = cleanUp;

function cleanUp()
{
	gYLHandler = null; //clear the main guy, your list handler
	gSortImages = null; // clear the sort image associative array(just an object)
	gImageURLs = null; // clear the image urls associative array(just an object)
	gCheckedItemsCache = null;//clear the checkbox cache
	gListItems = []; //clear the list item array
}

function initYL(totalItemCount, filteredItemCount, displayThreshold)
{
	//populate image array
	gSortImages[LISTITEM_PROPS.BRANDNAME] = gE('imgBrandSort');
	gSortImages[LISTITEM_PROPS.LASTPURCHASEDATE] = gE('imgPurchaseDateSort');
	gSortImages[LISTITEM_PROPS.RATING] = gE('imgRatingSort');
	gSortImages[LISTITEM_PROPS.ISONSALE] = gE('imgSaleSort');
	gSortImages[LISTITEM_PROPS.EPRICE] = gE('imgPriceSort');
	gSortImages[LISTITEM_PROPS.SELECTED] = gE('imgCheckedSort');

	gYLHandler = new ListHandler(gE("frmYourList"), "list", gE("TblListItems"), gE("ItemWrapper"), gE("EmptyPanel"), gE("divPrivacySettings"), gE("ProgressPanel"), totalItemCount, filteredItemCount, displayThreshold);
	gYLHandler.initEx();
}

function removeSelectedYLItems(obj, trx){if(obj && gYLHandler) gYLHandler.removeSelectedItems(obj, trx);}
function clearYLFilters(obj){if(obj && gYLHandler) gYLHandler.clearYLFilters(obj);}
function removeOneYLItem(obj, prodId, trx){if(obj && gYLHandler) gYLHandler.removeItem(obj, prodId, trx);}
function recalcYL3(){if(gYLHandler) gYLHandler.calcTotal();}
function selectAll(obj){if(obj && gYLHandler)	gYLHandler.selectAll(obj.checked);}
function showPrivateItems(obj, flag){if(obj && gYLHandler) gYLHandler.showPrivateItems(obj, flag);}
function addToBag(obj){if(obj && gYLHandler) gYLHandler.addToBag(obj);}
function saveYLFilter(obj){if(obj && gYLHandler) gYLHandler.saveFilters(obj);}

function sortYL(obj, sortBy)
{
	if(obj)
	{
		if (gYLHandler.filteredItemCount <= gYLHandler.list.items.length)
		{
			gYLHandler.updateCheckboxCache();
			gYLHandler.sort(sortBy);
			gYLHandler.render();
		}
		else
		{
			gYLHandler.sort(sortBy, undefined, true);
		}
	}
}

function filterYL(obj)
{
	if(obj)
	{
		if ((gYLHandler.totalItemCount <= gYLHandler.displayThreshold) || (gYLHandler.hasAllItems == true))
		{
			gYLHandler.list.reset();
			gYLHandler.filter();
			gYLHandler.render();
		}
		else
		{
			gYLHandler.filter(true);
		}
	}
}

function viewAllItems()
{
	gYLHandler.form.hdnAction.value = "viewall";
	gYLHandler.form.viewall.value = "yes";
	gYLHandler.form.submit();
}


function ListHandler(frmList, viewType, tblListItems, divItemContainer, divEmptyPanel, divPrivacySettings, divProgressPanel, totalItemCount, filteredItemCount, displayThreshold)
{
	this.form = frmList;
	this.viewType = viewType;
	this.tblListItems = tblListItems;
	this.cmbAttrFilter = this.form.cmbFilters;
	this.cmbCatFilter = this.form.cmbCatFilters;
	this.chkAll = this.form.chkAll;
	this.hdnAction = this.form.hdnAction;
	this.hdnSortBy = this.form.hdnSortBy;
	this.hdnSortOrder = this.form.hdnSortOrder;
	this.hdnShowPrivateItems = this.form.hdnShowPrivateItems;
	this.lastSortImg = (this.hdnSortBy ? gSortImages[this.hdnSortBy.value] : null);
	this.updateFilters = false;
	this.noItemsSelectedMsg = "Sorry, no items have been selected. Please choose some items to remove from list or add to bag.";
	this.noQtyMsg = "Please check the quantity of the product you have selected.";
	this.divEmptyPanel = divEmptyPanel;
	this.divItemContainer = divItemContainer;
	this.divPrivacySettings = divPrivacySettings;
	this.divProgressPanel = divProgressPanel;
	this.totalItemCount = (totalItemCount != undefined ? totalItemCount : 0);
	this.filteredItemCount = (filteredItemCount != undefined ? filteredItemCount : 0);
	this.displayThreshold = (displayThreshold != undefined ? displayThreshold : 0);
	this.hasAllItems = false;
	this.init();
}

ListHandler.prototype.attrFilter = function(){return ((this.cmbAttrFilter)? this.cmbAttrFilter.value : LISTITEM_FILTERS.ALL);};
ListHandler.prototype.catFilter = function(){return ((this.cmbCatFilter)? this.cmbCatFilter.value : LISTITEM_FILTERS.ALL);};

ListHandler.prototype.init = function()
{
	this.sortBy = ((this.hdnSortBy) ? ((this.hdnSortBy.value.length > 0) ? this.hdnSortBy.value : LISTITEM_PROPS.BRANDNAME) : LISTITEM_PROPS.BRANDNAME);
	this.sortOrder = ((this.hdnSortOrder) ? ((this.hdnSortOrder.value.length > 0) ? this.hdnSortOrder.value : "asc") : "asc");
	this.list = new ListItemCollection();
	this.list.init(gListItems);
	if(this.hdnSortBy) this.hdnSortBy.value = this.sortBy;
	if(this.hdnSortOrder) this.hdnSortOrder.value = this.sortOrder;
}

ListHandler.prototype.reset = function()
{
	this.sortBy = LISTITEM_PROPS.BRANDNAME;
	this.sortOrder = "asc"
	this.cmbAttrFilter.selectedIndex = 0;
	this.cmbCatFilter.selectedIndex = 0;
	this.viewType = "list";
	//this.lastSortImg = null;
	this.list.reset();
}
/*
x= total # of yl items
y= total # of items matching the current filter
z= item display threshold count
if(x > z) then filteratserver, clearfilter and send to server
if(y <= z) then sort at client else sort at server
*/
ListHandler.prototype.clearYLFilters = function(obj)
{
	this.cmbCatFilter.selectedIndex = 0;
	this.cmbAttrFilter.selectedIndex = 0;
	if ((gYLHandler.totalItemCount <= gYLHandler.displayThreshold) || (gYLHandler.hasAllItems == true))
	{
		this.list.reset();
		this.updateFilters = true;
		this.filter();
		this.render();
	}
	else
	{
		this.form.submit();
	}
}

ListHandler.prototype.addToBag = function(obj)
{
	try
	{
		var selectedItems = this.selectedItems();
		if (selectedItems.length > 0)
		{
			var productsForWATrx = new Array();
			for(i = 0; i < selectedItems.length; i++)
			{
				var item = selectedItems[i];
				var qty = 1;
				if(item.qty) { cleanQty(item.qty); qty = Math.abs(parseInt(item.qty.value));}
					if(qty > 0)
					{
						productsForWATrx[productsForWATrx.length] = new productDataForWA(item.id, item.ePrice, qty, item.site);
					}
					else
					{
						var html;
						html = "<div class=\"ylconfirmbody\">" + this.noQtyMsg + "</div>";
						dsAlert(html, "", "ylconfirm", obj);
						return;
					}
			}
			// web analytics tracking
			trackYLAddToBag(obj, productsForWATrx);
			this.hdnAction.value = "addtobag";
			this.form.submit();
		}
		else
		{		
			var html;
			html = "<div class=\"ylconfirmbody\">" + this.noItemsSelectedMsg + "</div>";
			dsAlert(html, "", "ylconfirm", obj);
		}
	}
	catch(e){}
}

ListHandler.prototype.saveFilters = function(obj)
{
	try
	{
		this.hdnAction.value = "save";
		this.form.submit();
	}
	catch(e){}
}

ListHandler.prototype.showPrivateItems = function(obj, flag)
{
	try
	{		
		this.hdnAction.value = "";
		this.hdnShowPrivateItems.value = (flag ? "1" : "0");
		this.form.submit();
	}
	catch(e){}
}

ListHandler.prototype.sort = function(sortBy, sortOrder, postBack)
{
	if(this.list.items.length > 0)
	{
		if (postBack != undefined && postBack == true)
		{
			if(sortOrder != undefined)
			{
				this.sortOrder = sortOrder;
			}
			else
			{
				if(sortBy == this.sortBy) this.sortOrder = ((this.sortOrder == "asc") ? "desc" : "asc");
				else if(sortBy == LISTITEM_PROPS.BRANDNAME || sortBy == LISTITEM_PROPS.ISONSALE || sortBy == LISTITEM_PROPS.SELECTED) this.sortOrder = "asc";
				else this.sortOrder = "desc";
			}
			
			this.sortBy = sortBy;
			this.hdnSortBy.value = this.sortBy;
			this.hdnSortOrder.value = this.sortOrder;
			this.hdnAction.value = "";
			this.form.submit();
		}
		else
		{
			var sortImg;
			sortImg = gSortImages[sortBy];
			if(sortOrder != undefined)
			{
				this.sortOrder = sortOrder;
			}
			else
			{
				if(sortBy == this.sortBy) this.sortOrder = ((this.sortOrder == "asc") ? "desc" : "asc");
				else if(sortBy == LISTITEM_PROPS.BRANDNAME || sortBy == LISTITEM_PROPS.ISONSALE || sortBy == LISTITEM_PROPS.SELECTED) this.sortOrder = "asc";
				else this.sortOrder = "desc";
			}
			
			this.sortBy = sortBy;
			
			this.list.sort(this.sortBy, this.sortOrder);
			
			//cosmetics: update the arrow image sort
			if(sortImg)
			{
				if(sortBy == LISTITEM_PROPS.ISONSALE || sortBy == LISTITEM_PROPS.SELECTED)
					sortImg.src = ((this.sortOrder == "asc") ? gImageURLs["sort_down"] : gImageURLs["sort_up"]);
				else
					sortImg.src = ((this.sortOrder == "desc") ? gImageURLs["sort_down"] : gImageURLs["sort_up"]);
			}
			if(this.lastSortImg) 
				if (this.lastSortImg != sortImg) this.lastSortImg.src = gImageURLs["sort_right"];
			
			if(sortImg) this.lastSortImg = sortImg;
			
			this.hdnSortBy.value = this.sortBy;
			this.hdnSortOrder.value = this.sortOrder;
		}
	}
}

ListHandler.prototype.filter = function(postBack)
{
	if (postBack != undefined && postBack == true)
	{
		this.hdnAction.value = "";
		this.form.submit();
	}
	else if(this.list.items.length > 0)
	{
		var opt;
		var catFilter, attrFilter;
		this.updateCheckboxCache();
		/*	
			Conditional update of combo options:
			we want to display the selected filter option even if it does not fetch any items and 
			we want to remove this filter option from the combo when the user chooses to clear the filtering, 
			if the list does not contain any matching items for the filter.
		*/
		if(this.updateFilters == true) this.updateFilterCombos();
			
		catFilter = this.catFilter();
		attrFilter = this.attrFilter();
		
		// filter by category
		if (catFilter == SITE_DSCM) this.list.filterByProp(LISTITEM_PROPS.BTY, false);
		else if (catFilter == SITE_BTY) this.list.filterByProp(LISTITEM_PROPS.BTY, true);
		else if (catFilter != LISTITEM_FILTERS.ALL) this.list.filterByProp(LISTITEM_PROPS.TCATID, Number(catFilter));
		
		// filter by product attribute
		if (attrFilter != LISTITEM_FILTERS.ALL) this.list.filterByProp(attrFilter, true);
		
		/* sorting is required after each filtering as the list items are re-loaded with items from global cache each time*/
		if(this.list.items.length > 0) this.sort(this.sortBy, this.sortOrder);
		
		this.calcTotal();
		this.filteredItemCount = this.list.items.length;
	}
	else
	{
		// do nothing
	}
}

ListHandler.prototype.preProcess = function()
{
	//add pre-processing steps, if any
	/*	
	turn it on so that the scrollheight property will be updated and 
	so can be used to adjust the width of "checkbox" column when overflow occurs.
	*/
	if(this.divItemContainer) this.divItemContainer.className = "show"; 
	//hide the list items table before rearranging to avoid the "compress & expand" UX
	this.tblListItems.style.visibility = "hidden";
	if(this.divProgressPanel) this.divProgressPanel.className = ((this.list.items.length > 0) ? "show" : "hide");
}

ListHandler.prototype.updateCheckboxCache = function()
{
	if(isIE) // To correct IE only bug where it forgets the status of check boxes after removing/adding the container rows to the list table.
	{
		var lineItem, chk;
		for(var i=0; i<this.list.items.length; i++)
		{
			lineItem = this.list.items[i];
			chk = gE(lineItem.checkId);
			if(chk) gCheckedItemsCache[lineItem.checkId] = chk.checked;
		}
	}
}

ListHandler.prototype.render = function()
{
	if(this.tblListItems)
	{
		var lineItem, tBody = this.tblListItems.tBodies[0];
		
		this.preProcess();
		
		if(tBody)
		{
			if (this.viewType == "cat")
			{
				var cats = this.list.getPCats();
				var newList;
				for(i = 0; i < cats.length; i++)
				{
					newList = new ListItemCollection();
					newList.loadItems(this.list.fetchItemsByProp(LISTITEM_PROPS.PCATID, cats[i].id));
					ListHandler.addItemRows.apply(this);
					newList.removeAll();
				}
			}
			else
			{
				ListHandler.addItemRows.apply(this);
			}
		}
		this.postProcess();
	}
}

ListHandler.prototype.initEx = function()
{
	this.preProcess();
	//this does not add rows...instead just adjust the row width based on the availability of vertical scroll bar
	ListHandler.addItemRows.call(this, true); 
	this.postProcess();
	this.hasAllItems = (this.list.items.length == this.totalItemCount);
}

ListHandler.prototype.postProcess = function()
{
	//adjust sort and filter dropdowns based on the current user selected sort and filter options
	this.tblListItems.style.visibility = "visible";
	if(this.divProgressPanel) this.divProgressPanel.className = "hide";
	if(this.divEmptyPanel) this.divEmptyPanel.className = ((this.list.items.length == 0) ? "show" : "hide");
	this.divItemContainer.className = ((this.list.items.length == 0) ? "hide" : "show");
	
	if(this.chkAll)
	{
		if(this.list.items.length > 0)
			this.chkAll.checked = !this.list.hasItems(LISTITEM_PROPS.SELECTED, false);
		else
			this.chkAll.checked = false;
	}
}

ListHandler.addItemRows = function(doNotAddRows)
{
	var lineItem, tBody = this.tblListItems.tBodies[0];
	var justAdjustRowWidth = false;
	if (doNotAddRows != undefined) justAdjustRowWidth = doNotAddRows;
	if (!justAdjustRowWidth)
	{
		for (i = tBody.childNodes.length - 1; i >= 0; i--)
			tBody.removeChild(tBody.childNodes[i]); //start clean
	}
	var noScrollItems = [];
	var listScrolling = false;
	for(i=0; i<this.list.items.length; i++)
	{
		lineItem = this.list.items[i];
		
		if(lineItem.row)
		{		
			if (!justAdjustRowWidth)
			{
				tBody.appendChild(lineItem.row);
				lineItem.row.className = "lineitem";
			}
			if(isIE)// To correct IE only bug where it forgets the status of check boxes after removing/adding the container rows to the list table.
				if(lineItem.check) lineItem.check.checked = gCheckedItemsCache[lineItem.checkId];
			
			if(this.divItemContainer)
			{
				if(!listScrolling)
				{
					listScrolling = (this.divItemContainer.scrollHeight > this.divItemContainer.clientHeight);
					noScrollItems[noScrollItems.length] = lineItem;
				}
				var clsName = (listScrolling ? "checkScroll" : "check");
				if(listScrolling && noScrollItems.length > 0)
				{
					for(j=0; j<noScrollItems.length;j++)
					{
						var tmpItem = noScrollItems[j];
						if(!tmpItem.isDead && tmpItem.row) tmpItem.row.lastChild.className = clsName;
					}
					noScrollItems.clear();
				}
				else
				{
					if(!lineItem.isDead && lineItem.row) lineItem.row.lastChild.className = clsName;
				}
			}
		}
	}
}

ListHandler.prototype.updateFilterCombos = function()
{
	var opt;
	// remove attr filters that are not applicable
	for (i = this.cmbAttrFilter.options.length-1; i >=0; i--)
	{
		opt = this.cmbAttrFilter.options[i];
		if(opt.value != LISTITEM_FILTERS.ALL)
			if(!this.list.hasItems(opt.value, true))
				this.cmbAttrFilter.removeChild(opt);
	}
	
	var hasBtyItems = this.list.hasItems(LISTITEM_PROPS.BTY, true);
	var hasNonBtyItems = this.list.hasItems(LISTITEM_PROPS.BTY, false);
	// remove cat filters that are not applicable
	for (i = this.cmbCatFilter.options.length-1; i >=0 ; i--)
	{
		opt = this.cmbCatFilter.options[i];
		if(opt.value != LISTITEM_FILTERS.ALL)
		{
			if (opt.value == SITE_DSCM)
			{
				if(!(hasNonBtyItems && hasBtyItems))
					this.cmbCatFilter.removeChild(opt);
			}
			else if(opt.value == SITE_BTY)
			{
				if(!(hasBtyItems && hasNonBtyItems))
					this.cmbCatFilter.removeChild(opt);
			}
			else if(!this.list.hasItems(LISTITEM_PROPS.TCATID, Number(opt.value)))
				this.cmbCatFilter.removeChild(opt);
		}
	}

	opt = null;
	this.updateFilters = false; // switch it back after updating the filters
}

ListHandler.prototype.removeItem = function(obj, itemId, trx)
{
	var trackingCode = ((trx) ? trx : "");
	//passing "null" here to position the delete confirm box based on css positions for "remove from list" action
	ListHandler.deleteConfirm(obj, new Array(itemId), trackingCode);
}

ListHandler.deleteConfirm = function(obj, itemIds, trx)
{
	var html, deleteDeadItem = (itemIds.length == 1 && obj.id == "remove_" + itemIds[0]), overlayId;
	if(deleteDeadItem)
		overlayId = "yldelconfirmver2";
	else
		overlayId = "yldelconfirm";

	html = "Are you sure you want to remove " + itemIds.length + " item(s)?<br/><br/>"
	html = html + "<span class=\"cancel\">";
		html = html + "<a href=\"javascript:showOverlay(this, '" + overlayId + "', false);\" >"
			html = html + "<img title=\"cancel\" src=\"" + gImageURLs["cancelbtn"] + "\" border=\"0\" hspace=\"0\" vspace=\"0\" alt=\"cancel\"/>"
		html = html + "</a>";
	html = html + "</span>";
	html = html + "<span class=\"delete\">";
		html = html + "<a href=\"#\" onclick=\"javascript:gYLHandler.removeItems([" + itemIds.join(",") + "], '" + trx + "');showOverlay(this, '" + overlayId + "', false);\">"
			html = html + "<img title=\"remove\" src=\"" + gImageURLs["deletebtn"] + "\" border=\"0\" hspace=\"0\" vspace=\"0\" alt=\"remove\"/>"
		html = html + "</a>";
	html = html + "</span>";
	html = "<div class=\"deleteconfirmbody\">" + html + "</div>";
	
	setOverlayEvtHandler("onshow", overlayId, function(){gYLHandler.abilifyActionControls(false);});
	setOverlayEvtHandler("onhide", overlayId, function(){gYLHandler.abilifyActionControls(true);});
	
	if(deleteDeadItem)
		dsAlert(html, "", overlayId, null, false);
	else
		dsAlert(html, "", overlayId, obj, false);
}

ListHandler.prototype.removeSelectedItems = function(obj, trx)
{
	var itemsToRemove = new Array();
	var selectedItems = this.selectedItems();
	var trackingCode = ((trx) ? trx : "");
	
	if(selectedItems.length > 0)
	{
		for(i = 0; i < selectedItems.length; i++)
			itemsToRemove[itemsToRemove.length] = selectedItems[i].id;
		
		ListHandler.deleteConfirm(obj, itemsToRemove, trackingCode);
	}
	else
	{
		var html;
		html = "<div class=\"ylconfirmbody\">" + this.noItemsSelectedMsg + "</div>";
		dsAlert(html, "", "ylconfirm", obj);
	}
}

ListHandler.prototype.removeItems = function(itemIds, trx)
{
	var removedItems, msg, html;
	
	removedItems = removeFromYL(itemIds.join(","), trx); // calling the function that makes ajax request
	if(removedItems.length > 0)
	{
		// update the global items cache
		for(i = 0; i < removedItems.length; i++)
		{
			for(j = 0; j < gListItems.length; j++)
			{
				if(removedItems[i] == gListItems[j].id.toString())
				{
					gListItems.splice(j, 1);
					break;
				}
			}
		}
		if(gListItems.length > 0)
		{
			// re-render the list items table
			this.list.reset();
			this.filter();
			this.render();
			this.updateFilters = true; //update the filters after the removing items from the list
			this.totalItemCount -= removedItems.length;
			if(this.divPrivacySettings)
				if(!this.list.hasItems(LISTITEM_PROPS.ISPRIVATE, true))
					this.divPrivacySettings.className = "hide";
		}
		else
		{
			this.hdnAction.value = "";
			this.form.submit();
		}
	}
	else
	{
		msg = "We are experiencing issues while trying to remove selected item(s) from <b>your list&#8482;</b>. Please try again later.";
		html = "<div class=\"ylconfirmbody\">" + msg + "</div>";
		dsAlert(html, "", "ylconfirm");
	}
	return removedItems;
}

ListHandler.prototype.selectedItems = function()
{
	return this.list.fetchItemsByProp(LISTITEM_PROPS.SELECTED, true);
}

ListHandler.prototype.selectAll = function(flag)
{
	for(var i = 0; i < this.list.items.length; i++) 
	{
		var item = this.list.items[i];
		if(item.check)
			item.check.checked = flag;
	}
	this.calcTotal();
}

ListHandler.prototype.calcTotal = function()
{
	if(!(document.all || document.getElementById)) return;
	
	var total = 0;
	var savings = 0;
	var fsEligibleSubtotal = 0;
	var dsDollarsEligibleSubtotal = 0;
	
	for(var i = 0; i < this.list.items.length; i++) {
		var item = this.list.items[i];
		var qty = item.qty;
		var check = item.check;
		
		if (item.qty != null) cleanQty(qty);
			
		if((check != null) && (check.checked)) {
			var quantity = Math.abs(parseInt(qty.value));
			
			if(!isNaN(quantity)) {
				var price = 0;
				
				if (item.tprQtyLimit > 0) {
					if (quantity > item.tprQtyLimit) {
						// (promo pricing) + (non promo pricing)
						price = ((item.tprQtyLimit * item.tprPrice) + ((quantity - item.tprQtyLimit) * item.ePrice));
						// calculate savings w/promo pricing first
						savings = (item.tprQtyLimit * (item.bPrice - product.ePrice));
						// now calculate everything beyond the promo qty
						savings += ((quantity - item.tprQtyLimit) * (item.base - item.ePrice));
					}
				}
				
				if (price == 0) {
					price = (quantity * item.ePrice);
					savings += (quantity * (item.bPrice - item.ePrice));
				}
				
				total += price;
				
				if(item.dsDollarEligible) {
					dsDollarsEligibleSubtotal = dsDollarsEligibleSubtotal + price;
				}
				//savings = savings + (quantity * (product.base - price));
				if(item.efsEligible) {
					fsEligibleSubtotal = fsEligibleSubtotal + price;
				}
			}
		}
	}

	try {
		var obj;
		obj = gE("txtSubTotal");
		if(obj) obj.innerHTML = numberFormat(total);
		
		obj = gE("txtSavings");
		if(obj) obj.innerHTML = numberFormat(savings);
		
		obj = gE("txtDollars");
		if(obj) obj.innerHTML = numberFormat(0.05 * dsDollarsEligibleSubtotal);
		
		obj = gE("txtSubTotal2");
		if(obj) obj.innerHTML = '$' +  numberFormat(total);
		
		obj = gE("txtSavings2");
		if(obj) obj.innerHTML = '$' + numberFormat(savings);
		
		obj = gE("txtDollars2");
		if(obj) obj.innerHTML = '$' + numberFormat(0.05 * dsDollarsEligibleSubtotal);
	} catch(e) {}
}

ListHandler.prototype.abilifyActionControls = function(flag)
{
	var listItem;
	for(i=0; i<this.list.items.length; i++)
	{
		listItem = this.list.items[i];
		if(listItem.check) listItem.check.disabled = !flag;
	}
	if(this.chkAll) this.chkAll.disabled = !flag;
	this.cmbAttrFilter.disabled = !flag;
	this.cmbCatFilter.disabled = !flag;
	gE("btnYLOrder").disabled = !flag; gE("btnYLOrder2").disabled = !flag;
}

function ListItemCollection()
{
	/// member declaration
	this.items = [];
	this.sortBy = LISTITEM_PROPS.BRANDNAME;
	this.sortOrder = "asc";
}

ListItemCollection.prototype.init = function(lineItems)
{
	this.items = ((lineItems != undefined) ? lineItems.slice() : gListItems.slice());
	this.sortBy = LISTITEM_PROPS.BRANDNAME;
	this.sortOrder = "asc";
}

/* a override to load items array with custom item array */
ListItemCollection.prototype.loadItems = function(items)
{
	var temp = this.items;
	this.items = items;
	temp.clear();
}

ListItemCollection.prototype.add = function(lineItem)
{
	this.items[this.items.length] = lineItem;
}

ListItemCollection.prototype.itemIndex = function(id)
{
	for (var i=0;i<this.items.length;i++) 
		if(this.items[i].id == id) 
			return i;
}

ListItemCollection.prototype.getItemByID = function(id)
{
	return this.items[this.itemIndex(id)];
}

ListItemCollection.prototype.removeById = function(id)
{
	this.items.splice(this.itemIndex(id),1);
}

ListItemCollection.prototype.removeAll = function()
{
	this.items.clear();
}

ListItemCollection.prototype.reset = function()
{
	var temp = this.items;
	temp.clear(); // clear it
	this.init();
}

ListItemCollection.prototype.sort = function(sortBy, sortOrder)
{
	// update the object members
	this.sortBy = sortBy;
	if (sortOrder != undefined)
		this.sortOrder = sortOrder;
	
	// special handling for sorting selected items
	if(this.sortBy == LISTITEM_PROPS.SELECTED) 
		this.updateSelectedProp();
	
	if(this.items.length > 0)
	{
		var tmpItems, deadItems;
		var dataType = typeof(this.items[0][sortBy]);
		// sort the filtered items based on brand so that the sorted items are arranged by brand
		this.items = ListItemCollection.sort(this.items, LISTITEM_PROPS.BRANDNAME, "asc");
		
		// filter the dead items
		deadItems = this.fetchItemsByProp(LISTITEM_PROPS.ISDEAD, true);
		if(deadItems.length > 0)
			this.filterByProp(LISTITEM_PROPS.ISDEAD, false);
		
		// special case handling for boolean values
		if(dataType == "boolean")
		{			
			// get the NOT matching ones for the current sort order
			tmpItems = this.fetchItemsByProp(this.sortBy, (sortOrder != "asc"));

			// get the matching ones for the current sort order
			this.filterByProp(this.sortBy, (sortOrder == "asc"));
			
			// append the non-matching ones to the end of matching ones.
			for(i = 0; i < tmpItems.length; i++)
			{
				this.add(tmpItems[i]); //append an item to the end of current list.
			}
			tmpItems.clear();
		}
		else if(dataType == "number")
		{
			// get all them items that do not have the value for the property
			tmpItems = this.fetchItemsByProp(this.sortBy, 0);
			
			// get all them items that do have the value for the property
			this.filterByProp(this.sortBy, 0, "!=");
			// sort the filtered items based property value and sort order
			this.items = ListItemCollection.sort(this.items, this.sortBy, this.sortOrder);
			// append the non-matching ones to the end of matching ones.
			for(i = 0; i < tmpItems.length; i++)
			{
				this.add(tmpItems[i]); //append an item to the end of current list.
			}
			tmpItems.clear();
		}
		else
		{
			this.items = ListItemCollection.sort(this.items, this.sortBy, this.sortOrder);
		}
		// append dead items to end of the list
		if(deadItems.length > 0)
		{
			for(i = 0; i < deadItems.length; i++)
			{
				this.add(deadItems[i]); //append an item to the end of current list.
			}
			deadItems.clear();
		}
	}
}

/* the default Array.Sort([function]) provided by browsers are not consistent 
(i.e. the index order of same valued items are not same after the sorting.)
so, writing my own bubble sorting here.
*/
ListItemCollection.sort = function(items, sortBy, sortOrder)
{
	return ListItemCollection.mergesort(items, sortBy, sortOrder);
}

ListItemCollection.mergesort = function(array, sortBy, sortOrder)
{
	if(array.length < 2)
		return array;
	var middle = Math.ceil(array.length/2);
	return ListItemCollection.merge(ListItemCollection.mergesort(array.slice(0,middle), sortBy, sortOrder),
			ListItemCollection.mergesort(array.slice(middle), sortBy, sortOrder), sortBy, sortOrder);
}

ListItemCollection.merge = function(left, right, sortBy, sortOrder)
{
	var result = new Array();
	while((left.length > 0) && (right.length > 0))
	{
		if(ListItemCollection.comparison(left[0][sortBy], right[0][sortBy], sortOrder) < 0)
			result.push(left.shift());
		else
			result.push(right.shift());
	}
	while(left.length > 0)
		result.push(left.shift());
	while(right.length > 0)
		result.push(right.shift());
	return result;
}

ListItemCollection.comparison = function(left, right, sortOrder)
{
	if (typeof(left) == "string")
	{
		left = left.toLowerCase(); right = right.toLowerCase();
	}
	if(left == right) return 0;
	if(sortOrder == "desc")
	{
		if (left > right) return -1;
		else return 1;
	}
	else
	{
		if (left < right) return -1;
		else return 1;
	}
	
}


ListItemCollection.prototype.fetchItemsByProp = function(propName, propValue, compareOperator)
{
	var opr = "==";
	if(propName == LISTITEM_PROPS.SELECTED)// spl treatment for selected item property
		this.updateSelectedProp();
	if (compareOperator != undefined) opr = compareOperator;
	return this.items.filter(function(listItem){return ListItemCollection.exprPasses(listItem, propName, propValue, opr);});
}

ListItemCollection.exprPasses = function(listItem, propName, propValue, opr)
{
	var retVal;
	switch(opr)
	{
		case "==":
			retVal = (listItem[propName] == propValue);
			break;
		case "!=":
			retVal = (listItem[propName] != propValue);
			break;
		case ">":
			retVal = (listItem[propName] > propValue);
			break;
		case "<":
			retVal = (listItem[propName] < propValue);
			break;
		case ">=":
			retVal = (listItem[propName] >= propValue);
			break;
		case "<=":
			retVal = (listItem[propName] <= propValue);
			break;
		default:
			retVal = (listItem[propName] == propValue);
			break;
	}
	return retVal;
}

ListItemCollection.prototype.filterByProp = function(propName, propValue, compareOperator)
{
	var temp = this.items, opr = "==";
	if (compareOperator != undefined) opr = compareOperator;
	this.items = this.fetchItemsByProp(propName, propValue, opr);
	temp.clear();
}

ListItemCollection.prototype.hasItems = function(propName, propValue)
{
	if(propName == LISTITEM_PROPS.SELECTED)// spl treatment for selected item property
		this.updateSelectedProp();
	return this.items.some(function(listItem){return ListItemCollection.exprPasses(listItem, propName, propValue);});
}

ListItemCollection.prototype.getPCats = function()
{
	var cats = [], item;
	for(i=0;i<this.items.length;i++)
	{
		item = this.items[i];
		if(cats[item.pCatId] == undefined)
			cats[cats.length] = {id: item.pCatId, name: item.pCatName};
	}
	return cats;
}

ListItemCollection.prototype.updateSelectedProp = function()
{
	for(i = 0; i < this.items.length; i++)
	{
		if(this.items[i].check)
			this.items[i].selected = this.items[i].check.checked;
	}
}

function ListItem(id, tcId, bName, bPrice, ePrice, tprPrice, tprQtyLimit, lastPurchaseDate, rating, site, flags)
{
	this.id = id;
	this.tCatId = tcId;
	this.brandName = bName;
	this.bPrice = bPrice;
	this.ePrice = ePrice;
	this.tprPrice = tprPrice;
	this.tprQtyLimit = tprQtyLimit;
	this.lastPurchaseDate = 0;
	if(lastPurchaseDate.length > 0)
	{
		var dt = new Date(lastPurchaseDate);
		this.lastPurchaseDate = dt.getTime();
	}
	this.rating = rating;
	this.site = site;
	this.flags = flags;
	this.isOnSale = ((flags & LISTITEM_FLAGS.ONSALE) == LISTITEM_FLAGS.ONSALE); //bitwise AND operation
	this.isDead = ((flags & LISTITEM_FLAGS.DEAD) == LISTITEM_FLAGS.DEAD);
	this.isOutOfStock = ((flags & LISTITEM_FLAGS.OUTOFSTOCK) == LISTITEM_FLAGS.OUTOFSTOCK);
	this.fsaEligible = ((flags & LISTITEM_FLAGS.FSA) == LISTITEM_FLAGS.FSA);
	this.efsEligible = ((flags & LISTITEM_FLAGS.EFS) == LISTITEM_FLAGS.EFS);
	this.dsDollarEligible = ((flags & LISTITEM_FLAGS.DSDOLLARS) == LISTITEM_FLAGS.DSDOLLARS);
	this.autoDeliverable = ((flags & LISTITEM_FLAGS.AUTODELIVERY) == LISTITEM_FLAGS.AUTODELIVERY);
	this.volumeDiscountEligible = ((flags & LISTITEM_FLAGS.VOLUMEDISCOUNT) == LISTITEM_FLAGS.VOLUMEDISCOUNT);
	this.isBeauty = ((flags & LISTITEM_FLAGS.BTY) == LISTITEM_FLAGS.BTY);
	this.isPrivate = ((flags & LISTITEM_FLAGS.PRIVATE) == LISTITEM_FLAGS.PRIVATE);
	this.checkId = "chkPidYL3_" + id;
	this.qtyId = "qtyYL3_" + id;
	this.row = gE("trYL_" + id);
	this.check = gE(this.checkId);
	this.qty = gE(this.qtyId);
	if(this.check)
	{
		gCheckedItemsCache[this.checkId] = this.check.checked;
		this.check.onclick = function(){recalcYL3();if(gYLHandler.chkAll && gYLHandler.chkAll.checked) gYLHandler.chkAll.checked = this.checked;};
	}
	if(this.qty)
	{
		this.qty.onchange = recalcYL3;
		this.qty.onkeyup = recalcYL3;
	}
	this.selected = ((this.check) ? (this.check.checked) : false);
}

/////////////////////////////////////////////////////////////////
/////////////// Your List Enhancements - End ////////////////////
/////////////////////////////////////////////////////////////////
