/********************************************************************
 * GLOBAL VARIABLES
 *******************************************************************/
 
/* XML-BASED VARIABLES */
var xmlDOM;
var xmlHTTP;

/* IMAGE DISPLAY VARIABLE */
var clearImageTimer = null;
var alternateColors = new Array();
var currentColor    = null;

/********************************************************************
 * CLASSES
 *******************************************************************/

/** PRODUCT OBJECT
 * Class definition using class creation from Prototype
 * framework that takes in XML for a product and sets
 * values for required fields within.
 *
 * @author: Randy Davis
 * @param: product - XML to define variables
 * @version: 1.6
 */

var Product = Class.create({
  initialize: function(product) {
    /* Set product object values */
    this.xml              = product;
    this.active           = xmlInfo(product, "active", 0);
    this.productId        = xmlInfo(product, "productId", 0);
    this.colorDescription = xmlInfo(product, "colorDescription", 0);
    this.description      = xmlInfo(product, "description", 0);
    this.colorId          = xmlInfo(product, "colorId", 0);
    this.thumbnail        = xmlInfo(product, "image", 0);
    this.name             = xmlInfo(product, "name", 0);
    this.wasPrice         = xmlInfo(product, "original", 0) == "no-sale" ? "" : xmlInfo(product, "original", 0);
    this.styleDescription = xmlInfo(product, "style", 0)+" "+xmlInfo(product, "colorId", 0);
    this.styleId          = xmlInfo(product, "style", 0);
    this.nowPrice         = xmlInfo(product, "sale", 0);
    this.salesText        = xmlInfo(product, "original", 0) != "no-sale" ? "SALE!" : "";
    this.onSale           = xmlInfo(product, "original", 0) == "no-sale" ? false : true;
    
    /* Loop through "details" */
    this.otherDetails = new Array();
    for (var i=0; i<xmlObject(product, "details").length; i++) {
      this.otherDetails[i] = xmlInfo(product, "details", i);
    }
    
    /* Loop through alternate colors and add to alternate colors array */
    this.colors = new Array();
    for (var i=0; i<xmlObject(xmlObject(product, "colors")[0], "color").length; i++) {
      this.colors[i] = xmlObject(xmlObject(product, "colors")[0], "color")[i];
    }
    
    /* Loop through skus and add to skus array */
    this.skus         = new Array();
    this.skuAvailable = new Array();
    for (var i=0; i<xmlObject(xmlObject(product, "sizes")[0], "size").length; i++) {
      this.skus[i] = xmlObject(xmlObject(product, "sizes")[0], "size")[i];
      this.skuAvailable[i] = xmlAttribute(xmlObject(xmlObject(product, "sizes")[0], "size")[i], "available");
    }
  },
  
  /** GET ALTERNATE COLOR XML VALUES
   * Gets the information for an alternative color
   * based on the supplied iterator. An array is
   * returned.
   *
   * @author: Randy Davis
   * @version: 1.15
   * @param: iterator - for functions to pull colors array values
   * @return: array with name, selected, productId, thumbnailUrl
   */
   
  getColorArray: function(iterator) {
    var colorArray = new Array();
    colorArray[0]  = this.getColorName(iterator);
    colorArray[2]  = this.getColorSelected(iterator);
    colorArray[1]  = this.getColorProductId(iterator);
    colorArray[3]  = this.getColorThumbnail(iterator);
    
    return colorArray;
  },
  
  /** GET NAME
   * Gets the alternate color name based on the supplied
   * iterator.
   *
   * @author: Randy Davis
   * @version: 1.15
   * @param: iterator - for colors array
   * @return: alternate color name
   */
   
  getColorName: function(iterator) {
    return this.colors[iterator].firstChild.nodeValue.replace("=AMPERSAND=", "&");
  },
  
  /** GET PRODUCTID
   * Gets the alternate color productId based on
   * the supplied iterator.
   *
   * @author: Randy Davis
   * @version: 1.15
   * @param: iterator - for colors array
   * @return: alternate color productId
   */
   
  getColorProductId: function(iterator) {
    return xmlAttribute(this.colors[iterator], "productId");
  },
  
  /** GET SELECTED VALUE
   * Gets the alternate color selected value based on
   * the supplied iterator.
   *
   * @author: Randy Davis
   * @version: 1.15
   * @param: iterator - for colors array
   * @return: if alternate color is selected
   */
  
  getColorSelected: function(iterator) {
    return xmlAttribute(this.colors[iterator], "selected");
  },
  
  /** GET THUMBNAIL IMAGE
   * Gets the alternate color thumbnail based on the
   * supplied iterator.
   *
   * @author: Randy Davis
   * @version: 1.15
   * @param: iterator - for colors array
   * @return: alternate color thumbnail image
   */
  
  getColorThumbnail: function(iterator) {
    return xmlAttribute(this.colors[iterator], "thumbnail");
  },
  
  /** GET ALTERNATE 
   * Gets the alternate color thumbnail based on the
   * supplied iterator.
   *
   * @author: Randy Davis
   * @version: 1.15
   * @param: iterator - for colors array
   * @return: alternate color thumbnail image
   */
  
  getSizeArray: function(iterator) {
    var sizeArray = new Array();
    sizeArray[0]  = this.getSizeText(iterator);
    sizeArray[1]  = this.getSizeSku(iterator);
    
    return sizeArray;
  },
  
  /** GET SIZE TEXT
   * Gets the alternate color size text based on
   * the supplied iterator
   *
   * @author: Randy Davis
   * @version: 1.15
   * @param: iterator - for skus array
   * @return: alternate color size text
   */
  
  getSizeText: function(iterator) {
    return this.skus[iterator].firstChild.nodeValue.replace("=AMPERSAND=", "&");
  },
  
  /** GET SIZE SKU
   * Gets the alternate color sku value based on
   * the supplied iterator
   *
   * @author: Randy Davis
   * @version: 1.15
   * @param: iterator - for skus array
   * @return: alternate color sku value
   */
  
  getSizeSku: function(iterator) {
    return xmlAttribute(this.skus[iterator], "sku");
  }
});


/** ADD ALTERNATE PRODUCT OBJECT
 * Class definition using class creation from Prototype
 * framework that a supplied productId and pulls product
 * XML from the database.  If pull is successful, a new
 * Product object is created and stored in the alternateColors
 * array and place [iterator]
 *
 * @author: Randy Davis
 * @version: 1.15
 * @param: productId - id of product to be loaded
 * @param: iterator - placement in alternateColors array
 */
 
var AlternateProduct = Class.create({
  initialize: function(productId, iterator) {
    this.productId = productId;
    this.iterator  = iterator;
    
    var url = "/store/results/fragments/productLookupXML.jsp?productId="+this.productId;
    new Ajax.Request(url, {
      method: 'get',
      onSuccess: function(response) {
        var xmlDOM = null;
        if (isIE()) {
          xmlDOM  = new ActiveXObject("Microsoft.XMLDOM");
          xmlDOM.loadXML(response.responseText);
        } else {
          var vParser = new DOMParser();
          xmlDOM = vParser.parseFromString(response.responseText, "text/xml");
        }
        var product = xmlObject(xmlDOM, "product")[0];
        alternateColors[iterator] = new Product(product);
      }
    });
  }
});

var CurrentProduct = Class.create({
  initialize: function(productId) {
    this.productId = productId;
    
    var url = "/store/results/fragments/productLookupXML.jsp?productId="+this.productId;
    new Ajax.Request(url, {
      method: 'get',
      onSuccess: function(response) {
        var xmlDOM = null;
        if (isIE()) {
          xmlDOM  = new ActiveXObject("Microsoft.XMLDOM");
          xmlDOM.loadXML(response.responseText);
        } else {
          var vParser = new DOMParser();
          xmlDOM = vParser.parseFromString(response.responseText, "text/xml");
        }
        var product = xmlObject(xmlDOM, "product")[0];
        currentColor = new Product(product);
      }
    });
  }
});


/********************************************************************
 * SHORTCUTS
 *******************************************************************/

/** REDIRECT PAGE
 * Redirect the current page to the page supplied
 * to the function.
 *
 * @author: Randy Davis
 * @version: 1.0
 */

function redirectPage(url) {
  window.location = url;
}

/** CHANGE CLASS ON MOUSEOVER
 * Used by onMouseOver and onMouseOut to change
 * the class of the object.
 *
 * @author: Randy Davis
 * @version: 1.0
 */

function changeMouseOverClass(objName, className) {
  addAttribute(objName, "class", className);
  addAttribute(objName, "className", className);
}


/** GET ELEMENT BY CLASS NAME
 * Retreive all elements from "node" with the
 * classname given.
 *
 * URL: http://snipplr.com/view/1696/get-elements-by-class-name/
 *
 * @author: Randy Davis 
 * @version: 1.0
 */

function getElementsByClassName(classname, nodeName) {
  node = !nodeName ? document.getElementsByTagName("body")[0] : $(nodeName);
  if(!node) node = document.getElementsByTagName("body")[0];
  var a = [];
  var re = new RegExp('\\b' + classname + '\\b');
  var els = node.getElementsByTagName("*");
  for(var i=0,j=els.length; i<j; i++)
    if(re.test(els[i].className))a.push(els[i]);
  return a;
}



/** SET VALUE
 * Set the object with id of "id" with the
 * value supplied.  If the value is "null"
 * then set value to "".
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function setValue(id, value) {
  $(id).innerHTML = value == "null" ? "" : value;
}



/********************************************************************
 * BROWSER FUNCTIONS
 *******************************************************************/

/** IS THIS IE?
 * If the browser is IE, then the following function will return
 * boolean true.
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function isIE() {
  return window.ActiveXObject;
}

/** IS THIS MOZILLA?
 * If the browser is Mozilla-based, then the following function
 * will return boolean true.
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function isMozilla() {
  return window.XMLHttpRequest;
}

/********************************************************************
 * AJAX
 *******************************************************************/

/** PREPARE AJAX
 * Sets the xmlDOM and xmlHTTP variables according to the browser
 * the user is on.  This removes the need to do a browser check/set
 * for the constants in AJAX.
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function prepAJAX() {
  if (isIE()) {
    xmlDOM  = new ActiveXObject("Microsoft.XMLDOM");
    xmlHTTP = new ActiveXObject("Microsoft.XMLHTTP");
  } else {
    xmlHTTP = new XMLHttpRequest();
  }
}


/********************************************************************
 * XML PARSING FUNCTIONS
 * Instead of having to use functions on a DOM object, the
 * following functions have been created.
 *******************************************************************/
 
/** NODE VALUE OF OBJECT
 * xmlInfo returns the nodeValue of the firstChild of the "number" tag
 * of tag "tag" in object "obj".
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function xmlInfo(obj, tag, number) {
  return obj.getElementsByTagName(tag)[number].firstChild.nodeValue.replace("=AMPERSAND=", "&");
}

/** OBJECT INSIDE OBJECT
 * xmlObject returns the object in tag "tag" in object "obj".
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function xmlObject(obj, tag) {
  return obj.getElementsByTagName(tag);
}

/** ATTRIBUTE OF OBJECT
 * xmlAttribute returns the value of attribute "attribute" in
 * object "obj"
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function xmlAttribute(obj, attribute) {
  return obj.getAttribute(attribute);
}



/********************************************************************
 * DOM OBJECT CREATION/MANIPULATION
 *******************************************************************/

/** CREATE OPTION FOR SELECTBOX
 * Creates and returns an option object to be added
 * to the calling select box.  The value and text
 * are supplied.
 *
 * @author: Randy Davis
 * @version: 1.0
 */

function createOption(optionValue, optionText) {
  var option   = document.createElement("OPTION");
  option.value = optionValue;
  option.text  = optionText;
  return option;
}

/** ADD ELEMENT
 * Creates a dom object of a certin type with an id and places
 * it within the parent object.
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function addElement(parent, type, id) {
  var parentObj = $(parent);
  var newObj    = document.createElement(type);
  if (id != "")
    newObj.setAttribute("id", id);
  parentObj.appendChild(newObj);
}

/** ADD ELEMENT WITH CLASS
 * Creates a dom object of a certain type with an id and
 * class and places it within the parent object.
 *
 * @author: Randy Davis
 * @version: 1.0
 */

function addElementWithClass(parent, type, id, className) {
  var parentObj = $(parent)
  var newObj    = document.createElement(type);
  newObj.setAttribute("id", id);
  newObj.setAttribute("class", className);
  newObj.setAttribute("className", className);
  parentObj.appendChild(newObj);
}

/** REMOVE ELEMENT
 * Removes a child object from the supplied
 * parent object
 *
 * @author: Randy Davis
 * @version: 1.0
 */

function removeElement(parent, child) {
  var parentObj = $(parent);
  var childObj  = $(child);
  parentObj.removeChild(childObj);
}


/** DISPLAY ELEMENT
 * Sets the object with the supplied id to
 * visible by setting the display to "block"
 *
 * @author: Randy Davis
 * @version: 1.0
 */
function displayElement(id) {
  $(id).style.display = "block";
}

/** HIDE ELEMENT
 * Sets the object with the supplied id to
 * hidden by setting the display to "none"
 *
 * @author: Randy Davis
 * @version: 1.0
 */

function hideElement(id) {
  $(id).style.display = "none";
}

/** ADD ATTRIBUTE
 * Adds an attribute with a particular value to a DOM object.
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function addAttribute(objName, attribute, value) {
  var obj = $(objName);
  obj.setAttribute(attribute, value);
}

/** APPEND ATTRIBUTE
 * Retreives the current value of the given
 * attribute and appends the supplied value
 * to the end.
 *
 * @author: Randy Davis
 * @version: 1.0
 */

function appendAttribute(objName, attribute, value) {
  var newValue = getAttribute(objName, attribute)+";"+value;
  addAttribute(objName, attribute, newValue);
}

/** GET ATTRIBUTE
 * Retreives the current value of a given
 * attribute and returns.
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function getAttribute(objName, attribute) {
  return $(objName).getAttribute(attribute);
}

/** REMOVE ATTRIBUTE
 * Removes an attribute from the given DOM object.
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function removeAttribute(objName, attribute) {
  var obj = $(objName);
  obj.removeAttribute(attribute);
}

/** ADD TEXT
 * Creates a text node and adds it to the
 * supplied dom object.<b> 
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function addText(objName, text) {
  var textNode = document.createTextNode(text)
  $(objName).appendChild(textNode);
}
 
/** CHANGE TEXT
 * Updates the supplied object with the
 * given text.
 *
 * @author: Randy Davis
 * @version: 1.0
 */

function changeText(objName, text) {
  var obj = $(objName);
  obj.innerHTML = text;
}

/** ADD ERROR MESSAGE
 * Adds the error message supplied to the
 * object given with appropriate styling.
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function addErrorMessage(objName, text) {
  addElement(objName, "span", "error_"+objName);
    addAttribute("error_"+objName, "class", "errorMessage");
    addAttribute("error_"+objName, "className", "errorMessage");
  addText("error_"+objName, text);
}


/********************************************************************
 * VIEWPORT HEIGHT AND WIDTH
 * Functions used to pull the browser height and width
 *******************************************************************/

function getViewportHeight() {
  if (window.innerHeight!=window.undefined) return window.innerHeight;
  if (document.compatMode=='CSS1Compat') return document.documentElement.clientHeight;
  if (document.body) return document.body.clientHeight; 
  return window.undefined; 
}

function getViewportWidth() {
  if (window.innerWidth!=window.undefined) return window.innerWidth; 
  if (document.compatMode=='CSS1Compat') return document.documentElement.clientWidth; 
  if (document.body) return document.body.clientWidth; 
  return window.undefined; 
}

/********************************************************************
 * PRODUCT RELATED FUNCTIONS
 * Functions used in regards to product
 *******************************************************************/

/** LOAD IMAGE
 * To preload an image onto the page, the function
 * takes the imageName and optional height and width
 * values to create an image object.
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function loadImage(imageName,height,width) {
  var loadingPic = height != null && width != null ? new Image(height,width) : new Image();
  loadingPic.src=imageName;
}

/** LOAD COLOR IMAGE
 * To preload a product image, the function takes
 * the supplied imageName, converts it to represent
 * the large version, and calls the loadImage function.
 *
 * @author: Randy
 * @version: 1.0
 */

function loadColorImage(imageName) {
  imageName = convertSmallImageToLarge(imageName);
  loadImage(imageName, 255, 255);
}

/** CONVERT SMALL IMAGE TO LARGE
 * A check is made on the supplied imageName for
 * a value of "/sm" and converts it to "lg" to
 * make it represent the large version of the
 * product.  A check is then made to convert
 * a value of ".gif" to ".jpg" so that the right
 * extension is being called.
 *
 * @author: Randy Davis
 * @version: 1.0
 */

function convertSmallImageToLarge(imageName) {
  return imageName.replace("/sm", "/lg").replace(".gif", ".jpg");
}

/** CONVERT TO EXTRA LARGE
 * A check is made on the supplied imageName for
 * a value of "/sm" or "/lg" and converts it to "xl"
 * to make it represent the extra large version of
 * the product.  A check is then made to convert a
 * value of ".gif" to ".jpg" so that the right
 * extension is being called.
 *
 * @author: Randy Davis
 * @version: 1.2
 */
 
function convertToExtraLarge(imageName) {
  return imageName.replace("/sm", "/xl").replace("/lg", "/xl").replace(".gif", ".jpg");
}

/** CONVERT LARGE IMAGE TO SMALL
 *
 * @author: Randy Davis
 * @version: 1.6
 * @param: imageName - image to be converted
 * @return: converted image name
 */

function convertLargeImageToSmall(imageName) {
  return imageName.replace("/lg", "/sm").replace(".jpg", ".gif");
}

/** HIDE MOUSEOVER IMAGE
 * Remove the mouseover image and set the
 * div to hidden.
 *
 * @author: Randy Davis
 * @version: 1.5
 */

function clearMouseOverImage() {
  clearImageTimer = setTimeout("$('imageOver').style.display='none'", 125);
}

/** SHOW MOUSEOVER IMAGE
 * Set the mouse over image in the imageOver
 * div and set display to visible.
 *
 * @author: Randy Davis
 * @version: 1.5
 */

function showMouseOverImage(colorImage) {
  clearTimeout(clearImageTimer);
  colorImage = convertSmallImageToLarge(colorImage);
  setValue("imageOver", "");
  addElement("imageOver", "img", "imageOverImg");
    addAttribute("imageOverImg", "src", colorImage);
  $("imageOver").style.display = "block";
}

function unencode(pUrl) {
  // note urlCText is declared in cart_body.jsp and omniture suggest.jsp
  var sUrl = new Array();
  var sParams = new Array();
  if(pUrl.toUpperCase().indexOf("%2FSTORE%2FCATALOG") > -1) {
    // old url - unencode and process
    pUrl = pUrl.replace(/%2F/g, "/");
    pUrl = pUrl.replace(/%3F/g, "?");
    pUrl = pUrl.replace(/%3D/g, "=");
    pUrl = pUrl.replace(/%26/g, "&");
    pUrl = pUrl.replace(/%25/g, "%");
    sUrl = pUrl.split("?");
    if(sUrl.length >= 2) {
      var pParams = sUrl[1];
      var pId = "";
      sParams = pParams.split("&");
      for(var i=0; i < sParams.length; i++) {
        if(sParams[i].indexOf("productId=") > -1) {
          pId = sParams[i];
        }
      }
      if(pId != "") {
        // productId exists create clean url
        pUrl = urlCText + "/store/catalog/product.jsp?" + pId;
      }
      else {
        // no productId . . . bad url - redirect back to site
        pUrl = urlCText + "/store/index.jsp";
      }
    }
    else {
      // bad url . . . cannot parse - redirect to back to site
      pUrl = urlCText + "/store/index.jsp";
    }
  }
  else if(pUrl.toUpperCase().indexOf("%2FSTORE%2FIMAGES") > -1) {
    // only unencode on images
    pUrl = pUrl.replace(/%2F/g, "/");
    pUrl = pUrl.replace(/%3F/g, "?");
    pUrl = pUrl.replace(/%3D/g, "=");
    pUrl = pUrl.replace(/%26/g, "&");
    pUrl = pUrl.replace(/%25/g, "%");
    pUrl = urlCText + pUrl     
  }
  else {
    pUrl = urlCText + pUrl
  }
  return pUrl;
}

/********************************************************************
 * TESTING FUNCTIONS
 * Functions used in regards to testing
 *******************************************************************/

/** CREATE TEST
 * Creates the testInfo object to be used in
 * testing into the object supplied.
 *
 * @author: Randy Davis
 * @version: 1.0
 */
 
function createTest(objName) {
  addElement(objName, "div", "testInfo");
}

/** TEST INFO
 * Used for testing, the value supplied is
 * placed into the object "testInfo".
 *
 * @author: Randy Davis
 * @version: 1.0
 */

function addTestInfo(value) {
  try {
    $("testInfo").innerHTML += value + "<br/>";
  } catch (e) {}
}