//object available to page
var oFormBuilder = new formBuilder();

/**
 * the formBuilder class provides methods for javascript functionalities related to php form_builder object
 *
 */

function formBuilder(){
  //properties
  this.bValidate;
  this.formId;
  this.formTitle;
  this.autocompleteOver;
  //objects
  this.oInvalidFields;
  this.oHTTPUpload;
  //methods
  this.getFormTitle = getFormTitle;
  this.getFieldValue = getFieldValue;
  this.setFieldValue = setFieldValue;
  this.hasFieldValue = hasFieldValue;
  this.getFieldLabel = getFieldLabel;
  this.focusField = focusField;
  this.resetField = resetField;
  this.resetFieldById = resetFieldById;
  this.resetFields = resetFields;
  this.displayTextareaRich = displayTextareaRich;
  this.displayDatetime = displayDatetime;
  this.checkMandatories = checkMandatories;
  this.highlightInvalid = highlightInvalid;
  this.alertInvalid = alertInvalid;
  this.validateGroup = validateGroup;
  this.checkTextValue = checkTextValue;
  this.checkTextareaRich = checkTextareaRich;
  this.checkRadioCheckbox = checkRadioCheckbox;
  this.checkSelect = checkSelect;
  this.getForeignSelect = getForeignSelect;
  this.emptySelect = emptySelect;
  this.fillSelect = fillSelect;
  this.fillForeignSelect = fillForeignSelect;
  this.selectForeignRecord = selectForeignRecord;
  this.generatePassword = generatePassword;
  this.startProgressBarMonitor = startProgressBarMonitor;
  this.getProgressBarStatus = getProgressBarStatus;
  this.progressBarStatusGot = progressBarStatusGot;
  this.stopProgressBarMonitor = stopProgressBarMonitor;
  this.updateProgressBar = updateProgressBar;
  this.autocompleteLaunch = autocompleteLaunch;
  this.autocompleteGot = autocompleteGot;
  this.autocompleteDestroy = autocompleteDestroy;
  this.autocompleteDestroyLaunch = autocompleteDestroyLaunch;
	this.autocompleteSelect = autocompleteSelect;
	this.checkMaxChar = checkMaxChar;
}

/**
 * gets field value depending on field type
 *
 * @param string fieldType
 * @param string inputId  
 *
 * @return mixed field value
 *
 */
function getFormTitle(){
	if(!this.formTitle && this.formId && document.getElementById('form_builder_title_'+this.formId)){
		this.formTitle = document.getElementById('form_builder_title_'+this.formId).innerHTML;	
	}
	return this.formTitle;
}

/**
 * gets field value depending on field type
 *
 * @param string fieldType
 * @param string inputId  
 *
 * @return mixed field value
 *
 */
function getFieldValue(fieldType,inputId){
  var fieldValue;
	switch(fieldType){
		case 'text':
			fieldValue = document.getElementById(inputId).value;
		break;
  	case 'select':
  	case 'select-one':
      var oSelect = document.getElementById(inputId);
      var selectedIndex = oSelect.selectedIndex;
      fieldValue = oSelect.options[selectedIndex].value;
  	break;
  }
  return fieldValue;
}

/**
 * checks whther field has value depending on field type
 *
 * @param string fieldType
 * @param string inputId  
 *
 * @return boolean
 *
 */
function hasFieldValue(fieldType,inputId){
	var value = this.getFieldValue(fieldType,inputId);
	return (value != 0 && value != '');
}

/**
 * sets field value depending on field type
 *
 * @param string fieldType
 * @param string inputId
 * @param string value    
 * @param boolean bAppend: for fields with text value, whether to append value to current value or to overwrite
 *
 * @return void
 *
 */
function setFieldValue(fieldType,inputId,value,bAppend){
  var oField;
	switch(fieldType){
		case 'text':
		
			oField = document.getElementById(inputId);
			if(bAppend) oField.value += value
			else oField.value = value;
		break;
		case 'textarea':
			oField = document.getElementById(inputId);
			if(oDisplayManager.browserDetect.browser == 'Explorer' && oDisplayManager.browserDetect.version <= 6){
				oField.innerHTML = value;
				if(bAppend) oField.innerHTML += value
				else oField.innerHTML = value;	
			}else{
				if(bAppend) oField.value += value
				else oField.value = value;
			}
		break;
  	case 'select':
      var oField = document.getElementById(inputId);
      var selectedIndex;
      for(i in oField.options){
      	if(oField.options[i].value == value){
      		oField.selectedIndex = i;
					break;
				}
      }
  	break;
  }
}

/**
 * gets field label
 *
 * @param string inputId
 *
 * @return void
 *
 */
function getFieldLabel(inputId){
  var fieldLabel;
  if(document.getElementById('form_label_'+inputId)){
  	fieldLabel = document.getElementById('form_label_'+inputId).innerHTML.replace(/&nbsp;\*/g,'');
  }
  return fieldLabel;
}

/**
 * gives focus to a field
 *
 * @param string inputId
 *
 * @return void
 *
 */
function focusField(inputId){
  document.getElementById(inputId).focus();
}

/**
 * reset fields values
 *
 * @param string formId
 * @param array aExcluded: array with fields to be excluding from resetting
 *
 * @return void
 *
 */
function resetFields(formId,aExcluded){
  var oFields = document.getElementById(formId).elements;
  var oField;
  for(i in oFields){
    oField = oFields[i];
    if(!oField || oVarManipulator.inArray(oField.name,aExcluded)) continue;
    else this.resetField(oField);
    /*
    if(oField.checked) oField.checked = false;
    else if(oField.options) oField.selectedIndex = 0;
    else{
      switch(oField.type){
        case 'text':
          oField.value = '';
        break;
        case 'password':
          oField.value = '';
        break;
        case 'textarea':
          oField.value = '';
        break;
        
      }
    }
    */
  }
  //date time fields
  var aDTFields = oDisplayManager.getElementsByClassName('form_input_datetime');
  var DTFieldId;
  for(i in aDTFields){
    oField = aDTFields[i];
    //check form name
    if(oField.id.indexOf(formId+'_') === 0){
      //get basic field id
      DTFieldId = oField.id.replace(/_trigger/g,'');
      //reset display
      document.getElementById(DTFieldId+'_display').innerHTML = '';
      //reset hidden
      document.getElementById(DTFieldId).value = '';
    }
  }
}

/**
 * resets field object value
 *
 * @param object oField: HTML object for field
 *
 * @return void
 *
 */
function resetField(oField){
  switch(oField.type){
    case 'text':
    case 'password':
    case 'textarea':
    case 'hidden':
      oField.value = '';
    break;
    case 'radio':
    case 'checkbox':
    	oField.checked = false;
    break;
    case 'select':
    case 'select-one':
    	oField.selectedIndex = 0;
    break;
  }
}

/**
 * resets field value by id
 *
 * @param object fieldId: field's id html attribute
 *
 * @return void
 *
 */
function resetFieldById(fieldId){
	this.resetField(document.getElementById(fieldId));
}

/**
 * turns html textarea input into a rich textarea input using fckeditor
 *
 * @param string inputName
 * @param object oConfig
 * @param boolean bCKFinder whether to integrate also CKFinder
 *
 * @return void
 *
 */
function displayTextareaRich(inputName,oConfig,bCKFinder){
  var oCKeditor = CKEDITOR.replace(inputName,oConfig);
  if(bCKFinder){
		CKFinder.SetupCKEditor(oCKeditor,oApplication.pathToRoot+'kernel/_lib/3d_part/ckfinder/');
	}
}

/**
 * display one of the datetime input fields using jscalendar
 *
 * @param string inputName
 * @param string ifFormat date format for hidden value
 * @param string daFormat date format for display value
 * @param boolean showsTime whether to diplay time selector    
 *
 * @return void
 *
 */
function displayDatetime(inputName,ifFormat,daFormat,showsTime){ 
  var oSettings = new Object();
  oSettings.inputField = inputName;
  oSettings.button = inputName + '_trigger';
  oSettings.displayArea = inputName + '_display';
  oSettings.ifFormat = ifFormat;
  oSettings.daFormat = daFormat;
  oSettings.showsTime = showsTime;
  Calendar.setup(oSettings);
}

/**
 * checks form mandatory field values
 *
 * @param aFieldsGroups array each element rapresents a group and is an object, each object corrisponds to a form field  
 *                      for the form to be validated at least one of the input in each group must have a value or be checked / selected.
 *                      in the most common case a group contains only one input
 *                      aFieldsGroups = [oGroup1,oGroup2,...]
 *                      oGroup1 = {
 *                                name:,
 *                                type:,                                 
 *                                label;,
 *                                aInputs:   
 *                                }    
 *                      aInputs = [oInput1,oInput2,...]
 *                      oInput1 = {
 *                                id:                                   
 *                               } 
 *
 * @return void
 *
 */
function checkMandatories(aFieldsGroups){
  this.highlightInvalid(true);
  this.bValidate = true;
  this.oInvalidFields = new Object();
  //this.oInvalidFields.aIds = new Array();
  //this.oInvalidFields.aLabels = new Array();
  var oGroup;
  var aGroupFields;
  var oInput;
  var oHtmlField;
  for(i in aFieldsGroups){
    oGroup = aFieldsGroups[i];
    switch(oGroup.type){
      case'radio':
      case'checkbox':
        this.checkRadioCheckbox(oGroup);
      break;
      case'select':
        this.checkSelect(oGroup);
      break;
      case 'textarearich':
        this.checkTextareaRich(oGroup);
      break;
      default:
        this.checkTextValue(oGroup);
      break;
    }
  }
  this.highlightInvalid(false);
  this.alertInvalid();
  return this.bValidate;
}

/**
 * alerts for mandatory incomplete fields
 *
 * @param boolean bRestore whether to restore to default labels previously highlighted
 *
 * @return void    
 *
 */
function highlightInvalid(bRestore){
  if(this.bValidate === false){
    var labelClass = bRestore ? 'form_label_box' : 'form_label_box_invalid';
    var oRule;
    var id;
    for(rule in this.oInvalidFields){
      oRule = this.oInvalidFields[rule];
      for(j in oRule.aIds){
        id = oDisplayManager.cleanId(oRule.aIds[j]);
        //try and find the label box
				if(document.getElementById('form_label_box_'+id)){
					var labelClass = bRestore ? 'form_label_box' : 'form_label_box_invalid';
					//cross browser set css class method
        	document.getElementById('form_label_box_'+id).setAttribute((document.all ? 'className' : 'class'),labelClass);
        //else try to highlight all of the box becouse it could be a non-label field such as checkbox or radio group 
				}else if(document.getElementById('form_field_box_'+id)){
					var labelClass = bRestore ? 'form_field_box' : 'form_label_box_invalid';
        	document.getElementById('form_field_box_'+id).setAttribute((document.all ? 'className' : 'class'),labelClass);
        }
      }
    }
  }
}

/**
 * alerts for mandatory incomplete fields
 *
 * @return void
 *
 */
function alertInvalid(){
  var aMsg = new Array();
  if(!this.bValidate){
    //var msg = oTxts.mandatories;
    //msg += this.oInvalidFields.aLabels.join(',');
    for(rule in this.oInvalidFields){
      var msg = oTxts.oMandatories[rule];
      msg += this.oInvalidFields[rule].aLabels.join(',');
      aMsg.push(msg);
    }
    alert(aMsg.join('\n'));
  }
}

/**
 * validates a field value according to group validation rules
 *
 * @param fieldType: type of field, not strictly html type 
 *  but corresponding to this.check[fieldType]Value() method 
 * @param inputId
 * @param oGroup    
 *
 * @return boolean for validation result
 *
 */
function validateGroup(fieldType,inputId,oGroup){
  var aValidationRules = oGroup.aValidationRules;
  var oRule;
  var bValidate;
  var label;
  for(i in aValidationRules){
    oRule = aValidationRules[i];
    bValidate = true;
    switch(oRule.type){
      //standard validation, not null
      case "std":
        label = oGroup.label;
        switch(fieldType){
          case "text":
            //bValidate = (document.getElementById(inputId).value != "");
            bValidate = (this.getFieldValue('text',inputId) != "");
          break;
          case "textarearich":
            var oEditor = FCKeditorAPI.GetInstance(inputId);
            bValidate = oEditor.GetXHTML(true);
          break;
          case "select":
            /*var oSelect = document.getElementById(inputId);
            var selectedIndex = oSelect.selectedIndex;
            var selectedValue = oSelect.options[selectedIndex].value;*/
            var selectedValue = this.getFieldValue('select',inputId);
            bValidate = (selectedValue !== false && selectedValue != 0 && selectedValue != '');
          break;
          case "radiocheckbox":
            for(i in oGroup.aInputs){
              oInput = oGroup.aInputs[i];
              var inputId = oDisplayManager.cleanId(oInput.id);
              bValidate = (document.getElementById(inputId).checked);
              if(bValidate) break;
            }
          break;
        }
      break;
      //fixed length
      case "len":
        label = oGroup.label+' ('+oRule.fixedLength+')';
        switch(fieldType){
          case "text":
            bValidate = (!document.getElementById(inputId).value) || (document.getElementById(inputId).value.length == oRule.fixedLength);
          break;
          case "textarearich":
            var oEditor = FCKeditorAPI.GetInstance(inputId);
            //bValidate = oEditor.GetXHTML(true);
            alert('validation rule of type len not yet implemented for textarearich fields');
          break;
          case "select":
            alert('validation rule of type len doesn\'t make sense for textarearich fields...');
          break;
          case "radiocheckbox":
            alert('validation rule of type len doesn\'t make sense for radiocheckbox fields...');
          break;
        }
      break;
      //minimum length
      case "lmi":
        label = oGroup.label+' ('+oRule.lengthMin+')';
        switch(fieldType){
          case "text":
            bValidate = (!document.getElementById(inputId).value) || (document.getElementById(inputId).value.length >= oRule.lengthMin);
          break;
          case "textarearich":
            var oEditor = FCKeditorAPI.GetInstance(inputId);
            //bValidate = oEditor.GetXHTML(true);
            alert('validation rule of type len not yet implemented for textarearich fields');
          break;
          case "select":
            alert('validation rule of type len doesn\'t make sense for select fields...');
          break;
          case "radiocheckbox":
            alert('validation rule of type len doesn\'t make sense for radiocheckbox fields...');
          break;
        }
      break;
      //length range
      case "ler":
        label = oGroup.label+' ('+oRule.lengthMin+'-'+oRule.lengthMax+')';
        switch(fieldType){
          case "text":
            bValidate = (!document.getElementById(inputId).value) || (document.getElementById(inputId).value.length >= oRule.lengthMin && document.getElementById(inputId).value.length <= oRule.lengthMax);
          break;
          case "textarearich":
            var oEditor = FCKeditorAPI.GetInstance(inputId);
            //bValidate = oEditor.GetXHTML(true);
            alert('validation rule of type len not yet implemented for textarearich fields');
          break;
          case "select":
            alert('validation rule of type len doesn\'t make sense for select fields...');
          break;
          case "radiocheckbox":
            alert('validation rule of type len doesn\'t make sense for radiocheckbox fields...');
          break;
        }
      break;
      //email format
      case "ema":
        label = oGroup.label;
        switch(fieldType){
          //only text type, of curse
          case "text":
            var email = document.getElementById(inputId).value;
            var emailRegEx = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
            bValidate = (!document.getElementById(inputId).value) || (email.match(emailRegEx));
          break;
        }
      break;
      //numbers only
      case "num":
        label = oGroup.label;
        switch(fieldType){
          //only text type, of curse
          case "text":
            var value = document.getElementById(inputId).value;
            var emailRegEx = /^([0-9])*$/;
            bValidate = value.match(emailRegEx);
          break;
        }
      break;
      //numbers only
      case "flo":
        label = oGroup.label;
        switch(fieldType){
          //only text type, of curse
          case "text":
            var value = document.getElementById(inputId).value;
            var emailRegEx = /^([0-9]+,+[0-9]{2})*$/;
            bValidate = value.match(emailRegEx);
          break;
        }
      break;
      //numbers and letters only
      case "nlo":
        label = oGroup.label;
        switch(fieldType){
          //only text type, of curse
          case "text":
          case "password":
            var value = document.getElementById(inputId).value;
            var emailRegEx = /^([0-9a-zA-z])*$/;
            bValidate = value.match(emailRegEx);
          break;
        }
      break;
      //equal value with another field
      case "eta":
        label = this.getFieldLabel(oRule.otherInputId)+', '+oGroup.label;
        switch(fieldType){
          case "text":
            var value = document.getElementById(inputId).value;
            var otherFieldValue = document.getElementById(oRule.otherInputId).value;
            bValidate = value == otherFieldValue;
          break;
        }
      break;
      //mutual exclusion with other fields
      case "exc":
        label = oRule.excludeFieldsIds.join(',');
        bValidate = true;
        var bThisIsFilled = false;
        switch(fieldType){
          case "text":
          case "hidden":
            bThisIsFilled = (document.getElementById(inputId).value != "");
          break;
          case "textarearich":
            var oEditor = FCKeditorAPI.GetInstance(inputId);
            bThisIsFilled = oEditor.GetXHTML(true);
          break;
          case "select":
            var oSelect = document.getElementById(inputId);
            var selectedIndex = oSelect.selectedIndex;
            var selectedValue = oSelect.options[selectedIndex].value;
            bThisIsFilled = (selectedValue !== false && selectedValue != 0 && selectedValue != '');
          break;
          case "radiocheckbox":
            for(i in oGroup.aInputs){
              oInput = oGroup.aInputs[i];
              var inputId = oDisplayManager.cleanId(oInput.id);
              bThisIsFilled = (document.getElementById(inputId).checked);
              if(bThisIsFilled) break;
            }
          break;
        }
        if(bThisIsFilled){
					var aOtherFieldsIds = oRule.excludeFieldsIds.split('|');
					var otherFieldId,oOtherField;
					for(i in aOtherFieldsIds){
						otherFieldId = aOtherFieldsIds[i];
						if(otherFieldId == inputId) continue;
						oOtherField = document.getElementById(otherFieldId);
						if(oOtherField.value){
							bValidate = false;
						}
					}
				}
      break;
      //mutual inclusion with other fields
      case "inc":
        label = this.getFieldLabel(inputId);
        bValidate = true;
        var bThisIsFilled = this.hasFieldValue(fieldType,inputId);
				var aOtherFieldsIds = oRule.includeFieldsIds.split('|');
				var otherFieldId,oOtherField;
				for(i in aOtherFieldsIds){
					otherFieldId = aOtherFieldsIds[i];
					if(otherFieldId == inputId) continue;
					oOtherField = document.getElementById(otherFieldId);
					if((bThisIsFilled && !this.hasFieldValue(oOtherField.type,otherFieldId)) || (!bThisIsFilled && this.hasFieldValue(oOtherField.type,otherFieldId))){
						bValidate = false;
					}
				}
      break;
      //custom methods:MUST have a method property and an oTxts.oMandatories[oRule.type] message
      default:
        label = (oRule.bDeleteLabel) ? '' : oGroup.label;
        switch(fieldType){
          case "text":
            var value = this.getFieldValue('text',inputId);
            bValidate = eval(oRule.method+'(\''+value+'\')');
          break;
          default:
          	bValidate = eval(oRule.method+'()');
          break;
        }
      break;
    }
    if(!bValidate){
      this.bValidate = false;
      if(!this.oInvalidFields[oRule.type]){
        this.oInvalidFields[oRule.type] = new Object();
      }
      if(!this.oInvalidFields[oRule.type].aIds){
        this.oInvalidFields[oRule.type].aIds = new Array();
      }
      if(!this.oInvalidFields[oRule.type].aLabels){
        this.oInvalidFields[oRule.type].aLabels = new Array();
      }
      this.oInvalidFields[oRule.type].aIds.push(oGroup.id);
      //if there is no label it could be a single-field-form with no need for label
      //so try to use form title
      if(!label) label = this.getFormTitle();
      this.oInvalidFields[oRule.type].aLabels.push(label);
    }
  }
}

/**
 * checks a group of form fields with plain text value (text,password,hidden, normal textarea)
 *
 * @param oGroup array with inputs objects
 *                      oGroup = {
 *                                name:,
 *                                type:,                                 
 *                                label:, 
 *                                aInputs:,
 *                                aValidationRules:    
 *                                }    
 *                      aInputs = [oInput1,oInput2,...]
 *                      oInput1 = {
 *                                id:                                   
 *                               }
 *                      aValidationRules = [oRule1,oRule2,...]
 *                      oRule1 = {
 *                                type:validation type 
 *                                property1:property1value,...                                   
 *                               } 
 *
 * @return void
 *
 */
function checkTextValue(oGroup){
  var oInput;
  var bValidate = true;
  for(i in oGroup.aInputs){
    oInput = oGroup.aInputs[i];
    var id = oDisplayManager.cleanId(oInput.id);
    /*
    if(document.getElementById(id).value == ''){
      bValidate = false;
      break;
    }
    */
    bValidate = this.validateGroup('text',id,oGroup);
    if(!bValidate) break;
  }
  /*
  if(!bValidate){
    this.bValidate = false;
    this.oInvalidFields.aIds.push(oGroup.id);
    this.oInvalidFields.aLabels.push(oGroup.label);
  }
  */
}

/**
 * checks a group of textareas rich
 *
 * @param oGroup array with inputs objects
 *                      oGroup = {
 *                                name:,
 *                                type:,                                 
 *                                aInputs:,
 *                                aValidationRules:    
 *                                }    
 *                      aInputs = [oInput1,oInput2,...]
 *                      oInput1 = {
 *                                id:                                   
 *                               }
 *                      aValidationRules = [oRule1,oRule2,...]
 *                      oRule1 = {
 *                                type:validation type 
 *                                property1:property1value,...                                   
 *                               }    
 *
 * @return void
 *
 */
function checkTextareaRich(oGroup){
  var oInput;
  var bValidate = true;
  var oEditor;
  for(i in oGroup.aInputs){
    oInput = oGroup.aInputs[i];
    var id = oDisplayManager.cleanId(oInput.id);
    /*
    oEditor = FCKeditorAPI.GetInstance(oInput.id);
    if(!oEditor.GetXHTML(true)){ 
      bValidate = false;
      break;
    }
    */
    bValidate = this.validateGroup('textarearich',id,oGroup);
    if(!bValidate) break;
  }
  /*
  if(!bValidate){
    this.bValidate = false;
    this.oInvalidFields.aIds.push(oGroup.id);
    this.oInvalidFields.aLabels.push(oGroup.label);
  }
  */
}

/**
 * checks a select
 *
 * @param oGroup array with inputs objects
 *                      oGroup = {
 *                                name:,
 *                                type:,                                 
 *                                label;,
 *                                aInputs:,
 *                                aValidationRules:    
 *                                }    
 *                      aInputs = [oInput1,oInput2,...]
 *                      oInput1 = {
 *                                id:                                   
 *                               }
 *                      aValidationRules = [oRule1,oRule2,...]
 *                      oRule1 = {
 *                                type:validation type 
 *                                property1:property1value,...                                   
 *                               }    
 *
 * @return void
 *
 */
function checkSelect(oGroup){
  // a select always has one input
  /*
  var id = oDisplayManager.cleanId(oGroup.aInputs[0].id);
  var oSelect = document.getElementById(id);
  var selectedIndex = oSelect.selectedIndex;
  var selectedValue = oSelect.options[selectedIndex].value;
  if(selectedValue === false || selectedValue == 0 || selectedValue == ''){
    this.bValidate = false;
    this.oInvalidFields.aIds.push(oGroup.id);
    this.oInvalidFields.aLabels.push(oGroup.label);
  }
  */
  var id = oDisplayManager.cleanId(oGroup.aInputs[0].id);
  this.validateGroup('select',id,oGroup);
  /*
  if(!bValidate){
    this.bValidate = false;
    this.oInvalidFields.aIds.push(oGroup.id);
    this.oInvalidFields.aLabels.push(oGroup.label);
  }
  */
}

/**
 * checks a radio or checkbox group
 *
 * @param oGroup array with inputs objects
 *                      oGroup = {
 *                                type:,
 *                                label;,
 *                                aInputs:,
 *                                aValidationRules:    
 *                                }    
 *                      aInputs = [oInput1,oInput2,...]
 *                      oInput1 = {
 *                                id:                                   
 *                               }
 *                      aValidationRules = [oRule1,oRule2,...]
 *                      oRule1 = {
 *                                type:validation type 
 *                                property1:property1value,...                                   
 *                               }    
 *
 * @return void
 *
 */
function checkRadioCheckbox(oGroup){
  this.validateGroup('radiocheckbox',false,oGroup);
  /*
  var bValidate = false;
  var oInput;
  for(i in oGroup.aInputs){
    oInput = oGroup.aInputs[i];
    var id = oDisplayManager.cleanId(oInput.id);
    //if(document.getElementById(id).checked){
    //  return;
    //}
    bValidate = this.validateGroup('radiocheckbox',id,oGroup.aValidationRules);
    if(bValidate) break;
  }
  */
  /*
  if(!bValidate){
    this.bValidate = false;
    this.oInvalidFields.aIds.push(oGroup.id);
    this.oInvalidFields.aLabels.push(oGroup.label);
  }
  */
}

/**
 * gets the list of selectable items for a foreign list
 *
 * @param string inputName
 * @param string pathToPage path to reach page that returns list  
 *
 * @return void
 *
 */
function getForeignSelect(inputName,pathToPage){
  //get current value if any 
	var currentValue = document.getElementById(inputName).value;
  if(currentValue) pathToPage += '&selected_value='+currentValue;
  //show list container
  var displayState = oDisplayManager.switchElementDisplay(inputName+'_selection_container','none');
  if(displayState == 'block'){
    //set loading image
    var oForeignListContainer = document.getElementById(inputName+'_selection_container');
    oForeignListContainer.innerHTML = '<img alt="loading..." src="'+oApplication.pathToRoot+'kernel/etc/images/loading_bar.gif" />';
    oApplication.makeAjaxCall(pathToPage,'fillForeignSelect',{inputName:inputName});
  }
}

/**
 * displays foreign list
 *
 * @param string inputName
 *
 * @return void
 *
 */
function fillForeignSelect(response,inputName){
  var oForeignListContainer = document.getElementById(inputName+'_selection_container');
  oForeignListContainer.innerHTML = response;
}

/**
 * gets the list of selectable items for a foreign list
 *
 * @param string inputName
 * @param string selectedId
 * @param string selectedDisplay  
 *
 * @return void
 *
 */
function selectForeignRecord(inputName,selecteId,selectedDisplay){
  //close list
  oDisplayManager.switchElementDisplay(inputName+'_selection_container');
  //set display
  var oDisplay = document.getElementById(inputName+'_display');
  oDisplay.value = selectedDisplay;
  //set value
  document.getElementById(inputName).value = selecteId;
  //fire onchange event on hidden field in case an onchange script has been set
  if(document.getElementById(inputName).onchange) document.getElementById(inputName).onchange();
}

/**
 * generates a random password and displays it into a given text field
 *
 * @param string targetId: if of text iput to display password into
 * @param string length: password length
 *
 * @return void
 *
 */
function generatePassword(targetId,length){
	document.getElementById(targetId).value = oVarManipulator.generateRandomString(length);
}

/**
 * Fast javascript function to clear all the options in an HTML select element
 * Provide the id of the select element
 * References to the old <select> object will become invalidated!
 * grabbed from http://www.somacon.com/p542.php 
 *
 * @param string selectId
 *
 * @return object reference to the new select object
 *
 */
function emptySelect(selectId){
	var selectObj = document.getElementById(selectId);
	var selectParentNode = selectObj.parentNode;
	var newSelectObj = selectObj.cloneNode(false); // Make a shallow copy
	selectParentNode.replaceChild(newSelectObj, selectObj);
	return newSelectObj;
}

/**
 * empties and re-fills a select
 *
 * @param string selectId
 * @param string aOptions: array with options objects
 * 							[{typePropertyName:optgroup | option,valuePropertyName:value,labelPropertyName:label}]  
 * @param string valuePropertyName: name of objects properties which holds value information  
 * @param string labelPropertyName: name of objects properties which holds label information  
 * @param string optgroupPropertyName: name of objects properties which holds optgroup information (if any)
 * @param string oOptionZero: option object with first option to be added
 * 								{value:,label:}     
 * @param string selectedValue 
 *
 * @return void
 *
 */
function fillSelect(selectId,aOptions,valuePropertyName,labelPropertyName,optgroupPropertyName,oOptionZero,selectedValue){
	//empty 
	var oSelect = this.emptySelect(selectId);
	var oHTMLOption,oHTMLOptgroup;
	if(oOptionZero){
		oHTMLOption = oDisplayManager.createElementWithAttributes('option',false,{value:oOptionZero.value});
		oHTMLOption.innerHTML = oOptionZero.label;
		oSelect.appendChild(oHTMLOption);
	}
	var oCurContainer = oSelect;
	var curOptgroup;
	for(i in aOptions){
		oOption = aOptions[i];
		if(optgroupPropertyName && oOption[optgroupPropertyName] && oOption[optgroupPropertyName] != curOptgroup){
			curOptgroup = oOption[optgroupPropertyName];
			oHTMLOptgroup = oDisplayManager.createElementWithAttributes('optgroup',false,{label:curOptgroup});
			oSelect.appendChild(oHTMLOptgroup);
			oCurContainer = oHTMLOptgroup;
		}
		var oAttributes = {value:oOption[valuePropertyName]};
		if(selectedValue && oOption[valuePropertyName] == selectedValue) oAttributes.selected = 'selected';
		oHTMLOption = oDisplayManager.createElementWithAttributes('option',false,oAttributes);
		oHTMLOption.innerHTML = oOption[labelPropertyName];
		oCurContainer.appendChild(oHTMLOption);
	}
}

/**
 * starts monitoring the upload progress bar
 *
 * @param string formId
 * @param string redirectUrl  
 * @param string successMessage  
 *  
 * @return void  
 *
 */
function startProgressBarMonitor(formId,redirectUrl,successMessage){
	this.formId = formId;
	this.oHTTPUpload = new Object();
	this.oHTTPUpload.redirectUrl = redirectUrl;
	this.oHTTPUpload.successMessage = successMessage;
	this.getProgressBarStatus(true);
	var oDate = new Date();
	this.oHTTPUpload.startTime = Math.round(oDate.getTime() / 1000);
	document.getElementById(formId+'_progress_bar_container').style.visibility = 'visible';
}

/**
 * stops monitoring the upload progress bar
 *
 * @return void
 *
 */
function stopProgressBarMonitor(){
	if(this.oHTTPUpload.redirectUrl){
		if(this.oHTTPUpload.successMessage && !this.oHTTPUpload.bError) alert(this.oHTTPUpload.successMessage);
		window.location = this.oHTTPUpload.redirectUrl;
	}
}

/**
 * get upload progress bar stauts
 *
 * @param boolean bFirst: whether it is first call (and thus htpp upload total size  must be retrieved)
 *  
 * @return void  
 *
 */
function getProgressBarStatus(bFirst){
	var progressKey = document.getElementById('APC_UPLOAD_PROGRESS').value;
	var pathToPage = 'kernel/_bin/ajax.php?application=memory_manager&method=apc_fetch_key_ajax&apc_key='+progressKey;
	var oCallbackParameters = (bFirst) ? {bFirst:true} : {bFirst:false};
	oApplication.makeAjaxCall(oApplication.pathToRoot+pathToPage,'oFormBuilder.progressBarStatusGot',oCallbackParameters);
}

/**
 * processes APC data
 *
 * @param string response
 * @param boolean bFirst: whether it is first call (and thus htpp upload total size  must be retrieved) 
 *  
 * @return void
 *
 */
function progressBarStatusGot(response,bFirst){
	//response contains apc upload array aAPC definition
	eval(response);
	if(aAPC){
		//init values
		if(bFirst){
			this.oHTTPUpload.totalSize = Number(aAPC['total']);
			document.getElementById(this.formId+'_progress_bar_data_size_value').innerHTML = oVarManipulator.displayBytes(this.oHTTPUpload.totalSize);
		}
		//transeferred
		this.oHTTPUpload.currentlyTransferred = Number(aAPC['current']);
		//elapsed time
		var oDate = new Date();
		this.oHTTPUpload.elapsedTime = Math.round(oDate.getTime() / 1000) - this.oHTTPUpload.startTime;
		//speed
		this.oHTTPUpload.speed = Math.round(this.oHTTPUpload.currentlyTransferred / this.oHTTPUpload.elapsedTime);
		//remaining time
		this.oHTTPUpload.remainingTime = Math.round((this.oHTTPUpload.totalSize - this.oHTTPUpload.currentlyTransferred) / this.oHTTPUpload.speed);
		//progress percent
		if(this.oHTTPUpload.currentlyTransferred >= this.oHTTPUpload.totalSize) this.oHTTPUpload.progress = 100;
		else this.oHTTPUpload.progress = Math.round(this.oHTTPUpload.currentlyTransferred / this.oHTTPUpload.totalSize * 100);
		//update display
		this.updateProgressBar();
	}
	//stop or continue
	if(this.oHTTPUpload.progress == 100) this.stopProgressBarMonitor();
	else setTimeout("oFormBuilder.getProgressBarStatus()",500);
}

/**
 * update HTML progress bar elements
 *
 * @return void
 *
 */
function updateProgressBar(){
	document.getElementById(this.formId+'_progress_bar_cursor').style.width = this.oHTTPUpload.progress+'%';
	document.getElementById(this.formId+'_progress_bar_cursor_label').innerHTML = this.oHTTPUpload.progress+'%';
	document.getElementById(this.formId+'_progress_bar_data_elapsed_time_value').innerHTML = oVarManipulator.displaySecondsToTime(this.oHTTPUpload.elapsedTime);
	document.getElementById(this.formId+'_progress_bar_data_remaining_time_value').innerHTML = oVarManipulator.displaySecondsToTime(this.oHTTPUpload.remainingTime);
	
}

function autocompleteLaunch(valueId,oTextElement,aSourcesIds,application,method,minChars){
	//if(oElement.id && oElement.value && oElement.value.length >= minChars){
	if(oTextElement.id){
		if(oTextElement.value.length >= minChars){
			var fileToLoad = oApplication.pathToRoot+'kernel/_bin/ajax.php?application='+application+'&method='+method+'&value_id='+valueId+'&text_id='+oTextElement.id;
			for(i in aSourcesIds){
				fileToLoad += '&a_autocomplete_tokens[]='+document.getElementById(aSourcesIds[i]).value;
			} 
			oApplication.makeAjaxCall(fileToLoad,'oFormBuilder.autocompleteGot',{valueId:valueId,textId:oTextElement.id});
		}else{
			this.autocompleteDestroy(valueId);
		}
	}
}

function autocompleteGot(response,valueId,textId){
	if(document.getElementById(valueId)){
		if(!document.getElementById(valueId+'_autocomplete')){
			var oTextElement = document.getElementById(textId);
			var oDimensions = oDisplayManager.getElementDimensions(textId);
			oAttrs = {id:valueId+'_autocomplete'
							//,class:'autocomplete_container'
							,style:'margin-top:'+(oDimensions.height+2)+'px'
							};
			oAttrs['class'] = 'autocomplete_container';
			
			var oContainer = oDisplayManager.createElementWithAttributes('div',false,oAttrs);
			oContainer.innerHTML = response;
			oTextElement.parentNode.insertBefore(oContainer,oTextElement);
		}else{
			document.getElementById(valueId+'_autocomplete').innerHTML = response;
		}
	} 
}

function autocompleteDestroy(valueId){
	if(document.getElementById(valueId+'_autocomplete')){
		var oContainer = document.getElementById(valueId+'_autocomplete');
		oContainer.parentNode.removeChild(oContainer);
	}
}

function autocompleteDestroyLaunch(valueId){
	setTimeout("oFormBuilder.autocompleteDestroy('"+valueId+"')",100);
}

function autocompleteSelect(valueId,value,elementLabelId,label,callbackFunction){
	if(document.getElementById(valueId)){
		document.getElementById(valueId).value = value;
		if(elementLabelId && document.getElementById(elementLabelId)){
			document.getElementById(elementLabelId).value = label;
		}
		this.autocompleteDestroy(valueId);
		if(callbackFunction) eval(callbackFunction+'()');
	}
}

function checkMaxChar(fieldId,maxLength,displayId){
	if(document.getElementById(fieldId)){
		maxLength = new Number(maxLength);
		var oField = document.getElementById(fieldId);
		if (oField.value.length > maxLength){
			oField.value = oField.value.substring(0,maxLength);
		}
		if(displayId && document.getElementById(displayId)){
			document.getElementById(displayId).innerHTML = maxLength - oField.value.length;
		}
	}
}
