/*
 * Copyright (c) 1998-2009 TeamDev Ltd. All Rights Reserved.
 * Use is subject to license terms.
 */

// ----------------- DEBUG ---------------------------------------------------
var Q__DEBUG = true;

function q__logError(message) {
  if (Q__DEBUG)
    alert("ERROR: " + message);
}

function q__logWarning(message) {
  //  if (Q__DEBUG)
  //    alert("WARNING: " + message);
}


function q__assert(value, message) {
  if (value != null && value != undefined && value !== false)
    return;
  q__logError(message);
}


function q__log(text) {
  if (!window._logger)
    window._logger = new q__Logger();
  window._logger.log(text);
}

function q__Logger() {
  var div = document.createElement("div");
  div.style.position = "absolute";
  div.style.left = "200px";
  div.style.top = "400px";
  div.style.width = "700px";
  div.style.height = "200px";
  div.style.overflow = "auto";
  div.style.background = "white";
  div.style.border = "2px solid black";
  document.body.appendChild(div);

  if (!document._q_loggersCreated)
    document._q_loggersCreated = 1;
  else
    document._q_loggersCreated++;
  div.id = "_q_logger_" + document._q_loggersCreated;
//  q__initPopupLayer(div.id, 100, 100, 700, 200, null, null, true);

  this._div = div;
  //  this._win = window.open("about:blank", "q__logger");
  this.log = function (text) {
    var date = new Date();
    //    this._win.document.write(date + " : " + text + "<br>");
    this._div.innerHTML = date + " : " + text + "<br>" + this._div.innerHTML;
  }
}

function q__Profiler() {
  this._timeStamps = new Array();
  this._timeAccumulators = new Array();

  this.logTimeStamp = function(name) {
    this._timeStamps.push({time: new Date(), name: name});
  }

  this.startMeasuring = function(name) {
    var timeAccumulator = this._timeAccumulators[name];
    if (timeAccumulator == null) {
      timeAccumulator = {name: name, secondsElapsed: 0.0, lastPeriodStartDate: null};
      this._timeAccumulators[name] = timeAccumulator;
      this._timeAccumulators.push(timeAccumulator);
    }
    q__assert(!timeAccumulator.lastPeriodStartDate, "q__Profiler.startMeasuring cannot be called twice for the same name without endMeasuring being called: " + name);
    timeAccumulator.lastPeriodStartDate = new Date();
  }

  this.endMeasuring = function(name) {
    var dateAfter = new Date();
    var timeAccumulator = this._timeAccumulators[name];
    q__assert(timeAccumulator, "q__Profiler.endMeasuring: startMeasuring wasn't called for name: " + name);
    q__assert(timeAccumulator.lastPeriodStartDate, "q__Profiler.endMeasuring: startMeasuring wasn't called for name: " + name);
    var dateBefore = timeAccumulator.lastPeriodStartDate;
    timeAccumulator.lastPeriodStartDate = null;
    var secondsElapsed = (dateAfter.getTime() - dateBefore.getTime()) / 1000;
    timeAccumulator.secondsElapsed += secondsElapsed;
  }

  this.showTimeStamps = function() {
    var result = "";
    for (var i = 0, count = this._timeStamps.length - 1; i < count; i++) {
      var stampBefore = this._timeStamps[i];
      var stampAfter = this._timeStamps[i + 1];
      var elapsed = (stampAfter.time.getTime() - stampBefore.time.getTime()) / 1000;
      result += stampBefore.name + " - " + stampAfter.name + " : " + elapsed + "\n";
    }
    alert(result);
  }

  this.showTimeMeasurements = function() {
    var result = "";
    for (var i = 0, count = this._timeAccumulators.length; i < count; i++) {
      var accumulator = this._timeAccumulators[i];
      var name = accumulator.name;
      var elapsed = accumulator.secondsElapsed;
      result += name + " : " + elapsed + "\n";
    }
    alert(result);
  }

  this.showAllTimings = function() {
    var result = "--- Time-stamps: --- \n\n";
    for (var i = 0, count = this._timeStamps.length - 1; i < count; i++) {
      var stampBefore = this._timeStamps[i];
      var stampAfter = this._timeStamps[i + 1];
      var elapsed = (stampAfter.time.getTime() - stampBefore.time.getTime()) / 1000;
      result += stampBefore.name + " - " + stampAfter.name + " : " + elapsed + "\n";
    }
    result += "\n--- Time measurements: --- \n\n";
    for (var i = 0, count = this._timeAccumulators.length; i < count; i++) {
      var accumulator = this._timeAccumulators[i];
      var name = accumulator.name;
      var elapsed = accumulator.secondsElapsed;
      result += name + " : " + elapsed + "\n";
    }
    alert(result);
  }

}

// ----------------- STRING, ARRAYS, OTHER LANGUAGE UTILITIES ---------------------------------------------------

function q__stringsEqualIgnoreCase(str1, str2) {
  if (str1)
    str1 = str1.toLowerCase();
  if (str2)
    str2 = str2.toLowerCase();
  return str1 == str2;
}

function q__StringBuffer() {
  this._strings = [];
  this.append = function(value) {
    this._strings.push(value);
    return this;
  }
  this.toString = function() {
    return this._strings.join("");
  }
  this.getNextIndex = function() {
    return this._strings.length;
  }
  this.setValueAtIndex = function(index, value) {
    this._strings[index] = value;
  }
}

function q__ltrim(value) {
  var re = /\s*((\S+\s*)*)/;
  return value.replace(re, "$1");
}

function q__rtrim(value) {
  var re = /((\s*\S+)*)\s*/;
  return value.replace(re, "$1");
}

function q__trim(value) {
  return q__ltrim(q__rtrim(value));
}

function q__stringEndsWith(str, ending) {
  if (!str || !ending)
    return false;
  var endingLength = ending.length;
  var length = str.length;
  if (length < endingLength)
    return false;
  var actualEnding = str.substring(length - endingLength, length);
  return actualEnding == ending;
}

function q__stringStartsWith(str, text) {
  if (!str || !text)
    return false;
  var textLength = text.length;
  var length = str.length;
  if (length < textLength)
    return false;
  var actualStartText = str.substring(0, textLength);
  return actualStartText == text;
}

function q__findValueInArray(value, arr) {
  for (var i = 0, count = arr.length; i < count; i++) {
    var obj = arr[i];
    if (obj == value)
      return i;
  }
  return -1;
}

function q__getArrayFromString(str, delimiter) {
  var idx = str.indexOf(delimiter);
  var arr = new Array();
  var arrIdx = 0;
  while (idx != -1) {
    arr[arrIdx++] = str.substring(0, idx);
    str = str.substring(idx + 1);
    idx = str.indexOf(delimiter);
  }
  arr[arrIdx] = str;
  return arr;
}

function q__arrayContainsValue(array, value) {
  var idx = q__findValueInArray(value, array);
  return idx != -1;
}

function q__unescapeHtml(val) {
  var re = /\&\#(\d+)\;/
  while (re.test(val)) {
    val = val.replace(re, String.fromCharCode(RegExp.$1));
  }
  return val;
}

// ----------------- BROWSER DETECTION ---------------------------------------------------

function q__userAgentContains(browserName) {
  return navigator.userAgent.toLowerCase().indexOf(browserName.toLowerCase()) > -1;
}

function q__isStrictMode() {
  return document.compatMode == "CSS1Compat"
}

function q__isMozilla() { // todo: returns true under Safari 3 (its userAgent value is "navigator.userAgent = Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/523.15 (KHTML, like Gecko) Version/3.0 Safari/523.15")
  if (window._q_mozilla == undefined)
    window._q_mozilla = q__userAgentContains("mozilla") && !q__userAgentContains("msie");
  return window._q_mozilla;
}

function q__isMozillaFF() {
  return q__isMozilla() && !q__isSafari();
}


function q__isMozillaFF3() {
  return q__isMozillaFF() && q__userAgentContains("Firefox/3.0");
}

function q__isExplorer() {
  if (window._q_explorer == undefined)
    window._q_explorer = q__userAgentContains("msie") && !q__userAgentContains("opera");
  return window._q_explorer;
}

function q__isExplorer6() {
  return q__isExplorer() && !q__isExplorer7();
}

function q__isExplorer7() {
  if (window._q_explorer7 == undefined)
    window._q_explorer7 = q__isExplorer() && q__userAgentContains("MSIE 7");
  return window._q_explorer7;
}

function q__isOpera9AndLate() {
  if (window._q_opera9 == undefined) {
    if (q__isOpera()) {
      window._q_opera9 = /\bOpera(\s|\/)(\d{2,}|([9]){1})/i.test(navigator.userAgent);
    }
  }
  return window._q_opera9;
}

function q__isSafari3AndLate() {
  if (window._q_safari3 == undefined)
    if (q__isSafari()) {
     window._q_safari3 = /\bversion(\s|\/)(\d{2,}|[3-9]{1})/i.test(navigator.userAgent);
    }
  return window._q_safari3;
}

function q__isSafariOnMac() {
  if (window._q_safariOnMac == undefined) {
    window._q_safariOnMac = q__isSafari() && q__userAgentContains("Macintosh");
  }
  return window._q_safariOnMac;
}

function q__isSafariOnWindows() {
  if (window._q_safariOnWindows == undefined) {
    window._q_safariOnWindows = q__isSafari() && q__userAgentContains("Windows");
  }
  return window._q_safariOnWindows;
}

function q__isSafari2() {
  if (window._q_safari2 == undefined)
    if (q__isSafari()) {
       window._q_safari2 = !q__isSafari3AndLate()
    }
  return window._q_safari2;
}

function q__isOpera() {
  if (window._q_opera == undefined)
    window._q_opera = q__userAgentContains("opera");
  return window._q_opera;
}

function q__isSafari() {
  if (window._q_safari == undefined)
    window._q_safari = q__userAgentContains("safari");
  return window._q_safari;
}

// ----------------- DOM FUNCTIONS ---------------------------------------------------

function q__getControl(id) {
  return document.getElementById(id);
}

function q__findParentNode(element, tagName) {
  tagName = tagName.toUpperCase();
  while (element) {
    var elementNodeName = element.nodeName;
    if (elementNodeName)
      elementNodeName = elementNodeName.toUpperCase();
    if (elementNodeName == tagName)
      break;
    element = element.parentNode;
  }
  if (element != null)
    return element;
  else
    return null;
}

function q__findAnyParentNode(element, tagNames) {
  for (var i = 0, count = tagNames.length; i < count; i++)
    tagNames[i] = tagNames[i].toUpperCase();
  while (element && q__findValueInArray(element.nodeName.toUpperCase(), tagNames) == -1)
    element = element.parentNode;
  if (element != null)
    return element;
  else
    return null;
}

function q__getElement(identifier) {
  var element = document.getElementById(identifier);
  if (element)
    return element;

  var elementCollection = document.getElementsByName(identifier);
  if (elementCollection)
    return elementCollection[0];

  return null;
}

function q__isChild(parent, child) {
  if (parent.id && child.id && parent.id == child.id) return true;
  if (child.parentNode && child.parentNode.nodeName && child.parentNode.nodeName.toUpperCase() != "BODY") {
    return q__isChild(parent, child.parentNode);
  }
  return false;
}

function q__findChildNodesByClass(node, className, searchTopLevelOnly) {
  var result = new Array();
  var children = node.childNodes;
  for (var i = 0, count = children.length; i < count; i++) {
    var child = children[i];
    if (child.className == className)
      result.push(child);
    //    var childClass = child.className;
    //    var childClassNames = childClass ? childClass.split(" ") : new Array();
    //    if (childClassNames.q__indexOf(className))
    var subResult = !searchTopLevelOnly && q__findChildNodesByClass(child, className);
    for (var childIndex = 0, subResultCount = subResult.length; childIndex < subResultCount; childIndex++) {
      var innerResult = subResult[childIndex];
      result.push(innerResult);
    }
  }
  return result;
}

function q__getChildNodesWithNames(node, nodeNames) {
  var selectedChildren = new Array();
  var children = node.childNodes;
  for (var i = 0, count = children.length; i < count; i++) {
    var child = children[i];
    var childNodeName = child.nodeName;
    if (childNodeName)
      childNodeName = childNodeName.toLowerCase();
    for (var j = 0, jcount = nodeNames.length; j < jcount; j++) {
      var nodeName = nodeNames[j];
      nodeName = nodeName.toLowerCase();
      if (childNodeName == nodeName)
        selectedChildren.push(child);
    }
  }
  return selectedChildren;
}

function q__findElementByPath(node, childPath, ignoreNonExistingElements) {
  var separatorIndex = childPath.indexOf("/");
  var locator = separatorIndex == -1 ? childPath : childPath.substring(0, separatorIndex);
  var remainingPath = separatorIndex != -1 ? childPath.substring(separatorIndex + 1) : null;

  var bracketIndex = locator.indexOf("[");
  var childElementName = bracketIndex == -1 ? locator : locator.substring(0, bracketIndex);
  var childElementIndex;
  if (bracketIndex == -1) {
    childElementIndex = 0;
  } else {
    q__assert(q__stringEndsWith(locator, "]"), "q__findElementByPath: unparsable element locator - non-matching brackets: " + childPath);
    var indexStr = locator.substring(bracketIndex + 1, locator.length - 1);
    try {
      childElementIndex = parseInt(indexStr);
    } catch (e) {
      if (ignoreNonExistingElements)
        return null;
      throw "q__findElementByPath: Couldn't parse child index (" + indexStr + "); childPath = " + childPath;
    }
  }
  var childrenByName = q__getChildNodesWithNames(node, [childElementName]);
  if (childrenByName.length == 0) {
    if (ignoreNonExistingElements)
      return null;
    throw "q__findElementByPath: Couldn't find child nodes by element name: " + childElementName + " ; childPath = " + childPath;
  }
  var child = childrenByName[childElementIndex];
  if (!child) {
    if (ignoreNonExistingElements)
      return null;
    throw "q__findElementByPath: Child not found by index: " + childElementIndex + " ; childPath = " + childPath;
  }
  if (remainingPath == null)
    return child;
  else
    return q__findElementByPath(child, remainingPath);
}

function q__isElementPresentInDocument(element) {
  var result = false;
  if (element == document) {
    return true;
  }
  if (element.parentNode != null) {
    result = q__isElementPresentInDocument(element.parentNode);
  }
  return result;
}

// ----------------- FORM, FORM ELEMENTS MANIPULATION ---------------------------------------------------

function q__submitEnclosingForm(element) {
  q__assert(element, "element should be passed to q__submitEnclosingForm");
  var frm = q__findParentNode(element, "FORM");
  q__assert(frm, "q__submitEnclosingForm: Enclosing form not found for element with id: " + element.id + "; element tag name: " + element.tagName);
  if (frm.onsubmit)
    if (!frm.onsubmit())
      return;

  frm.submit();
}

function q__submitEnclosingElementsForm(elements) {
  q__assert(elements[0], "elements should be passed to q__submitEnclosingElementsForm");
  var frm = q__findParentNode(elements[0], "FORM");
  if (!elements.every(function(element) {return (frm == q__findParentNode(element, "FORM"));})) {
    q__logError("q__submitEnclosingElementsForm: Enclosing forms differ for components");
  }
  q__assert(frm, "q__submitEnclosingElementsForm: Enclosing form not found for elements");
  if (frm.onsubmit)
    if (!frm.onsubmit())
      return;

  frm.submit();
}

function q__submitFormWithAdditionalParam(element, paramName, paramValue) {
  q__assert(element, "element should be passed to q__submitFormWithAdditionalParam");
  q__assert(paramName, "paramName should be passed to q__submitFormWithAdditionalParam");
  q__addHiddenField(element, paramName, paramValue);
  var frm = q__findParentNode(element, "FORM");
  frm.submit();
}

function q__addHiddenField(element, fieldName, fieldValue) {
  var frm;
  if (!element) {
    frm = document.forms[0];
    q__assert(frm, "q__addHiddenField: There must be a form in the document");
  } else {
    frm = q__findParentNode(element, "FORM");
    q__assert(frm, "q__addHiddenField: Enclosing form not found for element with id: " + element.id + "; element tag name: " + element.tagName);
  }
  var existingField = document.getElementById(fieldName);
  var newParamField = existingField ? existingField : document.createElement("input");
  if (!existingField) {
    newParamField.type = "hidden";
    newParamField.id = fieldName;
    newParamField.name = fieldName;
    frm.appendChild(newParamField);
  }
  if (!fieldValue)
    fieldValue = "";
  newParamField.value = fieldValue;
  return newParamField;
}

function q__submitById(elementId) {
  var element = document.getElementById(elementId);
  q__assert(element, "correct element id should be passed to q__submitById");
  q__submitEnclosingForm(element);
}

function q__submitByIds(elementIds) {
    var elements = new Array();
    for (var i = 0, count = elementIds.length; i < count; i++) {
      elements[elements.length] = document.getElementById(elementIds[i]);
      q__assert(elements[elements.length - 1], "correct element id should be passed to q__submitByIds");
    }
    q__submitEnclosingElementsForm(elements);
}

function q__setValue(elementId, value) {
  var field = document.getElementById(elementId);
  q__assert(field, "Correct element id should be passed to q__setValue; elementId = " + elementId);
  if (field) {
    field.value = value;
  }
}

q__addLoadEvent(function() {
  var forms = document.forms;
  for (var i = 0, count = document.forms.length; i < count; i++) {
    var frm = document.forms[i];
    q__addEventHandler(frm, "submit", function() {
      if (!this.target || this.target != "_blank") {
        document._q_formSubmissionJustStarted = true;
        // _q_formSubmissionJustStarted should be reset so as not to block further ajax actions if this is not actually
        // a normal form submission, but file download (JSFC-2940)
        setTimeout(function(){document._q_formSubmissionJustStarted = false;}, 100);
      }
    });
    if (frm._q_prevSubmit) continue;
    frm._q_prevSubmit = frm.submit;
    frm.submit = function() {
      if (!this.target || this.target != "_blank") {
        document._q_formSubmissionJustStarted = true;
        setTimeout(function(){document._q_formSubmissionJustStarted = false;}, 100);
      }
      this._q_prevSubmit();
    }
  }

});

//{
//  var submitElement = null;
//  submitElement = document.getElementById("submit");
//  if (submitElement == null) {
//    for (var i = 0, count = document.forms.length; i < count; i++) {
//      submitElement = document.forms.getElementsByName("submit");
//      if (submitElement)
//        break;
//    }
//  }
//  if (submitElement) {
//    q__logError("The document contains an element with id or name equal to \"submit\". Please use different id/name in order to avoid collision with form.submit() method");
//  }
//}
//
function q__isFormSubmissionJustStated() {
  return document._q_formSubmissionJustStarted;
}

// ----------------- EVENT UTILITIES ---------------------------------------------------

function q__getEventHandlerFunction(handlerName, handlerArgs, mainObj) {
  var handlerFunction;

  if (!q__getEventHandlerFunction.apply) {
    eval('handlerFunction = function() { return arguments.callee.prototype._ownObj.' + handlerName + '(' + (handlerArgs ? handlerArgs : '') + '); }');
  } else {
    var argString = handlerArgs ? ('[' + handlerArgs + ']') : 'arguments';
    eval('handlerFunction = function() { return arguments.callee.prototype._ownObj.' + handlerName + '.apply(arguments.callee.prototype._ownObj,' + argString + '); }');
  }
  handlerFunction.prototype._ownObj = mainObj;
  return handlerFunction;
}

function q__addEvent(componentCilentId, eventName, functionScript) {
  if (!document.__attachedEvents) {
    document.__attachedEvents = new Array();
  }

  var element = q__getElement(componentCilentId);
  if (element) {
    q__addEventHandler(element, eventName, functionScript);
  }

  var eventToDetach = new Object();
  eventToDetach.componentClientId = componentCilentId;
  eventToDetach.eventName = eventName;
  eventToDetach.functionScript = functionScript;

  if (!document.__attachedEvents[componentCilentId]) {
    document.__attachedEvents[componentCilentId] = new Array();
  }

  var componentAttachedEvents = document.__attachedEvents[componentCilentId];
  componentAttachedEvents.push(eventToDetach);
  document.__attachedEvents[componentCilentId] = componentAttachedEvents;
}

function q__addEventHandler(elt, evtName, evtScript, useCapture) {
  if (elt.addEventListener) {
    elt.addEventListener(evtName, evtScript, !!useCapture);
  } else if (elt.attachEvent) {
    elt.attachEvent("on" + evtName, evtScript);
  }
}

function q__removeEventHandler(elt, evtName, evtScript, useCapture) {
  if (elt.addEventListener) {
    elt.removeEventListener(evtName, evtScript, !!useCapture);
  } else if (elt.attachEvent) {
    elt.detachEvent("on" + evtName, evtScript);
  }
}

/* Use this function instead of direct field assignment to work around Mozilla problems firing old events when
   new page is loading (JSFC-2276) */
function q__assignEventHandlerField(element, fieldName, handler) {
  element[fieldName] = handler;
  if (q__isMozilla()) {
    q__addUnloadEvent(function() {
      element[fieldName] = null;
    })
  }
}

function q__repeatClickOnDblclick(e) {
    if (q__isExplorer()) this.onclick(e);
  }

q__invokeOnce(q__initDocumentMouseClickListeners, "q__initDocumentMouseClickListeners");

function q__initDocumentMouseClickListeners() {
  if (document._q__initDocumentMouseClickListeners_called) {
    return;
  }

  if (!document._mouseClickListeners) {
    document._mouseClickListeners = new Array();
  }
  document._addClickListener = function (listener) {
    if (listener) {
      this._mouseClickListeners.push(listener);
    }
  };
  q__addEventHandler(document, "mousedown", function (event) {
    for (var i = 0; i < document._mouseClickListeners.length; i++) {
      document._mouseClickListeners[i](event);
    }
  });

  document._q__initDocumentMouseClickListeners_called = true;
}

/*
 * The last "receiverThisRef" parameter can be omitted if it's acceptable that "this" variable in the
 * event handler refer to eventSource.
 */
function q__addEventHandlerSimple(eventSource, eventName, handlerFunctionName, receiverThisRef) {
  var handler = q__getEventHandlerFunction(handlerFunctionName, null, receiverThisRef ? receiverThisRef : eventSource);
  q__addEventHandler(eventSource, eventName, handler);
}

/*
 * eventName should be without the "on" prefix, for example: "change", "click", etc.
 */
function q__createEvent(eventName) {
  var e;
  try {
    e = document.createEvent ? document.createEvent("Events") : document.createEventObject();
  } catch (exception) {
    e = [];
  }

  var eventInitialized = false;
  try {
    if (document.createEvent)
      e.initEvent(eventName, true, true);
  } catch (exception) {
    // e.g. takes place in Safari
  }
  if (!eventInitialized)
    e.name = "on" + eventName;

  return e;
}


/*
 * eventName should be without the "on" prefix, for example: "change", "click", etc.
 */
function q__sendEvent(object, eventName) {
  var safari = q__isSafari();
  var e = safari ? {} :
          document.createEvent ? document.createEvent("Event") :
          document.createEventObject();
  if (document.createEvent && !safari) {
    e.initEvent(eventName, true, true);
    e._qk_event = true;
    object.dispatchEvent(e);
  } else {
    e.name = "on" + eventName;
    e._qk_event = true;
    var handler = object[e.name];
    if (!handler)
      return;
    return object[e.name](e);
    //    object.fireEvent(e.name, e); // - didn't work for firing "onchange" for <table>
  }

}


function q__cancelBubble(evt) {
  var e = evt ? evt : window.event;
  e.cancelBubble = true;
}

function q__isAltPressed(event) {
  if (event == null || event.altKey == null)
    return false;
  return event.altKey;
}
//

function q__isCtrlPressed(event) {
  if (event == null || event.ctrlKey == null)
    return false;
  return event.ctrlKey;
}
//

function q__isShiftPressed(event) {
  if (event == null || event.shiftKey == null)
    return false;
  return event.shiftKey;
}

function q__getEvent(e) {
  var evt = (e != undefined) ? e : event;
  return evt;
}

function q__breakEvent(e) {
  var evt = q__getEvent(e);

  if (evt.preventDefault) {
    evt.preventDefault();
  }
  evt.cancelBubble = true;
  evt.returnValue = false;
}

function q__addLoadEvent(func) {
  q__addLoadEvent(func, false);
}

function q__addLoadEvent(func, isAjaxRequest) {
  if (document._q_onLoadEventsProcessed || isAjaxRequest) {
    func();
  }
  else {
    q__addEventHandler(window, "load", func);
  }
}

function q__addUnloadEvent(func) {
  var invokeOnUnloadHandlersFunction = function() {
    for (var i = 0, count = window._q_onUnloadEvents.length; i < count; i++) {
      var onUnloadHandler = window._q_onUnloadEvents[i];
      onUnloadHandler();
    }
  }

  if (!window._q_onUnloadEvents) {
    window._q_onUnloadEvents = new Array();

    var oldonunload = window.onunload;
    if (typeof window.onunload != 'function') {
      window.onunload = function() {
        invokeOnUnloadHandlersFunction();
      }
    } else {
      window.onunload = function() {
        oldonunload();
        invokeOnUnloadHandlersFunction();
      }
    }
  }

  _q_onUnloadEvents.push(func);
}


//This function call is required to make components know certainly that onLoad event had been already proccesed.
q__addLoadEvent(function() {
  document._q_onLoadEventsProcessed = true;
});

function q__isLoadedFullPage() {
  return document._q_onLoadEventsProcessed;
}

function q__createHiddenFocusElement(tabindex) {
  var createTextArea = true;
  var focusControl = document.createElement(createTextArea ? "textarea" : "input");
  if (!createTextArea)
    focusControl.type = "button";
  focusControl.className = "q_hiddenFocus";
  if (tabindex)
    focusControl.tabIndex = tabindex;
  return focusControl;
}

function q__initDefaultScrollPosition(trackerFieldId, scrollPos) {
  q__addHiddenField(null, trackerFieldId, scrollPos);
  q__initScrollPosition_(trackerFieldId, true, 1);
}

function q__initScrollPosition(scrollPosFieldId, autoSaveScrollPos) {
  q__initScrollPosition_(scrollPosFieldId, autoSaveScrollPos, 2);
}

function q__initScrollPosition_(scrollPosFieldId, autoSaveScrollPos, priority) {
  if (window.q__scrollPosTrackingParams)
    if (window.q__scrollPosTrackingParams.priority > priority)
      return;
  window.q__scrollPosTrackingParams = {fieldId: scrollPosFieldId, autoSave: autoSaveScrollPos, priority: priority};
  q__addLoadEvent(function() {
    if (!window.q__scrollPosTrackingParams)
      return;
    var scrollPosFieldId = window.q__scrollPosTrackingParams.fieldId;
    var autoSaveScrollPos = window.q__scrollPosTrackingParams.autoSave;
    window.q__scrollPosTrackingParams = null;
    var fld = document.getElementById(scrollPosFieldId)
    document.q__scrollPositionField = fld;
    var scrollPos = fld.value;

    q__scrollToPossition(scrollPos);

    q__addEventHandler(window, "scroll", function() {
      var scrollPos = q__getPageScrollPos();
      document.q__scrollPositionField.value = "[" + scrollPos.x + "," + scrollPos.y + "]";
    });
  });
}

function q__saveScrollPositionIfNeeded() {
  //needed for saving scroll position between ajax request under Mozilla Firefox
  var isMozilla = q__isMozilla();
  var isScrollPositionTrackingEnabled = (document.q__scrollPositionField);

  // remember scrollPosition before replacing oldElement by new one
  if (isMozilla && isScrollPositionTrackingEnabled) {
    var scrollPosFieldId = document.q__scrollPositionField.id;
    var fld = document.getElementById(scrollPosFieldId)
    var scrollPos = fld.value;
    document.q__scrollPositionBeforeAjaxRequest = scrollPos;
  }
}

function q__retoreScrollPositionIfNeeded() {
  var isMozilla = q__isMozilla();
  var isScrollPositionTrackingEnabled = (document.q__scrollPositionField);

  //scroll to previous scrollPosition
  if (isMozilla && isScrollPositionTrackingEnabled) {
    var scrollPos = document.q__scrollPositionBeforeAjaxRequest;
    q__scrollToPossition(scrollPos);
  }
}

function q__scrollToPossition(scrollPos) {
  if (window.scrollTo && scrollPos && scrollPos != "") {
    scrollPos = scrollPos.substring(1, scrollPos.length - 1);
    var separatorIndex = scrollPos.indexOf(",");
    var x = scrollPos.substring(0, separatorIndex);
    var y = scrollPos.substring(separatorIndex + 1, scrollPos.length);
    var currentScrollPos = q__getPageScrollPos();
    if (x == currentScrollPos.x && y == currentScrollPos.y) {
      return;
    }
    window.scrollTo(x, y);
    if (q__isExplorer()) {
      setTimeout(function() {
        window.scrollTo(x, y)
      }, 10);
    }
  }
}
function q__initDefaultFocus(trackerFieldId, focusedComponentId) {
  q__addHiddenField(null, trackerFieldId, focusedComponentId);
  q__initFocus_(trackerFieldId, true, 1);
}

function q__initFocus(trackerFieldId, autoSaveFocus) {
  q__initFocus_(trackerFieldId, autoSaveFocus, 2);
}

function q__initFocus_(trackerFieldId, autoSaveFocus, priority) {
  q__addLoadEvent(function() {
    if (!document.q__focusPriority || priority > document.q__focusPriority) {
      document.q__focusPriority = priority;
      var trackerField = document.getElementById(trackerFieldId);
      document.q__focusField = trackerField;
      var componentId = trackerField.value;
      var focused = false;
      if (componentId) {
        var c = document.getElementById(componentId);
        if (c && c.focus) {
          try {
            c.focus();
            var rect = q__getElementRectangle(c);
            q__scrollRectIntoView(rect);
          } catch(ex) {
          }
          document.q__activeElement = c;
          focused = true;
        }
      }
      if (!focused && document.q__activeElement && document.q__activeElement.blur) {
        document.q__activeElement.blur();
        //        q__setPageScrollPos({x: 0, y: 0});
      }
    }

    if (!autoSaveFocus)
      return;

    if (document.q__autoSavingFocusInitialized)
      return;
    document.q__autoSavingFocusInitialized = true;

    var bodyElement = document.getElementsByTagName("body")[0];
    if (bodyElement == null)
      return;
    q__setupFocusOnTags(bodyElement, "input");
    q__setupFocusOnTags(bodyElement, "a");
    q__setupFocusOnTags(bodyElement, "button");
    q__setupFocusOnTags(bodyElement, "textarea");
    q__setupFocusOnTags(bodyElement, "select");
  });
}

function q__setupFocusOnTags(parent, tagName) {
  var elements = parent.getElementsByTagName(tagName);
  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    element.q__prevOnFocusHandler = element.onfocus;
    element.onfocus = function (e) {
      document.q__activeElement = this;
      document.q__focusField.value = this.id;
      if (this.q__prevOnFocusHandler)
        this.q__prevOnFocusHandler(e);
    }
    element.q__prevOnBlurHandler = element.onblur;
    element.onblur = function (e) {
      if (document.q__activeElement == this) {
        document.q__activeElement = null;
        document.q__focusField.value = "";
      }
      if (this.q__prevOnBlurHandler)
        this.q__prevOnBlurHandler(e);
    }
  }

}

function q__initMouseListenerUtils() {
  if (document._mouseListenerUtilsInitialized)
    return;
  document._mouseListenerUtilsInitialized = true;
  document._q_elementUnderMouse = null;
  document._q_prevMouseMove = document.onmousemove;
  document.onmousemove = function(e) {
    var result = undefined;
    if (document._q_prevMouseMove) {
      result = document._q_prevMouseMove(e);
    }

    var evt = q__getEvent(e);
    var elementList = new Array();
    if (document._q_elementUnderMouse) {
      for (var element = document._q_elementUnderMouse; element; element = element.parentNode) {
        element._q_mouseInside = false;
        element._q_fireMouseOut = true;
        elementList.push(element);
      }
    }
    document._q_elementUnderMouse = evt.target ? evt.target : evt.srcElement;
    if (document._q_elementUnderMouse) {
      for (var element = document._q_elementUnderMouse; element; element = element.parentNode) {
        element._q_mouseInside = true;
        element._q_fireMouseOver = true;
        elementList.push(element);
      }
    }

    for (var i = 0, count = elementList.length; i < count; i++) {
      var el = elementList[i];
      if (!el._q_fireMouseOut && !el._q_fireMouseOver)
        continue;
      if (el._q_fireMouseOut && el._q_fireMouseOver) {
        el._q_fireMouseOut = undefined;
        el._q_fireMouseOver = undefined;
        continue;
      }
      if (el._q_fireMouseOut) {
        if (el._q_mouseOutListeners)
          for (var listenerIndex = 0, listenerCount = el._q_mouseOutListeners.length; listenerIndex < listenerCount; listenerIndex++) {
            var listener = el._q_mouseOutListeners[listenerIndex];
            listener(e);
          }
        el._q_fireMouseOut = undefined;
      }
      if (el._q_fireMouseOver) {
        if (el._q_mouseOverListeners)
          for (var listenerIndex = 0, listenerCount = el._q_mouseOverListeners.length; listenerIndex < listenerCount; listenerIndex++) {
            var listener = el._q_mouseOverListeners[listenerIndex];
            listener(e);
          }
        el._q_fireMouseOver = undefined;
      }
    }

    return result;
  }
}

function q__addMouseOverListener(element, listener) {
  q__initMouseListenerUtils();
  if (!element._q_mouseOverListeners)
    element._q_mouseOverListeners = new Array();
  element._q_mouseOverListeners.push(listener);
}

function q__addMouseOutListener(element, listener) {
  q__initMouseListenerUtils();
  if (!element._q_mouseOutListeners)
    element._q_mouseOutListeners = new Array();
  element._q_mouseOutListeners.push(listener);
}

function q__isEventFromInsideOfElement(e, element) {
  var evt = q__getEvent(e);
  var eventTarget = evt.target ? evt.target : evt.srcElement;
  for (var currElement = eventTarget; currElement; currElement = currElement.parentNode) {
    if (currElement == element)
      return true;
  }
  return false;
}

function q__getTargetComponentHasOwnMouseBehavior(evt) {
  var element = evt.target ? evt.target : evt.srcElement;
  var tagName = element ? element.tagName : null;
  if (tagName)
    tagName = tagName.toUpperCase();
  var elementHasItsOwnMouseBehavior =
          tagName == "INPUT" ||
          tagName == "TEXTAREA" ||
          tagName == "SELECT" ||
          tagName == "OPTION" ||
          tagName == "BUTTON" ||
          tagName == "A";
  return elementHasItsOwnMouseBehavior;
}

function q__handleDragStart(e, draggable) {
  var evt = q__getEvent(e);
  if (q__getTargetComponentHasOwnMouseBehavior(evt))
    return; // don't drag native components to avoid unwanted effects (see JSFC-2347 and all related requests)

  q__addEventHandler(document, "mousemove", q__handleDragMove, true);
  q__addEventHandler(document, "mouseup", q__handleDragEnd, true);
  if (q__isExplorer())
    draggable._draggingInProgress = true; // is this needed (ie only) ?

  draggable.dragStartCalled = false;

  var pageScrollPos = q__getPageScrollPos();
  draggable.dragX = evt.clientX + pageScrollPos.x;
  draggable.dragY = evt.clientY + pageScrollPos.y;

  draggable.startX = draggable.offsetLeft;
  draggable.startY = draggable.offsetTop;

  document._q_draggedElement = draggable;
  q__breakEvent(evt);
}


function q__handleDragMove(e) {
  var evt = q__getEvent(e);
  var draggable = document._q_draggedElement;

  draggable._draggingInProgress = true;
  if (!draggable.dragStartCalled && draggable.ondragstart) {
    draggable.dragStartCalled = true;
    draggable.ondragstart(evt);
  }
  var pageScrollPos = q__getPageScrollPos();
  var dragX = evt.clientX + pageScrollPos.x;
  var dragY = evt.clientY + pageScrollPos.y;
  var newLeft = draggable.offsetLeft + (dragX - draggable.dragX);
  draggable.setLeft(newLeft);
  draggable.setTop(draggable.offsetTop + (dragY - draggable.dragY));
  draggable.dragX = dragX;
  draggable.dragY = dragY;
  q__breakEvent(evt);
}

function q__handleDragEnd(e) {
  var evt = q__getEvent(e);

  var draggable = document._q_draggedElement;
  if (draggable.dragStartCalled) {
    draggable.dragStartCalled = undefined;
    if (draggable.ondragend)
      draggable.ondragend(evt);
  }

  q__removeEventHandler(document, "mousemove", q__handleDragMove, true);
  q__removeEventHandler(document, "mouseup", q__handleDragEnd, true);
  if (!draggable._onmouseup) {
    q__breakEvent(evt);
  }
  draggable._draggingInProgress = false;
}

// ----------------- STYLE UTILITIES ---------------------------------------------------

function q__addCssRules(ruleArray) {
  for (var i = 0, count = ruleArray.length; i < count; i++) {
    var rule = ruleArray[i];
    q__addCssRule(rule);
  }
}

function q__getLocalStyleSheet() {
  var styleSheets = document.styleSheets;
  if (!styleSheets)
    return null;

  if (document._q_localStyleSheet)
    return document._q_localStyleSheet;

  function locateLocalStyleSheet() {
    var documentLocation = document.location;
    for (var i = 0, count = styleSheets.length; i < count; i++) {
      var styleSheet = styleSheets[i];
      if (styleSheet.href == documentLocation || /* Mozilla Firefox */
          !styleSheet.href /* other browsers */) {
        document._q_localStyleSheet = styleSheet;
        break;
      }
    }
  }

  locateLocalStyleSheet();
  if (document._q_localStyleSheet)
    return document._q_localStyleSheet;

  if (document.createStyleSheet) {
    document._q_localStyleSheet = document.createStyleSheet();
  } else {
    var styleElement = document.createElement("style");
    var headTags = document.getElementsByTagName("head");
    var styleParent = headTags.length > 0 ? headTags[0] : document.getElementsByTagName("body")[0];
    styleParent.appendChild(styleElement);
  }
  locateLocalStyleSheet();
  if (!document._q_localStyleSheet) {
    if (styleSheets.length > 0) {
      q__logWarning(document._q_localStyleSheet, "q__getLocalStyleSheet: couldn't find or create local style-sheet in this document, using the first available one.");
      document._q_localStyleSheet = styleSheets[0];
      // relative url paths in background won't work in Mozilla in this case
    } else {
      q__logWarning(document._q_localStyleSheet, "q__getLocalStyleSheet: no style-sheets could be found or created in this document");
    }
  }
  return document._q_localStyleSheet;
}

function q__addCssRule(strRule) {
  var styleSheet = q__getLocalStyleSheet();
  if (!styleSheet)
    return;

  if (styleSheet.addRule) { // IE only
    var idx1 = strRule.indexOf("{");
    var idx2 = strRule.indexOf("}");
    q__assert(idx1 != -1 && idx2 != -1 && idx2 > idx1, "q__addCssRule: Couldn't parse CSS rule \"{...}\"  boundaries: " + strRule);
    var selector = strRule.substring(0, idx1);
    var declaration = strRule.substring(idx1 + 1, idx2);
    styleSheet.addRule(selector, declaration);
  } else { // all others
    styleSheet.insertRule(strRule, styleSheet.cssRules.length);
  }
}

function q__findCssRule(selector) {
  var rules = q__findCssRules([selector]);
  if (rules === undefined)
    return undefined;
  if (rules.length == 0)
    return null;
  return rules[0];
}

/**
 * Searches for CSS rules with the specified selectors, and returns an array of CSSStyleRule (or CSSRule) objects
 * in order of their occurence in DOM
 */
function q__findCssRules(selectors) {
  var styleSheets = document.styleSheets;
  if (!styleSheets)
    return undefined;

  var selectorCount = selectors.length
  if (selectorCount == 0)
    return [];

  for (var i = 0; i < selectorCount; i++)
    selectors[i] = selectors[i].toLowerCase();

  var rulesFound = new Array();
  for (var sheetIndex = 0; sheetIndex < styleSheets.length; sheetIndex++) {
    var ss = styleSheets[sheetIndex];
    var rules = ss.cssRules ? ss.cssRules : ss.rules;
    if (!rules) continue;
    for (var ruleIndex = 0, ruleCount = rules.length; ruleIndex < ruleCount; ruleIndex++) {
      var rule = rules[ruleIndex];
      var selectorName = rule.selectorText;
      if (!selectorName)
        continue;
      selectorName = selectorName.toLowerCase();
      if (q__findValueInArray(selectorName, selectors) != -1)
        rulesFound.push(rule);
    }
  }
  return rulesFound;
}

function q__evaluateStyleClassProperty(styleClass, propertyName) {
  var propertyValues = q__evaluateStyleClassProperties(styleClass, [propertyName]);
  return propertyValues[propertyName];
}

function q__evaluateStyleClassProperties(styleClass, propertyNames) {
  if (!styleClass || propertyNames.length == 0)
    return {};
  var classNames = styleClass.split(" ");
  var classSelectors = new Array();
  for (var i = 0, count = classNames.length; i < count; i++) {
    var className = classNames[i];
    if (className)
      classSelectors.push("." + className);
  }
  var cssRules = q__findCssRules(classSelectors);
  if (!cssRules)
    return {};

  var propertyCount = propertyNames.length;
  var propertyValues = new Object();
  var propertyImportantFlags = new Array();
  for (var i = 0, count = cssRules.length; i < count; i++) {
    var cssRule = cssRules[i];
    var ruleStyle = cssRule.style;
    for (var propertyIndex = 0; propertyIndex < propertyCount; propertyIndex++) {
      var propertyName = propertyNames[propertyIndex];
      var thisPropertyValue = ruleStyle[propertyName];
      if (!thisPropertyValue)
        continue;
      var thisPropertyImportant = ruleStyle.getPropertyPriority && (ruleStyle.getPropertyPriority(propertyName) == "important");
      if (!propertyImportantFlags[propertyIndex]) {
        propertyValues[propertyName] = thisPropertyValue;
        if (thisPropertyImportant)
          propertyImportantFlags[propertyIndex] = true;
      } else {
        if (thisPropertyImportant)
          propertyValues[propertyName] = thisPropertyValue;
      }
    }
  }

  return propertyValues;
}

//

function q__combineClassNames(classNames) {
  var nonNullClassNames = new Array();
  for (var i = 0, count = classNames.length; i < count; i++) {
    var className = classNames[i];
    if (className)
      nonNullClassNames.push(className);
  }
  var result = nonNullClassNames.join(" ");
  return result;
}

function q__appendClassNames(element, classesToAppend) {
  var oldClassName = element.className;
  var newClassName = q__combineClassNames(classesToAppend);
  if (oldClassName)
    newClassName = newClassName ? oldClassName + " " + newClassName : oldClassName;
  if (newClassName != oldClassName)
    element.className = newClassName;
  return oldClassName;
}

function q__checkClassNameUsed(element, className) {
  var classNames = element.className.split(" ");
  for (var i = 0, count = classNames.length; i < count; i++) {
    var usedClassName = classNames[i];
    if (usedClassName && usedClassName == className)
      return true;
  }

  return false;
}

function q__excludeClassNames(element, classesToExclude) {
  var newClassesToExclude = new Array();
  for (var i = 0, count = classesToExclude.length; i < count; i++) {
    var clsToExclude = classesToExclude[i];
    if (!clsToExclude)
      continue;
    var subClassesToExclude = clsToExclude.split(" ");
    for (var j = 0, jcount = subClassesToExclude.length; j < jcount; j++) {
      var subClassToExclude = subClassesToExclude[j];
      newClassesToExclude.push(subClassToExclude);
    }
  }

  var someClassesExcluded = false;
  var clsName = element.className;
  var clsNames = clsName ? clsName.split(" ") : new Array();
  var newNames = new Array();
  for (var nameIndex = 0, nameCount = clsNames.length; nameIndex < nameCount; nameIndex++) {
    var currName = clsNames[nameIndex];
    if (currName) {
      if (q__findValueInArray(currName, newClassesToExclude) == -1)
        newNames.push(currName);
      else
        someClassesExcluded = true;
    }
  }
  var newClsName = newNames.join(" ");
  if (element.className != newClsName)
    element.className = newClsName;
  return someClassesExcluded;
}

function q__getElementOwnStyle(element) {
  var styleMappings = element._styleMappings;
  if (!styleMappings)
    return element.className;
  else
    return styleMappings.__initialStyle;
}

function q__setElementOwnStyle(element, value) {
  var styleMappings = element._styleMappings;
  if (!styleMappings)
    return element.className = value;
  else
    return styleMappings.__initialStyle = value;
}

function q__setElementStyleMappings(element, styleMappings) {
  if (!element._styleMappings)
    element._styleMappings = {__initialStyle: element.className};
  var elementStyleMappings = element._styleMappings;
  for (var styleName in styleMappings) {
    if (!styleName || styleName.charAt(0) != "_")
      continue;
    element._styleMappings[styleName] = styleMappings[styleName];
  }
  var compoundClassName = "";
  for (var styleName in elementStyleMappings) {
    if (!styleName || styleName.charAt(0) != "_")
      continue;
    var styleValue = elementStyleMappings[styleName];
    if (styleValue)
      compoundClassName += styleValue + " ";
  }
  if (element.className != compoundClassName) {
	  element.className = compoundClassName;
	  if (element._classNameChangeHandler)
	    element._classNameChangeHandler();
  }
}

function q__calculateStyleProperty(element, propertyName, enableValueCaching) {
  var result;
  if (enableValueCaching) {
    if (!element._cachedStyleValues)
      element._cachedStyleValues = {};
    result = element._cachedStyleValues[propertyName];
  }
  if (result != undefined)
    return result;

  if (element.currentStyle) {
    var capitalizedProperty = q__capitalizeCssPropertyName(propertyName);
    result = element.currentStyle[capitalizedProperty];
  } else {
    var computedStyle = document.defaultView.getComputedStyle(element, "");
    if (computedStyle)
      result = computedStyle.getPropertyValue(propertyName);
  }
  if (!result)
    result = "";
  if (enableValueCaching) {
    element._cachedStyleValues[propertyName] = result;
  }
  return result;
}

function q__capitalizeCssPropertyName(propertyName) {
  while (true) {
    var idx = propertyName.indexOf("-");
    if (idx == -1)
      return propertyName;
    var firstPart = propertyName.substring(0, idx);
    var secondPart = propertyName.substring(idx + 1);
    if (secondPart.length > 0) {
      var firstChar = secondPart.substring(0, 1);
      firstChar = firstChar.toUpperCase();
      var otherChars = secondPart.substring(1);
      secondPart = firstChar + otherChars;
    }
    propertyName = firstPart + secondPart;
  }
}

function q__repaintAreaForOpera(element, deferredRepainting) {
  if (!q__isOpera())
    return;
  if (!element)
    return;
  if (deferredRepainting) {
    setTimeout(function() {
      q__repaintAreaForOpera(element, false);
    }, 1);
    return;
  }
  // using backgroundColor instead of just background is important here for cases when image is set as background
  // NOTE: setting the calculated border is an erroneous pattern because any further background changes through
  // element's className will be overriden by this in-place style declaration. However it must be uesd for document.body
  // because this element behaves differently when assigned old background - assigning a non-specified old background
  // makes the background white disregarding the appropriate stylesheets (JSFC-2346, JSFC-2275)
  var oldBackgroundColor = element != document.body
          ? element.style.backgroundColor
          : q__calculateStyleProperty(element, "background-color");
  element.style.backgroundColor = "white";
  element.style.backgroundColor = "#fefefe";
  element.style.backgroundColor = oldBackgroundColor;
}

//JSFC-3270
function q__repaintWindowForSafari(deferredRepainting){
  if (!q__isSafari())
    return;
  if (deferredRepainting) {
    setTimeout(function() {               //for fast machine
      q__repaintWindowForSafari(false);
    }, 50);
    setTimeout(function() {                //for slow machine
      q__repaintWindowForSafari(false);
    }, 300);
    return;
  }
  var tempDiv = document.createElement("div");
  tempDiv.innerHTML = "<div> <style type='text/css'> .d_u_m_p_c_l_a_s_s_ { background: black; filter: alpha( opacity = 50 ); opacity: .50; } </style> </div>"
}

function q__preloadImage(imageUrl) {
  var image = new Image();
  image.src = imageUrl;
}

function q__preloadImages(imageUrls) {
  for (var i = 0, count = imageUrls.length; i < count; i++) {
    var imageUrl = imageUrls[i];
    q__preloadImage(imageUrl);
  }
}

// ----------------- DATE/TIME UTILITIES ---------------------------------------------------

function q__initDateTimeFormatObject(months, shortMonths, days, shortDays, localeStr) {
  if (!this._dateTimeFormatMap) {
    this._dateTimeFormatMap = new Array();
  }
  if (!this._dateTimeFormatMap[localeStr]) {
    this._dateTimeFormatMap[localeStr] = new DateTimeFormat(months, shortMonths, days, shortDays);
  }
  //  this._dateTimeFormat = new DateTimeFormat(months, shortMonths, days, shortDays);
}

function q__getDateTimeFormatObject(locale) {
  if(this._dateTimeFormatMap)
    return this._dateTimeFormatMap[locale];
  return null;
}

// ----------------- ABSOLUTE POSITIONING / METRICS UTILITIES ---------------------------------------------------

function q__getElementPos(elt, ignoreAbsolutePosition, stopAtContainingBlocks) {
  var left = 0;
  var top = 0;
  //  left = elt.clientLeft;
  var checkAbsoluteOffsetParent = ignoreAbsolutePosition || (q__calculateStyleProperty(elt, "position") != "absolute");
  // quirk for FireFox - JSFC-1183
  var checkAbsolutePositionedTable = (q__isMozilla() || q__isExplorer) && elt.tagName.toLowerCase() == 'table';
  // todo: checking q__isExplorer might not be needed here -- check this
  if (!(elt != null && (checkAbsoluteOffsetParent || checkAbsolutePositionedTable))) {
    return {left: 0, top: 0};
  }

  var offsetParent = elt.offsetParent;
  left = elt.offsetLeft;
  top = elt.offsetTop;
  /*if component has border style*/
  if (q__isExplorer() || q__isOpera() || q__isSafari3AndLate()) {
    var lowerCaseTagName = elt.tagName.toLowerCase();
    if (lowerCaseTagName == 'table' && q__isSafari3AndLate()) {
      var border = q__calculateNumericCSSValue(elt.border);
      if (border > 0) {
        left += border;
        top += border;
      }
    } else {
      if (lowerCaseTagName == 'div' || lowerCaseTagName == 'td') {
        if (!q__isOpera9AndLate()) { // border in Opera 9 included in offsetLeft and offsetTop;
          left += (elt.clientLeft == undefined ? q__calculateNumericStyleProperty(elt, "border-left-width") : elt.clientLeft);
          top += (elt.clientTop == undefined ? q__calculateNumericStyleProperty(elt, "border-top-width") : elt.clientTop);
        }
      }
    }
  }

  if (q__isMozilla() || q__isExplorer()){
    var prnt = elt.parentNode;
    if (prnt && prnt.nodeName && prnt.nodeName.toUpperCase() != "HTML"
            && !(q__isExplorer() && prnt.nodeName.toUpperCase() == "BODY")) {  //JSFC-2598
      var pscrollLeft = prnt.scrollLeft;
      if (pscrollLeft)
        left -= pscrollLeft;
      var pscrollTop = prnt.scrollTop;
      if (pscrollTop)
        top -= pscrollTop;
    }
  }

  if (offsetParent) {
    if (!(stopAtContainingBlocks && q__isContainingBlock(offsetParent))) {
      var parentPos = q__getElementPos(offsetParent, ignoreAbsolutePosition, stopAtContainingBlocks);

      left += parentPos.left;
      top += parentPos.top;
    } else {
      if (offsetParent.tagName.toLowerCase() == "div" && (q__isOpera9AndLate() || q__isSafari2())) {
        if (q__calculateStyleProperty(offsetParent, "border-style") != "none") {
          var border_left_width = q__calculateNumericStyleProperty(offsetParent, "border-left-width");
          var border_top_width = q__calculateNumericStyleProperty(offsetParent, "border-top-width");
          left -= border_left_width;
          top -= border_left_width;
        }
      }
    }
  }
  return {left: left, top: top};
}

function q__getElementLeft(elt, ignoreAbsolutePosition, stopAtContainingBlocks) {
  return q__getElementPos(elt, ignoreAbsolutePosition, stopAtContainingBlocks).left;
}

function q__getElementTop(elt, ignoreAbsolutePosition, stopAtContainingBlocks) {
  return q__getElementPos(elt, ignoreAbsolutePosition, stopAtContainingBlocks).top;
}

/**
 * Introduced according to CSS spec http://www.w3.org/TR/REC-CSS2/visudet.html#containing-block-details
 * See JSFC-2045 Popups displayed incorrectly under JBoss Portal
 */
function q__isContainingBlock(elt) {
  q__assert(elt, "elt is null");
  var position = q__calculateStyleProperty(elt, "position");
  if (!position) return false;
  return position != "static";
}

function q__getElementRectangle(element) {
  var pos = q__getElementPos(element);
  return new q__Rectangle(pos.left, pos.top, element.offsetWidth, element.offsetHeight);
}

function q__Rectangle(x, y, width, height) {
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;

  this.getMinX = function() {
    return this.x;
  }
  this.getMinY = function() {
    return this.y;
  }
  this.getMaxX = function() {
    var result = this.x + this.width;
    return result;
  }
  this.getMaxY = function() {
    var result = this.y + this.height;
    return result;
  }
  this.addRectangle = function(rect) {
    q__assert(rect, "rect parameter should be passed");
    var x1 = this.getMinX();
    if (rect.getMinX() < x1)
      x1 = rect.getMinX();
    var y1 = this.getMinY();
    if (rect.getMinY() < y1)
      y1 = rect.getMinY();
    var x2 = this.getMaxX();
    if (rect.getMaxX() > x2)
      x2 = rect.getMaxX();
    var y2 = this.getMaxY();
    if (rect.getMaxY() > y2)
      y2 = rect.getMaxY();
    this.x = x1;
    this.y = y1
    this.width = x2 - x1;
    this.height = y2 - y1;
  }

  this.isIntersects = function(rect) {
    var x1 = this.getMinX();
    var x2 = this.getMaxX();
    var rectX1 = rect.getMinX();
    var rectX2 = rect.getMaxX();
    var y1 = this.getMinY();
    var y2 = this.getMaxY();
    var rectY1 = rect.getMinY();
    var rectY2 = rect.getMaxY();

    return (rectX2 > x1 && rectY2 > y1 && rectX1 < x2 && rectY1 < y2);
  }
}

function q__getVisibleRectangle() {
  var pageScrollPos = q__getPageScrollPos();
  var x = pageScrollPos.x;
  var y = pageScrollPos.y;
  var width = document.body.clientWidth;
  var height = document.body.clientHeight;
  return new q__Rectangle(x, y, width, height);
}

function q__scrollRectIntoView(rect) {
  var visibleRect = q__getVisibleRectangle();
  var dx = 0;
  if (rect.getMinX() < visibleRect.getMinX())
    dx = rect.getMinX() - visibleRect.getMinX();
  if (rect.getMaxX() > visibleRect.getMaxX())
    dx = rect.getMaxX() - visibleRect.getMaxX();
  var dy = 0;
  if (rect.getMinY() < visibleRect.getMinY())
    dy = rect.getMinY() - visibleRect.getMinY();
  if (rect.getMaxY() > visibleRect.getMaxY())
    dy = rect.getMaxY() - visibleRect.getMaxY();

  // account for rect being bigger than visibleRect - align by top, right edges should have a priority in this case
  var newMinX = visibleRect.getMinX() + dx;
  if (rect.getMinX() < newMinX)
    dx = rect.getMinX() - newMinX;
  var newMinY = visibleRect.getMinY() + dy;
  if (rect.getMinY() < newMinY)
    dy = rect.getMinY() - newMinY;

  window.scrollBy(dx, dy);
}

function q__getPageScrollPos() {
  var x = 0;
  var y = 0;
  if (typeof( window.pageYOffset ) == 'number') {
    //Netscape compliant
    y = window.pageYOffset;
    x = window.pageXOffset;
  } else if (document.body && ( document.body.scrollLeft || document.body.scrollTop )) {
    //DOM compliant
    y = document.body.scrollTop;
    x = document.body.scrollLeft;
  } else if (document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop )) {
    //IE6 standards compliant mode
    y = document.documentElement.scrollTop;
    x = document.documentElement.scrollLeft;
  }
  return {x: x, y: y};
}

function q__setPageScrollPos(scrollPos) {
  window.scrollTo(scrollPos.x, scrollPos.y);
}

function q__getLeftBodyMargin() {
  return q__calculateNumericStyleProperty(document.body, "margin-left");
}

function q__getTopBodyMargin() {
  return q__calculateNumericStyleProperty(document.body, "margin-top");
}

function q__calculateNumericStyleProperty(element, propertyName, enableValueCaching) {
  var str = q__calculateStyleProperty(element, propertyName, enableValueCaching);
  return q__calculateNumericCSSValue(str);
}

function q__calculateNumericCSSValue(value) {
  if (!value)
    return 0;
  if (!isNaN(1 * value))
    return 1 * value;
  if (q__stringEndsWith(value, "px"))
    return 1 * value.substring(0, value.length - 2);

  if (!window._q_nonPixelValueMeasurements)
    window._q_nonPixelValueMeasurements = [];
  var pixelValue = window._q_nonPixelValueMeasurements[value];
  if (pixelValue != undefined)
    return pixelValue;

  var outerDiv = window._q_nonPixelMeasurements_outerDiv;
  var innerDiv = window._q_nonPixelMeasurements_innerDiv;
  if (!outerDiv) {
    outerDiv = document.createElement("div");
//    outerDiv.style.position = "absolute";
//    outerDiv.style.left = "0px"
//    outerDiv.style.top = "0px"
    outerDiv.style.padding = "0px";
    outerDiv.style.margin = "0px";
    innerDiv = document.createElement("div");
    innerDiv.style.padding = "0px";
    innerDiv.style.margin = "0px";
    outerDiv.appendChild(innerDiv);
    window._q_nonPixelMeasurements_outerDiv = outerDiv;
    window._q_nonPixelMeasurements_innerDiv = innerDiv;
  }
  outerDiv.style.border = value + " solid white";
  document.body.appendChild(outerDiv);
  pixelValue = innerDiv.offsetTop - outerDiv.offsetTop;
  document.body.removeChild(outerDiv);
  window._q_nonPixelValueMeasurements[value] = pixelValue;
  return pixelValue;
}

// ----------------- HIDE <SELECT> CONTROLS UNDER POPUP IN IE ---------------------------------------------------

var q__controlsToHide = q__isExplorer() ? new Array('select-one', 'select-multiple') : null;
var q__controlsHiddenControlsMap = new Object();

function q__walkControlsToHide(popup, runFunction) {
  if (popup._coveredControls) {
    for (var i = 0; i < popup._coveredControls.length; i++) {
      var control = popup._coveredControls[i];
      runFunction.call(this, control);
    }
  }
}

function q__hideControlsUnderPopup(popup) {
  if (q__isExplorer() && q__controlsToHide && q__controlsToHide.length > 0) {
    var runFunction = function(control) {
      var controlData = new Object();
      controlData.id = popup.id;
      controlData.visibility = control.style.visibility;
      q__controlsHiddenControlsMap[control.id] = controlData;
      control.style.visibility = 'hidden';
    }

    var rectangle = new q__Rectangle(popup.offsetLeft, popup.offsetTop, popup.offsetWidth, popup.offsetHeight);
    popup._coveredControls = new Array();
    var frm = q__findParentNode(popup, "FORM");
    var controls = frm.elements;
    var index = 0;
    for (var i = 0; i < controls.length; i++) {
      var control = controls[i];
      if (control.type && q__arrayContainsValue(q__controlsToHide, control.type)) {
        if (! q__isChild(popup, control)) {
          var examRectangle = q__getElementRectangle(control);
          if (rectangle.isIntersects(examRectangle)) {
            popup._coveredControls[index++] = control;
          }
        }
      }
    }


    q__walkControlsToHide(popup, runFunction);
  }
}

function q__unhideControlsUnderPopup(popup) {
  if (q__isExplorer() && q__controlsToHide && q__controlsToHide.length > 0) {
    var runFunction = function(control) {
      var controlData = q__controlsHiddenControlsMap[control.id];
      if (controlData && (controlData.id == popup.id)) {
        control.style.visibility = controlData.visibility;
      }
    }
    q__walkControlsToHide(popup, runFunction);
    popup._coveredControls = null;
  }
}

function q__initIETransparencyWorkaround(popup) {
  if (!q__isExplorer() || q__isExplorer7())
    return;
  popup._requireTransparencyWorkaround = true;
  if (popup._preCreatedIETransparencyControl)
    return;

  var iframe = document.createElement("iframe");
  iframe.src = "javascript:'';";
  // to overcome the "unsecured items" message on HTTPS pages
  iframe.id = popup.id + "::ieTransparencyControl";
  iframe.scrolling = "No";
  iframe.frameBorder = "0";
  iframe.style.position = "absolute";
  iframe.style.filter = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)";
  // to support transparency of the popup itself

  iframe._updatePositionAndSize = function() {
    iframe.style.width = popup.offsetWidth + "px";
    iframe.style.height = popup.offsetHeight + "px";
    iframe.style.left = popup.offsetLeft + "px";
    iframe.style.top = popup.offsetTop + "px";
  }

  var popupZIndex = q__calculateStyleProperty(popup, "z-index");
  if (!popupZIndex) {
    popupZIndex = 10;
    popup.style.zIndex = popupZIndex;
  }
  iframe.zIndex = popup.zIndex - 1;

  iframe.style.display = "none";
  popup.parentNode.insertBefore(iframe, popup);
  popup._preCreatedIETransparencyControl = iframe;
}

function q__addIETransparencyControl(popup) {
  if (!popup._requireTransparencyWorkaround)
    return;
  if (popup._ieTransparencyControl) {
    popup._ieTransparencyControl._updatePositionAndSize();
    return;
  }

  if (!popup._preCreatedIETransparencyControl)
    q__initIETransparencyWorkaround(popup);
  var iframe = popup._preCreatedIETransparencyControl;
  iframe.style.display = "";
  iframe._updatePositionAndSize();
  popup._ieTransparencyControl = iframe;
}

function q__removeIETransparencyControl(popup) {
  if (!popup._requireTransparencyWorkaround || !popup._ieTransparencyControl)
    return;

  popup._ieTransparencyControl.style.display = "none";
  popup._ieTransparencyControl = undefined;
}

function q__invokeOnce(func, funcId) {
  if (!q__isInvoked(funcId)) {
    func();
    q__getInvokedFunctions().push(funcId);
  }
}

function q__isInvoked(funcId) {
  var invokedFunctions = q__getInvokedFunctions();
  return q__contains(invokedFunctions, funcId);
}

function q__getInvokedFunctions() {
  var invokedFunctions = document.q__invokedFunctions;
  if (!invokedFunctions) {
    invokedFunctions = new Array();
    document.q__invokedFunctions = invokedFunctions;
  }
  return invokedFunctions;
}

function q__contains(array, object) {
  for (var i = 0, count = array.length; i < count; i++) {
    if (object == array[i])
      return true;
  }
  return false;
}

function q__isInvisible(element) {
  if (!element.style) {
    return false;
  }
  return element.style.display == "none" || element.style.visibility == "hidden";
}

function q__isVisibleRecursive(element) {
  if (q__isInvisible(element)) {
    return false;
  }
  var parentNode = element.parentNode;
  if (!parentNode) {
    return true;
  }
  return q__isVisibleRecursive(parentNode);
}


//AUTO GENERATED CODE

window['q_loadedLibrary:/quipukit/demo/qk_internalResource/teamdev/jsf/renderkit/util/util-1.6.2.js'] = true;