//
//  Class:
//      VdfField
//
//  Wrapper for html form elements representing an Database field. With this 
//  wrapper all elements (radio, text, select) have the same interface to talk 
//  to.
//
//  Since:
//      20-01-2006
//  Changed:
//      --
//  Version:
//      0.9
//  Creator:
//      Data Access Europe (Harm Wibier)
//


//
//  Constructor of VdfField class.
//
//  Params:
//      eField      The form element to wrap
//      oVdfForm    The VdfForm form for fetching information
//  
function VdfField(eField, oVdfForm, sDataBinding){    
    if(typeof(oVdfForm) == "undefined"){
        this.oVdfForm           = null;
    }else{
        this.oVdfForm           = oVdfForm;
    }

    this.eElement               = eField;

    //  Determine type
    if((eField.tagName == "INPUT" && eField.type != "button") || eField.tagName == "SELECT" || eField.tagName == "TEXTAREA"){
        if(eField.tagName == 'SELECT'){
            this.sType              = 'select';
        }else if(eField.tagName == "TEXTAREA"){
            this.sType = "textarea";
        }else{
            this.sType              = eField.type.toLowerCase();
        }
    }else{
        this.sType = "dom"
    }
    
    //  Determine names   
    this.sDataBinding           = sDataBinding;
    if(this.sDataBinding.indexOf('__') > -1){
        this.sTable                 = this.sDataBinding.substr(0, this.sDataBinding.indexOf('__'));
        this.sField                 = this.sDataBinding.substr(this.sDataBinding.indexOf('__') + 2);
    }else{
        this.sTable = "";
        this.sField = "";
    }
    
    
    //  TYPE Specific properties and functionality
    if (this.sType == "select"){
        if(oVdfForm != null){
            //  Fill with descriptionvalues if available
            var aDescriptionValues = oVdfForm.getVdfFieldAttribute(this, "aDescriptionValues");
            
            if(aDescriptionValues != null){
                for (var iCount = 0; iCount < aDescriptionValues.length; iCount++){
                    eField.options[iCount] = new Option((this.bUseDescriptionValue ? aDescriptionValues[iCount].sDescription : aDescriptionValues[iCount].sValue), aDescriptionValues[iCount].sValue);
                    if(aDescriptionValues[iCount].sValue == this.sDefaultValue) eField.selectedIndex = iCount;
                }
            }
        }
    }else if(this.sType == "radio"){
        this.aElements          = new Object();
        this.addElement(eField);
        
    
    }else if(this.sType == "checkbox"){
        
        //  Fetch checked and unchecked values from DD
        this.sCheckedValue      = "1";
        this.sUncheckedValue    = "0";
        if(oVdfForm != null){
            if(oVdfForm.getVdfFieldAttribute(this, "sCheckboxCheckedValue") != null){
                this.sCheckedValue = oVdfForm.getVdfFieldAttribute(this, "sCheckboxCheckedValue");
            }
            if(oVdfForm.getVdfFieldAttribute(this, "sCheckboxUncheckedValue") != null){
                this.sUncheckedValue = oVdfForm.getVdfFieldAttribute(this, "sCheckboxUncheckedValue");
            }
        }
    }
    eField.oVdfField        = this;
    
    //  Set datatype class for alignment (if no css class is set)
    if(this.oVdfForm != null){
        if(this.getCSSClass() == null || this.getCSSClass() == ""){
            this.setCSSClass(this.oVdfForm.getVdfFieldAttribute(this, "sDataType") + "_data");
        }
    }
    
    //  Sets the sOrigValue
    if(this.sType == "text" || this.sType == "textarea"){
        this.sOrigValue = eField.value;
    }else{
        //  Workaround because special elements should always be saved with new record
        this.sOrigValue = "";
    }
    
    this.sOrigDisplayValue = this.getValue();
}

//
//  Add elements for field of a type that contain more elements (radio..)
//
//  Param:
//      eField  Element to add
//
VdfField.prototype.addElement = function(eField){
    if(this.sType == 'radio'){
        this.aElements[eField.value] = eField;
        if(eField.checked){
            this.sOrigDisplayValue = eField.value;
        }
        
        eField.oVdfField = this;
    }
    
    this.sOrigDisplayValue = this.getValue();
}

//
//  Returns:
//      String with the field type (select, radio, text, checkbox etc..)
//
//  DEPRECATED
VdfField.prototype.getType = function(){
    return this.sType;
}

//
//  Returns:
//      The html form element (or an array of elements)
//
VdfField.prototype.getElement = function(){
    var oResult = null;
    
    if(this.sType == 'radio'){
        oResult = this.aElements;
    }else{
        oResult = this.eElement;
    }
    
    return oResult;
}

//
//  Returns:
//      The servertable of the field
//
//  DEPRECATED
VdfField.prototype.getServerTable = function(){
    return this.sServerTable;
}

//
//  Sets the servertable if not set already.
//
//  Params:
//      sNewServerTable New server table for the field
//      bOverwriteOrig  If true the new server table is always set
//
//  PRIVATE
VdfField.prototype.setServerTable = function(sNewServerTable, bOverwriteOrig){
    if(bOverwriteOrig || this.sServerTable == null){
        this.sServerTable = sNewServerTable;
    }
}

//
//  Returns:
//      The current (selected)value of the field
//
VdfField.prototype.getValue = function(){
    var sValue = '', sCurrentValue;
    
    if(this.sType == 'radio'){
        for(sCurrentValue in this.aElements){
            if(this.aElements[sCurrentValue].checked){
                sValue = sCurrentValue;
            }
        }
    }else if(this.sType == "checkbox"){
        sValue = (this.eElement.checked ? this.sCheckedValue : this.sUncheckedValue);
    }else if(this.sType == "dom"){
        sValue = browser.dom.getElementText(this.eElement);
    }else{
        sValue = this.eElement.value;
    }
    
    return sValue;
}

//
//  Set the value of the field
//
//  Params:
//      sValue  The new field value
//      bReset  If true the startvalue and changedstate are resetted 
//              (default: false)
//
VdfField.prototype.setValue = function(sValue, bReset){
    var sElement;
    
    if(typeof(bReset) == "undefined"){
        var bReset = false;
    }
    
    //  If needed reset the origvalue used for the changedstate
    if(bReset){
        this.sOrigValue = sValue;
    }
    
    if(this.sType == 'radio'){
        //  If none given select first
        if(sValue == ""){
            for(sElement in this.aElements){
                this.aElements[sElement].checked = true;
                break;
            }
        }
        
        //  Try to select
        if(this.aElements[sValue] != null){
            this.aElements[sValue].checked = true;
        }
    }else if(this.sType == "checkbox"){
        //  Set checked only if new value matches checkedvalue..
        this.eElement.checked = (sValue == this.sCheckedValue);
        this.eElement.defaultChecked = (sValue == this.sCheckedValue);
    }else if(this.sType == "select"){
        //  Select first if no value given
        if(sValue == ""){
            this.eElement.selectedIndex = 0;
        }
        
        //  Try to set the value
        this.eElement.value = sValue;
    }else if(this.sType == "dom"){
        browser.dom.setElementText(this.eElement, sValue);
    }else if(this.sType == "textarea"){
        this.eElement.value = sValue;
        this.sOrigValue = this.getValue();
    }else{
        //  Just set the value
        this.eElement.value = sValue;
    }
    if(this.sDataBinding == "invt__ext"){
        this.sOrigValue = this.getValue();
    }
    if(bReset){
        this.sOrigDisplayValue = this.getValue();
    }
}

//
//  Should be used to set the field to a value from a dataset. Decides using 
//  the bUseDescriptionValue property if the descriptionvalue should be used.
//
//  Params:
//      oDataSet    The dataset to fetch the value from
//      bReset  If true the startvalue and changedstate are resetted 
//              (default: false)
//
VdfField.prototype.setDataSetValue = function(oDataSet, bReset){
    if(typeof(bReset) == "undefined"){
        var bReset = false;
    }

    if(oDataSet.hasValue(this.sDataBinding) || oDataSet.bNew){
        if(this.bUseDescriptionValue && this.sType != "select"){ // Select boxes display the description value but work with the real value
            this.setValue(oDataSet.getDisplayValue(this.sDataBinding), bReset);
        }else{
            this.setValue(oDataSet.getValue(this.sDataBinding), bReset);
        }
    }
}

//
//  Returns:
//      True if the value is not the origional value so it should be saved
//
VdfField.prototype.getChangedState = function(){
    if(this.sType == "dom"){
        return false;
    }else{
        return (this.getValue() != this.sOrigValue);
    }
}

//
//  Returns:
//      True if the user has changed the value since the last reset to determine
//      wheter save is nessacary
//
VdfField.prototype.getDisplayChangedState = function(){
    if(this.sType == "dom"){
        return false;
    }else{
        return (this.getValue() != this.sOrigDisplayValue);
    }
}

//
//  Returns:
//      The name of the element
//
//  DEPRECATED
VdfField.prototype.getName = function(){
    return this.sDataBinding;
}

//
//  Returns:
//      Name of the table
//
//  DEPRECATED
VdfField.prototype.getTableName = function(){
    return this.sTable;
}

//
//  Returns:
//      Name of the field
//
//  DEPRECATED
VdfField.prototype.getFieldName = function(){
    return this.sField;
}

//
//  Params:
//      sName       Name of the attribute
//      sDefault    The value returned if no value found
//  Returns:
//      The vdf value of the field attribute (Use VdfForm.getVdfFieldAttribute 
//      for datadictionary properties!)
//
VdfField.prototype.getVdfAttribute = function(sName, sDefault){
    var sResult, sCurrentValue;

    if(typeof(sDefault) == "undefined"){
        var sDefault = null;
    }
    sResult = sDefault;
    
    if(this.sType == 'radio'){
        for(sCurrentValue in this.aElements){
            sResult = browser.dom.getVdfAttribute(this.aElements[sCurrentValue], sName, sDefault);
            if(sResult != sDefault){
                break;
            }
        }
    }else{
        sResult = browser.dom.getVdfAttribute(this.eElement, sName, sDefault);
    }
    
    return sResult;
}

//
//  Params:
//      sName       The name of the attribute
//      sDefault    The value returned if no value found
//  Returns:
//      Value of the element attribute (null / default if not set)
//
VdfField.prototype.getAttribute = function(sName, sDefault){
    var sResult, sCurrentValue;
    
    if(typeof(sDefault) == "undefined"){
        var sDefault = null;
    }
    
    //  Fetch value
    if(this.sType == "radio"){
        for(sCurrentValue in this.aElements){
            sResult = this.aElements[sCurrentValue].getAttribute(sName);
            if(sResult != null){
                break;
            }
        }
    }else{
        sResult = this.eElement.getAttribute(sName);
    }
    
    //  Set to default and parse boolean
    if(sResult == null){
        sResult = sDefault;
    }else if(typeof(sResult) == "string"){
        if(sResult.toLowerCase() == "true"){
            sResult = true;
        }else if(sResult.toLowerCase() == "false"){
            sResult = false;
        }
    }
    
    return sResult;
}

//
//  Sets the field elements vdf attribute
//
//  Params:
//      sName   Name of the attribute to set
//      sValue  New value of the attribute
//
VdfField.prototype.setVdfAttribute = function(sName, sValue){
    if(this.sType == 'radio'){
        var sCurrentValue;
        for(sCurrentValue in this.aElements){
            browser.dom.setVdfAttribute(this.aElements[sCurrentValue], sName, sValue);
            break;
        }
    }else{
        browser.dom.setVdfAttribute(this.eElement, sName, sValue);
    }
}

//
//  Set the field elements attributes
//
//  Params:
//      sName   Name of the attribute to set
//      sValue  New value of the attribute
//
VdfField.prototype.setAttribute = function(sName, sValue){
    if(this.sType == 'radio'){
        var sCurrentValue;
        for(sCurrentValue in this.aElements){
            this.aElements[sCurrentValue].setAttribute(sName, sValue);
            break;
        }
    }else{
        this.eElement.setAttribute(sName, sValue);
    }
}

//
//  Set the focus to the field and if possible select the text in the element.
//  (with radio elements the selected element will receive the focus)
//
//  Returns:
//      False if element can't receive focus
//
VdfField.prototype.focusSelect = function(){
    var sCurrentValue, bResult = true;
    
    if(this.sType == 'radio'){
        for(sCurrentValue in this.aElements){
            if(this.aElements[sCurrentValue].checked){
                browser.dom.setFocus(this.aElements[sCurrentValue]);
            }
        }
    }else if(this.sType == 'select' || this.sType == "checkbox"){
        browser.dom.setFocus(this.eElement);
    }else if(this.sType == "dom"){
        bResult = false;
    
    }else{
        browser.dom.setFocus(this.eElement);
        this.eElement.select();
    }
    
    return bResult;
}

//
//  Sets the width of the field element
//
//  Params:
//      iPixels     The new width in pixels
//
VdfField.prototype.setWidth = function(iPixels){
    if(this.sType == 'radio'){
    
    }else{
        this.eElement.style.width = iPixels + 'px';
    }
}

//
//  Params:
//      The new css class for the elemnt
//
VdfField.prototype.setCSSClass = function(sClassName){
    if(this.sType == 'radio'){
        var sCurrent;
        for(sCurrent in this.aElements){
            this.aElements[sCurrent].className = sClassName;
        }
    }else{
        this.eElement.className = sClassName;
    }
}

//
//  Returns:
//      The current css class of the (first) element
//
VdfField.prototype.getCSSClass = function(){
    if(this.sType == 'radio'){
        var sCurrent;
        for(sCurrent in this.aElements){
            return this.aElements[sCurrent].className;
        }
        return null;
    }else{
        return this.eElement.className;
    }
}

//
//  Attaches keylistener to the element
//
//  Params:
//      oListener   Method to fetch event
//
VdfField.prototype.addKeyListener = function(oListener){
    if(this.sType == 'radio'){
        var sCurrent;
        for(sCurrent in this.aElements){
            browser.events.addKeyListener(this.aElements[sCurrent], oListener);
        }
    }else{
        browser.events.addKeyListener(this.eElement, oListener);
    }
}


//
//  Attaches keylistener to the element
//
//  Params:
//      oListener   Method to fetch event
//
//  DEPRECATED
VdfField.prototype.addKeyDownListener = function(oListener){
    if(this.sType == 'radio'){
        var sCurrent;
        for(sCurrent in this.aElements){
            browser.events.addKeyDownListener(this.aElements[sCurrent], oListener);
        }
    }else{
        browser.events.addKeyDownListener(this.eElement, oListener);
    }
}

//
//  Attachers generic listener to the element
//
//  Params:
//      sEvent      Name of the event
//      oListener   Method to fetch the event
//
VdfField.prototype.addGenericListener = function(sEvent, oListener){
    if(this.sType == 'radio'){
        var sCurrent;
        for(sCurrent in this.aElements){
            browser.events.addGenericListener(sEvent, this.aElements[sCurrent], oListener);
        }
    }else{
        browser.events.addGenericListener(sEvent, this.eElement, oListener);
    }
}

//
//  Removes keylistener from the element
//
//  Params:
//      oListener   Method to fetch event
//
VdfField.prototype.removeKeyListener = function(oListener){
    if(this.sType == 'radio'){
        var sCurrent;
        for(sCurrent in this.aElements){
            browser.events.removeKeyListener(this.aElements[sCurrent], oListener);
        }
    }else{
        browser.events.removeKeyListener(this.eElement, oListener);
    }
}

//
//  Removes generic listener from the element
//
//  Params:
//      sEvent      Name of the event
//      oListener   Method to fetch the event
//
VdfField.prototype.removeGenericListener = function(sEvent, oListener){
    if(this.sType == 'radio'){
        var sCurrent;
        for(sCurrent in this.aElements){
            browser.events.removeGenericListener(sEvent, this.aElements[sCurrent], oListener);
        }
    }else{
        browser.events.removeGenericListener(sEvent, this.eElement, oListener);
    }
}

//
//  Checks wether the field is a foreign field in the form or not using the 
//  VdfTable.isForeign method and the form maintable setting.
//
//  Returns:
//      True is field is a foreign field
//
VdfField.prototype.isForeign = function(){
    return this.oVdfForm.aTables[this.sTable].isForeign(this.oVdfForm.sMainTable);
}


//  - - - - - - - USER EVENTS - - - - - - - -

//
//  This function is called if the field is validated (only if bValidateClient 
//  = true) and can be used to add custom validation methods. Overriding can be 
//  done in asp file like:
//
//  function initForm(){
//      getVdfControl("form").getField("customer__name").onValidate = function(sDataType){
//          if(this.getValue() == "harm"){
//              VdfErrorHandle(new VdfFieldError(600, "Value harm is not allowed ", this, this.oVdfForm));
//              return false;
//          }else{
//              VdfErrorsClearError(this.sTable, this.sField, 301);
//              return true;
//          }
//      }
//  }
//
//  The function should return true if no validation errors occur. If false is
//  returned the action (save or tabbing out) is cancelled.
//
VdfField.prototype.onValidate = function(sDataType){
    return true;
}