//<![CDATA[
// General purpose global helper fcns and classes

// HtmlElement Class: Creates objects to hold/manipulate html elements of type <type>
// OPTIONALLY: attach to DOM at <eParentNode>; Set id to <id>; Add text node with string <text>
// RETURN: pointer to newly created html element
(function() {
  HtmlElement = function(type, eParentNode, id, text) { // Constructor
    // public members (could be private, but need to add all the getters)
    this.id = '';
    this.type = '';
    this.text = '';
    this.eParentNode = '';
    this.elt = document.createElement(type); // create new elt of type <type>

    // Handle optional params
    if (Boolean(eParentNode)) {
      HtmlElement.attach2dom(this, eParentNode);
    }
    if (Boolean(id)) {
      HtmlElement.setId(this, id);
    }
    if (Boolean(text)) {
      HtmlElement.setText(this, text);
    }
  }

  // Privileged/Static methods
  HtmlElement.attach2dom = function(instance, eParentNode) {
    try {
      eParentNode.appendChild(instance.elt);
    } catch(e) {
      alert('HtmlElement::Error attaching HtmlElement to DOM: eParentNode is invalid');
    }
    instance.eParentNode = eParentNode;
  }
  HtmlElement.setId = function(instance, id) {
    if ( typeof id === 'string') {
      instance.id = id;
      instance.elt.setAttribute('id', id);
    }
  }
  HtmlElement.setText = function(instance, text) {
    if ( (typeof text === 'string') || (typeof text === 'number') ) {
      instance.text = text;
      var eNewText = document.createTextNode(text);
      instance.elt.appendChild(eNewText);
    }
  }
})();


// HtmlTable Class: Creates objects to hold/manipulate HTML tables (from 2-dimensional aData array)
// OPTIONALLY: Attach to DOM element <eParent>; Label columns using aHeading; Set id attribute to <id>
// CALLS: helperFcns.js::HtmlElement(), helperFcns.js::isEmpty()
// NOTE: Only handles aData arrays w/constant # of cols
(function() {
  HtmlTable = function(aHeading, aData, eParentNode, id) { // Constructor
    // public members (could be private, but need to add all the getters)
    this.elt = '';
    this.eParentNode = '';
    this.id = '';
    this.numRows = 0;
    this.numCols = aData[0].length; // Only handles data arrays w/constant # of cols
    // temp variables
    var eCurrentRow, eThead, eTbody;

    // Create table element, set id if one was sent, attach to <eParentNode> if one was sent
    eCurrentRow = new HtmlElement('table', eParentNode, id);
    this.elt = eCurrentRow.elt;

    // Optionally: Create Table Header (column headings)
    if ( ! isEmpty(aHeading) ) {
      eThead = new HtmlElement('thead', this.elt);
      eCurrentRow = new HtmlElement('tr', eThead.elt);

      for (var colNum=0; colNum < this.numCols; ++colNum) {
        new HtmlElement('th', eCurrentRow.elt, null, aHeading[colNum] );
      }
    }

    // Create Table Body
    eTbody = new HtmlElement('tbody', this.elt);
    for (var rowNum in aData) {
      eCurrentRow = new HtmlElement('tr', eTbody.elt);

      for (var colNum=0; colNum < (this.numCols); ++colNum) {
        new HtmlElement('td', eCurrentRow.elt, null, aData[rowNum][colNum] );
      }
    }

    this.numRows = parseInt(rowNum) + 1;
  }

  // Privileged/static methods
  //
  // Attach instance.elt to <eParentNode> of DOM
  HtmlTable.attach2dom = function(instance, eParentNode) {
    if ( Boolean(eParentNode) ) {
      try {
        eParentNode.appendChild(instance.elt);
      } catch(e) {
        alert('HtmlTable::Error attaching HtmlTable to DOM: eParentNode is invalid');
      }
      instance.eParentNode = eParentNode;
      return true;
    } else {
      alert('HtmlTable::Error attaching HtmlTable to DOM: eParentNode missing or invalid');
      return false;
    }
  };
  // Set id of instance.elt to <id>
  HtmlTable.setId = function(instance, id) {
    if ( Boolean(id) ) {
      instance.id = instance.elt.id = id;
      return true;
    } else {
      alert('HtmlTable::Error setting id: id is missing or invalid');
      return false;
    }
  };
})();


// typeof fix for arrays and nulls
// RETURNS: 'array', 'object', or 'null' as appropriate
function typeOf(value) {
  var type = typeof value;
  if (type === 'object') {
    if (value) {
      if (typeof value.length === 'number' &&
          !(value.propertyIsEnumerable('length')) &&
          typeof value.splice === 'function') {
        type = 'array';
      }
    } else {
      type = 'null';
    }
  }
  return type;
}

// RETURNS: true if oObj is object or array w/no enumerable members
// CALLS: typeOf()
function isEmpty(oObj) {
  var i, value;
  if ( (typeOf(oObj) === 'object') || (typeOf(oObj) === 'array') ) {
    for (i in oObj) {
      value = oObj[i];
      if (value !== undefined && typeOf(value) !== 'function') {
        return false;
      }
    }
  }
  return true;
}

function dollarCentsFormat(value) {
  // PARAMS: value is expected to be a float
  // RETURNS: value as string in normalized dollars.cents notation, rounded up to nearest penny
  var dollars = Math.floor(value);  // chop off floating point portion
  var cents   = Math.round((value % 1) * 100); // chop int portion, >>2, round up
  if (cents < 10) { cents = '' + cents + '0'; }
  return(dollars + '.' + cents);
}

function isMobileBrowser() {
  // RETURNS: true if mobile browser detected, false otherwise
  var bIsMobile = false;

  // List below may need periodic updating (from http://detectmobilebrowser.com/)
  (function(a){if(/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) bIsMobile=true})(navigator.userAgent||navigator.vendor||window.opera);

  if ( bIsMobile || (navigator.appVersion.indexOf('Mobile') > -1) ) {
    return true;
  }
}

// Procedural version of HtmlElement() above
// Create html element of type <type>, and attach to DOM at <eParentNode>
//  Optionally: Set id to <id>, and add text node with string <text>
// RETURNS: pointer to newly created html element
function attachHtmlElement(type, eParentNode, id, text) {
  var eNewText, eNewElt = document.createElement(type);
  eParentNode.appendChild(eNewElt);
  if ( typeof id === 'string') {
    eNewElt.setAttribute('id', id);
  }
  if ( (typeof text === 'string') || (typeof text === 'number') ) {
    eNewText = document.createTextNode(text);
    eNewElt.appendChild(eNewText);
  }
  return eNewElt;
}
//]]>

