/* common Javascript functions */
/*  2007, William R Parke      */

// probably obsolete...
 if (document.all && !document.getElementById) {
  document.getElementById = function(id) {
   return document.all[id];
  }
 }

 var IsNN = "Netscape" == navigator.appName;
 var IsIE = "Microsoft Internet Explorer" == navigator.appName;
   

 function cancelKeyCode(event)
 {
  if (IsNN)
   event.preventDefault();
  else
   event.keyCode = null;
 }


 function clipCopy(id)
 {
  // IE only
  if (IsIE)
  {
   try
   {
    var txtrng = toObj(id).createTextRange();
    txtrng.execCommand("Copy");
    return true;
   }
   catch(e)
   {
    alert(e);
    return false;
   }
  }
  else
   return false;
 }


 function clipCut(id)
 {
  // IE only
  if (IsIE)
  {
   try
   {
    var txtrng = toObj(id).createTextRange();
    txtrng.execCommand("Cut");
    return true;
   }
   catch(e)
   {
    alert(e);
    return false;
   }
  }
  else
   return false;
 }


 function clipPaste(id)
 {
  // IE only
  if (IsIE)
  {
   try
   {
    var txtrng = toObj(id).createTextRange();
    txtrng.execCommand("Paste");
    return true;
   }
   catch(e)
   {
    alert(e);
    return false;
   }
  }
  else
   return false;
 }


 function fromUrlChr(str)
 {
  //: convert URL hex escapes to ASCII characters
  str = str.replace(/\+/gi,' ');
  str = str.replace(/%0A/gi,'\n');
  str = str.replace(/%0D/gi,'\r');
  str = str.replace(/%20/gi,' ');
  str = str.replace(/%26/gi,'\&amp;');
  str = str.replace(/%2C/gi,',');

  try {
   str = decodeURI(str);
  }
  catch (e)
  {
   var hex = str.match(/%+\w{2}/gi);

   if (hex)
   {
    var i, n, rx;
    for (i=0; i<hex.length; i++)
    {
     n = parseInt(hex[i].substr(1),16);
     if (!isNaN(n))
     {
      rx = new RegExp(hex[i],"gi");
      str = str.replace(rx,String.fromCharCode(n));
     }
    }
   }
  }
  return str;
 }


 function getClipboardText(id)
 {
  // IE only
  if (IsIE)
  {
   var txtrng = toObj(id).createTextRange();
   try
   {
    txtrng.execCommand("Paste");
    return toObj(id).value;
   }
   catch(e)
   {
    alert(e);
    return "";
   }
  }
  else
   return "";
 }


 function getEventSourceObject(event)
 {
  if (event.srcElement)
   return event.srcElement;
  else
   return event.target;
 }


 function getKeyCode(event)
 {
  if (event.keyCode)
   return event.keyCode;
  else
   return event.which;
 }


 function getMaxLength(obj)
 {
  //: get maximum length of elements in string or array
  var n = 0;
  if ("string" == typeof(obj))
   n = obj.length;
  else
   for (var i=0; i<obj.length; i++)
    n = Math.max(n,obj[i].length);
  return n;
 }


 function getQueryValue(str,name)
 {
  //: return named value from query string of name=value pairs
  var n = str.length;
  if ((0 == n) || (0 == name.length))
   return "";
  if (-1 == name.indexOf('='))
   name += "=";
  var i = str.toLowerCase().indexOf('\&'+name);
  if (-1 == i)
   i = str.toLowerCase().indexOf('\?'+name);
  if (-1 != i)
  {
   i += 1 + name.length;
   var d = str.indexOf('\&',i);
   if (-1 == d)
     d = n;
   return str.substr(i,d-i);
  }
  else
   return "";
 }


 function getRadioValue(name)
 {
  //: return value of selected radio button
  var val = null;
  var obj = document.getElementsByName(name);
  if (obj)
  {
   for (var i=0; i<obj.length; i++)
   {
    if (obj[i].checked)
    {
     val = obj[i].value;
     break;
    }
   }
  }
  return val;
 }


 function getSelectedValue(id,val)
 {
  //: return selected value of HTML <select> element; optional default value if object not found
  var obj = document.getElementById(id);
  if (obj)
   return obj.options[obj.selectedIndex].value;
  else
   if (val)
    return val;
   else
    return "";
 }


 function getValue(id,val)
 {
  //: return value of HTML <input> element; optional default value if object not found
  var obj = document.getElementById(id);
  if (obj)
   return obj.value;
  else
   if (val)
    return val;
   else
    return "";
 }


 function getValueAsNumber(id,def)
 {
  //: return value of HTML <input> element as number; optional default value if object not found or value not a number
  var obj=document.getElementById(id);
  var val;
  if (obj)
  {
   val = Number(obj.value);
   if (isNaN(val))
   {
    if (def)
     val = def;
    else
     val = 0;
   }
  }
  else
   if (def)
    val = def;
   else
    val = 0;

  return val;
 }


 function handleIntKeyDown(event)
 {
  // trap keydown event in <input> element, allow cursor up/down to scroll values 
  var code = getKeyCode(event);
  var obj = getEventSourceObject(event);
  if (38 == code)
  {
   // cursor up
   cancelKeyCode(event);
   inputInt(obj,1);
   return false;
  }
  else
  {
   if (40 == code)
   {
    // cursor down
    cancelKeyCode(event);
    inputInt(obj,-1);
    return false;
   }
    else
     return true;
  }
 }


 function handleIntKeyPress(event)
 {
  // trap keypress event in <input> element, allow +/- to scroll values 
  var code = getKeyCode(event);
  var obj = getEventSourceObject(event);
  if ((57 < code) || (48 > code))
  // anything besides 0-9
  {
   if ((43 == code) || (61 == code))
   {
    // + or =
    cancelKeyCode(event);
    inputInt(obj,1);
   }
   else
   {
    if (45 == code)
    {
     // - (minus)
     if (0 != obj.value.length)
     {
      cancelKeyCode(event);
      inputInt(obj,-1);
     }
    }
    else
     // allow backspace, left cursor, right cursor, delete
     if ((8 != code) && (37 != code) && (39 != code) (46 != code))
      cancelKeyCode(event);
   }
  }
 }


 function inputInt(obj,inc,min,max)
 {
  var n = Number(obj.value);
  if (!min)
   min = obj.min;
  if (!max)
   max = obj.max;

  if (!isNaN(n))
  {
   n += inc;
   if ("undefined" != typeof(min))
    n = Math.max(n,min);
   if ("undefined" != typeof(max))
    n = Math.min(n,max);
  }
  else
  {
   if ("undefined" != typeof(min))
    n = min;
   else
    n = 0;
  }
  obj.value = n;
 }


 function isaN(n)
 {
  //: is a number
  return !isNaN(n);
 }


 function isNumeric(str)
 {
  //: determine if string contains all numerals (and decimal, signs and separators)
  if (0 == str.length)
   return false;
  if (!isNaN(Number(str)))
   return true;
  var rx = /[^ 0-9\-\+\.\,]/;
  if (-1 != str.search(rx))
   return false;
  return true;
 }


 function padEach(obj,len,ch)
 {
  //: pad each element of array to length with char or obj
 
  if (0 != len)
  {
   var alen;
   var item;
   var pad;
   if (0 < obj.length)
   {
    if ("string" == typeof(obj[i]))
    {
     if ("undefined" == ch)
      ch = ' ';
     for (var i=0; i<obj.length; i++)
     {
      pad = "";
      item = obj[i];
      alen = Math.abs(len)-item.length; 
      while (pad.length < alen)
       pad += ch;
      if (0 > len)
       // pad right
       item = pad + item;
      else
       item = item + pad;
      obj[i] = item;
     }
    }
    else
    {
     // array
     if ("number" == typeof(obj))
     {
      obj = [obj];
      if ("undefined" == ch)
       ch = 0;
     }
     else
      if ("undefined" == ch)
       ch = [];

     for (var i=0; i<obj.length; i++)
     {
      pad = [];
      item = obj[i];
      alen = Math.abs(len)-item.length; 
      while (pad.length < alen)
       pad.push(ch);
      if (0 > len)
       // pad right
       item = pad.concat(item);
      else
       item = item.concat(pad);
      obj[i] = item;
     }
    }
   }
   else
   {
    if ("undefined" == ch)
     ch = []; 
    obj.push(ch);
   }
  } 
  return obj;
 }


 function padString(str,len,ch)
 {
  //: pad string to length with char
  if (0 != len) {
   if (!ch)
    ch = ' ';
   var pad = "";
   var alen = Math.abs(len)-str.length; 
   while (pad.length < alen)
    pad += ch;
   if (0 > len)
    // pad right
     str = pad + str;
   else
     str = str + pad;
  }
  return str;
 }


 function padStringEach(obj,len,ch)
 {
  //: pad each string in object to length with char
  if (!ch)
   ch = ' ';
  var pad = "";
  var alen = len;
  for (i=0; i<obj.length; i++)
  {
   str = obj[i];
   alen = Math.abs(len)-str.length;
   if (alen != pad.length)
   {
    pad = "";
    while (pad.length < alen)
     pad += ch;
   }
   if (0 > len)
    // pad right
     str = pad + str;
   else
     str = str + pad;
   obj[i] = str;
  }
  return obj;
 }


 function rxWhere(obj,rx,len)
 {
  // find indices of all occurrences and lengths of RegExp match in string
  var res = [];
  var ix = -1;
  var offset = 0;
  if (!len)
   len = 0;
  var match = obj.match(rx);
 
  do
  {
    ix = obj.search(rx);
    if (-1 != ix)
    {
     res.push([ix+offset,((0 == len) ? match[0].length : len)]);
     if (rx.global)
     { 
      match.shift();
      obj = obj.substr(1+ix);
      if (0 == obj.length)
       ix = -1;
      else
       offset = offset + ix +1;     
     }
     else
      ix = -1;
    }
  } while ( -1 != ix);
  return res;
 }

 function scrollInt(id,inc,min,max)
 {
  inputInt(toObj(id),inc,min,max);
 }


 function selectAll(id)
 {
  //: select all text in input control
  toObj(id).focus();
  toObj(id).select();
 }


 function setKeyCode(code)
 {
  if (IsNN)
   event.which = code;
  else
   event.keyCode = code;
 }


 function setRadioValue(name,val)
 {
  //: selected radio button with specified value
  var obj = document.getElementsByName(name);
  if (obj)
  {
   for (var i=0; i<obj.length; i++)
   {
    if (val == obj[i].value)
    {
     obj[i].checked = true;
     break;
    }
   }
  }
 }


 function setSelectedIndex(id,index)
 {
  //: set selected option in HTML <select> element by index
  var obj = document.getElementById(id);
  if (obj)
   obj.options[index].selected = "selected";
 }


 function setSelectedValue(id,val)
 {
  //: set selected option of HTML <select> element by value
  var obj = document.getElementById(id);
  if (obj)
  {
   for (var i=0; i < obj.options.length; i++)
   {
    if (val == obj.options[i].value)
    {
     obj.selectedIndex = i;
     return;
    }
   }
  }
 }


 function toNumeric(str)
 {
  //: convert string of numerals to numeric array
  var aa = [];
  if ((0 != str.length) && ("string" == typeof(str)))
  {
   var n = Number(str);
   if (!isNaN(n))
    aa.push(n);
   else
   {
    if (isNumeric(str))
    {
     str = str.replace(/ /g,",");
     str = str.split(",");
     for (var i=0; i<str.length; i++)
     {
      if (0 == str[i].length)
       continue;
      n = Number(str[i]);
      if (!isNaN(n))
       aa.push(n);
      else
      {
       aa = [];
       break;
      }
     }
    }
   }
  }
  return aa;
 }


 function toObj(id)
 {
  return document.getElementById(id);
 }


 function toReverse(obj)
 {
  //: reverses array or string
  if (1 < obj.length)
  {
   var istr = "string" == typeof(obj);
   if (istr)
    obj = obj.split("");
   obj.reverse();
   if (istr)
    obj = obj.join("");
  }
  return obj;
 }


 function toStringEach(obj)
 {
  //: convert each object element to string
  for (var i=0; i<obj.length; i++)
   obj[i] = obj[i].toString();
  return obj;
 }


 function toTrue(val)
 {
  //: return true|false value
  switch (val)
  {
   case "true":
    return true;
   case "yes":
    return true;
   case "1":
    return true;
   case "+":
    return true;
   case 1:
    return true;
   default :
    return false;
  }
 }


 function toUrlChr(str)
 {
  //: create URL-compatible string 
  str = encodeURI(str);
  return str;
 }


 function trimAll(str)
 {
  //: trim all extra whitespace from string
  // adapted from http://lawrence.ecorp.net/inet/samples/regexp-format.php
  // remove leading and trailing
  str = str.replace(/^\s+|\s+$/g, '');
  // now convert multiple spaces to single
  str = str.replace(/ {2,}/g, ' ');
  return str; 
 }


 function trimBoth(str)
 {
  //: trim leading and trailing white-space
  // from http://lawrence.ecorp.net/inet/samples/regexp-format.php
  return str.replace(/^\s+|\s+$/g, '');
 }


 function trimLeft(str)
 {
  //: trim leading white-space
  // from http://lawrence.ecorp.net/inet/samples/regexp-format.php
  return str.replace(/^\s+/, '');
 }


 function trimRight(str)
 {
  //: trim trailing white-space
  // from http://lawrence.ecorp.net/inet/samples/regexp-format.php
  return str.replace(/\s+$/, '');
 }


 function validInt(obj,dft)
 {
  //: validate integer input; called onblur
  if (isNaN(Number(this.value)))
   this.value = dft;
 }






