/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var mx, my;
var ACTIVATED_LOOKUP = null;
var LOOKUP_DIV = null;
var INITIALLY_COLLAPSED = null;
var COLLAPSE_SEQUENCE_NUMBER = 1999;

var target = null;
var target2 = null;
var targetW = null;
var lookups = [];

function getViewNameWithSeparator(view_name) {
    var sep = "?";
    if (view_name.indexOf("?") >= 0) {
        sep = "&";
    }
    return view_name + sep;
}

function lookup_error(str_message) {
    var CommonErrorMessage2 = getJSONuiLabel("CommonUiLabels", "CommonErrorMessage2");
    showErrorAlert(CommonErrorMessage2, str_message);
}

function lookup_popup1(view_name, form_name, viewWidth, viewheight) {
    var obj_lookupwindow = window.open(getViewNameWithSeparator(view_name) + 'formName=' + form_name + '&presentation=' + this.presentation
            + '&id=' + this.id, '_blank', 'width=' + viewWidth + ',height=' + viewheight + ',scrollbars=yes,status=no,resizable=yes,top='
            + my + ',left=' + mx + ',dependent=yes,alwaysRaised=yes');
    obj_lookupwindow.opener = window;
    obj_lookupwindow.focus();
}

function lookup_popup2(view_name) {
    var argString = "";
    if (this.args !== null) {
        if (this.args.length > 2) {
            var i;
            for (i = 2; i < this.args.length; i++) {
                argString += "&parm" + (i - 3) + "=" + this.args[i];
            }
        }
    }

    var obj_lookupwindow = window.open(getViewNameWithSeparator(view_name) + 'presentation=' + this.presentation + '&id=' + this.id
            + argString, '_blank', 'width=900,height=700,scrollbars=yes,status=no,resizable=yes,top=' + my + ',left=' + mx
            + ',dependent=yes,alwaysRaised=yes');
    obj_lookupwindow.opener = window;
    obj_lookupwindow.focus();
}

function fieldLookup1(obj_target, args, presentation) {
    this.args = args;
    this.presentation = presentation;
    // passing methods
    this.popup = lookup_popup1;
    this.popup2 = lookup_popup2;

    // validate input parameters
    if (!obj_target) {
        return lookup_error("Error calling the field lookup: no target control specified");
    }
    if (obj_target.value === null) {
        return lookup_error("Error calling the field lookup: parameter specified is not valid target control");
    }
    targetW = obj_target;
}

function fieldLookup2(obj_target, obj_target2, args, presentation) {
    this.args = args;
    this.presentation = presentation;
    // passing methods
    this.popup = lookup_popup1;
    this.popup2 = lookup_popup2;
    // validate input parameters
    if (!obj_target) {
        return lookup_error("Error calling the field lookup: no target control specified");
    }
    if (obj_target.value === null) {
        return lookup_error("Error calling the field lookup: parameter specified is not valid target control");
    }
    targetW = obj_target;
    // validate input parameters
    if (!obj_target2) {
        return lookup_error("Error calling the field lookup: no target2 control specified");
    }
    if (obj_target2.value === null) {
        return lookup_error("Error calling the field lookup: parameter specified is not valid target2 control");
    }
    target2 = obj_target2;
}

function call_fieldlookup3(target, target2, viewName, presentation) {
    var fieldLookup = new fieldLookup2(target, target2, arguments, presentation);
    fieldLookup.popup2(viewName);
}

function call_fieldlookup(target, viewName, formName, viewWidth, viewheight) {
    var fieldLookup = new fieldLookup1(target);
    if (!viewWidth) {
        viewWidth = 350;
    }
    if (!viewheight) {
        viewheight = 200;
    }
    fieldLookup.popup(viewName, formName, viewWidth, viewheight);
}

function call_fieldlookup2(target, viewName, presentation) {
    var fieldLookup = new fieldLookup1(target, arguments, presentation);
    fieldLookup.popup2(viewName);
}

function CollapsePanel(link, areaId) {
    var container, liElement;

    container = jQuery(areaId);
    liElement = jQuery(link).up('li');

    liElement.removeClassName('expanded');
    liElement.addClassName('collapsed');
    Effect.toggle(container, 'appear');
}

function initiallyCollapse() {
    if ((!LOOKUP_DIV) || (INITIALLY_COLLAPSED != "true")) {
        return;
    }

    var i, j, childEle, childElements, ul, slTitleBar, slTitleBars = LOOKUP_DIV.getElementsByClassName('screenlet-title-bar');
    for (i in slTitleBars) {
        slTitleBar = slTitleBars[i];
        ul = slTitleBar.firstChild;
        if ((typeof ul) != 'object') {
            continue;
        }

        childElements = ul.childNodes;
        for (j in childElements) {
            if (childElements[j].className === 'expanded' || childElements[j].className === 'collapsed') {
                break;
            }
        }

        childEle = childElements[j].firstChild;
        new CollapsePanel(childEle, 'lec' + COLLAPSE_SEQUENCE_NUMBER);
        break;
    }
}

function initiallyCollapseDelayed() {
    setTimeout("initiallyCollapse()", 400);
}

/*******************************************************************************
 * Lookup Object
 ******************************************************************************/
var Lookup = function(options) {
    var _newInputBoxId, _lookupId, _inputBox, _lookupContainer, _backgroundCloseClickEvent;

    options = {
        requestUrl : options.requestUrl || "",
        inputFieldId : options.inputFieldId || "",
        dialogTarget : options.dialogTarget || "",
        dialogOptionalTarget : options.dialogOptionalTarget || "",
        formName : options.formName || "",
        width : options.width || "620",
        height : options.height || "500",
        position : options.position || "topleft",
        modal : options.modal || "true",
        ajaxUrl : options.ajaxUrl || "",
        showDescription : options.showDescription || "",
        presentation : options.presentation || "layer",
        defaultMinLength : options.defaultMinLength || "",
        defaultDelay : options.defaultDelay || "",
        args : options.args || ""
    }

    function _init() {
        _lookupId = GLOBAL_LOOKUP_REF.createNextKey();
        _modifyContainer();
        _createAjaxAutoComplete();

        _lookupContainer = jQuery("#" + _lookupId);
        var dialogOpts = _createDialogOptions(_lookupContainer);

        // init Dialog and register
        // create an object with all Lookup Informationes that are needed
        var dialogRef = _lookupContainer.dialog(dialogOpts);

        // setting up global variabels, for external access
        this.inputBoxId = _inputBox.id;
        this.lookupId = _lookupId;
        this.formName = options.formName;
        this.target = null;
        this.presentation = options.presentation;
        this.showDescription = (options.showDescription == "true") ? true : false;
        if (options.dialogOptionalTarget != null) {
            this.target2 = null;
        }
        this.prevLookup = null;
        this.dialogRef = dialogRef;

        // write external settings in global window manager
        GLOBAL_LOOKUP_REF.setReference(_lookupId, this);

        _addOpenEvent(dialogRef);
    }

    function _modifyContainer() {
        _inputBox = document.getElementById(options.inputFieldId);
        _newInputBoxId = _lookupId + "_" + options.inputFieldId;
        _inputBox.id = _newInputBoxId;
        var parent = _inputBox.parentNode;

        var link = document.createElement('A');
        link.href = "javascript:void(0);";
        link.id = _lookupId + "_button";

        parent.appendChild(link);

        var hiddenDiv = document.createElement("DIV");
        hiddenDiv.id = _lookupId;
        hiddenDiv.css = "{display: none;}";
        hiddenDiv.title = "";

        parent.appendChild(hiddenDiv);
    }

    function _createAjaxAutoComplete() {
        if (options.ajaxUrl != "") {
            // write the new input box id in the ajaxUrl Array
            options.ajaxUrl = options.ajaxUrl.replace(options.ajaxUrl.substring(0, options.ajaxUrl.indexOf(",")), _newInputBoxId);
            new ajaxAutoCompleter(options.ajaxUrl, (options.showDescription == "true") ? true : false, options.defaultMinLength, options.defaultDelay,
                    options.formName);
        }
    }

    function _createDialogOptions(_lookupContainer) {
        var positioning = _positioning();

        var dialogOpts = {
            modal : (options.modal == "true") ? true : false,
            bgiframe : true,
            autoOpen : false,
            height : parseInt(options.height),
            width : parseInt(options.width),
            position : positioning,
            draggable : true,
            resizeable : true,
            open : _dialogOpen,
            close : _dialogClose
        };

        return dialogOpts;
    }

    function _positioning() {
        var positioning = null;
        if (options.position == "topleft") {
            positioning = [ 'left', 'top' ];
        } else if (options.position == "topcenter") {
            positioning = [ 'center', 'top' ];
        } else if (options.position == "topright") {
            positioning = [ 'right', 'top' ];
        } else if (options.position == "center") {
            positioning = 'center';
        } else if (options.position == "left") {
            positioning = 'left';
        } else if (options.position == "right") {
            positioning = 'right';
        } else {
            positioning = [ 'left', 'top' ];
        }

        return positioning;
    }

    function _dialogOpen(event, ui) {
        waitSpinnerShow();
        _lookupContainer.empty();

        var queryArgs = "presentation=" + options.presentation;
        if (typeof options.args == "object" && jQuery.isArray(options.args)) {
            for ( var i = 0; i < options.args.length; i++) {
                queryArgs += "&parm" + i + "=" + jQuery(options.args[i]).val();
            }
        }

        _lookupChaining();
        _addCloseEventForClickingOnBackgroundLayer();

        // load lookup data from server
        jQuery.ajax({
            type : "POST",
            url : options.requestUrl,
            data : queryArgs,
            timeout : AJAX_REQUEST_TIMEOUT,
            cache : false,
            dataFilter : function(data, dataType) {
                waitSpinnerHide();
                return data;
            },

            success : function(data) {
                _lookupContainer.html(data);
                new ButtonModifier(_lookupId).modifyLookupLinks();
            },

            error : function(xhr, reason, exception) {
                if (exception != 'abort') {
                    alert("An error occurred while communicating with the server:\n\n\nreason=" + reason + "\n\nexception=" + exception);
                }
                location.reload(true);
            }
        });
    }

    function _lookupChaining() {
        /*
         * set up the window chaining if the ACTIVATED_LOOKUP var is set there
         * have to be more than one lookup, before registrating the new lookup
         * we store the id of the old lookup in the preLookup variable of the
         * new lookup object. I.e. lookup_1 calls lookup_8, the lookup_8 object
         * need a reference to lookup_1, this reference is set here
         */

        var prevLookup = null
        if (ACTIVATED_LOOKUP) {
            prevLookup = ACTIVATED_LOOKUP;
        }

        _activateLookup(_lookupId);

        GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).prevLookup = prevLookup;
    }

    function _activateLookup(newAl) {
        if (ACTIVATED_LOOKUP != newAl) {
            ACTIVATED_LOOKUP = newAl;
        }
    }

    function _addCloseEventForClickingOnBackgroundLayer() {
        _backgroundCloseClickEvent = function() {
            if (ACTIVATED_LOOKUP && ACTIVATED_LOOKUP == _lookupId) {
                GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).dialogRef.dialog("close");
            }
        }

        jQuery(".ui-widget-overlay").click(_backgroundCloseClickEvent);
    }

    function _dialogClose() {
        jQuery(".ui-widget-overlay").unbind("click", _backgroundCloseClickEvent)

        var prevLookup = null;
        if (ACTIVATED_LOOKUP) {
            prevLookup = GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).prevLookup;
        }

        if (prevLookup) {
            _activateLookup(prevLookup);
        } else {
            ACTIVATED_LOOKUP = null;
        }
    }

    function _addOpenEvent(dialogReference) {
        jQuery("#" + _lookupId + "_button").click(function() {
            dialogReference.dialog("open");

            GLOBAL_LOOKUP_REF.getReference(_lookupId).target = jQuery(options.dialogTarget);
            if (options.dialogOptionalTarget != null) {
                GLOBAL_LOOKUP_REF.getReference(_lookupId).target2 = jQuery(options.dialogOptionalTarget);
            }
        });

    }

    return {
        init : _init
    }
};

/*******************************************************************************
 * Lookup Counter Object
 ******************************************************************************/
var FieldLookupCounter = function() {
    this.refArr = {};

    this.setReference = function(key, ref) {
        // if key doesn't exist in the array and
        var itm;
        for (itm in this.refArr) {
            if (itm == key) {
                prefix = key.substring(0, key.indexOf("_"));
                key = prefix + "_" + key;
                this.refArr["" + key + ""] = ref;
                return this.refArr[key];
            }
        }
        this.refArr["" + key + ""] = ref;
        return this.refArr[key];
    };

    this.getReference = function(key) {
        // when key does not exist return null?
        return this.refArr[key] != null ? this.refArr[key] : null;
    };

    this.getLastReference = function() {
        return (this.countFields() - 1) + "_lookupId";
    }

    this.createNextKey = function() {
        return this.countFields() + "_lookupId";
    };

    this.countFields = function() {
        var count = 0;
        jQuery.each(this.refArr, function(itm) {
            count++;
        });
        return count;
    };

    this.removeReference = function(key) {
        // deletes the Array entry (doesn't effect the array length)
        delete this.refArr[key];
    };

};
var GLOBAL_LOOKUP_REF = new FieldLookupCounter();

/*******************************************************************************
 * Button Modifier Object
 ******************************************************************************/
var ButtonModifier = function(lookupDiv) {

    function _modifyLookupLinks() {
        if (!lookupDiv) {
            return;
        }

        _modifyCollapseable();

        _modifySubmitButton();

        _modifyPagination();

        _modifyResultTable();
    }

    function _modifyCollapseable() {

        var slTitleBars = jQuery("#" + lookupDiv + " .screenlet-title-bar");

        jQuery.each(slTitleBars, function(index) {
            var slTitleBar = slTitleBars[index];
            var ul = slTitleBar.firstChild;
            if ((typeof ul) != 'object') {
                return true;
            }
            var childElements = ul.childNodes;

            for (j in childElements) {
                if (childElements[j].className == 'expanded' || childElements[j].className == 'collapsed') {
                    break;
                }
            }

            _getNextCollapseSeq();
            var childEle = childElements[j].firstChild;

            childEle.setAttribute('onclick', "javascript:toggleScreenlet(this, 'lec" + COLLAPSE_SEQUENCE_NUMBER
                    + "', 'true', 'Expand', 'Collapse');");
            childEle.href = "javascript:void(0);"
            jQuery(slTitleBar).next('div').attr('id', 'lec' + COLLAPSE_SEQUENCE_NUMBER);

        });
    }

    function _getNextCollapseSeq() {
        COLLAPSE_SEQUENCE_NUMBER++;
        return COLLAPSE_SEQUENCE_NUMBER;
    }

    function _modifySubmitButton() {
        var lookupForm = jQuery("#" + lookupDiv + " form:first");

        // set new form name and id
        var oldFormName = lookupForm.attr("name");
        lookupForm.attr("name", "form_" + lookupDiv);
        lookupForm.attr("id", "form_" + lookupDiv);
        lookupForm = jQuery("#form_" + lookupDiv);

        // set new links for lookups
        var newLookups = jQuery("#" + lookupDiv + " .field-lookup");

        var formAction = lookupForm.attr("action");

        // remove the form action
        lookupForm.attr("action", "");
        var input = jQuery("#" + lookupDiv + " input[type=submit]").css({
            display : "block"
        });

        // remove the original input button and replace with a new one
        var txt = input.attr("value");
        (input.parent()).append(jQuery("<button/>", {
            id : "lookupSubmitButton",
            href : "javascript:void(0);",
            click : function() {
                lookupFormAjaxRequest(formAction, lookupForm.attr("id"));
                return false;
            },
            text : txt
        }));

        input.remove();
    }

    function _modifyPagination() {
        // modify nav-pager
        var navPagers = jQuery("#" + lookupDiv + " .nav-pager a");
        jQuery.each(navPagers, function(navPager) {
            var onClickEvent = navPagers[navPager].onclick;
            navPagers[navPager].onclick = function(){
                this.setAttribute("data-lookupajax", "true");
                onClickEvent.apply(this);
            }
        });

        var navPagersSelect = jQuery("#" + lookupDiv + " .nav-pager select");
        jQuery.each(navPagersSelect, function(navPager) {
            var onChangeEvent = navPagersSelect[navPager].onchange;
            navPagersSelect[navPager].onchange = function(){
                this.setAttribute("data-lookupajax", "true");
                onChangeEvent.apply(this);
            }
        });
    }

    function _modifyResultTable() {
        var resultTable = jQuery("#" + lookupDiv + " #search-results table:first tbody");
        var tableChilds = resultTable.children();

        jQuery.each(tableChilds, function(tableChild) {
            var childElements = jQuery(tableChilds[tableChild]);
            var tableRows = childElements.children();

            jQuery.each(tableRows, function(cell) {
                var cellChilds = jQuery(tableRows[cell]).children();

                jQuery.each(cellChilds, function(child) {
                    if (cellChilds[child].tagName == "A") {
                        var link = cellChilds[child].href;
                        if (link.indexOf("javascript:set_") != -1) {
                            cellChilds[child].href = link;
                        } else {
                            var liSub = link.substring(link.lastIndexOf('/') + 1, (link.length));
                            cellChilds[child].href = "javascript:lookupAjaxRequest('" + liSub + "&presentation=layer')";
                        }
                    }
                });

            });

        });
    }

    return {
        modifyLookupLinks : _modifyLookupLinks
    }
}

/*******************************************************************************
 * Ajax Request Helper
 ******************************************************************************/
function lookupAjaxRequest(request) {
    // get request arguments
    var arg = request.substring(request.indexOf('?') + 1, (request.length));
    request = request.substring(0, request.indexOf('?'));
    lookupId = GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).lookupId;
    jQuery("#" + lookupId).load(request, arg, function(data) {
        new ButtonModifier(lookupId).modifyLookupLinks();
    });
}

function lookupFormAjaxRequest(formAction, form) {
    var lookupId = GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).lookupId;
    var data = jQuery("#" + form).serialize();
    data = data + "&presentation=" + GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).presentation;

    var screenletTitleBar = jQuery("#" + lookupId + " .screenlet-title-bar :visible:first");
    jQuery.ajax({
        url : formAction,
        type: "POST",
        data : data,
        beforeSend : function(jqXHR, settings) {
            // Here we append the spinner to the lookup screenlet and it will
            // shown till the ajax request is processed.
            var indicator = screenletTitleBar.find("span.indicator");
            // Check that if spinner is already in execution then don't add new
            // spinner
            if (indicator.length == 0) {
                jQuery("<span class='indicator'><img src='/images/ajax-loader.gif' alt='' /></span>").appendTo(screenletTitleBar);
            }
        },
        success : function(result) {
            if (result.search(/loginform/) != -1) {
                window.location.href = window.location.href;
                return;
            }
            // Here we are removing the spinner.
            var indicator = screenletTitleBar.find("span.indicator");
            if (indicator != undefined) {
                jQuery("span.indicator").remove();
            }
            jQuery("#" + lookupId).html(result);
            new ButtonModifier(lookupId).modifyLookupLinks();
        }
    });
}

function lookupPaginationAjaxRequest(navAction, type) {
    var lookupDiv = (GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).divRef);
    var lookupContent = (GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).contentRef);

    var lookupId = GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).lookupId;
    var screenletTitleBar = jQuery("#" + lookupId + " .screenlet-title-bar :visible:first");

    jQuery.ajax({
        url : navAction.substring(0, navAction.indexOf("?")),
        type : "POST",
        data : navAction.substring(navAction.indexOf("?")+1, navAction.length),
        beforeSend : function(jqXHR, settings) {
            // Here we append the spinner to the lookup screenlet and it will
            // shown till the ajax request is processed.
            var indicator = screenletTitleBar.find("span.indicator");
            // Check that if spinner is already in execution then don't add new
            // spinner
            if (indicator.length == 0) {
                jQuery("<span class='indicator'><img src='/images/ajax-loader.gif' alt='' /></span>").appendTo(screenletTitleBar);
            }
        },
        success : function(result) {
            if (result.search(/loginform/) != -1) {
                window.location.href = window.location.href;
                return;
            }
            // Here we are removing the spinner.
            var indicator = screenletTitleBar.find("span.indicator");
            if (indicator != undefined) {
                jQuery("span.indicator").remove();
            }
            jQuery("#" + lookupId).html(result);
            new ButtonModifier(lookupId).modifyLookupLinks();
        }
    });
}

/*******************************************************************************
 * This code inserts the value lookedup by a popup window back into the
 * associated form element
 ******************************************************************************/
var re_id = new RegExp('id=(\\d+)');
var num_id = (re_id.exec(String(window.location)) ? new Number(RegExp.$1) : 0);
var obj_caller;
try {
    obj_caller = (window.opener && window.opener.lookups? window.opener.lookups[num_id]: null);
    if (obj_caller == null && window.opener != null) {
        obj_caller = window.opener;
    } else if (obj_caller == null && window.opener == null) {
        obj_caller = parent;
    }
}
catch (err) {
    obj_caller = parent;
    if (console) {
        console.log(err);
    }
}

function setSourceColor(src) {
    if (src && src != null) {
        src.css("background-color", "yellow");
    }
}
// function passing selected value to calling window, using only in the
// TimeDuration case
function set_duration_value(value) {
    if (GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP)) {
        obj_caller.target = GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).target;
    } else {
        obj_caller.target = jQuery(obj_caller.targetW);
    }
    var target = obj_caller.target;

    write_value(value, target);
    closeLookup();
}
// function passing selected value to calling window
function set_value(value) {
    if (GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP)) {
        obj_caller.target = GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).target;
    } else {
        obj_caller.target = jQuery(obj_caller.targetW);
    }

    var target = obj_caller.target;
    write_value(value, target);

    closeLookup();
}
// function passing selected value to calling window
function set_values(value, value2) {
    if (GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP)) {
        obj_caller.target = GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).target;
        obj_caller.target2 = GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).target2;
    } else {
        obj_caller.target = jQuery(obj_caller.targetW);
    }
    var target = obj_caller.target;
    var target2 = obj_caller.target2;
    write_value(value, target);
    write_value(value2, target2)
    var showDescription = GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP) ? GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).showDescription : false;
    if (showDescription) {
        setLookDescription(target.attr("id"), value + " " + value2, "", "", showDescription);
    }

    closeLookup();
}

function write_value(value, target) {
    if (target && target != null) {
        setSourceColor(target);
        target.val(value);
        target.trigger("lookup:changed");
    }
}

function set_multivalues(value) {
    obj_caller.target.value = value;
    field = jQuery("#" + target.attr('id'));
    field.trigger("lookup:changed");
    /*
     * If we decide to keep it (only used in Example, though it's needed also
     * for Themes and Languages but not the same way)
     */
    if (field.change != null) {
        field.click().change()
    }

    var thisForm = obj_caller.target.form;
    var evalString = "";

    if (arguments.length > 2) {
        for ( var i = 1; i < arguments.length; i = i + 2) {
            evalString = "setSourceColor(thisForm." + arguments[i] + ")";
            eval(evalString);
            evalString = "thisForm." + arguments[i] + ".value='" + arguments[i + 1] + "'";
            eval(evalString);
        }
    }
    closeLookup();
}

// close the window after passing the value
function closeLookup() {
    if (window.opener != null && GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP) == null) {
        window.close();
    } else {
        var lookupId = GLOBAL_LOOKUP_REF.getReference(ACTIVATED_LOOKUP).lookupId;
        jQuery("#" + lookupId).dialog("close");
    }
}

/*******************************************************************************
 * Lookup Description Helper
 ******************************************************************************/
// load description for lookup fields
var lookupDescriptionLoaded = function(fieldId, url, params, formName) {
    this.init(fieldId, url, params, formName);
}
lookupDescriptionLoaded.prototype.init = function(fieldId, url, params, formName) {
    this.fieldId = fieldId;
    this.url = url;
    this.params = params;
    this.formName = formName;
}
lookupDescriptionLoaded.prototype.update = function() {
    var tooltipElement = jQuery("#" + this.fieldId + '_lookupDescription');
    if (tooltipElement.length) {// first remove current description
        tooltipElement.remove();
    }

    var indexOf = this.params.indexOf("searchValueFieldName");
    if (indexOf == -1) {
        return;
    }

    // actual server call
    var fieldName = this.params.substring(indexOf);
    fieldName = fieldName.substring(fieldName.indexOf("=") + 1);
    fieldObj = jQuery("input[name=" + fieldName + "]", jQuery("form[name=" + this.formName + "]"));
    if (fieldObj.val()) {
        var fieldSerialized = fieldObj.serialize();
        this.allParams = this.params + '&' + fieldSerialized + '&' + 'searchType=EQUALS';
        var _fieldId = this.fieldId;

        jQuery.ajax({
            url : this.url,
            type : "POST",
            data : this.allParams,
            async : false,
            success : function(result) {
                // This would be far more reliable if we were removing
                // the widget boundaries in LookupDecorator using
                // widgetVerbose in context :/
                if (result.split("ajaxAutocompleteOptions.ftl -->")[1]) {
                    setLookDescription(_fieldId, result.split("ajaxAutocompleteOptions.ftl -->")[1].trim().split("<!--")[0].trim(),
                            "", "");
                }
            }
        });
    }
}

// Needed because IE8 does not implement trim yet
if (typeof String.prototype.trim !== 'function') {
    String.prototype.trim = function() {
        return this.replace(/^\s+|\s+$/g, '');
    }
}