//
// Common Javascript functions - Copyright (c) 2002 interactivetools.com, inc.
//

/* ---------------------------------------------------------------------- *\
  Function    : cloneObject
  Description : copy an object by value instead of by reference
  Usage       : var newObj = cloneObject(oldObj);
\* ---------------------------------------------------------------------- */

function cloneObject(obj) {
  var newObj          = new Object; 

  // check for array objects
  if (isArray(obj)) { newObj = obj.constructor(); }

  for (var n in obj) {
    var node = obj[n];
    if (typeof node == 'object') { newObj[n] = cloneObject(node); }
    else                         { newObj[n] = node; }
  }
  
  return newObj;
}

/* ------------------------------------------------------------------------- *\
  Function    : 
  Description : 
  Usage       : 
\* ------------------------------------------------------------------------- */

function isArray(obj) {
  if (typeof obj == 'object') {
    if (obj.constructor.toString().indexOf('function Array(') == 1) { return true; }
  }
  return false;
}

/* ------------------------------------------------------------------------- *\
  Function    : 
  Description : 
  Usage       : 
\* ------------------------------------------------------------------------- */

function show(obj) {
  if (typeof obj == 'string') { obj = document.getElementById(obj); }

  obj.style.display = ""; // set to default
  forceRedraw();
}

/* ------------------------------------------------------------------------- *\
  Function    : showHide
  Description : show specifed elements in showList array and hide those in
                hideList.  showList takes precedence over hideList.
  Usage       : showHide( showArray, hideArray );
                showHide( [ 'id1','id2'], ['id1','id2','id3'] );
\* ------------------------------------------------------------------------- */

function showHide(showArray, hideArray) {

  if (typeof showArray != 'object') { alert('first argument must be an array'); }
  if (typeof hideArray != 'object') { alert('second argument must be an array'); }

  var showList = new Object();
  for (var n=0; n < showArray.length; n++) {
    if (showArray[n]) { showList[ showArray[n] ] = true; }
  }

  // hide elements
  for (var n=0; n < hideArray.length; n++) {
    var thisElement = hideArray[n];
    var thisElementName = thisElement;
    if (typeof thisElement == 'string') { thisElement = document.getElementById(thisElement); }
    if (!thisElement) { alert("Couldn't find element: " + thisElementName); }
    else if (thisElement.id) { 
      if (!showList[thisElement]) { thisElement.style.display = 'none'; }
    }
  }  

  // show elements
  for (var n=0; n < showArray.length; n++) {
    var thisElement = showArray[n];
    var thisElementName = thisElement;
    if (!thisElement) { continue; }    
    if (typeof thisElement == 'string') { thisElement = document.getElementById(thisElement); }
    if (!thisElement) { alert("Couldn't find element: " + thisElementName + thisElement); continue; }
    if (thisElement.id) { thisElement.style.display = ''; }
  }  

  forceRedraw();

}

/* ------------------------------------------------------------------------- *\
  Function    : 
  Description : 
  Usage       : 
\* ------------------------------------------------------------------------- */

function hide(obj) {
  if (typeof obj == 'string') { obj = document.getElementById(obj); }
  
  if (obj.style.display != 'none') { obj.style.display = 'none'; }
  forceRedraw();
}

/* ------------------------------------------------------------------------- *\
  Function    : 
  Description : 
  Usage       : 
\* ------------------------------------------------------------------------- */

function toggleVisibility(obj) {
  if (typeof obj == 'string') { obj = document.getElementById(obj); }

  if (obj.style.display != 'none') { obj.style.display = 'none'; }
  else                             { obj.style.display = ''; }
  
  forceRedraw();
}

/* ------------------------------------------------------------------------- *\
  Function    : 
  Description : 
  Usage       : 
\* ------------------------------------------------------------------------- */

function forceValidDate(yearName,monName,dayName) {
  var dayObj = document.getElementsByName(dayName)[0];
  var year   = document.getElementsByName(yearName)[0].value;
  var mon    = document.getElementsByName(monName)[0].value;
  var day    = dayObj.value;

  // get days in month
  var monDays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) { monDays[1] = "29"; } // check for leap year
  var daysInMonth = monDays[ mon-1 ];

  // remember selected Index
  var myIndex = dayObj.selectedIndex;

  // remove days
  while (dayObj.options[dayObj.length-1].value > daysInMonth) {
    dayObj.options[dayObj.length-1] = null;
  }
  
  // add days
  while (dayObj.options[dayObj.length-1].value < daysInMonth) {
    var nextDay = Number(dayObj.options[dayObj.length-1].value) + 1;
    dayObj.options[dayObj.length] = new Option(nextDay, nextDay);
  }

  // if no day selected, select highest day in month
  if (dayObj.options[myIndex] == null) { dayObj.options[dayObj.length-1].selected = true; }

}

function _applyToBranch(el, coderef) {   // run code for each element node in DOM branch
  if (typeof el == 'string') { el = document.getElementById(el); }
  if (el == null) { return alert('_applyToBranch: Invalid elect name or reference'); };

  // apply to parent
  coderef(el);        // note: this gets called twice

  // apply child nodes
  for (var n=0; n<el.childNodes.length; n++) { 
    var thisNode = el.childNodes[n];

    // display each child element node
    if (thisNode.nodeType == 1) { coderef(thisNode); }

    // if child node has children of it's own, disable those
    if (thisNode.childNodes.length) { _applyToBranch(thisNode, coderef); }
  }
}

function DisableBranch(el) {
  var coderef = function(node) { node.setAttribute('disabled','disabled', 0); };
  _applyToBranch(el, coderef);
}

function EnableBranch(el) {
  var coderef = function(node) { node.removeAttribute('disabled', 0); };
  _applyToBranch(el, coderef);
}

// addOtherOption - allow user to select "<other>" and add options to pulldowns
// NOTE: other must be the LAST option, options after it may be erased
// NOTE: be sure to have "other" values persist on redisplay of form

function addOtherOption(obj, promptText) {
  if (promptText == null) { promptText = "Enter new option value:"; }
  var selectedValue = obj.options[obj.selectedIndex].value;
  var otherToken    = '__other__';  

  if (selectedValue == otherToken) {
    var optValue = prompt(promptText,"");                      // ask for new option
    if (optValue == null) { obj.selectedIndex = 0; return; }   // select first option on cancel

    if (obj.options[obj.length-1].value != otherToken) {       // remove previously added "other" options
      obj.options[obj.length-1] = null;
    }

    obj.options[obj.length] = new Option(optValue, optValue);  // add new option
    obj.selectedIndex = obj.length - 1;                        // select new option
  }
}

/* ---------------------------------------------------------------------- *\
  Function    : obj2query
  Description : convert the names/values of an objects properties into a
                querystring or vice versa.
  Usage       : var obj   = query2obj(queryString);
                var query = obj2query(obj);
\* ---------------------------------------------------------------------- */

function obj2query(obj) {
  var newQuery = "";

  for (var pname in obj) {
    var pvalue = obj[pname];
    if (typeof pvalue == 'object') { continue; }
    if (newQuery.length > 0) { newQuery += "&"; }
    newQuery += escape(pname) +"="+ escape(pvalue);
  }
  
  return newQuery;
}

function query2obj(Query) {
  var obj   = new Object();
  var pairs = new Array();

  // remove ? from query string
  if (Query.charAt(0) == '?') { Query = Query.substring(1, Query.length); }

  pairs = Query.split("&");
  
  for (var i=0; i < pairs.length; i++) {
    var thispair = pairs[i]
    var temp = '';

    // Replace + char with ' ' 
    for (var n=0; n < thispair.length; n++) {
      var chr = thispair.charAt(n);
      if (chr == '+') { chr = ' '; }
      temp += chr;
    }
    thispair = temp;

    // split into name and value
    var namevalue = thispair.split("=");

    // set field name/value values.  set undefined values to zero length string
    var fname  = (namevalue[0] == null)  ? '' : unescape( namevalue[0] );
    var fvalue = (namevalue[1] == null)  ? '' : unescape( namevalue[1] );
    
    if (fname.length) { obj[fname] = fvalue; }            // set object value
  }
  
  return obj;
  
}

function templateCell(cellName, placeholders) {

  // load templatecell
  var cellHTML;
  if (typeof this[cellName] == 'string') { // check cache
    cellHTML = this[cellName];
  } else {                                // load from doc and cache
    cellHTML = getInnerHTML(cellName);
    //alert(cellHTML);
    this[cellName] = cellHTML;
  }

  // create name/value pairs for "*_checked" and "*_selected" placeholders
  var placeholderNVPairs = new Object;
  for (var keyname in placeholders)         { placeholderNVPairs[keyname +"_"+ placeholders[keyname]] = true; }
  for (var keyname in templateCell.globals) { placeholderNVPairs[keyname +"_"+ templateCell.globals[keyname]] = true; }

  cellHTML = cellHTML.replace(/<!--\s*javascript\s*insert\s*:\s*(.*?)\s*-->/g, '$1');

  // mozilla encodes attribute values properly, so we'll need to search for converted strings too
  cellHTML = cellHTML.replace(/&lt;!--\s*javascript\s*insert\s*:\s*(.*?)\s*--&gt;/g, '$1');
  cellHTML = cellHTML.replace(/&lt;!--(?:%20)*javascript(?:%20)*insert(?:%20)*:(?:%20)*(.*?)(?:%20)*--&gt;/g, '$1');
  cellHTML = cellHTML.replace(/%3C%21--(?:%20)*javascript(?:%20)*insert(?:%20)*:(?:%20)*(.*?)(?:%20)*--%3E/g, '$1');

  // replace placeholders and return content
  return cellHTML.replace(/\%(\w+):?(\w*)\%/g, function(mSubstr, capture1, capture2) {
    var pValue = templateCell.globals[capture1] || placeholders[capture1];
    if (pValue) { pValue = pValue.toString(); }
    var r;
//    if (pValue != null) {
    if (pValue) {
      if (capture2 != 'raw') {
        pValue = pValue.replace(/&/g, "&amp;");
        pValue = pValue.replace(/"/g, "&quot;");
        pValue = pValue.replace(/</g, "&lt;");
        pValue = pValue.replace(/>/g, "&gt;");
        pValue = pValue.replace(/ /g, "&nbsp;");  // because IE doesn't always quote value="" fields grep'd w/ innerhtml
      }
      return pValue;
    }
    else if (r = capture1.match(/^(\w+)_checked$/)) {
      if (placeholderNVPairs[ r[1] ]) { return "checked"; }
    }
    else if (r = capture1.match(/^(\w+)_selected$/)) {
      if (placeholderNVPairs[ r[1] ]) { return "selected"; }    
    }
    else {
      return '';
    }
  });

}

// initialize cache and globals
templateCell.cache = new Object();
templateCell.globals = new Object();

/* ---------------------------------------------------------------------- *\
  Function    : formFieldValue()
  Description : return the value that would be submitted by a form element
                returns either string or array
\* ---------------------------------------------------------------------- */

function formFieldValue(el) {

  var ftype = el.type
  var fvalue = '';                                     // field value (defined below)
  var fvalues = [];                                    // field value (defined below)
 
  // for single pulldowns
  if (ftype == 'select-one') {
    var idx = el.options.selectedIndex;
    var txt = el.options[idx].text;                 // <option>text</option> value
    var val = el.options[idx].value;                // <option value="this">

//alert(el.options[idx].value);

    if (val.length) { fvalue = val; }                  // try and use value first
    else            { fvalue = txt; }
    return fvalue;
  }
  
  // for multiple pulldowns
  else if (ftype == 'select-multiple') {
    var sCount = 0;                                           // selected options count
    for (var idx=0; idx <= el.options.length-1; idx++) {    // o is option index
      if (el.options[idx].selected != true) { continue; }   // skip unselected values
      sCount += 1;                                            // add one to selected options counter        

      var txt = el.options[idx].text;                       // <option>text</option> value
      var val = el.options[idx].value;                      // <option value="this">
      if (val.length) { fvalue = val; }                        // try and use value first
      else            { fvalue = txt; }
      fvalues.push(fvalue);
    }
    return fvalues;
  }    

  // for checkboxes and radios
  else if (ftype == 'checkbox' || ftype == 'radio') {
    if (el.checked) {                                       // only show "checked" checkboxes
      fvalue = el.value;                             // field value
      return fvalue;
    }
    else { return ""; }
  }
  
  // for all other fields
  else {
    fvalue = el.value;                               // field value
    return fvalue;                      
  }
  
}

/* ------------------------------------------------------------------------- *\
  Function    : 
  Description : 
  Usage       : 
\* ------------------------------------------------------------------------- */




/* ------------------------------------------------------------------------- */



