/* $Id: sbiplg.js 21220 2010-12-16 10:07:34Z dve $ */

/**
 * JavaScript interface to the PROMOS Plugin
 *
 * Copyright: (C)2003 SBI AG, Basel
 * All rights reserved.
 *
 * Author: PPo
 **/

// globals, do not access directly
var sbiplg_currentLanguage = 0;
var sbiplg_isInitialized   = false;
var sbiplg_hasShownNotInstalledMsg   = false;

//--------------------------------------------------------------

/**
 * @brief Checks if SBI plugin exists
 *
 * @param interactive If true then a message is displayed
 * when there is no plugin
 *
 * @param force_message If true then a message is displayed
 * in any case if the plugin does not exist. Otherwise it is
 * shown only once. This is intended to avoid multiple display
 * of the error message when page is reloaded.
 *
 * @return true if sbiplg is available, false if not
 **/
function sbiplg_checkExisting(interactive, force_message) {

    try {
        document.sbiplg.compute("dummy");
        return(true);
    }
    catch(e) {
         var msg = new Array(
            "Fehler: Das SBI Plugin ist nicht installiert.",
            "Error: the SBI plugin is not installed.",
            "Erreur: Le plugin SBI n'est pas installé.",
            "Error: Plug-in SBI nie jest zainstalowany.",
            "Error: El Plugin SBI no está instalado.");
        if(interactive && (force_message || !sbiplg_hasShownNotInstalledMsg)) {
            sbiplg_hasShownNotInstalledMsg = true;
            alert(msg[sbiplg_currentLanguage]);
        }
        return(false);
    }

} /* sbiplg_checkExisting() */

//--------------------------------------------------------------

/**
 * @brief initialize plugin with a model
 *
 * ... loads the PROMOS model from the given URL which may
 * be a local or remote file. A new session is created using this
 * model.
 *
 * @param url Location of model to be used
 *
 * @return  -none-
 **/
function sbiplg_init(url) {

    if(!sbiplg_checkExisting(true, false)) return;
    sbiplg_isInitialized = document.sbiplg.loadsession(url);

} /* sbiplg_init() */

//--------------------------------------------------------------

/**
 * @brief session cloning
 *
 * ... clones the actual session into a new session.
 *
 * @return  -none-
 **/
function sbiplg_clone() {

    if(!sbiplg_isInitialized) return;
    document.sbiplg.clonesession();

} /* sbiplg_clone() */

//--------------------------------------------------------------

/**
 * @brief session committing
 *
 * ... commits the the actual cloned session into the origin session.
 *
 * @return  -none-
 **/
function sbiplg_commit() {

    if(!sbiplg_isInitialized) return;
    document.sbiplg.commitsession();

} /* sbiplg_commit() */

//--------------------------------------------------------------

/**
 * @brief session closing
 *
 * ... closes all cloned sessions.
 *
 * @return  -none-
 **/
function sbiplg_closeclones() {

    if(!sbiplg_isInitialized) return;
    document.sbiplg.closeclonedsessions();

} /* sbiplg_closeclones() */

//--------------------------------------------------------------

/**
 * @brief session closing
 *
 * ... closes the actual session.
 *
 * @return  -none-
 **/
function sbiplg_close() {

    if(!sbiplg_isInitialized) return;
    document.sbiplg.closesession();

} /* sbiplg_close() */

//--------------------------------------------------------------

/**
 * @brief direct setting
 *
 * ... sets the value of an attribute defined by name
 *
 * @param attribute
 * @param value
 *
 * @return -none-
 **/
function sbiplg_setvar(attribute, value) {

    if(!sbiplg_isInitialized) return;
    var code = document.sbiplg.setvar(attribute, value);
    if(document.sbiplg.message) alert(document.sbiplg.message);
    return(code);

} /* sbiplg_setvar() */

//--------------------------------------------------------------

/**
 * @brief direct setting
 *
 * ... inserts the value of an attribute defined by name
 *
 * @param attribute
 * @param value
 *
 * @return -none-
 **/
function sbiplg_insertvar(attribute, value) {

    if(!sbiplg_isInitialized) return;
    document.sbiplg.insertvar(attribute, value);
    if(document.sbiplg.message) alert(document.sbiplg.message);

} /* sbiplg_insertvar() */

//--------------------------------------------------------------

/**
 * @brief direct setting
 *
 * ... removes an attribute defined by name
 *
 * @param attribute
 *
 * @return -none-
 **/
function sbiplg_removevar(attribute) {

    if(!sbiplg_isInitialized) return;
    document.sbiplg.removevar(attribute);
    if(document.sbiplg.message) alert(document.sbiplg.message);

} /* sbiplg_removevar() */

//--------------------------------------------------------------

/**
 * @brief direct setting
 *
 * ... swaps attribute values defined by name
 *
 * @param attribute
 *
 * @return -none-
 **/
function sbiplg_swapvar(attribute1, attribute2) {

    if(!sbiplg_isInitialized) return;
    document.sbiplg.swapvar(attribute1, attribute2);
    if(document.sbiplg.message) alert(document.sbiplg.message);

} /* sbiplg_swapvar() */

//--------------------------------------------------------------

/**
 * @brief direct getting
 *
 * ... computes the value of a property defined by name. If the
 * calculation is successful with return code == 0, the result
 * will be stored in document.sbiplg.result.
 *
 * @param property
 *
 * @return return code
 **/
function sbiplg_compute(property) {

    if(!sbiplg_isInitialized) return(-1);
    var code = document.sbiplg.compute(property);
    if(document.sbiplg.message) alert(document.sbiplg.message);
    return(code);

} /* sbiplg_compute() */

//--------------------------------------------------------------

/**
 * @brief direct getting
 *
 * ... returns the actual path for temporary files.
 *
 * @return path to temporary files
 **/
function sbiplg_pathTmp() {

    return(document.sbiplg.pathtmp);

} /* sbiplg_pathTmp() */

//--------------------------------------------------------------

/**
 * @brief direct getting
 *
 * ... returns the actual user name.
 *
 * @return user name
 **/
function sbiplg_userName() {

    return(document.sbiplg.username);

} /* sbiplg_userName() */

//--------------------------------------------------------------

/**
 * @brief debugging

 * ... prints a message text to the debugger device specified in
 * promos.ini
 *
 * @param message text to be printed
 *
 * @return  -none-
 **/
function sbiplg_debugPrint(message) {

    if(!sbiplg_isInitialized) return;
    document.sbiplg.debugout(message);

} /* sbiplg_debugPrint() */

//--------------------------------------------------------------

/**
 * @brief debugging
 *
 * ... prints a message text with a terminating newline to the
 * debugger device specified in promos.ini
 *
 * @param message text to be printed
 *
 * @return  -none-
 **/
function sbiplg_debugPrintLine(message) {

    if(!sbiplg_isInitialized) return;
    document.sbiplg.debugout(message + String.fromCharCode(13,10));

} /* sbiplg_debugPrintLine() */

//--------------------------------------------------------------

/**
 * @brief import/export
 *
 * ... reads xml data from specific file into the opened PROMOS
 * session
 *
 * @param filename
 *
 * @return  -none-
 **/
function sbiplg_readXmlData(filename) {

    if(!sbiplg_isInitialized) return(0);
    var datalen = document.sbiplg.readdata(filename);
    if(datalen > 0) document.sbiplg.restorexmlsession();
    return(datalen);

} /* sbiplg_readXmlData() */

//--------------------------------------------------------------

/**
 * @brief import/export
 *
 * ... writes xml data from the opened PROMOS session into
 * the specific file
 *
 * @param filename
 *
 * @return  -none-
 **/
function sbiplg_writeXmlData(filename) {

    if(!sbiplg_isInitialized) return(0);
    var datalen = document.sbiplg.storexmlsession();
    if(datalen > 0) document.sbiplg.writedata(filename);
    return(datalen);

} /* sbiplg_writeXmlData() */

//--------------------------------------------------------------

/**
 * @brief import/export
 *
 * ... executes the import function from the specific library
 * into the opened PROMOS session
 *
 * @param filename
 *
 * @return  -none-
 **/
function sbiplg_importData(library, userdata) {

    if(!sbiplg_isInitialized) return(0);
    return(document.sbiplg.importsession(library, userdata));

} /* sbiplg_importData() */

//--------------------------------------------------------------

/**
 * @brief import/export
 *
 * ... executes the export function from the specific library
 * from the opened PROMOS session
 *
 * @param filename
 *
 * @return  -none-
 **/
function sbiplg_exportData(library, userdata) {

    if(!sbiplg_isInitialized) return(0);
    return(document.sbiplg.exportsession(library, userdata));

} /* sbiplg_exportData() */

//--------------------------------------------------------------

/**
 * @brief print
 *
 * ... generates a HTML document based on the opened PROMOS session,
 * the mapping definitions and the document template. The HTML
 * document will be stored to filename and directy shown in a
 * separate window.
 *
 * @param definitionurl
 * @param templateurl
 * @param filename
 *
 * @return  -none-
 **/
function sbiplg_showHtmlDocument(definitionurl, templateurl, filename) {

    if(!sbiplg_isInitialized) return;
    if(document.sbiplg.processxml(definitionurl, templateurl, true)) {
        document.sbiplg.writedata(filename);
        window.open(filename);
    }

} /* sbiplg_showHtmlDocument() */

//--------------------------------------------------------------

/**
 * @brief print
 *
 * ... generates a XML document based on the opened PROMOS session,
 * the mapping definitions and the document template. The XML
 * document will be stored to filename and directy shown in a
 * separate window.
 *
 * @param definitionurl
 * @param templateurl
 * @param filename
 *
 * @return  -none-
 **/
function sbiplg_showXmlDocument(definitionurl, templateurl, filename) {

    if(!sbiplg_isInitialized) return;
    if(document.sbiplg.processxml(definitionurl, templateurl, false)) {
        document.sbiplg.writedata(filename);
        window.open(filename);
    }

} /* sbiplg_showXmlDocument() */

//--------------------------------------------------------------

/**
 * @brief options and configuration
 *
 * ... sets the system language within the Plug-In.
 *
 * @param language
 *
 * @return -none-
 **/
function sbiplg_setLanguage(language) {

    if(!sbiplg_isInitialized) return;
    var code = new Array("DE", "EN", "FR", "PL", "ES");

    if((language < 0) || (language > 4)) return;
    sbiplg_setvar("$LANGUAGE", code[language]);
    sbiplg_currentLanguage = language;

} /* sbiplg_setLanguage() */

//--------------------------------------------------------------

/**
 * @brief options and configuration
 *
 * ... starts a new process.
 *
 * @param commandline
 *
 * @return -none-
 **/
function sbiplg_execute(commandline) {

    if(!sbiplg_isInitialized) return;
    document.sbiplg.execute(commandline);

} /* sbiplg_execute() */

//--------------------------------------------------------------

/**
 * @brief options and configuration
 *
 * ... executes a shell command.
 *
 * @param commandline
 *
 * @return -none-
 **/
function sbiplg_shell(commandline) {

    if(!sbiplg_isInitialized) return;
    return(document.sbiplg.shell(commandline));

} /* sbiplg_shell() */

//==============================================================

/**
 * @brief Constructor for sbiplg_Attributes objects
 *
 * sbiplg_Attributes objects are a collection of sbiplg_AttributesItem objects
 *
 * Attributes:
 *   items (ARRAY) - array of sbiplg_AttributesItem objects
 *   form  (FORM)  - form to use
 *
 * Methods:
 *   addItem               - adds a single attribute
 *   modifyItem            - modifies a single attribute
 *   updateAll             - sets choice items and (default if none) values
 *   updateItem            - sets choice item and (default if none) value
 *   prepareItem           - handles control focus event, param: either control or its name
 *   commitItem            - handles control change event, param: either control or its name
 *   resetItem             - sets attribute value to default
 *   searchItemByControl   - search a single attribute by its control name
 *   searchItemByAttribute - search a single attribute by its attribute name
 *   searchItemByIndex     - search a single attribute's index by its control name
 *   synchronizeAll        - updates all attributes of model with value from control
 *                           for mapped items with checkValue the value is checked
 *                           and rewritten to the control
 *
 * @param form contains the controls on which the methods operate
 **/
function sbiplg_Attributes(form) {

    // attributes:
    this.items = new Array();
    this.form = form;

    // methods:
    this.addItem = sbiplg_addAttribute;
    this.modifyItem = sbiplg_modifyAttribute;
    this.updateAll = sbiplg_updateAttributes;
    this.updateItem = sbiplg_updateAttributesItem;
    this.prepareItem = sbiplg_onFocusAttribute;
    this.commitItem = sbiplg_onChangedAttribute;
    this.resetItem = sbiplg_resetAttribute;
    this.searchItemByControl = sbiplg_searchItemByControl;
    this.searchItemByAttribute = sbiplg_searchAttributeByName;
    this.searchItemByIndex = sbiplg_searchItemByIndex;
    this.synchronizeAll = sbiplg_synchronizeAttributes;
    this.focusFirst = sbiplg_focusFirst;

} /* sbiplg_Attributes() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Attributes
 *
 * ... adds an attribute item
 * Do not use directly
 *
 * @param controlName name of control to associate with attribute
 * @param attributeName name of attribute to associate with control
 * @param checkValue wether value is to be checked
 * @param checkOtherAvailable wether to check if attribute is available for
 *    computation 'checkProperties'
 * @param checkSelfAvailable wether to check if attribute is available
 * @param checkProperties for checkSelfAvailable
 *
 * @return the new item
 **/
function sbiplg_addAttribute(controlName, attributeName, checkValue, checkOtherAvailable, checkSelfAvailable, checkProperties) {

    var item = new sbiplg_AttributesItem(this, controlName, attributeName, checkValue, checkOtherAvailable, checkSelfAvailable, checkProperties);
    this.items.push(item);
    return(item);

} /* sbiplg_addAttribute() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Attributes
 *
 * ... changes an attribute
 * Do not use directly
 *
 * @param controlName name of control to associate with attribute
 * @param attributeName name of attribute to associate with control
 * @param checkValue wether value is to be checked
 * @param checkOtherAvailable wether to check if attribute is available for
 *    computation 'checkProperties'
 * @param checkSelfAvailable wether to check if attribute is available
 * @param checkProperties for checkSelfAvailable
 *
 * @return -none-
 **/
function sbiplg_modifyAttribute(controlName, attributeName, checkValue, checkOtherAvailable, checkSelfAvailable, checkProperties) {

    var item = this.searchItemByControl(controlName);
    if(!item) return;
    item.modify(attributeName, checkValue, checkOtherAvailable, checkSelfAvailable, checkProperties);

} /* sbiplg_modifyAttribute() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Attributes
 *
 * ... sets choice items and values (default values if none)
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_updateAttributes() {

    for(var i = 0; i < this.items.length; i++) {
        this.updateItem(this.items[i]);
    }

} /* sbiplg_updateAttributes() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Attributes
 *
 * ... sets choice item and value (default value if none)
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_updateAttributesItem(item) {

    if(typeof(item) == "string") {
        item = this.searchItemByControl(item);
    }
    if(!item) return;

    item.prepared = false;
    item.updateChoice();
    item.updateRadio();
    item.updateControl();
    item.updateAvailable();

} /* sbiplg_updateAttributesItem() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Attributes
 *
 * Do not use directly
 *
 * @param item item itself, item index or name of control
 *
 * @return -none-
 **/
function sbiplg_onFocusAttribute(item) {

    if(typeof(item) == "string") {
        item = this.searchItemByControl(item);
    } else {
        item = this.searchItemByControl(item.name);
    }
    if(!item || (item.prepared == true)) return;

    // prepare item:
    item.prepareChoice();
    item.prepared = true;

} /* sbiplg_onFocusAttribute() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Attributes
 *
 * Do not use directly
 *
 * @param item item itself, item index or name of control
 *
 * @return -none-
 **/
function sbiplg_onChangedAttribute(item) {

    if(typeof(item) == "string") {
        item = this.searchItemByControl(item);
    } else {
        item = this.searchItemByControl(item.name);
    }
    if(!item) return(0);

    // synchronize item:
    var code = item.synchronize();

    // check available dependency:
    if(item.checkOtherAvailable) {
        for(var i = 0; i < this.items.length; i++) {
            this.items[i].updateAvailable();
        }
    }
    return(code);

} /* sbiplg_onChangedAttribute() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Attributes
 *
 * set value of attribute to default
 * Do not use directly
 *
 * @param attribute name of attribute
 *
 * @return -none-
 **/
function sbiplg_resetAttribute(attribute) {

    if(!sbiplg_isInitialized) return;
    var item = this.searchItemByControl(attribute);
    if(!item) return;

    var code = sbiplg_compute(item.attributeName + ".default");
    if(code == 0) {
        sbiplg_setvar(item.attributeName, document.sbiplg.result);
        this.updateItem(item);
    }

} /* sbiplg_resetAttribute() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Attributes
 *
 * Finds an item
 * Do not use directly
 *
 * @param name name of attribute
 *
 * @return the sbiplg_AttributesItem
 **/
function sbiplg_searchAttributeByName(name) {

    var attributeName = name.toLowerCase();
    for(var i = 0; i < this.items.length; i++) {
        if(this.items[i].attributeName.toLowerCase() == attributeName) return(item);
    }
    return(null);

} /* sbiplg_searchAttributeByName() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Attributes
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_synchronizeAttributes() {

    var code = 0;
    var codeitem = 0;

    for(var i = 0; i < this.items.length; i++) {
        codeitem = this.items[i].synchronize();
        if(codeitem > 0) code = code + codeitem;
    }
    if(code == 0) code = -1;
    return(code);

} /* sbiplg_synchronizeAttributes() */

//--------------------------------------------------------------
/**
 * @brief Method of sbiplg_focusFirstControl
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_focusFirst() {

    for(var i = 0; i < this.items.length; i++) {
        var control = this.items[i].getControl(false);
        if(!control || control.disabled || control.readOnly) continue;
        try {
          control.focus();
          break;
        } catch(e) {continue;}
    }

} /* sbiplg_focusFirst() */

//==============================================================

/**
 * @brief Constructor for a new sbiplg_AttributesItem object
 *
 * Objects of this type are control by sbiplg_Attributes objects
 *
 * Attributes:
 *   set                 (OBJECT) - the set to which this item belongs to
 *   controlName         (STRING) - name of control to associate with attribute
 *   attributeName       (STRING) - name of attribute to associate with control
 *   checkValue          (BOOL)   - wether value is to be checked
 *   checkOtherAvailable (BOOL)   - wether to check if attribute is available for
 *                                  computation 'checkProperties'
 *   checkSelfAvailable  (BOOL)   - wether to check if attribute is available
 *   checkProperties     (STRING) - for checkSelfAvailable
 *   controlProxy        (OBJECT) - the control, if retrieved (used internally)
 *
 * Methods:
 *   change        - changes the attributes of this attribute
 *   getControl    - Get the associated control, if param force is true then
 *                   controlProxy is updated from the form
 *   updateChoice  - update the coice values (if it is a select control)
 *   updateRadio   - update the radio values (if it is a radio control)
 *   updateControl - set associated control value to computed result,
 *                   if there's none take then default value
 *                   if checkValue is true then value is checked
 *   synchronize   - update attribute with value from control
 *
 * @param set the set to which this item belongs to
 * @param controlName name of control to associate with attribute
 * @param attributeName name of attribute to associate with control
 * @param checkValue wether value is to be checked
 * @param checkOtherAvailable wether to check if attribute is available for
 *    computation 'checkProperties'
 * @param checkSelfAvailable wether to check if attribute is available
 * @param checkProperties for checkSelfAvailable
 *
 * @return -none-
 **/
function sbiplg_AttributesItem(set, controlName, attributeName, checkValue, checkOtherAvailable, checkSelfAvailable, checkProperties) {

    // attributes:
    this.set = set;
    this.controlName = controlName;
    this.attributeName = attributeName;
    this.checkValue = (checkValue == true);
    this.checkOtherAvailable = (checkOtherAvailable == true);
    this.checkSelfAvailable = (checkSelfAvailable == true);
    this.checkProperties = "";
    if(checkProperties) this.checkProperties = checkProperties;
    this.controlProxy = null;

    // methods:
    this.modify = sbiplg_modifyAttributesItem;
    this.getControl = sbiplg_getControl;
    this.getControlValue = sbiplg_getControlValue;
    this.setControlValue = sbiplg_setControlValue;
    this.prepareChoice = sbiplg_prepareChoiceAttributesItem;
    this.updateChoice = sbiplg_updateChoiceAttributesItem;
    this.updateRadio = sbiplg_updateRadioAttributesItem;
    this.updateControl = sbiplg_updateControlAttributesItem;
    this.updateAvailable = sbiplg_updateAvailableAttributesItem;
    this.synchronize = sbiplg_synchronizeAttributesItem;

} /* sbiplg_AttributesItem() */

//--------------------------------------------------------------
/**
 * @brief Method of sbiplg_AttributesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_modifyAttributesItem(attributeName, checkValue, checkOtherAvailable, checkSelfAvailable, checkProperties) {

    this.attributeName = attributeName;
    if((checkValue == true) || (checkValue == false)) this.checkValue = checkValue;
    if((checkOtherAvailable == true) || (checkOtherAvailable == false)) this.checkOtherAvailable = checkOtherAvailable;
    if((checkSelfAvailable == true) || (checkSelfAvailable == false)) this.checkSelfAvailable = checkSelfAvailable;
    if(checkProperties) this.checkProperties = checkProperties;
    return(this.updateControl());

} /* sbiplg_modifyAttributesItem() */

//--------------------------------------------------------------
/**
 * @brief Method of sbiplg_AttributesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_prepareChoiceAttributesItem() {

    if(!sbiplg_isInitialized) return;

    // check for choice control:
    var selectbox = this.getControl(false);
    if(!selectbox || (selectbox.type != "select-one") || (selectbox.style.display == "none")) return;

    // clear items:
    for(var i = selectbox.options.length - 1; i >= 0; i--) {
        if(selectbox.options[i]) selectbox.options[i].removeNode(true);
    }

    // fill items:
    var code = document.sbiplg.choice("", this.attributeName);
    while(code == 1) {
        var oOption = selectbox.document.createElement("option");
        oOption.text = document.sbiplg.message;
        oOption.value = document.sbiplg.result;
        selectbox.add(oOption);
        code = document.sbiplg.choice("", this.attributeName);
    }

    var code = sbiplg_compute(this.attributeName);
    if(code == 0) selectbox.value = document.sbiplg.result;

} /* sbiplg_prepareChoiceAttributesItem() */

//--------------------------------------------------------------
/**
 * @brief Method of sbiplg_AttributesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_updateChoiceAttributesItem() {

    if(!sbiplg_isInitialized) return;

    // check for choice control:
    var selectbox = this.getControl(false);
    if(!selectbox || (selectbox.type != "select-one") || (selectbox.style.display == "none")) return;

    // clear items:
    for(var i = selectbox.options.length - 1; i >= 0; i--) {
        if(selectbox.options[i]) selectbox.options[i].removeNode(true);
    }

    // get attribute value:
    var value = "";
    var code = sbiplg_compute(this.attributeName);
    if(code == 0) value = document.sbiplg.result;

    // fill items:
    var code = document.sbiplg.choice(value, this.attributeName);
    while(code == 1) {
        var oOption = selectbox.document.createElement("option");
        oOption.text = document.sbiplg.message;
        oOption.value = document.sbiplg.result;
        selectbox.add(oOption);
        code = document.sbiplg.choice(value, this.attributeName);
    }

} /* sbiplg_updateChoiceAttributesItem() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_AttributesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_updateRadioAttributesItem() {

    if(!sbiplg_isInitialized) return;

    // check for radio control:
    var radiobox = this.getControl(false);
    if(!radiobox || (radiobox.type != "radio")) return;

    // fill all radio items in a given form:
    var control, code;
    for(var i = 0; i < this.set.form.length; i++) {
        control = this.set.form.elements[i];
        if(control.name.toLowerCase() == radiobox.name.toLowerCase() && (control.type == "radio")) {
            code = document.sbiplg.choice("", this.attributeName);
            if(code == 1) {
                control.replaceAdjacentText("afterEnd", document.sbiplg.message);
                control.value = document.sbiplg.result;
            }
        }
    }
    // complete the function choice if the table in PROMOS is greater than the Control-array
    while(code == 1) {
        code = document.sbiplg.choice("", this.attributeName);
    }

} /* sbiplg_updateRadioAttributesItem() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_AttributesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_updateControlAttributesItem() {

    if(!sbiplg_isInitialized) return;

    // get attribute value:
    var value = "";
    var code = sbiplg_compute(this.attributeName);
    if(code == 0) value = document.sbiplg.result;

    // set value to control:
    var control = this.getControl(false);
    if(!control) return(0);
    sbiplg_setControlValue(this.set.form, control, value);
    sbiplg_setvar(this.attributeName, value);

} /* sbiplg_updateControlAttributesItem() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_AttributesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_updateAvailableAttributesItem() {

    if(!sbiplg_isInitialized) return;

    if(!this.checkSelfAvailable) return;

    var control = this.getControl(false);
    var code = document.sbiplg.available(this.checkProperties, this.attributeName);
    if(document.sbiplg.message) alert(document.sbiplg.message);

    var coll = control.document.all.item(control.name);
    if(typeof(coll.type) != "undefined") {
        coll.disabled = (code == 0 ? true : false);
        coll.readOnly = (code == 0 ? true : false);
    } else {
        for(var i=0; i<coll.length; i++) {
            coll[i].disabled = (code == 0 ? true : false);
            coll[i].readOnly = (code == 0 ? true : false);
        }
    }

} /* sbiplg_updateAvailableAttributesItem() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_AttributesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_synchronizeAttributesItem() {

    if(!sbiplg_isInitialized) return;

    // get control:
    var control = this.getControl(false);
    if(!control || ((control.type == "select-one") && (control.style.display == "none"))) return(0);

    // set attribute with control value:
    var code = sbiplg_setvar(this.attributeName, this.getControlValue(control));

    // check value and update control:
    if(this.checkValue) this.updateControl();
    return(code);

} /* sbiplg_synchronizeAttributesItem() */

//==============================================================

/**
 * @brief Constructor for sbiplg_Properties objects
 *
 * sbiplg_Properties objects are a collection of sbiplg_PropertiesItem objects
 *
 * Attributes:
 *   items    (ARRAY) - Array of sbiplg_AttributesItem objects
 *   form       (FORM)  - form to use
 *
 * Methods:
 *   addItem             - add a single property
 *   updateAll           - update all controls with values from model
 *   searchItemByControl - search a single property by its control name
 *   searchItemByIndex   - search a single attribute's index by its control name
 *
 * @param form contains the controls on which the
 * methods operate
 **/
function sbiplg_Properties(form) {

    // attributes:
    this.items = new Array();
    this.form = form;

    // methods:
    this.addItem = sbiplg_addProperty;
    this.modifyItem = sbiplg_modifyProperty;
    this.updateAll = sbiplg_updateProperties;
    this.transferItem = sbiplg_transferProperty;
    this.getControlValue = sbiplg_getControlValue;
    this.searchItemByControl = sbiplg_searchItemByControl;
    this.searchItemByIndex = sbiplg_searchItemByIndex;

} /* sbiplg_Properties() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Properties
 *
 * Adds an property item
 * Do not use directly
 *
 * @param controlName name of control to associate with attribute
 * @param propertyName name of property to associate with control
 *
 * @return the new item
 **/
function sbiplg_addProperty(controlName, propetyName) {

    var item = new sbiplg_PropertiesItem(this, controlName, propetyName);
    this.items.push(item);
    return(item);

} /* sbiplg_addProperty() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_modifyProperty
 *
 * ... changes a property
 * Do not use directly
 *
 * @param item item itself, item index or name of control
 *
 * @return -none-
 **/
function sbiplg_modifyProperty(controlName, propertyName) {

    var item = this.searchItemByControl(controlName);
    if(!item) return;
    item.modify(propertyName);

} /* sbiplg_modifyProperty() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Properties
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_updateProperties() {

    for(var i = 0; i < this.items.length; i++) {
        this.items[i].updateControl();
    }

} /* sbiplg_updateProperties() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Properties
 *
 * Adds an property item
 * Do not use directly
 *
 * @param controlName name of control witch value should be transfered
 * @param attributeName name of attribute whitch should accept the value
 *
 * @return -none-
 **/
function sbiplg_transferProperty(controlName, attributeName) {

    if(!sbiplg_isInitialized) return(0);

    var control;
    var name = controlName.toLowerCase();

    for(var i = 0; i < this.form.length; i++) {
        control = this.form.elements[i];
        if(name == control.name.toLowerCase()) {
            return(sbiplg_setvar(attributeName, this.getControlValue(control)));
        }
    }
    return(-1);

} /* sbiplg_transferProperty() */

//==============================================================

/**
 * @brief Constructor for a new sbiplg_PropertiesItem object
 *
 * Objects of this type are control by sbiplg_Attributes objects
 *
 * Attributes:
 *   set          (OBJECT) - the set to which this item belongs to
 *   controlName  (STRING) - name of control to associate with attribute
 *   propertyName (STRING) - name of property to be calculated
 *   controlProxy (OBJECT) - the control, if retrieved (used internally)
 *
 * Methods:
 *   getControl    - get the associated control, if param force is true
 *                   then controlProxy is updated from the form
 *   updateControl - set associated control value to computed result
 *
 * @param set the set to which this item belongs to
 * @param controlName name of control to associate with attribute
 * @param propertyName name of property to be calculated
 *
 **/
function sbiplg_PropertiesItem(set, controlName, propertyName) {

    // attributes:
    this.set = set;
    this.controlName = controlName;
    this.propertyName = propertyName;
    this.controlProxy = null;

    // methods
    this.modify = sbiplg_modifyPropertyItem;
    this.getControl = sbiplg_getControl;
    this.getControlValue = sbiplg_getControlValue;
    this.setControlValue = sbiplg_setControlValue;
    this.updateControl = sbiplg_updateControlPropertiesItem;

} /* sbiplg_PropertiesItem() */

//--------------------------------------------------------------
/**
 * @brief Method of sbiplg_PropertiesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_modifyPropertyItem(propertyName) {

    this.propertyName = propertyName;
    this.updateControl();

} /* sbiplg_modifyPropertyItem() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_PropertiesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_updateControlPropertiesItem() {

    if(!sbiplg_isInitialized) return;

    // get control:
    var control = this.getControl(false);
    if(!control) return;

    // set computed property to control:
    if(sbiplg_compute(this.propertyName) == 0) sbiplg_setControlValue(this.set.form, control, document.sbiplg.result);

} /* sbiplg_updateControlPropertiesItem() */

//==============================================================

/**
 * @brief Method of sbiplg_Attributes and sbiplg_Properties
 *
 * Finds an item
 * Do not use directly
 *
 * @param name name of control
 *
 * @return the sbiplg_AttributesItem/sbiplg_PropertiesItem
 **/
function sbiplg_searchItemByControl(name) {

    var controlName = name.toLowerCase();
    var item;

    for(var i = 0; i<this.items.length; i++) {
        item = this.items[i];
        if(item.controlName.toLowerCase() == controlName) return(item);
    }
    return(null);

} /* sbiplg_searchItemByControl() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_Attributes and sbiplg_Properties
 *
 * Finds the index of an item by its control name
 * Do not use directly
 *
 * @param name name of attribute
 *
 * @return the index of the control item, -1 if not found
 **/
function sbiplg_searchItemByIndex(name) {

    var controlName = name.toLowerCase();
    var item;

    for(var i = 0; i < this.items.length; i++) {
        item = this.items[i];
        if(item.controlName.toLowerCase() == controlName) return(i);
    }
    return(-1);

} /* sbiplg_searchItemByIndex() */

//==============================================================

/**
 * @brief Method of sbiplg_AttributesItem and sbiplg_PropertiesItem
 *
 * sets controlProxy and returns the value
 *
 * Do not use directly
 *
 * @param force_update if true then current value of proxy is ignored
 *
 * @return  -none-
 **/
function sbiplg_getControl(force_update) {

    if(force_update || !this.controlProxy) {
        var control;
        var controlName = this.controlName.toLowerCase();

        this.controlProxy = null;
        for(var i = 0; i < this.set.form.length; i++) {
            control = this.set.form.elements[i];
            if(controlName == control.name.toLowerCase()) {
                this.controlProxy = control;
                break;
            }
        }
    }
    return(this.controlProxy);

} /* sbiplg_getControl() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_AttributesItem and sbiplg_PropertiesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_getControlValue(control) {

    if(!control) return("");

    // get value of a checkbox:
    if(control.type == "checkbox") {
        if(control.checked) return("1"); else return("0");
    }

    // get value of a radiogroup:
    if(control.type == "radio") {
        var radiobox;
        for(var i = 0; i < this.set.form.length; i++) {
            radiobox = this.set.form.elements[i];
            if((control.name.toLowerCase() == radiobox.name.toLowerCase()) && (radiobox.type == "radio")) {
                if(radiobox.checked) return(radiobox.value);
            }
        }
        return("$nil");
    }

    // get value of a formated text:
    if(control.format && (control.format.length > 0)) {
        if(sbiplg_compute("unformat(\"" + control.value + "\";\"" + control.format + "\")") == 0) return(document.sbiplg.result);
    }

    // get any value:
    return(control.value);

} /* sbiplg_getControlValue() */

//--------------------------------------------------------------

/**
 * @brief Method of sbiplg_AttributesItem and sbiplg_PropertiesItem
 *
 * Do not use directly
 *
 * @return -none-
 **/
function sbiplg_setControlValue(form, control, value) {

    if(!control) return;

    // set value of a checkbox:
    if(control.type == "checkbox") {
        control.checked = (value == "1");
        return;
    }

    // set value of a radiogroup:
    if(control.type == "radio") {
        var radiobox;
        for(var i = 0; i < form.length; i++) {
            radiobox = form.elements[i];
            if((radiobox.type == "radio") && (control.name.toLowerCase() == radiobox.name.toLowerCase())) {
                if(radiobox.value == value) radiobox.checked = true;
            }
        }
        return;
    }

    // set value of a formated text:
    if(control.format && (control.format.length > 0)) {
        if(sbiplg_compute("format(\"" + value + "\";\"" + control.format + "\")") == 0) {
            control.value = document.sbiplg.result;
            return;
        }
    }

    // set any value:
    control.value = value;

} /* sbiplg_setControlValue() */

//==============================================================

/**
 * @brief Constructor for sbiplg_Table objects
 *
 * Tables that contain columns with promos model values
 *
 * Attributes:
 *   columns      (ARRAY)  - Contains objects of type sbiplg_Column
 *   form         (OBJECT) - HTML form which contains the table
 *   tableID      (STRING) - ID string for table to generate
 *   rowsProperty (STRING) - name of property which evaluates to number of rows
 *   spacerGif    (STRING) - name of gif file with a certain size; default is "img/space.gif"
 *
 * Methods:
 *   addColumn - Add a new column to the table
 *   update    - Update the table representation inside the form
 *
 * @param form on which a table is generated
 * @param tableID ID of table
 * @param rowsProperty a property which evaluates to the number of rows
 *
 * @return -none-
 **/
function sbiplg_Table(form, tableID, rowsProperty) {

    // attributes:
    this.columns = new Array();
    this.form = form;
    this.tableID = tableID;
    this.rowsProperty = rowsProperty;
    this.filter = null;

    // methods:
    this.addColumn = sbiplg_addTableColumn;
    this.setFilter = sbiplg_setTableFilter;
    this.setFilterByValue = sbiplg_setTableFilterByValue;
    this.removeFilter = sbiplg_removeTableFilter;
    this.update = sbiplg_updateTable;

} /* sbiplg_Table() */

//--------------------------------------------------------------

/**
 * @brief Method of for sbiplg_Table objects
 *
 * Add a new column to the table
 *
 * @param header header text
 * @param headerStyle style class of header
 * @param expression attribute or property name to calculate
 * @param type type of expression: "A" or "P" or "AP"
 * @param style style class of column
 * @param width width in pixel
 * @param format format of numerical values
 * @param rule rule of expression: "0;x" or "x;0" or "1;x" or "x;1" ... x as evaluates to number of rows
 *
 * @return -none-
 **/
function sbiplg_addTableColumn(header, headerStyle, expression, type, style, width, format, rule) {

    var column = new sbiplg_Column(this, header, headerStyle, expression, type, style, width, format, rule);
    this.columns.push(column);
    return(column);

} /* sbiplg_addTableColumn() */

//--------------------------------------------------------------

/**
 * @brief Method of for sbiplg_Table objects
 *
 * Set a new filter to the table
 *
 * @param expression name of attribute or property to be calculated
 * @param type type of expression: "A" or "P" or "AP"
 * @param rule rule of expression: "0;x" or "x;0" or "1;x" or "x;1" ... x as evaluates to number of rows
 *
 * @return -none-
 **/
function sbiplg_setTableFilter(expression, type, rule) {

    if(expression == null || typeof(expression) != "string" || expression == "") return;
    this.filter = new sbiplg_Filter(this, expression, type, "1", "==", rule);

} /* sbiplg_setTableFilter() */

//--------------------------------------------------------------

/**
 * @brief Method of for sbiplg_Table objects
 *
 * Set a new filter to the table
 *
 * @param expression name of attribute or property to be calculated
 * @param type type of expression: "A" or "P" or "AP"
 * @param value value to be compare
 * @param op operator to be compare: "==" or "!=" or ">"or "<" or ">=" or "<="
 * @param rule rule of expression: "0;x" or "x;0" or "1;x" or "x;1" ... x as evaluates to number of rows
 *
 * @return -none-
 **/
function sbiplg_setTableFilterByValue(expression, type, value, op, rule) {

    if(expression == null || typeof(expression) != "string" || expression == "") return;
    this.filter = new sbiplg_Filter(this, expression, type, value, op, rule);

} /* sbiplg_setTableFilterByValue() */

//--------------------------------------------------------------

/**
 * @brief Method of for sbiplg_Table objects
 *
 * Remove a filter from the table
 *
 * @return -none-
 **/
function sbiplg_removeTableFilter() {

    this.filter = null;

} /* sbiplg_removeTableFilter() */

//--------------------------------------------------------------

/**
 * @brief Method of for sbiplg_Table objects
 *
 * Generate the visible part of the table
 *
 * @return -none-
 **/
function sbiplg_updateTable() {

    if(!sbiplg_isInitialized) return;

    var currDoc = this.form.document;
    var tableNode = currDoc.getElementById(this.tableID);
    var tableParent;
    if(tableNode) {
        tableParent = tableNode.parentNode;
        tableNode.removeNode(true);
    } else tableParent = this.form;
    tableNode = currDoc.createElement("table");
    tableParent.appendChild(tableNode);
    tableNode.setAttribute("id", this.tableID, false);
    tableNode.setAttribute("border", "0", false);

    // set table column header:
    var newRow = tableNode.insertRow();
    var column;
    var newCell;
    for(var i = 0; i < this.columns.length; i++) {
        column = this.columns[i];
        newCell = newRow.insertCell();
        newCell.setAttribute("className", column.headerStyle, false);
        newCell.setAttribute("innerHTML", column.header, false);
    }

    // set table body
    var code;
    code = sbiplg_compute(this.rowsProperty);
    if(code == 0) {
        var max = document.sbiplg.result;
        var property;
        var value;

        for(var k = 0; k < max; k++) {
            var add = true;
            if(this.filter) {
                var suf = k;
                if(this.filter.rule && (this.filter.rule.length > 0) && (this.filter.rule.toLowerCase().indexOf("x") >= 0)) {
                    suf = this.filter.rule.toLowerCase().replace("x", k);
                }
                if((this.filter.type == "AP") || (this.filter.type == "ap")) {
                    var pos = this.filter.expression.indexOf(".");
                    if(pos < 0) {
                        property = this.filter.expression + "[" + suf + "]";
                    } else {
                        property = this.filter.expression.substring(0, pos) + "[" + suf + "]" + this.filter.expression.substring(pos, 999);
                    }
                } else if((this.filter.type == "A") || (this.filter.type == "a")) {
                    property = this.filter.expression + "[" + suf + "]";
                } else {
                    property = this.filter.expression + "(" + suf + ")";
                }
                code = sbiplg_compute(property);
                var op = "==";
                if(this.filter.op && (this.filter.op.length > 0)) {
                    op = this.filter.op;
                }
                add = false;
                if (code == 0) {
                     if (op == "==") add = (document.sbiplg.result == this.filter.value);
                     if (op == "!=") add = (document.sbiplg.result != this.filter.value);
                     if (op == ">")  add = (parseFloat(document.sbiplg.result) >  parseFloat(this.filter.value));
                     if (op == "<")  add = (parseFloat(document.sbiplg.result) <  parseFloat(this.filter.value));
                     if (op == ">=") add = (parseFloat(document.sbiplg.result) >= parseFloat(this.filter.value));
                     if (op == "<=") add = (parseFloat(document.sbiplg.result) <= parseFloat(this.filter.value));
                }
            }
            if(add) {
                newRow = tableNode.insertRow();
                newRow.id = String(k);
                for(var i = 0; i < this.columns.length; i++) {
                    column = this.columns[i];
                    var suf = k;
                    if(column.rule && (column.rule.length > 0) && (column.rule.toLowerCase().indexOf("x") >= 0)) {
                        suf = column.rule.toLowerCase().replace("x", k);
                    }
                    if((column.type == "AP") || (column.type == "ap")) {
                        var pos = column.expression.indexOf(".");
                        if(pos < 0) {
                            property = column.expression.expression + "[" + suf + "]";
                        } else {
                            property = column.expression.substring(0, pos) + "[" + suf + "]" + column.expression.substring(pos, 999);
                        }
                    } else if((column.type == "A") || (column.type == "a")) {
                        property = column.expression + "[" + suf + "]";
                    } else {
                        property = column.expression + "(" + suf + ")";
                    }
                    code = sbiplg_compute(property);
                    if(code == 0) value = document.sbiplg.result; else value = "-";
                    newCell = newRow.insertCell();
                    newCell.setAttribute("className", column.style, false);
                    if(column.format && (column.format.length > 0)) {
                        if(sbiplg_compute("format(\"" + value + "\";\"" + column.format + "\")") == 0) value = document.sbiplg.result;
                    }
                    newCell.innerHTML = value;
                }
            }
        }
    }

} /* sbiplg_updateTable() */

//==============================================================

/**
 * @brief Constructor for sbiplg_Column objects
 *
 * Columns of sbiplg_Table
 *
 * Attributes:
 *   table       (OBJECT)  table to which column belongs to
 *   header      (STRING)  header text
 *   headerStyle (STRING)  header style class
 *   expression  (STRING)  property or attribute name to be calculated
 *   type        (STRING)  what expression is: "A" or "P" or "AP"
 *   style       (STRING)  column style class
 *   width       (INTEGER) width in pixels
 *   format      (STRING)  format of numerical values
 *   rule        (STRING)  what expression is: "0;x" or "x;0" or "1;x" or "x;1" ... x as evaluates to number of rows
 *
 * @param table to which column is added
 * @param header header text of the column
 * @param headerStyle style class of the header
 * @param expression name of attribute or property to be calculated
 * @param type type of expression: "A" or "P" or "AP"
 * @param cellClass style class to use for header title
 * @param width in pixel
 *
 * @return -none-
 **/
function sbiplg_Column(table, header, headerStyle, expression, type, style, width, format, rule) {

    this.table = table;
    this.header = header;
    this.headerStyle = headerStyle;
    this.expression = expression;
    this.type = type;
    this.style = style;
    this.width = width;
    this.format = format;
    this.rule = rule;

} /* sbiplg_Column() */

//==============================================================

/**
 * @brief Constructor for sbiplg_Filter objects
 *
 * Filter of sbiplg_Table
 *
 * Attributes:
 *   table       (OBJECT)  table to which column belongs to
 *   expression  (STRING)  property or attribute name to be calculated
 *   type        (STRING)  what expression is: "A" or "P" or "AP"
 *   value       (STRING)  value to be compare
 *   op          (STRING)  operator to be compare: "==" or "!=" or ">"or "<" or ">=" or "<="
 *   rule        (STRING)  what expression is: "0;x" or "x;0" or "1;x" or "x;1" ... x as evaluates to number of rows
 *
 * @param table to which filter is added
 * @param expression name of attribute or property to be calculated
 * @param type type of expression: "A" or "P" or "AP"
 * @param value value to compare
 *
 * @return -none-
 **/
function sbiplg_Filter(table, expression, type, value, op, rule) {

    this.table = table;
    this.expression = expression;
    this.type = type;
    this.value = value;
    this.op = op;
    this.rule = rule

} /* sbiplg_Filter() */

//==============================================================

