//============================================
// getTarget
//============================================
function getTarget( sender, id ) {


    //=========================================================
    // Identify the html element that will be the target
    // of this request using the id-parameter.
    // When this is found, all its child form-objects
    // must be submitted / added to the generated request.
    //=========================================================

    //=========================================================
    // Try identifying the target container by
    // - direct retrieval from the document level
    //   (using document.getElementById(id))
    // - traversing upwards from the sender-element
    //   using its ancestors (element.parentNode)
    //=========================================================
    var topDownTargetContainer = document.getElementById(id);

    var bottomUpTargetContainer = null;
    var parent = sender.parentNode;

    while( bottomUpTargetContainer == null ) {
        if( parent.getAttribute('id') == id ) {
            bottomUpTargetContainer = parent;
        }
        if( parent.parentNode == parent.ownerDocument ) {
            break;
        }
        parent = parent.parentNode;
    }

    //=========================================================
    // If only element retrieval from the document root
    // returned a result, this element will be our container.
    // Otherwise, the retured element from upwards traversing
    // is the element we're after,
    // and we will post its child-elements
    //=========================================================
    if( topDownTargetContainer && !bottomUpTargetContainer )
        return topDownTargetContainer;
    else if( bottomUpTargetContainer )
        return bottomUpTargetContainer;
}


//============================================
// asyncUpdate
//
// Takes id of element to be replaced,
// and new content url as parameters
//============================================
function getEventSubmitAsync( sender, eventName, parameters, id, url, validation, elementContext, componentContext, compositeIdContext ) {

    if( document.getElementById('_cmdPosted') != null )
        return;

    var elmUpdate = getTarget(sender, id);
    if( elmUpdate == null ) {
        alert('AJAX update failure, the specified element #' + id + ' was not found');
        return;
    }

    //=========================================================
    // Parse and handle command parameters.
    //=========================================================
    var reqParameters = "_cmdName=" + eventName + "&_updateTargetId=" + id + "&_compositeIdContext=" + compositeIdContext + "&_validate=" + validation + "&" + escapeParameterString("_updateContext", elementContext) + "&_componentContainerContext=" + componentContext;
    if( parameters != '' ) {
        for( var paramCounter = 0; paramCounter < parameters.length; paramCounter++ ) {
            reqParameters = reqParameters + "&" + escapeParameterString("_param" + paramCounter, parameters[paramCounter]);
        }
    }

    var senderName = sender.name;
    var senderValue = sender.value;

    //========================================================
    // Add post-parameter for sender-element.
    //========================================================

    // Make sure that we post an empty value if the sender is an unchecked checkbox
    if( sender.type == 'checkbox' && !sender.checked )
        senderValue = "";
    // If the sender is a button with 'allow text wrapping' set, this will be rendered as a
    // div with no name or value set. If so, this should not be added to the generated parameter string.
    if( sender.tagName != "DIV" )
        reqParameters = reqParameters + "&" + escapeParameterString(sender.name, senderValue);
    else
        senderName = "";

    //========================================================
    // Add post-parameter for all INPUT form-elements.
    //========================================================
    var formElements = elmUpdate.getElementsByTagName("INPUT");
    for( var elementCounter = 0; elementCounter < formElements.length; elementCounter++ ) {
        var formElement = formElements[elementCounter];
        if( senderName != formElement.name && "" != formElement.name && !formElement.disabled ) {

            var elementValue = formElement.value
            if( formElement.type == 'checkbox' && !formElement.checked )
                elementValue = "";

            // Only the checked radiobutton must be posted, as all radiobuttons in a radiobutton-group points to the same xpath.
            if( formElement.type != 'radio' || formElement.checked )
                reqParameters = reqParameters + "&" + escapeParameterString(formElement.name, elementValue)
        }
    }

    //========================================================
    // Add post-parameter for all TEXT-AREA form-elements.
    //========================================================
    formElements = elmUpdate.getElementsByTagName("textarea");
    for( var elementCounter = 0; elementCounter < formElements.length; elementCounter++ ) {
        var element = formElements[elementCounter];
        if( senderName != element.name )
            if( !element.disabled )
                reqParameters = reqParameters + "&" + escapeParameterString(element.name, element.value)
    }

    //========================================================
    // Add post-parameter for all SELECT form-elements.
    //========================================================
    formElements = elmUpdate.getElementsByTagName("SELECT");
    for( var elementCounter = 0; elementCounter < formElements.length; elementCounter++ ) {
        var element = formElements[elementCounter];
        if( senderName != element.name )
            if( !element.disabled )
                reqParameters = reqParameters + "&" + escapeParameterString(element.name, element.value)
    }

    //=========================================================
    //Execute ajax-request
    //=========================================================
    var anim = showProgress(sender);
    var serverResponse = execRequest(reqParameters);
    handleResponse(elmUpdate, serverResponse);
    $(anim).remove();

    $("textarea").autoGrow();
    
    if( "" != senderName ) {
        var focusElements = document.getElementsByName(senderName);
        if( focusElements.length == 1 ) {
            var focusElement = focusElements[0];
            focusElement.focus();
        }
    }
}

function escapeParameterString( paramName, paramValue ) {
    paramName = paramName.replace(/&/g, '%26').replace(/'/g, "%27").replace(/=/g, '%3D').replace(/\+/g, '%2B');
    paramValue = paramValue.replace(/&/g, '%26').replace(/'/g, "%27").replace(/\+/g, "%2B");
    return paramName + "=" + paramValue;
}


function execRequest( reqParameters ) {

    $.ajaxSetup({
        'xhr':function() {
            return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
        }
    });

    //Execute ajax-request
    return $.ajax({
        url: document.forms[0].action.replace('htmlViewer', 'htmlViewerAjax'),
        global: false,
        async: false,
        type: "POST",
        data: reqParameters,
        dataType: "xml",
        contentType: "application/x-www-form-urlencoded;charset=utf-8"
    });
}

function handleResponse( updateElement, response ) {
    $(updateElement).replaceWith(response.responseText);
}

// Build and output the keepAlive javascript
function sessionKeepAlive( targetUrl ) {
    //alert('keeping alive');
    if( maximumKeepAlives > 0 ) {
        $.ajaxSetup({'xhr':function() {
            return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
        }});
        var date = new Date();

        //Execute ajax keepalive request
        $.ajax({
            url: targetUrl + '&timestamp=' + date.getTime(),
            async: true,
            type: "GET",
            dataType: "xml"
        });
        maximumKeepAlives--;
    }
    else {
        clearInterval(keepAliveInterval);
    }
}


function sessionCleanOnClose( targetEndpoint ) {

    $.ajaxSetup({'xhr':function() {
        return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
    }});

    //Execute ajax sessionCleaner request
    $.ajax({
        url: targetEndpoint,
        async: true,
        type: "GET"
    });
}
