/*
 * Copyright (c) 1998-2009 TeamDev Ltd. All Rights Reserved.
 * Use is subject to license terms.
 */

// ================================== PUBLIC API FUNCTIONS

Q$.extend(window.QuipuKit, {
  ReloadComponents: Q$.createClass(null, {
    constructor: function(componentIds, params) {
      this.componentIds = componentIds;
      if (params)
        Q$.extend(this, params);
    },

    run: function() {
      q_reloadComponents(this.componentIds, this);
    }
  }),

  _initReloadComponents: function(id, componentIds, params) {
    function initComponent() {
      var component = Q$(id);
      if (!component) {
        setTimeout(function() {initComponent();}, 100);
        return;
      }
      Q$.extend(component, new Q$.ReloadComponents(componentIds, params));
    }
    if (Q$(id))
      initComponent();
    else
      setTimeout(function() {
        if (Q$(id))
          initComponent();
        else
          q__addLoadEvent(function(){
            initComponent();
          });
      }, 1);
  }

});


/**
 * componentIds - components to which an ajax request is being made
 * agrs - (optional) is an object, which consist of:
 *    onajaxend - (optional) the function that should be invoked when ajax request is fully processed
 *    submittedComponentIds - (optional) array of clientIds for components whose processDecodes->...->processUpdates phases should be invoked in addition to the component being reloaded
 *    onerror - (optional) the function that should be invoked when ajax request fails to complete successfully for some reason
 *    onajaxstart - (optional) the function that should be invoked before ajax request is started
 *    immediate - (optional) true means that the serverAction should be executed during Apply Request Values phase, rather than waiting until the Invoke Application phase
 */
function q_reloadComponents(componentIds, args) {
  /* todo: revise this API. We'll need programmatic access for invoking q:reloadComponents with JavaScript. This method should probably be
  removed in favor of that API. There should be an ability to create q:reloadComponents at run-time, and API for 
  running it should be the same regardless of whether it's included on the page or created with JavaScript,
  e.g. new Q$.ReloadComponents(componentId, {onajaxend: ...}).run(),
  or Q$.reloadComponents(componentId).run();*/
  q__reloadComponent(componentIds, args);
}

// ================================== IMPLEMENTATION


var Q__AJAX_REQUEST_MARKER = "teamdev_ajax";
var Q__UPDATE_PORTIONS_SUFFIX = "q_ajax_portions";
var Q__SUBMIT_PARAMS_SUFFIX = "_ajax_submit_params";
var Q__PARAM_COMPONENT_IDS = "q__componentIds";
var Q__CUSTOM_JSON_PARAM = "q__customJsonParam";
var Q__SUBMITTED_COMPONENT_IDS = "submittedComponentIds";
var Q__SERVER_ACTION = "serverAction";
var Q__SERVER_ACTION_SOURCE_COMPONENT_ID = "serverActionSourceComponentId";
var Q__ACTION_LISTENER = "q__actionListener";
var Q__ACTION_COMPONENT = "q__actionComponent";
var Q__IMMEDIATE = "q__immediate";
var Q__TAG_AJAX_UPDATABLE = "updatable";
var Q__TAG_AJAX_SCRIPT = "script";
var Q__TAG_AJAX_CSS = "css";
var Q__TAG_AJAX_SESSION_EXPIRED = "session_expired";
var Q__TAG_AJAX_SESSION_EXPIRED_LOCATION = "session_expired_location";
var Q__TAG_AJAX_EXCEPTION = "ajax_exception";
var Q__TAG_AJAX_EXCEPTION_MESSAGE = "ajax_exception_message";
var Q__TAG_AJAX_STYLE = "style";

var Q__UPDATE_TYPE_SIMPLE = "simple";
var Q__UPDATE_TYPE_PORTION = "portion";
var Q__UPDATE_TYPE_STATE = "state";

var Q__UPDATE_TYPE_INITIALIZATION = "initialization";

var Q__TEXT_RESPONSE_PREFIX = "_quipukit_ajax_response_prefix_";
var Q__TEXT_RESPONSE_SUFFIX = "_quipukit_ajax_response_suffix_";

window.QuipuKit.Ajax = {
  Page: {},
  Components: new Array()
};

function q__setCommonAjaxEventHandler(eventName, func) {
  if (!eventName || !func)
    return;

//  if (document.__commonAjaxEventHandlerInitialized && document.__commonAjaxEventHandlerInitialized[eventName])
  //    return;

  if (!QuipuKit.Ajax.Page[eventName]) {
    QuipuKit.Ajax.Page[eventName] = func;
  }
  else {
    var oldEventHandlerFunction = QuipuKit.Ajax.Page[eventName];
    QuipuKit.Ajax.Page[eventName] = function(event) {
      if (oldEventHandlerFunction(event) !== false)
        func(event);
    }
  }

  if (!document.__commonAjaxEventHandlerInitialized) {
    document.__commonAjaxEventHandlerInitialized = new Array();
    document.__commonAjaxEventHandlerInitialized[eventName] = true;
  }

  document.__commonAjaxEventHandlerInitialized[eventName] = true;
}


function q__setComponentAjaxEventHandler(eventName, func, componentId) {
  if (!eventName || !func || !componentId)
    return;

//  if ((document.__componentsAjaxEventHandlerInitialized &&
  //       document.__componentsAjaxEventHandlerInitialized[componentId] &&
  //       document.__componentsAjaxEventHandlerInitialized[componentId][eventName]))
  //    return;


  if (!QuipuKit.Ajax.Components[componentId]) {
    QuipuKit.Ajax.Components[componentId] = new Array();
  }

  if (!QuipuKit.Ajax.Components[componentId][eventName]) {
    QuipuKit.Ajax.Components[componentId][eventName] = func;
  } else {
    var oldComponentEventHandlerFunction = QuipuKit.Ajax.Components[componentId][eventName];
    QuipuKit.Ajax.Components[componentId][eventName] = function(event) {
      if (oldComponentEventHandlerFunction(event) == false) {
        return;
      } else {
        func(event);
        return;
      }
    }
  }

  if (!document.__componentsAjaxEventHandlerInitialized) {
    document.__componentsAjaxEventHandlerInitialized = new Array();
    document.__componentsAjaxEventHandlerInitialized[componentId] = new Array();
  }

  if (!document.__componentsAjaxEventHandlerInitialized[componentId]) {
    document.__componentsAjaxEventHandlerInitialized[componentId] = new Array();
  }

  document.__componentsAjaxEventHandlerInitialized[componentId][eventName] = true;
}


function q_reloadPage(loc) {
  window.location = loc;
}

function q__reloadComponent(componentIds, args) {
  if (!args) args = {}
  var params = args.additionalParams ? args.additionalParams : [];
  var ids = new Array();
  if (args.serverAction)
    params.push([Q__SERVER_ACTION, args.serverAction]);
  if (componentIds instanceof Array) {
    ids = componentIds;
  } else {
    ids[0] = componentIds;
  }
  args.additionalParams = params;
  if (!args.requestDelay)
    q__sendAjaxRequestIfNoFormSubmission(ids, args);
  else {
    var delayId = args.requestDelayId;
    if (!delayId) {
      delayId = "";
      for (var i = 0, count = ids.length; i < count; i++) {
        delayId += ids[i];
        if (i < count - 1)
          delayId += ",";
      }
    }
    q__invokeFunctionAfterDelay(function() {
      q__sendAjaxRequestIfNoFormSubmission(ids, args);
    }, args.requestDelay, delayId);
  }
}

function q__requestComponentPortions(componentId, portionNames, customJsonParam, portionProcessor, onerror, serverAction) {
  if (!componentId)
    throw "componentId should be specified";
  if (! (portionNames instanceof Array))
    throw "portionNames should be specified as an array, but specified as: " + portionNames;
  if (!portionProcessor)
    throw "q__requestComponentPortions: portionProcessor should be specified";
  var params = new Array();
  if (serverAction)
    params.push([Q__SERVER_ACTION, serverAction]);
  q__sendAjaxRequestIfNoFormSubmission([componentId], {portionNames: portionNames, portionProcessor: portionProcessor,
    additionalParams: params, onerror: onerror, customJsonParam: customJsonParam});
}

/*
  Sends ajax request only if no form submission is initated in the same event handler
  (e.g. a submit button invoking an ajax request in the onclick handler)
*/
function q__sendAjaxRequestIfNoFormSubmission() {
  var ajaxArgs = arguments;
  document.q__ajaxRequestScheduled = true;
  setTimeout(function() {
    document.q__ajaxRequestScheduled = false;
    if (q__isFormSubmissionJustStated())
      return;

    if (document.q__ajax_request_processing) {

      if (!document.q__ajax_requests_queue) {
        document.q__ajax_requests_queue = new Array();
      }
      document.q__ajax_requests_queue.push(ajaxArgs);

      return;
    }

    document.q__ajax_request_processing = true;
    q__sendAjaxRequest.apply(null, ajaxArgs);
  }, 1);
}

/**
 * componentId - component to which an ajax request is being made
 *
 * args fields: 
 * portionNames - null value means that the whole component should be reloaded, otherwise it should be an array of component portion names
 * portionProcessor - must be specified if portionNames is specified
 * onajaxend - (optional) the function that should be invoked when ajax request is fully processed
 * submittedComponentIds - (optional) array of clientIds for components whose processDecodes->...->processUpdates phases should be invoked in addition to the component being reloaded
 * additionalParams - (optional) array of parameters those should be submitted in addition to form field data parameters
 * onerror - (optional) the function that should be invoked when ajax request fails to complete successfully for some reason
 * actionListener -
 * onajaxstart -
 * immediate -
 * actionComponent -
 * customJsonParam -
 *
 * serverAction - (optional) server action in the form of EL, which should be executed during this ajax request
 * serverActionSourceComponentId - (optional) client id of a component from which this action is initiated (e.g. actual for a button in a table which needs current row's data in the action)
 */
function q__sendAjaxRequest(componentIds, args) {
  if (document.__sessionHasExpired
          && document.__componentsAjaxEventHandlerInitialized
          && componentIds.every(function(element) {
    return (document.__componentsAjaxEventHandlerInitialized[element]) ? true : false;
  })
          && componentIds.every(function(element) {
    return (document.__componentsAjaxEventHandlerInitialized[element]["onsessionexpired"]) ? true : false;
  })) {
    if (q__processSessionExpiration(document.__sessionReloadLocation, componentIds, null, true)) {
      if (args.onerror) {
        args.onerror();
      }
      document.q__ajax_request_processing = false;
      return;
    }
  }

  if (document.__sessionHasExpired &&
      document.__commonAjaxEventHandlerInitialized &&
      document.__commonAjaxEventHandlerInitialized["onsessionexpired"]) {
    if (q__processSessionExpiration(document.__sessionReloadLocation, componentIds, null, true)) {
      if (args.onerror) {
        args.onerror();
      }
      document.q__ajax_request_processing = false;
      return;
    }
  }

  if (!componentIds.length) {
    q__logError("q__sendAjaxRequest: Array of components ids should be not empty");
  }
  var components = new Array()
  for (i = 0; i < componentIds.length; i++) {
    components[components.length] = q__getElement(componentIds[i]);
  }

  //we need to fire validation for enclosing form (if there are no client validation support - just skip client validation (there will be server side validation only)
  //if form is not valid - no AJAX request at all
  //    if (document.q_clientValidationSupport) {
  //      if (!q_validateEnclosingForm(component)) {
  //        return;
  //      }
  //    }
  var form = q__findParentNode(components[0], "FORM");
  q__assert(form, "q__sendAjaxRequest: Enclosing form not found for element with id: " + components[0].id);
  if (!components.every(function(element) {
    return (form == q__findParentNode(element, "FORM"));
  })) {
    q__logError("q__sendAjaxRequest: Enclosing forms differ for components");
  }

  var ajaxObject = new q__AjaxObject(componentIds);
  ajaxObject._onajaxstart = args.onajaxstart;
  q__requestStarted(ajaxObject);

  var paramsBuf = new q__StringBuffer();
  q__prepareFormParams(form, paramsBuf);
  paramsBuf.append("&");
  if (q__prepareUpdates(paramsBuf, componentIds, args.portionNames))
    paramsBuf.append("&");
  if (componentIds != null) {
    var componentIdsParams = "";
    for (var index = 0, componentsCount = componentIds.length; index < componentsCount; index++) {
      if (componentIdsParams != "")
        componentIdsParams += ";";
      componentIdsParams += componentIds[index];
    }
    paramsBuf.append(Q__PARAM_COMPONENT_IDS).append("=").append(componentIdsParams);
  }
  if (args.submittedComponentIds != null) {
    paramsBuf.append("&");
    var componentIdsParam = "";
    for (var idx = 0, submittedComponentCount = args.submittedComponentIds.length; idx < submittedComponentCount; idx++) {
      if (componentIdsParam != "")
        componentIdsParam += ";";
      componentIdsParam += args.submittedComponentIds[idx];
    }
    paramsBuf.append(Q__SUBMITTED_COMPONENT_IDS).append("=").append(componentIdsParam);
  }
  if (args.additionalParams) {
    for (var i = 0, additionalParamCount = args.additionalParams.length; i < additionalParamCount; i++) {
      var paramEntry = args.additionalParams[i];
      paramsBuf.append("&");
      paramsBuf.append(paramEntry[0]).append("=").append(paramEntry[1]);
    }
  }
  if (args.actionListener && args.actionComponent) {
    paramsBuf.append("&").append(Q__ACTION_LISTENER).append("=").append(args.actionListener);
    paramsBuf.append("&").append(Q__ACTION_COMPONENT).append("=").append(args.actionComponent);
  }
  if (args.immediate) {
    paramsBuf.append("&").append(Q__IMMEDIATE).append("=").append(args.immediate);
  }
  paramsBuf.append("&");
  if (args.customJsonParam)
    paramsBuf.append(Q__CUSTOM_JSON_PARAM).append("=").append(args.customJsonParam);
  paramsBuf.append("&");
  paramsBuf.append(Q__AJAX_REQUEST_MARKER).append("=").append("true");


  if (args.portionProcessor) {
    ajaxObject._customProcessor = args.portionProcessor;
  }
  ajaxObject._ajaxFailedProcessor = args.onerror;

  ajaxObject._request.onreadystatechange = q__getEventHandlerFunction("_processResponse", null, ajaxObject);
  ajaxObject._completionCallback = args.onajaxend;
  ajaxObject._requestedComponentId = componentIds;

  var url = form.action;
  ajaxObject._request.open("POST", url, true);
  ajaxObject._request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
  ajaxObject._request.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
  // this if-modified-since header is required for IE not to cache response (vital for Portlets)
  var params = paramsBuf.toString();
  ajaxObject._request.send(params);
  ajaxObject._params = params;
  ajaxObject._url = url;

  q__saveScrollPositionIfNeeded();
}

var q__ajaxRequestsInProgress = 0;

function q__requestStarted(ajaxObject) {
  q__ajaxRequestsInProgress++;

  for (var i = 0; i < ajaxObject._targetIds.length; i++) {
    var targetId = ajaxObject._targetIds[i];
    var ajaxSettingsForComponent = QuipuKit.Ajax.Components[targetId];
    if (ajaxSettingsForComponent && ajaxSettingsForComponent.onajaxstart) {
      var ajaxstartEvent = q__createEvent("ajaxstart");
      try {
        ajaxSettingsForComponent.onajaxstart(ajaxstartEvent);
      } catch(ex) {
        q__requestFinished(ajaxObject);
        throw ex;
      }

    }
  }

  if (QuipuKit.Ajax.Page.onajaxstart) {
    var ajaxstartEvent = q__createEvent("ajaxstart");

    try {
      QuipuKit.Ajax.Page.onajaxstart(ajaxstartEvent);
    } catch(ex) {
      q__requestFinished(ajaxObject);
      throw ex;
    }

  }
  var ajaxstartEventLocal = q__createEvent("ajaxstart");
  if (ajaxObject._onajaxstart) {
    try {
      ajaxObject._onajaxstart(ajaxstartEventLocal);
    } catch(ex) {
      q__requestFinished(ajaxObject);
      throw ex;
    }
  }

  if (q__ajaxRequestsInProgress == 1) {
    q__showAjaxProgressMessage();
  }
}

function q__requestFinished(ajaxObject) {
  q__ajaxRequestsInProgress--;
  for (var i = 0; i < ajaxObject._targetIds.length; i++) {
    var targetId = ajaxObject._targetIds[i];
    var ajaxSettingsForComponent = QuipuKit.Ajax.Components[targetId];
    if (ajaxSettingsForComponent && ajaxSettingsForComponent.onajaxend) {
      var ajaxendEvent = q__createEvent("ajaxend");

      try {
        ajaxSettingsForComponent.onajaxend(ajaxendEvent);
      } catch(ex) {
        if (!ajaxObject._clientSideException) {
          ajaxObject._clientSideExceptions = new Array();
        }
        ajaxObject._clientSideExceptions.push(ex);
      }

    }
  }

  if (QuipuKit.Ajax.Page.onajaxend) {
    var ajaxendEvent = q__createEvent("ajaxend");

    try {
      QuipuKit.Ajax.Page.onajaxend(ajaxendEvent);
    } catch(ex) {
      if (!ajaxObject._clientSideException) {
        ajaxObject._clientSideExceptions = new Array();
      }
      ajaxObject._clientSideExceptions.push(ex);
    }

  }

  if (document.q__ajax_requests_queue && ajaxObject._clientSideExceptions) {
    while (ajaxObject._clientSideExceptions && ajaxObject._clientSideExceptions.length >= 0) {
      var exception = ajaxObject._clientSideExceptions.shift();
      throw exception;
    }
  }

  var newRequestStarted = false;

  if (document.q__ajax_requests_queue) {
    var ajaxArgs = document.q__ajax_requests_queue.shift();

    if (ajaxArgs) {
      document.q__ajax_request_processing = true;
      q__sendAjaxRequest.apply(null, ajaxArgs);
      newRequestStarted = true;
    }
  }


  if (q__ajaxRequestsInProgress == 0) {
    q__hideAjaxProgressMessage();
    q__retoreScrollPositionIfNeeded();
  }

  setTimeout(function() {
    if (!newRequestStarted)
      document.q__ajax_request_processing = false;
  }, 1);

  if (ajaxObject._clientSideExceptions) {
    while (ajaxObject._clientSideExceptions.length >= 0) {
      var exception = ajaxObject._clientSideExceptions.shift();
      throw exception;
    }
  }
}

function q__setAjaxCleanupRequired(ajaxCleanupRequired) {
  document._ajaxCleanupRequired = ajaxCleanupRequired;
}

function q__setAjaxMessageHTML(messageHTML) {
  if (document._ajaxInProgressMessage) {
    return;
  }

  var div = document.createElement("div");
  var simulateFixedPos = q__isExplorer();
  div.style.position = simulateFixedPos ? "absolute" : "fixed";
  div.style.zIndex = 1000;
  div.style.right = 0;
  div.style.top = 0;
  div.style.visibility = "hidden";
  div.innerHTML = messageHTML;
  document._ajaxInProgressMessage = div;
  q__addLoadEvent(function() {
    var prnt = q__getDefaultAbsolutePositionParent();

    prnt.appendChild(document._ajaxInProgressMessage);
    setTimeout(
            function() {
              if (document._ajaxInProgressMessage.style.visibility == "hidden") {
                document._ajaxInProgressMessage.style.display = "none";
                document._ajaxInProgressMessage.style.visibility = "";
              }
            }, 1000);
  })
}

function q__showAjaxProgressMessage() {
  var message = document._ajaxInProgressMessage;
  q__assert(message, "q__showAjaxProgressMessage: no message was registered");
  var simulateFixedPos = q__isExplorer();
  if (simulateFixedPos)
    q__updateAjaxInProgressMessagePos();

  if (message.style.visibility == "hidden")
    message.style.visibility = "";
  else
    message.style.display = "";
  if (document.body.style.cursor != "progress") {
    document.body.oldCursor = document.body.style.cursor;
  }
  document.body.style.cursor = "progress";

  if (simulateFixedPos) {
    window.attachEvent("onscroll", q__updateAjaxInProgressMessagePos);
    window.attachEvent("onresize", q__updateAjaxInProgressMessagePos);
  }
}

function q__hideAjaxProgressMessage() {
  var simulateFixedPos = q__isExplorer();
  if (simulateFixedPos) {
    window.detachEvent("onscroll", q__updateAjaxInProgressMessagePos);
    window.detachEvent("onresize", q__updateAjaxInProgressMessagePos);
  }
  document.body.style.cursor = document.body.oldCursor;
  var message = document._ajaxInProgressMessage;
  q__assert(message, "q__hideAjaxProgressMessage: no message was registered");
  message.style.display = "none";
}

function q__updateAjaxInProgressMessagePos() {
  var message = document._ajaxInProgressMessage;
  message.style.top = q__getPageScrollPos().y;
}

// q__AjaxObject class
function q__AjaxObject(componentIds) {
  this._targetIds = componentIds;
  this._mode = undefined;
  this._loc = undefined;
  if (window.XMLHttpRequest) {
    this._request = new XMLHttpRequest();
  } else {
    this._request = new ActiveXObject("Microsoft.XMLHTTP");
    // todo: catch exception here and report some meaningful error
  }

  this._processResponse = function() {
    var request = this._request;
    if (request.readyState != 4)
      return;

    var errorMessage = request.getResponseHeader("Error-Message");
    if (errorMessage) {
      processErrorDuringAjaxRequest(errorMessage, this._targetIds, this);
    }

    var requestStatus;
    try {
      requestStatus = request.status;
    }
    catch(exception) {
      if (exception.name == "NS_ERROR_NOT_AVAILABLE") {
        alert("An attempt to connect to the server failed. Please, check your network connection.");
        q__requestFinished(this);
        return;
      }
    }

    if (requestStatus == 0) {
      alert("An attempt to connect to the server failed. Please, check your network connection.");
      q__requestFinished(this);
      return;
    }

    if (requestStatus == 12029) {
      alert("An attempt to connect to the server failed. Please, check your network connection.");
      q__requestFinished(this);
      return;
    }
    if (requestStatus == 12030) {
      alert("The connection with the server has been terminated. Please, check your network connection.");
      q__requestFinished(this);
      return;
    }
    if (requestStatus == 12031) {
      alert("The connection with the server has been reset. Please, check your network connection.");
      q__requestFinished(this);
      return;
    }

    if (requestStatus != 200) {
      q__requestFinished(this);

      if (requestStatus == 500) {
        alert("Error while performing Ajax request: 500 (internal server error). See server logs for details.");
      } else if (requestStatus == 302) { // by the spec, 302 responses should be handled transparently by XMLHttpRequest
        alert("Error while performing Ajax request: 302 (this usually means a bug in the browser). If you're using Opera 9.0.x, please upgrade to Opera 9.1 or higher.");
      } else {
        alert("Error while performing Ajax request: \n" + requestStatus);
      }
      // todo: fire onerror event and invoke error handler
      return;
    }

    //test if there were no validation error during processing request on the server-side
    if (q__validationErrorDuringProcessing(request)) {
      q__requestFinished(this);
      q__submitByIds(this._targetIds);
      return;
    }


    try {
      //set flag - ajax update in progress
      document._q_page_is_already_initialized = true;
      if (request.responseXML) {
        var responseXML = request.responseXML;
        this._jsIncludes = responseXML.getElementsByTagName(Q__TAG_AJAX_SCRIPT);
        this._updatables = responseXML.getElementsByTagName(Q__TAG_AJAX_UPDATABLE);
        this._styles = responseXML.getElementsByTagName(Q__TAG_AJAX_STYLE);
        this._cssFiles = responseXML.getElementsByTagName(Q__TAG_AJAX_CSS);
      }
      if (!this._updatables || this._updatables.length == 0) {
        var responseText = request.responseText;
        var startIndex = responseText.indexOf(Q__TEXT_RESPONSE_PREFIX);
        if (startIndex == -1) {
          q__requestFinished(this);
          var errorMessage = "Error while performing Ajax request: illegal response - couldn't find data start marker. Response length: " + responseText.length;
          //          q__log("<b>" + errorMessage + "<br/>Original parameter list: " + this._params + "<br/>Original URL: " + this._url + "<br/>Response follows:><br/></b><xmp>" + responseText + "</xmp>");

          alert(errorMessage);
          return;
        }
        startIndex += Q__TEXT_RESPONSE_PREFIX.length;
        var endIndex = responseText.lastIndexOf(Q__TEXT_RESPONSE_SUFFIX);
        if (endIndex == -1) {
          q__requestFinished(this);
          alert("Error while performing Ajax request: illegal response - couldn't find data end marker. Response length: " + responseText.length);
          return;
        }
        var clippedResponseText = responseText.substring(startIndex, endIndex);
        var responseObj;
        eval("responseObj = " + clippedResponseText);
        this._jsIncludes = responseObj[Q__TAG_AJAX_SCRIPT];
        this._updatables = responseObj[Q__TAG_AJAX_UPDATABLE];
        this._styles = responseObj[Q__TAG_AJAX_STYLE];
        this._cssFiles = responseObj[Q__TAG_AJAX_CSS];
        this._sessionExpired = responseObj[Q__TAG_AJAX_SESSION_EXPIRED];
        this._sessionExpiredLocation = responseObj[Q__TAG_AJAX_SESSION_EXPIRED_LOCATION];
        this._exception = responseObj[Q__TAG_AJAX_EXCEPTION];
        this._exceptionMessage = responseObj[Q__TAG_AJAX_EXCEPTION_MESSAGE];
      }

      var isExceptionWasThrown = this._exception ? this._exception[0].value : undefined;
      if (isExceptionWasThrown) {
        var exceptionMessage = this._exceptionMessage ? this._exceptionMessage[0].value : "Exception";
        processErrorDuringAjaxRequest(exceptionMessage, this._targetIds, this);
      }

      q__processStylesIncludes(this._styles);
      q__processCSSFilesIncludes(this._cssFiles);
      //substitute document.write method to prevent error if foreign js library contains code that executes on library
      //loading and invokes document.write method to render some HTML. Otherwise document.write() method rewrites all
      //currently rendered in page content with content passed to it on AJAX response
      q__substituteDocumentWrite();
      try {
        q__processJSIncludes(this._jsIncludes);
      } catch (e) {
        q__restoreDocumentWrite();
        throw e;
      }
    } catch (e) {
      q__requestFinished(this);
      throw e;
    }

    var loc = request.getResponseHeader("Location");
    var expiredMessage = request.getResponseHeader("Ajax-Expired");

    if (!expiredMessage && this._sessionExpired) {
      expiredMessage = this._sessionExpired[0].value;
    }

    if (!loc && this._sessionExpiredLocation) {
      loc = this._sessionExpiredLocation[0].value;
    }


    if (expiredMessage) {
      this._mode = "Expiration-Handling";
      this._loc = loc;
      document.__sessionHasExpired = true;
      document.__sessionReloadLocation = loc;
    }

    this._processUpdatesWhenReady();


    document._q_page_is_already_initialized = null;
  }
  this._processUpdatesWhenReady = function() {
    try {
      var jsIncludes = this._jsIncludes;
      if (!q__areRequiredLibrariesLoaded(jsIncludes)) {
        setTimeout(q__getEventHandlerFunction("_processUpdatesWhenReady", null, this), 50);
        return;
      }
      //restore document.write() method to original. used in pair with q__substituteDocumentWrite() method.
      q__restoreDocumentWrite();

      this._processUpdates();
    } catch (e) {
      if (!this._clientSideExceptions) {
        q__requestFinished(this);
      }
      throw e;
    }

    if (!this._delayedSimpleUpdate)
      q__requestFinished(this);


    this._jsIncludes = undefined;
    this._updatables = undefined;
    this._styles = undefined;
    this._cssFiles = undefined;
    this._request = false;
  }

  this._processUpdates = function() {
    var updatables = this._updatables;
    if (!updatables || updatables.length == 0)
      return;
    var rtLibrary = undefined;

    // Cache state update part
    var updateStateId;
    var updateStateHTML;
    for (var i = 0; i < updatables.length; i++) {
      var upd = updatables[i];
      var updType = upd.tagName ? upd.getAttribute("type") : upd.type;

      if (updType == Q__UPDATE_TYPE_STATE) {
        var updId = upd.tagName ? upd.getAttribute("id") : upd.id;
        var updHTML = upd.tagName ? upd.getAttribute("value") : upd.value;
        if (q__isSafari()) {  //unescape ampersands for Safari
          updHTML = updHTML.replace(/&#38;/g, "&");
          updHTML = updHTML.replace(/&amp;/g, "&");
        }
        updateStateId = updId;
        updateStateHTML = updHTML;
        break;
      }
    }

    var simpleUpdate = false;
    for (var i = 0; i < updatables.length; i++) {
      var upd = updatables[i];
      var updType = upd.tagName ? upd.getAttribute("type") : upd.type;
      var updId = upd.tagName ? upd.getAttribute("id") : upd.id;
      var updHTML = upd.tagName ? upd.getAttribute("value") : upd.value;
      var updScripts = upd.tagName ? upd.getAttribute("scripts") : upd.scripts;
      var updData = upd.tagName ? upd.getAttribute("data") : upd.data;

      // runtime generated library with initialization scripts for all components presented on page
      if (updType == Q__UPDATE_TYPE_INITIALIZATION) {
        rtLibrary = updHTML;
      }
      if (q__isSafari()) {  //unescape ampersands for Safari
        updHTML = updHTML.replace(/&#38;/g, "&");
        updHTML = updHTML.replace(/&amp;/g, "&");
      }

      if (updType == Q__UPDATE_TYPE_SIMPLE) {
        if (this._mode == "Expiration-Handling") {
          this._processUpdateOnExpirationOrError(updId, updHTML, updScripts, updateStateHTML);
        } else {
          this._processSimpleUpdate(updId, updHTML, updScripts, updateStateHTML);
        }
        simpleUpdate = true;
      }
      else if (updType == Q__UPDATE_TYPE_PORTION) {
        if (this._mode == "Expiration-Handling") {
          this._processUpdateOnExpirationOrError(updId, updHTML, updScripts, updateStateHTML);
        } else {
          this._processPortionUpdate(updId, updHTML, updScripts, updData);
        }
      }
    }

    if (!simpleUpdate && updateStateHTML && !(this._mode == "Expiration-Handling")) {
      q__processStateUpdate(updateStateId, updateStateHTML)
    }

    if (rtLibrary) {
      q__processJSInclude(rtLibrary);
    }

    if (this._completionCallback)
      this._completionCallback(this._requestedComponentId);
  }

  this._processUpdateOnExpirationOrError = function (updId, updHTML, updScripts, updateStateHTML) {
    if (document.__sessionExpirationUpd) {
      return;
    }
    var tempDiv = document.createElement("div");
    tempDiv.innerHTML = updHTML;

    var newElements = [];
    for (var childIndex = 0, childCount = tempDiv.childNodes.length; childIndex < childCount; childIndex++) {
      var newElement = tempDiv.childNodes[childIndex];
      q__ajax_pushElementsWithId(newElements, newElement);
    }

    for (var childIndex = 0, childCount = newElements.length; childIndex < childCount; childIndex++) {
      var newElement = newElements[childIndex];
      q__assert(newElement.id, "_processSimpleUpdate: newElement without id encountered");
      var parent = document.body;
      parent.insertBefore(newElement, parent.lastChild);


      if (q__isOpera()) { // needed for Opera8.5 only (JSFC-1170)
        var oldClassName = parent.className;
        parent.className = parent.className + " _non_existing_class_name_q__123_";
        parent.className = oldClassName;
      }

    }

    //todo: insert runtime js library invokation with all initial scripts (instead of scripts passing to ajax response) here.
    //todo: replace q__executeScripts() method with runtime js library invokation
    q__executeScripts(updScripts);

    q__processStateUpdate(updId, updateStateHTML);

    if (q__isExplorer()) {
      if (document._ajaxCleanupRequired)
        q__destroyAllFunctions(tempDiv);
      tempDiv.innerHTML = "";
    }

    if (this._mode == "Expiration-Handling") {
      q__processSessionExpiration(this._loc, this._targetIds, this, false);
      q__requestFinished(this);
    }

    document.__sessionExpirationUpd = true;
  }
  this._processSimpleUpdate = function(updId, updHTML, updScripts, updateStateHTML) {

    var replacedElement = document.getElementById(updId);

    if (replacedElement.onComponentUnload) {
      var delayedUpdate = replacedElement.onComponentUnload();
      if (delayedUpdate) {
        replacedElement.onComponentUnload = null;
        var this_ = this;
        var delayedCompletionCallback = this._completionCallback;
        var delayedCompletionCallbackComponentId = this._requestedComponentId;
        var delayedSimpleUpdate = this._processSimpleUpdate;
        this._delayedSimpleUpdate = true;
        setTimeout(function () {
          delayedSimpleUpdate.apply(this_, [updId, updHTML, updScripts, updateStateHTML]);
          if (delayedCompletionCallback)
            delayedCompletionCallback(delayedCompletionCallbackComponentId);
          q__requestFinished(this);
        }, 1);
        this._completionCallback = null;
        return;
      }
    }

    var tempDiv = q__replaceDocumentElements(updHTML);

    //todo: insert runtime js library invokation with all initial scripts (instead of scripts passing to ajax response) here.
    //todo: replace q__executeScripts() method with runtime js library invokation
    q__executeScripts(updScripts);

    q__processStateUpdate(updId, updateStateHTML);

    if (q__isExplorer()) {
      if (document._ajaxCleanupRequired)
        q__destroyAllFunctions(tempDiv);
      tempDiv.innerHTML = "";
    }
  }

  this._processPortionUpdate = function(portionName, portionHTML, portionScripts, portionDataStr) {
    var componentId = this._targetIds;
    var component = document.getElementById(componentId);
    q__assert(component, "Couldn't find component by id: " + componentId);
    var portionData = portionDataStr ? eval("(" + portionDataStr + ")") : null;
    this._customProcessor(component, portionName, portionHTML, portionScripts, portionData);
  }

}

/*
  Replaces all elements in htmlPortion if they have an appropriate counterpart with the same Id in the document. All
  elements that couldn't be placed into the document (due to lack of id or a lack of an element with the same id in the
  document) are retained in the returned "div" element. The "div" element itself is just a temporary container and is
  not a part of HTML passed as a parameter.
 */
function q__replaceDocumentElements(htmlPortion, allowElementsWithNewIds) {
  var tempDiv = document.createElement("div");
  try {
    tempDiv.innerHTML = htmlPortion;
  } catch (e) {
    q__logError("q__replaceDocumentElements: couldn't set innerHTML for tempDiv. error message: " + e.message + "; htmlPortion: " + htmlPortion);
    throw e;
  }

  var newElements = [];
  for (var i = 0, count = tempDiv.childNodes.length; i < count; i++) {
    var el = tempDiv.childNodes[i];
    q__ajax_pushElementsWithId(newElements, el);
  }
  for (var childIndex = 0, childCount = newElements.length; childIndex < childCount; childIndex++) {
    var newElement = newElements[childIndex];
    q__assert(newElement.id, "_processSimpleUpdate: newElement without id encountered");
    var elementId = newElement.id;
    var oldElement = document.getElementById(elementId);
    if (!oldElement) {
      if (!allowElementsWithNewIds) {
        q__logError(oldElement, "Couldn't find component to replace: " + elementId);
      }
      continue;
    }
    var parent = oldElement.parentNode;

    if (q__isExplorer()) {
      if (typeof oldElement._cleanUp == "function") {
        oldElement._cleanUp();
      }
      if (document._ajaxCleanupRequired)
        q__destroyAllFunctions(oldElement);
    }

    parent.replaceChild(newElement, oldElement);

    if (q__isOpera()) { // needed for Opera8.5 only (JSFC-1170)
      var oldClassName = parent.className;
      parent.className = parent.className + " _non_existing_class_name_q__123_";
      parent.className = oldClassName;
    }

    oldElement = null;
  }
  return tempDiv;
}

function q__processSessionExpiration(loc, ajaxComponentIds, ajaxObject, isHandlingWasDelayed) {

  if (ajaxComponentIds) {
    if (ajaxComponentIds.every(function(element) {
      return !!QuipuKit.Ajax.Components[element];
    })
            && ajaxComponentIds.every(function(element) {
      return !!QuipuKit.Ajax.Components[ajaxComponentIds].onsessionexpired;
    })) {
      var sessionexpiredEvent = q__createEvent("sessionexpired");

      try {
        for (var i = 0; i < ajaxComponentIds.length; i++) {
          var ajaxComponentId = ajaxComponentIds[i];
          QuipuKit.Ajax.Components[ajaxComponentId].onsessionexpired(sessionexpiredEvent);
        }
      } catch(ex) {
        if (!isHandlingWasDelayed) {
          if (!ajaxObject._clientSideException) {
            ajaxObject._clientSideExceptions = new Array();
          }
          ajaxObject._clientSideExceptions.push(ex);
          return true;
        } else {
          document.q__ajax_request_processing = false;
          throw ex;
        }
      }

      return true;
    }
  }

  if (QuipuKit.Ajax.Page.onsessionexpired) {
    var sessionexpiredEvent = q__createEvent("sessionexpired");

    try {
      QuipuKit.Ajax.Page.onsessionexpired(sessionexpiredEvent);
    } catch(ex) {
      if (!isHandlingWasDelayed) {
        if (!ajaxObject._clientSideException) {
          ajaxObject._clientSideExceptions = new Array();
        }
        ajaxObject._clientSideExceptions.push(ex);

        return true;
      } else {
        document.q__ajax_request_processing = false;
        throw ex;
      }
    }

    return true;
  }

  return false;
}

function processErrorDuringAjaxRequest(errorMessage, ajaxComponentIds, ajaxObject) {
  if (ajaxComponentIds) {
    if (ajaxComponentIds.every(function(element) {
      return (QuipuKit.Ajax.Components[element]) ? true : false;
    })
            && ajaxComponentIds.every(function(element) {
      return (QuipuKit.Ajax.Components[ajaxComponentIds].onerror) ? true : false;
    })) {
      var errorEvent = q__createEvent("error");
      var result = false;
      try {
        var result = true;
        for (var i = 0; i < ajaxComponentIds.length; i++) {
          var ajaxComponentId = ajaxComponentIds[i];
          result = result & QuipuKit.Ajax.Components[ajaxComponentId].onerror(errorEvent);
        }
      } catch(ex) {
        if (!ajaxObject._clientSideException) {
          ajaxObject._clientSideExceptions = new Array();
        }
        ajaxObject._clientSideExceptions.push(ex);
        q__requestFinished(ajaxObject);
        return;
      }

      if (result != false) {
        q__showDefaultAlertAfterException(errorMessage, ajaxObject);
      }
      return;
    }
  }

  if (QuipuKit.Ajax.Page.onerror) {
    var errorEvent = q__createEvent("error");
    var onerrorResult = false;
    try {
      onerrorResult = QuipuKit.Ajax.Page.onerror(errorEvent);
    } catch(ex) {
      if (!ajaxObject._clientSideException) {
        ajaxObject._clientSideExceptions = new Array();
      }
      ajaxObject._clientSideExceptions.push(ex);
      q__requestFinished(ajaxObject);
      return;
    }

    if (onerrorResult != false) {
      q__showDefaultAlertAfterException(errorMessage, ajaxObject);
    }
    return;
  }

  q__showDefaultAlertAfterException(errorMessage, ajaxObject);
}

function q__processStateUpdate(updId, updHTML) {
  if (!updHTML) return;

  var updatedElement = document.getElementById(updId);

  var prnt = updatedElement.parentNode;
  var tempDiv = document.createElement("div");
  tempDiv.id = "stateUpdateDiv";
  tempDiv.innerHTML = updHTML;

  var stateField = tempDiv.childNodes[0];
  q__assert(stateField, "No state field found in updateable");
  q__assert(tempDiv.childNodes.length == 1, "There should be only one element in the state field array");
  var stateFieldId = stateField.id;
  var stateOnPage = document.getElementById(stateFieldId);
  if (stateOnPage)
  {
    stateOnPage.parentNode.replaceChild(stateField, stateOnPage);
    stateOnPage.innerHTML = "";
  }
  else
  {
    // Try to add hidden field into updated element
    var tagName = updatedElement.tagName.toUpperCase();
    if (tagName == "TABLE")
    {
      var firstTD = q__getFirstChildWithName(updatedElement, "TD");
      firstTD.appendChild(stateField);
    }
    else if (updatedElement.childNodes) // check that element already has children to filter one tag elements
    {
      updatedElement.appendChild(stateField);
    }
    else
    {
      prnt.appendChild(stateField);
    }
  }
  tempDiv.innerHTML = "";
}

function q__getFirstChildWithName(node, tagName) {
  tagName = tagName.toUpperCase();
  var children = node.childNodes;
  for (var i = 0; i < children.length; i++)
  {
    var childrenTagName = children[i].tagName;
    if (childrenTagName && tagName == childrenTagName.toUpperCase()) {
      return children[i];
    }
    var deepResult = q__getFirstChildWithName(children[i], tagName);
    if (deepResult)
    {
      return deepResult;
    }
  }

  return null;
}

var q__lastAjaxId = 0;

function q__ajax_pushElementsWithId(destElements, element) {
  if (!element)
    return;
  if (element.id) {
    destElements.push(element);
    return;
  }

  for (var childIndex = 0, childCount = element.childNodes.length; childIndex < childCount; childIndex++) {
    var subElement = element.childNodes[childIndex];
    q__ajax_pushElementsWithId(destElements, subElement);
  }

}

function q__findStateField(node) {
  var children = node.childNodes;
  for (var i = 0, count = children.length; i < count; i++) {
    var child = children[i];
    if (q__isStateField(child))
      return child;
  }
  return null;
}

function q__isStateField(element) {
  if (!element || !element.id)
    return false;
  return q__stringEndsWith(element.id, "::_state")
}

function q__processJSIncludes(jsIncludes) {
  if (jsIncludes) {
    for (var i = 0; i < jsIncludes.length; i++) {
      var jsIncludeElement = jsIncludes[i];
      var include = jsIncludeElement.tagName ? jsIncludeElement.getAttribute("value") : jsIncludeElement.value;
      q__processJSInclude(include);
    }
  }
}

function q__processJSInclude(jsInclude) {
  var found = q__isLibraryLoaded(jsInclude);
  if (!found) {
    var newScript = document.createElement("script");
    newScript.type = "text/javascript";
    newScript.src = jsInclude;
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(newScript);
  }
}
function q__processCSSFilesIncludes(cssFiles) {
  if (!cssFiles)
    return;
  var head = document.getElementsByTagName("head")[0];
  for (var i = 0; i < cssFiles.length; i++) {
    var cssFileElement = cssFiles[i];
    var cssFile = cssFileElement.tagName ? cssFileElement.getAttribute("value") : cssFileElement.value;
    var newCSSFile = document.createElement("link");
    newCSSFile.type = "text/css";
    newCSSFile.href = cssFile;
    newCSSFile.rel = "stylesheet";
    head.appendChild(newCSSFile);
  }
}

function q__processStylesIncludes(styles) {
  if (!styles)
    return;

  for (var i = 0; i < styles.length; i++) {
    var styleElement = styles[i];
    var rule = styleElement.tagName ? styleElement.getAttribute("value") : styleElement.value;
    q__addCssRule(rule);
  }
}

function q__executeScripts(source) { // should not be invoked because all init scripts are moved to runtime generated js library (as for now) // todo: review -- is this really so currently?
  if (!source || source.length == 0) return;
  var idx1 = source.indexOf("<script");
  var result;
  if (idx1 > -1) {
    result = source.substring(idx1);
    idx1 = result.indexOf(">");
    idx1 += 1;

    var idx2 = result.indexOf("</script>");
    var script = result.substring(idx1, idx2);
    script = script.replace(/<!--/g, "");
    script = script.replace(/\/\/-->/g, "");
    try {
      window.eval(script);
    } catch (e) {
      alert("Couldn't execute script on Ajax request: \n" + script);
      throw e;
    }
    idx2 += "</script>".length;
    result = result.substring(idx2);
    q__executeScripts(result);
  }
}

function q__prepareUpdates(buf, componentId, portionName) {
  if (!portionName || portionName.length <= 0) return false;

  buf.append(Q__UPDATE_PORTIONS_SUFFIX).append("=");
  for (var i = 0, count = portionName.length; i < count; i++) {
    buf.append(q__escapeSymbol(portionName[i], [","]));
    if (i < count - 1) {
      buf.append(",");
    }
  }
  return true;
}

function q__escapeSymbol(portionName, param) {
  var res = new q__StringBuffer();
  for (var i = 0, count = portionName.length; i < count; i++) {
    var temp = portionName.charAt(i);
    if (temp == "\\") {
      res.append("\\");
    } else {
      var index = q__findValueInArray(temp, param);
      if (index != -1) {
        var fullCharCode = new String(param[index].charCodeAt() + 10000);
        res.append("\\" + fullCharCode.substr(1, fullCharCode.length));
        continue;
      }
    }
    res.append(temp);
  }
  return res.toString();
}

function q__prepareFormParams(form, buf) {
  var elements = form.elements;
  for (var i = 0, count = elements.length; i < count; i++) {
    var element = elements[i];
    var elementName = element.name;
    if (!elementName)
      continue;
    var elementType = element.type;
    if (elementType)
      elementType = elementType.toLowerCase();
    if (!elementType || elementType == "image" || elementType == "button" || elementType == "submit")
      continue;

    if (elementType == "checkbox" || elementType == "radio") {
      if (!element.checked)
        continue;
    }

    var paramName = encodeURIComponent(elementName);
    var paramValue = encodeURIComponent(element.value);
    buf.append(paramName).append("=").append(paramValue);
    if (i < count - 1) {
      buf.append("&");
    }
  }
}

function q__areRequiredLibrariesLoaded(libs) {
  if (!libs) return true;
  for (var i = 0; i < libs.length; i++) {
    var libElement = libs[i];
    var lib = libElement.tagName ? libElement.getAttribute("value") : libElement.value;
    var loaded = q__isLibraryLoaded(lib);
    if (!loaded) return false;
  }
  return true;
}

function q__isLibraryLoaded(lib) {
  var result = eval("window['q_loadedLibrary:" + lib + "']");
  return result;
}

function q__validationErrorDuringProcessing(request) {
  if (!request)
    return true;
  if (request.responseText && request.responseText.indexOf("validation error") > -1)
    return true;
  return false;
}

function q__substituteDocumentWrite() {
  document._oldWrite = document.write;
  document._tempAjaxStr = "";
  document.write = function(str) {
    document._tempAjaxStr += str;
  };
}

function q__restoreDocumentWrite(placeHolderId) {
  if (document._tempAjaxStr.length > 0) {
    var div = document.createElement("div");
    div.innerHTML = document._tempAjaxStr;
    var childNodes = div.childNodes;
    var i;
    if (!placeHolderId) {
      for (i = 0; i < childNodes.length; i++) {
        document.body.appendChild(childNodes[i]);
      }
    } else {
      var placeholderEl = document.getElementById(placeHolderId);
      if (placeholderEl) {
        var parentEl = placeholderEl.parentNode;
        for (i = 0; i < childNodes.length; i++) {
          parentEl.insertBefore(childNodes[i], placeholderEl);
        }
        parentEl.removeChild(placeholderEl);
      }
    }
  }
  document.write = document._oldWrite;
  document._tempAjaxStr = undefined;
}

function q__updateViewStateSequenceForMyFaces(viewStateSequence) {
  for (var facesViewStateFieldIndex = 0; facesViewStateFieldIndex < document.getElementsByName('javax.faces.ViewState').length; facesViewStateFieldIndex++) {
    if (document.getElementsByName('javax.faces.ViewState')[facesViewStateFieldIndex]) {
      document.getElementsByName('javax.faces.ViewState')[facesViewStateFieldIndex].value = viewStateSequence;
    }
  }
}

function q_updateOrCreateMyFacesStateFields(stateId, viewId) {
  for (var jsfTreeIndex = 0; jsfTreeIndex < document.forms.length; jsfTreeIndex++) {
    if (document.getElementsByName('jsf_tree')[jsfTreeIndex]) {
      document.getElementsByName('jsf_tree')[jsfTreeIndex].value = stateId;
    }
  }

  for (var jsfViewIdIndex = 0; jsfViewIdIndex < document.forms.length; jsfViewIdIndex++) {
    if (document.getElementsByName('jsf_viewid')[jsfViewIdIndex]) {
      document.getElementsByName('jsf_viewid')[jsfViewIdIndex].value = viewId;
    }
  }

  var formsCount = document.forms.length;
  var jsfTreeHiddenFieldCount = document.getElementsByName('jsf_tree').length;
  var jsfViewIdHiddenFieldCount = document.getElementsByName('jsf_viewid').length;

  if (jsfTreeHiddenFieldCount < formsCount && jsfViewIdHiddenFieldCount < formsCount) {
    for (var fieldIndex = 0; fieldIndex < document.forms.length; fieldIndex++) {
      var jsfTreeHiddenField = document.createElement("input");
      jsfTreeHiddenField.id = "jsf_tree";
      jsfTreeHiddenField.name = "jsf_tree";
      jsfTreeHiddenField.type = "hidden";
      jsfTreeHiddenField.value = stateId;

      document.forms[fieldIndex].insertBefore(jsfTreeHiddenField, document.forms[fieldIndex].lastChild);

      var jsfViewIdHiddenField = document.createElement("input");
      jsfViewIdHiddenField.id = "jsf_viewid";
      jsfViewIdHiddenField.name = "jsf_viewid";
      jsfViewIdHiddenField.type = "hidden";
      jsfViewIdHiddenField.value = viewId;

      document.forms[fieldIndex].insertBefore(jsfViewIdHiddenField, document.forms[fieldIndex].lastChild);
    }
  }
}

function q__updateJsfSequenceForMyFaces(jsfSequence) {
  for (var jsfSequenceIndex = 0; jsfSequenceIndex < document.getElementsByName('jsf_sequence').length; jsfSequenceIndex++) {
    if (document.getElementsByName('jsf_sequence')[jsfSequenceIndex]) {
      document.getElementsByName('jsf_sequence')[jsfSequenceIndex].value = jsfSequence;
    }
  }
}

function q__updateViewIdForRI(viewId) {
  if (document.getElementById('com.sun.faces.VIEW')) {
    // JSF RI 1.1
    for (var sunFacesViewFieldIndex = 0; sunFacesViewFieldIndex < document.getElementsByName('com.sun.faces.VIEW').length; sunFacesViewFieldIndex++) {
      if (document.getElementsByName('com.sun.faces.VIEW')[sunFacesViewFieldIndex]) {
        document.getElementsByName('com.sun.faces.VIEW')[sunFacesViewFieldIndex].value = viewId;
      }
    }
  }
  else {
    // JSF RI 1.2
    if (document.getElementsByName('javax.faces.ViewState')) {
      for (var facesViewStateFieldIndex = 0; facesViewStateFieldIndex < document.getElementsByName('javax.faces.ViewState').length; facesViewStateFieldIndex++) {
        if (document.getElementsByName('javax.faces.ViewState')[facesViewStateFieldIndex]) {
          document.getElementsByName('javax.faces.ViewState')[facesViewStateFieldIndex].value = viewId;
        }
      }
    }
  }
}

function q__showDefaultAlertAfterException(errorMessage, ajaxObject) {
  alert("An error occured on the server.\nError message:\n\"" + errorMessage + "\".\nPlease see server logs for full stacktrace.");
  q__requestFinished(ajaxObject);
}
function q__destroyAllFunctions(elt) {
  if (!elt || elt.nodeName == "#text")
    return;

  var elementId = elt.id;

  // Break the potential circular references
  for (var member in elt) {
    if (member.indexOf("_") != 0 && member.indexOf("on") != 0)
      continue;
    if (!elt[member])
      continue;
    if (elementId && (typeof elt[member] === "function"))
      (function() {
        var e = document.getElementById(elementId);
        e[member] = null;
      })();
    else
      elt[member] = null;
  }

  var attachedEvents = document.__attachedEvents;
  if (elementId && attachedEvents) {
    var allAttachedEvents = attachedEvents[elementId];
    if (allAttachedEvents) {
      for (var eventsIndex = 0, eventCount = allAttachedEvents.length; eventsIndex < eventCount; eventsIndex++) {
        var eventObject = allAttachedEvents[eventsIndex];
        q__removeEventHandler(elt, eventObject.eventName, eventObject.functionScript);
      }
      attachedEvents[elementId] = null;
    }
  }

  var childNodes = elt.childNodes;
  if (childNodes) {
    var length = childNodes.length;
    for (var index = 0; index < length; index++) {
      q__destroyAllFunctions(childNodes[index]);
    }
  }
}

//AUTO GENERATED CODE

window['q_loadedLibrary:/qk_internalResource/teamdev/jsf/renderkit/util/ajaxUtil-2.0.js'] = true;