/*
 * Form functions
 * Version 1.1
 * Copyright (C) 2003-2004 Vladan Zajda
 *
 * Licensed under the terms of the GNU General Public License
 * (http://www.opensource.org/licenses/gpl-license.php)
 *
 * forms.js: Form functions
 *
 * Authors:
 *   Vladan Zajda (vzajda [AT] centrum [DOT] cz)
 */

var element;
var msg;
var defaultLang = "cs";

var messages = { cs : 
                     {
                       required         : 'Pole "%s" je nutné vyplnit.',
                       invalid          : 'Pole "%s" je chybně vyplněno.',
                       number           : 'Je možné zadat číslice, případně znaménko a znak procenta.',
                       integer          : 'Je možné zadat číslice, případně znaménko.', 
                       real             : 'Je možné zadat číslice, desetinnou tečku, případně znaménko.',
                       percentual       : 'Je možné zadat číslice, znak procenta, případně desetinnou tečku či znaménko.',
                       minute           : 'Je možné zadat pouze hodnoty od 0 do 59.',
                       hour             : 'Je možné zadat pouze hodnoty od 0 do 23.',
                       day              : 'Je možné zadat pouze hodnoty od 1 do 31.',
                       month            : 'Je možné zadat pouze hodnoty od 1 do 12.',
                       year             : 'Je možné zadat pouze hodnoty od 1 do 2100.',
                       telfax           : 'Formát telefonního čísla je min. 9 číslic.',
                       psc              : 'Formát PSČ je 5 číslic.',
                       ico              : 'Formát IČ je min. 5 číslic.',
                       dic              : 'Formát DIČ je XXNNNNN\nX - písmeno, N - číslice. Min. počet číslic je 5.',
                       bank             : 'Formát bankovního účtu je NN-NNNN\nN - číslice.',
                       email            : 'Chybně zadána emailová adresa.',
                       url              : 'Chybně zadána URL adresa.',
                       range            : 'Hodnota musí musí být',
                       rangeFrom        : ' min. od ',
                       rangeTo          : ' max. do ',
                       element          : 'Nedefinovaný prvek formuláře "%s" nebo "%s[]".'
                     },                 
                 en :
                    {
                       required         : 'Field "%s" is required.',
                       invalid          : 'Field "%s" is filled out wrong.',
                       number           : 'It is possible to enter digits, eventually a sign and a percent mark.',
                       integer          : 'It is possible to enter digits, eventually a sign.', 
                       real             : 'It is possible to enter digits, decimal point, eventually a sign.',
                       percentual       : 'It is possible to enter digits, percent mark, eventually a decimal point or a sign.',
                       minute           : 'It is only possible to enter values from 0 to 59.',
                       hour             : 'It is only possible to enter values from 0 to 23.',
                       day              : 'It is only possible to enter values from 1 to 31.',
                       month            : 'It is only possible to enter values from 1 to 12.',
                       year             : 'It is only possible to enter values from 1 to 2100.',
                       telfax           : 'Phone number is minimally 9 digits long.',
                       psc              : 'Zip-code is minimally 5 digits long.',
                       // ---- dodělat ----
                       ico              : 'IČ is minimally 5 digits long.',
                       dic              : 'DIČ is XXNNNNN\nX - letter, N - number (minimally 5 digits long).',
                       // -----------------
                       bank             : 'Bank account number is NN-NNNN\nN - number.',
                       email            : 'Wrong email address.',
                       url              : 'Wrong URL address.',
                       range            : 'The value must be',
                       rangeFrom        : ' minimally from ',
                       rangeTo          : ' maximum to ',
                       element          : 'Undefined form element "%s" nebo "%s[]".'
                    },
                 de :
                    {
                       required         : 'Feld "%s" ist nötig zu ergänzen.',
                       invalid          : 'Field "%s" is filled out wrong.',
                       number           : 'It is possible to enter digits, eventually a sign and a percent mark.',
                       integer          : 'It is possible to enter digits, eventually a sign.',
                       real             : 'It is possible to enter digits, decimal point, eventually a sign.',
                       percentual       : 'It is possible to enter digits, percent mark, eventually a decimal point or a sign.',
                       minute           : 'It is only possible to enter values from 0 to 59.',
                       hour             : 'It is only possible to enter values from 0 to 23.',
                       day              : 'It is only possible to enter values from 1 to 31.',
                       month            : 'It is only possible to enter values from 1 to 12.',
                       year             : 'It is only possible to enter values from 1 to 2100.',
                       telfax           : 'Phone number is minimally 9 digits long.',
                       psc              : 'Zip-code is minimally 5 digits long.',
                       // ---- dodělat ----
                       ico              : 'IČ is minimally 5 digits long.',
                       dic              : 'DIČ is XXNNNNN\nX - letter, N - number (minimally 5 digits long).',
                       // -----------------
                       bank             : 'Bank account number is NN-NNNN\nN - number.',
                       email            : 'Wrong email address.',
                       url              : 'Wrong URL address.',
                       range            : 'The value must be',
                       rangeFrom        : ' minimally from ',
                       rangeTo          : ' maximum to ',
                       element          : 'Undefined form element "%s" nebo "%s[]".'
                    },
                 ru : 
                    {
                       required         : 'Поле «%s» обязательно для заполнения.',                    
                       invalid          : 'Field "%s" is filled out wrong.',
                       number           : 'It is possible to enter digits, eventually a sign and a percent mark.',
                       integer          : 'It is possible to enter digits, eventually a sign.', 
                       real             : 'It is possible to enter digits, decimal point, eventually a sign.',
                       percentual       : 'It is possible to enter digits, percent mark, eventually a decimal point or a sign.',
                       minute           : 'It is only possible to enter values from 0 to 59.',
                       hour             : 'It is only possible to enter values from 0 to 23.',
                       day              : 'It is only possible to enter values from 1 to 31.',
                       month            : 'It is only possible to enter values from 1 to 12.',
                       year             : 'It is only possible to enter values from 1 to 2100.',
                       telfax           : 'Phone number is minimally 9 digits long.',
                       psc              : 'Zip-code is minimally 5 digits long.',
                       // ---- dodělat ----
                       ico              : 'IČ is minimally 5 digits long.',
                       dic              : 'DIČ is XXNNNNN\nX - letter, N - number (minimally 5 digits long).',
                       // -----------------
                       bank             : 'Bank account number is NN-NNNN\nN - number.',
                       email            : 'Wrong email address.',
                       url              : 'Wrong URL address.',
                       range            : 'The value must be',
                       rangeFrom        : ' minimally from ',
                       rangeTo          : ' maximum to ',
                       element          : 'Undefined form element "%s" nebo "%s[]".'
                    },
                 pl : 
                    {
                       required         : 'Pole  "%s" należy wypełnić.',                    
                       invalid          : 'Field "%s" is filled out wrong.',
                       number           : 'It is possible to enter digits, eventually a sign and a percent mark.',
                       integer          : 'It is possible to enter digits, eventually a sign.', 
                       real             : 'It is possible to enter digits, decimal point, eventually a sign.',
                       percentual       : 'It is possible to enter digits, percent mark, eventually a decimal point or a sign.',
                       minute           : 'It is only possible to enter values from 0 to 59.',
                       hour             : 'It is only possible to enter values from 0 to 23.',
                       day              : 'It is only possible to enter values from 1 to 31.',
                       month            : 'It is only possible to enter values from 1 to 12.',
                       year             : 'It is only possible to enter values from 1 to 2100.',
                       telfax           : 'Phone number is minimally 9 digits long.',
                       psc              : 'Zip-code is minimally 5 digits long.',
                       // ---- dodělat ----
                       ico              : 'IČ is minimally 5 digits long.',
                       dic              : 'DIČ is XXNNNNN\nX - letter, N - number (minimally 5 digits long).',
                       // -----------------
                       bank             : 'Bank account number is NN-NNNN\nN - number.',
                       email            : 'Wrong email address.',
                       url              : 'Wrong URL address.',
                       range            : 'The value must be',
                       rangeFrom        : ' minimally from ',
                       rangeTo          : ' maximum to ',
                       element          : 'Undefined form element "%s" nebo "%s[]".'
                    }                      
};
                                 
setLang(defaultLang);

function setLang(lang) {
   msg = messages[lang];
}

function msgBox(message, param1, param2, param3) {
   if (arguments.length < 1) {
      return false;
   }
   
   for (var i = 1; i < arguments.length; i++ ) {
       if (message.indexOf("%s") == -1 || !arguments[i] || arguments[i] == null) break;
       message = message.replace(/\%s/, arguments[i]);
   }
   
   alert(message);
}

/*
 * Checks if form is filed-out correctly
 */
 
function IsFormValid(form) {   
   for (var name in JSData) {
       if (!JSData[name]['required']) continue;
      
       var valid = false;
       var obj = form.elements[name];
       if (!obj) obj = form.elements[name + "[]"];
       if (obj.tagName != null) var o = obj;
       else var o = obj[0];

       switch (o.tagName.toUpperCase()) {
         case "INPUT" :
            switch (o.type.toLowerCase()) {
              case "text" :
              case "hidden" :
                 if (o.value) {
                    valid = true;
                    break;
                 }
                 for (var i=0; i < obj.length; i++) {
                     if (obj[i].value) {
                        valid = true;
                        break;
                     }
                 }
                 break;
              case "checkbox" :
              case "radio" :
                 if (obj.checked) {
                    valid = true;
                    break;
                 }
                 for (var i=0; i < obj.length; i++) {
                     if (obj[i].checked) {
                        valid = true;
                        break;
                     }
                 }
                 break;
            }
            break;
         case "SELECT" :
            valid = (o.selectedIndex != -1 && JSData[name]['value'][o.selectedIndex] != '');
            break;
         case "TEXTAREA" :
            valid = (o.value != '');
            break;
       }
       if (!valid) {
          var title = JSData[name]['title'];
          msgBox(msg.required, title);
          o.focus();
          return false;
       }
   }
   return true;
}



/*
 * Checks if given element has correct value
 */
 
function IsElementValid(type, element) {
   if (element.value == "") return true; 
   parent.element = element;

   // strip '[]' from name
   var name = element.name;
   if (name.indexOf("[") != -1) {
      name = name.substring(0, name.indexOf("["));
   }

   // element title
   var title = JSData[name]['title'];

   var valid;
   switch (type) {
     case 'telfax':     if (!(valid = IsTelFaxValid(element.value, title)))     element.focus(); break;
     case 'email':      if (!(valid = IsEmailValid(element.value, title)))      element.focus(); break;
     case 'url':        if (!(valid = IsURLValid(element.value, title)))        element.focus(); break;
     case 'psc':        if (!(valid = IsPSCValid(element.value, title)))        element.focus(); break;
     case 'ico':        if (!(valid = IsICOValid(element.value, title)))        element.focus(); break;
     case 'dic':        if (!(valid = IsDICValid(element.value, title)))        element.focus(); break;
     case 'bank':       if (!(valid = IsBankValid(element.value, title)))       element.focus(); break;
     case 'number':     if (!(valid = IsNumberValid(element.value, title)))     element.focus(); break;
     case 'integer':    if (!(valid = IsIntegerValid(element.value, title)))    element.focus(); break;
     case 'real':       if (!(valid = IsRealValid(element.value, title)))       element.focus(); break;
     case 'percentual': if (!(valid = IsPercentualValid(element.value, title))) element.focus(); break;
   }
   return valid;
}

// number
function IsNumberValid(value, title) {
   var valid = value.match(/^[\+\-]?\d+(\.\d+)?\%?$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.number, title);
   else valid = IsValueInRange(value, title);
   return valid;
}

// integer
function IsIntegerValid(value, title) {
   var valid = value.match(/^[\+\-]?\d+$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.integer, title);
   else valid = IsValueInRange(value, title);
   return valid;
}

// real number
function IsRealValid(value, title) {
   var valid = value.match(/^[\+\-]?\d+(\.\d+)?$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.real, title);
   else valid = IsValueInRange(value, title);
   return valid;
}

// percentual
function IsPercentualValid(value, title) {
   var valid = value.match(/^[\+\-]?\d+(\.\d+)?\%$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.percentual, title);
   else valid = IsValueInRange(value, title);
   return valid;
}

// minute
function IsMinuteValid(value, title) {
   var valid = (value.match(/^\d{1,2}$/i) != null);
   if (!valid) msgBox(msg.invalid + "\n" + msg.minute, title);
   else valid = IsValueInRange(value, title, 0, 59);
   return valid;
}

// hour
function IsHourValid(value, title) {
   var valid = (value.match(/^\d{1,2}$/i) != null);
   if (!valid) msgBox(msg.invalid + "\n" + msg.hour, title);
   else valid = IsValueInRange(value, title, 0, 24);
   return valid;
}

// day
function IsDayValid(value, title) {
   var valid = (value.match(/^\d{1,2}$/i) != null);
   if (!valid) msgBox(msg.invalid + "\n" + msg.day, title);
   else valid = IsValueInRange(value, title, 1, 31);
   return valid;
}

// month
function IsMonthValid(value, title) {
   var valid = (value.match(/^\d{1,2}$/i) != null);
   if (!valid) msgBox(msg.invalid + "\n" + msg.month, title);
   else valid = IsValueInRange(value, title, 1, 12);
   return valid;
}

// year
function IsYearValid(value, title) {
   var valid = (value.match(/^\d{1,4}$/i) != null);
   if (!valid) msgBox(msg.invalid + "\n" + msg.year, title);
   else valid = IsValueInRange(value, title, 1900, 2100);
   return valid;
}


/*****************************************************************************/

// phone/fax
function IsTelFaxValid(value, title) {
   var valid = value.match(/^[\d\+\-\s\/\\]{9,}$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.telfax, title);
   return valid;

}

// postal code
function IsPSCValid(value, title) {
   var valid = value.match(/^\d{3}\s?\d{2}$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.psc, title);
   return valid;
}

// identification number
function IsICOValid(value, title) {
   var valid = value.match(/^\d{5,}$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.ico, title);
   return valid;
}

// tax identification number
function IsDICValid(value, title) {
   var valid = value.match(/^[a-z]{2}\d{5,15}$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.dic, title);
   return valid;
}

// bank account number
function IsBankValid(value, title) {
   var valid = value.match(/^[\d\-]{2,}\/\d{4}$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.bank, title);
   return valid;
}

// email address
function IsEmailValid(value, title) {
   var valid = value.match(/^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.email, title);
   return valid;
}

// URL address
function IsURLValid(value, title) {
   var valid = value.match(/^(http\:\/\/)?([w]{3}\.)?[\w-]+(\.[\w-]+)+(\/.*)?$/i) != null;
   if (!valid) msgBox(msg.invalid + "\n" + msg.url, title);
   return valid;
}


function IsValueInRange(value, title, min, max) {
   min    = min == null ? JSData[element.name]['min'] : min;
   max    = max == null ? JSData[element.name]['max'] : max;
   min    = min == '' ? null : min;
   max    = max == '' ? null : max;
   fMin   = parseFloat(min);
   fMax   = parseFloat(max);
   fValue = parseFloat(value);
   valid = (fValue >= fMin || min == null) && (fValue <= fMax || max == null);
   if (!valid) msgBox(msg.invalid + "\n" + msg.range + (min ? msg.rangeFrom + min : "") + (max ? msg.rangeTo + max : ""), title);
   return valid;
}

/*
 * Calculates simple formula(expression)(2nd parameter) via form values.
 * Calculated value is stored in element (1st parameter)
 * Element values and other atributes are stored in 'JSData' object.
 */

function Calculate(element, formula, substitute, precision) {
   // result element
   var result = document.getElementsByName(element);
   result = result[0];

   // expression to solve
   var expr = formula; 
     
   // looking for names of the elements
   var names = new Array();
   if (substitute == 1 || substitute === '')
      names = formula.match(/[\^]?[a-zA-Z]\w*(\[\d+\])?/g);

   var obj = new Array();
   for (var i=0; i < names.length; i++) {
       temp  = names[i].match(/([\^])/);                     // attribute
       attr  = temp != null ? temp[1] : null;
       name  = names[i].match(/[a-zA-Z]\w*/);                // name
       temp  = names[i].match(/\[(\d+)\]/);
       index = temp != null ? temp[1] : null;                // index

       obj = document.getElementsByName(name);               // form element
       if (obj.length == 0)
          // if 'name' does not exist, looking for 'name[]'
          obj = document.getElementsByName(name + "[]");     // form element
       if (obj.length == 0)
          // undefined name
          msgBox(msg.element, name);

       o   = obj[0];                                         // actual element
       val = undefined;                                      // element value
       switch (o.tagName.toUpperCase()) {                    // type of element
         case "INPUT" :
            switch (o.type.toLowerCase()) {                  // type of 'input'
              case "text" :
              case "hidden" :
                 val = o.value;
                 break;
              case "checkbox" :
                 if (index != null) {
                    // checked 'checkbox'?
                    if (attr == "^") {
                       o = obj[index] ? obj[index] : null;
                       val = parseInt(o && o.checked);
                    } else
                       val = JSData[name]["value"][index];
                 }
                 break;
              case "radio" :
                 if (index == null) {
                    if (attr == "^") val = 0;
                    for (var j=0; j < obj.length; j++) {
                        o = obj[j];
                        if (o.checked) {
                           // checked 'radio'?
                           if (attr == "^") val = 1;             
                           else val = JSData[name]["value"][j];
                           break;
                        }
                    }
                 }
                 else {
                    // checked 'radio'?
                    if (attr == "^") val = parseInt(o.checked);
                    else val = JSData[name]["value"][index];
                 }
                 break;
            }
            break;
         case "SELECT" :
            if (index == null) {
               if (attr == "^") val = 0;
               if (o.selectedIndex != -1) {
                  // selected option?
                  if (attr == "^") val = 1;                      
                  else val = JSData[name]["value"][o.selectedIndex];
               }
            }
            else {
               // selected option?
               if (attr == "^") val = (o.selectedIndex == index) ? 1 : 0; 
               else val = JSData[name]["value"][index];
            }
            break;
         case "TEXTAREA" :
            val = o.value;
            break;
       }
       
       // mark wrong value as undefined
       val  = (isNaN(val) || val === "") ? undefined : val;
       // element name replaced by value
       expr = expr.replace(names[i], val);
   }
   
   // result of expression
   var value = eval(expr);
   if (isNaN(value)) {
      result.value = 0;
      return;
   }
     
   switch (precision) {
     case "round":
     case "ceil":
     case "floor":
         value = eval("Math."+ precision + "(" + value + ");");
         break;
     case "currency":
         var floor  = Math.floor(value);
         var heller = value - floor;
         if (heller < 0.24)
            value = floor;
         else if (heller < 0.74)
            value = floor + 0.50;
         else
            value = Math.ceil(value);
            
         value = (value*100)/100;
         break;
     default:
         precison = parseInt(precision);
         if (precision != 0) 
            value = Math.round(value*precision)/precision;
         break;
   }
   
   result.value = value;
}