String.prototype.repeat     = function(l){ var s = '', i = 0; while (i++ < l){ s += this; } return s; }
String.prototype.startsWith = function(s)
{
  s = s ? s : '';
  if (s == this.valueOf()){ return true; }
  return this.valueOf().substr(0, s.length) == s;
}
String.prototype.zf         = function(l){ return '0'.repeat(l - this.length) + this; }

Date.prototype.add          = function(interval, increment)
{
  if(isNaN(increment)){ return this; }
  var date = this;
  switch(interval.toLowerCase())
  {
    case 'yyyy' : date.setFullYear(this.getFullYear() + increment);         break;
    case 'q'    : date.setMonth(this.getMonth() + (increment * 3));         break;
    case 'm'    : date.setMonth(this.getMonth() + increment);               break;
    case 'y'    :
    case 'd'    :
    case 'w'    : date.setDate(this.getDate() + increment);                 break;
    case 'ww'   : date.setDate(this.getDate() + (increment * 7));           break;
    case 'h'    : date.setHours(this.getHours() + increment);               break;
    case 'n'    : date.setMinutes(this.getMinutes() + increment);           break;
    case 's'    : date.setSeconds(this.getSeconds() + increment);           break;
    case 'ms'   : date.setMilliseconds(this.getMilliseconds() + increment); break;
  }
  return this;
}

Date.prototype.diff         = function(interval, date)
{
  var intervals  = {
                    y: 365.25 * 24 * 60 * 60 * 1000 ,
                    m: 30     * 24 * 60 * 60 * 1000 ,
                    w: 7      * 24 * 60 * 60 * 1000 ,
                    d: 24     * 60 * 60 * 1000      ,
                    h: 60     * 60 * 1000           ,
                    n: 60     * 1000                ,
                    s: 1000                         ,
                    z: 1
                   };
  return Math.floor(Math.abs(date.getTime() - this.getTime()) / intervals[interval]);
}

Date.prototype.format       = function(f)
{
  if (!this.valueOf()){ return this.toString(); }
  var date    = this;
  var days    = new Array(
                          'Sunday'    ,
                          'Monday'    ,
                          'Tuesday'   ,
                          'Wednesday' ,
                          'Thursday'  ,
                          'Friday'    ,
                          'Saturday'
                         );
  var months  = new Array(
                          'January'   ,
                          'February'  ,
                          'March'     ,
                          'April'     ,
                          'May'       ,
                          'June'      ,
                          'July'      ,
                          'August'    ,
                          'September' ,
                          'October'   ,
                          'November'  ,
                          'December'
                         );
  return f.replace(
                    /(yyyy|mmmm|mmm|mm|dddd|ddd|dd|hh|nn|ss|a\/p)/gi  ,
                    function($1)
                    {
                      switch ($1.toLowerCase())
                      {
                        case 'yyyy' : return date.getFullYear();
                        case 'mmmm' : return months[date.getMonth()];
                        case 'mmm'  : return months[date.getMonth()].substr(0, 3);
                        case 'mm'   : return new String(date.getMonth() + 1).zf(2);
                        case 'dddd' : return days[date.getDay()];
                        case 'ddd'  : return days[date.getDay()].substr(0, 3);
                        case 'dd'   : return new String(date.getDate()).zf(2);
                        case 'hh'   : return new String((h = date.getHours() % 12) ? h : 12).zf(2);
                        case 'nn'   : return new String(date.getMinutes()).zf(2);
                        case 'ss'   : return new String(date.getSeconds()).zf(2);
                        case 'a/p'  : return date.getHours() < 12 ? 'AM' : 'PM';
                      }
                    }
                  );
}

function clickFilter(e)
{
  var message = '';
  if (e && e.which && (e.which == 2 || e.which == 3)){ return false; }
  if (event && event.button && (event.button == 2 || event.button == 3)){ (message); return false; }
  return true;
}

function formatDate(input, format)
{
  if (!input)           { return false; }
  if (!input.value)     { return false; }
  if (input.value == ''){ return false; }
  var val   = new String(input.value);
  if (!isDate(val))
  {
    input.value = '';
    return false;
  }
  format      = format ? format : 'mm/dd/yyyy';
  input.value = new Date(val).format(format);
  return true;
}

function formatPhone(val)
{
  if (!isPhone(val)){ return ''; }
  val    = val.replace(/[^+\d]/g, '');
  if (val.substr(0, 1) == '+')
  {
    return val.replace(/(.{4})(.{4})(.{4})/, '$1-$2-$3');
  }
  if (val.substr(0, 1) == '1')
  {
    return val.replace(/(1)(\d{3})(\d{3})(\d{4})/, '$1-$2-$3-$4');
  }
  return val.replace(/(\d{3})(\d{3})(\d{4})/, '$1-$2-$3');
}

function getDate(parent, target)
{
  parent          = document.getElementById(parent);
  target          = document.getElementById(target);
  if (!parent){ return false; }
  if (!target){ return false; }
  var currentDate = isDate(target.value) ? new Date(target.value) : new Date();
  target.value    = isDate(target.value) ? target.value           : '';
  parent.onblur   = function()
                            {
                              if (isChild(parent, document.activeElement)){ return; }
                              parent.style.display  = 'none';
                            };
  showCalendar(parent.id, target.name, currentDate.getFullYear(), currentDate.getMonth());
  return false;
}

function getPosition(el)
{
  var x = el.offsetLeft;
  var y = el.offsetTop;
  while ((el = el.offsetParent))
  {
    x += el.offsetLeft;
    y += el.offsetTop;
  }
  return { x:x, y:y };
}

function httpRequest(uri, query)
{
  try
  {
    if(window.XMLHttpRequest)
    {
      request = new XMLHttpRequest();
    } else if(window.ActiveXObject) {
      request = new ActiveXObject('Microsoft.XMLHTTP');
    }
  } catch(e) {
    return false;
  }
  request.onreadystatechange = function()
                               {
                                 if (request.readyState == 4)
                                 {
                                   if (request.status == 200)
                                   {
                                     dataChangeHandler(request.responseXML);
                                   } else {
                                     alert(request.statusText);
                                   }
                                 }
                               }
  request.open('post', uri, true);
  request.setRequestHeader('content-type' , 'application/x-www-form-urlencoded');
  request.setRequestHeader('connection'   , 'close');
  request.send(query);
}

function isChild(parent, element)
{
  if (element == parent){ return true; }
  var children  = parent.all;
  for (var child in children)
  {
    var node = children[child];
    if (element == node){ return true; }
    if (node.all)
    {
      if (isChild(node, element)){ return true; }
    }
  }
  return false;
}

function isDate (val)
{
  return !isNaN(new Date(val).getYear());
}

function isEmail(val)
{
  if (!val)     { return false; }
  if (val == ''){ return false; }
  var re = new RegExp(/^((\"[^\"]*?\")|([^\(\)\<\>\@\,\;\:\\\"\[\]\s\*\/]+))@(\[((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}|((([a-zA-Z0-9\-]+)\.)+))([a-zA-Z]{2,}|(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\])$/);
  return re.test(val);
}

function isPhone(val)
{
  if (!val)     { return false; }
  if (val == ''){ return false; }
  val    = val.replace(/[^+\d]/g, '');
  var re = new RegExp(/^(1?\d{10})|(\+\d{11})$/);
  return re.test(val);
}

function modify(id, action, method)
{
  record.elements['id'].value     = id;
  record.elements['action'].value = action;
  record.elements['method'].value = method;
  record.submit();
  return false;
}

function navigate(url, page, direction, sort, previous, append, showAll)
{
  var find   = document.getElementById('find');
  var findIn = document.getElementById('findIn');
  var uri    = '';
  if (find){   uri += '&find='   + escape(find.value);   }
  if (findIn){ uri += '&findIn=' + escape(findIn.value); }
  if (!url){        url         = ''; }
  if (!page){       page        = ''; }
  if (!direction){  direction   = ''; }
  if (!sort){       sort        = ''; }
  if (!previous){   previous    = ''; }
  if (!append){     append      = ''; }
  if (!showAll){    showAll     = ''; }
  document.location = url + '?page=' + page + '&sortDirection=' + direction + '&sort=' + sort + '&lastSort=' + previous + uri + '&' + append + '&showAll=' + showAll;
  return false;
}

function parseUrl(value)
{
  var regEx     = /^((https?|ftps?):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+\.[^#?&\s]+)((?:#|\?|&)(.*))?$/;
  var file      = '';
  var host      = '';
  var path      = '';
  var protocol  = '';
  var query     = '';
  var url       = '';
  if (value.match(regEx))
  {
    url       = RegExp['$&'];
    protocol  = RegExp.$2;
    host      = RegExp.$3;
    path      = RegExp.$4;
    file      = RegExp.$6;
    query     = RegExp.$8;
  }
  return  {
            url       : url       ,
            protocol  : protocol  ,
            host      : host      ,
            path      : path      ,
            file      : file      ,
            query     : query
          };
}

function selectOnFocus()
{
  var inputs = document.getElementsByTagName("input");
  for (var input in inputs)
  {
    if (inputs[input].type != 'text'){ continue; }
    inputs[input].onfocus = function(){ this.select(); }
  }
}

function selInput(item)
{
  var el = document.getElementById(item);
  if (!el){ return; }
  el.focus();
  if (el.type == "text"){ el.select(); }
}

function setInnerHTML(e, v)
{
  e = document.getElementById(e);
  if (!e){ return; }
  e.innerHTML = v;
}

function showCalendar(showIn, returnTo, year, month, day)
{
  showIn        = document.getElementById(showIn);
  returnTo      = document.getElementById(returnTo);
  if (!showIn){   return false; }
  if (!returnTo){ return false; }
  showIn.style.position = 'absolute';
  showIn.style.display  = '';
  if (day)
  {
    showIn.onblur         = null;
    showIn.style.display  = 'none';
    showIn.innerHTML      = '';
    var date              = new Date((month + 1) + '/' + day + '/' + year);
    returnTo.value        = date.format('mm/dd/yyyy');
    returnTo.focus();
    returnTo.select();
    return false;
  }
  var link      = null;
  var months    = new Array(
                              'January'    ,
                              'February'   ,
                              'March'      ,
                              'April'      ,
                              'May'        ,
                              'June'       ,
                              'July'       ,
                              'August'     ,
                              'September'  ,
                              'October'    ,
                              'November'   ,
                              'December'
                           );
  var thisDate  = new Date();
  year          = year < 2000 ? 2000 : year;
  year          = year > 2037 ? 2037 : year;
  thisDate.setYear(year);
  thisDate.setMonth(month);
  thisDate.setDate(1);
  var days        = 32 - new Date(year, month, 32).getDate();
  var nextDate    = new Date(year, month, days + 1);
  var lastDate    = new Date(year, month, 0);
  lastDate.setDate(1);
  var today       = new Date();
  var todayDay    = today.getDate();
  var todayMonth  = today.getMonth();
  var todayYear   = today.getFullYear();
  var html  = '';
  html     += '<table style="border:1px solid steelblue; margin:2px; padding:2px; width:225px;">\n';
  html     += ' <tr>\n';
  html     += '  <td style="background-color:#FF9900; font-family:arial; font-size:7.25pt; padding-right:5px; padding-top:2px; text-align:right;">\n';
  html     += '   <a\n';
  html     += '      href=""\n';
  html     += '      onclick="showCalendar(\'' + showIn.id + '\', \'' + returnTo.name + '\', ' + lastDate.getFullYear() + ', ' + lastDate.getMonth() + ')"\n';
  html     += '      title="Previous Month"\n';
  html     += '   ><img src="/images/arrow.left.gif" style="border:none;"></a>\n';
  html     += '  </td>\n';
  html     += '  <td colspan="5" style="background-color:#FF9900; padding-top:2px; text-align:center;">\n';
  html     += '   <select\n';
  html     += '      style="font-family:arial; font-size:7.25pt; text-align:center; width:85px;"\n';
  html     += '      onchange="showCalendar(\'' + showIn.id + '\', \'' + returnTo.name + '\', ' + thisDate.getFullYear() + ', this.value)"\n';
  html     += '   >\n';
  for (month in months)
  {
    var selected = month == thisDate.getMonth() ? 'selected' : '\n';
    html   += '    <option value="' + month + '" ' + selected + '>' + months[month] + '</option>\n';
  }
  html     += '   </select>\n';
  html     += '   <select\n';
  html     += '      style="font-family:arial; font-size:7.25pt; text-align:center; width:50px;"\n';
  html     += '      onchange="showCalendar(\'' + showIn.id + '\', \'' + returnTo.name + '\', this.value, ' + thisDate.getMonth() + ')"\n';
  html     += '   >\n';
  for (year = 2000; year < 2038; year++)
  {
    var selected = year == thisDate.getFullYear() ? 'selected' : '\n';
    html   += '    <option value="' + year + '" ' + selected + '>' + year + '</option>\n';
  }
  html     += '   </select>\n';
  html     += '  </td>\n';
  html     += '  <td style="background-color:#FF9900; font-size:7.25pt; padding-left:5px; padding-top:2px; text-align:left;">\n';
  html     += '   <a\n';
  html     += '      href=""\n';
  html     += '      onclick="showCalendar(\'' + showIn.id + '\', \'' + returnTo.name + '\', ' + nextDate.getFullYear() + ', ' + nextDate.getMonth() + ')"\n';
  html     += '      title="Next Month"\n';
  html     += '   ><img src="/images/arrow.right.gif" style="border:none;"></a>\n';
  html     += '  </td>\n';
  html     += ' <tr><td colspan="7" style="background-color:#FF9900; border-bottom:1px solid lavender; height:2px;"></td></tr>\n';
  html     += ' <tr>\n';
  html     += '   <td style="font-size:7.25pt; font-weight:600; text-align:center; width:25px;">Sun</td>\n';
  html     += '   <td style="font-size:7.25pt; font-weight:600; text-align:center; width:25px;">Mon</td>\n';
  html     += '   <td style="font-size:7.25pt; font-weight:600; text-align:center; width:25px;">Tue</td>\n';
  html     += '   <td style="font-size:7.25pt; font-weight:600; text-align:center; width:25px;">Wed</td>\n';
  html     += '   <td style="font-size:7.25pt; font-weight:600; text-align:center; width:25px;">Thu</td>\n';
  html     += '   <td style="font-size:7.25pt; font-weight:600; text-align:center; width:25px;">Fri</td>\n';
  html     += '   <td style="font-size:7.25pt; font-weight:600; text-align:center; width:25px;">Sat</td>\n';
  html     += ' </tr>\n';
  html     += ' <tr><td colspan="7" style="border-bottom:1px solid lavender; height:2px;"></td></tr>\n';
  html     += ' <tr>\n';
  month         = thisDate.getMonth();
  year          = thisDate.getFullYear();
  var daysLeft  = 0;
  var weekDay   = thisDate.getDay();
  if (weekDay > 0)
  {
    html   += '  <td colspan="' + weekDay + '" style="background-color:lavender; font-size:7.25pt; width:25px;">&nbsp;</td>\n';
  }
  for (var day = 1; day <= days; day++)
  {
    for (; weekDay < 7; weekDay++)
    {
      if (day > days)
      {
        daysLeft++;
        continue;
      }
      if (!weekDay)
      {
        html   += ' </tr>\n';
        html   += ' <tr>\n';
      }
      var border      = 'none';
      var fontWeight  = '100';
      if (day == todayDay && month == todayMonth && year == todayYear)
      {
        border      = '1px solid #990000';
        fontWeight  = '600';
      }
      html     += '<td style="border:' + border + 'font-size:7.25pt; width:20px;">\n';
      html     += '  <a\n';
      html     += '      href="' + day + '"\n';
      html     += '      style="font-weight:' + fontWeight + '; text-decoration:none;"\n';
      html     += '      onclick="return showCalendar(\'' + showIn.id + '\', \'' + returnTo.name + '\', ' + year + ', ' + month + ', ' + day + ')"\n';
      html     += '  >' + day + '</a>\n';
      html     += '</td>\n';
      day++
    }
    day--;
    weekDay = 0;
  }
  if (daysLeft > 0)
  {
    html   += '  <td colspan="' + daysLeft + '" style="background-color:lavender; width:25px;">&nbsp;</td>\n';
  }
  html     += ' </tr>\n';
  html     += '</table>\n';
  showIn.innerHTML = html;
  showIn.focus();
  return false;
}

function showMenu(parent, child, display)
{
  parent                 = document.getElementById(parent);
  var position           = getPosition(parent);
  position.x            -= 28;
  position.y            -= 68;
  child                  = document.getElementById(child);
  child.style.position   = 'absolute';
  child.style.left       = position.x + 'px';
  child.style.top        = position.y + 'px';
  child.style.display    = display ? '' : 'none';
}

function showStatus(p, b, f)
{
  b = document.getElementById(b);
  f = document.getElementById(f);
  if (!b){       return; }
  if (!b.style){ return; }
  if (!f){       return; }
  if (!f.style){ return; }
  var width     = parseInt(b.style.width);
  var percent   = parseInt(p);
  width         = (percent * width) / 100;
  f.style.width = width + "px";
}

function toggleDisplay(el)
{
  el                = document.getElementById(el);
  el.style.display  = el.style.display == 'none' ? '' : 'none';
}

function trim(string)
{
  string = string.replace(/^\s*/, "");
  return   string.replace(/\s*$/, "");
}
