// Version 2.0

//some of these global variables are set from the calling page (i.e. defaultContentsFormat = "VERTICAL")
var defaultSort, defaultContentsFormat, contentsFormat, tableWidth, numColumns, numPerPage, numPages, contentsElements, showDefaultSort,
    detailedSortInfo, showPagingModes, viewAll, sortBy, sortHighLow, pageLinkPrefix, rowpad, columnpad, storename, columnSeparatorColor,
    rowSeparatorColor, listModeBG1, listModeBG2, sortLinkSeparator, modeLinkSeparator, pageLinkSeparator, globalPageNum, globalViewallthistime,
    currentItem, currentItemImage, numArrowDivs, showListMode, addToCartImage, showBrandSort, strikePrice, showWrapMode, showQuantity, listModeShowImages,
    pageSegment;
var pageItems = new Array(); //array to hold master array - retains original contents even during filtering
var oldSortBy = "";

var _maxNumAttributes = 5;

var SORT_ASC = 1,
		SORT_DESC = -1; //constants used for sorting 

var _sortDirection = SORT_ASC;

var showsortmanufacturer = false; 
var showsortshipfromstate = false; 
var showsorttheme = false; 
var showsortprice = false; 
var sortmanufacturer = ""; 
var sortshipfromstate = ""; 
var sorttheme = ""; 
var sortprice = ""; 
var addToCartImage = '<input class=order-button valign=absmiddle type=submit value="Add to cart">'; 
var leftArrow = '<img src="http://site.invitationbox.com/images/previous-brown.gif" width="55" height="13" border="0" hspace="2" vspace="0" alt="previous page" />'; 
var rightArrow = '<img src="http://site.invitationbox.com/images/next-brown.gif" width="34" height="13" border="0" hspace="2" vspace="0" alt="next page" />'; 
var leftArrowG = '<img src="http://site.invitationbox.com/images/previous-grey.gif" width="0" height="0" border="0" hspace="2" vspace="0" />'; 
var rightArrowG = '<img src="http://site.invitationbox.com/images/next-grey.gif" width="0" height="0" border="0" hspace="2" vspace="0" />'; 
var downArrow = '<img src="http://site.invitationbox.com/images/downarrow.gif" height="11" width="11" border="0">'; 
var upArrow = '<img src="http://site.invitationbox.com/images/uparrow.gif" height="11" width="11" border="0">'; 
var storename = "invitationbox"; 
regularPriceText = "Regular price:"; 
salePriceText = "Sale price:"; 
numPerPage = 24; 
numColumns = 4; 
defaultContentsFormat = "VERTICAL"; 
viewAll = true; 
defaultSort = "default"; 
listModeShowImages = true; 
showDefaultSort = false; 
showListMode = false; 
detailedSortInfo = false; 
showPagingTheme = true; 
showPagingStyle = false; 
columnSeparatorColor = "#FFFFFF"; 
columnpad = "14"; 
listModeBG1 = "#FFFFFF"; 
listModeBG2 = "#FFFFFF"; 
pageLinkPrefix = "<font class='pagingBlueText'>Page</font>&nbsp;&nbsp;"; 
pageLinkSeparator = "&nbsp;&nbsp;|&nbsp;&nbsp;"; 
rowSeparatorColor = "#FFFFFF"; 
rowpad = "15"; 
showPagingModes = false;
sortLinkSeparator = "&nbsp;"; 
modeLinkSeparator = "&nbsp;"; 
tableWidth = "100%"; 
numArrowDivs = 4;
showBrandSort = false;
strikePrice = false;
showWrapMode = false;

contentsElements = "image/name/price/papercolor/icons/quickview";
loadjscssfile("http://site.invitationbox.com/js/swfobject.js", "js") //dynamically load and add this .js file

$(document).ready( function() {
	initPaging();
});

/* Mapping for defining more complex filters (such as whether items are on sale which filter on more than one attribute) */
var _filterCallbacks = {
	'onsale' : function(it, attr, value) { return isSaleItem(it); },
	'eventtype' : function(it, attr, value) { return filterEvent(it, value); }
}

function isSaleItem(it) { return it['showsalepricing']; }

function filterEvent(it, value) {
	// it == paging item
	// attr == attr type
	// value == value to match on
	_pagingState.filters['eventtype-'+value] = value;
	return (it['eventtype'].indexOf(value) != -1);	
}

function pagingItem(id, code, name, img, listimg, price, saleprice, options, abstr, orderable, brand, brandlink, theme, pricerange, mappricing, newitem, papercolor, fullname, attributes) {
	//use window items as a global array to track paging items
	if (!window.items) window.items = new Array();
		
	this.id         = id.toLowerCase();
	this.code       = code;
	this.name       = name;
	this.img        = img;
	this.listimg    = listimg;
	this.price      = price;
	this.saleprice  = saleprice;
	this.options    = options;
	this.abstr      = abstr;
	this.orderable  = orderable;
	this.brand      = brand;
	this.brandlink  = brandlink;
	this.theme      = theme;
	this.pricerange = pricerange;
	this.mappricing = mappricing;
	this.newitem    = newitem;
	this.papercolor = papercolor;
	this.fullname   = fullname;
	this.sortby     = "name";
	
	/* Added as a way to dynamically add attributes regardless of order, without having to change the constructor */
	for (attr in attributes)
		this[attr] = attributes[attr];

	//dynamically determine initial sort
	this.defaultsort=window.items.length;
	//add this pagingItem object to the global items array
	window.items[window.items.length] = this;
}

//paging state - made global variable to facilitate integration with older SolidCactus code
var _pagingState;

//get default paging state - added to support more advanced filtering and sorting capabilities 
function getDefaultPagingState() {	
	var ps = {
		pageName : '',
		pageNum : 1,		
		sortBy : 'defaultsort',
		sortDirection : SORT_ASC,
		contentsFormat : defaultContentsFormat, //this is a global var - set to VERTICAL via calling page
		viewAll : false,		
		filters : new Array() //assoc array to track filters being used where [filter=value]
	};
	return ps;
}

//load paging state from user's cookies as applicable
function loadPagingState() {	
	var ps = getDefaultPagingState();
	
	//get current page
	ps.pageName = getCurrentPageHTML();
	
	//get page name from cookie to determine where settings were applied
	var readName = GetCookie('thePageName');	
		
	//if the cookie has values defined load those values - else just use the default	
	if (readName) {		
		//global settings
		ps.viewAll = (GetCookie('viewall') == 1);		
		
		var readContentsFormat = GetCookie('contentsformat');		
		if (readContentsFormat)
			ps.contentsFormat = GetCookie('contentsformat');
	
		var readSortBy = GetCookie('theSort');
		if (readSortBy)
			ps.sortBy = readSortBy;
		
		var readSortDir = GetCookie('sortDirection')
			ps.sortDirection = readSortDir; 
		
		//load page specific state settings only if same page as last time settings were saved 
		if (readName == ps.pageName) {
			//get remaining cookie values
			var readPage = parseInt(GetCookie('thePage'));					
			ps.pageNum = (readPage == 0 || ps.viewAll) ? 1 : readPage;
			
			var readFilters = GetCookie('filters');
			if (readFilters)
				ps.filters = deserializeFilterData(readFilters);
		}
	}	
	var filterType = getParameterByName("ft");
	var filterVal = unescape(getParameterByName("fv"));
		
	if (filterType != '') {
		if (filterVal != '') {
			try {
				if (filterVal == 'true') {
					$("#cb"+filterType).attr('checked',true);
					ps.filters[filterType] = true;
				} else {
					ps.filters[filterType] = filterVal;
					$("#cb"+filterType+filterVal).attr('checked',true);
				}
			} catch (e) { alert(e); }
		}
	}	
	
	return ps;
}

function savePagingState(ps) {	
	SetCookie('thePageName', ps.pageName, exp); 		
	SetCookie('thePage', ps.pageNum, exp); 
	SetCookie('theSort', ps.sortBy, exp); 
	SetCookie('sortDirection', ps.sortDirection, exp); 
	SetCookie('contentsformat', ps.contentsFormat, exp); 
	SetCookie('viewall', (ps.viewAll ? 1 : 0), exp); 
	SetCookie('filters', serializeFilterData(ps.filters), exp);
}

/* return assoc array from serialized filter data */
function deserializeFilterData(data) {
	var ret = new Array();
	var filters = data.split("|");
	if (filters.length) {
		for (var i = 0; i < filters.length; i++) {
			var filter = filters[i].split("::");
			if (filter.length == 2) {
				var val = filter[1];
				//hack for boolean convert as applicable
				if (val == "true") 				
					val = true;
				else if (val == "false")
					val = false;						
					
				ret[filter[0]] = val;
			}
		}
	}
	return ret;
}

/* serialize filter data from assoc array to string for storage in cookie */
function serializeFilterData(data) {
	var str = '';
	var i = 0;
	for (filter in data) {
		//if (data[filter]) //filter is set
		//{
			if (i++)
				str += "|";		
			str += filter + "::" + data[filter];
		//}
	}
	return str;
}

function round_decimals(original_number, decimals) {
    var result1 = original_number * Math.pow(10, decimals)
    var result2 = Math.round(result1)
    var result3 = result2 / Math.pow(10, decimals)
    return pad_with_zeros(result3, decimals)
}

function pad_with_zeros(rounded_value, decimal_places) {
    var value_string = rounded_value.toString()
    var decimal_location = value_string.indexOf(".")
    if (decimal_location == -1) {
        decimal_part_length = 0
        value_string += decimal_places > 0 ? "." : ""
    }
    else {
        decimal_part_length = value_string.length - decimal_location - 1
    }
    var pad_total = decimal_places - decimal_part_length
    if (pad_total > 0) {
        for (var counter = 1; counter <= pad_total; counter++) 
            value_string += "0"
        }
    return value_string
}

/****************************************************************
		Generic utility function to retrieve DOM objects by ID
****************************************************************/
function FIND(item) {
	if (document.getElementById) return(document.getElementById(item));
	if (document.all) return(document.all[item]);
	return(false);
};

/****************************************************************
		Get a corresponding cross section of pagingItem objects 
		for a given page number.
		
		@param theArray - array of pagingItem objects
		@param pageNum - the current page
		
		@return array of pagingItem objects as a subset
		
		References numPerPage global variable
****************************************************************/
function pagingSegment(theArray,pageNum) {
	var newArray = new Array();
	for(i=(pageNum-1)*numPerPage; i<pageNum*numPerPage; i++) {
		newArray[i - (pageNum-1)*numPerPage] = theArray[i];
	}
	return newArray;
};

function sortArray(theArray, loBound, hiBound){
	var pivot, loSwap, hiSwap, temp;

	// Two items to sort
	if (hiBound - loBound == 1)
	{
		if (theArray[loBound].sortby > theArray[hiBound].sortby)
		{
			temp = theArray[loBound];
			theArray[loBound] = theArray[hiBound];
			theArray[hiBound] = temp;
		}
		return;
	}

	// Three or more items to sort
	pivot = theArray[parseInt((loBound + hiBound) / 2)];
	theArray[parseInt((loBound + hiBound) / 2)] = theArray[loBound];
	theArray[loBound] = pivot;
	loSwap = loBound + 1;
	hiSwap = hiBound;

	do {
		while (loSwap <= hiSwap && theArray[loSwap].sortby <= pivot.sortby)
			loSwap++;
		while (theArray[hiSwap].sortby > pivot.sortby)
			hiSwap--;
		if (loSwap < hiSwap)
		{
			temp = theArray[loSwap];
			theArray[loSwap] = theArray[hiSwap];
			theArray[hiSwap] = temp;
		}
	} while (loSwap < hiSwap);

	theArray[loBound] = theArray[hiSwap];
	theArray[hiSwap] = pivot;

	// 2 or more items in first section
	if (loBound < hiSwap - 1)
		sortArray(theArray, loBound, hiSwap - 1);

	// 2 or more items in second section
	if (hiSwap + 1 < hiBound)
		sortArray(theArray, hiSwap + 1, hiBound);
};

function changeClass(which,theclass) {
	which.className = theclass;	
}

function writePageLinks( viewallThisTime, pageNum) {
	//$("#pagelinks1").html(getPageLinks(viewallThisTime, pageNum));
	$("#pagelinks2").html(getPageLinks(viewallThisTime, pageNum, true));
}

function getPageLinks( viewallThisTime, pageNum, addTopLink) {
	var numLinks = 7;
	var plusMinus = 3;
	
	if (numPages > 1) {
		var pageLinks = "<span id=pagelinks>" + pageLinkPrefix;

		var a, b;
		
		if (numPages > numLinks) {
			a = pageNum - plusMinus;
			b = pageNum + plusMinus;
			if (a < 1) {a = 1;}
			if (b < numLinks) b = numLinks;
			if (b > numPages) {b = numPages;}
			if (a > (numPages - numLinks)) a = numPages - numLinks;
		} else {
			a = 1;
			b = numPages;
		}

		for(i=a; i<=b; i++) {
			if(i == pageNum && !viewallThisTime)
				pageLinks += "<span class=chosen>" + i + "</span>";
			else {
				pageLinks += '<a href="';
				
				if (addTopLink)
					pageLinks += '#top" onclick="';
				else
					pageLinks += 'javascript:';
					
				pageLinks += 'writePage(' + i + ',false);">' + i + '</a>';
			}
      
			if (i < b)
       	pageLinks += "<span class=sep>" + pageLinkSeparator + "</span>";	
		}
		
		if(viewAll) {
			pageLinks += "<span class=sep>" + pageLinkSeparator + "</span>";
			if(viewallThisTime)
				pageLinks += "<span class=chosen>View All</span>";
			else {
				pageLinks += '<a href="';
				if (addTopLink)
					pageLinks += '#top" onclick="';
				else
					pageLinks += 'javascript:';
				pageLinks += 'writePage(1,true)" class="viewall">View All</a>';
			}
		}
		pageLinks += "</span>";
	
		return pageLinks;
	}
	return '';
};


function writeItemXofX(viewallthistime,pageNum) {
	//var theItemDiv = FIND("itemof1");
	//if(theItemDiv) theItemDiv.innerHTML = theString;
	theItemDiv = FIND("itemof2");
	if(theItemDiv) theItemDiv.innerHTML = htmlItemXofX(viewallthistime, pageNum);
};

function htmlItemXofX(viewallthistime,pageNum) {
	var currentItemLow = ((pageNum - 1) * numPerPage + 1);
	var currentItemHigh = pageNum * numPerPage;
	var numItems = window.items.length == 0 ? 1 : window.items.length;
	var theString = "<span class=itemof>";

	if((currentItemLow <= numItems) && (numItems <= currentItemHigh)) {
		currentItemHigh = numItems;
	}
	
	if(currentItemLow == currentItemHigh) {
		theString += "showing product <span class=bold>" + currentItemLow + "</span> of " + numItems ;
	} else if(viewallthistime) {
		theString += "showing items <span class=bold>1</span> - <span class=bold>" + numItems + "</span> of " + numItems ;
	} else {
		theString += "showing items <span class=bold>" + currentItemLow + "</span> - <span class=bold>" + currentItemHigh + "</span> of " + numItems ;
	}
	theString += "</span>";
	
	return theString;
};

function writePageXofX(viewallthistime,pageNum) {
	//var pageofDiv = FIND("pageof1");
	//if(pageofDiv) pageofDiv.innerHTML = localContent;
	pageofDiv = FIND("pageof2");
	if(pageofDiv) pageofDiv.innerHTML = htmlPageXofX(viewallthistime, pageNum);
};

function htmlPageXofX(viewallthistime,pageNum) {
	var localContent = "<span class=pageof>";
	if(viewallthistime)
		localContent += "Viewing all items";
	else
		localContent += "Page <span class=bold>" + pageNum + " </span>of " + numPages;

	//debug
	if(detailedSortInfo) {
		if(sortBy == "default")
			localContent += " (default sort)";
		else {
			localContent += " <span class=detailedsortinfo>(sorted by " + sortBy;
			if(sortHighLow) localContent += " high to low)"; else localContent += " low to high)</span>";
		}
	}

	localContent += "</span>";

	return localContent;
};


function writeUpDownArrow(divname) {
	if(divname) {
		localContent = "";
		if(sortHighLow) localContent += "&nbsp;" + upArrow; else localContent += "&nbsp;" + downArrow;
		divname.innerHTML = localContent;
	}
}

function writeArrows(viewallthistime,pageNum) {
	var localContent;
	var leftArrowString = "", rightArrowString = "";
	var upDownArrowDiv  = FIND(sortBy + "arrowdiv1");
	var upDownArrowDiv2 = FIND(sortBy + "arrowdiv2");
	if(viewallthistime) {
		writeUpDownArrow(upDownArrowDiv);
		writeUpDownArrow(upDownArrowDiv2);
		leftArrowString += leftArrowG;
		rightArrowString += rightArrowG;
		for(i=1; i<=numArrowDivs; i++) {
			localDiv = FIND("rightArrowDiv" + i);
			if(localDiv) localDiv.innerHTML = rightArrowString;
			localDiv = FIND("leftArrowDiv" + i);
			if(localDiv) localDiv.innerHTML = leftArrowString;
		}
	} else {
		writeUpDownArrow(upDownArrowDiv);
		writeUpDownArrow(upDownArrowDiv2);
		if(numPages == 1) {
			leftArrowString += leftArrowG;
			rightArrowString += rightArrowG;
		} else if(pageNum == 1) {
			leftArrowString += leftArrowG;
			rightArrowString += "<a href=javascript:writePage(2)>" + rightArrow + "</a>";
		} else if (pageNum == numPages) {
			leftArrowString += "<a href=javascript:writePage(" + (numPages - 1) + ")>" + leftArrow + "</a>";
			rightArrowString += rightArrowG;
		} else {
			leftArrowString += "<a href=javascript:writePage(" + (pageNum - 1) + ")>" + leftArrow + "</a>"
			rightArrowString += "<a href=javascript:writePage(" + (pageNum + 1) + ")>" + rightArrow + "</a>";
		}
		for(i=1; i<=numArrowDivs; i++) {
			localDiv = FIND("rightArrowDiv" + i);
			if(localDiv) localDiv.innerHTML = "<span onClick=\"window.location.href = '#top'\">" + rightArrowString + "</span>";
			localDiv = FIND("leftArrowDiv" + i);
			if(localDiv) localDiv.innerHTML = "<span onClick=\"window.location.href = '#top'\">" + leftArrowString + "</span>";
		}
	}
};

function writeArrowsHtml(viewallthistime,pageNum) {
	var localContent ="";
	var leftArrowString = "", rightArrowString = "";
	var prevText = "<< Previous";
	var nextText = "Next >>";
	var sepText = "&nbsp;&nbsp;|&nbsp;&nbsp;";
	
	if(viewallthistime) {
		localContent += prevText + sepText + nextText;
	} else {
		if(numPages == 1) {
			leftArrowString += prevText + sepText;
			rightArrowString += nextText;
		} else if(pageNum == 1) {
			leftArrowString += prevText + sepText;
			rightArrowString += "<a href=javascript:writePage(2)>" + nextText + "</a>";
		} else if (pageNum == numPages) {
			leftArrowString += "<a href=javascript:writePage(" + (numPages - 1) + ")>" + prevText + "</a>" + sepText;
			rightArrowString += nextText;
		} else {
			leftArrowString += "<a href=javascript:writePage(" + (pageNum - 1) + ")>" + prevText + "</a>"  + sepText;
			rightArrowString += "<a href=javascript:writePage(" + (pageNum + 1) + ")>" + nextText + "</a>";
		}
		
		localContent += "<span onClick=\"window.location.href = '#top'\">" + leftArrowString + "</span>";
		localContent += "<span onClick=\"window.location.href = '#top'\">" + rightArrowString + "</span>";
		
	}
	return localContent;
};

/* pagingQuantity, pagingAddtoCart, pagingPrice */
function pagingPrice(localItem) {
	var onsale = (localItem['showsalepricing']);
	var supersale = (localItem['showsupersalepricing']);
	var usemap = localItem.mappricing;
	var localContent = "";
	if(localItem.price != "") {
		if(localItem.price == "Currently Not Available"){
			localContent += "<span class=saleprice>";
			localContent += localItem.price;
			localContent += "</span><br>";	
		}	else if (!onsale){
			localContent += "<span class=price>";
			localContent += localItem.price;
			localContent += "</span><br>";
		} else if(usemap && !onsale){
			localContent += mapPricing(localItem);
		} else if(onsale && supersale){
			localContent += "<span class=saleprice><b>";
			localContent += localItem.saleprice;
			localContent += "</b></span><br>";			
		} else {
			localContent += "<span class=saleprice>";
			localContent += localItem.saleprice;
			localContent += "</span><br>";
		}
	}
	
	if (localItem['minorder'] != '') {
		localContent += "<span class=minOrderQty>Minimum Order: " + localItem['minorder'] + "</span>";
	}
	
	if(onsale && usemap) localContent += mapPricing(localItem);

	return localContent;
}

function pagingQuantity(localItem) {
	var localContent = "";
	if(localItem.useprice != 0)
		if(localItem.orderable) {
			localContent += "<span class=qtytext>Quantity: ";
			localContent += "<input type=text name=vwquantity size=2 class=qtybox value=1>";
			localContent += "</span><br>";
		} else 
			localContent += "";	
	return localContent;
}

function pagingAddToCart(localItem) {
	var localContent = "";
	if(localItem.useprice != 0 && !localItem.mappricing)
		if(localItem.orderable) {
			localContent += "<form method=post action=http://order.store.yahoo.com/cgi-bin/wg-order?" + storename + ">";
			if(showQuantity) localContent += pagingQuantity(localItem);
			localContent += "<input type=hidden name=vwcatalog value=" + storename + ">";
			localContent += "<input type=hidden name=vwitem value=" + localItem.id + ">";
			if(addToCartImage != "") 
				localContent += addToCartImage;
			else
				localContent += "<input type=submit id=submit value='Add to Cart'>"
			localContent += "</form>";
		} else 
			localContent += "<span class=outofstock>Out of Stock</span>";	
	return localContent;
}


/***************************************************************
	Scripts to generate pagingVertical style 
	Extracted from eval/decrypt 
****************************************************************/

function writeVerticalInfo(currentRow, numRows) {
	var localContent = "";
	localContent += "<tr valign=top class=contents-row>";
	//VERTICAL - LOOP CELLS
	for(currentCol=0; currentCol<numColumns; currentCol++) {
		localContent += "<td width=" + 100 / numColumns + "% height=100% align=center";

		if(pageSegment[currentItem]) 
			localContent += " class=vcell id=vcell" + currentItem;
	
		localContent += "><div class='itemContent'>";
	
		if(pageSegment[currentItem]) {
			//get pagingItem object to render 
			localItem = pageSegment[currentItem];
			//contentsElements is a global array dictating which fields to show in the output
			
			if(contentsElements.indexOf("quantity")) 
				showQuantity = true;
				
			var elementArray = contentsElements.split("/");
	
			for(i=0;i<elementArray.length;i++) {
				switch(elementArray[i]) {
					case "iboxgreen":
						if(localItem["green"]) localContent += "<div class=iboxgreen><img alt='InvitationBoxGreen' src='http://site.invitationbox.com/images/iboxgreenshort.gif'/></div>";
						else localContent += "<div class=iboxgreen></div>"
						break;
					case "icons":
						localContent += writeIcons(localItem);
						break;
					case "papercolor":
						if(localItem.papercolor) localContent += "<div class=papercolor>{ <a href=" + localItem.id + ".html>More Colors</a> }</div>";
						break;
					case "name":
						if(localItem.name != "") localContent += "<div class=advanceditem><a href=" + localItem.id + ".html>" + localItem.name + "</a></div>";
						break;
					case "code":
						if(localItem.code != "") localContent += "<div class=code>" + localItem.code + "</div>";
						break;
					case "price":
						localContent += pagingPrice(localItem);
						break;
					case "minorder":
						if(localItem.minorder != "") localContent += "<div class=minorder>Minimum Order: " + localItem.minorder + "</div>";
						break;
					case "abstract":
						if(localItem.abstr != "") localContent += "<div class=abstract>" + localItem.abstr + "</div>";
						break;
					case "quickview":
						if ( $.browser.msie && $.browser.version <= 6 ) {
							localContent += "";
					  } else {
							localContent += "<div class='qvHover'><a href='javascript:loadQuickView(" + (currentItem) + ");' onMouseOver='javascript:$(\"#qvImg"+currentItem+"\").attr(\"src\",\"http://site.invitationbox.com/images/ibox-quickview-on.gif\");' onMouseOut='javascript:$(\"#qvImg"+currentItem+"\").attr(\"src\",\"http://site.invitationbox.com/images/ibox-quickview-off.gif\");'><img id='qvImg" + currentItem + "' src='http://site.invitationbox.com/images/ibox-quickview-off.gif' border='0'></a></div>";
						}
						break;
					case "brand":
						localContent += "<div class=regpr>" + localItem.brand + "</div>";
						break;
					case "order":
						localContent += pagingAddToCart(localItem);
						break;
					case "quantity": 
						break;
					case "image": 
						localContent += writeVerticalImage(localItem);
					break;
				}
			}		
			currentItem++;
		} else {
			localContent += "&nbsp;";
		}
		localContent += "</div></td>";
	}
	localContent += "</tr>";

	return localContent;
};

function writeIcons(localItem) {
	var s = "<div class=sectionIcons>";
	if (localItem["quickship"]) {
		s += "<img alt='Quick Ship' src='http://site.invitationbox.com/images/quick-ship-galler-icon.gif' title='Quick Ship Item' />";
	}
	if (localItem["green"]) {
		s += "<img alt='InvitationBoxGreen' src='http://site.invitationbox.com/images/recycle-icon-gallery.gif' title='InvitationBox Green Item'/>";
	}
		/*
	if (localItem["topseller"]) {
		s += "<img alt='Top Seller' src='http://site.invitationbox.com/images/top-seller-icon.gif' title='Top Selling Item'/>";
	}
	*/
	s += "</div>";
	
	return s;
}

function writeVerticalImage(localItem) {
	var localContent = "";
	localContent += "<table cellspacing=0 cellpadding=0 border=0><tr>";	
	localContent += "<td style='background-color:transparent;'>";

	/*
	if(localItem["showsalepricing"] && localItem["freera"]){
		localContent += "<div class=saleheader><img src='http://site.invitationbox.com/images/10off_freera_icon.gif'/></div>";
	} else if (localItem["showsalepricing"]) {
		localContent += "<div class=saleheader><img src='http://site.invitationbox.com/images/save10_icon.gif' /></div>";
	} else if (localItem["freera"]) {
		localContent += "<div class=saleheader><img src='http://site.invitationbox.com/images/free_ra.gif' /></div>";
	} else 
	*/
	if (localItem.newitem) {
		localContent += "<div class=saleheader><img src='http://site.invitationbox.com/images/newitem_icon.gif' /></div>";
	} else { localContent += "&nbsp;"; }
	/*
	else {
		localContent += "<div class=saleheader><img src='http://site.invitationbox.com/images/spacerTransparent.gif' height='12px' /></div>";
	}
	*/
	
	localContent += "</td>";
	
	
	localContent += "</tr><tr><td id=contents-image style='background-color:transparent;' valign='bottom'><a href=" + localItem.id + ".html>" + localItem.img + "</a></td></tr></table>";
	
	return localContent;
};

function writeVertical(pageNum, viewallthistime) {
	var localContent = "";
	var numRows = Math.ceil(pageSegment.length / numColumns);
	currentItem=0; currentItemImage = 0;
	for(currentRow=0; currentRow<numRows; currentRow++) {
		if(pageSegment[currentItem]) {
			localContent += writeVerticalInfo(currentRow, numRows);
			if (currentRow < numRows-1) {
				localContent += "<tr><td colspan='100'><hr shade color='#E4DBCA' width='95%' align='center'></td></tr>";
			}
		}		
	}
	return localContent;
};

/***************************************************************
	Scripts to generate pagingEll style 
	Extracted from eval/decrypt 
****************************************************************/

function writeEllInfoCell(currentRow, numRows) {
	var localContent = "";
	localContent += "<td width=" + 100 / numColumns + "% height=100% align=left onmouseover=changeClass(this,'ecell-on'); onmouseout=changeClass(this,'ecell'); class=ecell id=ecell" + currentItem + ">"
	if(pageSegment[currentItem]) {
		localItem = pageSegment[currentItem];
    if(contentsElements.indexOf("quantity")) showQuantity = true;
		var elementArray = contentsElements.split("/");
		for(i=0;i<elementArray.length;i++) {
			switch(elementArray[i]) {
				case "name":
					if(localItem.name != "") localContent += "<a href=" + localItem.id + ".html>" + localItem.name + "</a><br>";
					break
				case "code":
					if(localItem.code != "") localContent += "<div class=code>" + localItem.code + "</div>";
					break
				case "price":
					localContent += pagingPrice(localItem);
					break
				case "abstract":
					if(localItem.abstr != "") localContent += "<div class=abstract>" + localItem.abstr + "</div>";
					break
				case "brand":
					if(localItem.brand != "") localContent += "<div class=brand>" + localItem.brand + "</div>";
					break
				case "order":
	        localContent += pagingAddToCart(localItem);
					break
        case "quantity": break
				case "image": break
			}
		}
		currentItem++;
	} else {
		localContent += " ";
	}
	localContent += "</td>";
	return localContent;
};

function writeEllImageCell() {
	var localContent = "";
	localContent += "<td align=center valign=bottom onmouseover=changeClass(FIND('ecell" + currentItem + "'),'ecell-on'); onmouseout=changeClass(FIND('ecell" + currentItem + "'),'ecell');>"
	if(pageSegment[currentItem]) {
		localItem = pageSegment[currentItem];
		localContent += "<a href=" + localItem.id + ".html>" + localItem.img + "</a>";
	} else {
		localContent += " ";
	}
	localContent += "</td>";
	return localContent;
};

function writeEll(pageNum, viewallthistime) {
	var localContent = "";
	var numRows = Math.ceil(pageSegment.length / numColumns);
	currentItem=0; currentItemImage = 0;
	for(currentRow=0; currentRow<numRows; currentRow++) {
		if(pageSegment[currentItem]) {
			localContent += "<tr valign=top>";
			for(currentCol=0; currentCol<numColumns; currentCol++) {
				if(pageSegment[currentItem]) {
					if(contentsElements.indexOf("image") != -1) 
						localContent += writeEllImageCell();
					localContent += writeEllInfoCell();
				} else {
					if(contentsElements.indexOf("image") != -1) 
						localContent += "<td> </td>";
					localContent += "<td> </td>";
				}
				if(currentCol<numColumns-1 && columnpad > 0) 
					localContent += writeCellPadding();
			}
			localContent += "</tr>";
		}
	}
	return localContent;
};

/***************************************************************
	Scripts to generate pagingWrap style 
	Extracted from eval/decrypt 
****************************************************************/

function writeWrapCell(currentRow, numRows) {
	var localContent = "";
	localContent += "<td width=" + 100 / numColumns + "% height=100% align=left onmouseover=changeClass(this,'wcell-on'); onmouseout=changeClass(this,'wcell'); class=wcell>"
	if(pageSegment[currentItem]) {
		localItem = pageSegment[currentItem];
		if(contentsElements.indexOf("quantity")) showQuantity = true;
		var elementArray = contentsElements.split("/");
		for(i=0;i<elementArray.length;i++) {
			switch(elementArray[i]) {
				case "image":
					localContent += "<a href=" + localItem.id + ".html>" + localItem.img + "</a>";
					break;
				case "name":
					if(localItem.name != "") localContent += "<a href=" + localItem.id + ".html>" + localItem.name + "</a><br>";
					break;
				case "code":
					if(localItem.code != "") localContent += "<span class=code>" + localItem.code + "</span><br>";
					break;
				case "price":
					localContent += pagingPrice(localItem);
					break;
				case "abstract":
					if(localItem.abstr != "") localContent += "<span class=abstract>" + localItem.abstr + "</span><br>";
					break;
				case "brand":
					if(localItem.brand != "") localContent += "<span class=brand>" + localItem.brand + "</span><br>";
					break;
        case "order":
          localContent += pagingAddToCart(localItem);
        	break;
        case "quantity": break;
			}
		}
		currentItem++;
	} else {
		localContent += " ";
	}
	localContent += "</td>";
	return localContent;
};

function writeWrap(pageNum, viewallthistime) {
	var localContent = "";
	var numRows = Math.ceil(pageSegment.length / numColumns);
	currentItem=0; currentItemImage = 0;
	for(currentRow=0; currentRow<numRows; currentRow++) {
		if(pageSegment[currentItem]) {
			localContent += "<tr valign=top>";
			for(currentCol=0; currentCol<numColumns; currentCol++) {
				if(pageSegment[currentItem])
					localContent += writeWrapCell();
				else
					localContent += "<td> </td>";
				if(currentCol<numColumns-1 && columnpad > 0) 
					localContent += writeCellPadding();
			}
			localContent += "</tr>";
		}
	}
	return localContent;
};

/***************************************************************
	Master script to generate HTML within the #paging div
	Extracted from eval/decrypt - originally encrypted to prevent
	reuse across multiple stores
****************************************************************/
function writePage(pageNum, viewallthistime) {	
	var localContent = "";
	
	//NOTE: pageSegment is initialized here as a global variable
	if ((numPerPage > -1) && !(viewallthistime)) 
		pageSegment = pagingSegment(window.items, pageNum); 
	else 
		pageSegment = window.items; 
			
	var numRows = Math.ceil(pageSegment.length / numColumns); 

	$('#pagingNavBar').html(writePagingNavBar(viewallthistime, pageNum));
	$('#itemBlockFilter').html(writeItemFilterBlock(viewallthistime));
	localContent += "<table id=\"pagingTable\" cellspacing=0 cellpadding=0 width=" + tableWidth + " border=0>"; 
	localContent += writeVertical(pageNum, viewallthistime); 
	localContent += "</table>";

	$("#contents").fadeOut('fast', function() { $(this).html(localContent).fadeIn('fast') });

	writePageLinks(viewallthistime,pageNum); 
	writeItemXofX(viewallthistime,pageNum); 
	writePageXofX(viewallthistime,pageNum); 
	//writeSortLinksOneClick("1",viewallthistime); 
	//writeSortLinksOneClick("2",viewallthistime); 
	$("#navBottomNextPrev").html("<font style='font-family:arial;font-size:10pt;'>"+writeArrowsHtml(viewallthistime, pageNum)+"</font></td>").addClass('pagingNavBar'); 

		
	//update paging state and commit to cookie 
	_pagingState.pageNum = pageNum;
	_pagingState.viewAll = viewallthistime;
	
	savePagingState(_pagingState);
	globalPageNum = pageNum; 
	globalViewallthistime = viewallthistime; 
  if(document.cookie.indexOf('invitationboxrecentitemsCookie') > 0) {  	
		var so = new SWFObject("http://site.invitationbox.com/Flash/recently_viewed_items/recently_viewed_widget.swf", "sotester", "200", "200", "8", "#FFFFFF");
		so.addParam("scale", "noscale");
		so.addParam("allowScriptAccess", "always");
		so.write("recentlyViewedItems");	
	}
}; 
	
function changeSortAndPage(newSortBy, newHighLow, pageNum, viewallthistime) { 
	sortBy = newSortBy; 
	sortHighLow = newHighLow; 
	updateSortBy(window.items, sortBy); 
	sortArray(window.items,0,window.items.length-1); 
	if(sortHighLow) 
		window.items.reverse(); 
	
	if(viewallthistime) 
		writePage(pageNum, true); 
	else 
		writePage(pageNum, false); 
};


function writeCellPadding(num) {
	if(num) localnum = num; else localnum = currentItem;
	if(pageSegment[localnum]) {
		var localContent = "<th><img src=/lib/" + storename + "/pspacer.gif height=1 width="
		                 +  round_decimals(columnpad / 2,0) + "></th>"
		                 +  "<th width=1 bgcolor=\"" + columnSeparatorColor + "\"><img src=/lib/" + storename + "/pspacer.gif"
		                 +  " height=1 width=1></th>"
		                 +  "<th><img src=/lib/" + storename + "/pspacer.gif height=1 width="
		                 +  round_decimals(columnpad / 2,0) + "></th>";
		return localContent;
	} else {
		var localContent = "<th><img src=/lib/" + storename + "/pspacer.gif height=1 width="
		                 +  round_decimals(columnpad / 2,0) + "></th>"
		                 +  "<th width=1><img src=/lib/" + storename + "/pspacer.gif"
		                 +  " height=1 width=1></th>"
		                 +  "<th><img src=/lib/" + storename + "/pspacer.gif height=1 width="
		                 +  round_decimals(columnpad / 2,0) + "></th>";
		return localContent;
	}
}

/***************************************************************
	Parse out url to get name of page
****************************************************************/
function getCurrentPageHTML() {
	temp = document.location.href.split(".");
	temp2 = temp[temp.length - 2].split("/");
	currentPageHTML = temp2[temp2.length - 1] + ".html";
	return currentPageHTML;
}


/***************************************************************

	This script is invoked upon document load to initialize the 
	paging state and rewrite the contents of #paging

****************************************************************/

function initPaging() {	
	numPages = Math.ceil(window.items.length / numPerPage);
	_pagingState = loadPagingState(); //initialize global var
		
	if (_pagingState.sortBy != "defaultsort") {
		sortItems(window.items, _pagingState.sortBy, _pagingState.sortDirection);		
	}
	
	//save original items in master array
	pageItems = window.items;
	
	if (assocArraySize(_pagingState.filters)) {
		applyActiveFilters(_pagingState.viewAll);
	}
		
	writePage(_pagingState.pageNum, _pagingState.viewAll); 
};

function updateSortBy(array, sortby) {
	/* find what value to sort the array by and store it to a variable local to each item */
	for(i=0; i<array.length; i++) {
		switch(sortby) {
			case "default" :
			case "defaultsort" :
				array[i].sortby = array[i].defaultsort;
				break;
			case "name" :
				array[i].sortby = array[i].name;
				break;
			case "price" :
				array[i].sortby = parseInt(array[i].useprice);
				break;
			case "pricerange" :
				array[i].sortby = array[i].pricerange;
				break;
			case "brand" :
				array[i].sortby = array[i].brand;
				break;
			default : array[i].sortby = array[i].name;
		}
	}
};

function writeOneSortLink(linkid,linkname,sep,chosen,bot,viewallthistime) {
	var localContent = "";
	if(chosen) {
		localContent += "<a class=chosen href=#top onclick=javascript:changeSortAndPage(\"" + linkid + "\",";
		if(sortHighLow) localContent += "false"; else localContent += "true";
		localContent += ",1," + viewallthistime + ");>";
		localContent += linkname;
		localContent += "</a>";
	} else {
		localContent += "<a href=#top onclick=javascript:changeSortAndPage(\"" + linkid + "\",false,1," + viewallthistime + ");>";
		localContent += linkname;
		localContent += "</a>";
	}
	localContent += "<span id=" + linkid + "arrowdiv" + bot + "></span>";
	if(sep) localContent += sortLinkSeparator;
	return localContent;
}

/******************************************************************************
	Filter the result set for the given mode (attribute to filter on) and value 
	
	@param attr - attribute to base filter on
	@param value - value to seek for the attribute 
	@param viewallthistime - boolean as to whether we are in "viewall" mode
*******************************************************************************/
function applyFilter(attr, value, viewallthistime) {			
	//debugger;
	if (value == "All") {
		unnapplyFilter(attr, viewallthistime)
		return;
	}

	filterItems(attr, value);
	
	//recalculate the number of pages for this new result set
	calculatePaging();
	
	//mark filter as active - IMPORTANT: Invoke *before* rewriting page
	_pagingState.filters[attr] = value;

	//rewrite page	
	writePage(globalPageNum, viewallthistime);	
}

function filterItems(attr, value) {	
	var ar = new Array(); //new array to store filtered items
	var j = 0; //index for new array
	
	if (attr.indexOf('eventtype') != -1) {
		attr = 'eventtype';
	}
	
	var filterItemCallback = filterItem; //default behavior	
	
	if (_filterCallbacks[attr])
		filterItemCallback = _filterCallbacks[attr]; 
			
	//loop through all the pagingItem objects
	for (var i = 0; i < window.items.length; i++) {
		var it = window.items[i];		
		var matchFound;

		//if this item matches for the given filter then add it to the new array
		if (matchFound = filterItemCallback(it, attr, value)) {
			ar[j] = it;
			j++;
		}
	}
	
	//set the items to this new filtered array
	window.items = ar;
}

/* 
	Overrideable function to determine whether the item should be filtered 
	for the given attribute and value. Default implementation checks for 
	attr-to-property match on pagingItem object.
	
	@param it - the pagingItem object to inspect
	@param attr - the attribute to perform filter on (for default behavior this has 
								a 1-1 relationship with the pagingItem object property)
	@param value - the attribute value being applied for this filter
	
	@return Boolean indicating whether item should be filtered
*/
function filterItem(it, attr, value) {
	//override behavior for special case handling of empty attribute values via 'Other' reference
	if (value == 'Other')
		value = '';			
	
	//get the value to filter on 		
	var filterValue = it[attr];
			
	//console.log("Filtering value: " + filterValue);
	return filterValueMatch(filterValue, value);
}

function resetAllFilters(viewallthistime) {
	_pagingState.filters = new Array();
	window.items = pageItems; //set back to master array
	calculatePaging();
	writePage(_pagingState.pageNum, viewallthistime);	
}

/* Unapplying filters is trickier than applying - we basically have to unapply the single 
   filter and then reset to the master result set and *reapply* all the remaining filters */
function unnapplyFilter(attr, viewallthistime) {
	//console.log("Unapplying: ", attr);
	
	//mark filter as inactive - IMPORTANT: Invoke *before* rewriting page
	_pagingState.filters[attr] = false;
	
	//set back to master array
	window.items = pageItems; 
	
	//reapply all filters
	applyActiveFilters(viewallthistime);
	
	//recalculate the number of pages for this new result set
	calculatePaging();
	
	//rewrite page	
	writePage(_pagingState.pageNum, viewallthistime);	
}

/* applies active filters to pagingItems */
function applyActiveFilters(viewallthistime) {
	for (attr in _pagingState.filters) {
		if (_pagingState.filters[attr]) { //filter is set 
			filterItems(attr, _pagingState.filters[attr], viewallthistime);
		}
	}
	// recalculate the number of pages for this new result set
	calculatePaging();
}

function hasActiveFilters() {
	for (attr in _pagingState.filters)					
		if (_pagingState.filters[attr]) //at least one filter is set
			return true;
	
	return false;
}

//calculate the number of pages for the current result set in window.items
function calculatePaging() {
	//recalculate the number of pages for this new result set - NOTE: numPages is a global variable
	numPages = Math.ceil(window.items.length / numPerPage);
	numPages = numPages == 0 ? 1 : numPages;
	
	//this can occur if e.g. the user is viewing a page higher and then narrows the result set via a filter
	if (globalPageNum > numPages)
		globalPageNum = 1;		
}


function filterValueMatch(filterValue, itemValue) {
	//alert('fv='+ filterValue + '   iv='+ itemValue);
	if (typeof filterValue == 'string' && typeof itemValue == 'string')	{
		//alert('fv='+ filterValue.toLowerCase().replace("&quot;","\"") + '   iv='+ itemValue.toLowerCase());
		return filterValue.toLowerCase().replace(/&quot;/g,"\"") == itemValue.toLowerCase();
	}	else
		return filterValue == itemValue;
}

function getFilterValue(pagingItem, attr) {
	val = pagingItem[attr];
	//console.log("Filter is of type: ", typeof val);
	return val;
}

/********************************************************************
	Write drop down selectors as defined by global variables (i.e.
	showsortmanufacturer,sortmanufacturer,showsorttheme,sorttheme, etc.)	
*********************************************************************/
function writeSortLinks(bot,viewallthistime) {
	if (showsortmanufacturer) {
		col = sortmanufacturer.split("|");
		var strContent = "<select onchange=\"applyFilter('brand', this.value,"+viewallthistime+");\">";
		for (i=0; i<col.length; i++)
		{
			strContent += "<option value=\"" + col[i] + "\">" + col[i] + "</option>";
		}
		strContent += "</select>";
		document.getElementById("sortlinks" + bot).innerHTML = "Sort By:&nbsp;" + strContent;
	}
	if (showsorttheme) {
		col = sorttheme.split("|");
		var strContent = "<select onchange=\"applyFilter('theme', this.value,"+viewallthistime+");\">";
		for (i=0; i<col.length; i++)
		{
			strContent += "<option value=\"" + col[i] + "\">" + col[i] + "</option>";
		}
		strContent += "</select>";
		document.getElementById("sortlinks" + bot).innerHTML += "&nbsp;&nbsp;&nbsp;" + strContent;
	}
	if (showsortprice) {
		col = sortprice.split("|");
		var strContent = "<select onchange=\"applyFilter('pricerange', this.value,"+viewallthistime+");\">";
		for (i=0; i<col.length; i++)
		{
			strContent += "<option value=\"" + col[i] + "\">" + col[i] + "</option>";
		}
		strContent += "</select>";
		document.getElementById("sortlinks" + bot).innerHTML += "&nbsp;&nbsp;&nbsp;" + strContent;
	}
};

/*************************************************************************
	Write drop down selector that actually performs a sort and NOT a filter
**************************************************************************/
function writeSortLinksRevisited(bot, viewallthistime) {
	var strContent = "<strong>Sort By</strong> <select onchange=\"applySort(this.value,"+viewallthistime+");\">";
	strContent += "<option value=\"defaultsort\"" + ((sortBy == 'defaultsort') ? ' selected ' : '') + ">Default</option>";
	strContent += "<option value=\"name\"" + ((sortBy == 'name') ? ' selected ' : '') + ">Name</option>";
	strContent += "<option value=\"pricerange\"" + ((sortBy == 'pricerange') ? ' selected ' : '') + ">Price ($-$$$$)</option>";
	strContent += "<option value=\"brand\""+ ((sortBy == 'brand') ? ' selected ' : '') + ">Brand</option>";
	strContent += "</select>";
	$('#sortlinks' + bot).html(strContent);
}

function writeSortLinksOneClick(bot, viewallthistime) {
	var sortDir = _pagingState.sortDirection; //get sort direction from global pagingState object
	var strContent = '<strong>Sort By</strong> '; 
	strContent += ' &nbsp;&nbsp; ';
	
	strContent += '<span class=sortStyle><a href="javascript:applySort(\'defaultsort\',' + viewallthistime + ');">Default</a></span>';
	if (_pagingState.sortBy == 'defaultsort')
	  strContent += getSortDirectionArrow(sortDir);
		
	strContent += ' &nbsp;&nbsp; ';	
	strContent += '<span class=sortStyle><a href="javascript:applySort(\'name\',' + viewallthistime + ');">Name</a></span>';
	if (_pagingState.sortBy == 'name')
	  strContent += getSortDirectionArrow(sortDir);
		
	strContent += ' &nbsp;&nbsp; ';	
	strContent += '<span class=sortStyle><a href="javascript:applySort(\'pricerange\',' + viewallthistime + ');">Price ($-$$$$)</a></span>';
	if (_pagingState.sortBy == 'pricerange')
	  strContent += getSortDirectionArrow(sortDir);
		
	strContent += ' &nbsp;&nbsp; ';	
	strContent += '<span class=sortStyle><a href="javascript:applySort(\'brand\',' + viewallthistime + ');">Brand</a></span>';
	if (_pagingState.sortBy == 'brand')
	  strContent += getSortDirectionArrow(sortDir);
		
	$('#sortlinks' + bot).html(strContent).addClass('sortDiv');
}

function writeSortLinksImages(viewallthistime) {
	var sortDir = _pagingState.sortDirection; //get sort direction from global pagingState object
	var strContent = ''; 
	strContent += ' &nbsp;&nbsp; ';
	
	strContent += '<a href="javascript:applySort(\'defaultsort\',' + viewallthistime + ');">';
	strContent += (_pagingState.sortBy == 'defaultsort') ? '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Default-Bu.gif" height="24">' : '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Default-BR.gif" height="24">'; 		
	strContent += '</a>';
	
	strContent += ' &nbsp;&nbsp; ';	

	strContent += '<a href="javascript:applySort(\'name\',' + viewallthistime + ');">';
	if (_pagingState.sortBy == 'name') {
		if (sortDir == SORT_ASC) {
			strContent += '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Name-Up-Bu.gif" height="24">';
		} else {
			strContent += '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Name-Down-Bu.gif" height="24">';
		}
	} else {
		strContent += '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Name-BR.gif" height="24">';
	}
	strContent += '</a>';
	
	strContent += ' &nbsp;&nbsp; ';	
	strContent += '<a href="javascript:applySort(\'pricerange\',' + viewallthistime + ');">';
	if (_pagingState.sortBy == 'pricerange') {
		if (sortDir == SORT_ASC) {
			strContent += '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Price-low-high-Bu.gif" height="24">';
		} else {
			strContent += '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Price-high-low-Bu.gif" height="24">';
		}
	} else {
		strContent += '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Price-BR.gif" height="24">';
	}
	strContent += '</a>';
	strContent += ' &nbsp;&nbsp; ';	

	strContent += '<a href="javascript:applySort(\'brand\',' + viewallthistime + ');">';
	if (_pagingState.sortBy == 'brand') {
		if (sortDir == SORT_ASC) {
			strContent += '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Brand-Up-Bu.gif" height="24">';
		} else {
			strContent += '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Brand-Down-Bu.gif" height="24">';
		}
	} else {
		strContent += '<img class="valignCenter" src="http://site.invitationbox.com/images/paging/BTN-Brand-BR.gif" height="24">';
	}
	strContent += '</a>';
	
	return strContent;
}

function getSortDirectionArrow(sortDirection) {	
	if (typeof upArrow != "undefined" && typeof downArrow != "undefined") {
		return (sortDirection == SORT_ASC) ? upArrow : downArrow;
	} else {	
		//return '<span class="sortDirectionArrow">' + ((sortDirection == SORT_ASC) ? '&and;' : '&or;') + '</span>';
		return '<font face="Webdings" size="2">' + ((sortDirection == SORT_ASC) ? '5' : '6') + '</font>';
	}
}

function applySort(newSort, viewallthistime) {	
  sortDirection = (_pagingState.sortBy != newSort) ? SORT_ASC : _pagingState.sortDirection * -1; //check global sortby variable to determine which direction to sort
		
	//debugger;
	window.items = sortItems(window.items, newSort, sortDirection);
	//set global
	_pagingState.sortBy = newSort;	
	_pagingState.sortDirection = sortDirection;
	
	//rewrite page	
	writePage(_pagingState.pageNum, viewallthistime);		
}

/* This sort algorithm should perform faster (not needing to store sort at item level 
	 which is an extra step) and also allows secondary sorting */
function sortItems(items, newSort, sortDirection) {
	if (!sortDirection)
		sortDirection = SORT_ASC;
		
	items.sort(
		function () { 
			var arg0 = arguments[0][newSort];
			var arg1 = arguments[1][newSort];			
			if (typeof arg0 == 'string' && typeof arg1 == 'string') {
				arg0 = arg0.toLowerCase();
				arg1 = arg1.toLowerCase();
			}
						
			if (arg0 < arg1) { return -1 * sortDirection; }
			if (arg0 > arg1) { return 1 * sortDirection; }
			
			//secondary sort by name for brand and pricerange
			if (newSort == 'brand' || newSort == 'pricerange') {				
				var name0 = arguments[0]['name'].toLowerCase();
				var name1 = arguments[1]['name'].toLowerCase();				

				if (name0 < name1) { return -1; }
				if (name0 > name1) { return 1; }
			}
			return 0;			
		}
	);

	return items;
}

function changeFormat(newFormat) {
	_pagingState.contentsFormat = newFormat;
	writePage(globalPageNum, globalViewallthistime);
}

function makeMAPWin(ww, wh) {
	w1=window.open('','w1','width='+ww+',height='+wh+',status=no,toolbar=no,menubar=no,location=no,resizable=yes,scrollbars=yes');
	w1.document.open();
	w1.document.write("<font size=\"2\" face=\"Arial, Helvetica, sans-serif\"><b>Price \"Too Low to Display\" Explained<\/b><br> In order to provide the best support from our manufacturer's and distributors, we have agreed to abide by their \"MAP\" or minimum-advertised-price policy. You can see this price by clicking the product name and then selecting the Add to Cart button on the product information page. <br><br>Please be assured that simply adding an item to your cart does not obligate you to buy it--you can always delete the item from your cart if you decide not to purchase it.<p align=\"center\"><a href=\"javascript:window.close();\">Close Window</a></p></font>");
	w1.document.focus();
};

function mapPricing(useItem) {
	var mapstring = "<span class=map>";
	mapstring += "<form method=post action=http://order.store.yahoo.com/cgi-bin/wg-order?" + storename + ">"
	mapstring += '<input id=mapinput type=submit value="Click for instant price quote" height="16" width="155" border=0>';
	mapstring += ' <a href="javascript:makeMAPWin(300,350);">(Why?)</a><br>';
	mapstring += "<input type=hidden name=vwcatalog value=" + storename + ">"
	mapstring += "<input type=hidden name=vwitem value=" + localItem.id + ">";
	if(addToCartImage != "")
		mapstring += addToCartImage;
	else
		mapstring += "<input type=submit id=submit value='Add to Cart'>"
	mapstring += "</form>";
	mapstring += "</span>";
	return mapstring;
}

/****************************************************************
		BEGIN CUSTOM FUNCTIONS FOR ADVANCED FILTERING 10/15/07
****************************************************************/
function writeItemFilterBlock(viewallthistime) {	
	$("#paging").addClass("advanced");
	
	var showPhotos = false;
	
	for (var i=0;i<window.items.length;i++) {
		if (window.items[i]['photovalue']) {
			if (window.items[i]['photovalue'] > 0) {
				showPhotos = true;
				break;			
			}
		}
  }
	
	var html = '<table border=0 style="font-size:12pt;" id="filterTable" cellpadding=1 cellspacing=0 width="100%">';

	//html += '<tr><td><div class="filterBlockHeader">Narrow Your Results<br><div id="totalFilteredItems">'+window.items.length+' items</div><div id="resetAll"><a href="javascript:resetAllFilters('+viewallthistime+')">Reset All Filters</a></div></div></td></tr>';
	html +=	'<tr><td>' + getBooleanFilters(viewallthistime) + '<br></td></tr>';
	if (typeof(showEventType)!="undefined") {
		if (showEventType) {
			html += '<tr><td><table class="filterBorder" cellpadding=0 cellspacing=0 width="100%"><tr><td>' + createFilterEventType(viewallthistime) + '</td></tr></table><br></td></tr>';
		}
	}
	if (typeof(showPhotoCardStyle)!="undefined") {
		if (showPhotoCardStyle) {
		  html += '<tr><td><table class="filterBorder" cellpadding=0 cellspacing=0 width="100%"><tr><td>' + createPhotoCardStyleFilter(viewallthistime) + '</td></tr></table><br></td></tr>';	
		}
	}
	
	html += '<tr><td><table class="filterBorder" cellpadding=0 cellspacing=0 width="100%"><tr><td>' + createFeaturedThemes(viewallthistime) + '</td></tr></table><br></td></tr>';	
	if (showPhotos) {
		html += '<tr><td><table class="filterBorder" cellpadding=0 cellspacing=0 width="100%"><tr><td>' + createPhotoNums(viewallthistime) + '</td></tr></table><br></td></tr>';
	}
	html += '<tr><td><table class="filterBorder" cellpadding=0 cellspacing=0 width="100%"><tr><td>' + createFeaturedDesigners(viewallthistime) + '</td></tr></table><br></td></tr>';
	html += '<tr><td><table class="filterBorder" cellpadding=0 cellspacing=0 width="100%"><tr><td>' + createFilterPrintMethod(viewallthistime) + '</td></tr></table><br></td></tr>';
	html += '<tr><td><table class="filterBorder" cellpadding=0 cellspacing=0 width="100%"><tr><td>' + createItemSizeFilter(viewallthistime) + '</td></tr></table><br></td></tr>';
 	html += '<tr><td><div id="recentlyViewedItems"></div>';
	html += '</table>';
	
	return html;	
}

function writePagingNavBar(viewallthistime, pageNum) {
	var html = "<table align='center' border=0 cellpadding=4 cellspacing=0 width='988' height='35' background='http://site.invitationbox.com/images/paging/IMG-Section-Top-Bar.gif'><tr>";
	
	html += "<td class='pagingNavBar' valign='middle' width='250'>";
	html += "Narrow Your Results&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;";
	html += "<font class='pagingBlueText'>Sort By:</font></td>";
	html += "<td class='pagingSortButtons' valign='bottom'>" + writeSortLinksImages(viewallthistime) + "</td>";
	html += "<td class='pagingNavBar' valign='bottom' style='text-align:right !important;'><font style='font-family:arial;font-size:10pt;'>"+writeArrowsHtml(viewallthistime, pageNum)+"</font></td>";
	
	html += "</tr></table>";
	html += "<table align='center' border=0 cellpadding=0 cellspacing=0 width='988' height='35'><tr>";
	html += "<td class='pagingNavBar' style='text-align:center;' valign='top' width='150'>"+window.items.length+" items";
	html += "<a href=\"javascript:resetAllFilters("+viewallthistime+")\"><img src='http://site.invitationbox.com/images/paging/BTN-Reset-All-FIlters.gif' border=0></a></td>";
	html += "<td class='pagingNavBottomBar'>" + htmlItemXofX(viewallthistime, pageNum) + "</td>";
	html += "<td class='pagingNavBottomBar'>" + getPageLinks(viewallthistime,pageNum,false) + "</td>";
	html += "<td class='pagingNavBottomBar' align='right'>" + htmlPageXofX(viewallthistime, pageNum) 
	if (!viewallthistime) {
		html += '&nbsp;&nbsp;&nbsp;<a href="javascript:writePage(1,true)" class="viewall">View All</a>';
	}
	html += "</td>";
	html += "</tr></table>";
	return html;
}

function getResetAllOptionsLink(viewallthistime) {
	return (hasActiveFilters())	
		? '<p class="reset"><a href="javascript:resetAllFilters(' + viewallthistime + ');">Start Over</a></p>'
		: '';
}

function getAttributeFilterHtml(heading, attr, viewallthistime, allowEmptyValues) {
	html = getAttributeFilterListHtml(attr, viewallthistime, allowEmptyValues);
	if (html) {
		var h2 = '<div class=\'outerter\'><div class=\'h2innerborder\'><h2>' + heading;
		if (_pagingState.filters[attr]) //this filter is selected
			h2 += '	<a href="javascript:applyFilter(\'' + attr + '\', \'All\',' + viewallthistime + ');" class="filterviewall">Reset</a> ';
		h2 += '</h2></div>';
		html = h2 + html;
	}
	return html;
}

function createFeaturedThemes(viewallthistime) {  
	var html = '<table border=0 cellpadding=0 cellspacing=0 width="100%"><tr class=themeFilter><td class=titleCell>Filter By Theme</td></tr>';
	var allowEmptyValues = true;
	var attr = 'theme';

	//extract assoc array of all available values from pagingItem array for a given attribute
	var attrValues = getItemValues(attr, allowEmptyValues);
	var attrValue; //define var to hold current attr
	var themeDrop = "<select id='themeDrop' onchange='filterTheme(this.options[this.selectedIndex].value);' class='filterDropDown'><option value='All'>--- View All Themes ---</option>";
	var numAttributes = assocArraySize(attrValues);
	
	if (numAttributes)	{ //else display all available attributes
		//first sort the attributes
		var attrValues = ksort(attrValues);
		
		var topAttrValues = getTopAttrValues(attrValues, attr);		

		//now loop thru the sorted attributes
		var cx = 0;
		var maxItems = 10;
		var ddWritten = false;
		var bShowOthers = (_pagingState.filters[attr]);
		for (attrValue in attrValues)	{
			themeDrop += "<option value=\"" + attrValue + "\">" + attrValue + " (" + attrValues[attrValue] + ")</option>";
			if (! isAttrLinkHidden(attrValue, topAttrValues) && cx < maxItems) {
				cx++;
				if (_pagingState.filters[attr] == attrValue) {
					html += '<tr><td class=filterCell><input id="cb'+attr+attrValue.replace(/&quot;/g,"\"")+'" type=checkbox class="filterBox" Checked OnClick="applyFilter(\'theme\',\'All\',false);">&nbsp;<a href="javascript:applyFilter(\'theme\',\'All\',false);">' + attrValue + ' (' + attrValues[attrValue] + ')</a></td></tr>';
				} else {
					html += '<tr><td class=filterCell><input id="cb'+attr+attrValue.replace(/&quot;/g,"\"")+'" type=checkbox class="filterBox" OnClick="filterTheme(\'' + escapeQuotes(attrValue) + '\');">&nbsp;<a href="javascript:filterTheme(\'' + escapeQuotes(attrValue) + '\');">' + attrValue + ' (' + attrValues[attrValue] + ')</a></td></tr>';					
				}
			}
		}
	}
	
	//html += '<tr><td class=filterCell><a href="javascript:applyFilter(\'theme\',\'All\',false);">Show Others</a></td></tr>';
	themeDrop += "<option value='All'>View All</option></select>";
	html += '<tr><td class=filterCell>REPLACE_THEMEDD</td></tr>';
	html = html.replace('REPLACE_THEMEDD',themeDrop);
	html += '</table>';
	
	return html;
}

function createFilterPrintMethod(viewallthistime) {  
	return createFilter('printMethod','Print Method');	
}

function createPhotoNums(viewallthistime) {  
	return createFilter('photovalue','# of Photos');	
}
function createFilterEventType(viewallthistime) {  
	var html = '<table border=0 cellpadding=0 cellspacing=0 width="100%"><tr class=themeFilter><td class=titleCell>Filter By Event Type</td></tr>';
	var allowEmptyValues = true;
	var attr = 'eventtype';

	//extract assoc array of all available values from pagingItem array for a given attribute
	var attrValues = getItemCommaSeparatedValues(attr, allowEmptyValues);
	var attrValue; //define var to hold current attr
	var numAttributes = assocArraySize(attrValues);

	//var dropDown = "<select onchange='applyFilter(\"" + attr + "\",this.options[this.selectedIndex].value,false);'><option value='All'>--- View All Photo Options ---</option>";
	
	if (numAttributes)	{ //else display all available attributes
		//first sort the attributes
		var attrValues = ksort(attrValues);
		var topAttrValues = getTopAttrValues(attrValues, attr);		
	
		//now loop thru the sorted attributes
		var cx = 0;
		var maxItems = 10;
		for (attrValue in attrValues)	{  // For event type this could be a comma separated string
			//dropDown += "<option value=\"" + attrValue + "\">" + attrValue + " (" + attrValues[attrValue] + ")</option>";
			if (! isAttrLinkHidden(attrValue, topAttrValues) && cx < maxItems) {
				if (_pagingState.filters[attr +'-'+attrValue] == attrValue.replace(/&quot;/g,"\"")) {
					html += '<tr><td class=filterCell><input type=checkbox Checked class="filterBox" OnClick="applyFilter(\''+attr+'-'+attrValue+'\',\'All\',false);">&nbsp;<a href="javascript:applyFilter(\''+attr+'-'+attrValue+'\',\'All\',false);">' + attrValue + ' (' + attrValues[attrValue] + ')</a></td></tr>';
				} else {
					html += '<tr><td class=filterCell><input type=checkbox class="filterBox" OnClick="applyFilter(\''+attr+'-'+attrValue+'\',\'' + escapeQuotes(attrValue) + '\',false);">&nbsp;<a href="javascript:applyFilter(\''+attr+'-'+attrValue+'\',\'' + escapeQuotes(attrValue) + '\',false);">' + attrValue + ' (' + attrValues[attrValue] + ')</a></td></tr>';
				}
				cx++;
			}
		}
		//html += '<tr><td class=filterCell>REPLACE_DD</td></tr>';
	}				
	//dropDown += "<option value='All'>View All</option></select>";
	//html = html.replace('REPLACE_DD',dropDown);
	html += '</table>';
	
	return html;
}

function createItemSizeFilter(viewallthistime) {  
	return createFilter('productsize', 'Size');
}

function createPhotoCardStyleFilter(viewallthistime) {  
	return createFilter('photocardstyle', 'Card Style');
}

function createFilter(attr, titleStr) {
	var html = '<table border=0 cellpadding=0 cellspacing=0 width="100%"><tr class=themeFilter><td class=titleCell>Filter By '+titleStr+'</td></tr>';
	var allowEmptyValues = true;

	//extract assoc array of all available values from pagingItem array for a given attribute
	var attrValues = getItemValues(attr, allowEmptyValues);
	
	var attrValue; //define var to hold current attr
	var numAttributes = assocArraySize(attrValues);
	
	if (numAttributes)	{ //else display all available attributes
		//first sort the attributes
		var attrValues = ksort(attrValues);
		var topAttrValues = getTopAttrValues(attrValues, attr);		
	
		//now loop thru the sorted attributes
		var cx = 0;
		var maxItems = 10;
		for (attrValue in attrValues)	{
			if (! isAttrLinkHidden(attrValue, topAttrValues) && cx < maxItems) {
				if (_pagingState.filters[attr] == attrValue.replace(/&quot;/g,"\"")) {
					html += '<tr><td class=filterCell><input id="cb'+attr+attrValue.replace(/&quot;/g,"\"")+'" type=checkbox Checked class="filterBox" OnClick="applyFilter(\''+attr+'\',\'All\',false);">&nbsp;<a href="javascript:applyFilter(\''+attr+'\',\'All\',false);">' + attrValue + ' (' + attrValues[attrValue] + ')</a></td></tr>';
				} else {
					html += '<tr><td class=filterCell><input id="cb'+attr+attrValue.replace(/&quot;/g,"\"")+'" type=checkbox class="filterBox" OnClick="applyFilter(\''+attr+'\',\'' + escapeQuotes(attrValue) + '\',false);">&nbsp;<a href="javascript:applyFilter(\''+attr+'\',\'' + escapeQuotes(attrValue) + '\',false);">' + attrValue + ' (' + attrValues[attrValue] + ')</a></td></tr>';
				}
				cx++;
			}
		}
	}				
	html += '</table>';
	
	return html;
}

function filterTheme(theme) {			
	applyFilter('theme',theme,false);	
}

function createFeaturedDesigners(viewallthistime) {  
	var html = '<table border=0 cellpadding=0 cellspacing=0 width="100%"><tr class=designerFilter><td class=titleCell>Filter By Designer</td></tr>';
	var allowEmptyValues = true;
	var attr = 'brand';

	//extract assoc array of all available values from pagingItem array for a given attribute
	var attrValues = getItemValues(attr, allowEmptyValues);
	var attrValue; //define var to hold current attr
	var dropDown = "<select class='filterDropDown' onchange='applyFilter(\"" + attr + "\",this.options[this.selectedIndex].value,false);'><option value='All'>--- View All Designers ---</option>";
	var numAttributes = assocArraySize(attrValues);
	var bShowOthers = (_pagingState.filters[attr]);
	
	if (numAttributes)	{ //else display all available attributes
		//first sort the attributes
		var attrValues = ksort(attrValues);
		
		var topAttrValues = getTopAttrValues(attrValues, attr);

		//now loop thru the sorted attributes
		var cx = 0;
		var maxItems = 100;
		for (attrValue in attrValues)	{
			dropDown += "<option value=\"" + attrValue + "\">" + attrValue + " (" + attrValues[attrValue] + ")</option>";
			if (! isAttrLinkHidden(attrValue, topAttrValues) && cx < maxItems) {
				if (_pagingState.filters[attr] == attrValue) {
					html += '<tr><td id="cb'+attr+attrValue.replace(/&quot;/g,"\"")+'" class=filterCell><input type=checkbox class="filterBox" Checked OnClick="applyFilter(\'brand\',\'All\',false);">&nbsp;<a href="javascript:applyFilter(\'brand\',\'All\',false);">' + attrValue + ' (' + attrValues[attrValue] + ')</a></td></tr>';
				} else {
					html += '<tr><td id="cb'+attr+attrValue.replace(/&quot;/g,"\"")+'" class=filterCell><input type=checkbox class="filterBox" OnClick="applyFilter(\'brand\',\'' + escapeQuotes(attrValue) + '\',false);">&nbsp;<a href="javascript:applyFilter(\'brand\',\'' + escapeQuotes(attrValue) + '\',false);">' + attrValue + ' (' + attrValues[attrValue] + ')</a></td></tr>';					
				}				
				cx++;
			}
		}

		//html += '<tr><td class=filterCell>REPLACE_DD</td></tr>';
	}				
	//dropDown += "<option value='All'>View All</option></select>";
	//html = html.replace('REPLACE_DD',dropDown);
	html += '</table>';
	
	return html;
}

function getAttributeFilterListHtml(attr, viewallthistime, allowEmptyValues) {
	//extract assoc array of all available values from pagingItem array for a given attribute
	var attrValues = getItemValues(attr, allowEmptyValues);
	var attrValue; //define var to hold current attr
	var html = '';
	
	var numAttributes = assocArraySize(attrValues);
	
	if (attrValue = _pagingState.filters[attr]) { //this filter is already selected
		//display just single attr
		html += '<p>' + attrValue + '</p></div>';		
	}	 else if (numAttributes) { //else display all available attributes
		html = '<ul id="filter-' + attr + '">';
		//first sort the attributes
		var attrValues = ksort(attrValues);
		
		var topAttrValues = getTopAttrValues(attrValues, attr);		
		var hasHiddenAttributes = false;
		
		//now loop thru the sorted attributes
		for (attrValue in attrValues) {
			//render link for each attribute
			html += '<li';
			//is link hidden? 
			if (isAttrLinkHidden(attrValue, topAttrValues)) {
				html += ' style="display:none"';  //add style to hide attribute
				hasHiddenAttributes = true;
			}
							
			html += '><a href="javascript:applyFilter(\'' + attr + '\', \'' + escapeQuotes(attrValue) + '\',' + viewallthistime + ');">' + attrValue + ' (' + attrValues[attrValue] + ')</a></li>';	
			
		}
		//are there any hidden attributes?
		if (hasHiddenAttributes) {
			//display a view all link for the hidden attributes	
			html += '<li class="showAllAttributes"><a href="javascript:showAllAttributes(\'' + attr + '\');">More...</a></li>';
		}
		html += '</ul></div>';					
	}
	
	return html;
}

function showAllAttributes(attr) {
	$('#filter-' + attr + ' li').show('fast');
	$('#filter-' + attr + ' li.showAllAttributes').hide();
}

function isAttrLinkHidden(attrValue, topAttrValues) {
	return (typeof topAttrValues[attrValue] == "undefined");		
}

function escapeQuotes(val) {
	return val.replace(/'/, "\\'");
}

/* 
	For the currently loaded pagingItem objects retrieve an array of unique values that match the specified attribute.
	
	@param attr The attribute to inspect
	@param allowEmptyValues Optional - Boolean indicating whether to classify empty values as "Other"
	@return an associative array where [attribute value = number of occurences]
	
	NOTE: This does not include empty values.
*/
function getItemValues(attr, allowEmptyValues) {
	var values = new Array(); //array to hold all values and their count	
	for (var i = 0; i < window.items.length; i++) {
		var it = 	window.items[i];
		var val = it[attr];

		//eliminate empty values - TODO: Include as a miscellaneous option?
		if (val.length == 0) {
			if (!allowEmptyValues)
				continue;
			else 
				val = 'Other';
		}
		
		var count = (values[val]) ? values[val] : 0;
		values[val] = count + 1;
	}	
	
	//for (value in values)
	//	console.log(value, values[value]);
		
	return values;
}

function getItemCommaSeparatedValues(attr, allowEmptyValues) {
	var values = new Array(); //array to hold all values and their count	
	for (var i = 0; i < window.items.length; i++) {
		var it = 	window.items[i];
		var val = it[attr];

		//eliminate empty values - TODO: Include as a miscellaneous option?
		if (val) {
			if (val.length == 0) {
				if (!allowEmptyValues)
					continue;
				else 
					val = 'Other';
			}
		} else {
			continue;
		}

		var separatedValues = val.split(',');
		for (var idx = 0; idx < separatedValues.length; idx++) {
			var count = (values[separatedValues[idx]]) ? values[separatedValues[idx]] : 0;
			values[separatedValues[idx]] = count + 1;
		}
	}	

	return values;
}

function getPageItemValues(attr, allowEmptyValues) {
	var values = new Array(); //array to hold all values and their count	
	for (var i = 0; i < pageItems.length; i++) {
		var it = 	pageItems[i];
		var val = it[attr];
		
		//eliminate empty values - TODO: Include as a miscellaneous option?
		if (val.length == 0) {
			if (!allowEmptyValues)
				continue;
			else 
				val = 'Other';
		}
		
		var count = (values[val]) ? values[val] : 0;
		values[val] = count + 1;
	}	

	return values;
}


/* 
	For the currently loaded pagingItem objects determine the number of items that have a value defined for the specified attribute. 
	
	@param attr The attribute to inspect
	@return Total number of values (regardless of uniqueness)
*/
function getItemValuesCount(attr) {
	var count = 0;
	for (var i = 0; i < window.items.length; i++) {
		var it = 	window.items[i];
		var val = it[attr];		
		if (val.length > 0) //do not include empty values 
			count++;
	}
	return count;
}

function getBooleanFilters(viewallthistime) {
	var html = '';

	html += getBooleanFilter('Sale Items', 'onsale', viewallthistime, itemsAreOnSale);
	var ssfilter = getBooleanFilter('Super Sale Items', 'showsupersalepricing', viewallthistime);
	if ( ssfilter.indexOf('DISABLED') <= -1 ) {
		html += ssfilter;
	}
//	html += getBooleanFilter('Free Return Address', 'freera', viewallthistime);
	html += getBooleanFilter('Top Sellers', 'topseller', viewallthistime);
	html += getBooleanFilter('What\'s New', 'newitem', viewallthistime);
	html += getBooleanFilter('Quick Ship', 'quickship', viewallthistime);
	html += getBooleanFilter('InvitationBox Green', 'green', viewallthistime);
	//html += getBooleanFilter('Free Return Address Printing', 'freera', viewallthistime);
	
	if (html) { //has boolean filters
		//html = '<ul>' + html + '</ul>';
		//html = getResetAllOptionsLink(viewallthistime) + html;
		html = '<table cellpadding=0 cellspacing=0 width="100%" class="filterBorder"><tr><td><table border=0 cellpadding=0 cellspacing=0 width="100%"><tr class=featureFilter><td class=titleCell>Filter By Feature</td></tr>' + html + '</table></td></tr></table>';
	}
	
	return html;
}

/***********************************************************************************************************	  
	Generate HTML to control boolean style filters (on/off) to be appended to HTML unordered
	list.
	 
	@param label - Label to display for this filter
	@param attr - The handle/reference to the attribute which will be filtered (by default this is the 
							 same as the property in the pagingItem object)
	@param viewallthistime - Boolean to indicate whether "View All" mode is applied rather than view by page
	@param itemsHaveBooleanValueCallback - If a more complex filter is required (such as items on sale which
																				filter on multiple attributes) the attr will NOT be the same as the 
																				pagingItem property and will define a callback function 
																				to determine filter applicability
	@return HTML to add to the <ul> list																					
**********************************************************************************************************/	 
function getBooleanFilter(label, attr, viewallthistime, itemsHaveBooleanValueCallback) {
	var html = '';
	var num;
	
	if (!itemsHaveBooleanValueCallback)
		itemsHaveBooleanValueCallback = itemsHaveBooleanValue; //default implementation
		
	num = itemsHaveBooleanValueCallback(attr);
	if (_pagingState.filters[attr]) { //this filter is already defined
		html += '<tr><td class=filterCell><input type=checkbox class="filterBox" CHECKED onClick="applyFilter(\'' + attr + '\', \'All\',' + viewallthistime + ');">&nbsp;<a class="'+attr+'Filter" href="javascript:applyFilter(\'' + attr + '\', \'All\',' + viewallthistime + ');">' + label + ' (' + num + ')</a></td></tr>';
	}	else {
		//for a given attr check to make sure the pagingItem objects contain both true and false conditions
		//get the number of items that match the TRUE condition	 - TODO - rethink for selections (item set will be filtered to one condition)
		num = (typeof(num) == 'undefined') ? 0 : num;
		if (num > 0) {
			html += '<tr><td class=filterCell><input id="cb'+attr+'" type=checkbox class="filterBox" onClick="applyFilter(\'' + attr + '\', true,' + viewallthistime + ');">&nbsp;<a class="'+attr+'Filter" href="javascript:applyFilter(\'' + attr + '\', true,' + viewallthistime + ');">' + label + ' (' + num + ')</a></td></tr>';		
		} else {
			html += '<tr><td class=filterCell><input id="cb'+attr+'" type=checkbox class="filterBox" DISABLED>&nbsp;' + label + ' (' + num + ')</td></tr>';		
		}
	}
	
	return html;
}
	
/************************************************************************************************************	   
	For a the currently loaded pagingItem objects determine whether both true and false conditions exist
	for the specified attribute. If so return the number of true values.
	
	@param attr The attribute to inspect
	@return number of TRUE values
	
************************************************************************************************************/
function itemsHaveBooleanValue(attr) {		
	var values = getItemValues(attr);
	
	if (assocArraySize(values) == 0) {
		return 0;
	}
	return values[true];	
}

function itemsAreOnSale() {
	//the following would be the simplest implementation but the count may be off if both attribute conditions are true
	//return itemsHaveBooleanValue('showsalepricing') + getItemValuesCount('saleprice'); //
	
	//ergo we must explicitly find the count
	var count = 0;
	
	for (var i = 0; i < window.items.length; i++) {
		var it = 	window.items[i];
		if (isSaleItem(it))
			count++;
	}	
	
	return count;
}

function getTopAttrValues(arr,attr) {
	attributeLimiter = 10; //number of items to show when filter is crowded	-- default value
	if (attr == 'theme') attributeLimiter = 10;
	if (attr == 'brand') attributeLimiter = 100;
	var newArr = new Array();
	var i = 0;
	
	arr = assocArraySort(arr, numericCompareValueDesc);	
	
	for (var key in arr) {
		if (i++ >= attributeLimiter)
			break;
		newArr[key] = arr[key];
	}
	return newArr;
}

/*********************************************************
					ARRAY UTILITY FUNCTIONS
 *********************************************************/
function isArray(obj) {
   return (obj.constructor.toString().indexOf("Array") != -1);
}


function assocArraySize(arr) {
	var l = 0;
	for (var k in arr) {
		l++;
	}
	return l;
}

function ksort(arr) {
	/* take an assoc array and return an index of sorted keys */
	//return convertAssocToKeyArray(arr).sort(alphaCompare);
	
	//or just return the assoc array sorted (better)
	return assocArraySort(arr, alphaCompareKey);
}

/* return assoc array sorted by value */
function vsort(arr, compareFunction) {
	return convertAssocToKeyArray(arr, true).sort(compareFunction);
}


function assocArraySort(aInput, compareFunction) {
	//convert to multi-dim indexed array and sort
	var aTemp = [];
	for (var sKey in aInput)
		aTemp.push([sKey, aInput[sKey]]);
	
	
	//sort the multi indexed array
	if (!compareFunction)
		compareFunction = function () { return arguments[1][1] > arguments[0][1]}
	aTemp.sort(compareFunction);

	//convert back to an assoc array
	var aOutput = [];
	for (var nIndex = aTemp.length - 1; nIndex >=0; nIndex--)
		aOutput[aTemp[nIndex][0]] = aTemp[nIndex][1];
		
	return aOutput;
}

function alphaCompare(a, b) {
	var A = a.toLowerCase();
	var B = b.toLowerCase();
	if (A < B) return -1;
	if (A > B) return 1;
	return 0;
}

function alphaCompareKey(a, b) {
	var A = a[0].toLowerCase();
	var B = b[0].toLowerCase();
	//console.log("A=%s, B=%s", A, B);
	if (A < B) return 1;
	if (A > B) return -1;
	return 0;
}

function numericCompareAsc(a, b) {
	return a - b;
}

function numericCompareDesc(a, b) {
	return b - a;
}

function numericCompareValueAsc(a, b) {
	return b[1] - a[1];
}

function numericCompareValueDesc(a, b) {
	return a[1] - b[1];
}

/* convert an associative array to an indexed array of keys by default
	(slight misnomer)
	@arr - array to convert
	@value - boolean indicating whether values should be returned in the array instead
*/
function convertAssocToKeyArray(arr, value) {
	var newArr = new Array();
	for (var key in arr)
	{
		//console.log(arr[key]);
		newArr[newArr.length] = (value) ? arr[key] : key; 
	}		
	return newArr;
}

function loadjscssfile(filename, filetype){
 if (filetype=="js"){ //if filename is a external JavaScript file
  var fileref=document.createElement('script')
  fileref.setAttribute("type","text/javascript")
  fileref.setAttribute("src", filename)
 }
 else if (filetype=="css"){ //if filename is an external CSS file
  var fileref=document.createElement("link")
  fileref.setAttribute("rel", "stylesheet")
  fileref.setAttribute("type", "text/css")
  fileref.setAttribute("href", filename)
 }
 if (typeof fileref!="undefined")
  document.getElementsByTagName("head")[0].appendChild(fileref)
}

function getParameterByName( name ) {
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}

