if (!decimalSeparator) var decimalSeparator = ".";
if (!negativeSymbol)   var negativeSymbol =   "-";
if (!timeFormat)       var timeFormat =       "h:mm:ss t";
if (!timeSeparator)    var timeSeparator =    ":";
if (!amSymbol)         var amSymbol =         "AM";
if (!pmSymbol)         var pmSymbol =         "PM";
if (!dateFormat)       var dateFormat =       "M/dd/yyyy";
if (!dateSeparator)    var dateSeparator =    "/";
if (!dateTimeFormat)   var dateTimeFormat =   "M/dd/yyyy h:mm:ss t";
var microsoft = (navigator.appName.indexOf("Microsoft") >= 0);

function replaceFormat(text, from, to, pad) {
  var newTo;
  var fmt = text;
  
  if (to.length >= pad.length) {
    newTo = to;
  } else {
    newTo = pad.substring(0, pad.length - to.length) + to;
  }

  var pos = fmt.indexOf(from);
  while (pos >= 0) {
    fmt = fmt.substring(0, pos) + newTo + fmt.substring(pos + from.length);
    pos = fmt.indexOf(from);
  }
  
  return fmt;
}

function findElemOrder(format, elems) {
  var pos = new Array();
  var order = new Array();
  var x;
  
  for (var i = 0; i < elems.length; i++) {
    for (var j = 0; j < elems[i].length; j++) {
      pos[i] = format.indexOf(elems[i].charAt(j));
      if (pos[i] >= 0) break;
    }
    if (pos[i] < 0) pos[i] = format.length;
  }
  
  for (var i = 0; i < elems.length; i++) {
    x = 0;
    for (var j = 1; j < elems.length; j++) {
      if (pos[j] < pos[x]) x = j;
    }
    order[i] = elems[x];
    pos[x] = format.length + 1;
  }
  
  return order;
}

function numberParse(text, decimals) {
  var strNum = text
  var decPos = -1;
  var negPos = -1;
  
  if (decimalSeparator != ".") {
    decPos = strNum.indexOf(decimalSeparator);
  }
  if (negativeSymbol != "-") {
    negPos = strNum.indexOf(negativeSymbol);
  }
  if (decPos >= 0) {
    strNum = strNum.substring(0, decPos) + "." + strNum.substring(decPos + 1, strNum.length);
  }
  if (negPos >= 0) {
    strNum = strNum.substring(0, negPos) + "-" + strNum.substring(negPos + 1, strNum.length);
  }
  
  if (decimals == 0) {
    return Math.round(Number(strNum));
  } else if (decimals > 0) {
    return Math.round(Number(strNum) * Math.pow(10, decimals)) / Math.pow(10, decimals);
  } else {
    return Number(strNum);
  }
}

function numberString(num, decimals) {
  var strFmt = "";
  
  if (decimals < 0) {
    var decPos = num.toString().indexOf(".");
    if (decPos > -1) {
      decimals = Number(num.toString().length - (decPos + 1));
    } else {
      decimals = 0;
    }
  }
  
  if (decimals == 0) {
    strFmt = Math.abs(Math.round(num)).toString();
  } else {
    strFmt = Math.abs(Math.round(num * Math.pow(10, decimals))).toString();
    while (strFmt.length <= decimals) {
      strFmt = "0" + strFmt;
    }
    strFmt = strFmt.substring(0, strFmt.length - decimals) + decimalSeparator + strFmt.substring(strFmt.length - decimals, strFmt.length);
  }
  if (num < 0) {
    strFmt = negativeSymbol + strFmt;
  }
  return strFmt;
}

function numberValid(element, decimals, maxlength) {
  if (element.value != "") {
     var num = numberParse(element.value, decimals);
     if (isNaN(num)) {
       element.value = 0;
       return false;
     }
     element.value = numberString(num, decimals);
     return (element.value.length <= maxlength);
  } else {
     return true;
  }
}

function dateNextPart(pos, text, order, data, index, date) {
  var max;
  var maxlen;
  var nextPos = pos;
  
  if (!date) date = new Date();
  
  if (order[index] == "d") {
    max = 31;
    maxlen = 2;
    data[index] = date.getDate();
  } else if (order[index] == "M") {
    max = 12;
    maxlen = 2;
    data[index] = date.getMonth() + 1;
  } else if (order[index] == "y") {
    max = 9999;
    maxlen = 4;
    data[index] = date.getYear();
  } else if (order[index] == "Hh") {
    max = 23;
    maxlen = 2;
    data[index] = date.getHours();
  } else if (order[index] == "m") {
    max = 59;
    maxlen = 2;
    data[index] = date.getMinutes();
  } else if (order[index] == "s") {
    max = 59;
    maxlen = 2;
    data[index] = date.getSeconds();
  } else if (order[index] == "t") {
    maxlen = amSymbol.length;
    if (pmSymbol.length > maxlen) maxlen = pmSymbol.length;
    data[index] = "";
  }
  
  // skip over leading ignored characters
  while (pos < text.length) {
    if (".-/ :".indexOf(text.charAt(pos)) < 0) break;
    pos++;
  }
  
  if (order[index] == "t") {
    for (var i = pos + 1; i <= text.length; i++) {
      test = text.substring(pos, i).toLowerCase();
      
      if (test == amSymbol.substring(0, i - pos).toLowerCase()) {
        data[index] = amSymbol;
        nextPos = i;
      } else if (test == pmSymbol.substring(0, i - pos).toLowerCase()) {
        data[index] = pmSymbol;
        nextPos = i;
      } else {
        break;
      }
    }
    
  } else {
    for (var i = pos; i < text.length; i++) {
      if (".-/ :".indexOf(text.charAt(i)) >= 0) {
        nextPos = i + 1;
        break;
        
      } else {
        test = Number(text.substring(pos, i + 1));
        
        if (isNaN(test)) {
          nextPos = i + 1;
          break;
        } else if ((test > max) || ((i - pos) >= maxlen)) {
          nextPos = i;
          break;
        } else {
          data[index] = test;
          nextPos = i + 1;
        }
      }
    }
  }
  
  if ((order[index] == "y") && (data[index] < 100)) {
    data[index] = 2000 + data[index];
  }
  
  return nextPos;
}

function datePart(data, order, elem) {
  for (var i = 0; i < order.length; i++) {
    if (order[i] == elem) return data[i];
  }
  return 0;
}

function dateParse(text) {
  var date = new Date();
  var order = new Array();
  var data = new Array();
  
  order[0] = "d";
  order[1] = "M";
  order[2] = "y";
  order = findElemOrder(dateFormat, order);
  
  var pos = 0;
  for (var i = 0; i < 3; i++) {
    pos = dateNextPart(pos, text, order, data, i, date);
  }
  
  return new Date(datePart(data, order, "y"), datePart(data, order, "M") - 1, datePart(data, order, "d"), 0, 0, 0, 0);
}

function dateString(date) {
  var fmt = dateFormat;
  fmt = replaceFormat(fmt, "dd", date.getDate().toString(), "00");
  fmt = replaceFormat(fmt, "d", date.getDate().toString(), "0");
  fmt = replaceFormat(fmt, "MM", (date.getMonth() + 1).toString(), "00");
  fmt = replaceFormat(fmt, "M", (date.getMonth() + 1).toString(), "0");
  fmt = replaceFormat(fmt, "yyyy", date.getFullYear().toString(), "");
  fmt = replaceFormat(fmt, "yy", date.getFullYear().toString(), "00");
  return fmt;
}

function dateValid(element) {
  if (element.value != "") {
     var date = dateParse(element.value);
     if (!date) {
       return false;
     }
     element.value = dateString(date);
  }
  return true;
}

function timeParse(text, date) {
  var order = new Array();
  var data = new Array();
  
  if (!date) date = new Date(0);

  order[0] = "Hh";
  order[1] = "m";
  order[2] = "s";
  order[3] = "t";
  order = findElemOrder(timeFormat, order);

  var pos = 0;
  for (var i = 0; i < 4; i++) {
    pos = dateNextPart(pos, text, order, data, i, date);
  }
  
  date.setHours(datePart(data, order, "Hh"));
  date.setMinutes(datePart(data, order, "m"));
  date.setSeconds(datePart(data, order, "s"));
  var ampm = datePart(data, order, "t");
  
  if ((ampm == pmSymbol) && (date.getHours() < 12)) {
    date.setHours(date.getHours() + 12);
  } else if ((ampm == amSymbol) && (date.getHours() == 12)) {
    date.setHours(0);
  }
  
  return date;
}

function timeString(time, seconds) {
  var fmt = timeFormat;
  time = new Date(Number(time));

  if (seconds) {
    fmt = replaceFormat(fmt, "ss", time.getSeconds().toString(), "00");
    fmt = replaceFormat(fmt, "s", time.getSeconds().toString(), "0");
    
  } else {
    // wipe out any reference to seconds from the format
    fmt = replaceFormat(fmt, timeSeparator + "ss", "", "");
    fmt = replaceFormat(fmt, timeSeparator + "s", "", "");
    fmt = replaceFormat(fmt, "ss" + timeSeparator, "", "");
    fmt = replaceFormat(fmt, "s" + timeSeparator, "", "");
    fmt = replaceFormat(fmt, "s", "", "");
  }
  
  fmt = replaceFormat(fmt, "HH", time.getHours().toString(), "00");
  fmt = replaceFormat(fmt, "H", time.getHours().toString(), "0");
  fmt = replaceFormat(fmt, "mm", (time.getMinutes()).toString(), "00");
  fmt = replaceFormat(fmt, "m", (time.getMinutes()).toString(), "0");
  
  if ((fmt.indexOf("h") >= 0) || (fmt.indexOf("t") >= 0)) {
    var hrs = time.getHours();
    var ampm = amSymbol;

    if (hrs == 0) {
      hrs = 12;
      
    } else if (hrs == 12) {
      ampm = pmSymbol;
      
    } else if (hrs > 12) {
      hrs = hrs - 12;
      ampm = pmSymbol; 
      
    }
    fmt = replaceFormat(fmt, "hh", hrs.toString(), "00");
    fmt = replaceFormat(fmt, "h", hrs.toString(), "0");
    fmt = replaceFormat(fmt, "t", ampm, "");
  }
  return fmt;
}

function timeValid(element, seconds) {
  if (element.value != "") {
     var time = timeParse(element.value);
     if (!time) {
       return false;
     }

     element.value = timeString(time, seconds);
  }
  return true;
}

function dateTimeParse(text) {
  var date = new Date();
  var order = new Array();
  var data = new Array();
  
  order[0] = "d";
  order[1] = "M";
  order[2] = "y";
  order[3] = "Hh";
  order[4] = "m";
  order[5] = "s";
  order[6] = "t";
  order = findElemOrder(dateTimeFormat, order);

  var pos = 0;
  for (var i = 0; i < 7; i++) {
    pos = dateNextPart(pos, text, order, data, i, date);
  }
  
  date.setYear(datePart(data, order, "y"));
  date.setMonth(datePart(data, order, "M") - 1);
  date.setDate(datePart(data, order, "d"));
  date.setHours(datePart(data, order, "Hh"));
  date.setMinutes(datePart(data, order, "m"));
  date.setSeconds(datePart(data, order, "s"));
  var ampm = datePart(data, order, "t");
  
  if ((ampm == pmSymbol) && (date.getHours() < 12)) {
    date.setHours(date.getHours() + 12);
  } else if ((ampm == amSymbol) && (date.getHours() == 12)) {
    date.setHours(0);
  }
  
  return date;
}

function dateTimeString(dateTime, seconds) {
  var fmt = dateTimeFormat;
  dateTime = new Date(Number(dateTime));
  
  if (seconds) {
    fmt = replaceFormat(fmt, "ss", dateTime.getSeconds().toString(), "00");
    fmt = replaceFormat(fmt, "s", dateTime.getSeconds().toString(), "0");
    
  } else {
    // wipe out any reference to seconds from the format
    fmt = replaceFormat(fmt, timeSeparator + "ss", "", "");
    fmt = replaceFormat(fmt, timeSeparator + "s", "", "");
    fmt = replaceFormat(fmt, "ss" + timeSeparator, "", "");
    fmt = replaceFormat(fmt, "s" + timeSeparator, "", "");
    fmt = replaceFormat(fmt, "s", "", "");
  }

  fmt = replaceFormat(fmt, "dd", dateTime.getDate().toString(), "00");
  fmt = replaceFormat(fmt, "d", dateTime.getDate().toString(), "0");
  fmt = replaceFormat(fmt, "MM", (dateTime.getMonth() + 1).toString(), "00");
  fmt = replaceFormat(fmt, "M", (dateTime.getMonth() + 1).toString(), "0");
  fmt = replaceFormat(fmt, "yyyy", dateTime.getFullYear().toString(), "");
  fmt = replaceFormat(fmt, "yy", dateTime.getFullYear().toString(), "00");
  fmt = replaceFormat(fmt, "HH", dateTime.getHours().toString(), "00");
  fmt = replaceFormat(fmt, "H", dateTime.getHours().toString(), "0");
  fmt = replaceFormat(fmt, "mm", (dateTime.getMinutes()).toString(), "00");
  fmt = replaceFormat(fmt, "m", (dateTime.getMinutes()).toString(), "0");
  
  if ((fmt.indexOf("h") >= 0) || (fmt.indexOf("t") >= 0)) {
    var hrs = dateTime.getHours();
    var ampm = amSymbol;

    if (hrs == 0) {
      hrs = 12;
      
    } else if (hrs == 12) {
      ampm = pmSymbol;
      
    } else if (hrs > 12) {
      hrs = hrs - 12;
      ampm = pmSymbol; 
      
    }
    fmt = replaceFormat(fmt, "hh", hrs.toString(), "00");
    fmt = replaceFormat(fmt, "h", hrs.toString(), "0");
    fmt = replaceFormat(fmt, "t", ampm, "");
  }
  return fmt;
}

function dateTimeValid(element, seconds) {
  if (element.value != "") {
     var dateTime = dateTimeParse(element.value);
     if (!dateTime) {
       return false;
     }

     element.value = dateTimeString(dateTime, seconds);
  }
  return true;
}
