/* ShopNav object definition
	Used on all pages of the QuickerTek website. Write() method provides direct
	access to the page to overwrite content. Essential for product-central
	design.
	
   Cookie object defintion
   	Used primarily to hold information for ShopNav object. Exposing data in this 
   	way improves the overall stateless feel of the site. Included here as it will 
   	appear on all pages including the ShopNav object (which is all pages).
	
	Index
	==========
	[ShopNav object] ShopNav (XmlDocument xml)
		Constructor. Accepts the responseXML property of an [HTTP Request object] 
		as its data argument and then parses the data as needed to produce public 
		fields. Methods included to print as HTML, select alternate Category 
		configurations and print Product information to the page.
	[ShopNav object].writeTo (string whereOnPage, string whichLevel)
		Places the ShopNav object on a page.
	[ShopNav object].selectcategory (string category)
		OnSelect event handle. Accepts the currently selected category and loads 
		its Product elements into memory as the SelectedCategory property
	string [ShopNav object].bannerElement (string name, string type)
	[ShopNav object].selectproduct (string product)
	[ShopNav object].shiftIndex (int dir)
	
	TODO
	==========
	Animate Menu...fade out slide in
	*/
	
// Constants
var SHOPNAV_DIV = "shopnav";
var PRODUCT_DIV = "printProductInfo";
	
// [ShopNav object] ShopNav (XmlDocument xml)
function ShopNav (xml, isdirect) {	
 	this.$xml = xml; // Store XML in case mutation is necessary
 	// Select <category> elements
 	var categories = this.$xml.getElementsByTagName ("category");
 	// Public Members
 	this.Categories = new Array();
 	this.SelectedCategory = null; // Holds the Product objects
 	this.SelectedProduct = null; // Holds Product Data
 	this.Start	= 0; // Notes starting index
 	this.Length	= 4; // Available length of ShopNav
 	// load cookie
 	var m_cookie = new Cookie(document,COOKIE_NAME);
 	m_cookie.load();
 	// Iterate <category> elements into Categories property
 	for (var cat = 0; cat < categories.length; cat++) {
 		if (categories[cat].nodeType == 1) {
  			// Append a new [ShopCategory object] into this.Categories Member
  			var xproducts = null;
  			if (m_cookie.SelectedCategory!=""&&
  				categories[cat].getAttribute("name")==m_cookie.SelectedCategory) {
	  			var xproducts = categories[cat].getElementsByTagName("product");
	  		}
  			var n_Category = new ShopCategory(categories[cat],xproducts);
  			if(xproducts!=null) this.SelectedCategory = n_Category;
			this.Categories.push(n_Category);
 		}
 	}
	// Re-index categories based on ID attribute of <category>
	if (this.Categories.length > 0) { // Be sure no error occured
		var newOrder = new Array (this.Categories.length);
		for (var cat = 0; cat < this.Categories.length; cat++) {
			var intIndex = this.Categories[cat].ID;
//			alert(intIndex);
			newOrder[--intIndex] = this.Categories[cat];
		} this.Categories = newOrder; // reset this.Categories
	}
 }

// [ShopNav object].writeTo (string whereOnPage, bool page)
 ShopNav.prototype.writeTo = function (whereOnPage, pfla) {
 	// Create container element
// 	var snElement = document.createElement ('div');
 	var snElement = document.getElementById(whereOnPage);
 	while (snElement.hasChildNodes()) {
 		// Fade out
// 		Fade(snElement.childNodes[0].id);
	 	snElement.removeChild(snElement.childNodes[0]);
	 }
	// If a product has been selected
 	if (this.SelectedProduct != null) {
 		// Icon Tile
 		var prodElement = this.bannerElement (this.SelectedProduct.name, "product", this.SelectedProduct.Name, true);
 		prodElement.style.position = "relative";
 		prodElement.style.opacity = '1';
	    prodElement.style.filter = 'alpha(opacity = 100)';
	    prodElement.FadeState = 2;
 		// Alter action of Product element
 		var strOnclick	 = "new ShopNav(INVENTORY_XML).selectcategory('";
 		strOnclick		+= this.SelectedProduct.category+"')";
 		prodElement.setAttribute("onclick", strOnclick);
// 		alert(strOnclick);
 		// Fade In
 		snElement.appendChild (prodElement);
 		// Buy Tile
 		var buyElement	= document.createElement ('div');
 		buyElement.id	= "productselect";
 		buyElement.style.overflow = "hidden";
 		buyElement.style.position = "relative";
 		buyElement.style.opacity = '0';
	    buyElement.style.filter = 'alpha(opacity = 0)';
	    buyElement.FadeState = -2;
 		// Add a title to the Buy Tile
 		var buyTitleElement = document.createElement ('strong');
 		buyTitleElement.style.paddingLeft = "5px";
 		buyTitleElement.innerHTML = "Buy " + this.SelectedProduct.Name;
 		buyElement.appendChild (buyTitleElement);

 		// Add Price List
 		var priceList = document.createElement ('ul');
 		priceList.className = "noBullet";
// 		priceList.style.cssFloat = "left";
 		// Iterate price points into list
 		for (var cost = 0; cost < this.SelectedProduct.costs.length; cost++) {
// 		for (cost in this.SelectedProduct.costs) {
 			var pricePoint = document.createElement ('li');
 			pricePoint.style.paddingLeft = "5px";
 			if (this.SelectedProduct.costs.length > 1) {
	 			// Attach onClick event
	 			var strOnclick	= "onCostClick ('";
	 			strOnclick		+= this.SelectedProduct.costs[cost].id;
	 			strOnclick		+= "','";
	 			strOnclick		+= this.SelectedProduct.costs[cost].name;
	 			strOnclick		+= "','";
	 			strOnclick		+= this.SelectedProduct.costs[cost].value;
	 			strOnclick		+= "','";
	 			strOnclick		+= this.SelectedProduct.costs[cost].weight;
	 			strOnclick		+= "')";
	 			pricePoint.setAttribute ("onclick", strOnclick);
	 			// enable rollover effect
	 			pricePoint.className = "roll";
	 		}
 			pricePoint.innerHTML = this.SelectedProduct.costs[cost].name;
 			// Add price point to list
 			priceList.appendChild (pricePoint);
 		}
 		// Add list to Buy Element
 		buyElement.appendChild (priceList);
 		// Add Price Element
 		var priceDiv = document.createElement ('div');
 		priceDiv.style.paddingLeft = "5px";
 		priceDiv.style.cssFloat = "left";
 		priceDiv.id = "price";
 		// Append price
 		buyElement.appendChild(priceDiv);
 		// Add Buy Button
 		var buyButton = document.createElement ('div');
 		buyButton.id = "buy";	// Imperative for shopping cart hook up
// 		buyButton.style.cssFloat = "right";
 		// Append Buy Button to price element
 		buyElement.appendChild(buyButton);
 		// Actual shopping cart hook up
 		var sCartForm = document.createElement ('form');
 		sCartForm.id = (strCartFormId) ? strCartFormId : "cart";
 		sCartForm.action = "https://intuitivesecure.com/uCart/uCart.php";
 		sCartForm.method = "POST";
// 		sCartForm.target = "_blank";
 		// Append shopping cart hook up
 		buyElement.appendChild(sCartForm);
 		// Fade In
 		snElement.appendChild (buyElement);
 		// Phone Sales Tile
 		var phonEl = document.createElement ('div');
 		phonEl.className = "tile";
 		phonEl.id = "phoneshop";
 		phonEl.style.position = "relative";
 		phonEl.style.opacity = '0';
	    phonEl.style.filter = 'alpha(opacity = 0)';
	    phonEl.FadeState = -2;
 		// Add Image
 		var iphonEl = document.createElement ('div');
	 	iphonEl.style.position = "relative";
	 	iphonEl.style.background = "url(images/phone.png) no-repeat";
	 	iphonEl.style.backgroundPosition = "-2px -1px";
	 	iphonEl.style.margin = "3px auto";
	 	iphonEl.style.height = "67px";
	 	iphonEl.style.width = "64px";
	 	phonEl.appendChild(iphonEl);
	 	// Add Call text
	 	var tphonEl = document.createElement('div');
	 	tphonEl.innerHTML = "1 (866) 691-1585";
	 	phonEl.appendChild(tphonEl);
 		// Fade In
 		snElement.appendChild (phonEl);
 		// Store Location Tile
 		var storEl = document.createElement ('div');
 		storEl.className = "tile";
 		storEl.id = "storeshop";
 		storEl.style.position = "relative";
 		storEl.style.opacity = '0';
	    storEl.style.filter = 'alpha(opacity = 0)';
	    storEl.FadeState = -2;
 		storEl.setAttribute('onclick', "location.href='resellers.html'");
 		var istorEl = document.createElement ('div');
	 	istorEl.style.position = "relative";
	 	istorEl.style.background = "url(images/maps.png) no-repeat";
	 	istorEl.style.backgroundPosition = "-2px -1px";
	 	istorEl.style.margin = "3px auto";
	 	istorEl.style.height = "67px";
	 	istorEl.style.width = "64px";
	 	storEl.appendChild(istorEl);
	 	// Add Resellers Text
	 	tstorEl = document.createElement('div');
	 	tstorEl.innerHTML = "Find it at Retail";
	 	storEl.appendChild(tstorEl);
 		// Fade In
 		snElement.appendChild (storEl);
 		// Arrow
 		var strOnclick	 = "new ShopNav(INVENTORY_XML).selectcategory('";
 		strOnclick		+= this.SelectedProduct.category+"')";
 		mkIndexShiftCtl(snElement, strOnclick);
		//HACK:For the one
		//if (this.SelectedProduct.costs.length == 1) {
			// there can be only one!
			onCostClick (this.SelectedProduct.costs[0].id, this.SelectedProduct.costs[0].name, this.SelectedProduct.costs[0].value, this.SelectedProduct.costs[0].weight);
		//}
 	}
 	// Check if a category has been selected
 	else if (this.SelectedCategory != null) {
// 		alert(this.SelectedCategory.Products.length);
 		// Append category element
 		var scatElement = this.bannerElement (this.SelectedCategory.Name, "category");
// 		scatElement.style.position = "relative";
 		scatElement.style.opacity = '1';
	    scatElement.style.filter = 'alpha(opacity = 100)';
	    scatElement.FadeState = 2;
 		// Alter action of Category element
 		var strOnclick = "var c = new Cookie(document,COOKIE_NAME);c.load();";
 		strOnclick += "c.SelectedCategory='';c.Start=0;c.store();";
 		strOnclick += "new ShopNav(INVENTORY_XML).writeTo(SHOPNAV_DIV);";
 		scatElement.setAttribute("onclick", strOnclick);
 		// Fade In
 		snElement.appendChild(scatElement);
 		// Append product elements
// 		alert(this.SelectedCategory.Products.length);
 		for (var prod = this.Start; prod < this.SelectedCategory.Products.length; prod++) {
 			// Cut for this.Length
 			var iLimit = parseInt(this.Start) + parseInt(this.Length);
// 			alert(iLimit);
 			if (prod < iLimit) {
	 			var prodElement = this.bannerElement (this.SelectedCategory.Products[prod].name, "product", this.SelectedCategory.Products[prod].Name);
				// Establish new left position
				var cWidth	= parseInt(prodElement.style.width);
				var cMargin	= parseInt(prodElement.style.marginLeft);
				var prodPP	= prod - parseInt(this.Start) + 1;
				// Set start point
				prodElement.style.left = ((cWidth + cMargin) * prodPP) + "px"; 
//				alert(prodElement.style.left);
	 			// Fade In
	 			snElement.appendChild (prodElement);
	 		} else { break; }
 		}
 		// Allow for displayed index shifting
 		if (this.SelectedCategory.Products.length > parseInt (this.Length)) {
 			// Forward navigation onclick
 			var strOnclickF = "new ShopNav(openXml (\'";
			strOnclickF += XML_URI;
			strOnclickF += "\')).shiftIndex(1)";
			// Backward navigation onclick
 			var strOnclickB = "new ShopNav(openXml (\'";
			strOnclickB += XML_URI;
			strOnclickB += "\')).shiftIndex(2)";
 			// Add Index Shifter
 			if (this.Start == 0) { // At beginning, don't need back
 				strOnclickB = null;
 			}
 			var inext = parseInt(this.Start) + parseInt(this.Length);
 			if (inext >= this.SelectedCategory.Products.length) { // At end, don't need front
 				strOnclickF = null;
 			}
 			mkIndexShiftCtl(snElement, strOnclickF, strOnclickB);
 		}
 	}
  	else if (this.Categories != null) {
// 		var posLeft = 0;
 		for (var cat = this.Start; cat < this.Categories.length; cat++) {
// 			alert("Element "+cat+" is "+this.Categories[cat].Name);
 			var cName = this.Categories[cat].Name;
 			if (pfla) { cName += "_" + pfla; }
 			var catElement = this.bannerElement (cName, "category");
 			if (pfla) { // Change if used for Shop QuickerTek
 				// Swap elements
 				var holdCatElement = catElement;
 				holdCatElement.id = pfla;
 				holdCatElement.style.cssFloat = "none";
				catElement.style.position = "relative";
				catElement.style.opacity = '1';
				catElement.style.filter = 'alpha(opacity = 100)';
 				// Add text description
 				var txt = document.createElement("div");
 				txt.innerHTML = this.Categories[cat].Info[2];
 				// Reset and load up catElement
 				catElement = document.createElement("div");
 				catElement.style.cssFloat = "left";
 				catElement.style.width = "110px"
 				catElement.style.marginLeft = "20px";
				catElement.FadeState = 2;
 				catElement.appendChild(holdCatElement);
 				catElement.appendChild(txt);
 			} else {
	 			// Establish new left position
				var cWidth = parseInt(catElement.style.width);
				var cMargin = parseInt(catElement.style.marginLeft);
				// Set start point
				catElement.style.left = ((cWidth + cMargin) * cat) + "px"; 
			}
 			snElement.appendChild (catElement);
 		}
 	}
 	// Add Spacer
 	var spacer = document.createElement ('div');
 	spacer.className = "clear";
 	snElement.appendChild (spacer);
	// Fade In
	for (var f = 0; f < snElement.childNodes.length; f++) {
		if (snElement.childNodes[f].FadeState == -2) {
			Fade(snElement.childNodes[f].id,null,1);
		}
	}
 }

// [ShopNav object].selectcategory (string category)
 ShopNav.prototype.selectcategory = function (category) {
 	// Open Cookie
	var m_cookie = new Cookie (document, COOKIE_NAME);
	m_cookie.load ();
	// Load default
	if (category == null) { category = m_cookie.SelectedCategory; }
 	for (var cat = 0; cat < this.Categories.length; cat++) {
 		if (this.Categories[cat].Name == category) {
 			// Conditionally update cookie
 			if (m_cookie.SelectedCategory != category) {
	 			m_cookie.SelectedCategory = category;
	 			m_cookie.Start = 0;
	 		}
			// refresh xml
			var xproducts = INVENTORY_XML.getElementsByTagName("category");
			// find category
			for (var xcat = 0; xcat < xproducts.length; xcat++) {
				if (xproducts[xcat].getAttribute("name") == category) {
					xproducts = xproducts[xcat].getElementsByTagName("product");
					break;
				}
			}
	 		this.SelectedCategory = new ShopCategory(this.Categories[cat], xproducts);
//	 		this.SelectedCategory = new ShopCategory (this.Categories[cat], pxml);
	 		// Check Start index against products length
	 		if (this.SelectedCategory.Products.length < parseInt (this.Start)) {
	 			m_cookie.Start = parseInt (this.Start) - parseInt (this.Length);
	 		}
	 		//HACK: clear product selection for persistence
 			m_cookie.SelectedProduct = "";
	 		m_cookie.store ();
	 		this.Start = m_cookie.Start;
 			 // Print to screen
 			this.writeTo (SHOPNAV_DIV);
 			document.title = "Shop " + this.SelectedCategory.Name;
 			
 			break;
 		}
 	}
 }
 
// HtmlElement mkIndexShiftCtl(HtmlElement elem, string fonclick, string bonclick)
 function mkIndexShiftCtl(elem, fonclick, bonclick) {
 	// Index decrementor
	 if (bonclick != null) {
		var bkElement = document.createElement('div');
		bkElement.id = "arrow";
		bkElement.style.position = "absolute";
		bkElement.style.backgroundPosition = "0px 0px";
		var bsp = 10;
		if (elem.hasChildNodes()) {
			for (var sp = 0; sp < elem.childNodes.length; sp++) {
				bsp += parseInt(elem.childNodes[sp].style.width);
				bsp += parseInt(elem.childNodes[sp].style.marginLeft);
			}
		}
		bkElement.style.left = bsp + "px";
		// Navigation onclick hookup
		bkElement.setAttribute("onclick", bonclick);
		// Rollover effect
		var strOnover = "this.style.backgroundPosition='0px -33px'";
		bkElement.setAttribute("onmouseover", strOnover);
		var strOnout = "this.style.backgroundPosition='";
		strOnout += bkElement.style.backgroundPosition + "'";
		bkElement.setAttribute("onmouseout", strOnout);
		elem.appendChild(bkElement);
	}
	// Index incrementor
	if (fonclick != null) {
		var fwdElement = document.createElement('div');
		fwdElement.id = "arrow";
		fwdElement.style.position = "absolute";
		fwdElement.style.backgroundPosition = "-38px 0px";
		if (bonclick == null) {
			//fwdElement.style.marginLeft = "10px"; //HACK
			fwdElement.style.left = "585px";
		} else { fwdElement.style.left = "622px"; }
		// Navigation onclick hookup
		fwdElement.setAttribute("onclick", fonclick);
		// Rollover effect
		var strOnover = "this.style.backgroundPosition='-38px -33px'";
		fwdElement.setAttribute("onmouseover", strOnover);
		var strOnout = "this.style.backgroundPosition='";
		strOnout += fwdElement.style.backgroundPosition + "'";
		fwdElement.setAttribute("onmouseout", strOnout);
		elem.appendChild(fwdElement);
	}
 }

// string [ShopNav object].bannerElement (string name, string type)
 ShopNav.prototype.bannerElement = function (name, type, write, noclick) {
 	var strImage, strTitle, strOnerror, strOnclick; // Element attributes
  	// <image src>
 	strImage	= name.replace (/[ .,']/gi, "_");
  	strImage = strImage.toLowerCase ();
 	if (type == "category") {
 		strImage = "categories/" + strImage;
 		//HACK:to rem
 		strTitle = "";
 	}
 	else if (type == "product") {
 		strImage += "/" + strImage + "_99";
 		//HACK:to rem
 		strTitle = name;
 	}
 	// Prepend images folder and extension
 	strImage = "images/" + strImage + ".png";
 	// Make banner element
 	if(name.lastIndexOf("_") > 0) { // No longer need _alt
 		name = name.substr(0, name.lastIndexOf("_"));
 	}
 	var banner = document.createElement ('div');
 	banner.className = "tile";
 	//HACK: add positioning
 	banner.style.width = "110px";
	banner.style.marginLeft = "5px";
 	banner.id = name;
 	//HACK: fade
 	banner.style.opacity = '0';
    banner.style.filter = 'alpha(opacity = 0)';
    banner.FadeState = -2;
 	// Hook onclick handler
	 if (!noclick) {
	 	strOnclick = "clickBannerElement(this,'" + type + "')";
	 	/*
	 	strOnclick += "new ShopNav (openXml (\'" + XML_URI + "\')).select";
	 	strOnclick += type;
	 	strOnclick += " (\'";
	 	strOnclick += name;
	 	strOnclick += "\')";
	 	*/
	 	banner.setAttribute ("onclick", strOnclick);
	 }
 	// Make image
 	var imgElement = document.createElement ('div');
 	imgElement.style.position = "relative";
 	imgElement.style.background	= "url(" + strImage + ") no-repeat";
 	imgElement.style.height = "99px";
 	// Add name
 	var spName = document.createElement('div');
 	spName.style.position = "absolute";
 	spName.style.bottom = "0";
 	spName.style.left = "0"
 	spName.style.width = "100%";
 	spName.style.textAlign = "center";
 	if (write) { name = write; }
 	spName.innerHTML = name;
 	imgElement.appendChild(spName);
 	// Attach <image> to <div> and return
 	banner.appendChild (imgElement);
 	//HACK: fade
 	/*
	banner.style.opacity = "0";
	banner.style.filter = "alpha(opacity = 0)";
	banner.FadeState = -2;
	*/
 	return banner;
 }

// [ShopNav object].selectproduct (string product)
ShopNav.prototype.selectproduct = function (product, noprint) {
	// Open Cookie
	var m_cookie = new Cookie (document, COOKIE_NAME);
	m_cookie.load ();
	// Check for loaded product
	if (m_cookie.SelectedProduct != product) {
		// Remove cookies
		// Deselect category and product
		m_cookie.SelectedProduct	= null;
		this.SelectedProduct		= null;
		m_cookie.SelectedCategory	= null;
		this.SelectedCategory		= null;
	}
	if (!this.SelectedCategory) { // Locate correct field
		var a_products = INVENTORY_XML.getElementsByTagName("product");
		var m_category = null; // will later hold category
		for (var p = 0; p < a_products.length; p++) {
			// Check each product in table
			if (a_products[p].nodeType==1 && a_products[p].getAttribute("name")==product) {
				m_category = a_products[p].getAttribute("category");
				break;
			}
		}
		// Set this.SelectedCategory or throw error
		if (m_category != null) {
			for (var c = 0; c < this.Categories.length; c++) {
				if (this.Categories[c].Name == m_category) {
					//HACK: get product info
					var xproducts = INVENTORY_XML.getElementsByTagName("category");
					for (var xcat = 0; xcat < xproducts.length; xcat++) {
						if (xproducts[xcat].getAttribute("name") == m_category) {
							xproducts = xproducts[xcat].getElementsByTagName("product");
							break;
						}
					}
			 		this.SelectedCategory = new ShopCategory(this.Categories[c], xproducts);
//					this.SelectedCategory = this.Categories[c];
					break;
				}
			}
		} else {
			alert("Serious Problems. Reset Cookie.");
			// Reset cookie
			// Reset ShopNav
			// Return
		}
	}
	for (var prod = 0; prod < this.SelectedCategory.Products.length; prod++) {
		var m_prod = this.SelectedCategory.Products[prod]; // Readability
		if (m_prod.name.toLowerCase () == product.toLowerCase ()) {
			// Store product reference
			this.SelectedProduct = this.SelectedCategory.Products[prod];
			this.writeTo (SHOPNAV_DIV);
			if (!noprint) { // Print to screen
				this.SelectedProduct.writeTo (PRODUCT_DIV);
				document.title = this.SelectedProduct.name;
			}
			// Add to Cookie
			m_cookie.SelectedProduct = product;
//					m_cookie.SelectedCategory = this.Categories[cat].Products[prod].category;
			//HACK: Ensure that the correct category is selected
//					this.SelectedCategory = this.Categories[cat];
			m_cookie.store ();
			break;
//alert("cookie");
		}
	}
//		}	
//	}
}

// [ShopNav object].shiftIndex (int dir)
ShopNav.prototype.shiftIndex = function (dir) {
	// Open Cookie
	var m_cookie = new Cookie (document, COOKIE_NAME);
	m_cookie.load ();
	if (m_cookie.Start) {
		this.Start = m_cookie.Start;
	}
	if (dir == 1) { // Forward
		this.Start = parseInt (this.Start) + parseInt (this.Length);
	}
	if (dir == 2) { // Backward
		if (parseInt (this.Start) > 0) {
			this.Start = parseInt (this.Start) - parseInt (this.Length);
		}
	}
	// Add to Cookie
	m_cookie.Start = this.Start;
	m_cookie.store ();
	// Rewrite ShopNav
	this.selectcategory (m_cookie.SelectedCategory);
}

/* [ShopCategory object] ShopCategory (XmlElement thisCategory, XmlElement products)
 	Holds Category elements from Xml */
 function ShopCategory (thisCategory, products) {
 	// Data Members
// 	alert (thisCategory);
 	this.ID			= "";
 	this.Name		= "";
 	this.Info		= null;
 	this.Features	= null;
 
 	if (thisCategory.nodeType) { 
	 	this.ID			= thisCategory.getAttribute("id");
	 	this.Name		= thisCategory.getAttribute("name");
	 	this.Info		= new Array(3);
	 	this.Info[0]	= thisCategory.getAttribute("desc");
	 	var thisInfo	= thisCategory.getElementsByTagName("info")[0];
	 	this.Info[1]	= thisInfo.getAttribute("title");
	 	this.Info[2]	= thisInfo.firstChild.data;
	 } else {
	 	this.ID		= thisCategory.ID;
	 	this.Name	= thisCategory.Name;
	 	this.Info	= thisCategory.Info;
	 }

	if (products) {
		// Add Products
	 	this.Products = new Array();
	 	// Load products
//	 	for (prod in products) {
	 	for (var prod = 0; prod < products.length; prod++) {
	 		// Check that item is an [object Element]
	 		if (products[prod].nodeType == 1) {
	 			// Push a new ShopCategory element into this.Products property
//	 			alert(products[prod]);
	 			this.Products.push(new Product (products[prod]));
	 		}
	 	}
	 	
	 	// re-index based on id #
		if (this.Products.length > 0) {
//			alert(this.Products.length);
			var newOrder = new Array(this.Products.length);
			for (var prod = 0; prod < this.Products.length; prod++) {
				var intIndex = this.Products[prod].id;
				newOrder[--intIndex] = this.Products[prod];
			}
			// reset this.Categories
			this.Products = newOrder;
//			alert(this.Products.length);
		}
	}
 }
 
/* [Cookie object] Cookie (Document document, string name, string hours)
   Args: document - document to which cookie is assigned
         name - required string to define cookie
         hours - optional expiry for cookie
   Prototype includes 3 methods:
   .store () - saves cookie
   .load () - opens cookie */
 function Cookie (document, name, hours) {
	this.$document = document;
	this.$name = name;
	
	if (hours) { // Set optional parameter
		this.$expiration = new Date ((new Date ()).getTime() + hours*3600000);
	} else { this.$expiration = null; }
	
	// Additional optional parameters can go here
 }

/* [Cookie object].store() method */
 Cookie.prototype.store = function () {
	var cookieval = "";
	
	for (var prop in this){
		// Ignore properties and methods
		if ((prop.charAt(0) == "$") || ((typeof this[prop]) == "function")) { continue; }
		// Concatenate ampersand if adding a cookie
		if (cookieval != "") { cookieval += "&"; }
		
		cookieval += prop + ":" + escape(this[prop]);
	}
	
	// Translate into cookie string
	var cookie = this.$name + "=" + cookieval;
	if (this.$expiration) {
		cookie += "; expires=" + this.$expiration.toGMTString();
	}
	// Additional optional parameters here
	
	this.$document.cookie = cookie;
 }

/* [Cookie object].load() method */
 Cookie.prototype.load = function () {
	// Get array of all pertinent cookies
	var allcookies = this.$document.cookie;
	if (allcookies == "") { return false; } // return error if no cookies
	
	var start = allcookies.indexOf(this.$name + "=");
	if (start == -1) { return false; } // return error if none of our cookies
	start += this.$name.length + 1; // Skip name and equals sign
	
	var end = allcookies.indexOf(";", start);
	if (end == -1) { end = allcookies.length; } // Run to end of cookie string if now delimeter
	var cookieval = allcookies.substring(start, end);
	
	// Split cookie name/value pairs into an array
	var a = cookieval.split("&");
	for (var i = 0; i < a.length; i++) {
		a[i] = a[i].split(":");
	}
	
	for (var i = 0; i < a.length; i++) {
		this[a[i][0]] = unescape(a[i][1]);
	}
	
	return true; // Signal success!
 }
 
// Animation functions....
 
// var TimeToFade = 1000.0;
var FadeTime = 750.0;
var moveEl = null;
var moveLevel = null;

// clickBannerElement(clickedEl,level)
function clickBannerElement(clickEl, level) {
	// Members
	moveLevel	= level;
	moveEl		= clickEl;
	shopEl		= moveEl.parentNode.childNodes;
	// Iterate ShopNav child Elements
	for (var rm = 0; rm < shopEl.length; rm ++) {
		// Skip the clicked element
		if (shopEl[rm].id != moveEl.id) {
			Fade(shopEl[rm].id);
		}
	}
	// Move the clicked element - Step 1 + Step 2
	animate(moveEl.id, 0, 0, 500, step2);
//	clickBannerElement2(clickEl.id, level);
}

// follow up to clickBannerElement()
function step2 () {
//	alert("step2="+this.el.id);
	var cShop = new ShopNav(INVENTORY_XML);
	switch (moveLevel) { 
		case "category" :
			cShop.selectcategory(moveEl.id);
			break;
		case "product" :
			cShop.selectproduct(moveEl.id);
			break;
		}
}
 
	/*
strOnclick = "new ShopNav (openXml (\'" + XML_URI + "\')).select";
strOnclick += type;
strOnclick += " (\'";
strOnclick += name;
strOnclick += "\')";
banner.setAttribute ("onclick", strOnclick);
	 	*/

//function fade(eid, callback)
function Fade(eid, callback, end)
{
  var el = document.getElementById(eid);
  // Escape if no element in document
  if (el==null) return;
  
  // Check end state
  if (end==1) { // FadeIn
  	// Set to invisible
  	el.FadeState		= -2;
  	el.style.opacity	= "0";
  	el.style.filter		= "alpha(opacity=0)";
  }
  if (end==-1) { // FadeOut
  	el.FadeState		= 2;
  	el.style.opacity	= "1";
  	el.style.filter		= "alpha(opacity=100)";
  }
     
  if(el.FadeState == null)
  {
    if(el.style.opacity == null 
        || el.style.opacity == '' 
        || el.style.opacity == '1')
    { // Already visible
      el.FadeState = 2;
    }
    else
    { // Not already visible
      el.FadeState = -2;
    }
  }
    
  if(el.FadeState == 1 || el.FadeState == -1)
  { // if changing state already
    el.FadeState = el.FadeState == 1 ? -1 : 1;
    el.FadeTimeLeft = this.FadeTime - el.FadeTimeLeft;
  }
  else
  { // already visible or invisible
    el.FadeState = el.FadeState == 2 ? -1 : 1;
    el.FadeTimeLeft = this.FadeTime;
    setTimeout("animateFade(" + new Date().getTime() + ",'" + eid + "',"+callback+")", 33);
  }
}
//function animateFade(lastTick, eid)
function animateFade(lastTick, eid, callback)
{  
  var curTick = new Date().getTime();
  var elapsedTicks = curTick - lastTick;
  
  var el = document.getElementById(eid);
 
  if(el.FadeTimeLeft <= elapsedTicks)
  {
    el.style.opacity = el.FadeState == 1 ? '1' : '0';
    el.style.filter = 'alpha(opacity = ' 
        + (el.FadeState == 1 ? '100' : '0') + ')';
    el.FadeState = el.FadeState == 1 ? 2 : -2;
    if (callback != null) callback(); // Callback
    return;
  }
 
  el.FadeTimeLeft -= elapsedTicks;
  var newOpVal = el.FadeTimeLeft/this.FadeTime;
  if(el.FadeState == 1)
    newOpVal = 1 - newOpVal;

  el.style.opacity = newOpVal;
  el.style.filter = 'alpha(opacity = ' + (newOpVal*100) + ')';
  
  setTimeout("animateFade(" + curTick + ",'" + eid + "',"+callback+")", 33);
}

// Generic animation function
//function animate(elementID, newLeft, newTop, newWidth, newHeight, time, callback)
function animate(elementID, newLeft, newTop, time, callback)
{
  var el = document.getElementById(elementID);
  if(el == null)
    return;
 
  var cLeft = parseInt(el.style.left);
  if (isNaN(cLeft))
  	cLeft = 0;
  var cTop = parseInt(el.style.top);
  if (isNaN(cTop))
  	cTop = 0;
//  var cWidth = parseInt(el.style.width);
//  var cHeight = parseInt(el.style.height);
  
  var totalFrames = 1;
  if(time > 0)
    totalFrames = time/40;

  var fLeft = newLeft - cLeft;
  if(fLeft != 0)
    fLeft /= totalFrames;
  
  var fTop = newTop - cTop;
  if(fTop != 0)
    fTop /= totalFrames;
    
  /*
  var fWidth = newWidth - cWidth;
  if(fWidth != 0)
    fWidth /= totalFrames;
  
  var fHeight = newHeight - cHeight;
  if(fHeight != 0)
    fHeight /= totalFrames;
    */
    
//  doFrame(elementID, cLeft, newLeft, fLeft, cTop, newTop, fTop, 
//      cWidth, newWidth, fWidth, cHeight, newHeight, fHeight, callback);
  doFrame(elementID, cLeft, newLeft, fLeft, cTop, newTop, fTop, callback);
}

//function doFrame(eID, cLeft, nLeft, fLeft, cTop, nTop, fTop, 
//    cWidth, nWidth, fWidth, cHeight, nHeight, fHeight, callback)
function doFrame(eID, cLeft, nLeft, fLeft, cTop, nTop, fTop, callback)
{
  var el = document.getElementById(eID);
  if(el == null)
    return;

  cLeft = moveSingleVal(cLeft, nLeft, fLeft);
  cTop = moveSingleVal(cTop, nTop, fTop);
//  cWidth = moveSingleVal(cWidth, nWidth, fWidth);
//  cHeight = moveSingleVal(cHeight, nHeight, fHeight);

  el.style.left = Math.round(cLeft) + 'px';
  el.style.top = Math.round(cTop) + 'px';
//  el.style.width = Math.round(cWidth) + 'px';
//  el.style.height = Math.round(cHeight) + 'px';
  
//  if(cLeft == nLeft && cTop == nTop && cHeight == nHeight 
//    && cWidth == nWidth)
//alert("cLeft="+cLeft+" nLeft="+nLeft);
  if(cLeft == nLeft && cTop == nTop)
  {
    if(callback != null)
      callback();
    return;
  }
    
//  setTimeout( 'doFrame("'+eID+'",'+cLeft+','+nLeft+','+fLeft+','+cTop+','
//      +nTop+','+fTop+','+cWidth+','+nWidth+','+fWidth+','+cHeight+','
//      +nHeight+','+fHeight+','+callback+')', 40);
	setTimeout(	'doFrame("'+eID+'",'+cLeft+','+nLeft+','+fLeft+','+cTop+','
				+nTop+','+fTop+','+callback+')', 40);
}

function moveSingleVal(currentVal, finalVal, frameAmt)
{
  if(frameAmt == 0 || currentVal == finalVal)
    return finalVal;
  
  currentVal += frameAmt;
  if((frameAmt > 0 && currentVal >= finalVal) 
      || (frameAmt < 0 && currentVal <= finalVal))
  {
    return finalVal;
  }
  return currentVal;
}