/* QuickerTek JavaScript Support Document v1.02
	
	***Revisions***
	v1.0
	v1.01
		Code clean up --	removed depricated elements
							clarified variable names
							revised comments
							added pseudocode to function abstracts
	v1.02
		Navigational features --
			Introduce categorical navigation in UI through refactor and update of XML
			This is done by creating a [ShopNav object]
				ShopNav accepts Response XML data from the [HTTP Request object]
				This is first parsed into Level 1: [ShopCategory objects]
				Next, when called, into Level 2: [ShopProduct objects]
			Move function
	v1.03
		Resolve some error handling shortcomings
		Introduce [Shopping Bar object]
		Code clean
	**Revisions***
	
	Index:
		// Constants
		string PROD_INVENTORY_URI
		
		// [Product object]
		[Product object] Product (string uri, string|int prod_name)
			v1.02	-	defined variable and default product images
						added cookie support
		[Product object].writeTo (HtmlDocument document, string whereOnPage)
		
		// [Does object]
		[Does object] Does (XmlElement thisDoes)
		[Does object].toString ()
		
		// [Cost object]
		[Cost object] Cost (XmlElement thisCosts)
		[Cost object].toString ()
		
		// [ShopNav object]
		[ShopNav object] ShopNav (XmlDocument xml)
		[ShopNav object].writeTo (string whereOnPage, string whichLevel)
		[ShopNav object].selectcategory (string category)
		[ShopNav object].selectproduct (string product)
		
		// [ShopCategory object]
		[ShopCategory object] ShopCategory (XmlElement thisCategory)
		[ShopCategory object].toString ()
		
		// [ShopProduct object]
		[ShopProduct object] ShopProduct (XmlElement thisProduct)
		[ShopProduct object].toString ()
		
		void PageLoad ()
		void onClick_SitePage (string page)
		
		//TODO:
			[X]	Hook up to shopping cart
			[X]	Expose products externally
				[?] Meta-Tags for individual products
				[-] More button
			[ ]	Editor tool
				[ ]	refactor file names
			[?]	Search bar
			=============================
			[X]	Resellers page
				[-] Add to inventory.xml
				[X]	iterate/place balloon and logos
				[X] shift balloons to delay disappear
				[X] URL connect
				[X] correct format
			=============================
			[v] Contact page...
			[ ] clean missing designs
				[v] Add buy toolbar
				[ ] Build Shop QTek and Category home pages
			[v] Features
			[ ] New FAQs
			[-] Media, press, etc.
			=============================
			[X] shift shop index buttons
			[X] Overlay product names
			=============================
			[ ] Handel random tile size "46px"
 */
 
// Constants
var COOKIE_NAME = "QuickerTek";
var INVENTORY_XML = null;
var FAQ_XML = null;
var PRESS_XML = null;
var COMM_XML = null;
 
/* [DL object] DL (XmlElement thisDl) */
function DL (thisDl) {
	if (thisDl.tagName == "item") {
		this.type = thisDl.getAttribute ("type");
		this.link = thisDl.getAttribute ("link");
		this.name = thisDl.firstChild.data;
	} else { window.alert("Needs to be an XML Element named \"downloads>item\". LOL!"); return false; }
}
 
/* [Does object] Does (XmlElement thisDoes)
	Holds a product blurb information picked from the passed XmlElement.
	Arguments:
		thisDoes = a snippet of XML DOM with data we need
	Properties:
		id = indexer for printing
		short = simple description of blurb
		long = full blurb */
 function Does (thisDoes) {
 	// Make sure we have the right information
 	if (thisDoes.tagName == "does") {
 		this.short = thisDoes.getAttribute("name");
 		this.long = thisDoes.firstChild.data;
 	} else {
 		window.alert("Needs to be an XML Element named \"does\". LOL!");
 		return false;
 	}
 	// Signal trés benecia!
 	return true;
 }
 
/* [Does object].toString ()
 	Method for testing stored data */
 Does.prototype.toString = function () {
 	// Empty string to exit as return
 	var strDoes = "";
 	strDoes += "<p><b>" + this.short + ":</b>";
 	strDoes += "&nbsp;" + this.long + "</p>"
 	// Escape with string
 	return strDoes;
 }
 
/* [Cost object] Cost (XmlElement thisCosts)
	Describes pricing option for products.
	Arguments:
		thisCosts = XML DOM containing the price points
	Properties:
		id = Sales Order number
		name = description of option
		value = price in USD */
 function Cost (thisCosts) {
 	// Be certain we've received the correct data block
 	if (thisCosts.tagName == "option") {
 		this.id = thisCosts.getAttribute("id");
 		this.name = thisCosts.getAttribute("name");
 		this.value = thisCosts.getAttribute("value");
 		var m_weight = thisCosts.getAttribute("weight");
 		this.weight = (m_weight) ? m_weight : "1.0";
 	} else {
 		window.alert("Please send an XML Element named \"option\". THx!");
 		return false;
 	}
 	// Signal success!
 	return true;
 }
 
/* [Cost object].toString ()
	Method for testing stored data */
 Cost.prototype.toString = function () {
 	var strCosts = ""; // Return string
 	
 	strCosts += "<p>If you want " + this.name;
 	strCosts += ", you'd order " + this.id;
 	strCosts += " for $" + this.value + ".</p>";
 	
 	return strCosts; // Send it out
 }
 
/* [Feature object] Feature (XmlElement feature) */
 function Feature (feature) {
 	// Name the feature
 	this.name = feature.getAttribute ('name');
 	// Title the feature
 	elTitle = feature.getElementsByTagName ('title');
 	this.title = new Array (elTitle.length);
 	for (var t =0; t<this.title;t++) {
// 	for (t in this.title) {
 		if (elTitle[t].nodeType == 1) {
 			this.title.push (elTitle[t].firstChild.data);
 		} //alert (this.title[t]);
 	}
 	this.desc = feature.getElementsByTagName('desc')[0].firstChild.data;
 }
 
// [ProductSpecs object] ProductSpecs (XmlElement thisSpecs)
 function ProductSpecs (thisSpecs) {
 	// Public object Attributes
 	this.Ease			= "";
 	this.Includes		= new Array ();
 	this.Compatibility	= new Array ();
 	this.Weight			= "";
 	this.Dimensions		= new Array ();
 	this.OS				= new Array ();
 	this.TechInfo		= new Array ();
 
 	// Enter into Element
 	if (thisSpecs) {
 	var specs = thisSpecs.getElementsByTagName ("spec");
	 	for (var spec = 0; spec < specs.length; spec++) {
	// 	for (spec in specs) {
	 		// Check for NodeType
	 		if (specs[spec].nodeType == 1) {
			 	// Public attributes
			 	var thisType = specs[spec].getAttribute ("type");
			 	switch (thisType) {
			 		case "inst"	:
			 			this.Ease = specs[spec].firstChild.data;
			 			break;
			 		case "incl"	:
			 			this.Includes.push (specs[spec].firstChild.data);
			 			break;
			 		case "sppt"	:
			 			this.Compatibility.push (specs[spec].firstChild.data);
			 			break;
			 		case "wght"	:
			 			this.Weight = specs[spec].firstChild.data;
			 			break;
			 		case "dim"	:
			 			this.Dimensions.push (specs[spec].firstChild.data);
			 			break;
			 		case "os"	:
			 			this.OS.push (specs[spec].firstChild.data);
			 			break;
			 		case "tech"	:
			 			this.TechInfo.push (specs[spec].firstChild.data);
			 			break;
			 	}
			 }
	 	 }
	}
 	// defaults
  	this.Ease				= this.Ease=="" ? "none" : this.Ease;
 	this.Includes[0]		= this.Includes.length==0 ? "nothing" : this.Includes[0];
 	this.Compatibility[0]	= this.Compatibility.length==0 ? "none" : this.Compatibility[0];
 	this.Weight				= this.Weight=="" ? "none" : this.Weight;
 	this.Dimensions[0]		= this.Dimensions.length==0 ? "none" : this.Dimensions[0];
 	// you're brought back but you're running
 //	this.OS[0]				= this.OS.length==0 ? "Vista" : this.OS[0];
 	this.TechInfo[0]		= this.TechInfo.length==0 ? "none" : this.TechInfo[0];
 }
 
/* void PageLoad (string docUrl)
	Operations to load page */
 function PageLoad (){
 	// Copy an instance of the Inventory XML
	// 	var pageXml = openXml ("inventory.xml");
	var pageXml = openXml (XML_URI);
	INVENTORY_XML = pageXml;
	FAQ_XML = openXml("faq.xml");
 	// Get url for pagination
 	var docUrl	= document.URL;
 	var qUrl 	= document.URL;
	// print or no?
//	var noprint = true;

	//HACK: default to "home"
	if (docUrl.lastIndexOf (".html") < 0) { docUrl = "shop"; }
	else {
 	// Make general page layout
 	docUrl = docUrl.substring ((docUrl.lastIndexOf ("/")+1), docUrl.lastIndexOf (".html"));
 	}
 	// Load cookie variables
 	var page_cookie = new Cookie(document, COOKIE_NAME);
 	page_cookie.load();
 	// Get Main Data Entry section
 	var MAINELEM = document.getElementById(PRODUCT_DIV);
	// Write initial page content
 	switch (docUrl) {
 		// Press page
 		case "press":
 		/*
 		<div class="boxContentBody">
 			<div id="postman"></div>
 			<div class="column" style="border:none;">
 				<div style="font-size:30px">2009 Product Announcements</div>
 			</div>
 			<div class="column">
 				<div style="float:left">11/30/09</div>
 				<div style="float:left">&lt; BUTTON &gt;</div>
 				<div style="float:left">Apple Juicz Solar Charger for all MacBooks</div>
 			</div>
 		</div>
 		*/
 			// container element
 			var press_box = document.createElement("div");
 			press_box.className = "boxContentBody";
 			// send me a letter from b
 			var postman = document.createElement("div");
 			postman.id = "postman";
 			press_box.appendChild(postman);
 			// open and parse XML
 			var years = openXml("press.xml").getElementsByTagName("year");
 			for (var y = 0; y < years.length; y ++) {
 				var m_year = document.createElement("div");
 				m_year.className = "column";
 				m_year.style.fontSize = "30px";
 				m_year.style.marginTop = "20px";
 				m_year.innerHTML = "Announcements for " + years[y].getAttribute("is");
 				press_box.appendChild(m_year);
 				press_box.appendChild(document.createElement("br"));
 				var rels = years[y].getElementsByTagName("release");
	 			for (r = 0; r < rels.length; r++) {
	 				if (rels[r].nodeType==1) {
	 					//MAINELEM.innerHTML += rels[r].getAttribute("title");
	 					var m_rel = document.createElement("div");
	 					m_rel.className = "column";
	 					// date
	 					var m_relDate = document.createElement("div");
	 					m_relDate.style.cssFloat = "left";
	 					m_relDate.style.width = "50px";
	 					m_relDate.style.fontSize = "20px";
	 					m_relDate.style.textAlign = "right";
	 					m_relDate.innerHTML = rels[r].getAttribute("date");
	 					m_rel.appendChild(m_relDate);
	 					// button
	 					var m_relButton = document.createElement("div");
	 					m_relButton.style.cssFloat = "left";
	 					m_relButton.style.width = "58px";
	 					m_relButton.style.height = "18px";
	 					m_relButton.style.marginLeft = "10px";
	 					m_relButton.style.marginRight = "10px";
	 					m_relButton.style.cursor = "pointer";
	 					var rb_click = "window.open('";
	 					rb_click += rels[r].getElementsByTagName("link")[0].firstChild.data;
	 					rb_click += "')";
	 					m_relButton.setAttribute("onclick", rb_click);
	 					m_relButton.style.background = "url(images/pr-button.png) no-repeat";
	// 					m_relButton.innerHTML = "< BUTTON >";
	 					m_rel.appendChild(m_relButton);
	 					// title + link
	 					var m_relTitle = document.createElement("div");
	 					m_relTitle.style.cssFloat = "left";
	 					m_relTitle.style.fontSize = "15px";
	 					m_relTitle.innerHTML = rels[r].getElementsByTagName("title")[0].firstChild.data;
	 					m_rel.appendChild(m_relTitle);
	 					// add to displayed element
	 					press_box.appendChild(m_rel);
	 					press_box.appendChild(document.createElement("br"));
	 				}
	 			}
	 		}
 			// remove child nodes while they last!
 			while (MAINELEM.hasChildNodes()) {
 				MAINELEM.removeChild(MAINELEM.childNodes[0]);
 			}
 			MAINELEM.appendChild(press_box);
 			break;
 		
 		// FAQ page	
 		case "faq":
		/*
 			// limit
 			var lim = 1500;
 			var it = 0;
 			var boxBod = document.getElementById("faqs_go_here");
 			// Add Categories
 			var m_faq = FAQ_XML.getElementsByTagName("category");
 			for (var f = 0; f < m_faq.length; f++) {
 				// Add title
 				var c_title = document.createElement("div");
 				c_title.id = "column";
				c_title.style.width="380px";
				c_title.style.margin = "10px";
				c_title.style.cssFloat = "left";
				var tEl = document.createElement("strong");
				var atEl = document.createElement("a");
				atEl.innerHTML =  m_faq[f].getAttribute("name");
				tEl.appendChild(atEl);
 				c_title.appendChild(tEl);
 				boxBod.appendChild(c_title);
 				// Add questions
 				var q_faq = m_faq[f].getElementsByTagName("ask")[0];
// 				if (it<lim) {
// 				for (var q = 0; q < q_faq.length; q++) {
 					if (it<lim) {
 						var m_question = q_faq.getElementsByTagName("question")[0].firstChild.data;
 						var m_answer = q_faq.getElementsByTagName("answer")[0].firstChild.data
 						if (it+m_question.length>lim||it+m_answer.length>lim) {
 							// code
 							break;
 						}
	 					// Add question
	 					var askEl = document.createElement("div");
	 					askEl.id = "column";
	 					askEl.style.width = "380px";
	 					askEl.style.margin = "10px";
	 					askEl.style.cssFloat = "left";
	 					var qEl = document.createElement("div");
	 					var sqEl = document.createElement("strong");
	 					sqEl.innerHTML = m_question;
	 					qEl.appendChild(sqEl);
	 					askEl.appendChild(qEl);
	 					askEl.innerHTML += m_answer;
	 					boxBod.appendChild(askEl);
	 					// limit isht
	 					it += m_question.length + m_answer.length;
	 				}
//				}
//				}
 			}
 			
// 			MAINELEM.appendChild(boxBod);
			*/
			setFaq();
 			break;

 		// Resellers Page		 			
 		case "resellers":
			// Get Print location
			var rdat = openXml(SITE_CONFIG_URI).getElementsByTagName("site")[0];
			rdat = rdat.getElementsByTagName("resellers")[0];
			rdat = rdat.getElementsByTagName("reseller");
			// Append reseller info
			cartResellers(rdat, MAINELEM);
			// Make map with div
			var rmap = document.createElement('div');
			rmap.id = "resell_map";
			var irmap = document.createElement('img');
			irmap.src = "images/resell_map.png";
			irmap.style.width = "802px";
			irmap.style.height = "371px";
			irmap.useMap = "#resell";
			rmap.appendChild(irmap);
			MAINELEM.appendChild(rmap);
//			alert(laCarte.innerHTML);
/*
			var strResell = cartResellers (openXml ("site.xml").getElementsByTagName ("reseller"));
			strResell += "<div id=\"resell_map\">";
			strResell += "<img src=\"images/resell_map.png\"";
			strResell += " height=\"371px\" width=\"802px\" usemap=\"#resell\" />";
			strResell += "</div>";
			//strResell += cartResellers (openXml ("site.xml").getElementsByTagName ("reseller"));
			//printToPage ("page", cartResellers (openXml ("site.xml").getElementsByTagName ("reseller")), 1);penis
			printToPage (PRODUCT_DIV, strResell);
			*/
 			break;
 			
// 		Home Page
 		case "shop":
			// Add Productator to page
			var prodEl = document.createElement("div");
			prodEl.id = "printProductator";
			var tileEl = document.createElement("div");
			tileEl.style.marginTop = "25px";
			// News box
			var newEl = document.createElement("div");
/*
			newEl.style.cssFloat	= "left";
			newEl.style.width	= "254px";
			newEl.style.height	= "187px";
			newEl.style.padding	= "10px";
			newEl.style.overflow = "hide";
			newEl.style.marginRight = "10px";
			newEl.style.background = "url(images/random-tile-body.png) no-repeat";
*/
			newEl.className = "home_tile";
			newEl.id = "press_tile";
			newEl.style.cursor = "pointer";
			newEl.setAttribute("onclick","location='press.html'");
			// Set PRESS_XML
			PRESS_XML = openXml("press.xml");
			
			// Faqs
			var faqEl = document.createElement("div");
			faqEl.id = "faq_tile";
			faqEl.className = "home_tile";
			faqEl.style.cursor = "pointer";
			faqEl.setAttribute("onclick","location='faq.html'");
			// Set FAQ_XML
			FAQ_XML = openXml("faq.xml");
			
			// Make comments box
			var comEl = document.createElement("div");
			comEl.id = "com_tile";
			comEl.className = "home_tile";
			comEl.style.cursor = "pointer";
			comEl.setAttribute("onclick","location='#'");
			// Set COMM_XML
			COMM_XML = openXml("comments.xml");
			
			// Append
			MAINELEM.appendChild(prodEl);
			tileEl.appendChild(newEl);
			tileEl.appendChild(comEl);
			tileEl.appendChild(faqEl);
			MAINELEM.appendChild(tileEl);
			// Add content
			makePressComm();
			makeCustComm();
			makeFaqComm();
			// Add Productator
			var m_productator = new Productator();
			m_productator.writeTo(prodEl);
			break;
			
		 default:
		 	// blank page
		 break;
 	}
 	
 	// Build shopping navigation
 	var myShopNav = new ShopNav (pageXml);
 	// Check for passed selection 	
 	if (qUrl.indexOf ("?") > 0) {
 		qUrl = qUrl.substring (docUrl.indexOf ("?") + 1);
 		// check that it is a product
 		if (qUrl.indexOf ("product") >= 0) {
 			var stop = qUrl.length;
 			if (qUrl.indexOf ("&") > 0) {
 				stop = qUrl.indexOf ("&");
 			}
 			// read value
 			qUrl = qUrl.substring (qUrl.indexOf ("product"), stop);
 			// remove name
 			qUrl = qUrl.substring (qUrl.indexOf ("=") +1);
 			// replace spaces
 			qUrl = qUrl.replace (/%20/g, " ");
 			// lowerstring
	 		// call shopnav
	 		myShopNav.selectproduct (qUrl);
 		}
 	}
 	// Previous product selection
 	else if (page_cookie.SelectedProduct != null && page_cookie.SelectedProduct != "") {
 		myShopNav.selectproduct(page_cookie.SelectedProduct, true);
 	}
 	// Previous category selection
 	else if (page_cookie.SelectedCategory != null && page_cookie.SelectedCategory != "") {
 		myShopNav.selectcategory(page_cookie.SelectedCategory);
 	}
 	// Default to a clean ShopNav
 	else { myShopNav.writeTo (SHOPNAV_DIV); }
	/* Search the QuickerTek Cookie
		It consists of the Product cookie and the SitePage cookie. */
	var printProduct; // Default product to print
	var myDoc;
	var myTitle = "QuickerTek"; // Title string
	myTitle += " - Products";
	// Get config elements
	var siteConfig = openXml ("site.xml");
	// Add Site elements
	printToPage ("topnav", makeMainnav (siteConfig, docUrl));
	printToPage ("footerpad", makeFooter (siteConfig));
 }
 
/* [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!
 }