/*
* jQuery JavaScript Library v1.3.2
* http://jquery.com/
*
* Copyright (c) 2009 John Resig
* Dual licensed under the MIT and GPL licenses.
* http://docs.jquery.com/License
*
* Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
* Revision: 6246
*/
(function() {
    var l = this, g, y = l.jQuery, p = l.$, o = l.jQuery = l.$ = function(E, F) { return new o.fn.init(E, F) }, D = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/, f = /^.[^:#\[\.,]*$/; o.fn = o.prototype = { init: function(E, H) { E = E || document; if (E.nodeType) { this[0] = E; this.length = 1; this.context = E; return this } if (typeof E === "string") { var G = D.exec(E); if (G && (G[1] || !H)) { if (G[1]) { E = o.clean([G[1]], H) } else { var I = document.getElementById(G[3]); if (I && I.id != G[3]) { return o().find(E) } var F = o(I || []); F.context = document; F.selector = E; return F } } else { return o(H).find(E) } } else { if (o.isFunction(E)) { return o(document).ready(E) } } if (E.selector && E.context) { this.selector = E.selector; this.context = E.context } return this.setArray(o.isArray(E) ? E : o.makeArray(E)) }, selector: "", jquery: "1.3.2", size: function() { return this.length }, get: function(E) { return E === g ? Array.prototype.slice.call(this) : this[E] }, pushStack: function(F, H, E) { var G = o(F); G.prevObject = this; G.context = this.context; if (H === "find") { G.selector = this.selector + (this.selector ? " " : "") + E } else { if (H) { G.selector = this.selector + "." + H + "(" + E + ")" } } return G }, setArray: function(E) { this.length = 0; Array.prototype.push.apply(this, E); return this }, each: function(F, E) { return o.each(this, F, E) }, index: function(E) { return o.inArray(E && E.jquery ? E[0] : E, this) }, attr: function(F, H, G) { var E = F; if (typeof F === "string") { if (H === g) { return this[0] && o[G || "attr"](this[0], F) } else { E = {}; E[F] = H } } return this.each(function(I) { for (F in E) { o.attr(G ? this.style : this, F, o.prop(this, E[F], G, I, F)) } }) }, css: function(E, F) { if ((E == "width" || E == "height") && parseFloat(F) < 0) { F = g } return this.attr(E, F, "curCSS") }, text: function(F) { if (typeof F !== "object" && F != null) { return this.empty().append((this[0] && this[0].ownerDocument || document).createTextNode(F)) } var E = ""; o.each(F || this, function() { o.each(this.childNodes, function() { if (this.nodeType != 8) { E += this.nodeType != 1 ? this.nodeValue : o.fn.text([this]) } }) }); return E }, wrapAll: function(E) { if (this[0]) { var F = o(E, this[0].ownerDocument).clone(); if (this[0].parentNode) { F.insertBefore(this[0]) } F.map(function() { var G = this; while (G.firstChild) { G = G.firstChild } return G }).append(this) } return this }, wrapInner: function(E) { return this.each(function() { o(this).contents().wrapAll(E) }) }, wrap: function(E) { return this.each(function() { o(this).wrapAll(E) }) }, append: function() { return this.domManip(arguments, true, function(E) { if (this.nodeType == 1) { this.appendChild(E) } }) }, prepend: function() { return this.domManip(arguments, true, function(E) { if (this.nodeType == 1) { this.insertBefore(E, this.firstChild) } }) }, before: function() { return this.domManip(arguments, false, function(E) { this.parentNode.insertBefore(E, this) }) }, after: function() { return this.domManip(arguments, false, function(E) { this.parentNode.insertBefore(E, this.nextSibling) }) }, end: function() { return this.prevObject || o([]) }, push: [].push, sort: [].sort, splice: [].splice, find: function(E) { if (this.length === 1) { var F = this.pushStack([], "find", E); F.length = 0; o.find(E, this[0], F); return F } else { return this.pushStack(o.unique(o.map(this, function(G) { return o.find(E, G) })), "find", E) } }, clone: function(G) { var E = this.map(function() { if (!o.support.noCloneEvent && !o.isXMLDoc(this)) { var I = this.outerHTML; if (!I) { var J = this.ownerDocument.createElement("div"); J.appendChild(this.cloneNode(true)); I = J.innerHTML } return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0] } else { return this.cloneNode(true) } }); if (G === true) { var H = this.find("*").andSelf(), F = 0; E.find("*").andSelf().each(function() { if (this.nodeName !== H[F].nodeName) { return } var I = o.data(H[F], "events"); for (var K in I) { for (var J in I[K]) { o.event.add(this, K, I[K][J], I[K][J].data) } } F++ }) } return E }, filter: function(E) { return this.pushStack(o.isFunction(E) && o.grep(this, function(G, F) { return E.call(G, F) }) || o.multiFilter(E, o.grep(this, function(F) { return F.nodeType === 1 })), "filter", E) }, closest: function(E) { var G = o.expr.match.POS.test(E) ? o(E) : null, F = 0; return this.map(function() { var H = this; while (H && H.ownerDocument) { if (G ? G.index(H) > -1 : o(H).is(E)) { o.data(H, "closest", F); return H } H = H.parentNode; F++ } }) }, not: function(E) { if (typeof E === "string") { if (f.test(E)) { return this.pushStack(o.multiFilter(E, this, true), "not", E) } else { E = o.multiFilter(E, this) } } var F = E.length && E[E.length - 1] !== g && !E.nodeType; return this.filter(function() { return F ? o.inArray(this, E) < 0 : this != E }) }, add: function(E) { return this.pushStack(o.unique(o.merge(this.get(), typeof E === "string" ? o(E) : o.makeArray(E)))) }, is: function(E) { return !!E && o.multiFilter(E, this).length > 0 }, hasClass: function(E) { return !!E && this.is("." + E) }, val: function(K) { if (K === g) { var E = this[0]; if (E) { if (o.nodeName(E, "option")) { return (E.attributes.value || {}).specified ? E.value : E.text } if (o.nodeName(E, "select")) { var I = E.selectedIndex, L = [], M = E.options, H = E.type == "select-one"; if (I < 0) { return null } for (var F = H ? I : 0, J = H ? I + 1 : M.length; F < J; F++) { var G = M[F]; if (G.selected) { K = o(G).val(); if (H) { return K } L.push(K) } } return L } return (E.value || "").replace(/\r/g, "") } return g } if (typeof K === "number") { K += "" } return this.each(function() { if (this.nodeType != 1) { return } if (o.isArray(K) && /radio|checkbox/.test(this.type)) { this.checked = (o.inArray(this.value, K) >= 0 || o.inArray(this.name, K) >= 0) } else { if (o.nodeName(this, "select")) { var N = o.makeArray(K); o("option", this).each(function() { this.selected = (o.inArray(this.value, N) >= 0 || o.inArray(this.text, N) >= 0) }); if (!N.length) { this.selectedIndex = -1 } } else { this.value = K } } }) }, html: function(E) { return E === g ? (this[0] ? this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") : null) : this.empty().append(E) }, replaceWith: function(E) { return this.after(E).remove() }, eq: function(E) { return this.slice(E, +E + 1) }, slice: function() { return this.pushStack(Array.prototype.slice.apply(this, arguments), "slice", Array.prototype.slice.call(arguments).join(",")) }, map: function(E) { return this.pushStack(o.map(this, function(G, F) { return E.call(G, F, G) })) }, andSelf: function() { return this.add(this.prevObject) }, domManip: function(J, M, L) { if (this[0]) { var I = (this[0].ownerDocument || this[0]).createDocumentFragment(), F = o.clean(J, (this[0].ownerDocument || this[0]), I), H = I.firstChild; if (H) { for (var G = 0, E = this.length; G < E; G++) { L.call(K(this[G], H), this.length > 1 || G > 0 ? I.cloneNode(true) : I) } } if (F) { o.each(F, z) } } return this; function K(N, O) { return M && o.nodeName(N, "table") && o.nodeName(O, "tr") ? (N.getElementsByTagName("tbody")[0] || N.appendChild(N.ownerDocument.createElement("tbody"))) : N } } }; o.fn.init.prototype = o.fn; function z(E, F) { if (F.src) { o.ajax({ url: F.src, async: false, dataType: "script" }) } else { o.globalEval(F.text || F.textContent || F.innerHTML || "") } if (F.parentNode) { F.parentNode.removeChild(F) } } function e() { return +new Date } o.extend = o.fn.extend = function() { var J = arguments[0] || {}, H = 1, I = arguments.length, E = false, G; if (typeof J === "boolean") { E = J; J = arguments[1] || {}; H = 2 } if (typeof J !== "object" && !o.isFunction(J)) { J = {} } if (I == H) { J = this; --H } for (; H < I; H++) { if ((G = arguments[H]) != null) { for (var F in G) { var K = J[F], L = G[F]; if (J === L) { continue } if (E && L && typeof L === "object" && !L.nodeType) { J[F] = o.extend(E, K || (L.length != null ? [] : {}), L) } else { if (L !== g) { J[F] = L } } } } } return J }; var b = /z-?index|font-?weight|opacity|zoom|line-?height/i, q = document.defaultView || {}, s = Object.prototype.toString; o.extend({ noConflict: function(E) { l.$ = p; if (E) { l.jQuery = y } return o }, isFunction: function(E) { return s.call(E) === "[object Function]" }, isArray: function(E) { return s.call(E) === "[object Array]" }, isXMLDoc: function(E) { return E.nodeType === 9 && E.documentElement.nodeName !== "HTML" || !!E.ownerDocument && o.isXMLDoc(E.ownerDocument) }, globalEval: function(G) { if (G && /\S/.test(G)) { var F = document.getElementsByTagName("head")[0] || document.documentElement, E = document.createElement("script"); E.type = "text/javascript"; if (o.support.scriptEval) { E.appendChild(document.createTextNode(G)) } else { E.text = G } F.insertBefore(E, F.firstChild); F.removeChild(E) } }, nodeName: function(F, E) { return F.nodeName && F.nodeName.toUpperCase() == E.toUpperCase() }, each: function(G, K, F) { var E, H = 0, I = G.length; if (F) { if (I === g) { for (E in G) { if (K.apply(G[E], F) === false) { break } } } else { for (; H < I; ) { if (K.apply(G[H++], F) === false) { break } } } } else { if (I === g) { for (E in G) { if (K.call(G[E], E, G[E]) === false) { break } } } else { for (var J = G[0]; H < I && K.call(J, H, J) !== false; J = G[++H]) { } } } return G }, prop: function(H, I, G, F, E) { if (o.isFunction(I)) { I = I.call(H, F) } return typeof I === "number" && G == "curCSS" && !b.test(E) ? I + "px" : I }, className: { add: function(E, F) { o.each((F || "").split(/\s+/), function(G, H) { if (E.nodeType == 1 && !o.className.has(E.className, H)) { E.className += (E.className ? " " : "") + H } }) }, remove: function(E, F) { if (E.nodeType == 1) { E.className = F !== g ? o.grep(E.className.split(/\s+/), function(G) { return !o.className.has(F, G) }).join(" ") : "" } }, has: function(F, E) { return F && o.inArray(E, (F.className || F).toString().split(/\s+/)) > -1 } }, swap: function(H, G, I) { var E = {}; for (var F in G) { E[F] = H.style[F]; H.style[F] = G[F] } I.call(H); for (var F in G) { H.style[F] = E[F] } }, css: function(H, F, J, E) { if (F == "width" || F == "height") { var L, G = { position: "absolute", visibility: "hidden", display: "block" }, K = F == "width" ? ["Left", "Right"] : ["Top", "Bottom"]; function I() { L = F == "width" ? H.offsetWidth : H.offsetHeight; if (E === "border") { return } o.each(K, function() { if (!E) { L -= parseFloat(o.curCSS(H, "padding" + this, true)) || 0 } if (E === "margin") { L += parseFloat(o.curCSS(H, "margin" + this, true)) || 0 } else { L -= parseFloat(o.curCSS(H, "border" + this + "Width", true)) || 0 } }) } if (H.offsetWidth !== 0) { I() } else { o.swap(H, G, I) } return Math.max(0, Math.round(L)) } return o.curCSS(H, F, J) }, curCSS: function(I, F, G) { var L, E = I.style; if (F == "opacity" && !o.support.opacity) { L = o.attr(E, "opacity"); return L == "" ? "1" : L } if (F.match(/float/i)) { F = w } if (!G && E && E[F]) { L = E[F] } else { if (q.getComputedStyle) { if (F.match(/float/i)) { F = "float" } F = F.replace(/([A-Z])/g, "-$1").toLowerCase(); var M = q.getComputedStyle(I, null); if (M) { L = M.getPropertyValue(F) } if (F == "opacity" && L == "") { L = "1" } } else { if (I.currentStyle) { var J = F.replace(/\-(\w)/g, function(N, O) { return O.toUpperCase() }); L = I.currentStyle[F] || I.currentStyle[J]; if (!/^\d+(px)?$/i.test(L) && /^\d/.test(L)) { var H = E.left, K = I.runtimeStyle.left; I.runtimeStyle.left = I.currentStyle.left; E.left = L || 0; L = E.pixelLeft + "px"; E.left = H; I.runtimeStyle.left = K } } } } return L }, clean: function(F, K, I) { K = K || document; if (typeof K.createElement === "undefined") { K = K.ownerDocument || K[0] && K[0].ownerDocument || document } if (!I && F.length === 1 && typeof F[0] === "string") { var H = /^<(\w+)\s*\/?>$/.exec(F[0]); if (H) { return [K.createElement(H[1])] } } var G = [], E = [], L = K.createElement("div"); o.each(F, function(P, S) { if (typeof S === "number") { S += "" } if (!S) { return } if (typeof S === "string") { S = S.replace(/(<(\w+)[^>]*?)\/>/g, function(U, V, T) { return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? U : V + "></" + T + ">" }); var O = S.replace(/^\s+/, "").substring(0, 10).toLowerCase(); var Q = !O.indexOf("<opt") && [1, "<select multiple='multiple'>", "</select>"] || !O.indexOf("<leg") && [1, "<fieldset>", "</fieldset>"] || O.match(/^<(thead|tbody|tfoot|colg|cap)/) && [1, "<table>", "</table>"] || !O.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] || (!O.indexOf("<td") || !O.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] || !O.indexOf("<col") && [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"] || !o.support.htmlSerialize && [1, "div<div>", "</div>"] || [0, "", ""]; L.innerHTML = Q[1] + S + Q[2]; while (Q[0]--) { L = L.lastChild } if (!o.support.tbody) { var R = /<tbody/i.test(S), N = !O.indexOf("<table") && !R ? L.firstChild && L.firstChild.childNodes : Q[1] == "<table>" && !R ? L.childNodes : []; for (var M = N.length - 1; M >= 0; --M) { if (o.nodeName(N[M], "tbody") && !N[M].childNodes.length) { N[M].parentNode.removeChild(N[M]) } } } if (!o.support.leadingWhitespace && /^\s/.test(S)) { L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]), L.firstChild) } S = o.makeArray(L.childNodes) } if (S.nodeType) { G.push(S) } else { G = o.merge(G, S) } }); if (I) { for (var J = 0; G[J]; J++) { if (o.nodeName(G[J], "script") && (!G[J].type || G[J].type.toLowerCase() === "text/javascript")) { E.push(G[J].parentNode ? G[J].parentNode.removeChild(G[J]) : G[J]) } else { if (G[J].nodeType === 1) { G.splice.apply(G, [J + 1, 0].concat(o.makeArray(G[J].getElementsByTagName("script")))) } I.appendChild(G[J]) } } return E } return G }, attr: function(J, G, K) { if (!J || J.nodeType == 3 || J.nodeType == 8) { return g } var H = !o.isXMLDoc(J), L = K !== g; G = H && o.props[G] || G; if (J.tagName) { var F = /href|src|style/.test(G); if (G == "selected" && J.parentNode) { J.parentNode.selectedIndex } if (G in J && H && !F) { if (L) { if (G == "type" && o.nodeName(J, "input") && J.parentNode) { throw "type property can't be changed" } J[G] = K } if (o.nodeName(J, "form") && J.getAttributeNode(G)) { return J.getAttributeNode(G).nodeValue } if (G == "tabIndex") { var I = J.getAttributeNode("tabIndex"); return I && I.specified ? I.value : J.nodeName.match(/(button|input|object|select|textarea)/i) ? 0 : J.nodeName.match(/^(a|area)$/i) && J.href ? 0 : g } return J[G] } if (!o.support.style && H && G == "style") { return o.attr(J.style, "cssText", K) } if (L) { J.setAttribute(G, "" + K) } var E = !o.support.hrefNormalized && H && F ? J.getAttribute(G, 2) : J.getAttribute(G); return E === null ? g : E } if (!o.support.opacity && G == "opacity") { if (L) { J.zoom = 1; J.filter = (J.filter || "").replace(/alpha\([^)]*\)/, "") + (parseInt(K) + "" == "NaN" ? "" : "alpha(opacity=" + K * 100 + ")") } return J.filter && J.filter.indexOf("opacity=") >= 0 ? (parseFloat(J.filter.match(/opacity=([^)]*)/)[1]) / 100) + "" : "" } G = G.replace(/-([a-z])/ig, function(M, N) { return N.toUpperCase() }); if (L) { J[G] = K } return J[G] }, trim: function(E) { return (E || "").replace(/^\s+|\s+$/g, "") }, makeArray: function(G) { var E = []; if (G != null) { var F = G.length; if (F == null || typeof G === "string" || o.isFunction(G) || G.setInterval) { E[0] = G } else { while (F) { E[--F] = G[F] } } } return E }, inArray: function(G, H) { for (var E = 0, F = H.length; E < F; E++) { if (H[E] === G) { return E } } return -1 }, merge: function(H, E) { var F = 0, G, I = H.length; if (!o.support.getAll) { while ((G = E[F++]) != null) { if (G.nodeType != 8) { H[I++] = G } } } else { while ((G = E[F++]) != null) { H[I++] = G } } return H }, unique: function(K) { var F = [], E = {}; try { for (var G = 0, H = K.length; G < H; G++) { var J = o.data(K[G]); if (!E[J]) { E[J] = true; F.push(K[G]) } } } catch (I) { F = K } return F }, grep: function(F, J, E) { var G = []; for (var H = 0, I = F.length; H < I; H++) { if (!E != !J(F[H], H)) { G.push(F[H]) } } return G }, map: function(E, J) { var F = []; for (var G = 0, H = E.length; G < H; G++) { var I = J(E[G], G); if (I != null) { F[F.length] = I } } return F.concat.apply([], F) } }); var C = navigator.userAgent.toLowerCase(); o.browser = { version: (C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [0, "0"])[1], safari: /webkit/.test(C), opera: /opera/.test(C), msie: /msie/.test(C) && !/opera/.test(C), mozilla: /mozilla/.test(C) && !/(compatible|webkit)/.test(C) }; o.each({ parent: function(E) { return E.parentNode }, parents: function(E) { return o.dir(E, "parentNode") }, next: function(E) { return o.nth(E, 2, "nextSibling") }, prev: function(E) { return o.nth(E, 2, "previousSibling") }, nextAll: function(E) { return o.dir(E, "nextSibling") }, prevAll: function(E) { return o.dir(E, "previousSibling") }, siblings: function(E) { return o.sibling(E.parentNode.firstChild, E) }, children: function(E) { return o.sibling(E.firstChild) }, contents: function(E) { return o.nodeName(E, "iframe") ? E.contentDocument || E.contentWindow.document : o.makeArray(E.childNodes) } }, function(E, F) { o.fn[E] = function(G) { var H = o.map(this, F); if (G && typeof G == "string") { H = o.multiFilter(G, H) } return this.pushStack(o.unique(H), E, G) } }); o.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function(E, F) { o.fn[E] = function(G) { var J = [], L = o(G); for (var K = 0, H = L.length; K < H; K++) { var I = (K > 0 ? this.clone(true) : this).get(); o.fn[F].apply(o(L[K]), I); J = J.concat(I) } return this.pushStack(J, E, G) } }); o.each({ removeAttr: function(E) { o.attr(this, E, ""); if (this.nodeType == 1) { this.removeAttribute(E) } }, addClass: function(E) { o.className.add(this, E) }, removeClass: function(E) { o.className.remove(this, E) }, toggleClass: function(F, E) { if (typeof E !== "boolean") { E = !o.className.has(this, F) } o.className[E ? "add" : "remove"](this, F) }, remove: function(E) { if (!E || o.filter(E, [this]).length) { o("*", this).add([this]).each(function() { o.event.remove(this); o.removeData(this) }); if (this.parentNode) { this.parentNode.removeChild(this) } } }, empty: function() { o(this).children().remove(); while (this.firstChild) { this.removeChild(this.firstChild) } } }, function(E, F) { o.fn[E] = function() { return this.each(F, arguments) } }); function j(E, F) { return E[0] && parseInt(o.curCSS(E[0], F, true), 10) || 0 } var h = "jQuery" + e(), v = 0, A = {}; o.extend({ cache: {}, data: function(F, E, G) { F = F == l ? A : F; var H = F[h]; if (!H) { H = F[h] = ++v } if (E && !o.cache[H]) { o.cache[H] = {} } if (G !== g) { o.cache[H][E] = G } return E ? o.cache[H][E] : H }, removeData: function(F, E) { F = F == l ? A : F; var H = F[h]; if (E) { if (o.cache[H]) { delete o.cache[H][E]; E = ""; for (E in o.cache[H]) { break } if (!E) { o.removeData(F) } } } else { try { delete F[h] } catch (G) { if (F.removeAttribute) { F.removeAttribute(h) } } delete o.cache[H] } }, queue: function(F, E, H) { if (F) { E = (E || "fx") + "queue"; var G = o.data(F, E); if (!G || o.isArray(H)) { G = o.data(F, E, o.makeArray(H)) } else { if (H) { G.push(H) } } } return G }, dequeue: function(H, G) { var E = o.queue(H, G), F = E.shift(); if (!G || G === "fx") { F = E[0] } if (F !== g) { F.call(H) } } }); o.fn.extend({ data: function(E, G) { var H = E.split("."); H[1] = H[1] ? "." + H[1] : ""; if (G === g) { var F = this.triggerHandler("getData" + H[1] + "!", [H[0]]); if (F === g && this.length) { F = o.data(this[0], E) } return F === g && H[1] ? this.data(H[0]) : F } else { return this.trigger("setData" + H[1] + "!", [H[0], G]).each(function() { o.data(this, E, G) }) } }, removeData: function(E) { return this.each(function() { o.removeData(this, E) }) }, queue: function(E, F) { if (typeof E !== "string") { F = E; E = "fx" } if (F === g) { return o.queue(this[0], E) } return this.each(function() { var G = o.queue(this, E, F); if (E == "fx" && G.length == 1) { G[0].call(this) } }) }, dequeue: function(E) { return this.each(function() { o.dequeue(this, E) }) } });
    /*
    * Sizzle CSS Selector Engine - v0.9.3
    *  Copyright 2009, The Dojo Foundation
    *  Released under the MIT, BSD, and GPL Licenses.
    *  More information: http://sizzlejs.com/
    */
    (function() { var R = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g, L = 0, H = Object.prototype.toString; var F = function(Y, U, ab, ac) { ab = ab || []; U = U || document; if (U.nodeType !== 1 && U.nodeType !== 9) { return [] } if (!Y || typeof Y !== "string") { return ab } var Z = [], W, af, ai, T, ad, V, X = true; R.lastIndex = 0; while ((W = R.exec(Y)) !== null) { Z.push(W[1]); if (W[2]) { V = RegExp.rightContext; break } } if (Z.length > 1 && M.exec(Y)) { if (Z.length === 2 && I.relative[Z[0]]) { af = J(Z[0] + Z[1], U) } else { af = I.relative[Z[0]] ? [U] : F(Z.shift(), U); while (Z.length) { Y = Z.shift(); if (I.relative[Y]) { Y += Z.shift() } af = J(Y, af) } } } else { var ae = ac ? { expr: Z.pop(), set: E(ac)} : F.find(Z.pop(), Z.length === 1 && U.parentNode ? U.parentNode : U, Q(U)); af = F.filter(ae.expr, ae.set); if (Z.length > 0) { ai = E(af) } else { X = false } while (Z.length) { var ah = Z.pop(), ag = ah; if (!I.relative[ah]) { ah = "" } else { ag = Z.pop() } if (ag == null) { ag = U } I.relative[ah](ai, ag, Q(U)) } } if (!ai) { ai = af } if (!ai) { throw "Syntax error, unrecognized expression: " + (ah || Y) } if (H.call(ai) === "[object Array]") { if (!X) { ab.push.apply(ab, ai) } else { if (U.nodeType === 1) { for (var aa = 0; ai[aa] != null; aa++) { if (ai[aa] && (ai[aa] === true || ai[aa].nodeType === 1 && K(U, ai[aa]))) { ab.push(af[aa]) } } } else { for (var aa = 0; ai[aa] != null; aa++) { if (ai[aa] && ai[aa].nodeType === 1) { ab.push(af[aa]) } } } } } else { E(ai, ab) } if (V) { F(V, U, ab, ac); if (G) { hasDuplicate = false; ab.sort(G); if (hasDuplicate) { for (var aa = 1; aa < ab.length; aa++) { if (ab[aa] === ab[aa - 1]) { ab.splice(aa--, 1) } } } } } return ab }; F.matches = function(T, U) { return F(T, null, null, U) }; F.find = function(aa, T, ab) { var Z, X; if (!aa) { return [] } for (var W = 0, V = I.order.length; W < V; W++) { var Y = I.order[W], X; if ((X = I.match[Y].exec(aa))) { var U = RegExp.leftContext; if (U.substr(U.length - 1) !== "\\") { X[1] = (X[1] || "").replace(/\\/g, ""); Z = I.find[Y](X, T, ab); if (Z != null) { aa = aa.replace(I.match[Y], ""); break } } } } if (!Z) { Z = T.getElementsByTagName("*") } return { set: Z, expr: aa} }; F.filter = function(ad, ac, ag, W) { var V = ad, ai = [], aa = ac, Y, T, Z = ac && ac[0] && Q(ac[0]); while (ad && ac.length) { for (var ab in I.filter) { if ((Y = I.match[ab].exec(ad)) != null) { var U = I.filter[ab], ah, af; T = false; if (aa == ai) { ai = [] } if (I.preFilter[ab]) { Y = I.preFilter[ab](Y, aa, ag, ai, W, Z); if (!Y) { T = ah = true } else { if (Y === true) { continue } } } if (Y) { for (var X = 0; (af = aa[X]) != null; X++) { if (af) { ah = U(af, Y, X, aa); var ae = W ^ !!ah; if (ag && ah != null) { if (ae) { T = true } else { aa[X] = false } } else { if (ae) { ai.push(af); T = true } } } } } if (ah !== g) { if (!ag) { aa = ai } ad = ad.replace(I.match[ab], ""); if (!T) { return [] } break } } } if (ad == V) { if (T == null) { throw "Syntax error, unrecognized expression: " + ad } else { break } } V = ad } return aa }; var I = F.selectors = { order: ["ID", "NAME", "TAG"], match: { ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/, ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ }, attrMap: { "class": "className", "for": "htmlFor" }, attrHandle: { href: function(T) { return T.getAttribute("href") } }, relative: { "+": function(aa, T, Z) { var X = typeof T === "string", ab = X && !/\W/.test(T), Y = X && !ab; if (ab && !Z) { T = T.toUpperCase() } for (var W = 0, V = aa.length, U; W < V; W++) { if ((U = aa[W])) { while ((U = U.previousSibling) && U.nodeType !== 1) { } aa[W] = Y || U && U.nodeName === T ? U || false : U === T } } if (Y) { F.filter(T, aa, true) } }, ">": function(Z, U, aa) { var X = typeof U === "string"; if (X && !/\W/.test(U)) { U = aa ? U : U.toUpperCase(); for (var V = 0, T = Z.length; V < T; V++) { var Y = Z[V]; if (Y) { var W = Y.parentNode; Z[V] = W.nodeName === U ? W : false } } } else { for (var V = 0, T = Z.length; V < T; V++) { var Y = Z[V]; if (Y) { Z[V] = X ? Y.parentNode : Y.parentNode === U } } if (X) { F.filter(U, Z, true) } } }, "": function(W, U, Y) { var V = L++, T = S; if (!U.match(/\W/)) { var X = U = Y ? U : U.toUpperCase(); T = P } T("parentNode", U, V, W, X, Y) }, "~": function(W, U, Y) { var V = L++, T = S; if (typeof U === "string" && !U.match(/\W/)) { var X = U = Y ? U : U.toUpperCase(); T = P } T("previousSibling", U, V, W, X, Y) } }, find: { ID: function(U, V, W) { if (typeof V.getElementById !== "undefined" && !W) { var T = V.getElementById(U[1]); return T ? [T] : [] } }, NAME: function(V, Y, Z) { if (typeof Y.getElementsByName !== "undefined") { var U = [], X = Y.getElementsByName(V[1]); for (var W = 0, T = X.length; W < T; W++) { if (X[W].getAttribute("name") === V[1]) { U.push(X[W]) } } return U.length === 0 ? null : U } }, TAG: function(T, U) { return U.getElementsByTagName(T[1]) } }, preFilter: { CLASS: function(W, U, V, T, Z, aa) { W = " " + W[1].replace(/\\/g, "") + " "; if (aa) { return W } for (var X = 0, Y; (Y = U[X]) != null; X++) { if (Y) { if (Z ^ (Y.className && (" " + Y.className + " ").indexOf(W) >= 0)) { if (!V) { T.push(Y) } } else { if (V) { U[X] = false } } } } return false }, ID: function(T) { return T[1].replace(/\\/g, "") }, TAG: function(U, T) { for (var V = 0; T[V] === false; V++) { } return T[V] && Q(T[V]) ? U[1] : U[1].toUpperCase() }, CHILD: function(T) { if (T[1] == "nth") { var U = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2] == "even" && "2n" || T[2] == "odd" && "2n+1" || !/\D/.test(T[2]) && "0n+" + T[2] || T[2]); T[2] = (U[1] + (U[2] || 1)) - 0; T[3] = U[3] - 0 } T[0] = L++; return T }, ATTR: function(X, U, V, T, Y, Z) { var W = X[1].replace(/\\/g, ""); if (!Z && I.attrMap[W]) { X[1] = I.attrMap[W] } if (X[2] === "~=") { X[4] = " " + X[4] + " " } return X }, PSEUDO: function(X, U, V, T, Y) { if (X[1] === "not") { if (X[3].match(R).length > 1 || /^\w/.test(X[3])) { X[3] = F(X[3], null, null, U) } else { var W = F.filter(X[3], U, V, true ^ Y); if (!V) { T.push.apply(T, W) } return false } } else { if (I.match.POS.test(X[0]) || I.match.CHILD.test(X[0])) { return true } } return X }, POS: function(T) { T.unshift(true); return T } }, filters: { enabled: function(T) { return T.disabled === false && T.type !== "hidden" }, disabled: function(T) { return T.disabled === true }, checked: function(T) { return T.checked === true }, selected: function(T) { T.parentNode.selectedIndex; return T.selected === true }, parent: function(T) { return !!T.firstChild }, empty: function(T) { return !T.firstChild }, has: function(V, U, T) { return !!F(T[3], V).length }, header: function(T) { return /h\d/i.test(T.nodeName) }, text: function(T) { return "text" === T.type }, radio: function(T) { return "radio" === T.type }, checkbox: function(T) { return "checkbox" === T.type }, file: function(T) { return "file" === T.type }, password: function(T) { return "password" === T.type }, submit: function(T) { return "submit" === T.type }, image: function(T) { return "image" === T.type }, reset: function(T) { return "reset" === T.type }, button: function(T) { return "button" === T.type || T.nodeName.toUpperCase() === "BUTTON" }, input: function(T) { return /input|select|textarea|button/i.test(T.nodeName) } }, setFilters: { first: function(U, T) { return T === 0 }, last: function(V, U, T, W) { return U === W.length - 1 }, even: function(U, T) { return T % 2 === 0 }, odd: function(U, T) { return T % 2 === 1 }, lt: function(V, U, T) { return U < T[3] - 0 }, gt: function(V, U, T) { return U > T[3] - 0 }, nth: function(V, U, T) { return T[3] - 0 == U }, eq: function(V, U, T) { return T[3] - 0 == U } }, filter: { PSEUDO: function(Z, V, W, aa) { var U = V[1], X = I.filters[U]; if (X) { return X(Z, W, V, aa) } else { if (U === "contains") { return (Z.textContent || Z.innerText || "").indexOf(V[3]) >= 0 } else { if (U === "not") { var Y = V[3]; for (var W = 0, T = Y.length; W < T; W++) { if (Y[W] === Z) { return false } } return true } } } }, CHILD: function(T, W) { var Z = W[1], U = T; switch (Z) { case "only": case "first": while (U = U.previousSibling) { if (U.nodeType === 1) { return false } } if (Z == "first") { return true } U = T; case "last": while (U = U.nextSibling) { if (U.nodeType === 1) { return false } } return true; case "nth": var V = W[2], ac = W[3]; if (V == 1 && ac == 0) { return true } var Y = W[0], ab = T.parentNode; if (ab && (ab.sizcache !== Y || !T.nodeIndex)) { var X = 0; for (U = ab.firstChild; U; U = U.nextSibling) { if (U.nodeType === 1) { U.nodeIndex = ++X } } ab.sizcache = Y } var aa = T.nodeIndex - ac; if (V == 0) { return aa == 0 } else { return (aa % V == 0 && aa / V >= 0) } } }, ID: function(U, T) { return U.nodeType === 1 && U.getAttribute("id") === T }, TAG: function(U, T) { return (T === "*" && U.nodeType === 1) || U.nodeName === T }, CLASS: function(U, T) { return (" " + (U.className || U.getAttribute("class")) + " ").indexOf(T) > -1 }, ATTR: function(Y, W) { var V = W[1], T = I.attrHandle[V] ? I.attrHandle[V](Y) : Y[V] != null ? Y[V] : Y.getAttribute(V), Z = T + "", X = W[2], U = W[4]; return T == null ? X === "!=" : X === "=" ? Z === U : X === "*=" ? Z.indexOf(U) >= 0 : X === "~=" ? (" " + Z + " ").indexOf(U) >= 0 : !U ? Z && T !== false : X === "!=" ? Z != U : X === "^=" ? Z.indexOf(U) === 0 : X === "$=" ? Z.substr(Z.length - U.length) === U : X === "|=" ? Z === U || Z.substr(0, U.length + 1) === U + "-" : false }, POS: function(X, U, V, Y) { var T = U[2], W = I.setFilters[T]; if (W) { return W(X, V, U, Y) } } } }; var M = I.match.POS; for (var O in I.match) { I.match[O] = RegExp(I.match[O].source + /(?![^\[]*\])(?![^\(]*\))/.source) } var E = function(U, T) { U = Array.prototype.slice.call(U); if (T) { T.push.apply(T, U); return T } return U }; try { Array.prototype.slice.call(document.documentElement.childNodes) } catch (N) { E = function(X, W) { var U = W || []; if (H.call(X) === "[object Array]") { Array.prototype.push.apply(U, X) } else { if (typeof X.length === "number") { for (var V = 0, T = X.length; V < T; V++) { U.push(X[V]) } } else { for (var V = 0; X[V]; V++) { U.push(X[V]) } } } return U } } var G; if (document.documentElement.compareDocumentPosition) { G = function(U, T) { var V = U.compareDocumentPosition(T) & 4 ? -1 : U === T ? 0 : 1; if (V === 0) { hasDuplicate = true } return V } } else { if ("sourceIndex" in document.documentElement) { G = function(U, T) { var V = U.sourceIndex - T.sourceIndex; if (V === 0) { hasDuplicate = true } return V } } else { if (document.createRange) { G = function(W, U) { var V = W.ownerDocument.createRange(), T = U.ownerDocument.createRange(); V.selectNode(W); V.collapse(true); T.selectNode(U); T.collapse(true); var X = V.compareBoundaryPoints(Range.START_TO_END, T); if (X === 0) { hasDuplicate = true } return X } } } } (function() { var U = document.createElement("form"), V = "script" + (new Date).getTime(); U.innerHTML = "<input name='" + V + "'/>"; var T = document.documentElement; T.insertBefore(U, T.firstChild); if (!!document.getElementById(V)) { I.find.ID = function(X, Y, Z) { if (typeof Y.getElementById !== "undefined" && !Z) { var W = Y.getElementById(X[1]); return W ? W.id === X[1] || typeof W.getAttributeNode !== "undefined" && W.getAttributeNode("id").nodeValue === X[1] ? [W] : g : [] } }; I.filter.ID = function(Y, W) { var X = typeof Y.getAttributeNode !== "undefined" && Y.getAttributeNode("id"); return Y.nodeType === 1 && X && X.nodeValue === W } } T.removeChild(U) })(); (function() { var T = document.createElement("div"); T.appendChild(document.createComment("")); if (T.getElementsByTagName("*").length > 0) { I.find.TAG = function(U, Y) { var X = Y.getElementsByTagName(U[1]); if (U[1] === "*") { var W = []; for (var V = 0; X[V]; V++) { if (X[V].nodeType === 1) { W.push(X[V]) } } X = W } return X } } T.innerHTML = "<a href='#'></a>"; if (T.firstChild && typeof T.firstChild.getAttribute !== "undefined" && T.firstChild.getAttribute("href") !== "#") { I.attrHandle.href = function(U) { return U.getAttribute("href", 2) } } })(); if (document.querySelectorAll) { (function() { var T = F, U = document.createElement("div"); U.innerHTML = "<p class='TEST'></p>"; if (U.querySelectorAll && U.querySelectorAll(".TEST").length === 0) { return } F = function(Y, X, V, W) { X = X || document; if (!W && X.nodeType === 9 && !Q(X)) { try { return E(X.querySelectorAll(Y), V) } catch (Z) { } } return T(Y, X, V, W) }; F.find = T.find; F.filter = T.filter; F.selectors = T.selectors; F.matches = T.matches })() } if (document.getElementsByClassName && document.documentElement.getElementsByClassName) { (function() { var T = document.createElement("div"); T.innerHTML = "<div class='test e'></div><div class='test'></div>"; if (T.getElementsByClassName("e").length === 0) { return } T.lastChild.className = "e"; if (T.getElementsByClassName("e").length === 1) { return } I.order.splice(1, 0, "CLASS"); I.find.CLASS = function(U, V, W) { if (typeof V.getElementsByClassName !== "undefined" && !W) { return V.getElementsByClassName(U[1]) } } })() } function P(U, Z, Y, ad, aa, ac) { var ab = U == "previousSibling" && !ac; for (var W = 0, V = ad.length; W < V; W++) { var T = ad[W]; if (T) { if (ab && T.nodeType === 1) { T.sizcache = Y; T.sizset = W } T = T[U]; var X = false; while (T) { if (T.sizcache === Y) { X = ad[T.sizset]; break } if (T.nodeType === 1 && !ac) { T.sizcache = Y; T.sizset = W } if (T.nodeName === Z) { X = T; break } T = T[U] } ad[W] = X } } } function S(U, Z, Y, ad, aa, ac) { var ab = U == "previousSibling" && !ac; for (var W = 0, V = ad.length; W < V; W++) { var T = ad[W]; if (T) { if (ab && T.nodeType === 1) { T.sizcache = Y; T.sizset = W } T = T[U]; var X = false; while (T) { if (T.sizcache === Y) { X = ad[T.sizset]; break } if (T.nodeType === 1) { if (!ac) { T.sizcache = Y; T.sizset = W } if (typeof Z !== "string") { if (T === Z) { X = true; break } } else { if (F.filter(Z, [T]).length > 0) { X = T; break } } } T = T[U] } ad[W] = X } } } var K = document.compareDocumentPosition ? function(U, T) { return U.compareDocumentPosition(T) & 16 } : function(U, T) { return U !== T && (U.contains ? U.contains(T) : true) }; var Q = function(T) { return T.nodeType === 9 && T.documentElement.nodeName !== "HTML" || !!T.ownerDocument && Q(T.ownerDocument) }; var J = function(T, aa) { var W = [], X = "", Y, V = aa.nodeType ? [aa] : aa; while ((Y = I.match.PSEUDO.exec(T))) { X += Y[0]; T = T.replace(I.match.PSEUDO, "") } T = I.relative[T] ? T + "*" : T; for (var Z = 0, U = V.length; Z < U; Z++) { F(T, V[Z], W) } return F.filter(X, W) }; o.find = F; o.filter = F.filter; o.expr = F.selectors; o.expr[":"] = o.expr.filters; F.selectors.filters.hidden = function(T) { return T.offsetWidth === 0 || T.offsetHeight === 0 }; F.selectors.filters.visible = function(T) { return T.offsetWidth > 0 || T.offsetHeight > 0 }; F.selectors.filters.animated = function(T) { return o.grep(o.timers, function(U) { return T === U.elem }).length }; o.multiFilter = function(V, T, U) { if (U) { V = ":not(" + V + ")" } return F.matches(V, T) }; o.dir = function(V, U) { var T = [], W = V[U]; while (W && W != document) { if (W.nodeType == 1) { T.push(W) } W = W[U] } return T }; o.nth = function(X, T, V, W) { T = T || 1; var U = 0; for (; X; X = X[V]) { if (X.nodeType == 1 && ++U == T) { break } } return X }; o.sibling = function(V, U) { var T = []; for (; V; V = V.nextSibling) { if (V.nodeType == 1 && V != U) { T.push(V) } } return T }; return; l.Sizzle = F })(); o.event = { add: function(I, F, H, K) { if (I.nodeType == 3 || I.nodeType == 8) { return } if (I.setInterval && I != l) { I = l } if (!H.guid) { H.guid = this.guid++ } if (K !== g) { var G = H; H = this.proxy(G); H.data = K } var E = o.data(I, "events") || o.data(I, "events", {}), J = o.data(I, "handle") || o.data(I, "handle", function() { return typeof o !== "undefined" && !o.event.triggered ? o.event.handle.apply(arguments.callee.elem, arguments) : g }); J.elem = I; o.each(F.split(/\s+/), function(M, N) { var O = N.split("."); N = O.shift(); H.type = O.slice().sort().join("."); var L = E[N]; if (o.event.specialAll[N]) { o.event.specialAll[N].setup.call(I, K, O) } if (!L) { L = E[N] = {}; if (!o.event.special[N] || o.event.special[N].setup.call(I, K, O) === false) { if (I.addEventListener) { I.addEventListener(N, J, false) } else { if (I.attachEvent) { I.attachEvent("on" + N, J) } } } } L[H.guid] = H; o.event.global[N] = true }); I = null }, guid: 1, global: {}, remove: function(K, H, J) { if (K.nodeType == 3 || K.nodeType == 8) { return } var G = o.data(K, "events"), F, E; if (G) { if (H === g || (typeof H === "string" && H.charAt(0) == ".")) { for (var I in G) { this.remove(K, I + (H || "")) } } else { if (H.type) { J = H.handler; H = H.type } o.each(H.split(/\s+/), function(M, O) { var Q = O.split("."); O = Q.shift(); var N = RegExp("(^|\\.)" + Q.slice().sort().join(".*\\.") + "(\\.|$)"); if (G[O]) { if (J) { delete G[O][J.guid] } else { for (var P in G[O]) { if (N.test(G[O][P].type)) { delete G[O][P] } } } if (o.event.specialAll[O]) { o.event.specialAll[O].teardown.call(K, Q) } for (F in G[O]) { break } if (!F) { if (!o.event.special[O] || o.event.special[O].teardown.call(K, Q) === false) { if (K.removeEventListener) { K.removeEventListener(O, o.data(K, "handle"), false) } else { if (K.detachEvent) { K.detachEvent("on" + O, o.data(K, "handle")) } } } F = null; delete G[O] } } }) } for (F in G) { break } if (!F) { var L = o.data(K, "handle"); if (L) { L.elem = null } o.removeData(K, "events"); o.removeData(K, "handle") } } }, trigger: function(I, K, H, E) { var G = I.type || I; if (!E) { I = typeof I === "object" ? I[h] ? I : o.extend(o.Event(G), I) : o.Event(G); if (G.indexOf("!") >= 0) { I.type = G = G.slice(0, -1); I.exclusive = true } if (!H) { I.stopPropagation(); if (this.global[G]) { o.each(o.cache, function() { if (this.events && this.events[G]) { o.event.trigger(I, K, this.handle.elem) } }) } } if (!H || H.nodeType == 3 || H.nodeType == 8) { return g } I.result = g; I.target = H; K = o.makeArray(K); K.unshift(I) } I.currentTarget = H; var J = o.data(H, "handle"); if (J) { J.apply(H, K) } if ((!H[G] || (o.nodeName(H, "a") && G == "click")) && H["on" + G] && H["on" + G].apply(H, K) === false) { I.result = false } if (!E && H[G] && !I.isDefaultPrevented() && !(o.nodeName(H, "a") && G == "click")) { this.triggered = true; try { H[G]() } catch (L) { } } this.triggered = false; if (!I.isPropagationStopped()) { var F = H.parentNode || H.ownerDocument; if (F) { o.event.trigger(I, K, F, true) } } }, handle: function(K) { var J, E; K = arguments[0] = o.event.fix(K || l.event); K.currentTarget = this; var L = K.type.split("."); K.type = L.shift(); J = !L.length && !K.exclusive; var I = RegExp("(^|\\.)" + L.slice().sort().join(".*\\.") + "(\\.|$)"); E = (o.data(this, "events") || {})[K.type]; for (var G in E) { var H = E[G]; if (J || I.test(H.type)) { K.handler = H; K.data = H.data; var F = H.apply(this, arguments); if (F !== g) { K.result = F; if (F === false) { K.preventDefault(); K.stopPropagation() } } if (K.isImmediatePropagationStopped()) { break } } } }, props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), fix: function(H) { if (H[h]) { return H } var F = H; H = o.Event(F); for (var G = this.props.length, J; G; ) { J = this.props[--G]; H[J] = F[J] } if (!H.target) { H.target = H.srcElement || document } if (H.target.nodeType == 3) { H.target = H.target.parentNode } if (!H.relatedTarget && H.fromElement) { H.relatedTarget = H.fromElement == H.target ? H.toElement : H.fromElement } if (H.pageX == null && H.clientX != null) { var I = document.documentElement, E = document.body; H.pageX = H.clientX + (I && I.scrollLeft || E && E.scrollLeft || 0) - (I.clientLeft || 0); H.pageY = H.clientY + (I && I.scrollTop || E && E.scrollTop || 0) - (I.clientTop || 0) } if (!H.which && ((H.charCode || H.charCode === 0) ? H.charCode : H.keyCode)) { H.which = H.charCode || H.keyCode } if (!H.metaKey && H.ctrlKey) { H.metaKey = H.ctrlKey } if (!H.which && H.button) { H.which = (H.button & 1 ? 1 : (H.button & 2 ? 3 : (H.button & 4 ? 2 : 0))) } return H }, proxy: function(F, E) { E = E || function() { return F.apply(this, arguments) }; E.guid = F.guid = F.guid || E.guid || this.guid++; return E }, special: { ready: { setup: B, teardown: function() { } } }, specialAll: { live: { setup: function(E, F) { o.event.add(this, F[0], c) }, teardown: function(G) { if (G.length) { var E = 0, F = RegExp("(^|\\.)" + G[0] + "(\\.|$)"); o.each((o.data(this, "events").live || {}), function() { if (F.test(this.type)) { E++ } }); if (E < 1) { o.event.remove(this, G[0], c) } } } }} }; o.Event = function(E) { if (!this.preventDefault) { return new o.Event(E) } if (E && E.type) { this.originalEvent = E; this.type = E.type } else { this.type = E } this.timeStamp = e(); this[h] = true }; function k() { return false } function u() { return true } o.Event.prototype = { preventDefault: function() { this.isDefaultPrevented = u; var E = this.originalEvent; if (!E) { return } if (E.preventDefault) { E.preventDefault() } E.returnValue = false }, stopPropagation: function() { this.isPropagationStopped = u; var E = this.originalEvent; if (!E) { return } if (E.stopPropagation) { E.stopPropagation() } E.cancelBubble = true }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = u; this.stopPropagation() }, isDefaultPrevented: k, isPropagationStopped: k, isImmediatePropagationStopped: k }; var a = function(F) { var E = F.relatedTarget; while (E && E != this) { try { E = E.parentNode } catch (G) { E = this } } if (E != this) { F.type = F.data; o.event.handle.apply(this, arguments) } }; o.each({ mouseover: "mouseenter", mouseout: "mouseleave" }, function(F, E) { o.event.special[E] = { setup: function() { o.event.add(this, F, a, E) }, teardown: function() { o.event.remove(this, F, a) } } }); o.fn.extend({ bind: function(F, G, E) { return F == "unload" ? this.one(F, G, E) : this.each(function() { o.event.add(this, F, E || G, E && G) }) }, one: function(G, H, F) { var E = o.event.proxy(F || H, function(I) { o(this).unbind(I, E); return (F || H).apply(this, arguments) }); return this.each(function() { o.event.add(this, G, E, F && H) }) }, unbind: function(F, E) { return this.each(function() { o.event.remove(this, F, E) }) }, trigger: function(E, F) { return this.each(function() { o.event.trigger(E, F, this) }) }, triggerHandler: function(E, G) { if (this[0]) { var F = o.Event(E); F.preventDefault(); F.stopPropagation(); o.event.trigger(F, G, this[0]); return F.result } }, toggle: function(G) { var E = arguments, F = 1; while (F < E.length) { o.event.proxy(G, E[F++]) } return this.click(o.event.proxy(G, function(H) { this.lastToggle = (this.lastToggle || 0) % F; H.preventDefault(); return E[this.lastToggle++].apply(this, arguments) || false })) }, hover: function(E, F) { return this.mouseenter(E).mouseleave(F) }, ready: function(E) { B(); if (o.isReady) { E.call(document, o) } else { o.readyList.push(E) } return this }, live: function(G, F) { var E = o.event.proxy(F); E.guid += this.selector + G; o(document).bind(i(G, this.selector), this.selector, E); return this }, die: function(F, E) { o(document).unbind(i(F, this.selector), E ? { guid: E.guid + this.selector + F} : null); return this } }); function c(H) { var E = RegExp("(^|\\.)" + H.type + "(\\.|$)"), G = true, F = []; o.each(o.data(this, "events").live || [], function(I, J) { if (E.test(J.type)) { var K = o(H.target).closest(J.data)[0]; if (K) { F.push({ elem: K, fn: J }) } } }); F.sort(function(J, I) { return o.data(J.elem, "closest") - o.data(I.elem, "closest") }); o.each(F, function() { if (this.fn.call(this.elem, H, this.fn.data) === false) { return (G = false) } }); return G } function i(F, E) { return ["live", F, E.replace(/\./g, "`").replace(/ /g, "|")].join(".") } o.extend({ isReady: false, readyList: [], ready: function() { if (!o.isReady) { o.isReady = true; if (o.readyList) { o.each(o.readyList, function() { this.call(document, o) }); o.readyList = null } o(document).triggerHandler("ready") } } }); var x = false; function B() { if (x) { return } x = true; if (document.addEventListener) { document.addEventListener("DOMContentLoaded", function() { document.removeEventListener("DOMContentLoaded", arguments.callee, false); o.ready() }, false) } else { if (document.attachEvent) { document.attachEvent("onreadystatechange", function() { if (document.readyState === "complete") { document.detachEvent("onreadystatechange", arguments.callee); o.ready() } }); if (document.documentElement.doScroll && l == l.top) { (function() { if (o.isReady) { return } try { document.documentElement.doScroll("left") } catch (E) { setTimeout(arguments.callee, 0); return } o.ready() })() } } } o.event.add(l, "load", o.ready) } o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","), function(F, E) { o.fn[E] = function(G) { return G ? this.bind(E, G) : this.trigger(E) } }); o(l).bind("unload", function() { for (var E in o.cache) { if (E != 1 && o.cache[E].handle) { o.event.remove(o.cache[E].handle.elem) } } }); (function() { o.support = {}; var F = document.documentElement, G = document.createElement("script"), K = document.createElement("div"), J = "script" + (new Date).getTime(); K.style.display = "none"; K.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>'; var H = K.getElementsByTagName("*"), E = K.getElementsByTagName("a")[0]; if (!H || !H.length || !E) { return } o.support = { leadingWhitespace: K.firstChild.nodeType == 3, tbody: !K.getElementsByTagName("tbody").length, objectAll: !!K.getElementsByTagName("object")[0].getElementsByTagName("*").length, htmlSerialize: !!K.getElementsByTagName("link").length, style: /red/.test(E.getAttribute("style")), hrefNormalized: E.getAttribute("href") === "/a", opacity: E.style.opacity === "0.5", cssFloat: !!E.style.cssFloat, scriptEval: false, noCloneEvent: true, boxModel: null }; G.type = "text/javascript"; try { G.appendChild(document.createTextNode("window." + J + "=1;")) } catch (I) { } F.insertBefore(G, F.firstChild); if (l[J]) { o.support.scriptEval = true; delete l[J] } F.removeChild(G); if (K.attachEvent && K.fireEvent) { K.attachEvent("onclick", function() { o.support.noCloneEvent = false; K.detachEvent("onclick", arguments.callee) }); K.cloneNode(true).fireEvent("onclick") } o(function() { var L = document.createElement("div"); L.style.width = L.style.paddingLeft = "1px"; document.body.appendChild(L); o.boxModel = o.support.boxModel = L.offsetWidth === 2; document.body.removeChild(L).style.display = "none" }) })(); var w = o.support.cssFloat ? "cssFloat" : "styleFloat"; o.props = { "for": "htmlFor", "class": "className", "float": w, cssFloat: w, styleFloat: w, readonly: "readOnly", maxlength: "maxLength", cellspacing: "cellSpacing", rowspan: "rowSpan", tabindex: "tabIndex" }; o.fn.extend({ _load: o.fn.load, load: function(G, J, K) { if (typeof G !== "string") { return this._load(G) } var I = G.indexOf(" "); if (I >= 0) { var E = G.slice(I, G.length); G = G.slice(0, I) } var H = "GET"; if (J) { if (o.isFunction(J)) { K = J; J = null } else { if (typeof J === "object") { J = o.param(J); H = "POST" } } } var F = this; o.ajax({ url: G, type: H, dataType: "html", data: J, complete: function(M, L) { if (L == "success" || L == "notmodified") { F.html(E ? o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g, "")).find(E) : M.responseText) } if (K) { F.each(K, [M.responseText, L, M]) } } }); return this }, serialize: function() { return o.param(this.serializeArray()) }, serializeArray: function() { return this.map(function() { return this.elements ? o.makeArray(this.elements) : this }).filter(function() { return this.name && !this.disabled && (this.checked || /select|textarea/i.test(this.nodeName) || /text|hidden|password|search/i.test(this.type)) }).map(function(E, F) { var G = o(this).val(); return G == null ? null : o.isArray(G) ? o.map(G, function(I, H) { return { name: F.name, value: I} }) : { name: F.name, value: G} }).get() } }); o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(E, F) { o.fn[F] = function(G) { return this.bind(F, G) } }); var r = e(); o.extend({ get: function(E, G, H, F) { if (o.isFunction(G)) { H = G; G = null } return o.ajax({ type: "GET", url: E, data: G, success: H, dataType: F }) }, getScript: function(E, F) { return o.get(E, null, F, "script") }, getJSON: function(E, F, G) { return o.get(E, F, G, "json") }, post: function(E, G, H, F) { if (o.isFunction(G)) { H = G; G = {} } return o.ajax({ type: "POST", url: E, data: G, success: H, dataType: F }) }, ajaxSetup: function(E) { o.extend(o.ajaxSettings, E) }, ajaxSettings: { url: location.href, global: true, type: "GET", contentType: "application/x-www-form-urlencoded", processData: true, async: true, xhr: function() { return l.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest() }, accepts: { xml: "application/xml, text/xml", html: "text/html", script: "text/javascript, application/javascript", json: "application/json, text/javascript", text: "text/plain", _default: "*/*"} }, lastModified: {}, ajax: function(M) { M = o.extend(true, M, o.extend(true, {}, o.ajaxSettings, M)); var W, F = /=\?(&|$)/g, R, V, G = M.type.toUpperCase(); if (M.data && M.processData && typeof M.data !== "string") { M.data = o.param(M.data) } if (M.dataType == "jsonp") { if (G == "GET") { if (!M.url.match(F)) { M.url += (M.url.match(/\?/) ? "&" : "?") + (M.jsonp || "callback") + "=?" } } else { if (!M.data || !M.data.match(F)) { M.data = (M.data ? M.data + "&" : "") + (M.jsonp || "callback") + "=?" } } M.dataType = "json" } if (M.dataType == "json" && (M.data && M.data.match(F) || M.url.match(F))) { W = "jsonp" + r++; if (M.data) { M.data = (M.data + "").replace(F, "=" + W + "$1") } M.url = M.url.replace(F, "=" + W + "$1"); M.dataType = "script"; l[W] = function(X) { V = X; I(); L(); l[W] = g; try { delete l[W] } catch (Y) { } if (H) { H.removeChild(T) } } } if (M.dataType == "script" && M.cache == null) { M.cache = false } if (M.cache === false && G == "GET") { var E = e(); var U = M.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + E + "$2"); M.url = U + ((U == M.url) ? (M.url.match(/\?/) ? "&" : "?") + "_=" + E : "") } if (M.data && G == "GET") { M.url += (M.url.match(/\?/) ? "&" : "?") + M.data; M.data = null } if (M.global && !o.active++) { o.event.trigger("ajaxStart") } var Q = /^(\w+:)?\/\/([^\/?#]+)/.exec(M.url); if (M.dataType == "script" && G == "GET" && Q && (Q[1] && Q[1] != location.protocol || Q[2] != location.host)) { var H = document.getElementsByTagName("head")[0]; var T = document.createElement("script"); T.src = M.url; if (M.scriptCharset) { T.charset = M.scriptCharset } if (!W) { var O = false; T.onload = T.onreadystatechange = function() { if (!O && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")) { O = true; I(); L(); T.onload = T.onreadystatechange = null; H.removeChild(T) } } } H.appendChild(T); return g } var K = false; var J = M.xhr(); if (M.username) { J.open(G, M.url, M.async, M.username, M.password) } else { J.open(G, M.url, M.async) } try { if (M.data) { J.setRequestHeader("Content-Type", M.contentType) } if (M.ifModified) { J.setRequestHeader("If-Modified-Since", o.lastModified[M.url] || "Thu, 01 Jan 1970 00:00:00 GMT") } J.setRequestHeader("X-Requested-With", "XMLHttpRequest"); J.setRequestHeader("Accept", M.dataType && M.accepts[M.dataType] ? M.accepts[M.dataType] + ", */*" : M.accepts._default) } catch (S) { } if (M.beforeSend && M.beforeSend(J, M) === false) { if (M.global && ! --o.active) { o.event.trigger("ajaxStop") } J.abort(); return false } if (M.global) { o.event.trigger("ajaxSend", [J, M]) } var N = function(X) { if (J.readyState == 0) { if (P) { clearInterval(P); P = null; if (M.global && ! --o.active) { o.event.trigger("ajaxStop") } } } else { if (!K && J && (J.readyState == 4 || X == "timeout")) { K = true; if (P) { clearInterval(P); P = null } R = X == "timeout" ? "timeout" : !o.httpSuccess(J) ? "error" : M.ifModified && o.httpNotModified(J, M.url) ? "notmodified" : "success"; if (R == "success") { try { V = o.httpData(J, M.dataType, M) } catch (Z) { R = "parsererror" } } if (R == "success") { var Y; try { Y = J.getResponseHeader("Last-Modified") } catch (Z) { } if (M.ifModified && Y) { o.lastModified[M.url] = Y } if (!W) { I() } } else { o.handleError(M, J, R) } L(); if (X) { J.abort() } if (M.async) { J = null } } } }; if (M.async) { var P = setInterval(N, 13); if (M.timeout > 0) { setTimeout(function() { if (J && !K) { N("timeout") } }, M.timeout) } } try { J.send(M.data) } catch (S) { o.handleError(M, J, null, S) } if (!M.async) { N() } function I() { if (M.success) { M.success(V, R) } if (M.global) { o.event.trigger("ajaxSuccess", [J, M]) } } function L() { if (M.complete) { M.complete(J, R) } if (M.global) { o.event.trigger("ajaxComplete", [J, M]) } if (M.global && ! --o.active) { o.event.trigger("ajaxStop") } } return J }, handleError: function(F, H, E, G) { if (F.error) { F.error(H, E, G) } if (F.global) { o.event.trigger("ajaxError", [H, F, G]) } }, active: 0, httpSuccess: function(F) { try { return !F.status && location.protocol == "file:" || (F.status >= 200 && F.status < 300) || F.status == 304 || F.status == 1223 } catch (E) { } return false }, httpNotModified: function(G, E) { try { var H = G.getResponseHeader("Last-Modified"); return G.status == 304 || H == o.lastModified[E] } catch (F) { } return false }, httpData: function(J, H, G) { var F = J.getResponseHeader("content-type"), E = H == "xml" || !H && F && F.indexOf("xml") >= 0, I = E ? J.responseXML : J.responseText; if (E && I.documentElement.tagName == "parsererror") { throw "parsererror" } if (G && G.dataFilter) { I = G.dataFilter(I, H) } if (typeof I === "string") { if (H == "script") { o.globalEval(I) } if (H == "json") { I = l["eval"]("(" + I + ")") } } return I }, param: function(E) { var G = []; function H(I, J) { G[G.length] = encodeURIComponent(I) + "=" + encodeURIComponent(J) } if (o.isArray(E) || E.jquery) { o.each(E, function() { H(this.name, this.value) }) } else { for (var F in E) { if (o.isArray(E[F])) { o.each(E[F], function() { H(F, this) }) } else { H(F, o.isFunction(E[F]) ? E[F]() : E[F]) } } } return G.join("&").replace(/%20/g, "+") } }); var m = {}, n, d = [["height", "marginTop", "marginBottom", "paddingTop", "paddingBottom"], ["width", "marginLeft", "marginRight", "paddingLeft", "paddingRight"], ["opacity"]]; function t(F, E) { var G = {}; o.each(d.concat.apply([], d.slice(0, E)), function() { G[this] = F }); return G } o.fn.extend({ show: function(J, L) { if (J) { return this.animate(t("show", 3), J, L) } else { for (var H = 0, F = this.length; H < F; H++) { var E = o.data(this[H], "olddisplay"); this[H].style.display = E || ""; if (o.css(this[H], "display") === "none") { var G = this[H].tagName, K; if (m[G]) { K = m[G] } else { var I = o("<" + G + " />").appendTo("body"); K = I.css("display"); if (K === "none") { K = "block" } I.remove(); m[G] = K } o.data(this[H], "olddisplay", K) } } for (var H = 0, F = this.length; H < F; H++) { this[H].style.display = o.data(this[H], "olddisplay") || "" } return this } }, hide: function(H, I) { if (H) { return this.animate(t("hide", 3), H, I) } else { for (var G = 0, F = this.length; G < F; G++) { var E = o.data(this[G], "olddisplay"); if (!E && E !== "none") { o.data(this[G], "olddisplay", o.css(this[G], "display")) } } for (var G = 0, F = this.length; G < F; G++) { this[G].style.display = "none" } return this } }, _toggle: o.fn.toggle, toggle: function(G, F) { var E = typeof G === "boolean"; return o.isFunction(G) && o.isFunction(F) ? this._toggle.apply(this, arguments) : G == null || E ? this.each(function() { var H = E ? G : o(this).is(":hidden"); o(this)[H ? "show" : "hide"]() }) : this.animate(t("toggle", 3), G, F) }, fadeTo: function(E, G, F) { return this.animate({ opacity: G }, E, F) }, animate: function(I, F, H, G) { var E = o.speed(F, H, G); return this[E.queue === false ? "each" : "queue"](function() { var K = o.extend({}, E), M, L = this.nodeType == 1 && o(this).is(":hidden"), J = this; for (M in I) { if (I[M] == "hide" && L || I[M] == "show" && !L) { return K.complete.call(this) } if ((M == "height" || M == "width") && this.style) { K.display = o.css(this, "display"); K.overflow = this.style.overflow } } if (K.overflow != null) { this.style.overflow = "hidden" } K.curAnim = o.extend({}, I); o.each(I, function(O, S) { var R = new o.fx(J, K, O); if (/toggle|show|hide/.test(S)) { R[S == "toggle" ? L ? "show" : "hide" : S](I) } else { var Q = S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/), T = R.cur(true) || 0; if (Q) { var N = parseFloat(Q[2]), P = Q[3] || "px"; if (P != "px") { J.style[O] = (N || 1) + P; T = ((N || 1) / R.cur(true)) * T; J.style[O] = T + P } if (Q[1]) { N = ((Q[1] == "-=" ? -1 : 1) * N) + T } R.custom(T, N, P) } else { R.custom(T, S, "") } } }); return true }) }, stop: function(F, E) { var G = o.timers; if (F) { this.queue([]) } this.each(function() { for (var H = G.length - 1; H >= 0; H--) { if (G[H].elem == this) { if (E) { G[H](true) } G.splice(H, 1) } } }); if (!E) { this.dequeue() } return this } }); o.each({ slideDown: t("show", 1), slideUp: t("hide", 1), slideToggle: t("toggle", 1), fadeIn: { opacity: "show" }, fadeOut: { opacity: "hide"} }, function(E, F) { o.fn[E] = function(G, H) { return this.animate(F, G, H) } }); o.extend({ speed: function(G, H, F) { var E = typeof G === "object" ? G : { complete: F || !F && H || o.isFunction(G) && G, duration: G, easing: F && H || H && !o.isFunction(H) && H }; E.duration = o.fx.off ? 0 : typeof E.duration === "number" ? E.duration : o.fx.speeds[E.duration] || o.fx.speeds._default; E.old = E.complete; E.complete = function() { if (E.queue !== false) { o(this).dequeue() } if (o.isFunction(E.old)) { E.old.call(this) } }; return E }, easing: { linear: function(G, H, E, F) { return E + F * G }, swing: function(G, H, E, F) { return ((-Math.cos(G * Math.PI) / 2) + 0.5) * F + E } }, timers: [], fx: function(F, E, G) { this.options = E; this.elem = F; this.prop = G; if (!E.orig) { E.orig = {} } } }); o.fx.prototype = { update: function() { if (this.options.step) { this.options.step.call(this.elem, this.now, this) } (o.fx.step[this.prop] || o.fx.step._default)(this); if ((this.prop == "height" || this.prop == "width") && this.elem.style) { this.elem.style.display = "block" } }, cur: function(F) { if (this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null)) { return this.elem[this.prop] } var E = parseFloat(o.css(this.elem, this.prop, F)); return E && E > -10000 ? E : parseFloat(o.curCSS(this.elem, this.prop)) || 0 }, custom: function(I, H, G) { this.startTime = e(); this.start = I; this.end = H; this.unit = G || this.unit || "px"; this.now = this.start; this.pos = this.state = 0; var E = this; function F(J) { return E.step(J) } F.elem = this.elem; if (F() && o.timers.push(F) && !n) { n = setInterval(function() { var K = o.timers; for (var J = 0; J < K.length; J++) { if (!K[J]()) { K.splice(J--, 1) } } if (!K.length) { clearInterval(n); n = g } }, 13) } }, show: function() { this.options.orig[this.prop] = o.attr(this.elem.style, this.prop); this.options.show = true; this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur()); o(this.elem).show() }, hide: function() { this.options.orig[this.prop] = o.attr(this.elem.style, this.prop); this.options.hide = true; this.custom(this.cur(), 0) }, step: function(H) { var G = e(); if (H || G >= this.options.duration + this.startTime) { this.now = this.end; this.pos = this.state = 1; this.update(); this.options.curAnim[this.prop] = true; var E = true; for (var F in this.options.curAnim) { if (this.options.curAnim[F] !== true) { E = false } } if (E) { if (this.options.display != null) { this.elem.style.overflow = this.options.overflow; this.elem.style.display = this.options.display; if (o.css(this.elem, "display") == "none") { this.elem.style.display = "block" } } if (this.options.hide) { o(this.elem).hide() } if (this.options.hide || this.options.show) { for (var I in this.options.curAnim) { o.attr(this.elem.style, I, this.options.orig[I]) } } this.options.complete.call(this.elem) } return false } else { var J = G - this.startTime; this.state = J / this.options.duration; this.pos = o.easing[this.options.easing || (o.easing.swing ? "swing" : "linear")](this.state, J, 0, 1, this.options.duration); this.now = this.start + ((this.end - this.start) * this.pos); this.update() } return true } }; o.extend(o.fx, { speeds: { slow: 600, fast: 200, _default: 400 }, step: { opacity: function(E) { o.attr(E.elem.style, "opacity", E.now) }, _default: function(E) { if (E.elem.style && E.elem.style[E.prop] != null) { E.elem.style[E.prop] = E.now + E.unit } else { E.elem[E.prop] = E.now } } } }); if (document.documentElement.getBoundingClientRect) { o.fn.offset = function() { if (!this[0]) { return { top: 0, left: 0} } if (this[0] === this[0].ownerDocument.body) { return o.offset.bodyOffset(this[0]) } var G = this[0].getBoundingClientRect(), J = this[0].ownerDocument, F = J.body, E = J.documentElement, L = E.clientTop || F.clientTop || 0, K = E.clientLeft || F.clientLeft || 0, I = G.top + (self.pageYOffset || o.boxModel && E.scrollTop || F.scrollTop) - L, H = G.left + (self.pageXOffset || o.boxModel && E.scrollLeft || F.scrollLeft) - K; return { top: I, left: H} } } else { o.fn.offset = function() { if (!this[0]) { return { top: 0, left: 0} } if (this[0] === this[0].ownerDocument.body) { return o.offset.bodyOffset(this[0]) } o.offset.initialized || o.offset.initialize(); var J = this[0], G = J.offsetParent, F = J, O = J.ownerDocument, M, H = O.documentElement, K = O.body, L = O.defaultView, E = L.getComputedStyle(J, null), N = J.offsetTop, I = J.offsetLeft; while ((J = J.parentNode) && J !== K && J !== H) { M = L.getComputedStyle(J, null); N -= J.scrollTop, I -= J.scrollLeft; if (J === G) { N += J.offsetTop, I += J.offsetLeft; if (o.offset.doesNotAddBorder && !(o.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(J.tagName))) { N += parseInt(M.borderTopWidth, 10) || 0, I += parseInt(M.borderLeftWidth, 10) || 0 } F = G, G = J.offsetParent } if (o.offset.subtractsBorderForOverflowNotVisible && M.overflow !== "visible") { N += parseInt(M.borderTopWidth, 10) || 0, I += parseInt(M.borderLeftWidth, 10) || 0 } E = M } if (E.position === "relative" || E.position === "static") { N += K.offsetTop, I += K.offsetLeft } if (E.position === "fixed") { N += Math.max(H.scrollTop, K.scrollTop), I += Math.max(H.scrollLeft, K.scrollLeft) } return { top: N, left: I} } } o.offset = { initialize: function() { if (this.initialized) { return } var L = document.body, F = document.createElement("div"), H, G, N, I, M, E, J = L.style.marginTop, K = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>'; M = { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" }; for (E in M) { F.style[E] = M[E] } F.innerHTML = K; L.insertBefore(F, L.firstChild); H = F.firstChild, G = H.firstChild, I = H.nextSibling.firstChild.firstChild; this.doesNotAddBorder = (G.offsetTop !== 5); this.doesAddBorderForTableAndCells = (I.offsetTop === 5); H.style.overflow = "hidden", H.style.position = "relative"; this.subtractsBorderForOverflowNotVisible = (G.offsetTop === -5); L.style.marginTop = "1px"; this.doesNotIncludeMarginInBodyOffset = (L.offsetTop === 0); L.style.marginTop = J; L.removeChild(F); this.initialized = true }, bodyOffset: function(E) { o.offset.initialized || o.offset.initialize(); var G = E.offsetTop, F = E.offsetLeft; if (o.offset.doesNotIncludeMarginInBodyOffset) { G += parseInt(o.curCSS(E, "marginTop", true), 10) || 0, F += parseInt(o.curCSS(E, "marginLeft", true), 10) || 0 } return { top: G, left: F} } }; o.fn.extend({ position: function() { var I = 0, H = 0, F; if (this[0]) { var G = this.offsetParent(), J = this.offset(), E = /^body|html$/i.test(G[0].tagName) ? { top: 0, left: 0} : G.offset(); J.top -= j(this, "marginTop"); J.left -= j(this, "marginLeft"); E.top += j(G, "borderTopWidth"); E.left += j(G, "borderLeftWidth"); F = { top: J.top - E.top, left: J.left - E.left} } return F }, offsetParent: function() { var E = this[0].offsetParent || document.body; while (E && (!/^body|html$/i.test(E.tagName) && o.css(E, "position") == "static")) { E = E.offsetParent } return o(E) } }); o.each(["Left", "Top"], function(F, E) { var G = "scroll" + E; o.fn[G] = function(H) { if (!this[0]) { return null } return H !== g ? this.each(function() { this == l || this == document ? l.scrollTo(!F ? H : o(l).scrollLeft(), F ? H : o(l).scrollTop()) : this[G] = H }) : this[0] == l || this[0] == document ? self[F ? "pageYOffset" : "pageXOffset"] || o.boxModel && document.documentElement[G] || document.body[G] : this[0][G] } }); o.each(["Height", "Width"], function(I, G) { var E = I ? "Left" : "Top", H = I ? "Right" : "Bottom", F = G.toLowerCase(); o.fn["inner" + G] = function() { return this[0] ? o.css(this[0], F, false, "padding") : null }; o.fn["outer" + G] = function(K) { return this[0] ? o.css(this[0], F, false, K ? "margin" : "border") : null }; var J = G.toLowerCase(); o.fn[J] = function(K) { return this[0] == l ? document.compatMode == "CSS1Compat" && document.documentElement["client" + G] || document.body["client" + G] : this[0] == document ? Math.max(document.documentElement["client" + G], document.body["scroll" + G], document.documentElement["scroll" + G], document.body["offset" + G], document.documentElement["offset" + G]) : K === g ? (this.length ? o.css(this[0], J) : null) : this.css(J, typeof K === "string" ? K : K + "px") } })
})();

// Build 9.00.7440.8

IS_CHROME = navigator.userAgent.toLowerCase().indexOf("chrome") != -1;
IS_SAFARI = !IS_CHROME && (navigator.userAgent.toLowerCase().indexOf("safari") != -1 || navigator.userAgent.toLowerCase().indexOf("konqueror") != -1);
IS_OPERA = navigator.userAgent.toLowerCase().indexOf("opera") != -1;
IS_GECKO = !IS_SAFARI && !IS_CHROME && navigator.userAgent.toLowerCase().indexOf("gecko") != -1;
if (IS_GECKO) {
    GECKO_VERSION = parseFloat (navigator.userAgent.substr (navigator.userAgent.search ("Firefox") + 8, 3));
}
IS_MAC = navigator.userAgent.toLowerCase().indexOf("macintosh") != -1;
IS_IE = navigator.userAgent.toLowerCase().indexOf ("msie") != -1;
if (IS_IE) {
    IE_VERSION = parseFloat (navigator.userAgent.substr (navigator.userAgent.toLowerCase().search ("msie") + 4, 4));
}
IE_DOCMODE = document.documentMode;
IS_MOBILE = navigator.userAgent.toLowerCase().indexOf ("mobile") != -1;

//For now chrome is handled as firefox (Gecko)
if(IS_GECKO || IS_SAFARI || IS_OPERA || IS_CHROME) {
    // support "innerText"
    HTMLElement.prototype.__defineGetter__("innerText", function() { return this.textContent; });
    HTMLElement.prototype.__defineSetter__("innerText", function($value) { this.textContent = $value; });
    
    Event.prototype.__defineGetter__("srcElement", function() {
        return (this.target.nodeType == Node.ELEMENT_NODE) ? this.target : this.target.parentNode;
    });
    Event.prototype.__defineGetter__("toElement", function() {
        return (this.type == "mouseout") ? this.relatedTarget : (this.type == "mouseover") ? this.srcElement : null;
    });
}
if(typeof XMLDocument === "undefined" && typeof Document !== "undefined") XMLDocument = Document;

Qva = {} 

Qva.binders = {}
Qva.GetBinder = function(id, view) {
    var binder = Qva.binders[id || ""];
    if(!binder && view) {
        binder = new Qva.PageBinding(id);
        binder.View = view;
        if (Qva.Modal && !Qva.Modal.instance) new Qva.Modal();
        
        var def_binder = Qva.GetBinder();
        if(def_binder) {
            binder.Autoview   = def_binder.Autoview;
            binder.Remote     = def_binder.Remote;
            binder.JSON       = def_binder.JSON;
        }
    }
    return binder;
}
Qva.Start = function() {
    function GetDPI() {
        if(screen.deviceXDPI) return screen.deviceXDPI;
        //if(screen.logicalXDPI) return screen.logicalXDPI;
        
        var div = document.createElement("div");
        div.style.cssText = "padding: 0px; position: absolute; width: 1in; visibility: hidden;"
        document.body.appendChild(div);
        var dpi = div.offsetWidth;
        document.body.removeChild(div);
        return dpi;
    }
    Qva.DPI = GetDPI();
    function GetFactor() {
        var div = document.createElement("div");
        div.style.cssText = "border: none; padding: 0px; position: absolute; width: 1000pt; visibility: hidden;"
        document.body.appendChild(div);
        var factor = (300.0 * parseFloat(div.style.width)) / (72.0 * div.offsetWidth);
        document.body.removeChild(div);
        return factor;
    }
    Qva.Factor = GetFactor();
    
    function _Start() {
        if(Qva.Scanner && Qva.Scanner.instance) Qva.Scanner.instance.Start();
        for(var id in Qva.binders) Qva.binders[id].Start();
        if (document.addEventListener) { 
            document.addEventListener ("mouseup", function (event) { Qva.OnMouseUp(event); }, false);
            document.addEventListener ("keyup", function (event) { Qva.OnKeyUp(event); }, false);
            try {
                window.parent.addEventListener ("mouseup", function (event) { Qva.OnMouseUp(event); }, false);
                window.parent.addEventListener ("keyup", function (event) { Qva.OnKeyUp(event); }, false);
            } catch (Err) {}
        } else { 
            document.attachEvent ("onmouseup", function (event) { Qva.OnMouseUp(event); });
            document.attachEvent ("onkeyup", function (event) { Qva.OnKeyUp(event); });
        }
        document.onclick = function () { 
            var binder = null;
            if (Qva.PopupSearch != null) {
                var mgr = Qva.PopupSearch.AvqMgr;
                binder = mgr.PageBinder || Qva.GetBinder(mgr.binderid);
            }
            Qva.HideContextMenu (); 
            Qva.ClosePopupSearch (); 
            Qva.ClosePopupInput (); 
            if (binder) {
                binder.LoadBegin ();
            }
        }
    }
    
    var userid = Qva.ExtractProperty ("userid", null, true);
    var password = Qva.ExtractProperty ("password", null, true);

    if(userid === "" || password === "") {
        Qva.RemainingRetries = parseInt(Qva.ExtractProperty("retry", "3"));
        if(isNaN(Qva.RemainingRetries)) Qva.RemainingRetries = 3;
        
        var first = true;
        var fakePagebinder = {
            'LabelClick': false, 
            'Refresh': function() {
                if(!first) return;
                first = false;
                _Start();
            }
        };
        Qva.Modal.instance.Show(fakePagebinder, Qva.Modal.instance.ScriptPath + 'login.htm?userid=' + escape(userid));
    } else {
        _Start();
    }
}

Qva.AsyncPostPaintMgrQueue = [];
Qva.PopupInput = null;
Qva.ContextMenu = null;
Qva.ContextMenuMgr = null;
Qva.KeepContextMenuAlive = false;
Qva.MgrWithMouseDown = null;
Qva.MgrWithSelectStart = null;
Qva.StartoffsetX = 0;
Qva.StartoffsetY = 0;
Qva.ActiveObject = null;
Qva.SearchableObject = null;
Qva.ActiveElement = null;
Qva.PopupSearch = null;
Qva.KeepPopupSearchAlive = false;
Qva.PendingSearchName = '';
Qva.PendingSearchKeyName = '';
Qva.DragRect = null;
Qva.DragStartX = 0;
Qva.DragStartY = 0;
Qva.DragRectLeft = 0;
Qva.DragRectTop = 0;
Qva.DragRectWidth = 0;
Qva.DragRectHeight = 0;
Qva.LabelClick = true;

Qva.PageBinding = function(id) {
    this.ID = id || "";
    if(Qva.binders[this.ID]) { alert("Need unique binderid"); return; }
    Qva.binders[this.ID] = this;
    
    this.OnUpdateBegin = null;
    this.IsUpdating = false;
    this.HasPendingLoad = false;
    this.PendingNames = [];
    this.ScrollLeftToRemember = 0;
    this.ScrollTopToRemember = 0;
    this.IsPartialLoad = false;
    this.CurrentLoadIsPartial = false;
    this.Enabled = false;
    this.First = true;
    this.Managers = new Array();
    this.Members = {}
    try {
        this.Remote = (parent.qva && parent.qva.Remote) || '/QvAJAXZfc/QvsViewClient.asp';
    } catch (Error) {
        this.Remote = '/QvAJAXZfc/QvsViewClient.asp';
    }
    this.UsePost = true;
    this.JSON = false;
    this.Body = '';
    this.InitialSets = '';
    this.Mark = '';
    this.Stamp = '';
    this.RecursiveReadyLevel = 0;
    this.ShowMessage = Qva.DefaultShowMessage;
    this.OnSessionLost = Qva.DefaultOnSessionLost;
    this.OnUpdateComplete = Qva.NoAction;
    this.OnCreateContextMenu = Qva.DefaultOnCreateContextMenu;
    this.AllowComAgent = true;
    this.InlineStyle = true;
    this.TableLimit = 5000;
    this.Ident = null;
    this.TransientObject = '';
    this.GlobaSearchObject = '';
    this.ToggleSelect = "";
    this.ToggleSelects = null;
    this.TogglePhase = null;
    this.DelaySet = false;
    this.PendingDblClickName = '';
    this.DefaultScope = 'Document';
    this.IsContained = false; //WB used for workbench/webpart objects to prevent minimize/move 
    this.CustomIcons = {}
    
    try {
        var impl = window.document.implementation;
        if (impl && impl.createDocument) {
            var doc = impl.createDocument ("", "", null);
            if (doc.readyState == null) {
                doc.readyState = 1;
                doc.addEventListener("load", function () {
                    doc.readyState = 4;
                    if (typeof doc.onreadystatechange == "function") {
                        doc.onreadystatechange ();
                    }
                }, false);
            }
            this.Doc = doc;
            this.LeftButton = 0;
        } else if (window.ActiveXObject) {
            this.Doc = new ActiveXObject ("Microsoft.XMLDOM");
            this.LeftButton = 1;
        }
    } catch (e) {}
    if (this.Doc == null) throw new Error ("Your browser does not support XmlDocument objects");
}

Qva.PageBinding.prototype.Start = function () {
    this.IsRemote = true;
    this.IsHosted = false;
    if (this.View == null && parent.qva != null) this.View = parent.qva.View;
    if (this.JSON) this.Session = Qva.ExtractProperty ("session", this.Session);
    this.Ident = Qva.ExtractProperty ("ident", this.Ident);
    this.Userid = Qva.ExtractProperty ("userid", this.Userid);
    this.Xuserid = Qva.ExtractProperty ("xuserid", this.Xuserid);
    this.Password = Qva.ExtractProperty ("password", this.Password);
    this.Xpassword = Qva.ExtractProperty ("xpassword", this.Xpassword);
    this.Bookmark = Qva.ExtractProperty ("bookmark", this.Bookmark);
    this.View = Qva.ExtractProperty ("application", this.View);
    this.InitialSelections = Qva.ExtractPropertyArray("select", this.InitialSelections)
//    this.Ticket = Qva.ExtractProperty("ticket", this.Ticket);
    this.Ticket = Qva.ExtractPropertyForDocument("ticket", this.View, this.Ticket);
    this.AsyncServer = Qva.ExtractProperty("server") == "async";
    if (this.AsyncServer) this.AutoViewAppend (null, this.DefaultScope, 'asyncronous');
    this.Host = Qva.ExtractProperty ("host", this.Host);
    if (Qva.Benchmark) {
        this.Benchmark = new Qva.Benchmark();
    }
    this.Url = this.Remote;
    this.Url += (this.Url.indexOf ('?') == -1) ? '?mark=' : '&mark=';
    
    if (window.ActiveXObject && (this.Unicorn || window.location.protocol == "file:")) {
        this.TryAltAgent();
    }
    
    var _this = this;
    document.oncontextmenu = function (event) { return _this.OnContextMenu(event); }
    
    var useragent = "" + window.window.navigator.userAgent;
    var version = parseInt (useragent.substr (useragent.indexOf ('MSIE') + 5, 3));
    this.AutoViewAppend (null, qva.DefaultScope, 'ie6' + (useragent.indexOf ('MSIE') != -1 && version < 7));

    this.LoadBegin();
    // TODO: KeepAliveKicker ();
}

Qva.QueuePostPaintMessage = function (mgr) {
    for (var ix = 0; ix < Qva.AsyncPostPaintMgrQueue.length; ++ ix) {
        if (this.AsyncPostPaintMgrQueue [ix] == mgr) {
            return; // No need for multiple paints
        }
    }
    this.AsyncPostPaintMgrQueue.push (mgr);
    window.setTimeout (avqAsyncPostPaint, 0);
}

function avqAsyncPostPaint () {
    if (Qva.AsyncPostPaintMgrQueue.length == 0) {
        alert ("AsyncPostPaintMgrQueue.length == 0");
        return;
    }
    var mgr = Qva.AsyncPostPaintMgrQueue.shift ();
    mgr.PostPaint ();
}

Qva.MgrGetName = function (elem) {
    while (elem) {
        if (elem.AvqMgr != null) return elem.AvqMgr.Name;
        elem = elem.parentNode;
    }
    return "";
}

function ctrlKeyPressed (event) {
	// ctrlKey valid for windows - IE, Firefox
	// metaKey valid for Mac - Safari, Firefox
	// keyCode 224 for stopping onKeyUp on Firefox for Mac
	// keyCode 91 for stopping onKeyUp on Safari for Mac
	return event.ctrlKey || event.metaKey || event.keyCode == 224 || event.keyCode == 91;
}
Qva.OnMouseUp = function (event) {
    Qva.MgrWithMouseDown = null;
    if (! event) {
        event = window.event;
    }
    if (Qva.MgrWithSelectStart != null) {
        var mgr = Qva.MgrWithSelectStart;
        Qva.MgrWithSelectStart = null;
        var X = event.clientX;
        var Y = event.clientY;
        mgr.SelectEnd (X, Y, ctrlKeyPressed (event));
    } else {
        var elem = event.target;
        if (elem == null) elem = event.srcElement;
        if (Qva.MgrGetName (Qva.PopupSearch) != Qva.MgrGetName (elem)) {
            if (Qva.PopupSearch != null) {
                var binder = Qva.ClosePopupSearch();
                if (binder.Body != '') binder.LoadBegin ();
            }
        }
    }
}

Qva.OnKeyUp = function (event) {
    if (Qva.PopupInput != null) return;
    if (!Qva.LabelClick) return;
    if (! event) {
        event = window.event;
    }
    var srcelement = event.target;
    if (! srcelement) srcelement = event.srcElement;
    if (event.keyCode == 13 && srcelement.tagName == 'INPUT' && srcelement.onchange) {
        srcelement.onchange();
    }
    if (srcelement.tagName == 'INPUT' && srcelement.type == 'text') return;
    if (Qva.SearchableObject) {
        var element = document.getElementById (Qva.SearchableObject);
        if (element && element.AvqMgr) {
            var binder = element.AvqMgr.PageBinder;
            if (binder.ToggleSelect != "" && (event.keyCode == 17 || event.keyCode == 224 || event.keyCode == 91)) {
                var objectName = binder.ToggleSelect;
                if (binder.TogglePhase != null && binder.ToggleSelects.length > 0) {
                    binder.Set (objectName, 'phase', binder.TogglePhase, false);
                }
                binder.TogglePhase = null;
                for (var i = 0; i < binder.ToggleSelects.length; i++) {
                    binder.Set (objectName, 'value', binder.ToggleSelects [i], false);
                }
                binder.ToggleSelects = null;
                binder.ToggleSelect = "";
                binder.LoadBegin ();
            } else if (element.AvqMgr.Searchable) {
                if (Qva.PopupSearch == null && event.keyCode >= 32 && ! ctrlKeyPressed (event)) {
                    var key = event.keyCode;
                    if (key >= 33 && key <= 40) {
                        if (key != 37 && key != 39) {
                            var currentkey;
                            switch (key) {
                            case 33:
                                currentkey = "pgup";
                                break;
                            case 34:
                                currentkey = "pgdn";
                                break;
                            case 35:
                                currentkey = "end";
                                break;
                            case 36:
                                currentkey = "home";
                                break;
                            case 38:
                                currentkey = "up";
                                break;
                            case 40:
                                currentkey = "down";
                                break;
                            }
                            binder.Set (element.AvqMgr.PageName, 'key', currentkey, true);
                        }
                    } else if ((key >= 48 && key <= 57) || (key >= 65 && key <= 90) || (key >= 96 && key <= 107) || key == 109 || key == 111 || key == 187 || key == 189) {
                        Qva.OpenPopupSearch (element);
                        var character;
                        if (key >= 96 && key <= 105) {
                            character = key - 96;
                        } else if (key == 106) {
                            character = "*";
                        } else if (key == 107 || key == 187) {
                            character = "+";
                        } else if (key == 109 || key == 189) {
                            character = "-";
                        } else if (key == 111) {
                            character = "/";
                        } else {
                            character = String.fromCharCode (key).toLowerCase ();
                        }
                        Qva.PopupSearch.value = '*' + character + '*';
                        Qva.SetCursor (Qva.PopupSearch);
                        Qva.Search (element.AvqMgr, Qva.PopupSearch, key);
                    } 
                }
            }
        }
    }
}

Qva.Search = function (mgr, elem, key) {
    Qva.KeepPopupSearchAlive = (elem == Qva.PopupSearch);
    if (mgr.SearchName != "") {
        var binder = mgr.PageBinder || Qva.GetBinder(mgr.binderid);
		if (binder.Enabled) {
			binder.Set (mgr.SearchName, "search", elem.value, true);
		} else {
			Qva.PendingSearchName = mgr.SearchName;
			Qva.PendingSearchValue = elem.value;
		}
	}
}
Qva.CloseSearch = function (mgr, elem, accept, ctrl) {
    Qva.KeepPopupSearchAlive = false;
    var SearchName = mgr.SearchName;
    var currentsearchvalue = elem.value;
    elem.value = "";
    elem.onkeyup = null;
    if (elem == Qva.PopupSearch) mgr.SearchName = null;
    
    var binder = mgr.PageBinder || Qva.GetBinder(mgr.binderid);
    if (Qva.PopupSearch.searchcol != null) {
	    if (accept) binder.Set (SearchName + ":" + Qva.PopupSearch.searchcol, "searchcolumn", currentsearchvalue, true);
    } else {
        if (binder.Enabled) {
		    if (accept) binder.Set (SearchName, "search", currentsearchvalue, false);
		    var cmd;
		    if (accept) {
		        cmd = ctrl ? "ctrlaccept" : "accept";
		    } else {
		        cmd = "abort";
		    }
            binder.Set (SearchName, "closesearch", cmd, true);
        } else {
            Qva.PendingSearchKey = (accept ? "accept" : "abort");
            Qva.PendingSearchKeyName = SearchName;
        }
        var transientname = binder.TransientObject;
        if (transientname == SearchName) {
            binder.CloseTransient ();
        }
    }
}

Qva.OpenPopupSearch = function (elem, param) {
    var mgr = elem.AvqMgr;
    var searchname = elem.Name;
    if (! searchname) {
        searchname = mgr.Name || mgr.PageName;
        if (! searchname) {
            searchname = mgr.ColList [0].Name.split ('.') [1];
        }
    }
    if (searchname == mgr.SearchName && mgr.Search != null) return;
    mgr.SearchName = searchname;
    Qva.PopupSearch = document.createElement ('input');
    Qva.PopupSearch.param = param;
    Qva.PopupSearch.tabIndex = 1;
    Qva.PopupSearch.className = 'avqEdit';
    Qva.PopupSearch.onkeydown = AvqAction_Search_KeyDown;
    Qva.PopupSearch.onkeyup = AvqAction_Search_KeyUp;
    Qva.PopupSearch.onfocus = AvqAction_Search_Focus;

    if (elem.xx != null) {
        if (elem.yy != 0) debugger;
        Qva.PopupSearch.searchcol = elem.xx;
    }
    mgr.Search = Qva.PopupSearch;
    Qva.PopupSearch.AvqMgr = mgr;
    var positionsource = Qva.GetFrame (mgr.Element);
    if (positionsource == null) {
        var element = document.getElementById (searchname.replace (mgr.PageBinder.DefaultScope + ".", ""));
        positionsource = Qva.GetFrame (element);
        if (positionsource == null) {
            positionsource = element;
        }
    }
    var elemPageCoords = Qva.GetAbsolutePageCoords (positionsource);
    Qva.PopupSearch.style.position = "absolute";
    Qva.PopupSearch.style.left = elemPageCoords.x + "px";
    Qva.PopupSearch.style.top = elemPageCoords.y - 19 + "px";
    Qva.PopupSearch.style.width = '100pt';
    Qva.PopupSearch.style.zIndex = 666;
    Qva.PopupSearch.style.border = '1pt solid black';
    Qva.PopupSearch.style.display = '';

    document.body.insertBefore (Qva.PopupSearch, document.body.firstChild);
    Qva.PopupSearch.focus ();
    Qva.KeepPopupSearchAlive = true;
}
Qva.ClosePopupSearch = function () {
    if (Qva.PopupSearch == null) return;
    var mgr = Qva.PopupSearch.AvqMgr;
    var binder = mgr.PageBinder || Qva.GetBinder(mgr.binderid);
    if (mgr.SearchName != null) {
        binder.Set (mgr.SearchName, "closesearch", "abort", false);
    }
    if (Qva.ActiveElement == Qva.PopupSearch) Qva.ActiveElement = mgr.Element;
    mgr.SearchName = null;
    mgr.Search = null;
    document.body.removeChild (Qva.PopupSearch);
    Qva.PopupSearch = null;
    return binder;
}

Qva.OpenPopupInput = function (elem) {
    Qva.ClosePopupInput ();
    var parent = elem.parentNode;
    Qva.PopupInput = document.createElement ("input");
    if (IS_GECKO || IS_SAFARI || IS_OPERA || IS_CHROME) {
        var gs = document.defaultView.getComputedStyle (parent, "");
        Qva.PopupInput.style.fontFamily = gs.getPropertyValue ("font-family");
        Qva.PopupInput.style.fontSize = gs.getPropertyValue ("font-size");
    } else {
        Qva.PopupInput.style.fontFamily = parent.currentStyle.fontFamily;
        Qva.PopupInput.style.fontSize = parent.currentStyle.fontSize;
    }
    Qva.PopupInput.style.top = parent.offsetTop + "px";
    Qva.PopupInput.style.left = parent.offsetLeft + "px";
    Qva.PopupInput.style.width = parent.clientWidth + "px";
    Qva.PopupInput.style.height = parent.clientHeight + "px";
    Qva.PopupInput.style.zIndex = 666;
    Qva.PopupInput.style.position = "absolute";
    Qva.PopupInput.style.border = "none";
    Qva.PopupInput.style.padding = "0px 0px 0px 0px";
    Qva.PopupInput.value = parent.innerText;
    Qva.PopupInput.onmousedown = Qva.CancelAction;
    Qva.PopupInput.onmouseup = Qva.CancelAction;
    Qva.PopupInput.onclick = Qva.CancelAction;
    Qva.PopupInput.onkeydown = AvqAction_Input_KeyDown;
    Qva.PopupInput.binderid = elem.binderid;
    Qva.PopupInput.xx = elem.xx;
    Qva.PopupInput.yy = elem.yy;
    Qva.PopupInput.targetname = elem.targetname;
    parent.offsetParent.offsetParent.appendChild (Qva.PopupInput);
    
    Qva.PopupInput.focus ();
    Qva.SetCursor (Qva.PopupInput, true);
}
Qva.ClosePopupInput = function () {
    if (Qva.PopupInput == null) return;
    Qva.PopupInput.parentNode.removeChild (Qva.PopupInput);
    Qva.PopupInput = null;
}

Qva.AddRule = function (ss, name, style) {
    // Guard against security error
    try {
        if (ss.addRule) {
            ss.addRule (name, style);
        } else {
            ss.insertRule (name + " { " + style + " }", ss.cssRules.length);
        }
    } catch (e) {
    }
}

Qva.PageBinding.prototype.Refresh = function () {
    if (!this.Enabled) return;
    this.LoadBegin ();
}
Qva.PageBinding.prototype.LoadBegin = function (polling) {
    if (this.IsUpdating) {
        this.HasPendingLoad = true;
        return;
    }
    if (this.OnUpdateBegin != null) this.OnUpdateBegin (polling);	
    
    if (!polling) this.IsUpdating = true;
    this.ScrollLeftToRemember = 0;
    this.ScrollTopToRemember = 0;
    Qva.ActiveElement = null;
    try {
        this.ScrollLeftToRemember = document.body.scrollLeft;
        this.ScrollTopToRemember = document.body.scrollTop;
        Qva.ActiveElement = document.activeElement;
        if (!polling) document.body.style.cursor = 'wait';
    } catch(e) { }

    if (!this.IsPartialLoad && !polling) {
        if (!Qva.KeepPopupSearchAlive && Qva.PopupSearch != null) {
            var mgr = Qva.PopupSearch.AvqMgr;
            var binder = mgr.PageBinder || Qva.GetBinder(mgr.binderid);
            if(binder == this) {
                Qva.ClosePopupSearch();
            }
        }
        Qva.ClosePopupInput ();
    }
    if (! Qva.KeepContextMenuAlive && !polling) {
        Qva.HideContextMenu ();
    }

    if (!polling) this.Enabled = false;
    if (!this.First) {
        for (var mix = 0; mix < this.Managers.length; ++mix) {
            var mgr = this.Managers [mix];
            if (this.IsRemote && !polling && mgr.Lock) mgr.Lock ();
            mgr.Touched = false;
        }
    }

    if (this.Benchmark != null) this.Benchmark.Load.Start();

    if (this.View == null && this.Kind == null) {
        this.Ready ();
    } else {
        if (this.AutoviewDictionary != null && !polling) {
            this.SetAutoviewAddCommands ();
        }
        this.Load (polling);
    }
}

Qva.PageBinding.prototype.Load = function (polling) {
    this.HasPendingLoad = false;
    
    this.CurrentLoadIsPartial = this.IsPartialLoad;
    this.IsPartialLoad = false;

    if (polling) {
        //nothing
    } else if (Qva.PendingSearchName != '' || Qva.PendingSearchKeyName != '') {
        if (Qva.PendingSearchName != '') {
            this.Set (Qva.PendingSearchName, "search", Qva.PendingSearchValue, false);
            Qva.PendingSearchName = '';
        } 
        if (Qva.PendingSearchKeyName != '' && Qva.PopupSearch != null) {
            var mgr = Qva.PopupSearch.AvqMgr;
            var binder = mgr.PageBinder || Qva.GetBinder(mgr.binderid);
            if(binder == this) {
                this.Set (Qva.PendingSearchKeyName, "closesearch", Qva.PendingSearchKey, false);
                Qva.ClosePopupSearch();
                Qva.PendingSearchKeyName = '';
            }
        }
    } else if (this.PendingDblClickName != '') {
        this.Set (this.PendingDblClickName, "click", this.PendingDblClickName, false);
        this.PendingDblClickName = '';
    }
    var cmd = '<update mark="' + this.Mark + '" stamp="' + this.Stamp + '"';
    if (window.navigator && window.navigator.cookieEnabled) {
        cmd += ' cookie="true"';
    } else {
        cmd += ' cookie="false"';
    }
    if (this.DefaultScope != null) cmd += ' scope="' + this.DefaultScope + '"';
    if (this.JSON && this.Session != null) cmd += ' session="' + this.Session + '"';
    if (this.View != null) cmd += ' view="' + Qva.XmlEncode (this.View) + '"';
    if (this.Autoview != null && this.Autoview != "") cmd += ' autoview="' + Qva.XmlEncode (this.Autoview) + '"';
    cmd += ' ident="' + Qva.XmlEncode (this.Ident) + '"';
    if (this.Userid != null) cmd += ' userid="' + this.Userid + '"';
    if (this.Xuserid != null) cmd += ' xuserid="' + this.Xuserid + '"';
    if (this.Password != null) cmd += ' password="' + this.Password + '"';
    if (this.Xpassword != null) cmd += ' xpassword="' + this.Xpassword + '"';
    if (this.Kind != null) cmd += ' kind="' + this.Kind + '"';
    cmd += '>';
    if (polling) {
        cmd += '<poll />';
    } else {
        cmd += this.Body;
        if (!this.HasAutoviewAddCommands ()) {   // Do not add initial sets until all autoviews are done and we have space
            cmd += this.InitialSets;
            this.InitialSets = '';
        }
        this.Body = '';
    }
    cmd += '</update>';
    if (this.Trace != null && this.Trace.Request != null) this.Trace.Request.innerText = cmd;
    var pb = this;
    if (this.Agent == null) {
        var url = this.Url;
        
        if (this.Host != null) url += '&host=' + escape (this.Host);
        if (this.Ticket != null) url += '&ticket=' + escape (this.Ticket);
        if (this.View != null) url += '&view=' + escape (this.View);
        if (this.Userid != null) url += '&userid=' + escape (this.Userid);
        if (this.Xuserid != null) url += '&xuserid=' + escape (this.Xuserid);
        if (this.Password != null) url += '&password=' + escape (this.Password);
        if (this.Xpassword != null) url += '&xpassword=' + escape (this.Xpassword);
        if (this.Mark == '') {
            var platform = "browser.";
            if (IS_CHROME) {
                platform += "chrome";
            } else if (IS_GECKO) {
                platform += "gecko." + GECKO_VERSION;
            } else if (IS_SAFARI) {
                platform += "safari";
            } else if (IS_OPERA) {
                platform += "opera";
            } else if (IS_IE) {
                platform += navigator.userAgent.substr(navigator.userAgent.indexOf('MSIE'), 8);    
            } else {
                platform += "unknown";
            }
            url += '&platform=' + escape(platform);
        }
        
        if(this.JSON) {
            if (this.Session != null) url += '&session=' + escape (this.Session);
            url += '&json=' + escape (this.ID);
            url += '&cmd=' + escape (cmd);
            
            var scriptTag = document.createElement("script");
            
            // Add script object attributes
            scriptTag.setAttribute("type", "text/javascript");
            scriptTag.setAttribute("src", url);
            
            // Create the script tag
            var head = document.getElementsByTagName("head").item(0);
            if(this.ScriptTag) {
                head.replaceChild(scriptTag, this.ScriptTag)
            } else {
                head.appendChild(scriptTag);
            }
            this.ScriptTag = scriptTag;
            
        } else if (this.UsePost) {
            var xmlhttp;
            if (window.XMLHttpRequest){
                xmlhttp = new XMLHttpRequest()
            } else {
                xmlhttp = new ActiveXObject("MSXML2.XMLHTTP");
            }
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    if(xmlhttp.responseXML) { // somtime null in chrome
                        pb.Doc = xmlhttp.responseXML;
                    } else if(xmlhttp.responseText) {
                        debugger;
                        pb.loadXML(xmlhttp.responseText);
                    }
                    pb.Ready ();
                }
            }

            xmlhttp.open("POST", url, true);
            try {
                xmlhttp.send(cmd);
            } catch(e) {
                alert('Communication error (send): ' + e.message);
                this.Enabled = true;
            }
        } else {
            url += '&cmd=' + escape (cmd);
            this.Doc.onreadystatechange = function () {
                if (pb.Doc.readyState == 4) {
                    pb.Ready ();
                }
            }
            if (!this.Doc.load(url)) {
                alert('Communication error (get)');
                this.Enabled = true;
            }
        }
    } else {
        var data;
        try {
            data = this.UseExecute ? this.Agent.Execute (cmd) : this.Agent.XmlUpdate (cmd);
        } catch(e) {
            data = '<result><message text="Server not responding" /></result>';
        }
        if (!this.Doc.loadXML (data)) {
            alert ('Unexpected error loading');
            this.Enabled = true;
            return;
        }
        window.setTimeout (function () { pb.Ready() }, 0);	// make local loading asynchronous as well
    }
}

Qva.PageBinding.prototype.PartialLoad = function (name, pageoffset) {
    if (isNaN (parseInt (pageoffset))) return;
    this.IsPartialLoad = true;
    this.Set (name, "pageoffset", pageoffset, true);
}

Qva.PageBinding.prototype.AddManager = function (mgr) {
    mgr.PageBinder = this;
    mgr.Touched = false;
    mgr.Dirty = false;
    if (mgr.SelectedClassName == null) {
        mgr.SelectedClassName = 'AvqSelected';
        mgr.DeselectedClassName = 'AvqDeselected';
        mgr.EnabledClassName = 'AvqEnabled';
        mgr.DisabledClassName = 'AvqDisabled';
        mgr.LockedClassName = 'AvqLocked';
        mgr.ModeIfNotEnabled = 'n';    // Use "true" non-enabled mode
    }
    this.Managers [this.Managers.length] = mgr;
    this.Append (mgr, mgr.Name, mgr.Attr);
}

Qva.PageBinding.prototype.Append = function (mgr, name, attr, noautoview) {
    if (name == null || name.substr (0,1) == ".") debugger;
    if (name == null || name == "") return;
    var list = this.Members[name];
    if (list == null) {
        list = new Array ();
        this.Members[name] = list;
    }
    for (var i = 0; i < list.length; i ++) {
        if (list [i] == mgr) break;
    }
    if (i == list.length) {
        list [list.length] = mgr;
    }
    if (this.Autoview != null && ! noautoview) {
        var nameattr = name.split ('@');
        var autoviewname = nameattr [0];
        var autoviewattr = nameattr.length > 1 ? nameattr [1] : attr;
        this.AutoViewAppend (mgr, autoviewname, autoviewattr);
    }
}

Qva.PageBinding.prototype.HasAutoviewAddCommands = function () {
    if(this.AutoviewDictionary == null) return false;
    for (var name in this.AutoviewDictionary) {
        var item = this.AutoviewDictionary [name];
        if (item.dirty) return true;
    }
    return false;
}
Qva.PageBinding.prototype.AutoViewAppend = function (mgr, name, attr) {
    if (attr == null) attr = "text";
    if (this.AutoviewDictionary == null) this.AutoviewDictionary = {}
    var item = this.AutoviewDictionary[name];
    if (item == null) {
        item = {}
        item.dirty = true;
        item.attrs = "mode";
        this.AutoviewDictionary[name] = item;
    }
    if (item.attrs.indexOf(attr) == -1) {
        item.dirty = true;
        item.attrs += ";" + attr;
    }
}
Qva.PageBinding.prototype.SetAutoviewAddCommands = function() {
    for (var name in this.AutoviewDictionary) {
        var item = this.AutoviewDictionary[name];
        if (!item.dirty) continue;
        item.dirty = false;
        this.Set(name, 'add', item.attrs, false);
        if (this.First && this.Body.length > 900 && !this.UsePost) return;     // arbitrary length to keep URL below 1K
    }
    if (this.First && this.Bookmark != null) {

        /*************************************************************************************/
        /* Start of ICB tweaked code to prevent old factlab bookmarks from being applied */
        var runBookmark = false;

        if (!isNaN(Factlab.LatestOldBookmarkToAllow)) {

            // bookmark should be of format Server\BM02
            re = new RegExp(/Server\\BM(.*)/)
            var match = re.exec(this.Bookmark);

            if (match != null && match.length == 2) {
                var numberPartAsInt = parseInt(match[1]);
                if (!isNaN(numberPartAsInt) && numberPartAsInt >= Factlab.LatestOldBookmarkToAllow) {
                    runBookmark = true;
                }
            }
        }
        else {
            runBookmark = true;
        }

        if (runBookmark) {
            this.Set('bookmark-apply', 'docaction', this.Bookmark, false);
        }
        /* End of ICB tweaked code to prevent old factlab bookmarks from being applied */
        /*************************************************************************************/

        // Previous code
        this.Set('bookmark-apply', 'docaction', this.Bookmark, false);
    }
    if (this.First && this.InitialSelections != null) {
        for (var sel = 0; sel < this.InitialSelections.length; sel++) {
            var selection = this.InitialSelections[sel].split(",");
            var objectpart = selection[0].split(".");
            var dataok = true;
            if (objectpart.length == 2) {
                // data source specified for object, could be either name of document or datasource
                if (objectpart[objectpart.length - 2] != this.View && objectpart[objectpart.length - 2] != this.ID)
                    dataok = false;
            } else if (objectpart.length == 0) {
                dataok = false;
            }
            if (dataok) {
                if (objectpart[objectpart.length - 1].indexOf("\\") == -1)
                    var name = this.DefaultScope + ".Document\\" + objectpart[objectpart.length - 1];
                else
                    var name = this.DefaultScope + "." + objectpart[objectpart.length - 1];

                this.Set(name + ".CD", "action", "", false);
                for (var value = 1; value < selection.length; value++) {
                    this.Set(name, "text", selection[value], false);
                }
            }
        }
    }
}

Qva.PageBinding.prototype.loadXML = function (xmltext) {
    if(this.Doc && typeof this.Doc.loadXML !== "undefined") {
        return this.Doc.loadXML (xmltext)
    } else if(typeof DOMParser !== "undefined") {
        this.Doc = new DOMParser().parseFromString(xmltext, 'text/xml');
        return this.Doc != null;
    }
    return false;
}

function SetActiveStyle (element, isactive) {
    element.IsActive = isactive;
    if (element.style.display == "none") return;
    if (element.BorderWidth != null) {
        var bordercolor = isactive && element.ActiveBorderColor ? element.ActiveBorderColor : element.BorderColor;
        var borderstyle = element.BorderWidth + "pt " + element.BorderStyle + " " + bordercolor;
        element.style.border = borderstyle;
    }
    var captionelem = getSiblingByClassname (element, "caption");
    if (captionelem != null) {
        if (captionelem.style.display == "none") return;
        var color = isactive ? captionelem.activecolor : captionelem.color;
        if (color == null) return;
        if (captionelem.innerText == "Gg") {
            if (color.getAttribute ('bkgcolor')) captionelem.style.color = color.getAttribute ('bkgcolor');
        } else {
            setStyle (color, captionelem);
        }
        setBackgroundStyle (color, captionelem);
        captionelem.style.borderBottom = "1pt " + element.BorderStyle + " " + bordercolor;

        var numberofchildren = captionelem.childNodes.length;
        for (var ichild = 0; ichild < numberofchildren; ichild++) {
            var child = captionelem.childNodes [ichild];
            if (child.nodeName != "IMG") continue;
            var url = child.src;
            url = Qva.FixUrl (url, "color", color.getAttribute ('color'));
            url = Qva.FixUrl (url, "bkgcolor", color.getAttribute ('bkgcolor'));
            child.src = url;
        }
    }
}

function SetActiveAndSearchable (newsearchable, newactive) {
    if (newsearchable) {
        Qva.SearchableObject = newsearchable;
    }
    if (Qva.ActiveObject != newactive) {
        var oldelem = window.document.getElementById (Qva.ActiveObject + "_frame");
        if (oldelem) {
            SetActiveStyle (oldelem, false);
        } 
        var elem = window.document.getElementById (newactive + "_frame");
        if (elem) {
            SetActiveStyle (elem, true);
            Qva.ActiveObject = newactive;
        } else {
            Qva.ActiveObject = "";
        }
    } 
}

Qva.PageBinding.prototype.Ready = function() {
    if (this.RecursiveReadyLevel > 0) {
        return;
    }

    try {
        document.body.style.cursor = 'auto';
    } catch (e) { debugger }

    //    if (this.Enabled) { alert ('State error'); }
    this.Enabled = true;

    var pendingPoll = false;
    var openUrlWindow = null; // window opened from server using 'open/@url'
    for (; ; ) {
        if (this.Doc == null) {
            debugger;
            return;
        }
        var root = this.Doc.documentElement;
        if (this.View != null || this.Kind != null) {
            if (root == null) {
                var error_string = "";
                var parseError = this.Doc.parseError;
                if (parseError != null) {
                    error_string += 'Line: ' + parseError.line +
                    '\r\n\r\nChar: ' + parseError.filepos +
                    '\r\n\r\nReason: ' + parseError.reason + '\r\n\r\n';
                }
                error_string += 'Failed to load:\r\n\r\nURL: ' + this.Doc.url;
                this.ShowMessage(error_string);
                return;
            }
            switch (Qva.GetMessage(root)) {
                case "Error: No Authentication":
                    var url = '/QvAJAXZfc/Authentication.asp?json='
                    var scriptTag = document.createElement("script");

                    // Add script object attributes
                    scriptTag.setAttribute("type", "text/javascript");
                    scriptTag.setAttribute("src", url);

                    // Create the script tag
                    var head = document.getElementsByTagName("head").item(0);
                    if (this.ScriptTag) {
                        head.replaceChild(scriptTag, this.ScriptTag)
                    } else {
                        head.appendChild(scriptTag);
                    }
                    this.ScriptTag = scriptTag;
                    return;

                case "Failed to open document, you don't have access to the server.":
                    if (Qva.RemainingRetries <= 0) break;
                    var loc = Qva.FixUrl("" + window.location, 'userid', "");
                    if (this.JSON && this.Session) loc = Qva.FixUrl(loc, 'session', this.Session);
                    loc = Qva.FixUrl(loc, 'retry', Qva.RemainingRetries);
                    window.location = loc;
                    return;
            }
            if (!this.IsHosted) {
                if (root.getAttribute('unicorn') == '3') Qva.Unicorn = true;
                var session = root.getAttribute('session');
                if (this.Session == null) {
                    this.Session = session; // remember;
                } else if (this.Session != session) {
                    var message = Qva.GetMessage(root);
                    if (message == null) {
                        message = "Session timed out";
                    }
                    this.OnSessionLost(message);
                    return;
                }
            }
            var pending = root.getAttribute('pending');
            if (this.AsyncServer) {
                if (pending != null) {
                    pendingPoll = true;
                    this.PendingNames = pending.split(';');
                } else {
                    this.PendingNames = [];
                }
            } else {
                if (pending == "true") this.HasPendingLoad = true;
            }

            var currentobjects = root.getElementsByTagName('object');
            var newactive = null;
            var newsearchable = null;
            if (currentobjects.length >= 1) {
                newactive = currentobjects[0].getAttribute('activeobject');
                newsearchable = currentobjects[0].getAttribute('searchableobject');
            }
            SetActiveAndSearchable(newsearchable, newactive);

            var open_nodes = root.getElementsByTagName('open');
            if (open_nodes.length >= 1) {
                for (var iUrl = 0; iUrl < open_nodes.length; iUrl++) {
                    var open_node = open_nodes[iUrl];
                    var url = open_node.getAttribute('url');
                    if (url) {
                        var redirect = open_node.getAttribute('redirect') == "true";
                        try {
                            var OpenDoc = window.parent["OpenDoc"];
                            var doc = Qva.ExtractProperty('document', null, false, url);
                            if (doc && OpenDoc) {
                                var urlparams = null;
                                var index = url.indexOf('&');
                                if (index > 0) { urlparams = url.substr(index); }
                                url = OpenDoc(doc, urlparams, Qva.ExtractProperty, Qva.FixUrl);
                            }
                            if (url) {
                                if (redirect) {
                                    window.parent.location = url;
                                } else {
                                    // ICB added following call and commented out lines
                                    // below to make export to Excel work better in factlab
                                    show_exportTableToExcelPopup(url);
                                    //                                    openUrlWindow = window.open(url);
                                    //                                    if (IS_IE) {
                                    //                                        Qva.ShowOpenUrlMsg(url);
                                    //                                    }
                                }
                            }
                        } catch (e) {
                            this.ShowMessage("Can't open '" + url + "' due to error: " + e.description);
                        }
                        open_node.setAttribute("url", "");
                    }
                }
            }
            var ident = root.getAttribute('ident');
            if (ident != null) this.Ident = ident;
            var kind = root.getAttribute('kind');
            if (kind != null) this.Kind = kind;
            var mark = root.getAttribute('mark');
            var stamp = root.getAttribute('stamp');
            if (mark != null && stamp != null) {
                this.Mark = mark;
                this.Stamp = stamp;
            }

            var partial = this.CurrentLoadIsPartial;
            this.CurrentLoadIsPartial = false;

            if (this.Benchmark != null) this.Benchmark.Load.Stop();
            if (this.Benchmark != null) this.Benchmark.Paint.Start();
            this.PaintTree(root, '', partial);
            if (this.Benchmark != null) this.Benchmark.Paint.Stop();

            var MoreAutoviewsToAdd = this.First && (this.HasAutoviewAddCommands() || this.InitialSets != '');
            if (Qva.PendingSearchName != '' || Qva.PendingSearchKeyName != '' || this.PendingDblClickName != '' ||
                MoreAutoviewsToAdd || this.HasPendingLoad) {
                this.Enabled = false;
                if (MoreAutoviewsToAdd) this.SetAutoviewAddCommands();
                if (this.Benchmark != null) this.Benchmark.Load.Start();
                this.Load();
                return;
            }
            this.IsUpdating = false;
            break;
        }
    }
    this.PaintDone(true, root);

    if (this.View != null || this.Kind != null) {
        var msg = Qva.GetErrorMessage(root);
        if (msg != null) {
            if (msg.indexOf("Error Message: Object expected") != -1 || msg.indexOf("Error Message: Failed to connect") != -1)
                Qva.ErrorMessage("Could not connect to server!");
            else
                Qva.ErrorMessage(msg);
        } else {
            var msg = Qva.GetMessage(root);
            if (msg != null) {
                this.ShowMessage(msg);
            }
        }
        if (this.Trace != null && this.Trace.Response != null) this.Trace.Response.innerText = this.Doc.xml;
    }
    if (this.First && this.DeveloperMode) {
        var errmsg = this.OnceAfterLoad();
        if (errmsg != null) this.ShowMessage(errmsg);
    }
    if (this.IsHosted && this.first) window.focus();
    if (this.IsRemote) {
        try {
            if (document.selection && document.selection.type != 'None') {
                var y = document.selection.createRange();
                if (y != null) y.select();
            }
        } catch (e) { debugger }
    }
    this.First = false;
    try {
        document.body.scrollLeft = this.ScrollLeftToRemember;
        document.body.scrollTop = this.ScrollTopToRemember;
        if (document.activeElement != Qva.ActiveElement) {
            Qva.ActiveElement.focus();
        }
    } catch (e) { }

    if (Qva.PopupSearch != null) Qva.KeepPopupSearchAlive = false;

    if (openUrlWindow != null) {
        openUrlWindow.focus();
    }

    if (pendingPoll) this.LoadBegin(true);
}

Qva.OpenUrlMsg = null;
Qva.ShowOpenUrlMsg = function (url) {
    if(!Qva.OpenUrlMsg) {
        Qva.OpenUrlMsg = document.createElement("div");
        Qva.OpenUrlMsg.className = "QvUrlPopup";
        document.body.appendChild(Qva.OpenUrlMsg);
    }
    Qva.OpenUrlMsg.innerHTML = "";
    Qva.OpenUrlMsg.style.display = "";
    var span = document.createElement("span");
    span.innerText = "The requested content has been opened in another window. ";
    Qva.OpenUrlMsg.appendChild(span);
    var span = document.createElement("span");
    span.innerText = "If not, ";
    Qva.OpenUrlMsg.appendChild(span);
    var link = document.createElement("a");
    link.href = url;
    link.innerText = "press here";
    Qva.OpenUrlMsg.appendChild(link);
    var top = parseInt ((Qva.GetViewportHeight () - Qva.OpenUrlMsg.offsetHeight) / 2);
    var left = parseInt ((Qva.GetViewportWidth () - Qva.OpenUrlMsg.offsetWidth) / 2);
    Qva.OpenUrlMsg.style.top = top + "px";
    Qva.OpenUrlMsg.style.left = left + "px";
    var span = document.createElement("span");
    span.innerText = "close";
    span.onclick = Qva.CloseUrlMsgDiv;
    span.style.position = "relative";
    span.style.cursor = "pointer";
    Qva.OpenUrlMsg.appendChild(span);
    span.style.top = Qva.OpenUrlMsg.offsetHeight - span.offsetTop - span.offsetHeight - 20 + "px";
    span.style.left = Qva.OpenUrlMsg.offsetWidth - span.offsetLeft - span.offsetWidth - 30 + "px";
    window.setTimeout (function () { Qva.CloseUrlMsgDiv (); }, 10000);
}

Qva.CloseUrlMsgDiv = function () {
    if(!Qva.OpenUrlMsg) {
        debugger;
    } else {
        Qva.OpenUrlMsg.style.display = "none";
    }
}

Qva.PageBinding.prototype.OnceAfterLoad = function () {
    var errors = [];
    var dix = 0;
    for (var mix = 0; mix < this.Managers.length; ++mix) {
        var mgr = this.Managers [mix];
        if (mgr.Name == '' || mgr.Name == '#edit#' || mgr.Touched) {
            if (dix != mix) this.Managers [dix] = this.Managers [mix];
            ++dix;
        } else {
            if (mgr.Name != '') {
                try { mgr.Element.style.display = 'none'; } catch (e) { debugger }
                errors [errors.length] = 'Not found: ' + mgr.Name;
            }
        }
    }
    this.Managers.length = dix;
    
    if (errors.length == 0) return null;
    var msg = 'Errors:\n' + errors.join ('\n');
    return msg;
}
Qva.PageBinding.prototype.PaintTree = function (rootnode, prefix, partial) {
    for (var node = rootnode.firstChild; node != null; node = node.nextSibling) {
        if (node.nodeName != 'value' && node.nodeName != 'action' && node.nodeName != 'group' && node.nodeName != 'list') continue;
        var name = prefix + node.getAttribute ('name');
        var list = this.Members[name];
        if (list != null) {
            var mode = 'd';
            switch (node.getAttribute ('mode')) {
            case "not-applicable":
                mode = 'n';
                break;
            case "hidden":
                mode = 'h';
                break;
            case "enabled":
                mode = 'e';
                break;
            }
            var xlen = list.length;
            for (var ixx = 0; ixx < xlen; ++ixx) {
                var mgr = list [ixx];
                var mgrmode = mode;
                if (mode != 'n' && mgr.HideIf && mgr.HideIf(node.getAttribute('value'), node.getAttribute('text'))) mgrmode = 'n'; 
                mgr.Paint (mgrmode, node, name, partial);
            }
        }
    }
    for (var group = rootnode.firstChild; group != null; group = group.nextSibling) {
        if (group.nodeName != 'value' && group.nodeName != 'object' && group.nodeName != 'group' && group.nodeName != 'list') continue;
        var grpprefix = prefix + group.getAttribute('name') + '.';
        this.PaintTree (group, grpprefix, partial);
    }
}
Qva.PageBinding.prototype.PaintDone = function (remote, root) {
    if (this.First) {
        if (!this.IsHosted) {
            try {
                if (document.cookie.indexOf ("qlikmachineid") == -1) {
                    if (window.navigator && window.navigator.cookieEnabled) {
                        var machineid = root.getAttribute ('machineid');
                        if (machineid != null) {
                            var expires = new Date();
                            expires.setFullYear(2222, 2, 2);
                            document.cookie = "qlikmachineid=" + machineid + "; expires=" + expires.toGMTString();
                        }
                    }
                }
            } catch(e) {
                debugger;
            }
        }
    }

    if (this.Benchmark != null) this.Benchmark.Unlock.Start();
    for (var mix = 0; mix < this.Managers.length; ++mix) {
        var mgr = this.Managers [mix];
        if (mgr.Dirty) {
            mgr.PostPaint ();
            mgr.Dirty = false;
        }
        if (this.AsyncServer && mgr.SetPending) {
            mgr.SetPending(this.PendingNames);
        } 
        if (this.IsRemote && !mgr.Touched && mgr.Unlock) mgr.Unlock ();
    }
    if (this.Benchmark != null) this.Benchmark.Unlock.Stop();

    if (this.Benchmark != null) this.Benchmark.UpdateComplete.Start();
    this.OnUpdateComplete ();
    if (this.Benchmark != null) this.Benchmark.UpdateComplete.Stop();

    if (this.Benchmark != null) this.Benchmark.Display();

}

Qva.PageBinding.prototype.CloseTransient = function () {
    this.Set (this.TransientObject, "closetransient", "ok", false);
    Qva.ClosePopupSearch();
    var transientobject = window.document.getElementById (this.TransientObject.replace (this.DefaultScope + ".", ""));
    if (transientobject) {
        transientobject.parentNode.parentNode.style.display = "none";
    }
    this.TransientObject = '';
}

Qva.PageBinding.prototype.Set = function (name, type, value, _final) {
    if (this.GlobaSearchObject != '') {
        if (this.GlobaSearchObject != name.substr (0, this.GlobaSearchObject.length) &&
            this.TransientObject != name.substr (0, this.TransientObject.length) && 
            (Qva.ContextMenuMgr == null || name != Qva.ContextMenuMgr.Name)) 
        {
            this.Set (this.GlobaSearchObject, "closesearch", "abort", true);
            this.GlobaSearchObject = '';
            this.CloseTransient ();
        }
    } else if (this.TransientObject != '') {
        if (this.TransientObject != name.substr (0, this.TransientObject.length) && 
            (this.GlobaSearchObject == "" || this.GlobaSearchObject != name.substr (0, this.GlobaSearchObject.length)) &&
            (Qva.ContextMenuMgr == null || name != Qva.ContextMenuMgr.Name)) 
        {
            if (this.TransientObject == this.ToggleSelect) {
                this.ToggleSelect = "";
                this.ToggleSelects = null;
            }
            this.CloseTransient ();
        }
    }
    name = Qva.MgrMakeName (name, this.DefaultScope);
//    this.Body += '<set name="' + name + '" ' + type + '="' + Qva.XmlEncode(value) + '"/>';
    this.Body += '<set name="' + name + '" ' + type + '="' + Qva.XmlEncode(value) + '" clientsizeWH="' + Math.round(Qva.GetViewportWidth() * Qva.Factor) + ':' + Math.round(Qva.GetViewportHeight() * Qva.Factor) + '"/>';
    if (_final) {
        if(this.LoadBegin_Timeout) clearTimeout(this.LoadBegin_Timeout);
        if(this.DelaySet) {
            var self = this;
            this.LoadBegin_Timeout = setTimeout(function() { self.LoadBegin(); }, 200);
            //setTimeout(function() { self.LoadBegin(); }, 100);
        } else {
            this.LoadBegin ();
        }
    }
}

Qva.PageBinding.prototype.SetInitial = function (name, type, value) {
    this.InitialSets += '<set name="' + name + '" ' + type + '="' + Qva.XmlEncode(value) + '"/>';
}

Qva.SelectChild = function(root, names, ix) {
    for (var node = root.firstChild; node; node = node.nextSibling) {
        switch(node.nodeName) {
        case 'object':
            if (node.getAttribute('name') != names[ix]) break;
            return (ix == 0) ? node : null;
        case 'group':
        case 'list':
            if (node.getAttribute('name') != names[ix]) break;
            return node;
        case 'value':
        case 'action':
            if (node.getAttribute('name') != names[ix]) break;
            return (ix == names.length - 1) ? node : null;
        }
    }
    return null;
}
Qva.PageBinding.prototype.Select = function(path) {
    if (path == null) return null;
    path = Qva.MgrMakeName (path, this.DefaultScope);
    var parts = path.split ('.');
    var node = this.Doc.documentElement;
    for (var ix = 0; node != null && ix < parts.length; ++ix) {
        node = Qva.SelectChild(node, parts, ix);
    }
    return node;
}

Qva.SelectNode = function(root, path) {
    if (root == null || path == null) return null;
    var parts = path.split ('.');
    var node = root;
    for (var ix = 0; node != null && ix < parts.length; ++ix) {
        node = this.SelectChild(node, parts, ix);
    }
    return node;
}

Qva.PageBinding.prototype.SetClick = function (event, name, elem) {
    if (! this.Enabled) return;
    if (this.ToggleSelect != "") return;
    Qva.MgrWithMouseDown = null;
    var clickstring = "";
    if (elem) {
        var offsetX = 0;
        var offsetY = 0;
        if (! event) {
            offsetX = window.event.offsetX;
            offsetY = window.event.offsetY;
        } else {
            var evtOffsets = Qva.GetOffsets (event);
            offsetX = evtOffsets.offsetX;
            offsetY = evtOffsets.offsetY;
        }
        clickstring += '' + offsetX + ':' + offsetY;
        var objectframeNode = Qva.GetFrame(elem);
        var graphwidth = parseInt (imagewidth (objectframeNode, elem));
        var graphheight = parseInt (imageheight (objectframeNode, elem));
        clickstring += ':' + graphwidth + ':' + graphheight;
    }
    this.Set (name, "click", clickstring, true);
}

Qva.PageBinding.prototype.SetNewSheet = function() {
    var ActiveSheetNode = this.Select (".ActiveSheet");
    if (ActiveSheetNode) {
        var newTab = ActiveSheetNode.getAttribute ("text");
        if (newTab) this.NavigateToSheet (newTab);
    }
}
Qva.PageBinding.prototype.NavigateToSheet = function(id) {
    var parameters = window.location.search;
    var url = id + ".htm";
    var loc = "" + window.location.pathname;
    if (loc.length < url.length || loc.substr (loc.length - url.length) != url) {
        if (parameters.length > 0) url += parameters;
        if (this.JSON) url = Qva.FixUrl(url, 'session', this.Session);
        url = Qva.FixUrl(url, 'userid');
        url = Qva.FixUrl(url, 'password');
        window.location = url;
    }
}

Qva.GetContainingModal = function() { return window.parent.Qva.Modal.instance; }
Qva.CloseModal = function () {
     if(window.parent.Qva.Modal)
    {
        var modal = window.parent.Qva.Modal.instance;
        if (modal != null) modal.Close();
    }
}
Qva.SetModalTitle = function (text) {
    if(window.parent.Qva.Modal)
    {
        var modal = window.parent.Qva.Modal.instance;
        if (modal != null) modal.SetTitle(text);
    }
    
}

Qva.OpenDragRect = function (X, Y) {
    X = Qva.StartoffsetX - Qva.SelectClient2OffsetX + Qva.GetScrollLeft ();
    Y = Qva.StartoffsetY - Qva.SelectClient2OffsetY + Qva.GetScrollTop ();
    if (Qva.DragRect == null) {
        Qva.DragRect = document.createElement ("div");
        Qva.DragRect.className = "QvDragRect";
        Qva.DragRect.style.position = "absolute";
        Qva.DragRect.style.left = X + "px";
        Qva.DragRect.style.top = Y + "px";
        Qva.DragRect.style.width = "0px";
        Qva.DragRect.style.height = "0px";
        Qva.DragRect.style.zIndex = 666;
        Qva.DragRect.style.display = '';

        Qva.DragRect.onmousemove = function (event) { Qva.MouseMove(event, Qva.MgrWithSelectStart); }
        
        document.body.insertBefore (Qva.DragRect, document.body.firstChild);
    } else {
        Qva.DragRect.style.left = X + "px";
        Qva.DragRect.style.top = Y + "px";
        Qva.DragRect.style.display = '';
    }
    
    Qva.DragStartX = X;
    Qva.DragStartY = Y;
    Qva.DragRectLeft = X;
    Qva.DragRectTop = Y;
    Qva.DragRectWidth = 0;
    Qva.DragRectHeight = 0;
}

Qva.SizeDragRect = function (X, Y) {
    X += Qva.GetScrollLeft ();
    Y += Qva.GetScrollTop ();
    Qva.DragRectLeft = X > Qva.DragStartX ? Qva.DragStartX : X;
    Qva.DragRectTop = Y > Qva.DragStartY ? Qva.DragStartY : Y;
    Qva.DragRectWidth = X > Qva.DragStartX ? X - Qva.DragStartX : Qva.DragStartX - X;
    Qva.DragRectHeight = Y > Qva.DragStartY ? Y - Qva.DragStartY : Qva.DragStartY - Y;
    Qva.DragRect.style.left = Qva.DragRectLeft + "px";
    Qva.DragRect.style.top = Qva.DragRectTop + "px";
    Qva.DragRect.style.width = Qva.DragRectWidth + "px";
    Qva.DragRect.style.height = Qva.DragRectHeight + "px";
}

Qva.CloseDragRect = function (X, Y, name, binderid, elem) {
    Qva.SizeDragRect (X, Y);
    var left = Qva.DragRectLeft + Qva.SelectClient2OffsetX - Qva.GetScrollLeft ();
    var top = Qva.DragRectTop + Qva.SelectClient2OffsetY - Qva.GetScrollTop ();
    var width = Qva.DragRectWidth;
    var height = Qva.DragRectHeight;
    var rectstring = '' + left + ':' + top + ':' + width + ':' + height;
    Qva.DragRect.style.display = 'none';
    var objectframeNode = Qva.GetFrame(elem);
    var graphwidth = parseInt (imagewidth (objectframeNode, elem));
    var graphheight = parseInt (imageheight (objectframeNode, elem));
    rectstring += ':' + graphwidth + ':' + graphheight;
    Qva.GetBinder(binderid).Set (name, "rect", rectstring, true);
}

Qva.MouseDown = function (event, mgr) {
    //if (! this.Enabled) return;
    Qva.MgrWithMouseDown = mgr;
    Qva.MgrWithSelectStart = null;
    if (! event) {
        event = window.event;
        if (mgr.Select != null) {
            event.returnValue = false;
        }
        Qva.StartoffsetX = window.event.offsetX;
        Qva.StartoffsetY = window.event.offsetY;
    } else {
        if (mgr.Select != null) {
            event.preventDefault ();
        }
        var evtOffsets = Qva.GetOffsets (event);
        Qva.StartoffsetX = evtOffsets.offsetX;
        Qva.StartoffsetY = evtOffsets.offsetY;
    }
}

Qva.MouseMove = function (event, mgr, mindelta) {
    //if (! this.Enabled) return;
    if (Qva.MgrWithMouseDown != mgr && Qva.MgrWithSelectStart != mgr) return;
    var offsetX = 0;
    var offsetY = 0;
    if (! event) {
        event = window.event;
        if (mgr.Select != null) {
            event.returnValue = false;
        }
        offsetX = event.offsetX;
        offsetY = event.offsetY;
    } else {
        if (mgr.Select != null) {
            event.preventDefault ();
        }
        var evtOffsets = Qva.GetOffsets (event);
        offsetX = evtOffsets.offsetX;
        offsetY = evtOffsets.offsetY;
    }
    var X = event.clientX;
    var Y = event.clientY;
    if (Qva.MgrWithMouseDown == mgr) {
        var deltaX = offsetX - Qva.StartoffsetX;
        var deltaY = offsetY - Qva.StartoffsetY;
        if (mindelta == null) mindelta = 4;
        if (deltaX < -mindelta || deltaX > mindelta || deltaY < -mindelta || deltaY > mindelta) {
            Qva.MgrWithMouseDown = null;
            Qva.MgrWithSelectStart = mgr;
            Qva.SelectClient2OffsetX = offsetX - X;
            Qva.SelectClient2OffsetY = offsetY - Y;
            if (Qva.MgrWithSelectStart.SelectStart != null) {
                Qva.MgrWithSelectStart.SelectStart (X, Y);
            }
        }
    }
    if (Qva.MgrWithSelectStart == mgr) {
        if (Qva.MgrWithSelectStart.Select != null) {
            Qva.MgrWithSelectStart.Select (X, Y);
        }
    }
}

Qva.PageBinding.prototype.ContextClientAction = function (event, elem) {
    if (! event) { event = window.event; }
    event.cancelBubble = true;
    if (elem.clientaction == "search") {
        Qva.OpenPopupSearch (elem, elem.param);
    } else if (elem.clientaction == "modal" && Qva.Modal.instance != null) {
        var modals = elem.param.split(':');
        Qva.Modal.instance.Show (this, Qva.Modal.instance.ScriptPath + modals[0] + '.htm?target=' + escape(elem.Name || elem.AvqMgr.Name), parseInt(modals[1]), parseInt(modals[2]));
    } else if (elem.clientaction == "inputfield") {
        Qva.OpenPopupInput (elem);
    } else if (elem.clientaction == "confirm") {
        var parts = elem.param.split(':');
        var name = (elem.Name || elem.AvqMgr.Name) + '.' + parts[0];
        var msg = parts.slice(1).join(':');
        if (window.confirm(msg)) {
            this.Set(name, 'action', '', true);
        }
    } else if (elem.clientaction == "url") {
        window.open (elem.param);
    } else if (elem.clientaction == "bundledurl") {
        var url = this.BuildBinaryUrl (null, "", elem.param)
        window.open (url);
    } else if (elem.clientaction == "popup") {
        alert (elem.param);
    } else {
        alert ("Not supported clientside action: " + elem.clientaction); 
    }
    Qva.HideContextMenu ();
    return false;
}

Qva.PageBinding.prototype.OnContextMenu = function (event, name) {
    if (! event) event = window.event;
    if (event.shiftKey && ctrlKeyPressed (event)) return; 
    Qva.HideContextMenu ();
    var position = null;
    var fullname;
    var srcelement = event.target;
    if (! srcelement) {
        srcelement = event.srcElement;
    }
    if (srcelement.position != null) {
        fullname = srcelement.targetname ? this.DefaultScope + "." + srcelement.targetname : name;
        position = srcelement.position;
    } else if (name) {
        fullname = name;
        if (srcelement.tagName == "IMG" && srcelement.isgraph) {
            var pos = Qva.GetPageCoords(srcelement);
            position = (event.clientX - pos.x) + ':' + (event.clientY - pos.y);
        } else {
            position = "";
        }
    } else if (Qva.LabelClick) {
        fullname = this.DefaultScope + '.StandardActions';
    } else {
        return;
    }
    return this.OnCreateContextMenu (this, event, fullname, position);
}

Qva.HideContextMenu = function () {
    if (Qva.ContextMenu == null) return;
    if (Qva.ContextMenuMgr.SubMenuRow && Qva.ContextMenuMgr.SubMenuRow.SubMenu) {
        document.body.removeChild (Qva.ContextMenuMgr.SubMenuRow.SubMenu);
        Qva.ContextMenuMgr.SubMenuRow.SubMenu = null;
    }
    while (Qva.ContextMenu.rows.length > 0) {
        Qva.ContextMenu.deleteRow (Qva.ContextMenu.rows.length - 1);
    }
    Qva.ContextMenu.style.display = 'none';
}

Qva.PageBinding.prototype.TryAltAgent = function () {
    try {
        if(external && typeof (external.AvqIdent) == "string") {
            var _this = this;
            external.AvqInitServer (this.View, function() { if (_this.Enabled) _this.LoadBegin(); });
            if (this.HostedTitle == null) {
                external.AvqTitle (document.title);
            } else if (this.HostedTitle != "") {
                external.AvqTitle (this.HostedTitle);
            }
            this.IsRemote = false;
            this.IsHosted = true;
            this.Ident = external.AvqIdent;
            this.Kind = external.AvqKind;
            this.Agent = external;
        } else if (this.AllowComAgent) {
            try {
                var segm = /[\?\&]admin=/.exec (this.Remote);
                this.Agent = new ActiveXObject ("QvsRemote.Client");
            this.UseExecute = true;
                if (segm == null) {
                    this.Agent.Connect("localhost", true);
                } else {
                    this.Agent.AdminConnect("localhost");
                }
                this.IsRemote = false;
            } catch (e) {
                // will fail later
            }
        }
    } catch (e) {
        debugger
    }
}

Qva.PageBinding.prototype.BuildBinaryUrl = function (path, stamp, name, color) {
    if (!this.Unicorn && this.IsHosted) {
        if (! this.ImageFolder) {
            this.ImageFolder = path.replace (name + ".png", "");
        }
        return path;
    }
    if (name != null && stamp == null && this.CustomIcons [name]) {
        return this.CustomIcons [name];
    }
    var url = this.Url;
    url = url.replace ('mark=', 'datamode=binary');
    if (name != null) {
        url += '&name=' + escape (name);
    }
    if (this.Host != null) url += '&host=' + escape (this.Host);
    if (stamp != null) {
        url += '&stamp=' + escape (stamp);
        if (this.Ticket != null) url += '&ticket=' + escape (this.Ticket);
        if (this.View != null) url += '&view=' + escape (this.View);
        if (this.Kind != null) url += '&kind=' + this.Kind;
        if (this.Userid != null) url += '&userid=' + this.Userid;
        if (this.Xuserid != null) url += '&xuserid=' + this.Xuserid;
        if (this.Password != null) url += '&password=' + this.Password;
        if (this.Xpassword != null) url += '&xpassword=' + this.Xpassword;
    } else { // no stamp is session independent images
        url += '&public=only';
    }
    if (this.Session != null && this.JSON) url += '&session=' + escape (this.Session);
    if (color) url += '&color=' + escape (color);
    return url;
}

Qva.PageBinding.prototype.RemoveFromManagers = function (mgr) {
    var mix = -1;
    for (var ix = 0; ix < this.Managers.length; ++ ix) {
        if (this.Managers [ix] == mgr) {
            mix = ix;
            break;
        }
    }
    if (mix == -1) {
        debugger;
    } else {
        if (mix != this.Managers.length - 1) {
            var swap = this.Managers [mix];
            this.Managers [mix] = this.Managers [this.Managers.length - 1];
            this.Managers [this.Managers.length - 1] = swap;
            mix = this.Managers.length - 1;
        }
    }
    if (this.Managers [mix].Element.AvqMgr != null) {
        if (this.Managers [mix].Element.AvqMgr.Detach !== null) this.Managers [mix].Element.AvqMgr.Detach ();
        this.Managers [mix].Element.AvqMgr = null;
    }
    this.Managers [mix].Element = null;
    this.Managers.length = mix;
}
Qva.PageBinding.prototype.RemoveFromMembers = function (mgr) {
    var name = mgr.Name;
    if (name == null) debugger;
    if (name == null || name == "") return;
    var oldlist = this.Members[name];
    if (oldlist == null) {
        debugger;
        return;
    }
    var newlist = new Array ();
    for (var i = 0; i < oldlist.length; i ++) {
        if (oldlist [i] != mgr) {
            newlist [newlist.length] = oldlist [i];
        }
    }
    if (oldlist.length == newlist.length) {
        debugger;
    }
    this.Members[name] = newlist;
}

function AvqAction_Input_KeyDown (event) {
    if (! event) { event = window.event; }
    var key = event.keyCode;
    switch (key) {
    case 13:    // <Enter>
        Qva.GetBinder(this.binderid).Set (this.targetname, "inputvalue", this.xx + ":" + this.yy + ":" + this.value, true);
    case 27:    // <Escape>
        break;
    }
}

Qva.NoAction = function (event) {
    if (! event) event = window.event;
    if (! event) return;
    if (event.preventDefault) {
        event.preventDefault ();
    } else {
        event.returnValue = false;
    }
}

Qva.CancelAction = function (event) {
    if (! event) event = window.event;
    event.cancelBubble = true;
    this.pressed = true;
}

Qva.DefaultShowMessage = function (msg) { alert(msg); }
Qva.DefaultOnSessionLost = function (msg) {
//    Qva.RemainingRetries = parseInt(Qva.ExtractProperty("retry", "3"));
//    if(isNaN(Qva.RemainingRetries)) Qva.RemainingRetries = 3;
//    if (Qva.RemainingRetries < 1) {
//        document.body.innerText = msg;
//    } else {
//        document.body.innerText = msg + " Reconnecting...";
//        window.location = Qva.FixUrl(Qva.FixUrl("" + window.location, "session"), 'retry', Qva.RemainingRetries - 1);
//    }
    Qva.RetryMessage("Lost connection to server." + "<br><br>" + "Reconnecting...");
}

Qva.DefaultOnCreateContextMenu = function (binder, event, fullname, position) {
    event.cancelBubble = true;
    if (Qva.ContextMenu == null) { 
        Qva.ContextMenu = document.createElement ('table');
        Qva.ContextMenu.style.width = "140px";
        Qva.ContextMenu.style.position = "absolute";
        Qva.ContextMenu.style.zIndex = 666;
        Qva.ContextMenu.className = "contextmenu";
        var mgr = new Qva.Mgr.menu (binder, Qva.ContextMenu, binder.DefaultScope + ".Menu");
        Qva.ContextMenuMgr = mgr;
        document.body.appendChild(Qva.ContextMenu);
    } else {
        Qva.ContextMenu.style.display = "";
        while (Qva.ContextMenu.rows.length > 0) {
            Qva.ContextMenu.deleteRow ();
        }
    }
    var tr = Qva.ContextMenu.insertRow (-1);
    var td = tr.insertCell (-1);
    td.innerHTML = "<\BR>";
    var X = event.clientX + Qva.GetScrollLeft ();
    var Y = event.clientY + Qva.GetScrollTop ();
    Qva.ContextMenu.style.left = X + "px";
    Qva.ContextMenu.style.top = Y + "px";
    binder.Set (fullname, 'add', 'menu', false);
    if (position != null) binder.Set (fullname, 'position', position, false);
    try {
        Qva.ContextMenu.focus ();
    } catch (err) {} 
    Qva.KeepContextMenuAlive = true;
    binder.LoadBegin ();
    return false;
}

Qva.XmlEncode = function (value) {
    var val = '' + value;
    val = val.replace (/&/g, '&amp;');
    val = val.replace (/</g, '&lt;');
    val = val.replace (/>/g, '&gt;');
    val = val.replace (/"/g, '&quot;');
    return val;
}
Qva.GetMessage = function(root) {
    var msg_nodes = root.getElementsByTagName ('message');
    if (msg_nodes.length >= 1) {
        var msg = msg_nodes[0].getAttribute ('text');
        if (msg && msg != '') return msg;
    }
    return null;
}

Qva.GetErrorMessage = function(root) {
    var error_nodes = root.getElementsByTagName ('Error');
    if (error_nodes.length >= 1) {
        var msg_nodes = root.getElementsByTagName ('message');
        if (msg_nodes.length >= 1) {
            var msg = msg_nodes[0].getAttribute ('text');
            if (msg && msg != '') return msg;
        }
    }
    return null;
}

Qva.GetViewportHeight = function () {
    if (window.innerHeight!=window.undefined) return window.innerHeight;
    if (document.compatMode=='CSS1Compat') return document.documentElement.clientHeight;
    if (document.body) return document.body.clientHeight; 
}
Qva.GetViewportWidth = function () {
    if (window.innerWidth!=window.undefined) return window.innerWidth; 
    if (document.compatMode=='CSS1Compat') return document.documentElement.clientWidth; 
    if (document.body) return document.body.clientWidth; 
}
Qva.GetScrollTop = function () {
    if (self.pageYOffset) return self.pageYOffset; // all except Explorer
    if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop; // Explorer 6 Strict
    return document.body.scrollTop; // all other Explorers
}

Qva.GetScrollLeft = function () {
    if (self.pageXOffset) return self.pageXOffset; // all except Explorer
    if (document.documentElement && document.documentElement.scrollLeft) return document.documentElement.scrollLeft; // Explorer 6 Strict
    return document.body.scrollLeft; // all other Explorers
}

Qva.MgrSplit = function (mgr, name, namePrefix) {
    if (name == null) return false;
    var segm = name.split ('@');
    switch (segm.length) {
    case 1:
        mgr.Attr = 'text';
        break;
    case 2:
        mgr.Attr = segm [1];
        break;
    case 3:
        mgr.Attr = (segm [1] != '') ? segm [1] : 'text';
        mgr.Dec = parseInt (segm [2]);
        break;
    default:
        return false;
    }
    mgr.Name = Qva.MgrMakeName (segm [0], namePrefix);
    return true;
}
Qva.MgrMakeName = function (name, namePrefix) {
    if (name == null) debugger;
    if (name.substr (0,1) == '.') {
        if (namePrefix == null) debugger; 
        return namePrefix + name;
    } else {
        return name;
    }
}

Qva.MgrGetDisplayFromMode = function (mgr, mode) {
    if (mgr.Element.disabled && mgr.ModeIfNotEnabled == 'h') {
        return 'none';
    } else if (mode == 'd' || mode == 'e' || mgr.ModeIfNotEnabled == 'd') {
        return '';
    } else {
        return 'none';
    }
}

Qva.Trunc = function (txt, ndec) {
    var dot = txt.indexOf ('.');
    if (dot < 0) return txt;
    var adec = txt.length - dot - 1;
    if (adec <= ndec) return txt;
    var f = parseFloat (txt);
    if (isNaN (f)) return txt;
    var fact = Math.pow (10, ndec);
    f = Math.round (f * fact) / fact;
    return f.toString ();
}

Qva.LockDisabled = function () {
    this.Locked = this.Element.disabled;
    this.Element.disabled = true;
}
Qva.UnlockDisabled = function () { this.Element.disabled = this.Locked; }
Qva.LockReadOnly = function () {
    this.Locked = this.Element.readOnly;
    this.Element.readOnly = true;
}
Qva.UnlockReadOnly = function () { this.Element.readOnly = this.Locked; }

Qva.FixUrl = function (url, parameter, value) {
    var re = new RegExp ("[\?\&]" + parameter + "=[^\&]*", "i");
    url = url.replace(re, "");
    if(value != null) url += '&' + parameter + '=' + escape(value);
    if(url.indexOf ('?') == -1) url = url.replace(/&/, "?");
    return url;
}
Qva.ExtractProperty = function (name, defprop, allowEmpty, url) {
    if(allowEmpty) {
        var re = new RegExp ("[\?\&]" + name + "=([^\&]*)", "i");
    } else {
        var re = new RegExp ("[\?\&]" + name + "=([^\&]+)", "i");
    }
    var segm = re.exec (url || window.location);
    try {
        if (segm == null) segm = re.exec (top.location);
    } catch (e) {
    }
    return segm != null ? unescape (segm [1]) : defprop;
}
Qva.ExtractPropertyArray = function(name, defprop, allowEmpty, url) {
    if (allowEmpty) {
        var re = new RegExp("[\?\&]" + name + "=([^\&]*)", "gi");
    } else {
        var re = new RegExp("[\?\&]" + name + "=([^\&]+)", "gi");
    }
    var selections = [];
    var usedurl = "";
    try {
        if (re.test(url))
            usedurl = url;
        else if (re.test(window.location))
            usedurl = window.location;
        else if (re.test(top.location))
            usedurl = top.location;
    } catch (e) { }
    if (usedurl != "") {
        // reset lastIndex
        re.lastIndex = 0;
        do {
            var segm = re.exec(usedurl);
            if (segm != null)
                selections.push(unescape(segm[1]));
        } while (segm != null);
    }
    if (selections.length > 0)
        return selections;
    else
        return defprop;
}
Qva.ExtractPropertyForDocument = function(name, document, defprop, allowEmpty, url) {
    var ticket = null;
    var singelTicket = null;
    var properties = Qva.ExtractPropertyArray(name, defprop, allowEmpty, url);
    if (properties) {
        for (var row = 0; row < properties.length; row++) {
            var items = properties[row].split(":");
            if (items.length == 2) {
                if (items[0].toLowerCase() == document.toLowerCase())
                    ticket = items[1];
            }
            else
                singelTicket = properties[row];
        }
    }
    if (ticket == null && singelTicket != null)
        return singelTicket;
    else
        return ticket;
}
Qva.GetAbsolutePageCoords = function (element) {
    var coords = {x : 0, y : 0};
    while (element) {
        coords.x += element.offsetLeft;
        coords.y += element.offsetTop;
        element = element.offsetParent;
    }
    return coords;
}

Qva.GetPageCoords = function (element) {
    var coords = {x : 0, y : 0};
    while (element) {
        coords.x += element.offsetLeft;
        if (element.tagName == "DIV") coords.x -= element.scrollLeft
        coords.y += element.offsetTop;
        if (element.tagName == "DIV") coords.y -= element.scrollTop
        element = element.offsetParent;
    }
    coords.x -= Qva.GetScrollLeft ();
    coords.y -= Qva.GetScrollTop ();
    return coords;
}

Qva.GetOffsets = function (event, target) {
//    if(!target) target = event.target;
    if(!target) target = event.target  || event.srcElement;

    if (typeof target.offsetLeft == 'undefined') {
        target = target.parentNode;
    }
    var pageCoords = Qva.GetAbsolutePageCoords (target);
    var eventCoords = { 
        x: Qva.GetScrollLeft() + event.clientX,
        y: Qva.GetScrollTop()  + event.clientY
    };
    var offsets = {
        offsetX: eventCoords.x - pageCoords.x,
        offsetY: eventCoords.y - pageCoords.y
    };
    return offsets;
}

Qva.SetCursor = function (elem, input) {
    var cursorpos = 0;
    if (elem.value.length > 0) {
        cursorpos = elem.value.charAt (0) == "*" ? elem.value.length - 1 : elem.value.length;
    }
    if (window.document.selection) { // the deep ie caret position magic
        var sel = window.document.selection.createRange ();
        sel.moveStart ('character', -elem.value.length);
        sel.moveEnd ('character', -elem.value.length);
        if (input) {
            sel.moveStart ('character', 0);
            sel.moveEnd ('character', elem.value.length);
        } else {
            sel.moveStart ('character', cursorpos);
        }
        sel.select ();
    } else if (elem.selectionStart) { // mozilla
        if (input) {
            elem.selectionStart = 0;
            elem.selectionEnd = elem.value.length;
        } else {
            elem.selectionStart = Math.max (1, cursorpos);
            elem.selectionEnd = Math.max (1, cursorpos);
        }
    }
}

Qva.CancelBubble = function (event) {
    if (!event) {
        window.event.cancelBubble = true;
    } else {
        event.stopPropagation();
    }
}

function dosearch (elem) { Qva.OpenPopupSearch (elem); }


function AvqAction_Search_KeyDown(event) {
    if (! event) { event = window.event; }
    var mgr = this.AvqMgr;
    var key = event.keyCode;
    switch (key) {
    case 13:    // <Enter>
        Qva.CloseSearch (mgr, this, true, ctrlKeyPressed (event));
        break;
    case 27:    // <Escape>'
        var _this = this;
        window.setTimeout (function () { Qva.CloseSearch (mgr, _this, false); }, 0);
        break;
    }
}
function AvqAction_Search_KeyUp(event) {
    if (!event) { event = window.event; }
    var key = event.keyCode;
    switch (key) {
    case 13:    // <Enter>
    case 27:    // <Escape>
        break;
    default:
        if (this.searchcol == null) {
            Qva.Search(this.AvqMgr, this, key);
        }
        break;
    }
}

function AvqAction_Search_Focus () {
    if (this.value == "") {
        this.value = this.param != null ? this.param : "**";
        Qva.SetCursor (this);
    }
}

function getSiblingByClassname (objectframeNode, classname) {
    for (var i = 0; i < objectframeNode.childNodes.length; i++) {
        var child = objectframeNode.childNodes [i];
        if (child.className != classname) continue;
        if (child.tagName != "DIV") continue;
        if (child.style.display == 'none') break;
        return child;
    }
    return null;
}

function imageheight (objectframeNode, element) {
	var graphheight = element.style.height;
	if (graphheight == 'auto' || element.autosize) {
	    if (graphheight == 'auto') element.autosize = true;
	    graphheight = getMaxClientHeight (objectframeNode);
        if (objectframeNode != element.parentNode) {
            graphheight = getContentMaxHeight (element.parentNode);
	    }
        if (graphheight < 0) {
	        graphheight = getClientHeight (element.parentNode);
        }
		element.style.height = graphheight + "px";
	    return graphheight;
	} else {
	    return element.offsetHeight;
	}
}

function imagewidth (objectframeNode, element) {
	var graphwidth = element.style.width;
	if (graphwidth == 'auto' || element.autosize) {
	    if (graphwidth == 'auto') element.autosize = true;
		graphwidth = getClientWidth (element.parentNode);
		element.style.width = graphwidth + "px";
	    return graphwidth;
	} else {
	    return element.offsetWidth;
	}
}

function getContentMaxHeight (element) {
    var objectframeNode = element.parentNode;
    var newparentheigh = getMaxClientHeight (objectframeNode);
    var numberofchildren = objectframeNode.childNodes.length;
    for (var ichild = 0; ichild < numberofchildren; ichild++) {
        var child = objectframeNode.childNodes [ichild];
        if (child == element) continue;
        if (child.nodeName != "DIV") continue;
        if (child.style.display == 'none') continue;
        if (child.className == "MoveZone") continue;
        if (child.className == "ResizeFrame") continue;
        newparentheigh -= child.offsetHeight;
    }
    if (newparentheigh > 0) return newparentheigh;
    newparentheigh = parseInt (element.style.height);
    if (isNaN (newparentheigh)) return 0;
    return newparentheigh;
}

function getClientWidth (elem) {
    if (IS_GECKO || IS_SAFARI || IS_OPERA || IS_CHROME) {
        var clientWidth = elem.offsetWidth;
        var gs = document.defaultView.getComputedStyle (elem, "");
        var pad = parseInt (gs.getPropertyValue ("padding-left")) + parseInt (gs.getPropertyValue("padding-right"));
        var bor = parseInt (gs.getPropertyValue ("border-left-width")) + parseInt (gs.getPropertyValue("border-right-width"));
        clientWidth -= pad;
        clientWidth -= bor;
        return clientWidth;
    } else {
        return elem.clientWidth;
    }
}

function getClientHeight (elem) {
    if (IS_GECKO || IS_SAFARI || IS_OPERA || IS_CHROME) {
        var clientHeight = elem.offsetHeight;
        var gs = document.defaultView.getComputedStyle (elem, "");
        var pad = parseInt (gs.getPropertyValue ("padding-top")) + parseInt (gs.getPropertyValue("padding-bottom"));
        var bor = parseInt (gs.getPropertyValue ("border-top-width")) + parseInt (gs.getPropertyValue("border-bottom-width"));
        clientHeight -= pad;
        clientHeight -= bor;
        return clientHeight;
    } else {
        return elem.clientHeight;
    }
}

function setFrameHeight (elem, deltaframeY) {
    if (! elem.maxclientheight) {
        if (! elem.style.height) return;
        var maxclientheight = getClientHeight (elem);
        elem.maxclientheight = maxclientheight;
    }
    var height = elem.maxclientheight - deltaframeY;
//    if (height != elem.offsetHeight) {
    if (height != getClientHeight (elem)) {
        elem.style.height = height + "px";
        if (elem.firstChild.ResizeType) Qva.Mgr.CreateAndUpdateResizeHandles(elem);
    }
}

function getMaxClientHeight (elem) {
    if (elem.maxclientheight) {
        return elem.maxclientheight;
    } else {
        return getClientHeight (elem);
    }
}

function setFrameWidth (elem, deltaframeX) {
    if (! elem.maxclientwidth) {
        if (! elem.style.width) return;
        var maxclientwidth = getClientWidth (elem);
        elem.maxclientwidth = maxclientwidth;
    }
    var width = elem.maxclientwidth - deltaframeX;
    if (width != getClientWidth (elem)) {
        elem.style.width = width + "px";
        if (elem.firstChild.ResizeType) Qva.Mgr.CreateAndUpdateResizeHandles(elem);
    }
}

function getMaxClientWidth (elem) {
    if (elem.maxclientwidth) {
        return elem.maxclientwidth;
    } else {
        return getClientWidth (elem);
    }
}

function setContentWidth (objectframeNode, newwidth) {
    if (newwidth == null) newwidth = getClientWidth (objectframeNode);
    var numberofchildren = objectframeNode.childNodes.length;
    var anychanges = false;
    for (var ichild = 0; ichild < numberofchildren; ichild++) {
        var child = objectframeNode.childNodes [ichild];
        if (child.nodeName != "DIV") continue;
        if (child.style.display == 'none') continue;
        if (child.ResizeType) continue;
        var currentwidth = parseInt (child.style.width);
        if (currentwidth != newwidth) {
            child.style.width = newwidth + "px";
            anychanges = true;
        }
    }
    return anychanges; 
}

Qva.Hover = null;
Qva.PageBinding.prototype.GetHoverDiv = function () {
    if(!Qva.Hover) {
        Qva.Hover = document.createElement("div");
        Qva.Hover.className = "QvHover";
        Qva.Hover.style.zIndex = 666;
        Qva.Hover.style.display = "none";
        Qva.Hover.style.position = "absolute";
        Qva.Hover.style.backgroundColor = "#FFFFCC";
        Qva.Hover.style.border = "solid 1px black";
        Qva.Hover.style.padding = "1px 3px 2px 3px";
        document.body.appendChild(Qva.Hover);
        new Qva.Mgr.hover (this, Qva.Hover, this.DefaultScope + ".Hover");
    }
    return Qva.Hover;
}

Qva.GetFrame = function (elem) {
    function EndsWidth(str, end) {
        return str && str.length >= end.length && str.substr(str.length - end.length) == end;
    }
    while(elem && !EndsWidth(elem.id, "_frame")) {
        elem = elem.parentNode;
    }
    return elem;
}
Qva.RetryMessage = function(msg) {
    var msgdiv = document.createElement("DIV");
    msgdiv.className = "HTMLMessage";
    var textdiv = document.createElement("DIV");
    textdiv.style.width = "75%";
    textdiv.style.height = "100%";
    textdiv.innerHTML = msg;
    msgdiv.appendChild(textdiv);
    var img = document.getElementById("WorkingGif");
    if (img) {
        img.style.display="block";
        img.style.position="absolute";
        img.style.left = "85%";
        img.style.top = "40%";
        msgdiv.appendChild(img);
    }
    var cancelbtn = document.createElement("BUTTON");
    cancelbtn.innerText = "Cancel";
    cancelbtn.style.display="block";
    cancelbtn.style.position="absolute";
    cancelbtn.style.left = "75%";
    cancelbtn.style.top = "75%";
    var to = setTimeout( function() {
        //window.location = Qva.FixUrl("" + window.location, "session");
        //window.location = Qva.FixUrl(Qva.FixUrl("" + window.location, "session"), "ticket");
        //window.parent.location = Qva.FixUrl("" + window.parent.location, "session");
        
        var l = window.parent.location + "";
        var i = l.lastIndexOf("#")
        if(i != -1) l = l.substr(0, i);
        window.parent.location = Qva.FixUrl(l, "session");
    },5000);
    cancelbtn.onclick = function() {
        clearTimeout(to); 
        textdiv.innerHTML += "<br><br>Action canceled by user";
        if (img) img.style.display = "none";
        cancelbtn.style.display = "none";
    }
    msgdiv.appendChild(cancelbtn);
    
    document.body.appendChild(msgdiv);
}
Qva.ErrorMessage = function(msg) {
    var msgdiv = document.createElement("DIV");
    msgdiv.className = "HTMLMessage";
    var textdiv = document.createElement("DIV");
    textdiv.style.width = "100%";
    textdiv.style.height = "100%";
    textdiv.innerHTML = msg;
    textdiv.style.overflow = "auto";
    msgdiv.appendChild(textdiv);
    document.body.appendChild(msgdiv);
}
Qva.addEvent = function(el, evname, func) {
    el["on" + evname] = func;
//    if (el.attachEvent) { // IE
//        el.attachEvent("on" + evname, func);
//    } else if (el.addEventListener) { // Gecko / W3C
//        el.addEventListener(evname, func, false);
//    } else {
//        el["on" + evname] = func;
//    }
}
Qva.removeEvent = function(el, evname, func) {
    el["on" + evname] = null;
//    if (el.detachEvent) { // IE
//        el.detachEvent("on" + evname, func);
//    } else if (el.removeEventListener) { // Gecko / W3C
//        el.removeEventListener(evname, func, true);
//    } else {
//        el["on" + evname] = null;
//    }
};
Qva.cancelSelectEvent_md = function(event) {
    if (! Qva.MouseDown) return;
    
    event = event || window.event;
    var target   = event.target || event.srcElement;
    if (Qva.DragDrop.curDrag || (target.nodeName!="INPUT" && target.nodeName!="SELECT")) 
        Qva.cancelSelectEvent = true;
    //prevents text selections in Firefox
    if (Qva.cancelSelectEvent && event.preventDefault) event.preventDefault();

}
Qva.cancelSelectEvent_mm = function(event) {
    if (Qva.cancelSelectEvent) return false;
}

Qva.LoadScript = function(url, callback){
    var script = document.createElement("script")
    script.type = "text/javascript";
    if (script.readyState){  //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" ||
                    script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    } else {  //Others
        script.onload = function(){
            callback();
        };
    }
    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}


// Build 9.00.7440.8

if (!Qva.Mgr) Qva.Mgr = {}

function onclick_action() {
    var binder = Qva.GetBinder(this.binderid);
    if (!binder.Enabled) return;
    if (this.Position != null) binder.Set (this.PositionName, 'position', this.Position, false);
    binder.Set (this.Name, "action", "", true);
}

function onclick_ContextClientAction(event) { 
    Qva.GetBinder(this.binderid).ContextClientAction (event, this); 
}

Qva.Mgr.show = function (owner, elem, name, prefix, condition) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Condition = condition;
    owner.AddManager(this);
    this.Element = elem;
    owner.Append (this, this.Name, 'value');
}

Qva.Mgr.show.prototype.Paint = function(mode, node) {
    this.Touched = true;
    var show;
    if (mode == 'n') {
        show = (this.ModeIfNotEnabled == 'd');
    } else {
        show = (node.getAttribute (this.Attr) == this.Condition);
    }
    this.Element.style.display = show ? '' : 'none';
}

Qva.Mgr.hide = function (owner, elem, name, prefix, condition) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Condition = condition;
    this.Element = elem;
    owner.AddManager(this);
    owner.Append (this, this.Name, 'value');
}

Qva.Mgr.hide.prototype.Paint = function(mode, node) {
    this.Touched = true;
    var hide;
    if (mode == 'n') {
        if (this.Condition == null) {
            hide = (this.ModeIfNotEnabled != 'd');
        } else {
            hide = false;
        }
    } else {
        hide = (node.getAttribute (this.Attr) == this.Condition);
    }
    this.Element.style.display = hide ? 'none' : '';
}

Qva.Mgr.disable = function (owner, elem, name, prefix) {
    this.Name = Qva.MgrMakeName (name, prefix);
    this.Element = elem;
    owner.AddManager(this);
}

Qva.Mgr.disable.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.disable.prototype.Unlock = Qva.UnlockDisabled;
Qva.Mgr.disable.prototype.Paint = function(mode, node) {
    this.Touched = true;
    var element = this.Element;
    element.disabled = (mode != 'e');
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
}

Qva.Mgr.caption = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Element = elem;
    elem.AvqMgr = this;
    owner.AddManager(this);
    this.PageBinder = owner;
    elem.moveObj = elem.parentNode.id;
    var bkgid = elem.parentNode.id.replace ("_frame", "_bkg");
    var bkgelem = window.document.getElementById (bkgid);
    if (bkgelem) {
        elem.moveObj += ":" + bkgid;
    }
    this.MiddleName = this.Name.split('.')[1];
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    this.RowHeight = -1;
    this.InlineStyle = owner.InlineStyle;
    if (elem.getAttribute ('AvqStyle')) {
        this.InlineStyle = elem.getAttribute ('AvqStyle') == "true";
    }
}

Qva.Mgr.caption.prototype.SetPending = function (names) {
    for (var ix = 0; ix < names.length; ++ix) {
        if (this.MiddleName != names[ix]) continue;
        this.Element.parentNode.className += " QvPending";
        if (this.Element.BkgElem) this.Element.BkgElem.className += " QvPending";
        return;
    }
    var classname = this.Element.parentNode.className;
    this.Element.parentNode.className = classname.replace (" QvPending", "");
    if (this.Element.BkgElem) {
        classname = this.Element.BkgElem.className;
        this.Element.BkgElem.className = classname.replace (" QvPending", "");
    }
}

function setStyle (node, element) {
    if (node.getAttribute ('color')) element.style.color = node.getAttribute ('color');
    if (node.getAttribute ('fontfamily')) element.style.fontFamily = node.getAttribute ('fontfamily');
    if (node.getAttribute ('fontsize')) element.style.fontSize = node.getAttribute ('fontsize') + "pt";
    if (node.getAttribute ('fontstyle')) element.style.fontStyle = node.getAttribute ('fontstyle');
    if (node.getAttribute ('fontweight')) element.style.fontWeight = node.getAttribute ('fontweight');
    if (node.getAttribute ('textalign')) element.style.textAlign = node.getAttribute ('textalign');
    if (node.getAttribute ('verticalalign')) element.style.verticalAlign = node.getAttribute ('verticalalign');
    if (node.getAttribute ('textdecoration')) element.style.textDecoration = node.getAttribute ('textdecoration');
}

Qva.Mgr.caption.prototype.PostPaint = function () {
    var element = this.Element;
    if (this.RowHeight == -1 && this.RowSpan != 1) {
        this.RowHeight = element.clientHeight;
    }
    if (this.RowHeight != -1) {
        element.style.height = this.RowSpan == 1 ? "" : (this.RowHeight * this.RowSpan + "px");
    }
    if (this.NoText) {
        for (var ichild = 0; ichild < element.childNodes.length; ichild++) {
            var child = element.childNodes [ichild];
            if (child.tagName != "SPAN") continue;
            element.removeChild (child);
            break;
        }
    }
}

Qva.Mgr.caption.prototype.Paint = function(mode, node, name) {
    this.Touched = true;
    var element = this.Element;
    element.style.display = Qva.MgrGetDisplayFromMode(this, mode);
    if (element.style.display == "none") return;
    element.style.borderBottom = "solid 1pt Black";
    var IsContained = this.PageBinder.IsContained; //WB
    if (node.getAttribute("allowmove") == "true" && !IsContained) {
        element.onmousedown = Qva.Move.mouseDown;
    } else {
        element.onmousedown = null;
    }
    if (this.InlineStyle) {
        setStyle(node, element);
        element.activecolor = node.getElementsByTagName("activecolor")[0];
        element.color = node.getElementsByTagName("color")[0];
        var color = element.color.getAttribute('color');
        var bkgcolor = element.color.getAttribute('bkgcolor');
    }

    if (mode != 'n') {
        element.innerHTML = "";
        var icons = node.getElementsByTagName("action");
        if (icons.length >= 1) {
            for (var i = (icons.length - 1); i >= 0; i--) {
                var icon = icons[i];
                if (icon.getAttribute("type") == "divider") {
                    debugger;
                    continue;
                }
                if (IsContained && icon.getAttribute("name") == "MI") continue //WB
                var iconnodes = icon.getElementsByTagName("icon");
                var iconnode = null;
                for (var iIcon = 0; iIcon < iconnodes.length; iIcon++) {
                    iconnode = iconnodes[iIcon];
                }
                if (iconnode == null) {
                    debugger;
                    continue;
                }
                var img = document.createElement("img");
                img.alt = "";
                img.className = "CaptionIcon";
                img.title = icon.getAttribute("text");
                var style = iconnode.getAttribute("style");
                if (style) {
                    img.style.cssText = style;
                }
                var url = this.PageBinder.BuildBinaryUrl(iconnode.getAttribute("path"), iconnode.getAttribute("stamp"), iconnode.getAttribute("name"));
                if (!this.InlineStyle) {
                    url += "&color=" + escape(color);
                    url += "&bkgcolor=" + escape(bkgcolor);
                }
                img.src = url;
                var disabled = icon.getAttribute("mode") == "disabled";
                if (!disabled) {
                    var action = icon.getAttribute("name");
                    var clientaction = icon.getAttribute("clientaction");
                    img.binderid = element.binderid;
                    if (action) {
                        img.onclick = onclick_action;
                        img.Name = this.Name + "." + action;
                    }
                    if (clientaction) {
                        img.onclick = onclick_ContextClientAction;
                        img.Name = this.Name;
                        img.AvqMgr = this;
                        img.clientaction = clientaction;
                        img.param = icon.getAttribute('param');
                    }
                    if (icon.getAttribute("menu") == "true") {
                        img.targetname = this.Name.replace(".Caption", "").replace(this.PageBinder.DefaultScope + ".", "");
                        img.position = action;
                        img.oncontextmenu = function(event) { return Qva.GetBinder(this.binderid).OnContextMenu(event, this.Name); }
                    }
                }
                element.appendChild(img);
            }
        }
        var label = node.getAttribute('label');
        if (!label) {
            if (!this.InlineStyle)
                if (element.color.getAttribute('bkgcolor')) element.style.color = element.color.getAttribute('bkgcolor');
            label = "Gg";
            this.NoText = true;
        } else {
            this.NoText = false;
        }
        var span = document.createElement("span");
        span.innerText = label;
        element.appendChild(span);
    }
    if (this.InlineStyle) {
        this.RowSpan = node.getAttribute("rowspan");
        if (this.RowSpan) {
            Qva.QueuePostPaintMessage(this);
            this.Dirty = true;
        }
    }
}

Qva.Mgr.tabrow = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
}

Qva.Mgr.tabrow.prototype.Paint = function (mode, node, name) {
    this.Touched = true;
    var element = this.Element;
    if (mode != 'n') {
        var tabs = node.getElementsByTagName ("value");
        var tabNodes = element.getElementsByTagName("a");
        for (var itab = 0; itab < Math.max(tabs.length, tabNodes.length); itab++) {
            var tabnode = tabs [itab];
            var tabelem = tabNodes[itab];
            if(!tabnode && !tabelem) continue;
            if (!tabelem) {
                tabelem = document.createElement ("a");
                tabelem.dir = "ltr";
                element.appendChild (tabelem);
            }
            if(!tabnode || tabnode.getAttribute ('mode') == "hidden") {
                tabelem.style.display = "none";
                continue;
            }
            tabelem.innerHTML = "";
            var id = tabnode.getAttribute ("name");
            tabelem.id = id;
            tabelem.style.display = "";
            
            var selected = tabnode.getAttribute ('selected') === "true";
            tabelem.className = selected ? "selected" : "";
            setStyle (tabnode, tabelem);
            setBackgroundStyle (tabnode, tabelem);
            var icons = tabnode.getElementsByTagName ("icon");
            var text;
            if (IS_IE) {
                text =  " " + tabnode.getAttribute ("text") + " ";
                if (icons.length >= 1) tabelem.style.paddingRight = "4pt";
            } else {
                text = tabnode.getAttribute ("text");
                if (icons.length >= 1) text += " ";
                if (selected) {
                    tabelem.style.padding = "1pt 4pt 1pt 4pt";
                } else {
                    tabelem.style.padding = "0pt 4pt 0pt 4pt";
                }
            }
            var textnode = document.createTextNode (text);
            tabelem.appendChild (textnode);
            if (icons.length >= 1) {
                var stamp = icons[0].getAttribute ("stamp");
                var name = icons[0].getAttribute ("name");
                var color = icons[0].getAttribute ("color");
                var url = this.PageBinder.BuildBinaryUrl (icons[0].getAttribute ("path"), stamp, name, color);
                var img = document.createElement ("img");
                img.alt = "";
                img.src = url;
                tabelem.appendChild (img);
            }
            if (tabnode.getAttribute ('action')) {
                tabelem.onclick = onclick_action;
                tabelem.Name = this.Name + "." + id;
            }
            if (IS_MAC) {
                if (IS_GECKO) {
                    tabelem.style.top = "2pt";
                }
            } else if (IS_GECKO) {
                tabelem.style.top = "0.5pt";
            } else if (IS_CHROME) {
                tabelem.style.top = "2pt";
            }
        }
    }
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
}

Qva.Mgr.background = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    this.AutoSize = false;
}

function setBackgroundStyle (node, element) {
    if (node.getAttribute ('bkgcolor')) element.style.backgroundColor = node.getAttribute ('bkgcolor');
    element.style.backgroundPosition = node.getAttribute ('bkgposition') || "left top";
    if (node.getAttribute ('bkgrepeat')) element.style.backgroundRepeat = node.getAttribute ('bkgrepeat');
    if (node.getAttribute ('opacity')) {
        if (IS_CHROME || IS_OPERA || IS_SAFARI) {
            element.style.opacity = parseFloat (node.getAttribute ('opacity'));
        } else if (IS_GECKO) {
            element.style.MozOpacity = parseFloat (node.getAttribute ('opacity'));
        } else {
            element.style.filter = "alpha(opacity:" + parseFloat (node.getAttribute ('opacity')) * 100 + ")";
        }
    }
}

Qva.Mgr.background.prototype.PostPaint = function () {
    var element = this.Element;
    if (element.tagName == "DIV") {
        if (element.style.height == "auto" || this.AutoSize) {
            this.AutoSize = true;
            var newheight = parseInt (getContentMaxHeight (element));
            if (! isNaN (newheight)) {
                var frontid = element.parentNode.id.replace ("_bkg", "_frame");
                var frontelem = window.document.getElementById (frontid);
                if (frontelem) {
                    var froncaption = getSiblingByClassname (frontelem, "caption");
                    if (froncaption) {
                        var backgroundoffset = froncaption.offsetHeight;
                        var bkgcaption = getSiblingByClassname (element.parentNode, "caption");
                        if (bkgcaption && parseInt (bkgcaption.style.height) != backgroundoffset) {
                            if (bkgcaption.offsetHeight == 0) newheight -= backgroundoffset;
                            bkgcaption.style.height = backgroundoffset + "px";
                        }
                    }
                    else {
                        var backgroundoffset = 0;
                        var bkgcaption = getSiblingByClassname (element.parentNode, "caption");
                        if (bkgcaption && parseInt (bkgcaption.style.height) != backgroundoffset)
                            bkgcaption.style.height = backgroundoffset + "px";
                    }
                    var frontcontent = getSiblingByClassname (frontelem, "content");
                    if (frontcontent) {
                        var newheightfront = parseInt (getContentMaxHeight (frontcontent));
                        if (! isNaN (newheightfront))
                            frontcontent.style.height = newheightfront + "px";
                    }
                }
                element.style.height = newheight + "px";
            }
        }
        if (element.style.width == "auto" || this.AutoSize) {
            var objectframeNode = element.parentNode;
            setContentWidth (objectframeNode);
            if (frontelem) setContentWidth (frontelem);
        }
    }
    if (this.avq_url) { 
        var offset;
        if (element == document.body) {
            offset = Qva.GetAbsolutePageCoords(document.getElementById("PageContainer")).y;
        }
        var url = this.avq_url;
        if (this.AutoSize) {
            var width = parseInt (element.style.width);
            var height = parseInt (element.style.height);
            if (isNaN (width) || isNaN (height)) {
                if (element == document.body) {
                    width = parseInt (Qva.GetViewportWidth ());
                    height = parseInt (Qva.GetViewportHeight ());
                } else {
                    debugger;
                }
            }
            if (element == document.body) {
                height -= offset;
            }
            if (this.PageBinder.IsHosted) {
                this.PageBinder.Append (this, this.Name, 'w' + width + "px", false);
                this.PageBinder.Append (this, this.Name, 'w' + height + "px", false);
            } else {
                url += '&width=' + escape (width);
                url += '&height=' + escape (height);
            }
        }
        element.style.backgroundImage = "url(" + url + ")";
        if (element == document.body) {
            document.body.style.backgroundPosition = document.body.style.backgroundPosition.replace("top", offset + "px");
        }
    } else {
        element.style.backgroundImage = "";
    }
}

Qva.Mgr.background.prototype.Paint = function(mode, node, name) {
    this.Touched = true;
    var element = this.Element;
    var image = node.getAttribute ("bkgimage");
    if (image == "true") { 
        var stamp = node.getAttribute ("stamp");
        var url = this.PageBinder.BuildBinaryUrl (node.getAttribute ("path"), stamp, this.Name);
        this.avq_url = url;
    } else {
        this.avq_url = null;
        element.style.backgroundImage = "";
    }
    setBackgroundStyle (node, element);
    if (! node.getAttribute ('bkgposition') && node.getAttribute ('bkgrepeat') != "repeat" && element == document.body) {
        this.AutoSize = true
    }
    
    Qva.QueuePostPaintMessage (this);
}

Qva.Mgr.bind = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
}

Qva.Mgr.bind.prototype.Paint = function(mode, node, name) {
    this.Touched = true;
    var element = this.Element;
    if (mode != 'n') {
        setStyle (node, element);
        var attrValue = '';
        if (mode != 'n') {
            attrValue = node.getAttribute (this.Attr);
        }
        if (attrValue == '' && this.TextIfNull) attrValue = this.TextIfNull;
        var text;
        if (this.Dec != null) {
            text = Qva.Trunc (attrValue, this.Dec);
        } else {
            text = attrValue;
        }
        var icons = node.getElementsByTagName ("icon");
        if (icons.length >= 1) {
            element.innerHTML = text;
            var url = this.PageBinder.BuildBinaryUrl (icons[0].getAttribute ("path"), icons[0].getAttribute ("stamp"), icons[0].getAttribute ("name"));
            var innerhtml = '&nbsp;<img alt="" src="' + url + '" />';
            element.innerHTML += innerhtml;
        } else {
            if (text) element.innerText = text;
        }
        if (node.getAttribute ('action')) {
            element.onclick = onclick_action;
        }
    }
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
}

Qva.Mgr.label = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    this.AutoSize = false;
	if (elem.style.width == 'auto' && elem.style.height == 'auto') this.AutoSize = true;
    this.InlineStyle = owner.InlineStyle;
    if (elem.getAttribute ('AvqStyle')) {
        this.InlineStyle = elem.getAttribute ('AvqStyle') == "true";
    }
}

Qva.Mgr.label.prototype.PostPaint = function () {
    if (this.AutoSize) {
        var element = this.Element;
        if (element.tagName == "DIV") {
            var newheight = parseInt (getContentMaxHeight (element, true));
            if (! isNaN (newheight)) {
                element.style.height = newheight + "px";
            }
            var objectframeNode = element.parentNode;
            setContentWidth (objectframeNode);
        }
    }
}

Qva.Mgr.label.prototype.Paint = function(mode, node) {
    this.Touched = true;
    var element = this.Element;
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    if (this.InlineStyle) {
        setStyle (node, element);
    }
    if (element.style.display != "none" && this.AutoSize) Qva.QueuePostPaintMessage (this);
}

Qva.Mgr.frame = function (owner, elem, name, prefix, handleClick) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    elem.AvqMgr = this;
    if (! elem.Chart) {
        var chartid = elem.id.replace ("_frame", "_chart");
        elem.Chart = window.document.getElementById (chartid);
    }
    if (! elem.Caption) {
        var captionid = elem.id.replace ("_frame", "_caption");
        elem.Caption = window.document.getElementById (captionid);
    }
    var background = elem.getAttribute ('avqbackground');
    this.IsBackGround = false;
    if (background != null) {
        this.IsBackGround = background == "true";
    }
    
    this.BorderColor = null;
    this.BorderStyle = null;
    this.BorderWidth = null;
    if (!handleClick && Qva.LabelClick) {
        elem.onclick = function (event) { Qva.GetBinder(this.binderid).SetClick(event, this.Name); }
    }
    this.radiustopleft = -1;
    this.radiustopright = -1;
    this.radiusbottomleft = -1;
    this.radiusbottomright = -1;
    Qva.DragDrop.DropFrames[Qva.DragDrop.DropFrames.length] = this;
    var transientname = owner.DefaultScope + ".DS";
    if (Qva.LabelClick && owner.Members && ! owner.Members [transientname]) {
        this.PageBinder.CreateTransientListBox (transientname);
    }
}

Qva.Mgr.frame.prototype.Inside = function(pos, type) {
    var elem = this.Element;
    var cellPos = Qva.GetPageCoords(elem);
    var cellWidth = parseInt(elem.offsetWidth);
    var cellHeight = parseInt(elem.offsetHeight);
    if (pos.x > cellPos.x && pos.x < cellPos.x + cellWidth &&
            pos.y > cellPos.y && pos.y < cellPos.y + cellHeight) {
        return { 'Element': (this.DropType == type) ? elem : null };
    }
    return null;
}

Qva.Mgr.frame.prototype.PostPaint = function () {
    SetActiveStyle (this.Element, this.Element.IsActive);
}

Qva.Mgr.frame.prototype.PaintCorners = function (node) {
    if (! IS_IE) {
        var corners = node.getElementsByTagName("Corners");
        if (corners.length > 0 || this.radiustopleft != -1) {
            var element = this.Element;
            var firstchild = null;
            for (var ichild = 0; ichild < element.childNodes.length; ichild++) {
                var child = element.childNodes [ichild];
                if (! child.style) continue;
                if (child.style.display == 'none') continue;
                if (child.className == 'ResizeFrame') continue;
                if (child.className == 'MoveZone') continue;
                firstchild = child;
                break;
            }
            var anychanges = false;
            if (this.FirstChild != firstchild) {
                this.FirstChild = firstchild;
                anychanges = true;
            }
            var lastchild = null;
            for (var ichild = element.childNodes.length - 1; ichild >= 0; ichild--) {
                var child = element.childNodes [ichild];
                if (! child.style) continue;
                if (child.style.display == 'none') continue;
                lastchild = child;
                break;
            }
            if (this.LastChild != lastchild) {
                this.LastChild = lastchild;
                anychanges = true;
            }
            if (corners.length > 0) {
                var corner = corners[0];
                var radiustopleft = parseFloat (corner.getAttribute ('radiustopleft'));
                if (this.radiustopleft != radiustopleft) {
                    this.radiustopleft = radiustopleft;
                    anychanges = true;
                }
                var radiustopright = parseFloat (corner.getAttribute ('radiustopright'));
                if (this.radiustopright != radiustopright) {
                    this.radiustopright = radiustopright;
                    anychanges = true;
                }
                var radiusbottomleft = parseFloat (corner.getAttribute ('radiusbottomleft'));
                if (this.radiusbottomleft != radiusbottomleft) {
                    this.radiusbottomleft = radiusbottomleft;
                    anychanges = true;
                }
                var radiusbottomright = parseFloat (corner.getAttribute ('radiusbottomright'));
                if (this.radiusbottomright != radiusbottomright) {
                    this.radiusbottomright = radiusbottomright;
                    anychanges = true;
                }
            }
            if (anychanges == true) {
                element.style.MozBorderRadiusTopleft = this.radiustopleft + "pt";
                element.style.WebkitBorderTopLeftRadius = this.radiustopleft + "pt";
                if (this.FirstChild) {
                    this.FirstChild.style.MozBorderRadiusTopleft = this.radiustopleft + "pt";
                    this.FirstChild.style.WebkitBorderTopLeftRadius = this.radiustopleft + "pt";
                }
                element.style.MozBorderRadiusTopright = this.radiustopright + "pt";
                element.style.WebkitBorderTopRightRadius = this.radiustopright + "pt";
                if (this.FirstChild) {
                    this.FirstChild.style.MozBorderRadiusTopright = this.radiustopright + "pt";
                    this.FirstChild.style.WebkitBorderTopRightRadius = this.radiustopright + "pt";
                }
                element.style.MozBorderRadiusBottomleft = this.radiusbottomleft + "pt";
                element.style.WebkitBorderBottomLeftRadius = this.radiusbottomleft + "pt";
                if (this.LastChild) {
                    this.LastChild.style.MozBorderRadiusBottomleft = this.radiusbottomleft + "pt";
                    this.LastChild.style.WebkitBorderBottomLeftRadius = this.radiusbottomleft + "pt";
                }
                element.style.MozBorderRadiusBottomright = this.radiusbottomright + "pt";
                element.style.WebkitBorderBottomRightRadius = this.radiusbottomright + "pt";
                if (this.LastChild) {
                    this.LastChild.style.MozBorderRadiusBottomright = this.radiusbottomright + "pt";
                    this.LastChild.style.WebkitBorderBottomRightRadius = this.radiusbottomright + "pt";
                }
            }
        }
    }
}

Qva.Mgr.frame.prototype.Paint = function(mode, node) {
    this.Touched = true;
    this.DropType = node.getAttribute("accept");
    var element = this.Element;
    var isContained = Qva.GetBinder(element.binderid).IsContained;
    element.style.display = Qva.MgrGetDisplayFromMode(this, mode);
    if (element.style.display == "none") return;
    if (node.getAttribute("menu") == "true") {
        element.oncontextmenu = function(event) { return Qva.GetBinder(this.binderid).OnContextMenu(event, this.Name); }
    }
    this.PaintCorners(node);
    if (isContained) {
        // do nothing, size and position is determined by the container unless there are borders
        if (!this.ContainerHeight) {
            this.ContainerHeight = getClientHeight(element);
            this.ContainerWidth = getClientWidth(element);
            if (node.getAttribute('borderwidth')) {
                bor = node.getAttribute('borderwidth');
                this.ContainerHeight -= 2 * bor;
                this.ContainerWidth -= 2 * bor;
                element.style.height = this.ContainerHeight + "px";
                element.style.width = this.ContainerWidth + "px";
            }
        }
    }
    else if (node.getAttribute("maximized") == "true") {
        if (!this.Maximized) {
            if (element.Chart) element.Chart.src = "";
            if (element.maxclientheight) {
                this.maxclientheight = element.maxclientheight;
                element.maxclientheight = null;
            }
            if (element.maxclientwidth) {
                this.maxclientwidth = element.maxclientwidth;
                element.maxclientwidth = null;
            }
            this.normalheight = element.style.height;
            this.normalwidth = element.style.width;
            this.normaltop = element.style.top;
            this.normalleft = element.style.left;
            var pagecontainer = document.getElementById("PageContainer");
            var offset = Qva.GetAbsolutePageCoords(pagecontainer).y;
            var windowtop = Qva.GetScrollTop();
            var height = Qva.GetViewportHeight();
            var width = Qva.GetViewportWidth();
            var left = Qva.GetScrollLeft();
            var top = Math.max(windowtop - offset, 0);
            element.style.top = top + "px";
            element.style.left = left + "px";
            if (windowtop < offset) height -= (offset - windowtop);
            height -= element.offsetHeight - getClientHeight(element);
            height -= 7;
            element.style.height = height + "px";
            width -= element.offsetWidth - getClientWidth(element);
            width -= 6;
            element.style.width = width + "px";
            window.scrollTo(left, windowtop);
        }
    } else if (this.Maximized) {
        if (element.Chart) element.Chart.src = "";
        element.style.top = this.normaltop;
        element.style.left = this.normalleft;
        element.style.height = this.normalheight;
        element.style.width = this.normalwidth;
        if (this.maxclientheight) {
            element.maxclientheight = this.maxclientheight;
            this.maxclientheight = null;
        }
        if (element.maxclientwidth) {
            element.maxclientwidth = this.maxclientwidth;
            this.maxclientwidth = null;
        }
        this.normalheight = null;
        this.normalwidth = null;
        this.normaltop = null;
        this.normalleft = null;
    } else {
        var rects = node.getElementsByTagName("rect");
        var rect = null;
        if (rects.length > 0) {
            rect = rects[0];
            if (this.rect == null) {
                // first run
                element.style.left = parseFloat(rect.getAttribute("left")) + "pt";
                element.style.top = parseFloat(rect.getAttribute("top")) + "pt";
                element.style.width = parseFloat(rect.getAttribute("width")) + "pt";
                element.style.height = parseFloat(rect.getAttribute("height")) + "pt";
            } else if (rect != this.rect) {
                // changed rect
                element.maxclientheight = null;
                element.maxclientwidth = null;
                if (rect.getAttribute("left") != this.rect.getAttribute("left"))
                    element.style.left = parseFloat(rect.getAttribute("left")) + "pt";
                if (rect.getAttribute("top") != this.rect.getAttribute("top"))
                    element.style.top = parseFloat(rect.getAttribute("top")) + "pt";
                if (rect.getAttribute("width") != this.rect.getAttribute("width"))
                    element.style.width = parseFloat(rect.getAttribute("width")) + "pt";
                if (rect.getAttribute("height") != this.rect.getAttribute("height"))
                    element.style.height = parseFloat(rect.getAttribute("height")) + "pt";
            }
            var zindex = parseInt(rect.getAttribute("zindex"));
            if (zindex) {
                element.style.zIndex = zindex;
            }
        }
        this.rect = rect;
    }
    this.Maximized = node.getAttribute("maximized") == "true" && document.getElementById("PageContainer") != null;
    this.Simplified = node.getAttribute('simple') == "true";
    if (node.getAttribute('bordercolor')) {
        element.BorderColor = node.getAttribute('bordercolor');
        if (this.Simplified) {
            element.ActiveBorderColor = node.getAttribute('activebordercolor');
        }
        if (node.getAttribute('borderstyle')) {
            element.BorderStyle = node.getAttribute('borderstyle');
            if (node.getAttribute('borderwidth')) {
                element.BorderWidth = node.getAttribute('borderwidth');
                this.Dirty = true;
                Qva.QueuePostPaintMessage(this);
            }
        }
    }
    if (!element.avqbackground && !isContained) {
        var resizer = element.firstChild;
        if (resizer && resizer.className != "ResizeFrame") resizer = null;
        if (node.getAttribute("allowresize") == "true") {
            Qva.Mgr.CreateAndUpdateResizeHandles(element);
        } else {
            if (resizer) element.removeChild(resizer);
        }
        Qva.Mgr.CreateOrDeleteMoveHandle(element, node.getAttribute("allowmove") == "true")
    }
}

Qva.Mgr.edit = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
    owner.Append (this, this.Name, 'choice');
    this.InlineStyle = owner.InlineStyle;
    if (elem.getAttribute ('AvqStyle')) {
        this.InlineStyle = elem.getAttribute ('AvqStyle') == "true";
    }
}

Qva.Mgr.edit.prototype.Paint = function(mode, node, name) {
    this.Touched = true;
    var element = this.Element;
    if (name == this.ToolTip && node.getAttribute ('text')) {
        element.title = node.getAttribute ('text');
        return;
    }
    var attrValue = '';
    if (mode != 'n') {
        attrValue = node.getAttribute (this.Attr);
        switch (this.Attr) {
        case 'value':
            if (node.getAttribute ('text') == '') attrValue = '';
            break;
        case 'color':
            if (node.getAttribute ('color') && node.getAttribute ('bkgcolor')) {
                element.style.color = node.getAttribute ('color');
                element.style.backgroundColor = node.getAttribute ('bkgcolor');
                return;
            }
        }
    }
    if (attrValue == '' && this.TextIfNull) attrValue = this.TextIfNull;
    var text;
    if (this.Dec != null) {
        text = Qva.Trunc (attrValue, this.Dec);
    } else {
        text = attrValue;
    }
    element.innerText = text;
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    if (node.getAttribute ('paddingTop')) element.style.paddingTop = node.getAttribute ('paddingTop') + "pt";
    if (node.getAttribute ('paddingLeft')) element.style.paddingLeft = node.getAttribute ('paddingLeft') + "pt";
    if (node.getAttribute ('paddingRight')) element.style.paddingRight = node.getAttribute ('paddingRight') + "pt";
    if (node.getAttribute ('paddingBottom')) element.style.paddingBottom = node.getAttribute ('paddingBottom') + "pt";
    if (this.InlineStyle) {
        setStyle (node, element);
    }
}

Qva.Mgr.inputcheckbox = function (owner, elem, name, prefix, condition) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Element = elem;
    owner.AddManager(this);
    if (condition != null) {
        var sep = condition.substr(1,1);
        var parts = condition.split(sep);
        this.Conditional = (parts[0] == '-') ? -1 : 1;
        var alt1 = (parts.length > 1) ? parts[1] : '';
        var alt2 = (parts.length > 2) ? parts[2] : null;
        elem.True = (this.Conditional > 0) ? alt1 : alt2;
        elem.False = (this.Conditional < 0) ? alt1 : alt2;
    } else {
        this.Conditional = 0;
        elem.True = '1';
        elem.False = '0';
        this.Attr = 'value';
    }
    
    elem.Name = this.Name;
    elem.Attr = this.Attr;
    elem.binderid = owner.ID;
    
    elem.onclick = Qva.Mgr.inputcheckbox.OnClick;
    owner.Append (this, this.Name, 'choice');
}

Qva.Mgr.inputcheckbox.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.inputcheckbox.prototype.Unlock = Qva.UnlockDisabled;
Qva.Mgr.inputcheckbox.prototype.Paint = function(mode, node) {
    this.Touched = true;
    var element = this.Element;
    var val = node.getAttribute (this.Attr);
    if (this.Conditional < 0) {
        element.checked = (val != element.False);
    } else {
        element.checked = (val == element.True);
    }
    var choices = node.getElementsByTagName ("choice");
    if (choices.length == 0) {
        element.disabled = (mode != 'e');
    } else {
        choices = choices[0].getElementsByTagName ("element");
        var range = choices.length;
        if (range > 1) {
            element.disabled = (mode != 'e');
        } else {
            element.disabled = true;
        }
    }
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
}

Qva.Mgr.inputcheckbox.OnClick = function() {
    var binder = Qva.GetBinder(this.binderid);
    if (!binder.Enabled) return;
    var newval = this.checked ? this.True : this.False;
    if (newval != null) {
        binder.Set (this.Name, this.Attr, newval, true);
    } else {
        newval = this.checked ? this.False : this.True;
        binder.Set (this.Name, 'count', '-' + newval, true);
    }
}

Qva.Mgr.inputradio = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Element = elem;
    elem.Name = this.Name;
    elem.Attr = this.Attr;
    elem.binderid = owner.ID;
    owner.AddManager(this);
    
    elem.onclick = function () {
        if (!IS_GECKO && this.checked) return;
        var binder = Qva.GetBinder(this.binderid);
        if (!binder.Enabled) return;
        binder.Set (this.Name, this.Attr, this.value, true);
    };
    owner.Append (this, this.Name, 'choice');
}

Qva.Mgr.inputradio.prototype.PostScan = function(scanner) {
    var CheckIf = this.Element.getAttribute (scanner.Prefix + 'checkif');
    if (CheckIf) {
        this.CheckIf = new Function("value", "return " + CheckIf);
    }
}

Qva.Mgr.inputradio.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.inputradio.prototype.Unlock = Qva.UnlockDisabled;
Qva.Mgr.inputradio.prototype.Paint = function(mode, node) {
    this.Touched = true;
    var element = this.Element;
    var value = node.getAttribute(this.Attr);
    if (this.CheckIf) {
        element.checked = this.CheckIf(value);
    } else {
        element.checked = (element.value == value);
    }
    element.disabled = (mode != 'e');
    if (mode == 'e' && !element.checked) {
        // check if should be disabled because not in choice
        var choices = node.getElementsByTagName ("choice");
        if (choices.length >= 1) {
            element.disabled = true;
            choices = choices[0].getElementsByTagName ("element");
            var cholen = choices.length;
            for (var ix = 0; ix < cholen; ++ix) {
                if (choices [ix].getAttribute(this.Attr) == element.value) {
                    element.disabled = false;
                    break;
                }
            }
        }
    }
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
}

Qva.Mgr.inputtext = function (owner, elem, name, prefix, condition) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Element = elem;
    this.Condition = condition;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    elem.Attr = this.Attr;
    
    owner.AddManager(this);
    elem.onclick = function (event) {
        Qva.ActiveObject = null;
        if (!event) event = window.event;
        event.cancelBubble = true;
    };
    elem.onchange = function () {
        var binder = Qva.GetBinder(this.binderid);
        if (!binder.Enabled) return;
        if (this.value == '') {
            binder.Set(this.Name, 'text', '', true);
        } else {
            binder.Set(this.Name, this.Attr, this.value, true);
        }
    };
}
Qva.Mgr.inputtext.prototype.Lock = Qva.LockReadOnly;
Qva.Mgr.inputtext.prototype.Unlock = Qva.UnlockReadOnly;
Qva.Mgr.inputtext.prototype.Paint = function(mode, node) {
    this.Touched = true;
    var element = this.Element;
    element.readOnly = (mode != 'e');
    element.disabled = false;
    var attrValue = '';
    if (mode != 'n') {
        attrValue = node.getAttribute (this.Attr);
        if (this.Attr == 'value' && node.getAttribute ('text') == '') attrValue = '';
    }
    if (mode != 'n' && this.Condition != null) {
        var cval = node.getAttribute ('value');
        if (cval == this.Condition) {
            element.disabled = true;
            attrValue = '';
        }
    }
    if (attrValue == '' && this.TextIfNull) attrValue = this.TextIfNull;
    if (this.Dec != null) {
        element.value = Qva.Trunc (attrValue, this.Dec);
    } else {
        element.value = attrValue;
    }
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    setStyle (node, element);
}

function Avq_Search_Focus (event) {
    var binder = this.AvqMgr.PageBinder;
    var name = this.AvqMgr.Name.replace (".Input", "");
    if (this.value == this.AvqMgr.DefaultText) {
        this.style.fontStyle = "";
        this.style.color = "";
        this.value = "**";
        Qva.SetCursor (this);
        binder.Set (name, "click", "", true);
    }
    binder.GlobaSearchObject = name;
}

function WebkitClickFix (event) {
    if (this.value == "**") {
        Qva.SetCursor (this);
    }
}

function Avq_Search_KeyDown(event) {
    if (! event) { 
        event = window.event; 
    }
    var mgr = this.AvqMgr;
    if (this.value == mgr.DefaultText) {
        this.value = "**";
        Qva.SetCursor (this);
        this.style.fontStyle = "";
        this.style.color = "";
    }
    var key = event.keyCode;
    var accept = false;
    switch (key) {
    case 13:    // <Enter>
        accept = true;
    case 27:    // <Escape>'
        var binder = mgr.PageBinder || Qva.GetBinder(mgr.binderid);
        if (binder.Enabled) {
	        if (accept) binder.Set (mgr.SearchName, "search", this.value, false);
	        var cmd = accept ? "accept" : "abort";
            binder.Set (mgr.SearchName, "closesearch", cmd, true);
        }
        this.value = mgr.DefaultText;
        this.style.fontStyle = mgr.DefaultFontStyle;
        this.style.color = mgr.DefaultColor;
        binder.GlobaSearchObject = "";
        break;
    }
}

Qva.Mgr.inputsearch = function (owner, elem, name, prefix, condition) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Element = elem;
    this.Condition = condition;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    elem.Attr = this.Attr;
    elem.onkeydown = Avq_Search_KeyDown;
    elem.onkeyup = AvqAction_Search_KeyUp;
    elem.onfocus = Avq_Search_Focus;
    if (IS_SAFARI || IS_CHROME) {
        elem.onclick = WebkitClickFix;
    } else {
        elem.onclick = Qva.CancelAction;
    }
    elem.AvqMgr = this;
    this.SearchName = this.Name;
    owner.AddManager(this);
}

Qva.Mgr.inputsearch.prototype.PostPaint = function () {
    // A rather ugly way to get to the table parent
    var element = this.Element;
    var parentNode = element.parentNode.parentNode.parentNode.parentNode.parentNode;
    if (parentNode.tagName == "DIV" && parentNode.className == "content") {
        var newheight = parseInt (getContentMaxHeight (parentNode));
        if (! isNaN (newheight)) {
            parentNode.style.height = newheight + "px";
        }
        var objectframeNode = parentNode.parentNode;
        setContentWidth (objectframeNode);
    }
}

Qva.Mgr.inputsearch.prototype.Paint = function (mode, node) {
    this.Touched = true;
    var element = this.Element;
    element.readOnly = (mode != 'e');
    element.disabled = false;

    if (! this.DefaultText) {
        this.DefaultText = node.getAttribute ("defaulttext");
    }
    if (! this.DefaultFontStyle) {
        this.DefaultFontStyle = node.getAttribute ("fontstyle");
    }
    if (! this.DefaultColor) {
        this.DefaultColor = node.getAttribute ("color");
    }
    if (node.getAttribute ("searching") != "true") {
        element.value = this.DefaultText;
        this.DefaultFontStyle = node.getAttribute ("fontstyle");
        this.DefaultColor = node.getAttribute ("color");
    } else {
        this.PageBinder.GlobaSearchObject = this.Name.replace (".Input", "");
    }
    setStyle (node, element);
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    
    if (node.parentNode.getAttribute ("allowmove") == "false") {
        element.onmousedown = null;
    }
    Qva.QueuePostPaintMessage (this);
}

Qva.Mgr.searchresults = function (owner, elem, name, prefix, condition) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Element = elem;
    this.Condition = condition;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    elem.Attr = this.Attr;
    if (! elem.SO) {
        var parentid = elem.id.replace ("_results", "_frame");
        elem.SO = window.document.getElementById (parentid);
    }
    owner.AddManager(this);
}

Qva.Mgr.searchresults.prototype.Paint = function (mode, node) {
    this.Touched = true;
    var element = this.Element;
    var minheight = 100;
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    element.style.left = element.SO.style.left;
    element.style.width = element.SO.style.width;
    var freespace = Qva.GetViewportHeight() + Qva.GetScrollTop () - (element.SO.offsetTop + element.SO.clientHeight) - 40;
    if (freespace > minheight) {
        element.style.top = (element.SO.offsetTop + element.SO.clientHeight) + "px";
//        element.style.height = Qva.GetViewportHeight () - (parseInt (element.style.top) - Qva.GetScrollTop ()) - 40 + "px";
        element.style.height = freespace + "px";
    } else {
        element.style.height = element.SO.offsetTop + "px";
        setTimeout(function() {element.style.top = (element.SO.offsetTop - element.clientHeight) + "px";},0);
    }
}

Qva.Mgr.textarea = Qva.Mgr.inputtext;
Qva.Mgr.inputpassword = Qva.Mgr.inputtext;

Qva.Mgr.text = function (owner, elem, name, prefix, tooltip) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    if (tooltip != null) {
        this.ToolTip = Qva.MgrMakeName (tooltip, prefix);
        owner.Append (this, this.ToolTip);
    }
    if (elem.tagName == 'SELECT') { debugger; }
    owner.AddManager(this);
    this.Element = elem;
    owner.Append (this, this.Name, 'value');
    this.InlineStyle = owner.InlineStyle;
    if (elem.getAttribute ('AvqStyle')) {
        this.InlineStyle = elem.getAttribute ('AvqStyle') == "true";
    }
}

Qva.Mgr.text.prototype.Paint = Qva.Mgr.edit.prototype.Paint;

Qva.Mgr.step = function (owner, elem, name, prefix, step) {
    switch (step) {
    case "next":
        this.Next = true;
        break;
    case "prev":
        this.Next = false;
        break;
    default:
        elem.Step = parseFloat (step);
        if (isNaN (elem.Step)) return;
        break;
    }
    if (!Qva.MgrSplit (this, name, prefix)) return;
    if (elem.Step == null) elem.Choice = new Array();
    owner.AddManager(this);
    this.Element = elem;
    
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    elem.Attr = this.Attr;
    elem.onclick = Qva.Mgr.step.OnClick;
    owner.Append (this, this.Name, 'choice');
}

Qva.Mgr.step.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.step.prototype.Unlock = Qva.UnlockDisabled;
Qva.Mgr.step.prototype.Paint = function(mode, node) {
    this.Touched = true;
    var element = this.Element;
    element.disabled = (mode != 'e');
    if (mode == 'n') {
        // no action
    } else if (element.Step != null) {
        element.Last = parseFloat (node.getAttribute (this.Attr));
    } else {
        var value = node.getAttribute (this.Attr);
        var choiceNodes = node.getElementsByTagName ("choice");
        element.Pending = -1;
        if (choiceNodes.length >= 1) {
            var choices = choiceNodes[0].getElementsByTagName ("element");
            var height = choices.length;
            for (var rix = 0; rix < height; ++rix) {
                element.Choice [rix] = choices[rix].getAttribute(this.Attr);
                if (choices[rix].getAttribute("selected") == "yes") {
                    if (this.Next) {
                        element.Pending = rix + 1;
                    } else {
                        element.Pending = rix - 1;
                    }
                }
            }
            element.Choice.length = height;
        }
        if (element.Pending < 0 || element.Pending >= element.Choice.length) element.disabled = true;
    }
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
}

Qva.Mgr.step.OnClick = function() {
    var binder = Qva.GetBinder(this.binderid);
    if (!binder.Enabled) return;
    var newval;
    if (this.Step != null) {
        newval = this.Last + this.Step;
    } else {
        if (this.Pending < 0 || this.Pending >= this.Choice.length) return;
        newval = this.Choice[this.Pending];
    }
    binder.Set (this.Name, this.Attr, '' + newval, true);
}

Qva.Mgr.actions = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Attr = "mode";
    owner.AddManager(this);
    this.Element = elem;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
}

Qva.Mgr.actions.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.actions.prototype.Unlock = Qva.UnlockDisabled;
Qva.Mgr.actions.prototype.Paint = function (mode, node) {
    this.Touched = true;
    var element = this.Element;
    element.disabled = (mode != 'e');
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    if (node.getAttribute ('actions') == "true") {
        element.style.cursor = 'hand';
        element.onclick = onclick_action;
    }
}

Qva.Mgr.scroll = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
}

Qva.Mgr.scroll.prototype.Paint = function (mode, node) {
    this.Touched = true;
    var element = this.Element;
    if (node.getAttribute ('overflowx')) {
        element.style.overflowX = node.getAttribute ('overflowx');
    }
    if (node.getAttribute ('overflowy')) {
        element.style.overflowY = node.getAttribute ('overflowy');
    }
}

Qva.Mgr.action = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Attr = "mode";
    owner.AddManager(this);
    this.Element = elem;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    elem.onclick = onclick_action;
    owner.Append (this, this.Name, 'action');
}

Qva.Mgr.action.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.action.prototype.Unlock = Qva.UnlockDisabled;
Qva.Mgr.action.prototype.Paint = function (mode, node) {
    this.Touched = true;
    var element = this.Element;
    element.disabled = (mode != 'e');
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    if (node.getAttribute ('clientaction')) {
        element.onclick = onclick_ContextClientAction;
        element.Name = this.Name;
        element.AvqMgr = this;
        element.clientaction = node.getAttribute ('clientaction');
        element.param = node.getAttribute ("param");
    }
    setStyle (node, element);
}

Qva.Mgr.restore = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Attr = "mode";
    owner.AddManager(this);
    this.Element = elem;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    elem.moveObj = elem.id;
    owner.Append (this, this.Name, 'action');
}

Qva.Mgr.restore.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.restore.prototype.Unlock = Qva.UnlockDisabled;
Qva.Mgr.restore.prototype.Paint = function (mode, node) {
    this.Touched = true;
    var element = this.Element;
    element.disabled = (mode != 'e');
    element.style.display = node.getAttribute ("stamp") ? Qva.MgrGetDisplayFromMode (this, mode) : "none";
    if (node.getAttribute("left")) element.style.left = parseFloat(node.getAttribute("left")) + "pt";
    if (node.getAttribute("top")) element.style.top = parseFloat(node.getAttribute("top")) + "pt";
    if (node.getAttribute("width")) element.style.width = parseFloat(node.getAttribute("width")) + "pt";
    if (node.getAttribute("height")) element.style.height = parseFloat(node.getAttribute("height")) + "pt";

    element.oncontextmenu = function (event) { return Qva.GetBinder(this.binderid).OnContextMenu(event, this.Name.replace (".RE", "")); }
    if (node.getAttribute ("allowmove") == "true") {
        element.onmousedown = Qva.Move.mouseDown;
    } else {
        element.onmousedown = null;
    }
}

Qva.Mgr.select = function (owner, elem, name, prefix, condition) {
    if (elem.multiple) { debugger; return; }
    //if (elem.size > 1) { debugger; return; }
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
    this.Condition = condition;
    this.Texts = new Array ();
    this.Values = new Array ();
    this.Disabled = new Array ();
    this.Locked = new Array ();
    
    elem.binderid = owner.ID;
    elem.Name = this.Name;
    
    elem.onchange = Qva.Mgr.select.OnChange;
    elem.onclick = Qva.CancelBubble;
}

Qva.Mgr.select.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.select.prototype.Unlock = Qva.UnlockDisabled;
Qva.Mgr.select.prototype.Paint = function(mode, node) {
    this.Touched = true;
    var element = this.Element;
    if (mode != 'n' && element.ByValue == null) {
        element.ByValue = (node.getAttribute('value') != null);
    }
    setStyle (node, element);
    var currentValue = node.getAttribute("text");
    if (this.Dec != null) currentValue = Qva.Trunc (currentValue, this.Dec);
    if (currentValue == null) currentValue = "";
    if (this.TextIfNull && currentValue == "") currentValue = this.TextIfNull;
    var optlen = element.options.length;
    if (mode == 'e' && (this.Condition == null || currentValue != '')) {
        var choices = node.getElementsByTagName ("choice");
        if (choices.length >= 1) choices = choices[0].getElementsByTagName ("element");
        var first = (this.Condition == null) ? 0 : 1;
        var cholen = choices.length - first;
        element.options.length = cholen;
        if (cholen >= 1) {
            this.SelectedIndex = -1;
            for (var ix = 0; ix < cholen; ++ix) {
                var cho = choices [ix + first];
                var optval = cho.getAttribute("text");
                if (this.TextIfNull && optval == "") optval = this.TextIfNull;
                if (this.Dec != null) optval = Qva.Trunc (optval, this.Dec);
                var opt = element.options [ix];
                opt.text = optval.replace (/\t/g, ' ');
                opt.value = element.ByValue ? cho.getAttribute('value') : optval;
                var selected = false;
                if (optval == currentValue) {
                    this.SelectedIndex = ix;
                    selected = true;
                }
                if (selected) opt.selected = true;
            }
            if (this.SelectedIndex == -1) {
                element.options [cholen-1].selected = true;
            }
        }
        element.disabled = false;
    } else {
        element.disabled = true;
        if (optlen < 1 || this.Condition != null) {
            element.options.length = 1;
            var opt0 = element.options [0];
            opt0.text = (currentValue != null) ? currentValue.replace (/\t/g, ' ') : '';
            opt0.value = element.ByValue ? node.getAttribute('value') : currentValue;
            opt0.selected = true;
        }
    }
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
}

Qva.Mgr.select.OnChange = function() {
    var binder = Qva.GetBinder(this.binderid);
    if (!binder.Enabled) return;
    if (this.selectedIndex < 0) return;
    var opt = this.options [this.selectedIndex];
    if (this.ByValue === true) {
        binder.Set (this.Name, 'value', opt.value, true);
    } else {
        binder.Set (this.Name, "text", opt.text, true);
    }
}

Qva.Mgr.binary = function (owner, elem, name, prefix) {
    elem.Name = this.Name = Qva.MgrMakeName (name, prefix);
    elem.binderid = owner.ID;
	if (elem.style.width == 'auto' && elem.style.height == 'auto') elem.autosize = true;
    this.Attr = "mode";
    owner.AddManager(this);
    this.Element = elem;
    var hover = Qva.GetBinder(elem.binderid).GetHoverDiv();
    hover.style.display = "none";
    elem.style.display = "none";
    
    elem.SelectStart = Qva.Mgr.binary.SelectStart;
    elem.Select      = Qva.Mgr.binary.Select;
    elem.SelectEnd   = Qva.Mgr.binary.SelectEnd;
    elem.onclick = function (event) { Qva.GetBinder(this.binderid).SetClick(event, this.Name, this); }
    elem.onmousedown = function (event) { Qva.MouseDown(event, this); }
    elem.onmousemove = function (event) {
        Qva.MouseMove(event, this);
        this.onmouseover(event);
    }
    elem.onmouseover = function (event) {
        if(!this.hover) return;
        if(!event) event = window.event;
        var binder = Qva.GetBinder(this.binderid);
        var name   = this.Name;
        
        var hover = binder.GetHoverDiv();
        hover.style.left = (event.clientX + Qva.GetScrollLeft() + 5) + "px";
        hover.style.top  = (event.clientY + Qva.GetScrollTop() + 5)  + "px";
        hover.style.display = "none";
        
        var pos = Qva.GetPageCoords(this);
        var click = (event.clientX - pos.x) + ':' + (event.clientY - pos.y);
        var objectframeNode = Qva.GetFrame(this);
        var graphwidth = parseInt (imagewidth (objectframeNode, this));
        var graphheight = parseInt (imageheight (objectframeNode, this));
        click += ':' + graphwidth + ':' + graphheight;
        
        if (this.hoverTimout) { this.hoverTimout = clearTimeout(this.hoverTimout); }
        this.hoverTimout = setTimeout(function () {
            if (!binder.Enabled) return;
            if (Qva.ContextMenu != null && Qva.ContextMenu.style.display != 'none') return;
            binder.Set(name, "hover", click, true);
        }, 1000 );
    };
    elem.onmouseout  = function (event) {
        if (this.hoverTimout) { this.hoverTimout = clearTimeout(this.hoverTimout); }
    }
    
    elem.style.cursor = 'crosshair';
    if (owner.IsHosted && ! elem.sizefixed) {
        var objectframeNode = elem.parentNode.parentNode;
        if (elem.style.height != '') {
            var height = imageheight (objectframeNode, elem);
            owner.Append (this, this.Name, 'h' + height + "px");
        }
        if (elem.style.width != '') {
            var width = imagewidth (objectframeNode, elem);
            owner.Append (this, this.Name, 'w' + width + "px", true);
        }
    }
}

Qva.Mgr.binary.prototype.Unlock = function () {
    this.Touched = true;
    if (this.Element.style.display != 'none') {
        this.PostPaint ();
    }
}

GraphScrollBar.prototype.Step = function (pos) {
    var binder = Qva.GetBinder (this.binderid);
    var name   = this.Name;
    var step = pos - this.Pos;
    this.Pos = pos;
    binder.Set(name, "scrollstep", step, true);
}

GraphScrollBar.prototype.createScrollEnd = function (top, left, height, width, color, firstbutton) {
    var div = document.createElement("div");
    if (this.IsXScroll) {
        div.style.top = (top + 1) + "px";
        left++;
        if (! firstbutton) left += (width - height);
        div.style.left = left + "px";
        height -= 2;
        div.style.height = height + "px";
        div.style.width = height + "px";
    } else {
        div.style.left = (left + 1) + "px";
        top++;
        if (! firstbutton) top += (height - width);
        div.style.top = top + "px";
        width -= 2;
        div.style.height = width + "px";
        div.style.width = width + "px";
    }
    div.style.backgroundColor = color;
    div.style.cursor = "pointer";
    div.style.position = "absolute";
    div.firstbutton = firstbutton;

    var position, points;
    if (this.IsXScroll) {
        position = [parseInt (height / 2) - 1, parseInt (height / 2) - 3];
        points = firstbutton ? [[2,0], [0,3], [2,6]] : [[0,0], [2,3], [0,6]];
    } else {
        position = [parseInt (width / 2) - 3, parseInt (width / 2)];
        points = firstbutton ? [[0,2], [3,0], [6,2]] : [[0, 0], [3,2], [6, 0]];
    }
    var size = [9, 9];
    this.G.CreatePolygonObj (points, "#000000", div, position, size);
    var _this = this;
    div.onmousedown = function (event) {
        if (!event) event = window.event;
        event.cancelBubble = true;
        var pos = this.firstbutton ? _this.Pos - 1 : _this.Pos + 1;
        if (pos >= 0) {
            _this.Step (pos);
        }
        return false;
    };
    return div;
}

function GraphScrollBar (mgr, parent, top, left, width, height, color, bkgcolor, max, page, isxscroll) {
    var o_scroll = document.createElement("div");
    o_scroll.style.backgroundColor = bkgcolor;
    o_scroll.style.cursor = "pointer";
    o_scroll.style.position = "absolute";

//    this.binderid = mgr.binderid;
    this.binderid = mgr.Element.binderid;
    this.Name = mgr.Name;
    this.IsXScroll = isxscroll;
    var _this = this;

    this.G = SelectInitGraphics();

    o_scroll.onmousedown = function (event) {
        if (!event) event = window.event;
        event.cancelBubble = true;
        var relpos = Qva.GetPageCoords(this);
        var px;
        var scrollpos;
        if (_this.IsXScroll) {
            px = event.clientX - relpos.x;
            scrollpos = parseInt(_this.i_Scroll.style.left);
        } else {
            px = event.clientY - relpos.y;
            scrollpos = parseInt(_this.i_Scroll.style.top);
       }
        var pos = px < scrollpos ? _this.Pos -_this.Page : _this.Pos +_this.Page;
        if (pos >= 0) {
            _this.Step (pos);
        }
        return false;
    };

    var i_scroll = document.createElement("div");
    i_scroll.style.backgroundColor = color;
    i_scroll.style.border = "solid 1px white";
    i_scroll.style.cursor = "pointer";
    i_scroll.style.position = "absolute";

    i_scroll.onmousedown = function(event) {
        if (!event) event = window.event;
        event.cancelBubble = true;
        if (_this.IsXScroll) {
            i_scroll.mouseZero = event.clientX;
            i_scroll.scrollZero = i_scroll.offsetLeft;
        } else {
            i_scroll.mouseZero = event.clientY;
            i_scroll.scrollZero = i_scroll.offsetTop;
        }

        function Update (event, mouseup) {
            if (!event) event = window.event;
            var px, pos;
            if (_this.IsXScroll) {
                px = i_scroll.scrollZero + event.clientX - i_scroll.mouseZero;
            } else {
                px = i_scroll.scrollZero + event.clientY - i_scroll.mouseZero;
            }
            if (px < _this.ScrollStart) {
                px = _this.ScrollStart;
                pos = 0;
            } else if (px > _this.ScrollStop) {
                px = _this.ScrollStop;
                pos = _this.Max - _this.Page;
            } else {
                pos = Math.round ((px - _this.ScrollStart) * _this.Page / _this.ScrollLength);
            }
            if (_this.IsXScroll) {
                i_scroll.style.left = px + "px";
            } else {
                i_scroll.style.top = px + "px";
            }
            if (_this.Pos != pos) {
                _this.Step (pos);
            } else if (mouseup) {
                _this.UpdateScrollPos ();
            }
        }
        
        function SlideEnd(event) {
            Qva.removeEvent(document,"mousemove",SlideDrag);
            Qva.removeEvent(document,"mouseup",SlideEnd);
            Update (event, true);
            _this.i_Scroll.mouseZero = null;
            Qva.Select.Active = true;
        }
        function SlideDrag(event) {
            Update (event, false);
            
            event = event || window.event;
            if (event.preventDefault) 
                event.preventDefault();
            else
                event.returnValue = false;
            return false;
        }
        Qva.Select.Active = false;
        Qva.addEvent(document,"mousemove",SlideDrag);
        Qva.addEvent(document,"mouseup",SlideEnd);
        return false;
    }

    this.o_Scroll = o_scroll;
    this.i_Scroll = i_scroll;
    parent.appendChild (o_scroll);
    parent.appendChild (i_scroll);

    this.UpdateScrollSize (top, left, width, height, max, page, 0, color, bkgcolor);
}

GraphScrollBar.prototype.UpdateScrollPos = function (pos) {
    if (! isNaN (pos)) this.Pos = pos;
    var newstart = parseInt (this.Pos * this.ScrollLength / this.Page) + this.ScrollStart;
    if (newstart > this.ScrollStop) newstart = this.ScrollStop; 
    if (this.IsXScroll) {
        this.i_Scroll.style.left = newstart + "px";
    } else {
        this.i_Scroll.style.top = newstart + "px";
    }
}

GraphScrollBar.prototype.UpdateScrollSize = function (top, left, width, height, max, page, pos, color, bgColor) {
    if (this.Top != top || this.Left != left || this.Height != height || this.Width != width) {
        this.Height = height;
        this.Top = top;
        this.Left = left;
        this.Width = width;
        this.o_Scroll.style.height = height + "px";
        this.o_Scroll.style.top = top + "px";
        this.o_Scroll.style.left = left + "px";
        this.o_Scroll.style.width = Math.max(0, width) + "px";
        if (this.IsXScroll) {
            this.i_Scroll.style.height = Math.max (1, height - 4) + "px";
            this.i_Scroll.style.top = top + 1 + "px";
            this.i_Scroll.style.left = (height + left) + "px";
        } else {
            this.i_Scroll.style.top = (width + top) + "px";
            this.i_Scroll.style.left = (left + 1) + "px";
            this.i_Scroll.style.width = Math.max (1, width - 4) + "px";
        }
        var parent = this.o_Scroll.parentNode;
        if (this.firstbutton) {
            parent.removeChild (this.firstbutton);
            parent.removeChild (this.lastbutton);
        }
        var firstbutton = this.createScrollEnd (top, left, height, width, color , true);
        var lastbutton = this.createScrollEnd (top, left, height, width, color, false);
        this.firstbutton = firstbutton;
        this.lastbutton = lastbutton;
        parent.appendChild (firstbutton);
        parent.appendChild (lastbutton);
    }

    this.Page = page;
    this.Max = max;
    var maxpos = this.Max - this.Page;
    if (this.IsXScroll) {
        this.ScrollStart = this.o_Scroll.offsetLeft + parseInt (this.Height);
        this.ScrollLength = parseFloat ((this.Width - 2 * (this.Height)) * this.Page / this.Max);
        this.ScrollLengthVisible = (this.ScrollLength > 5) ? parseInt(this.ScrollLength) : 5
        this.ScrollStop = parseInt (maxpos * this.ScrollLength / this.Page) + this.ScrollStart - (this.ScrollLengthVisible - parseInt(this.ScrollLength));
        this.i_Scroll.style.width = this.ScrollLengthVisible + "px";
    } else {
        this.ScrollStart = this.o_Scroll.offsetTop + parseInt (this.Width);
        this.ScrollLength = parseFloat ((this.Height - 2 * (this.Width)) * this.Page / this.Max);
        this.ScrollLengthVisible = (this.ScrollLength > 5) ? parseInt(this.ScrollLength) : 5
        this.ScrollStop = parseInt (maxpos * this.ScrollLength / this.Page) + this.ScrollStart - (this.ScrollLengthVisible - parseInt(this.ScrollLength));
        this.i_Scroll.style.height = this.ScrollLengthVisible + "px";
    }
    if (bgColor) this.o_Scroll.style.backgroundColor = bgColor;
    this.i_Scroll.style.backgroundColor = color;
    this.firstbutton.style.backgroundColor = color;
    this.lastbutton.style.backgroundColor = color;
    this.UpdateScrollPos (pos);
}

GraphScrollBar.prototype.GetOffset = function (px) {
    var totlength;
    if (this.IsXScroll) {
        totlength = this.o_Scroll.offsetWidth - 2 * this.Height;
    } else {
        totlength = this.o_Scroll.offsetHeight - 2 * this.Width;
    }
    return Math.round(this.Page * px / totlength);
}

Qva.Mgr.binary.prototype.Paint = function (mode, node) {
    this.Touched = true;
    var element = this.Element;
    var disabled = (mode != 'e');
    element.disabled = disabled;
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    if (element.style.display == 'none') {
        return;
    }
    if (element.autosize) {
        var objectframeNode = element.parentNode.parentNode;
        setFrameWidth (objectframeNode, 0);
        setFrameHeight (objectframeNode, 0);
    }
    if (node.getAttribute ("selectable") == "false") { 
        element.style.cursor = '';
        element.SelectStart = null;
        element.Select      = null;
        element.SelectEnd   = null;
        element.onmousedown = null;
        element.onmousemove = null;
    } 
    if (node.getAttribute ('clientaction')) {
        element.onclick = onclick_ContextClientAction;
        element.Name = this.Name;
        element.AvqMgr = this;
        element.clientaction = node.getAttribute ('clientaction');
        element.param = node.getAttribute ("param");
    }
    
    element.hover = node.getAttribute ('hover') === "true";
    var scrollnode = node.getElementsByTagName("xscroll") [0];
    var isxscroll = true;
    if (! scrollnode) {
        scrollnode = node.getElementsByTagName("yscroll") [0];
        isxscroll = false;
    }
    if (scrollnode) {
        if (this.ScrollBar && this.ScrollBar.IsXScroll != isxscroll) {
            element.parentNode.removeChild (this.ScrollBar.o_Scroll);
            element.parentNode.removeChild (this.ScrollBar.i_Scroll);
            element.parentNode.removeChild (this.ScrollBar.firstbutton);
            element.parentNode.removeChild (this.ScrollBar.lastbutton);
            this.ScrollBar = null
        } 
        var max = parseInt (scrollnode.getAttribute ("max"));
        var page = parseInt (scrollnode.getAttribute ("page"));
        var top = parseInt (scrollnode.getAttribute ("top"));
        var left = parseInt (scrollnode.getAttribute ("left"));
        var height = parseInt (scrollnode.getAttribute ("height"));
        var width = parseInt (scrollnode.getAttribute ("width"));
        var color = scrollnode.getAttribute ("color");
        var bkgcolor = scrollnode.getAttribute ("bkgcolor");
        if (! this.ScrollBar) {
            if (width > 2 && height > 2) {
                this.ScrollBar = new GraphScrollBar (this, element.parentNode, top, left, width, height, color, bkgcolor, max, page, isxscroll);
            }
        } else {
            if (! this.ScrollBar.i_Scroll.mouseZero) {
                this.ScrollBar.UpdateScrollSize (top, left, width, height, max, page, parseInt (scrollnode.getAttribute ("pos")), color, bkgcolor)
            }
        }
    } else {
        if (this.ScrollBar) {
            element.parentNode.removeChild (this.ScrollBar.o_Scroll);
            element.parentNode.removeChild (this.ScrollBar.i_Scroll);
            element.parentNode.removeChild (this.ScrollBar.firstbutton);
            element.parentNode.removeChild (this.ScrollBar.lastbutton);
        }
        this.ScrollBar = null
    }
    var stamp = node.getAttribute ('stamp');
    if (stamp != "0") {
        var name = stamp ? this.Name : node.getAttribute ('name');
        if (element.disabled ) name += ".DISABLED";
        var url = this.PageBinder.BuildBinaryUrl (node.getAttribute ('path'), stamp, name);
        this.avq_url = url;
    }
    Qva.QueuePostPaintMessage (this);
}

Qva.Mgr.binary.prototype.PostPaint = function () {
    var elem = this.Element;
    if (elem.style.display == 'none') return;
    var imageelem = null;
    var isbutton = false;
    if (elem.tagName == "BUTTON" || elem.tagName == "DIV") {
        for (var i = 0; i < elem.childNodes.length; i++) {
            if (elem.childNodes [i].tagName == "IMG") {
                imageelem = elem.childNodes [i];
                break;
            }
        }
        isbutton = true;
        elem.style.cursor = elem.disabled ? "default" : "";
    } else {
        imageelem = elem;
    }
    elem.isgraph = ! isbutton;
    var parentNode = elem.parentNode;
    var objectframeNode = parentNode.parentNode;
    if (elem.autosize) {
        if (parentNode.tagName == "DIV") {
            var newheight = parseInt (getContentMaxHeight (parentNode));
            if (! isNaN (newheight)) {
                parentNode.style.height = newheight + "px";
            }
        }
        setContentWidth (objectframeNode, getMaxClientWidth (objectframeNode));
    }
    if (imageelem) {
        var url = this.avq_url;
        var sizeupdated = false;
        var sendsizetoserver = this.PageBinder.IsHosted || ! isbutton;
        if (elem.style.width != '') {
            var graphwidth = imagewidth (objectframeNode, elem);
            if ((IS_GECKO || IS_CHROME) && isbutton) {
                graphwidth -= 3;
            }
            if (sendsizetoserver && this.GraphWidth != graphwidth) {
                this.GraphWidth = graphwidth;
                sizeupdated = true;
            }
            if (! this.PageBinder.IsHosted) {
                url += '&width=' + escape (graphwidth);
            } else {
                imageelem.style.width = graphwidth + "px";
                elem.sizefixed = true;
            }
        }
        if (elem.style.height != '') {
            var graphheight = imageheight (objectframeNode, elem);
            if ((IS_GECKO || IS_CHROME) && isbutton) {
                graphheight -= 1;
            }
            if (sendsizetoserver && this.GraphHeight != graphheight) {
                this.GraphHeight = graphheight;
                sizeupdated = true;
            }
            if (! this.PageBinder.IsHosted) {
                url += '&height=' + escape (graphheight);
            } else {
                imageelem.style.height = graphheight + "px";
                elem.sizefixed = true;
            }
        }
        if (this.avq_url) {
            imageelem.src = url;
        }
        if (sizeupdated) {
            this.PageBinder.Set (this.Name, 'size', this.GraphWidth + ":" + this.GraphHeight, true);
        }
    } else {
        debugger;
    }
    if (imageelem) imageelem.style.display = "block";
}

Qva.Mgr.binary.SelectStart = function (X, Y) { Qva.OpenDragRect(X, Y); }
Qva.Mgr.binary.Select      = function (X, Y) { Qva.SizeDragRect(X, Y); }
Qva.Mgr.binary.SelectEnd   = function (X, Y) { Qva.CloseDragRect(X, Y, this.Name, this.binderid, this); }


Qva.Mgr.binaryaction = function (owner, elem, name, prefix) {
    elem.Name = this.Name = Qva.MgrMakeName (name, prefix);
    elem.binderid = owner.ID;
    this.Attr = "mode";
    owner.AddManager(this);
    this.Element = elem;
    var imageelem = null;
    if (elem.tagName == "BUTTON") {
        for (var i = 0; i < elem.childNodes.length; i++) {
            if (elem.childNodes [i].tagName == "IMG") {
                imageelem = elem.childNodes [i];
                break;
            }
        }
        if (! imageelem) {
            imageelem = document.createElement ("img");
            elem.appendChild (imageelem);
        }
    } else {
        imageelem = elem;
    }
	if (elem.style.width == 'auto' && elem.style.height == 'auto') elem.autosize = true;
    if (owner.IsHosted && ! elem.sizefixed) {
        var objectframeNode = elem.parentNode.parentNode;
        if (elem.style.width != '') {
            var width = imagewidth (objectframeNode, elem);
            imageelem.style.width = elem.style.width;
        }
        if (elem.style.height != '') {
            var height = imageheight (objectframeNode, elem);
            imageelem.style.height = elem.style.height;
        }
    }
    //prevent "mising image" icon to show in IE, image is displayed in the previous function: Qva.Mgr.binary.prototype.PostPaint
    if (imageelem) imageelem.style.display = "none";
    
    if (elem.Name.substring(elem.Name.length-3)==".RE")
        elem.ondblclick = onclick_action;
    else
        elem.onclick = onclick_action;
    owner.Append (this, this.Name, 'action');
}

Qva.Mgr.binaryaction.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.binaryaction.prototype.Unlock = Qva.UnlockDisabled;
Qva.Mgr.binaryaction.prototype.Paint = Qva.Mgr.binary.prototype.Paint;
Qva.Mgr.binaryaction.prototype.PostPaint = Qva.Mgr.binary.prototype.PostPaint;


Qva.Mgr.menu = function (owner, elem, name, prefix) {
    this.Name = Qva.MgrMakeName ((name != null) ? name : '', prefix);
    owner.AddManager(this);
    this.Element = elem;
    owner.Append (this, this.Name, 'menu');
}

function ShowSubMenu (elem) {
    var row = elem.parentNode;
    if (row.AvqMgr.SubMenuRow != null && row.AvqMgr.SubMenuRow != row && row.AvqMgr.SubMenuRow.SubMenu) {
        row.AvqMgr.SubMenuRow.SubMenu.style.display = 'none';
    }
    row.AvqMgr.SubMenuRow = row;
    if (! row.SubMenu) {
        row.SubMenu = document.createElement ('table');
        row.SubMenu.className = "contextsubmenu";
        var at = Qva.GetPageCoords (row);
        row.SubMenu.style.top = at.y - 1 + "px";
        row.SubMenu.style.left = at.x + row.offsetWidth + "px";
        document.body.appendChild(row.SubMenu);
        row.AvqMgr.AppendMenuItems (row.submenunode.getElementsByTagName ("action"), row.SubMenu, 1);
    }
    row.AvqMgr.SubMenuRow.SubMenu.style.display = '';
}

function HighLightRow (elem) {
    var row = elem.parentNode;
    row.className = "ContextHighlightedRow"; 
}

function LeaveRow (elem) {
    var row = elem.parentNode;
    row.className = ""; 
}

function HideSubMenu (elem) {
    var row = elem.parentNode;
    if (row.AvqMgr.SubMenuRow != null && row.AvqMgr.SubMenuRow.SubMenu) {
        row.AvqMgr.SubMenuRow.SubMenu.style.display = 'none';
    }
}

Qva.Mgr.menu.prototype.AppendMenuItems = function (itemnodes, element, level) {
    var currentrow = 0;
    var icononly = true;
    var numberofactions = 0;
    for (var i = 0; i < itemnodes.length; i++) {
        if (this.PageBinder.IsContained && itemnodes[i].getAttribute("name") == "MI") continue; //WB
        var text = itemnodes [i].getAttribute ("text");
        var isdivider = itemnodes [i].getAttribute ("type") == "divider";
        var iconnodes = itemnodes [i].getElementsByTagName("icon");
        var nodelevel = parseInt (itemnodes [i].getAttribute ("level"));
        if (nodelevel != level) continue;
        if (! text && ! isdivider && iconnodes.length == 0) {
            debugger;
            continue;
        }
        if (isdivider && i == (itemnodes.length -1)) break;
        numberofactions++;
        var row;
        var cell1;
        var cell2;
        if (icononly) {
            icononly = (! text && ! isdivider)
        }
        if (element.rows [currentrow] && element.rows [currentrow].cells [0]) {
            row = element.rows [currentrow];
            cell1 = row.cells [0];
            if (! icononly) cell2 = row.cells [1];
        } else {
            row = element.insertRow (-1);
            cell1 = row.insertCell (-1);
            if (! icononly) cell2 = row.insertCell (-1);
        }
        row.className = "ContextRow";
        currentrow++;
        cell1.style.width = "16px";
        if (! icononly) { 
            if (row.cells [1]) {
                cell2 = row.cells [1];
            } else {
                cell2 = row.insertCell (-1);
            }
            cell2.className = "ContextTextCell";
            element.style.width = "";
        } else {
            element.style.width = "20pt";
        }

        if (itemnodes [i].getAttribute ("type") == "divider")  {
            var div = document.createElement ('div');
            div.className = "ContextDivider";
            div.style.width = "100%";
	        div.style.height = "1px";
            cell2.appendChild(div);
            cell2.style.padding = "0px 0px 0px 10px";
	        cell2.style.height = "1px";
            cell1.style.padding = "0px";
	        cell1.style.height = "1px";
        }  else {
            for (var iIcon = 0; iIcon < iconnodes.length; iIcon++) {
                if (level != parseInt (iconnodes[iIcon].getAttribute ("level"))) continue;
                var url = this.PageBinder.BuildBinaryUrl (iconnodes[iIcon].getAttribute ("path"), iconnodes[iIcon].getAttribute ("stamp"), iconnodes[iIcon].getAttribute ("name"));
                cell1.innerHTML = '<img alt="" src="' + url + '" style="' + iconnodes[iIcon].getAttribute ("style") + '" />';
            }
            if (! isdivider) {
                if (! icononly) cell2.innerText = text ? text : " ";
                var disabled = itemnodes [i].getAttribute ("mode") == "disabled";
                row.disabled = disabled;
                row.binderid = this.PageBinder.ID;
                if (! disabled) {
                    var submenu = itemnodes [i].getAttribute ("submenu") == "true";
                    row.AvqMgr = this;
                    if (submenu) {
                        row.submenunode = itemnodes [i];
                        cell1.onmouseover = function () { 
                            ShowSubMenu (this);
                            HighLightRow (this);
                        }
                        cell2.onmouseover = function () { 
                            ShowSubMenu (this);
                            HighLightRow (this);
                        }
                    } else {
                        var action = itemnodes [i].getAttribute ("name");
                        var clientaction = itemnodes [i].getAttribute ("clientaction");
                        if (action) {
                            row.onclick = onclick_action;
                            row.Name = this.Context + "." + action;
                            var index = itemnodes [i].getAttribute ("index");
                            if (index) {
                                row.PositionName = this.Context;
                                row.Position = index;
                            } else if (this.Position) {
                                row.PositionName = this.Context;
                                row.Position = this.Position;
                            }
                        } else if (clientaction) {
                            row.onclick = onclick_ContextClientAction;
                            row.Name = this.Context;
                            row.clientaction = clientaction;
                            row.param = itemnodes [i].getAttribute ("param");
                        }
                        if (nodelevel == 0) {
                            cell1.onmouseover = function () { 
                                HideSubMenu (this);
                                HighLightRow (this);
                            }
                            if (! icononly)  {
                                cell2.onmouseover = function () { 
                                    HideSubMenu (this);
                                    HighLightRow (this);
                                }
                            }
                        } else {
                            cell1.onmouseover = function () { 
                                HighLightRow (this);
                            }
                            if (! icononly)  {
                                cell2.onmouseover = function () { 
                                    HighLightRow (this);
                                }
                            }
                        }
                    }
                    cell1.onmouseout = function () { LeaveRow (this); }
                    if (! icononly)  {
                        cell2.onmouseout = function () { LeaveRow (this); }
                    }
                } else {
                    cell1.style.color = "InactiveCaptionText";
                    if (! icononly) cell2.style.color = "InactiveCaptionText";
                }
            } else {
                debugger;
            }
        }
    }
    return numberofactions;
}

Qva.Mgr.menu.prototype.Paint = function (mode, node) {
    var itemnodes = node.getElementsByTagName ("action");
    if (itemnodes.length == 0) {
        Qva.HideContextMenu ();
        return;
    }
    this.Touched = true;
    this.Context = this.PageBinder.DefaultScope + "." + node.getAttribute ("context");
    this.Position = node.getAttribute ("position");  
    var numberofactions = this.AppendMenuItems (itemnodes, this.Element, 0);
    Qva.KeepContextMenuAlive = false;
    if (numberofactions == 0) {
        Qva.HideContextMenu ();
    } else {
        if (this.Element.offsetHeight + this.Element.offsetTop - Qva.GetScrollTop () >  Qva.GetViewportHeight ()) {
            var top = Math.max (0, this.Element.offsetTop - this.Element.offsetHeight);
            this.Element.style.top = top + "px";
        }
        if (this.Element.offsetWidth + this.Element.offsetLeft - Qva.GetScrollLeft () >  Qva.GetViewportWidth ()) {
            var left = Math.max (0, this.Element.offsetLeft - this.Element.offsetWidth);
            this.Element.style.left = left + "px";
        }
    }
}

Qva.Mgr.toolbar = function (owner, elem, name, prefix) {
    this.Name = Qva.MgrMakeName ((name != null) ? name : '', prefix);
    owner.AddManager(this);
    this.Element = elem;
    owner.Append (this, this.Name, 'toolbar');
}

Qva.Mgr.toolbar.prototype.Paint = function (mode, node) {
    this.Touched = true;
    var element = this.Element;
    
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    if (element.style.display == 'none') return;
    
    var itemnodes = node.getElementsByTagName ("action");
    
    var table = element.tagName == "TABLE" ? element : element.getElementsByTagName("table")[0];
    if (! table) {
        table = document.createElement("table");
        element.appendChild(table);
    }
    var row;
    if (table.rows[0]) {
        row = table.rows[0];
    } else {
        row = table.insertRow (-1);
    }
    
    if (row.cells.length > itemnodes.length) {
        // TODO: fix ?
    }
    
    var cellcount = 0;
    for (var i = 0; i < itemnodes.length; i++) {
        var action = itemnodes [i].getAttribute ("name");
        var clientaction = itemnodes [i].getAttribute ("clientaction");
        var iconnodes = itemnodes [i].getElementsByTagName ("icon");
        
        var cell;
        if (row.cells[cellcount]) {
            cell = row.cells[cellcount];
        } else {
            cell = row.insertCell(-1);
            
        }
        cellcount++;
        
        cell.style.width = "18pt";
        cell.align = "center";
        cell.className = ""
        cell.binderid = this.PageBinder.ID;
        
        var text = itemnodes [i].getAttribute ("text");
        cell.title = text;
        
        if(iconnodes.length == 0) {
            cell.innerText = text;
            cell.style.width = itemnodes[i].getAttribute("width") || "";
        }
        
        for (var iIcon = 0; iIcon < iconnodes.length; iIcon++) {
            if (iconnodes[iIcon].getAttribute ("usage") != null && iconnodes[iIcon].getAttribute ("usage") != "caption") continue;
            var url = this.PageBinder.BuildBinaryUrl (iconnodes[iIcon].getAttribute ("path"), iconnodes[iIcon].getAttribute ("stamp"), iconnodes[iIcon].getAttribute ("name"));
            cell.innerHTML = '<img title="' + text + '" style="height:16px; width:16px;" alt="&nbsp;" src="' + url + '" />';
        }
        if (action || clientaction) {
            if (action) {
                cell.onclick = onclick_action;
                cell.Name = this.Name + "." + action;
            }
            if (clientaction) {
                cell.onclick = onclick_ContextClientAction;
                cell.Name = this.Name;
                cell.AvqMgr = this;
                cell.clientaction = clientaction;
                cell.param = itemnodes [i].getAttribute ("param");
            }
            cell.disabled = itemnodes [i].getAttribute ("mode") == "disabled";
            cell.onmouseover = function () { this.className = "ToolBarHighlightedButton"; }
            cell.onmouseout = function () { this.className = "ToolBarButton"; }
            cell.className = "ToolBarButton";
        } else {
            cell.style.padding = "0px";
            cell.style.backgroundColor = "#cccccc";
            cell.style.width = "1px";
        }
    }
    var selects = node.getElementsByTagName ("value");
    for (var iSelect = 0; iSelect < selects.length; iSelect++) {
        var name = this.Name + "." + selects [iSelect].getAttribute ("name");
        var cell;
        if (row.cells[cellcount]) {
            cell = row.cells[cellcount];
        } else {
            cell = row.insertCell(-1);
        }
        cellcount++;
        if (cell.Name == name) continue;
        cell.Name = name;
        cell.className = "QvToolbarDropdownCell";
        var select = window.document.createElement ("SELECT");
        cell.appendChild (select);
        new Qva.Mgr.select (this.PageBinder, select, name);
    }
}


Qva.MgrLinkScan = function (mgr, owner, lnkname, namePrefix) {
    mgr.LinkParts = lnkname.split ('$');
    var plen = mgr.LinkParts.length;
    mgr.LinkArgs = lnkname.split ('$');
    if (plen >= 2) {
        for (var lix = 1; lix < plen; lix += 2) {
            var name = namePrefix + mgr.LinkParts [lix];
            owner.Append (mgr, name);
            mgr.LinkParts [lix] = name;
        }
    }
};

function onclick_link () { 
    window.open (this.link);
}

Qva.Mgr.link = function (owner, elem, name, prefix, path) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    Qva.MgrLinkScan (this, owner, path, prefix);
    owner.AddManager(this);
    this.Element = elem;
    elem.Name = this.Name;
    elem.binderid = owner.ID;
    elem.onclick = onclick_link;
}

Qva.Mgr.link.prototype.Paint = function (mode, node, name) {
    this.Touched = true;
    var element = this.Element;
    if (element.Name == name) {
        element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    }
    for (var lix = 1; lix < this.LinkParts.length; lix += 2) {
        if (this.LinkParts [lix] == name) {
            this.LinkArgs [lix] = node.getAttribute ("text");
        }
    }
    element.link = "";
    for (var lix = 0; lix < this.LinkArgs.length; lix ++) {
        element.link += this.LinkArgs [lix];
    }
}

Qva.Mgr.hover = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
}

Qva.Mgr.hover.prototype.Paint = function(mode, node, name) {
    var element = this.Element;
    element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    element.innerHTML = "";
    var lines = node.getElementsByTagName ("line");
    for (var i = 0; i < lines.length; i++) {
        var p = document.createElement ("span");
        p.innerText = lines [i].getAttribute ("text");
        element.appendChild (p);
        var br = document.createElement ("br");
        element.appendChild (br);
    }
}

Qva.ZIndex = function (owner) {
    this.Name = owner.DefaultScope + ".ZIndex";
    this.Attr = 'zindex';
    this.PageBinder = owner;
    owner.AddManager(this);
    this.Names = new Array ();
    this.ZIndexes = new Array ();
}

function SetRelatedElementsZindex (objectname, zindex) {
    var frame = window.document.getElementById (objectname + "_frame");
    if (frame) {
        var oldzindex = frame.style.zIndex;
        if (zindex == oldzindex) return;
        frame.style.zIndex = zindex;
    }
    var ids = [objectname + "_bkg", objectname + "_frame_resize", objectname + "_frame_move", objectname + "_minimized"];
    for (var i = 0; i < ids.length; i++) {
        var elem = window.document.getElementById (ids[i]);
        if (elem) elem.style.zIndex = zindex;
    }
}

Qva.ZIndex.prototype.PostPaint = function () {
    for (var i = 0; i < this.Names.length; i++) {
        SetRelatedElementsZindex (this.Names [i], this.ZIndexes [i]); 
    }
}

Qva.ZIndex.prototype.Paint = function (mode, node) {
    this.Touched = true;
    var objects = node.getElementsByTagName("object");
    this.Names.length = 0;
    this.ZIndexes.length = 0;
    for (var i = 0; i < objects.length; i++) {
        this.ZIndexes [this.ZIndexes.length] = parseInt (objects [i].getAttribute ("zindex"));
        this.Names [this.Names.length] = objects [i].getAttribute ("name");
    }
    Qva.QueuePostPaintMessage (this);
}

Qva.Mgr.CreateAndUpdateResizeHandles = function (frame) {
        // create resize-div
        var sizeIn = 4; //pixels inside frame
        var sizeOut = 4;//pixels outside frame
        var cellWidth  = parseInt(frame.offsetWidth);
        var cellHeight = parseInt(frame.offsetHeight);
        var resizeParentId = frame.id + '_resize';
        var handleParent = document.getElementById(resizeParentId)
        if (!handleParent) {
            var handleParent = document.createElement("div");
            handleParent.id = resizeParentId;
            handleParent.className = "ResizeFrame";
            handleParent.ResizeType = "Parent";
            frame.insertBefore (handleParent, frame.firstChild);
        }
        handleParent.style.left = "-1px";
        handleParent.style.top = "-1px";
        handleParent.style.height = "1px";
        handleParent.style.width = "1px";
        
        var handles = ["br","r","b","bl","l","tl","t","tr"];
        for (var i = 0; i < handles.length;i++) {
            var resizeId = frame.id + '_resize_' + handles[i];
            var handle = document.getElementById(resizeId)
            if (!handle) {
                var handle = document.createElement("div");
                handle.id = resizeId;
                handle.ResizeType = handles[i];
                handleParent.appendChild(handle);
                handle.className = "ResizeZone";
            }
            var offsetX = 0; 
            var offsetY = 0; 
            // left
            if (handles[i].indexOf("r")!=-1) {
                var left = offsetX + cellWidth - sizeIn;
            } else if (handles[i].indexOf("l")!=-1) {
                var left = offsetX - sizeOut;
            } else {
                var left = offsetX + sizeIn;
            }
            // top
            if (handles[i].indexOf("b")!=-1) {
                var top = offsetY + cellHeight - sizeIn;
            } else if (handles[i].indexOf("t")!=-1) {
                var top = offsetY - sizeOut;
            } else {
                var top = offsetY + sizeIn;
            }
            // width
            if (handles[i].indexOf("r")!=-1 || handles[i].indexOf("l")!=-1) {
                var width = sizeIn + sizeOut;
            } else {
                var width = cellWidth - 2 * sizeIn;
            }
            // hight
            if (handles[i].indexOf("t")!=-1 || handles[i].indexOf("b")!=-1) {
                var height = sizeIn + sizeOut;
            } else {
                var height = cellHeight - 2 * sizeIn;
            }
            // cursor
            var cu = "";
            if (handles[i].indexOf("t")!=-1) 
                cu = "n";
            else if (handles[i].indexOf("b")!=-1) 
                cu = "s";
            if (handles[i].indexOf("l")!=-1) 
                cu += "w";
            else if (handles[i].indexOf("r")!=-1) 
                cu += "e";
            handle.style.cssText = 'width: ' + width + 'px; height: ' + height + 'px; cursor: ' + cu + '-resize; left: ' + left + 'px; top: ' + top + 'px;';
            handle.onmousedown = function (event) { Qva.Resize.mouseDown (event, frame); }
        }
}

Qva.Mgr.CreateOrDeleteMoveHandle = function (frame, allowmove) {
    var moveElementId = frame.id + '_move';
    var moveElement = document.getElementById(moveElementId)
    if (allowmove) {
        // just above the resize handle
        var height = 4;
        var top = -8;
        var cellWidth  = parseInt(frame.offsetWidth);
        if (!moveElement) {
            moveElement = document.createElement("div");
            moveElement.id = moveElementId;
            moveElement.className = "MoveZone";
            moveElement.style.cssText = 'width: ' + cellWidth + 'px; height: ' + height + 'px; left: ' + 0 + 'px; top: ' + top + 'px;';
            moveElement.Name = frame.Name;
            moveElement.moveObj = frame.id;
            var bkgid = frame.id.replace ("_frame", "_bkg");
            var bkgelem = window.document.getElementById (bkgid);
            if (bkgelem) {
                moveElement.moveObj += ":" + bkgid;
            }
            moveElement.onmousedown = Qva.Move.mouseDown;
            frame.appendChild (moveElement);
        }
    } else {
        if (moveElement) {
            frame.removeChild(moveElement);
        }
    }
}


// Build 9.00.7440.8
function ScrollBar(parent) {
    var o_scroll = document.createElement("div");
    parent.appendChild(o_scroll);
    o_scroll.style.position = "absolute";
    o_scroll.style.overflowX = "hidden";
    o_scroll.style.overflowY = "scroll";
    o_scroll.style.width = "18px";
    o_scroll.style.top = "0px";
    o_scroll.style.zIndex = 10;
    var i_scroll = document.createElement("div");
    o_scroll.appendChild(i_scroll);
    i_scroll.style.width = "1px";
    this.Parent = parent;
    this.o_Scroll = o_scroll;
    this.i_Scroll = i_scroll;
    
    this.UpdateSize(30, 16);
}
ScrollBar.prototype.UpdateSize = function (totalRows, visibleRows) {
    this.VisibleRows = Math.max(visibleRows, 1);
    this.TotalRows   = totalRows;
    this.UpdateHeight();
}
ScrollBar.prototype.UpdateHeight = function (height) {
//    var height = this.Height = height || this.Height || Math.max(1, this.Parent.offsetHeight - this.Parent.offsetTop);
//    this.o_Scroll.style.height = height + "px";
//    this.i_Scroll.style.height = Math.round (height * this.TotalRows / this.VisibleRows) + "px";
    this.o_Scroll.style.height = "100%";
    var h = Math.round (100 * this.TotalRows / this.VisibleRows)
    this.i_Scroll.style.height = h + "%";
    this.o_Scroll.style.display = h <= 100 ? 'none' : '';
    this.o_Scroll.style.left = (this.Parent.offsetWidth - 18) + "px";
}
ScrollBar.prototype.GetWidth = function () { 
    if (IS_MAC) {
        return 15;
    } else {
        return 17;
    }
}
ScrollBar.prototype.GetOffset = function () { // TODO: fix ? ('independent' of this.Height) ? (save offest ?)
    if(this.Height != undefined) {
        return Math.round(this.VisibleRows * this.o_Scroll.scrollTop / this.Height)
    } else {
        return 0;
    }
}

if (!Qva.Mgr) Qva.Mgr = {};

Qva.Mgr.table = function (owner, elem, name, prefix, condition) {
    
    this.Name = Qva.MgrMakeName ((name != null) ? name : '', prefix);
    owner.AddManager(this);
    this.LeftButton = owner.LeftButton;
    this.Element = elem;
    elem.AvqMgr = this;
    this.TableScan (owner, prefix);
    if (! this.AutoCol && this.Name != "") {
        owner.Append (this, this.Name, 'choice');
    }
    this.ScrollParent = this.Element.parentNode;
    this.Frame = this.ScrollParent.parentNode;
}

Qva.Mgr.table.prototype.CellObject = function (optval, value) {
    this.val = optval ? optval : "";
    var title = value.getAttribute ("title");
    this.title = title ? title : this.val;
    var index = value.getAttribute ("value");
    if (index) {
        this.intval = index;
        this.selected = value.getAttribute ("selected") == "yes";
        this.deselected = value.getAttribute ("deselected") == "yes";
        this.selectedexcluded = value.getAttribute ("selectedexcluded") == "yes";
        this.locked = value.getAttribute ("locked") == "yes";
        this.frequency = value.getAttribute ("frequency");
        this.level = value.getAttribute ("level");
        this.parts = value.getElementsByTagName ("range");
    } else {
        if (value.getAttribute ("locked")) {
            this.locked = value.getAttribute ("locked") == "yes";
            this.byval = true;
        }
        if (value.getAttribute ("selected")) {
            this.selected = value.getAttribute ("selected") == "yes";
            this.byval = true;
        }
    }
    this.mode = value.getAttribute ("mode");
    this.disabled = this.mode == "disabled";
    this.style = value.getAttribute ("style");
    this.isnum = value.getAttribute ("isnum") == "true";
    this.icons = value.getElementsByTagName ("icon");
    this.subcell = value.getAttribute ("subcell");
    this.first = value.getAttribute ("first");
    this.action = value.getAttribute ("action");
    this.url = value.getAttribute ("url");
    var selecttype = value.getAttribute ("selecttype");
    if (selecttype) {
        this.selecttype = selecttype;
        this.selectsource = value.getAttribute ("selectsource") == "true";
        if (this.action) debugger;
    }
    this.input = value.getAttribute ("input") == "true";
    var rowspan = value.getAttribute ("rowspan");
    if (rowspan) {
        this.rowspan = parseInt (rowspan);
    } else {
        this.rowspan = 1;
    }
}

Qva.Mgr.table.prototype.TableScan = function (owner, prefix) {
    var element = this.Element;
    this.Selected = new Array ();
    var groupname = element.getAttribute ('AvqGroup');
    if (groupname != null) {
        this.Group = Qva.MgrMakeName (groupname, prefix);
        owner.Append (this, this.Group);
    }
    this.PageName = this.Name;
    this.PageSize = 0; // unlimited
    this.TotalSize = 0;
    this.ColMgr = [];
    this.Fixed = false;
    this.RowHeight = -1;
    this.AllwaysFullWidth = false;
    this.Search = null;
    this.SearchName = this.Name;
    this.Searchable = false;
    this.IsAsync = false;
    this.IsTransient = false;
    this.TableLimit = owner.TableLimit;
    this.InlineStyle = owner.InlineStyle;
    if (element.getAttribute ('AvqStyle')) {
        this.InlineStyle = element.getAttribute ('AvqStyle') == "true";
    }
    var async = element.getAttribute ('AvqAsync');
    this.IsHeader = element.getAttribute ('avqheader') == "true";
    this.IsBody = element.getAttribute ('avqbody') == "true";
    this.HeaderRowCount = 0;
    if (async != null) {
        if (async != '') {
            var asyncs = async.split (':');
            if (asyncs.length > 2) {
                m_errors [m_errors.length] = 'Invalid AvqAsync: ' + async;
                return;
            }
            var pageSize = parseInt (asyncs [0]);
            if (isNaN (pageSize) || pageSize <= 0) {
                m_errors [m_errors.length] = 'Invalid page-size in AvqAsync: ' + pageSize;
                return;
            }
            this.PageSize = pageSize;
            if (asyncs.length >= 2) {
                this.PageName = Qva.MgrMakeName (asyncs [1], prefix);
            }
        } else {
            this.PageSize = 20;
        }
        this.IsAsync = true;
    }
    this.PageIncr = this.PageSize > 0 ? this.PageSize : 20;
    if (this.IsAsync) {
        owner.Append (this, this.PageName, 'pageoffset');
        owner.Append (this, this.PageName, 'pagesize');
        owner.Append (this, this.PageName, 'totalsize');
        owner.SetInitial (this.PageName, 'pagesize', this.PageSize);
    }
    if (this.IsHeader || this.IsBody) {
        owner.Append (this, this.PageName, 'fixedrows');
    }
    if (element.tagName == 'TABLE') {
        this.Body = element.tBodies [0];
        if (this.Body == null) {
            element.insertRow(-1);
            this.Body = element.tBodies [0];
        }
    } else {
        this.Body = element;
    }
    
    var body = this.Body;
    if (body.rows.length < 1) {
        body.appendChild(document.createElement("tr"));
        //m_errors [m_errors.length] = 'At least one row must exist: ' + this.Name;
    }
    
    if(IS_GECKO && GECKO_VERSION < 3.5) {
        element.style.borderCollapse = "separate";
        element.style.borderSpacing = "0px";
        //setTimeout(function() { element.style.borderCollapse = "collapse"; }, 1000);
    }
    
    var row = body.rows [0];
    row.rix = 0;
    this.Width = row.cells.length;
    
    this.AutoCol = this.Width === 0;
    
    var choice = null;
    if (this.Name != '') {
        choice = element.getAttribute ('AvqChoice');
        if (choice == null) choice = this.Name;
    }
    this.Lines = new Array ();
    this.Style = new Array ();
    this.BorderStyle = new Array ();
    this.IsPainted = new Array ();
    this.RowClassNames = new Array ();
    this.ColList = new Array ();
    this.ColDict = {};
    
    this.ChoiceIx = -1;
    
    var cix = 0;
    for (; cix < this.Width; ++cix) {
        var cell = row.cells[cix];
        
        var colfld = cell.getAttribute ('AvqCol');
        if (colfld == null) continue;
        if (colfld.indexOf (':') == -1 && colfld.indexOf ('.') >= 0) {
            // no separator specified but field specified -> assume 'edit'
            colfld = 'edit:' + colfld;
        }
        var parts = colfld.split (':');
        
        var cmd = parts[0];
        var name = (parts.length > 1) ? parts[1] : this.Name;
        var extra = (parts.length > 2) ? parts.slice(2).join (':') : null;
        if(this.ColMgr[cix]) {
            cmd = this.ColMgr[cix].cmd;
            extra = this.ColMgr[cix].extra;
        }
        
        var type = Qva.ColMgr[cmd] || Qva.ColMgr.basic;
        var colmgr = new type(this, cix, cell, name, prefix, extra);
        colmgr.Cmd = cmd;
        
        if (colmgr.Name == null) {
            m_errors [m_errors.length] = 'Invalid AvqCol "' + parts [1] + '": ' + this.Name;
            continue;
        }
        if (this.Group == null) owner.Append (this, colmgr.Name);
        this.ColDict[colmgr.Name] = colmgr;
        this.ColList [this.ColList.length] = colmgr;
    }
    this.RowClassNames [0] = body.rows [0].className;
    
    var stripes = element.getAttribute ('AvqStripeClasses');
    if (stripes != null) {
        this.RowClassNames = this.RowClassNames.concat(('' + stripes).split(/\s/));
    }
    if (choice != null) {
        var colmgr = this.ColDict[choice];
        if (colmgr == null) {
            colmgr = new Qva.ColMgr.basic(this, cix, null, choice, prefix);
            if (this.Group == null) owner.Append (this, colmgr.Name);
            this.ColDict[choice] = colmgr;
            ++cix;
        }
        this.ChoiceIx = colmgr.Index;
    }
    if (!this.IsHeader) {
        try {
            var pp = element.parentNode;
            pp.AvqMgrForScroll = this;
            pp.onscroll = this.ParentScroll;
        } catch (e) {
            alert ("Error: " + element.parentNode.tagName);
        }
    }
    
    var objectname = this.PageName.replace (this.PageBinder.DefaultScope + ".", "");
    if (element.id == "" && this.IsHeader) {
        element.id = objectname;
    }
    if (this.IsBody && ! element.Header) {
        var header = document.getElementById (objectname);
        if (header && header != element) {
            element.Header = header;
        } else if (element.id == "") {
            //Listboxes and multiboxes has no header
            element.id = objectname;
        }
    }
    
    if(element.getAttribute('AvqScrollBar') != null) {
        this.ScrollBar = new ScrollBar(element.parentNode);
        
        var _this = this;
        this.ScrollBar.o_Scroll.onscroll = Delay(function () {
            Qva.QueuePostPaintMessage(_this);
        }, 100);
        
        //element.parentNode.style.overflowY = "hidden";
        
        var parent = element.parentNode;
        parent.removeChild(element);
        var div = document.createElement("div");
        parent.appendChild(div);
        div.appendChild(element);
        this.Element = div;
        
        parent.style.overflowY = "hidden";
        div.style.overflowY = "hidden";
        div.style.overflowY = "hidden";
        div.style.overflowX = "auto";
        
        div.style.position = "relative"; // Fix IE bug
        
        div.AvqMgrForScroll = this;
        div.onscroll = function () {
            var mgr = this.AvqMgrForScroll;
            if (!mgr.Element.Header) return
            var header = mgr.Element.Header;
            if (header && header.parentNode.scrollLeft != this.scrollLeft) {
                header.parentNode.scrollLeft = this.scrollLeft;
            }
        };
    }
}

function Delay(func, time) {
    return function() {
        var _this = this;
        if(func._wait) clearTimeout(func._wait);
        func._wait = setTimeout(function() { func.apply(_this, arguments); func._wait = null; }, time);
    }
}

var busy = false;

Qva.Mgr.table.prototype.ParentScroll = function() {
    if (busy) return;
    var mgr = this.AvqMgrForScroll;
    if (mgr == null) mgr = element.document.body.AvqMgrForScroll; // daft workaround for daft design... (onscroll on body behaves strangely)
    if (mgr == null) return;
    if (mgr.Element.Header != null) {
        busy = true;
        var header = mgr.Element.Header;
        if (header.parentNode.scrollLeft != this.scrollLeft) {
            header.parentNode.scrollLeft = this.scrollLeft;
        }
        busy = false;
    }
    mgr.debugcounter = 0;
    Qva.QueuePostPaintMessage (mgr);
}

Qva.Mgr.table.prototype.Lock = Qva.NoAction;
Qva.Mgr.table.prototype.Unlock = Qva.NoAction;

Qva.Mgr.table.prototype.getTableElement = function () {
    if (this.ScrollBar && this.IsBody) {
        return this.Element.getElementsByTagName("table")[0];
    } else {
        return this.Element;
    }
}

Qva.Mgr.table.prototype.FixCol = function (mode, node, name, partial) {
    var vals = new Array();
    for (var memb = node.firstChild; memb; memb = memb.nextSibling) {
        if (memb.nodeName != 'value') continue;
        if (memb.getAttributeNode ('width') == null) continue;
        vals [vals.length] = memb;
    }
    var element = this.Element;
    var objectisresized = this.Frame.maxclientheight == null || this.Frame.maxclientwidth == null;
    if (this.AllwaysFullWidth && ! this.IsTransient) {
        var Maximized = this.Frame.AvqMgr.Maximized;
        if (Maximized != this.Maximized) {
            objectisresized = true;
            this.Maximized = this.Frame.AvqMgr.Maximized;
        }
    }
    if (objectisresized && ! this.IsTransient) {
        setFrameWidth (this.Frame, 0);
        setFrameHeight (this.Frame, 0);
        if (this.Frame.maxclientwidth) {
            setContentWidth (this.Frame, this.Frame.maxclientwidth);
        }
    }
    
    if (this.Width == vals.length && this.Body.rows.length > 0) return;
    this.Fixed = false;

    this.Width = vals.length;
    
    var bodyParent = this.Body.parentNode;
    var body = this.Body.cloneNode (false);
    var row = document.createElement ("tr");
    body.appendChild(row);
    row.rix = 0;
    
    this.ColList = [];
    
    var cix = 0;
    var elem = vals [0] ? vals [0].childNodes [0] : null;
    var edit = elem && elem.getAttribute ('value');
    var tottablewidth = 0;

    this.UnmodifiedTableWidth = null;
    
    for (; cix < this.Width; ++cix) {
        var width = vals[cix].getAttribute ("width");
        var cell = row.cells[cix];
        if (cell == null) cell = row.appendChild (document.createElement("td"));
        if (width) {
            if (width == "auto") {
                cell.style.width = "" + 100 / this.Width + "%"
                this.AllwaysFullWidth = true;
            } else {
                var colwidth = parseInt (parseFloat (width) * 72 / 300);
                cell.style.width = colwidth + "pt";
                tottablewidth += colwidth;
                if (IS_GECKO) tottablewidth += 3;
                if (IS_CHROME || IS_SAFARI) tottablewidth += 2;
                if (cix == (this.Width - 1)) {
                    this.LastColWidth = colwidth + "pt"
                }
            }
            cell.innerText = "Gg";
        }
        if (this.InlineStyle) {
            var rowindex = 0;
            var val = null;
            while (! val) {
                val = vals[cix].getElementsByTagName('element') [rowindex];
                if (! val) break;
                if (this.IsHeader != (val.getAttribute ("position") == "top")) {
                    val = null;
                    rowindex++;
                }
            }
            if (val) {
                var data = new this.CellObject (val.getAttribute ("text"), val);
                cell.style.cssText += this.SetCellStyle (data, 0, cix, true, true);
            }
        }

        var extra = null;
        var cmd = edit ? (this.WindowsSelectionstyle ? 'windowsedit' : 'edit') : 'text';
        if (this.ColMgr[cix]) {
            cmd = this.ColMgr[cix].cmd;
            extra = this.ColMgr[cix].extra;
        }
        name = "." + vals[cix].getAttribute('name');
        var colmgr = new Qva.ColMgr[cmd] (this, cix, cell, name, this.PageName, extra);
                
        colmgr.Cmd = cmd;
        if (this.Group == null) this.PageBinder.Append (this, colmgr.Name, null, true);
        this.ColDict [colmgr.Name] = colmgr;
        this.ColList [this.ColList.length] = colmgr;
    }

    if (tottablewidth != 0) {
        this.getTableElement ().style.width = tottablewidth + "pt";
    }
    
    bodyParent.replaceChild (body, this.Body);
    this.Body = body;
    if (this.AllwaysFullWidth) {
        if ((IS_IE && IE_VERSION < 8) || IE_DOCMODE <= 7) {
            this.Element.style.width = "auto";
        } else {
            this.Element.style.width = "100%";
        }
    }
}

Qva.Mgr.table.prototype.AppendIfMissing = function(list, entry) {
    var len = list.length;
    for (var six = 0; six < len; ++six) {
        if (list [six] == entry) return;
    }
    list [len] = entry;
}

Qva.PageBinding.prototype.CreateTransientListBox = function (name) {

    var frame = document.createElement ("div");
    frame.style.cssText = "z-index: 100; display: none; left: 10pt; top: 10pt; width: 10pt; height: 800pt; position:absolute;";
    frame.className = "Frame DS";

    var body = document.createElement ("div");
    body.className = "body";

    var table = document.createElement ("table");
    table.style.cssText = "background-color: White;";
    table.setAttribute ("avqbody", "true");

    if (IS_GECKO || IS_SAFARI || IS_OPERA || IS_CHROME) {
        table.style.cssText += "width: 100%;";
    } else {
        table.style.cssText += "width: auto;";
    }
    table.setAttribute ("avqasync", "40:" + name);
    table.id = "DS";

    body.appendChild (table);
    frame.appendChild (body);
    document.body.appendChild (frame);

    new Qva.Mgr.label (this, frame, name);
    new Qva.Mgr.table (this, table);
}


Qva.Mgr.table.prototype.ModifyAltClasses = function (altclass, node) {
    var binder = this.PageBinder;
    for (var i = 0; i < document.styleSheets.length; i++) {
        var rules;
        try {
            rules = document.styleSheets[i].rules ? document.styleSheets[i].rules : document.styleSheets[i].cssRules;
        } catch (Error) { continue; }
        if (altclass == "LED") {
            for (var is = 0; is < rules.length; is++) {
                var style = rules[is];
                var state = null;
                var url = null;
                if (style.selectorText == (".AvqSelected_" + altclass)) {
                    if (!binder.Unicorn && binder.IsHosted) {
                        url = binder.BuildBinaryUrl (binder.ImageFolder + "HSI.png", "0", "HSI");
                    } else {
                        state = "AvqSelected";
                    }
                }
                if (style.selectorText == (".AvqDisabled_" + altclass)) {
                    if (!binder.Unicorn && binder.IsHosted) {
                        url = binder.BuildBinaryUrl (binder.ImageFolder + "IEI.png", "0", "IEI");
                    } else {
                        state = "AvqDisabled";
                    }
                }
                if (style.selectorText == (".AvqEnabled_" + altclass)) {
                    if (!binder.Unicorn && binder.IsHosted) {
                        url = binder.BuildBinaryUrl (binder.ImageFolder + "HOI.png", "0", "HOI");
                    } else {
                        state = "AvqEnabled";
                    }
                }
                if (style.selectorText == (".AvqLocked_" + altclass)) {
                    if (!binder.Unicorn && binder.IsHosted) {
                        url = binder.BuildBinaryUrl (binder.ImageFolder + "ILI.png", "0", "ILI");
                    } else {
                        state = "AvqLocked";
                    }
                }
                if (state != null) {
                    if (!binder.Unicorn && binder.IsHosted) debugger;
                    for (var memb = node.firstChild; memb; memb = memb.nextSibling) {
                        if (memb.getAttribute ("name") == state) {
                            url = binder.BuildBinaryUrl (binder.ImageFolder + altclass + ".png", null, altclass, memb.getAttribute ("color"));
                            break;
                        }
                    }
                }
                if (url == null) continue;
                style.style.backgroundImage = "url(" + url + ")";
            }
        } else {
            debugger;
        }
    }
}

Qva.Mgr.table.prototype.Paint = function (mode, node, name, partial) {
    this.debugcounter = 0;
    this.Touched = true;
    var NodeWithAttributes = (this.Name == name || this.PageName == name) ? node : node.parentNode;
    var WindowsSelectionstyle = NodeWithAttributes.getAttribute ("windowsselectionstyle") == "true";
    if (this.WindowsSelectionstyle != null && this.WindowsSelectionstyle != WindowsSelectionstyle) {
        this.Width = 0;
    }
    this.WindowsSelectionstyle = WindowsSelectionstyle;
    var owner = NodeWithAttributes.getAttribute ('owner');
    this.Height = -1;
    if (owner) {
        var row = parseInt (NodeWithAttributes.getAttribute ('row'));
        var col = parseInt (NodeWithAttributes.getAttribute ('col'));
        if (this.Owner && (this.Owner != owner || this.OwnerRow != row || this.OwnerCol != col)) {
            while (this.Body.rows.length > 0) {
                this.Body.deleteRow (this.Body.rows.length - 1);
            }
            this.ByValue = null;
            this.Fixed = false;
            this.getTableElement ().style.width = "";
        }
        this.Owner = owner;
        this.OwnerRow = row;
        this.OwnerCol = col;
        this.IsTransient = true;
        this.PageBinder.TransientObject = this.PageName;
        var ownerelement = document.getElementById (this.Owner);
        if (! ownerelement) {
            var legacyname = this.Owner + this.OwnerRow;
            ownerelement = document.getElementById (legacyname);
        }
        if (ownerelement && (ownerelement.nodeName == "TABLE" || ownerelement.nodeName == "TD")) {
            var left;
            var width;
            var top;
            if (ownerelement.nodeName == "TD") {
                left = ownerelement.offsetLeft;
                width = ownerelement.offsetWidth;
                top = ownerelement.offsetTop + ownerelement.offsetHeight;
                var offsetparent = ownerelement.offsetParent;
                while (offsetparent) {
                    left += offsetparent.offsetLeft;
                    top += offsetparent.offsetTop;
                    offsetparent = offsetparent.offsetParent;
                }
            } else if (ownerelement.nodeName == "TABLE") {
                if (this.OwnerRow == -1 && this.OwnerCol == -1) {
                    left = ownerelement.offsetLeft;
                    width = ownerelement.offsetWidth;
                    top = ownerelement.offsetTop + ownerelement.offsetHeight;
                    var offsetparent = ownerelement.offsetParent;
                    while (offsetparent) {
                        left += offsetparent.offsetLeft;
                        top += offsetparent.offsetTop;
                        offsetparent = offsetparent.offsetParent;
                    }
                } else {
                    if (ownerelement.rows.length > this.OwnerRow) {
                        var cell = ownerelement.rows[this.OwnerRow].cells [this.OwnerCol];
                        if (cell) {
                            if (cell.offsetWidth > 0) {
                                top = cell.offsetTop + cell.offsetHeight;
                                var ismultibox = false;
                                if (cell.offsetWidth < 23) {
                                    // Difference between multiboxes and otheer tables
                                    cell = ownerelement.rows[this.OwnerRow].cells [this.OwnerCol + 1];
                                    top = cell.offsetTop;
                                    ismultibox = true;
                                }
                                left = 2 + cell.offsetLeft;
                                width = cell.offsetWidth - 4;
                                var offsetparent = cell.offsetParent;
                                while (offsetparent) {
                                    left += offsetparent.offsetLeft;
                                    top += offsetparent.offsetTop;
                                    offsetparent = offsetparent.offsetParent;
                                }
                                top++;
                                if (! ismultibox) left -= 10;
                                width += 10;
                            }
                        }
                    }
                }
            }
            if (! isNaN (left)) {
                left -= (ownerelement.parentNode.scrollLeft - Qva.GetScrollLeft ());
                var height = 0;
                var offsetparent = ownerelement;
                while (offsetparent) {
                    height = offsetparent.offsetHeight;
                    offsetparent = offsetparent.offsetParent;
                }
                height -= (top - Qva.GetScrollTop ());
                // Take tabs into consideration
                if (height > 80) height -= 40;
                this.Frame.style.left = left + "px";
                this.Frame.style.top = top + "px";
                if (height > 0) {
                    if (this.Frame.maxclientheight != height) { 
                        this.Frame.maxclientheight = height;
                        setFrameHeight (this.Frame, 0);
                    }
                }
                if (this.Frame.maxclientwidth != width) { 
                    this.Frame.maxclientwidth = width;
                    setFrameWidth (this.Frame, 0);
                }
            }
        } else {
            debugger;
        }
    } else if (this.IsTransient) {
        this.Frame.maxclientwidth = null;
        this.Frame.maxclientheight = null;
        this.Element.parentNode.style.height = "";
        this.Element.parentNode.style.width = "";
        this.LastColWidth = null;
        this.PageBinder.TransientObject = "";
    }
    
    
    this.Searchable = NodeWithAttributes.getAttribute ("searchable") == "true";

    var element = this.Element;
    try {
        var newmode = Qva.MgrGetDisplayFromMode (this, mode);
        var colmgr = this.ColDict[name];
        if (colmgr == null) {
            if (newmode != element.style.display) {
                element.style.display = newmode;
            }
        } else if (newmode == 'none') {
            if (colmgr.Index != 0) {
                for (var rix = 0; rix < this.Lines.length && this.Lines [rix]; ++rix) {
                    this.Lines [rix][colmgr.Index] = null;
                }
            }
            return;
        }
    } catch (e) {
        debugger
    }
    element.disabled = (mode != 'e');
    if (this.InlineStyle) setStyle (node, element);
    var sortable = node.parentNode.getAttribute ('issortable');
    if (sortable && sortable == 'true') this.sortable = true;
    if (this.InlineStyle) {
        var stylenodes = node.getElementsByTagName ('style');
        if (stylenodes.length == 0) stylenodes = node.parentNode.getElementsByTagName ('style');
        if (stylenodes.length > 0) {
            stylenodes = stylenodes[0].getElementsByTagName ('style');
            for (var istyle = 0; istyle < stylenodes.length; istyle++) {
                this.Style [istyle] = new this.StyleObject (stylenodes [istyle]);
            }
        }
        stylenodes = node.getElementsByTagName ('borderstyle');
        if (stylenodes.length == 0) stylenodes = node.parentNode.getElementsByTagName ('borderstyle');
        if (stylenodes.length > 0) {
            stylenodes = stylenodes[0].getElementsByTagName ('borderstyle');
            for (istyle = 0; istyle < stylenodes.length; istyle++) {
                this.BorderStyle [istyle] = new this.BorderStyleObject (stylenodes [istyle]);
            }
        }
    }
    if (node.getAttribute ("menu") == "true") {
        this.Menu = true;
    }
    this.Dirty = true;
    if (this.Group == name) {
        var entries = node.childNodes;
        var height = entries.length;
        if (height > this.TableLimit) {
            TableTruncateAlert (this.Name, height);
            height = this.TableLimit;
        }
        var rowsskipped = 0;
        for (rix = 0; rix < height; ++ rix) {
            var entry = entries [rix];
            if (this.ByValue == null) {
                this.ByValue = (entry.getAttribute("value") != null);
            }
            var position = entry.getAttribute ('position');
            if (this.IsHeader) {
                if (! position == 'top') continue;
                if (! position) break;
            }
            if (this.IsBody) {
                if (position) {
                    rowsskipped++
                    continue;
                }
            }
            var actualrow = rix - rowsskipped;
            if (actualrow >= this.Lines.length) {
                this.Lines [actualrow] = new Array ();
            }
            var header = entry.getAttribute ('isheader');
            if (header && header == 'true') this.Lines [actualrow].IsHeader = true;
            this.IsPainted [actualrow] = false;
            var values = entry.childNodes;
            var width = values.length;
            for (var cix = 0; cix < width; ++ cix) {
                var value = values [cix];
                name = value.getAttribute ("name");
                for(var colix in this.ColList) {
                    var colmgr = this.ColList[colix];
                    if (colmgr.Name != name) continue;
                    var optval = value.getAttribute (colmgr.Attr);
                    if (colmgr.Dec != null) optval = Qva.Trunc (optval, colmgr.Dec);
                    this.Lines[actualrow][colmgr.Index] = new this.CellObject (optval, value);
                }
            }
        }
        this.Lines.length = height;
        this.TotalSize = height;
        return;
    }
    this.AndMode = NodeWithAttributes.getAttribute ("andmode") == "true";
    this.Semantic = NodeWithAttributes.getAttribute ("semantic") == "true";
    var AltClass = NodeWithAttributes.getAttribute ("altclass");
    if (AltClass != this.AltClass) {
        this.AltClass = AltClass;
        this.ModifyAltClasses (this.AltClass, NodeWithAttributes.getElementsByTagName (this.AltClass) [0]);
    }
    this.SizeTodata = NodeWithAttributes.getAttribute ("sizetodata") == "true" && this.AutoCol; 
    this.SupressHorizontalScroll = NodeWithAttributes.getAttribute ("suppresshorizontalscroll") == "true" && this.AutoCol;
    if (this.IsBody) {
        if (this.SupressHorizontalScroll && this.IsBody) {
            element.parentNode.style.overflowX = "hidden";
        } else {
            element.parentNode.style.overflowX = "auto";
        }
    }
    this.Fixed = false;
    if (this.PageName == "" || this.PageName == name) {
        this.ChunkOffset = parseInt (NodeWithAttributes.getAttribute ("pageoffset"));
        this.ChunkSize = parseInt (NodeWithAttributes.getAttribute ("pagesize"));
        this.TotalSize = parseInt (NodeWithAttributes.getAttribute ("totalsize"));
        var inflatesize = Math.max (500, this.ChunkSize);
        if (isNaN (this.EffectiveSize) || this.EffectiveSize < inflatesize) this.EffectiveSize = inflatesize;
        if (this.ChunkOffset + this.ChunkSize >= inflatesize) {
            this.EffectiveSize += inflatesize;
        }
        if (this.EffectiveSize > this.TotalSize) this.EffectiveSize = this.TotalSize;
        if (this.IsAsync) {
            if (! partial) {
                this.Lines.length = 0;
                for (var ix = 0; ix < this.IsPainted.length; ix ++) {
                    this.IsPainted [ix] = false;
                }
                if (this.ChunkOffset == 0) {
                    this.ScrollParent.scrollTop = 0;
                }
            }
            if (this.TotalSize == 0) return;
        }
    }
    if (this.Name == name) {
        this.Current = node.getAttribute ("text");
        if (this.Current != null) return;
        entries = node.getElementsByTagName ('choice');
        var checkSelected = entries.length >= 1;
        if (checkSelected) {
            entries = entries[0].getElementsByTagName ('element');
        } else {
            entries = node.getElementsByTagName ('element');
        }
        height = entries.length;

        if (this.IsAsync && partial) {
            for (rix = 0; rix < height; ++rix) {
                entry = entries [rix].getAttribute("text");
                if (!checkSelected || entries [rix].getAttribute("selected") == "yes") {
                    this.AppendIfMissing(this.Selected, entry);
                }
            }
        } else {
            var selix = 0;
            var disix = 0;
            var lckix = 0;
            for (rix = 0; rix < height; ++rix) {
                entry = entries [rix].getAttribute("text");
                if (!checkSelected || entries [rix].getAttribute("selected") == "yes") {
                    this.Selected [selix++] = entry;
                }
            }
            this.Selected.length = selix;
        }
        {
            entries = node.getElementsByTagName ("choice");
            if (entries.length >= 1) entries = entries[0].getElementsByTagName ("element");
            height = entries.length;
            
            if(0 < height && this.ByValue == null) {
                this.ByValue = (entries[0].getAttribute("value") != null);
            }
        }
        if (this.ByValue == true) {
            if (this.AllValues == null) this.AllValues = new Array ();
            var entries = node.getElementsByTagName ("choice");
            if (entries.length >= 1) entries = entries[0].getElementsByTagName ("element");
            var height = entries.length;
            if (this.IsAsync) {
                if (! partial) {
                    this.AllValues.length = this.EffectiveSize;
                }
                var ChunkOffset = this.ChunkOffset;
                for (var rix = 0; rix < height; ++rix) {
                    this.AllValues [rix + ChunkOffset] = entries [rix].getAttribute("value");
                }
            } else {
                this.AllValues.length = height;
                for (var rix = 0; rix < height; ++rix) {
                    this.AllValues [rix] = entries [rix].getAttribute("value");
                }
            }
        }
    }
    if (this.PageName == name && this.AutoCol && mode != 'h') {
        this.FixCol(mode, node, name, partial);
    }
    if (this.Name == "" && this.PageName == name) {
        // navigation has been updated, that is enough
        return;
    }
    var colmgr = this.ColDict[name];
    if (colmgr == null) {
        alert ('PaintTable unknown name:' + name);
        return;
    }
    var xIx = (this.Name == name && colmgr.Index != 0) ? 0 : -1;
    var entries;
    if(this.Name != name) {
        entries = node.getElementsByTagName('element');
    } else {
        entries = node.getElementsByTagName ("choice");
        if (entries.length >= 1) entries = entries[0].getElementsByTagName ("element");
    }
    var height = entries.length;
    if (height > this.TableLimit) {
        TableTruncateAlert (this.Name, height);
        height = this.TableLimit;
    }
    var rowsskipped = 0;
    var full_rix = 0;
    for (var rix = 0; rix < height; ++rix) {
        var entry = entries [rix];
        var optval = entry.getAttribute("text");
        var position = entry.getAttribute ('position');
        if (this.IsHeader) {
            if (! position == 'top') continue;
            if (! position) break;
        }
        if (this.IsBody) {
            if (position) {
                rowsskipped++
                continue;
            }
        }
        full_rix = rix - rowsskipped;
        if (this.IsAsync) {
            full_rix += this.ChunkOffset;
        }
        if (this.Lines [full_rix] == null) this.Lines [full_rix] = new Array ();
        var header = entry.getAttribute ('isheader');
        if (header && header == 'true') this.Lines [full_rix].IsHeader = true;
        this.IsPainted [full_rix] = false;
        this.Lines [full_rix][colmgr.Index] = new this.CellObject (optval, entry);
        if (xIx >= 0) this.Lines [full_rix][xIx] = new this.CellObject (optval, entry);
    }
    if (! this.IsAsync && height > 0) {
        this.Lines.length = full_rix + 1;
    }
    if (height == 0) {
        this.Lines.length = 0;
    }
}

Qva.Mgr.table.prototype.StyleObject = function (node) {
    this.BgColor = node.getAttribute ('bgcolor');
    this.Color = node.getAttribute ('color');
    this.NumAdjust = node.getAttribute ('numadjust');
    this.TextAdjust = node.getAttribute ('textadjust');
    this.BorderStyle = node.getAttribute ('borderstyle');
    var fontstyle = node.getAttribute ('fontstyle')
    this.FontStyle = fontstyle;
    this.FontWeight = node.getAttribute ('fontweight');
    this.TextDecoration = node.getAttribute ('textdecoration');
    this.SizeMod = node.getAttribute ('sizemod');
    var stretchmode = node.getAttribute ('stretchmode');
    if (stretchmode) this.StretchMode = stretchmode;
}

Qva.Mgr.table.prototype.BorderStyleObject = function (node) {
    this.Top = node.getAttribute ('top');
    this.Bottom = node.getAttribute ('bottom');
    this.Left = node.getAttribute ('left');
    this.Right = node.getAttribute ('right');
}

Qva.Mgr.table.prototype.GetIndex = function (line) {
    if (this.ChoiceIx < 0) return 0;
    var val = line [this.ChoiceIx].val;
    if (this.Current != null) {
        return (this.Current === val) ? 1 : 0;
    }
    for (var ix = 0; ix < this.Selected.length; ++ix) {
        if (this.Selected [ix] === val) return 1;
    }
    return 0;
}

Qva.Mgr.table.prototype.GetSelected = function (rix, cix) {
    var line = this.Lines [rix];
    return line[cix] ? line[cix].selected : false;
}

Qva.Mgr.table.prototype.GetDisabled = function (rix, cix) {
    var line = this.Lines [rix];
    return line [cix] ? line [cix].disabled : true;
}

function AvqAction_TableCheck () {
    var box = this;
    var row = box.parentNode.parentNode;
    if (row.tagName != 'TR') return;
    var mgr = row.parentNode.AvqMgr;
    if (mgr == null) mgr = row.parentNode.parentNode.AvqMgr;
    if (mgr == null) return;
    if (! mgr.PageBinder.Enabled) return;
    var selIx = row.rix;
    var SearchActive = (mgr.Search != null && mgr.Search.value != '');
    var valName = (mgr.Count != null) ? mgr.Count : mgr.Name;
    if (mgr.ByValue && mgr.PageBinder.Autoview != null) {
        // This code is not bw compat, check against AvqAutoView for "QlikView-only" activation
        // There is no other logical connection with AvqAutoView
        var ixVal = mgr.AllValues [selIx];
        mgr.PageBinder.Set (valName, 'count', (box.checked ? ' ' : '-') + ixVal, ! SearchActive);
    } else if (mgr.ChoiceIx != -1)  {
        var ixName = mgr.Lines [selIx][mgr.ChoiceIx].val;
        mgr.PageBinder.Set (valName, 'count', (box.checked ? ' ' : '-') + ixName, ! SearchActive);
    } else {
        var colname = mgr.ColList[box.parentNode.cellIndex].Name;
        mgr.PageBinder.Set (mgr.Group, 'cell', selIx + ':' + colname + ':' + (box.checked ? '1' : '0'), ! SearchActive);
    }
    if (SearchActive) {
        mgr.PageBinder.Set (mgr.SearchName, "closesearch", "abort", true);      // break out of search mode
        if (mgr.Search != null) mgr.Search.value = '';				// Allow for popup search being closed
    }
}

function AvqAction_TableInput () {
    var box = this;
    var row = box.parentNode.parentNode;
    if (row.tagName != 'TR') return;
    var mgr = row.parentNode.AvqMgr;
    if (mgr == null) mgr = row.parentNode.parentNode.AvqMgr;
    if (mgr == null) return;
    if (! mgr.PageBinder.Enabled) return;
    var selIx = row.rix;
    var colname = mgr.ColList[box.parentNode.cellIndex].Name;
    mgr.PageBinder.Set (mgr.Group, 'cell', selIx + ':' + colname + ':' + box.value, true);
}

Qva.Mgr.table.prototype.appendCellIcon = function (icon, cix, rix, stretchmode, adjust, colmgr) {
    var img = document.createElement ("img");
    var style = 'cursor: pointer;';
    var iconstyle = icon.getAttribute ("iconstyle");
    var alttext = icon.getAttribute ("alttext");
    img.alt = alttext ? alttext : "";
    if (iconstyle != null) {
        style += ' left:0px; top:0px; ' + iconstyle;
    } else {
        style += ' float:right; top:2px; right:1px; position:relative;';
    }
    var stamp = icon.getAttribute ("stamp");
    var sendsizetoserver = icon.getAttribute ("sendsize") == "true";
    if (sendsizetoserver) {
        if (colmgr.CellHeight == -1 || colmgr.CellWidth == -1) debugger;
        style += "height:" + colmgr.CellHeight + "px; width:" + colmgr.CellWidth + "px; ";
    }
    img.style.cssText = style;
    
    var url = icon.getAttribute ("url");
    if (url) {
        img.src = url;
    } else {
        var name = icon.getAttribute ("name");
        var stamp = icon.getAttribute ("stamp");
        var color = icon.getAttribute ("color");
        var url = this.PageBinder.BuildBinaryUrl (icon.getAttribute ("path"), stamp, name, color);
        if (! this.PageBinder.IsHosted && sendsizetoserver) {
            url += "&width=" + colmgr.CellWidth + "&height=" + colmgr.CellHeight + "&stretchmode=" + stretchmode + "&adjust=" + adjust;
        }
        img.src = url;
        
        var action       = icon.getAttribute ("action");
        var clientaction = icon.getAttribute ("clientaction");
        var drag         = icon.getAttribute ("drag");
        if (action || clientaction) {
            var binder = this.PageBinder;
            img.binderid = this.PageBinder.ID;
            if (action) {
                img.onmousedown = avq_action_md;
                img.onmouseup = avq_action_mu;
                img.pressed = false;
                img.action = action;
            } else if (clientaction) {
                img.onmousedown = Qva.CancelAction;
                img.onmouseup = Qva.CancelAction;
                img.onclick = onclick_ContextClientAction;
                img.AvqMgr = this;
                img.clientaction = clientaction;
                img.param = icon.getAttribute ("param");
            }
            var targetname = colmgr.Name.split ('.') [1];
            img.targetname = targetname;
            img.xx = cix;
            img.yy = rix;
            if (icon.getAttribute ("menu") == "true") {
                img.position = action + ":" + cix + ":" + rix;
                img.oncontextmenu = function (event) { 
                    this.pressed = false;
                    return Qva.GetBinder(this.binderid).OnContextMenu(event, this.Name); 
                }
            }
        } else if(drag) {
            img.dragObj = { 'Name': this.PageName, 'type': "col" };
        } else {
            img.ondrag = function () { return false; };
            img.onmousedown = Qva.NoAction;
            img.onmouseup = Qva.NoAction;
            img.onclick = Qva.NoAction;
        }
    }
    return img;
}

Qva.Mgr.table.prototype.appendCellContent = function (cell, data, text, cix, rix, colmgr) {
    if (! this.ByValue) rix += this.HeaderRowCount + this.PageOffsetForPainting ();
    var level = parseInt (data.level);
    if (! isNaN (level)) {
        var level = parseInt (data.level);
        var paddingleft = cell.origpadding;
        if (isNaN (cell.origpadding)) {
            if (IS_GECKO || IS_SAFARI || IS_OPERA || IS_CHROME) {
                var gs = document.defaultView.getComputedStyle (cell, "");
                paddingleft = parseInt (gs.getPropertyValue ("padding-left"));
            } else {
                paddingleft = parseInt (cell.currentStyle.paddingLeft);
            }
            cell.origpadding = paddingleft;
        } else {
            paddingleft = cell.origpadding;
        }
        for (var i = 0; i < parseInt (data.level); i++) paddingleft += 10;
        cell.style.paddingLeft = paddingleft + "px";
    }
    cell.innerHTML = "";
    var textalign = "left";
    var style = this.Style [data.style];
    var stretchmode = null;
    if (style) {
        textalign = data.isnum ? style.NumAdjust : style.TextAdjust;
        stretchmode = style.StretchMode;
    }
    if (data.frequency) {
        if (textalign != "right") {
            var span = document.createElement ("span");
            span.innerText = data.frequency;
            span.style.position = "absolute";
            span.style.textAlign = "right";
            cell.appendChild  (span);
            var left = cell.offsetLeft - span.offsetWidth - 1;
            if (colmgr.CellWidth != -1) {
                left += colmgr.CellWidth;
            } else {
                left += cell.offsetWidth;
                debugger;
            }
            if (IS_GECKO || IS_OPERA) {
                left -= 3;
            }
            span.style.left = left + "px";
        } else {
            text += "  " + data.frequency;
        }
    }
    for (var iicons = 0; iicons < data.icons.length; iicons++) {
        var icon = data.icons [iicons];
        var iconelem = this.appendCellIcon (icon, cix, rix, stretchmode, textalign, colmgr);
        cell.appendChild (iconelem);
    }
    if (data.parts && data.parts.length > 0) {
        var currentpos = 0;
        var currentpart = 0;
        while (text != "") {
            var part = data.parts [currentpart++];
            if (part) {
                var partpos = parseInt (part.getAttribute ("pos"));
                var partcount = parseInt (part.getAttribute ("count"));
                if (partpos > currentpos) {
                    var span = document.createElement ("span");
                    span.innerText = text.substr (0, partpos - currentpos);
                    text = text.substr (partpos - currentpos)
                    currentpos = partpos;
                    cell.appendChild (span);
                } 
                var span = document.createElement ("span");
                span.innerText = text.substr (0, partcount);
                text = text.substr (partcount)
                currentpos += partcount;
                span.className = "qvHighLighted";
                cell.appendChild (span);
            } else {
                var span = document.createElement ("span");
                span.innerText = text;
                cell.appendChild (span);
                text = "";
            }
        }
    } else {
        var textnode = document.createTextNode (text);
        cell.appendChild (textnode);
    }
}

Qva.Mgr.table.prototype.GetScrollWidth = function () {
    if (IS_MAC) {
        return 15;
    } else {
        return 17;
    }
}

Qva.Mgr.table.prototype.GetScrollHeight = function () {
    if (IS_MAC) {
        return 15;
    } else {
        return 17;
    }
}

Qva.Mgr.table.prototype.HasHorizontalScrollbar = function () {
    return getClientWidth (this.Frame) < this.Element.offsetWidth && ! this.SupressHorizontalScroll;
}

Qva.Mgr.table.prototype.HasVerticalScrollbar = function (maxheight, scrollheight) {
    var numberofrows = isNaN (this.TotalSize) ? this.Lines.length : this.TotalSize;
    var calculatedscrollheight = this.RowHeight * numberofrows;
    var HasVerticalScrollbar = (maxheight - scrollheight) < calculatedscrollheight;
    HasVerticalScrollbar = HasVerticalScrollbar || this.Element.offsetHeight > (maxheight - scrollheight);
    return HasVerticalScrollbar;
}

Qva.Mgr.table.prototype.FixTableWidth = function (header) {
    if (this.Lines.length > 0 && this.getTableElement ().offsetWidth < 10) debugger;
    var scrollheight = 0;
    if (this.HasHorizontalScrollbar ()) {
        scrollheight = this.GetScrollHeight ();
    }
    var HasVerticalScrollbar = this.HasVerticalScrollbar (parseInt (getContentMaxHeight (this.ScrollParent)), scrollheight);
    var scrollwidth = 0;
    if (HasVerticalScrollbar) {
        scrollwidth = this.GetScrollWidth ();
    }

    var maxwidth = getMaxClientWidth (this.Frame);
    var delta = maxwidth - this.UnmodifiedTableWidth;
    var modifylastcolumn = this.SupressHorizontalScroll && delta < 0 || (delta > 0 && delta < scrollwidth);

    var lastheadercells = new Array ();
    if (header) {
        for (var i = 0; i < header.rows.length; i ++) {
            if (header.rows [i].cells [this.Width - 1]) {
                lastheadercells [lastheadercells.length] = header.rows [i].cells [this.Width - 1];
            }
        }
    }
    var newscrollwidth = maxwidth;
    var newheaderwidth = newscrollwidth;
    var lastheadercellfixed = false;
    if (this.Body.rows.length > 0) {
        var cell = this.Body.rows[0].cells [this.Width - 1];
        if (modifylastcolumn) {
            cell.style.width = "";
            for (var i = 0; i < lastheadercells.length; i ++) {
                lastheadercells [i].style.width = "";
            }
            if (this.SupressHorizontalScroll) {
                this.getTableElement ().style.width = (newscrollwidth - scrollwidth) + "px";
            } else {
                debugger;
            }
        } else {
            cell.style.width = this.LastColWidth;
            if (this.m_HasVerticalScrollbar != HasVerticalScrollbar) {
                this.getTableElement ().style.width = this.UnmodifiedTableWidth + "px";
            }
            if (! HasVerticalScrollbar) {
                for (var i = 0; i < lastheadercells.length; i ++) {
                    lastheadercells [i].style.width = this.LastColWidth;
                }
            }
            if (! this.SizeTodata && this.getTableElement ().offsetWidth < newscrollwidth) {
                newheaderwidth = this.getTableElement ().offsetWidth;
                if ((IS_CHROME || IS_GECKO || IS_SAFARI) && lastheadercells.length > 0) {
                    if (parseInt (lastheadercells [0].style.width) != parseInt (this.LastColWidth)) {
                        for (var i = 0; i < lastheadercells.length; i ++) {
                            lastheadercells [i].style.width = this.LastColWidth;
                        }
                    }
                    lastheadercellfixed = true;
                }
                scrollwidth = 0;
            } else if (this.SupressHorizontalScroll) {
                newheaderwidth = this.UnmodifiedTableWidth;
                this.getTableElement ().style.width = this.UnmodifiedTableWidth + "px";
                if (this.SizeTodata) {
                    newheaderwidth += scrollwidth;
                    newscrollwidth = newheaderwidth;
                }
                if (scrollwidth != 0) {
                    scrollwidth++
                }
            } else if (this.getTableElement ().offsetWidth < newscrollwidth) {
                if (this.SizeTodata) {
                    newscrollwidth = this.getTableElement ().offsetWidth;
                    newscrollwidth += scrollwidth;
                    newheaderwidth = newscrollwidth;
                } else {
                    debugger;
                }
            } else {
                // Horizontal scrollbar
                newheaderwidth = Math.max (this.getTableElement ().offsetWidth, 1);
                newheaderwidth += scrollwidth;
                if (scrollwidth != 0) {
                    scrollwidth++
                }
            }
        } 
    } else {
        // No data cells
        if (modifylastcolumn) {
            for (var i = 0; i < lastheadercells.length; i ++) {
                lastheadercells [i].style.width = "";
            }
        } else {
            newscrollwidth = this.UnmodifiedTableWidth;
            newheaderwidth = this.UnmodifiedTableWidth;
        }
    }
    if (header) {
        header.style.width = newheaderwidth + "px";
        if (lastheadercells.length > 0) {
            if (IS_GECKO || IS_SAFARI || IS_CHROME) {
                var bodycell = this.Body.rows [0] ? this.Body.rows [0].cells [this.Width - 1] : null;
                if (bodycell) {
                    if (HasVerticalScrollbar && ! (this.SupressHorizontalScroll && modifylastcolumn) && ! lastheadercellfixed) {
                        var cellwidth = getClientWidth (bodycell);
                        if (parseInt (lastheadercells [0].style.width) != cellwidth) {
                            for (var i = 0; i < lastheadercells.length; i ++) {
                                lastheadercells [i].style.width = cellwidth + "px";
                            }
                        }
                    }
                } else {
                    debugger;
                }
            }
            var rightpadding = scrollwidth != 0 ? scrollwidth + "px" : "";
            if (parseInt (lastheadercells [0].style.paddingRight) != parseInt (rightpadding)) {
                for (var i = 0; i < lastheadercells.length; i ++) {
                    lastheadercells [i].style.paddingRight = scrollwidth != 0 ? scrollwidth + "px" : "";
                }
            }
        }
    }
    
    var deltaframeX = maxwidth - newscrollwidth;
    setFrameWidth (this.Frame, deltaframeX);
    var resetpaint = this.m_HasVerticalScrollbar != null && ! this.m_HasVerticalScrollbar && HasVerticalScrollbar;
    setContentWidth (this.Frame, newscrollwidth);
    if (this.ScrollBar && this.SizeTodata) { 
        this.getTableElement ().style.width = (newscrollwidth - scrollwidth) + "px";
        var table = this.getTableElement();
        var element = this.Element;
        setTimeout(function() {
            element.style.width = table.offsetWidth + "px"; 
            //alert("x: " + table.offsetWidth);
        }, 1);
    }
    this.m_HasVerticalScrollbar = HasVerticalScrollbar;
    return resetpaint;
}


Qva.Mgr.table.prototype.FixTableHeight = function () {
    var objectframeclientheight = getMaxClientHeight (this.Frame);
    var maxscrollheight = getContentMaxHeight (this.ScrollParent);
    var newscrollheight = maxscrollheight;
    if (this.ScrollParent.clientHeight == 0 && this.Element.offsetHeight == 0) {
        return;
    }
            
    if (this.SizeTodata) {
        var realHeight, sParent;
        if(this.ScrollBar && this.Body.rows.length > 0) {
            realHeight = this.RowHeight * this.ScrollBar.TotalRows;
            realWidth = this.Element.getElementsByTagName("table")[0].offsetWidth;
            sParent = this.Element;
        } else {
            realHeight = this.Element.offsetHeight;
            realWidth = this.Element.offsetWidth
            sParent = this.ScrollParent;
        }
        if (realHeight < newscrollheight) {
            var hashorizontalscrollbar = getClientWidth (this.Frame) < realWidth && ! this.SupressHorizontalScroll;
            newscrollheight = realHeight;
            if (hashorizontalscrollbar) {
                var scrollheight = sParent.offsetHeight - sParent.clientHeight;
                newscrollheight += scrollheight;
            }
        }
    } else {
//                debugger;
    }
    var deltaframeY = maxscrollheight - newscrollheight;
    if (parseInt (this.ScrollParent.style.height) != newscrollheight) {
        if (isNaN(newscrollheight)) {
            this.ScrollParent.style.height = "1px";
        } else {
            this.ScrollParent.style.height = Math.max (newscrollheight, 1) + "px";
        }
    }
    setFrameHeight (this.Frame, deltaframeY);
    if (this.ScrollBar) {
        var cellheight = this.RowHeight == -1 ? this.Body.rows [0].cells [0].offsetHeight : this.RowHeight;
        
        var scrollBar = this.ScrollBar;
        setTimeout(function() {
            scrollBar.Height = getClientHeight(this.ScrollParent);
        }, 1);
        this.Element.style.height = "auto";
        this.Element.parentNode.style.height = "auto";
        var maxRows = Math.max(1, Math.min(this.TotalSize, Math.floor(getContentMaxHeight(this.ScrollParent) / cellheight)));
        if(this.ScrollBar.VisibleRows != maxRows || this.ScrollBar.TotalRows != this.TotalSize) {
            this.ScrollBar.UpdateSize(this.TotalSize, maxRows);
            postpaintposted = true;
            Qva.QueuePostPaintMessage (this);
            return;
        }
    }
}


Qva.Mgr.table.prototype.PostPaint = function () {
    this.debugcounter++;
    if (this.debugcounter > 50) {
        debugger;
        this.debugcounter = 0;
        return;
    }
    
    if (this.Lines == null) return;
    if (!this.ScrollParent || (this.ScrollParent.style && this.ScrollParent.style.display == 'none')) {
        this.Fixed = true;
        return;
    }
    
    if (this.RowHeight <= 0 && this.Body.rows [0] && this.Body.rows [0].cells [0]) {
        if (this.Lines.length > 0 && this.Lines [0].length > 0) {
            if (this.Body.rows [0].cells [0].offsetHeight > 0) {
                if (IS_GECKO || IS_OPERA) {
                    this.RowHeight = this.Body.rows [0].offsetHeight;
                } else {
                    this.RowHeight = getClientHeight (this.Body.rows [0].cells [0]);
                }
                if (this.IsBody && this.ScrollBar) {
                    //this.ScrollBar.UpdateSize(this.TotalSize, getContentMaxHeight (scrollParent) / this.RowHeight);
                    //this.ScrollBar.UpdateHeight (getContentMaxHeight (scrollParent));
                    this.ScrollBar.UpdateSize(this.TotalSize, 1); 
                }
            }
        }
    }
    if (this.Frame.style && this.Frame.style.display == 'none') return;
    var WantedChunkNumber = null;
    var postpaintposted = false;
    var header = this.Element.Header;
    var lastheadercell = null;
    if (header != null) {
        if (header != this.Element) {
            if (! header.AvqMgr.Fixed) {
                Qva.QueuePostPaintMessage (this);
                return;
            }
            lastheadercell = header.rows [0] ? header.rows [0].cells [this.Width - 1] : null;
        } else {
            debugger;
        }
    }
    var frame = Qva.GetFrame (this.Element);
    if (frame) {
        if (frame.AvqMgr && frame.AvqMgr.Dirty) {
            Qva.QueuePostPaintMessage (this);
            return;
        }
        if (frame.Caption) {
            if (frame.Caption.AvqMgr && frame.Caption.AvqMgr.Dirty) {
                Qva.QueuePostPaintMessage (this);
                return;
            }
        }
    }
    if (frame && this.InlineStyle && ! this.IsTransient && ! (IS_GECKO || IS_SAFARI || IS_OPERA || IS_CHROME)) {
        // In IE "medium" means that the element is not yet attached to the DOM
        if (this.Frame.currentStyle.borderLeftWidth == "medium") {
            Qva.QueuePostPaintMessage (this);
            return;
        }
    }
    if (this.IsBody && this.LastColWidth) {
        if (! this.UnmodifiedTableWidth) {
            this.UnmodifiedTableWidth = this.getTableElement ().offsetWidth;
            if (header) this.UnmodifiedTableWidth = Math.max (this.UnmodifiedTableWidth, header.offsetWidth);
        }
    }
    var height;
    if (!this.IsHeader) {
        if (this.TotalSize == 0 || this.Lines.length == 0) {
            height = 0;
        } else if (this.ScrollBar && this.RowHeight > 1) {
            height = this.ScrollBar.VisibleRows;
        } else if (this.IsAsync) {
            height = this.EffectiveSize;
        } else {
            height = this.Lines.length;
        }
    } else {
        height = this.Lines.length;
    }
    var rowlen = this.Body.rows.length;
    if (height != rowlen) {
        if (!this.ScrollBar && this.IsAsync && height < rowlen && rowlen <= this.TotalSize) {
            // special case: new table data is shorter for Mozilla
            this.EffectiveSize = rowlen;
            height = this.EffectiveSize;
        } else {
            this.Inflate (height, rowlen);	// make sure table is right size
        }
    }

    if (this.IsBody && this.LastColWidth) {
        if (this.FixTableWidth (header)) {
            Qva.QueuePostPaintMessage (this);
            return;
        }
    }

    if (! this.Fixed) {
        if (this.IsBody) {
            this.FixTableHeight ();
        } else {
            this.Fixed = true;
        }
    }

    var newscrollheight;
    if (this.InlineStyle && this.IsBody) {
        newscrollheight = getContentMaxHeight (this.ScrollParent);
    } else {
        newscrollheight = getClientHeight (this.ScrollParent);
    }
    var rix_start = 0;
    var rix_stop = height;
    if (! this.ScrollBar && this.IsAsync) {
        if (this.TotalSize < this.PageSize) {
            rix_start = 0;
            rix_stop = this.TotalSize;
        } else {
            var scrollpos = this.ScrollParent.scrollTop;
            rix_start = this.RowForPos (this.Body.rows, scrollpos);
            if (this.ChunkOffset == 0 && scrollpos == 0 && rix_start != 0) {
                rix_start = 0;
                rix_stop = this.PageSize;
            } else {
                rix_stop = this.RowForPos (this.Body.rows, scrollpos + newscrollheight) + 1;
                var visibleScrollRowsDiv2 = Math.ceil ((rix_stop - rix_start) / 2);
                rix_start -= visibleScrollRowsDiv2;
                rix_stop += visibleScrollRowsDiv2;
            }
            if (rix_start < 0) rix_start = 0;
            if (rix_stop > height) rix_stop = height;
            if (rix_stop > this.TotalSize) rix_stop = this.TotalSize;
        }
    }

    var rows = this.Body.rows;
    var PaintedLines = 0;
    var LastRowAdjusted = false;
    this.HeaderRowCount = header ? header.rows.length : 0;
    this.Height = this.IsBody ? this.TotalSize : rows.length;
    for (var rix = rix_start; rix < rix_stop; ++ rix) {
        if (!this.ScrollBar && this.IsPainted [rix]) continue;
        var lix = rix + this.PageOffsetForPainting ();
        var line = this.Lines[lix];
        var row = this.Body.rows[rix];
        if (line == null) {
            if (WantedChunkNumber == null && lix < this.TotalSize) {
                WantedChunkNumber = Math.floor (lix / this.ChunkSize);
            }
            if (row != null) {
                for (var cix = 0; cix < row.cells.length; ++ cix) {
                    row.cells [cix].innerText = '|';
                }
            }
            break;
        }
        var IsSelected = this.GetIndex(line);
        var rcix = rix % this.RowClassNames.length;
        if (row.className != this.RowClassNames [rcix]) {
            row.className = this.RowClassNames [rcix];
        }
        if (row.rix == null) row.rix = rix;
        for (var cix = 0; cix < this.Width; ++ cix) {
            var colmgr = this.ColList [cix];
            if (! colmgr) continue;
            if (this.ByValue == null) {
                this.ByValue = colmgr.Cmd == 'edit' || colmgr.Cmd == 'windowsedit';
            }
            var cell = row.cells [cix];
            if (cell == null) {
                cell = document.createElement ("td");
                row.appendChild (cell);
            }
            if (!colmgr.IsLocal && line [cix] == null) {
                cell.style.display = "none";
            } else {
                if (this.RowHeight > 1) {
                    var rowheight = this.RowHeight * line[cix].rowspan;
                    if (this.WindowsSelectionstyle) {
                        rowheight = Math.max (rowheight, 20);
                    }
                    cell.style.height = rowheight + "px";
                    if (colmgr.CellWidth == -1) colmgr.CellWidth = getClientWidth (cell);
                    colmgr.CellHeight = rowheight;
                }
                cell.style.display = "";
                var IsDisabled = this.GetDisabled (lix, cix);
                colmgr.PaintCell (line, cell, rix, IsDisabled || IsSelected);
                cell.oncontextmenu = function (event) { this.pressed = false ; return Qva.GetBinder(this.binderid).OnContextMenu(event); }
                cell.binderid = this.PageBinder.ID;
                cell.position = cix + ":" + rix + ":";
                cell.position += this.IsHeader ? "Head" : "Body";
                var targetname = colmgr.Name.split ('.') [1];
                if (targetname == "Fields") targetname += "." + colmgr.Name.split ('.') [2]
                cell.targetname = targetname;
            }
        }

        this.IsPainted [rix] = true;
        PaintedLines ++;
        if (!this.ScrollBar && PaintedLines >= this.PageIncr && this.IsAsync) {
            postpaintposted = true;
            Qva.QueuePostPaintMessage (this);
            break;
        }
    }
    if (this.IsBody && this.LastColWidth && ! this.AllwaysFullWidth) {
        var scrollheight = 0;
        if (this.HasHorizontalScrollbar ()) {
            scrollheight = this.GetScrollHeight ();
        }
        var HasVerticalScrollbar = this.HasVerticalScrollbar (parseInt (getContentMaxHeight (this.ScrollParent)), scrollheight);
        if (this.m_HasVerticalScrollbar != HasVerticalScrollbar) {
            Qva.QueuePostPaintMessage (this);
            return;
        }
    }
    
    this.Unlock ();
    this.Element.style.display = "";
    if (WantedChunkNumber != null) {
        var newChunkOffset = WantedChunkNumber * this.ChunkSize;
        if (this.ChunkOffset != newChunkOffset) {
            this.ChunkOffset = newChunkOffset;
            this.PageBinder.PartialLoad (this.PageName, this.ChunkOffset);
        }
    }
    if (! this.Fixed && this.IsBody) {
        this.FixTableHeight ();
        this.Fixed = true;
    }
}

Qva.Mgr.table.prototype.Inflate = function (height, rowlen) {
    var mgr = this;
    var body = mgr.Body;
    var bodyParent = body.parentNode;
    var onerow = document.createElement ("tr");
    for(var i = 0; i < this.Width; ++i) {
        var cell = document.createElement ("td");
        var colmgr = mgr.ColList [i];
        cell.className = colmgr.ClassName;
        cell.align = colmgr.Align;
//        switch (colmgr.Cmd) {
//        case 'check':
//            cell.innerHTML = '<input class="avqCheckbox" type=checkbox >';
//            break;
//        default:
            cell.innerHTML = "|";
//        }
        onerow.appendChild (cell);
    }
    var height_to_inflate = height;
    var chunksize = mgr.ChunkSize;
    if (chunksize == null || chunksize <= 0) chunksize = 20;
    for (var rix = 0; rix < rowlen && rix < height_to_inflate; ++ rix) {
        mgr.IsPainted [rix] = false;
        var row = body.rows [rix];
        row.rix = rix;
        row.style.position = "static";
    }
    for (var rix = rowlen; rix < height_to_inflate; ++ rix) {
        mgr.IsPainted [rix] = false;
        var row = null;
        if (rix == 0 && mgr.Body.rows [0]) {
            row = mgr.Body.rows [0].cloneNode (true);
        } else {
            row = onerow.cloneNode (true);
        }
        row.rix = rix;
        var rcix = rix % mgr.RowClassNames.length;
        row.className = mgr.RowClassNames [rcix];
        body.appendChild (row);
    }
    if (height_to_inflate < height) {
        var last_rix = height - 1;
        var rcix = last_rix % mgr.RowClassNames.length;
        var row = null;
        if (body.rows.length <= height_to_inflate) {
            row = onerow.cloneNode (true);
            row.className = mgr.RowClassNames [rcix];
            row.style.position = "absolute";
            row.style.left = body.rows [1].offsetLeft + "px";
            row.style.top = body.rows [1].offsetHeight * last_rix + "px";
            body.appendChild (row);
        } else {
            while (body.rows.length > height_to_inflate + 1) {
                body.deleteRow (height_to_inflate + 1);
            }
            row = body.rows [height_to_inflate];
            row.className = mgr.RowClassNames [rcix];
            row.style.position = "absolute";
            row.style.left = body.rows [1].offsetLeft + "px";
            row.style.top = body.rows [1].offsetHeight * last_rix + "px";
        }
        row.rix = last_rix;
    }
    
//var fillTime = new Date ().valueOf () - Time;
    if (height_to_inflate == height) {
        while (mgr.Body.rows.length > height_to_inflate) {
            mgr.Body.deleteRow (height_to_inflate);
        }
    }
//Time = new Date ().valueOf () - Time;
//if (timeIt) alert ("Time: " + Time + " cloneTime: " + cloneTime + " fillTime: " + fillTime + " swapBody: " + swapBody + " height: " + height);
}

Qva.Mgr.table.prototype.RowForPos = function (rows, pos) {
    var lo = 0;
    var hi = rows.length;
    while (hi - lo > 1) {
        var m = Math.floor ((hi + lo) / 2);
        if (rows [m].offsetTop > pos) {
            hi = m;
        } else {
            lo = m;
        }
    }
    return lo;
}


Qva.Mgr.table.prototype.PageOffsetForPainting = function () {
    if(this.ScrollBar) {
        return this.ScrollBar.GetOffset();
    } else {
        return 0;
    }
}

Qva.Mgr.table.prototype.GetSelectionStateClassName = function (is_selected, is_enabled, is_disabled, is_locked, is_deselected) {
    if (is_selected == true) {
        return this.SelectedClassName;
    } else if (is_deselected == true) {
        return this.DeselectedClassName;
    } else if (is_enabled == true) {
        return this.EnabledClassName;
    } else if (is_disabled == true) {
        return this.DisabledClassName;
    } else if (is_locked == true) {
        return this.LockedClassName;
    } else {
        return "";
    }
}

Qva.Mgr.table.prototype.ClearSelection = function () {
    if (window.getSelection) {
        window.getSelection().removeAllRanges();
    } else {
        window.document.selection.empty ();
    }
}

Qva.Mgr.table.prototype.IndicateCellsToSelect = function (ctrl, clearselection) {
    if (this.SelectionStartRow == null) return;
    if (this.Element.id != Qva.SearchableObject) {
        SetActiveAndSearchable (this.Element.id, this.IsTransient ? Qva.ActiveObject : this.Element.id);
    }
    if (! ctrl) {
        ctrl = this.ctrl;
    }
    var rix_start = this.SelectionStartRow.rix;
    var rix_end = this.SelectionEndRow.rix;
    if (rix_start > rix_end) {
        var tmp = rix_end;
        rix_end = rix_start;
        rix_start = tmp;
    }
    var cix_start = this.SelectionStartCol;
    var cix_end = this.SelectionEndCol;
    if (cix_start > cix_end) {
        var tmp = cix_end;
        cix_end = cix_start;
        cix_start = tmp;
    }
    if (this.prev_cix_start == null) this.prev_cix_start = new Array ();
    if (this.prev_cix_end == null) this.prev_cix_end = new Array ();
    var row_loop_start = this.prev_rix_start != null && this.prev_rix_start < rix_start ? this.prev_rix_start : rix_start;
    var row_loop_end = this.prev_rix_end != null && this.prev_rix_end > rix_end ? this.prev_rix_end : rix_end;
    if (this.AndMode) {
        if (this.CurrentPhase != null && ! clearselection && m_MgrWithPendingAndMode == null) this.CurrentPhase = (this.CurrentPhase + 1) % 3;
    }
    for (var rix = row_loop_start; rix <= row_loop_end; rix ++) {
        var row = this.Body.rows[rix];
        var selIx = rix + this.PageOffsetForPainting ();
        var col_loop_start = this.prev_cix_start [rix] != null && this.prev_cix_start [rix] < cix_start ? this.prev_cix_start [rix] : cix_start;
        var col_loop_end = this.prev_cix_end [rix] != null && this.prev_cix_end [rix] > cix_end ? this.prev_cix_end [rix] : cix_end;
        var actualcixstart = (this.ByValue && rix != row_loop_start) ? 0 : cix_start;
        var actualcixend = (this.ByValue && rix < row_loop_end) ? (row.cells.length - 1) : cix_end;
        col_loop_start = Math.min (col_loop_start, actualcixstart);
        col_loop_end = Math.max (col_loop_end, actualcixend);
        this.prev_cix_start [rix] = actualcixstart;
        this.prev_cix_end [rix] = actualcixend;
        for (var cix = col_loop_start; cix <= col_loop_end; ++ cix) {
            var StateClassName = null;
            var cell = row.cells [cix];
            var IsDisabled = this.GetDisabled (selIx, cix);
            if (rix < rix_start || rix > rix_end || cix < actualcixstart || cix > actualcixend) {
                // restore state
                var IsSelected = (ctrl || cell.windowsselectionstyle) ? this.GetSelected(selIx, cix) : false;
                StateClassName = this.GetSelectionStateClassName (IsSelected, IsDisabled == false, IsDisabled == true);
            } else {
                // change to selected state or toggle if ctrl pressed
                if (this.AndMode) {
                    if (this.CurrentPhase == null) {
                        this.CurrentPhase = 0;
                    }
                    switch (this.CurrentPhase) {
                        case 0:
                            if (ctrl) {
                                StateClassName = IsDisabled ? this.DeselectedClassName : this.SelectedClassName;
                            } else {
                                StateClassName = this.SelectedClassName;
                            }
                            break;
                        case 1:
                            if (ctrl) {
                                StateClassName = IsDisabled ? this.SelectedClassName : this.DeselectedClassName;
                            } else {
                                StateClassName = this.DeselectedClassName;
                            }
                            break;
                        case 2:
                            StateClassName = IsDisabled ? this.DisabledClassName: this.EnabledClassName;
                            break;
                        default:
                            debugger;
                            break;
                    }
                } else {
                    var IsEnabled = !IsDisabled;
                    var IsSelected = (ctrl || cell.windowsselectionstyle) ? !this.GetSelected(selIx, cix) : true;
                    StateClassName = this.GetSelectionStateClassName (IsSelected, IsEnabled, IsDisabled, false);
                }
            }
            var rcix = rix % this.RowClassNames.length;
            if (row.className != this.RowClassNames [rcix]) {
                row.className = this.RowClassNames [rcix];
            }
            var colmgr = this.ColList [cix];
            if (this.ByValue && cell.value == -1) continue;
            var cellClassName = colmgr.ClassName;
            var deselect = clearselection || (StateClassName == this.EnabledClassName);
            if (this.Semantic) {
                if (StateClassName != '') {
                    StateClassName += "_Semantic";
                    if (! deselect) StateClassName += "_Pressed";
                    cellClassName += " " + StateClassName;
                } else {
                    debugger;
                }
            } else if (this.AltClass) {
                if (StateClassName != '') {
                    StateClassName += "_" + this.AltClass;
                    cellClassName += " " + StateClassName;
                } else {
                    debugger;
                }
            } else {
                if (StateClassName != '') {
                    cellClassName += " " + StateClassName;
                }
            }
            if (cell.className != cellClassName) {
                this.IndicateSingleSelect (rix, cix, deselect, StateClassName);
            }
        }
    }
    this.prev_rix_start = rix_start;
    this.prev_rix_end = rix_end;
    if (this.AndMode) {
        this.ctrl = ctrl;
        DelayAndModeToogle (this);
    }
}

var m_MgrWithPendingAndMode = null;

function DelayAndModeToogle (mgr) {
    if (m_MgrWithPendingAndMode != null) return;
    m_MgrWithPendingAndMode = mgr;
    window.setTimeout (AndModeToogle, 1000);
}

function AndModeToogle () {
    var mgr = m_MgrWithPendingAndMode;
    m_MgrWithPendingAndMode = null;
    mgr.IndicateCellsToSelect ();
}

Qva.Mgr.table.prototype.SetCellSelected = function (cell, newclassName, deselect, colmgr) {
    if (cell.windowsselectionstyle) {
        var input = null;
        for (var iElem = 0; iElem < cell.childNodes.length; iElem++) {
            if (cell.childNodes [iElem].tagName == "INPUT") {
                input = cell.childNodes [iElem];
                break;
            }
        }
        if (input == null) debugger;
        var checked = this.SelectedClassName == newclassName;
        input.checked = checked;
    } else {
        if (deselect) {
            if (cell.origcolor != "") {
                cell.style.color = cell.origcolor;
                cell.origcolor = "";
            }
            if (cell.origbackgroundColor != "") {
                cell.style.backgroundColor = cell.origbackgroundColor;
                cell.origbackgroundColor = "";
            }
        } else {
            if (cell.style.color != "") {
                cell.origcolor = cell.style.color;
                cell.style.color = "";
            }
            if (cell.style.backgroundColor != "") {
                cell.origbackgroundColor = cell.style.backgroundColor;
                cell.style.backgroundColor = "";
            }
        }
        var cellClassName = colmgr.ClassName;
        if (newclassName != '') {
            cellClassName += " " + newclassName;
        }
        if (cell.className != cellClassName) {
            cell.className = cellClassName;
        }
    }
}

Qva.Mgr.table.prototype.IndicateSingleSelect = function (rowindex, colindex, deselect, newclassname) {
    var rows = this.Body.rows;
    var row = rows[rowindex];
    var cell = row.cells [colindex];
    var colmgr = this.ColList [colindex];
    if (cell.selectsource) {
        var selectedclassName = this.GetSelectionStateClassName (true, false, false);
        for (var cix = 0; cix < row.cells.length ; cix ++) {
            var cell = row.cells [cix];
            if (! cell.selectsource && (cell.singleselect || cell.multiselect)) {
                this.SetCellSelected (cell, selectedclassName, deselect, colmgr);
            }
        }
        for (var rix = 0; rix < rowindex; rix ++) {
            var cell = rows[rix].cells [colindex];
            if (! cell.selectsource && (cell.singleselect || cell.multiselect)) {
                this.SetCellSelected (cell, selectedclassName, deselect, colmgr);
            }
        }
    } else {
        this.SetCellSelected (cell, newclassname, deselect, colmgr);
    }
}

Qva.Mgr.table.prototype.SetCellStyle = function (data, rix, cix, ignorecolor, hidetext) {
    if (! this.InlineStyle) return "";
    if (! data.style) return "";
    var style = this.Style [data.style];
    if (! style) return ""
    var firstrow = rix == 0;
    var lastrow = this.Height != -1 ? rix == (this.Height - 1) : this.IsHeader;
    var firstcol = cix == 0;
    var lastcol = cix == (this.Width - 1)
    
    var csstext = "";
    if (hidetext) {
        csstext += "; background-color:" + style.BgColor;
        csstext += "; color:" + style.BgColor;
    } else if (! ignorecolor) {
        csstext += "; background-color:" + style.BgColor;
        csstext += "; color:" + style.Color;
    } else {
        csstext += "; background-color:";
        csstext += "; color:";
    }
    csstext += "; text-align:" + (data.isnum ? style.NumAdjust : style.TextAdjust);

    csstext += "; font-style:" + style.FontStyle;
    csstext += "; font-weight:" + style.FontWeight;
    csstext += "; text-decoration:" + style.TextDecoration;
    switch (style.SizeMod) {
        case "2":
            csstext += "; font-size:large";
            break;
        case "1":
            csstext += "; font-size:larger";
            break;
        case "-1":
            csstext += "; font-size:smaller";
            break;
        case "-2":
            csstext += "; font-size:small";
            break;
    }
    if (! this.Semantic) {
        var borderstyle = this.BorderStyle [style.BorderStyle];
        if (borderstyle) {
            var hastopborder = false;
            var hasbottomborder = false;
            if (! (data.subcell == "y")) {
                hastopborder = true;
                if (! (data.first == "y")) {
                    hasbottomborder = true;
                }
            }
            csstext += "; border-bottom:";
            if (lastrow && this.SizeTodata && ! this.IsHeader || ! hasbottomborder) {
                var hiddenborder = borderstyle.Bottom.substr (0, borderstyle.Bottom.indexOf ("#")) + style.BgColor;
                csstext += hiddenborder;
            } else {
                csstext += borderstyle.Bottom;
            }
            csstext += "; border-top:";
            if ((IS_GECKO && GECKO_VERSION < 3.5) || firstrow || ! hastopborder) {
                var hiddenborder = borderstyle.Top.substr (0, borderstyle.Top.indexOf ("#")) + style.BgColor;
                csstext += hiddenborder;
            } else {
                csstext += borderstyle.Top;
            }
            var hasleftborder = false;
            var hasrightborder = false;
            if (! (data.subcell == "x")) {
                hasleftborder = true;
                if (! (data.first == "x")) {
                    hasrightborder = true;
                }
            }
            if ((IS_GECKO && GECKO_VERSION < 3.5) || firstcol || ! hasleftborder) {
                csstext += "; border-left:none";
            } else {
                csstext += "; border-left:" + borderstyle.Left;
            }
            if (lastcol && this.SizeTodata || ! hasrightborder) {
                csstext += "; border-right:none";
            } else {
                csstext += "; border-right:" + borderstyle.Right;
            }
        }
    }
    return csstext;
}

Qva.Mgr.table.prototype.SelectRows = function (ctrl) {
    var rix_start = this.SelectionStartRow.rix;
    var rix_end = this.SelectionEndRow.rix;
    if (rix_start > rix_end) {
        var tmp = rix_end;
        rix_end = rix_start;
        rix_start = tmp;
    }
    var cix_start = this.SelectionStartCol;
    var cix_end = this.SelectionEndCol;
    if (cix_start > cix_end) {
        var tmp = cix_end;
        cix_end = cix_start;
        cix_start = tmp;
    }
    this.IndicateCellsToSelect (ctrl, true);
    this.SelectionStartRow = null;
    this.SelectionEndRow = null;
    this.SelectionStartCol = null;
    this.SelectionEndCol = null;
    if (this.AndMode && this.CurrentPhase == 2) {
        this.CurrentPhase = null;
        return;
    }
    
    var SearchActive = (this.Search != null && this.Search.value != '');
    if (this.ByValue) {
        var sendtext = this.Body.rows[0].cells [0].value == null;
        var singlecellselection = (rix_start == rix_end && cix_start == cix_end);
        var windowsselectionstyleandradio = false;
        if (singlecellselection) {
            if (this.Body.rows[rix_start].cells [cix_start].value == -1) return;
            windowsselectionstyleandradio = this.WindowsSelectionstyle && this.Body.rows[rix_start].cells [cix_start].singleselect == true;
        }
        var selIx = rix_start + this.PageOffsetForPainting ();
        var IsSelected = this.GetIndex(this.Lines[selIx]);
        var valName = this.PageName;
        if (valName == "") {
            valName = this.ColList [0].Name.split ('.') [1];
        }
        if (! ctrl && ! sendtext && (! this.WindowsSelectionstyle || windowsselectionstyleandradio) && ! (IS_SAFARI && IS_MOBILE)) {	// Not toggle mode
            this.PageBinder.Set (valName, 'clear', '', false);
            if (IsSelected && this.Selected.length == 1 && singlecellselection) {
                rix_start ++; // nothing more to do
            }
        }
        var phasesent = false;
        for (var rix = rix_start; rix <= rix_end; rix ++) {
            var row = this.Body.rows[rix];
            var actualcixstart = (rix != rix_start) ? 0 : cix_start;
            var actualcixend = (rix < rix_end) ? (row.cells.length - 1) : cix_end;
            for (var cix = actualcixstart; cix <= actualcixend; cix ++) {
                var cell = row.cells [cix];
                var valValue = cell.value;
                if (ctrl) { // Toggle mode
                    if (! this.AndMode) {
                        this.Lines [rix] [cix].selected = ! this.Lines [rix] [cix].selected;
                    }
                    if (this.AndMode && ! phasesent) {
                        this.PageBinder.TogglePhase = this.CurrentPhase;
                        phasesent = true;
                    }
                    this.PageBinder.ToggleSelect = valName;
                    Qva.ActiveObject = this.Element.id;
                    if (this.PageBinder.ToggleSelects == null) {
                        this.PageBinder.ToggleSelects = new Array ();
                    }
                    this.PageBinder.ToggleSelects [this.PageBinder.ToggleSelects.length] = valValue;
                } else {
                    if (sendtext) {
                        this.PageBinder.Set (valName, 'text', cell.innerText, false);
                    } else {
                        if (this.AndMode && ! phasesent) {
                            this.PageBinder.Set (valName, 'phase', this.CurrentPhase, false);
                            phasesent = true;
                        }
                        this.PageBinder.Set (valName, 'value', valValue, false);
                    }
                }
            }
        }
    } else {
        var valName = this.PageName;
        if (valName == "") {
            valName = this.ColList [0].Name.split ('.') [1];
        }
        var rectstring = '' + cix_start + ':' + (rix_start + this.PageOffsetForPainting ()) + ':' + (cix_end - cix_start + 1) + ':' + (rix_end - rix_start + 1);
        if (this.IsHeader) rectstring += ':Head';
        this.PageBinder.Set (valName, "rect", rectstring, true);
    }
    if (! ctrl) {
        if (SearchActive) {
            this.PageBinder.Set (this.SearchName, "closesearch", "abort", true);      // break out of search mode
            if (this.Search != null) this.Search.value = '';				// Allow for popup search being closed
        } else {
            this.PageBinder.LoadBegin ();
        }
    }
    this.CurrentPhase = null;
}

var m_MgrWithSelectStart  = null;

function AvqAction_TableEditMouseMove (event) {
    if (! event) event = window.event;
    
    var row = this.parentNode;
    if (row.tagName != 'TR') return;
    var mgr = row.parentNode.AvqMgr;
    if (mgr == null) mgr = row.parentNode.parentNode.AvqMgr;
    if (mgr == null) return;
    if (mgr.SelectionStartRow == null) return;
    if (m_MgrWithSelectStart != null && m_MgrWithSelectStart != mgr) {
        return;
    }
    if (mgr.SelectSource != this.selectsource) return;
    mgr.ClearSelection ();
    if (! mgr.PageBinder.Enabled) return;
    mgr.SelectionEndRow = row;
    mgr.SelectionEndCol = this.cellIndex;
    if (this.singleselect) {
        mgr.SelectionStartRow = mgr.SelectionEndRow;
        mgr.SelectionStartCol = mgr.SelectionEndCol;
    }
    mgr.IndicateCellsToSelect (ctrlKeyPressed (event));
}

function AvqAction_TableEditMouseDown (event) {
    if (! event) event = window.event;
    
    var row = this.parentNode;
    if (row.tagName != 'TR') return;
    var mgr = row.parentNode.AvqMgr;
    if (mgr == null) mgr = row.parentNode.parentNode.AvqMgr;
    if (mgr == null) return;
    if (event.button != mgr.LeftButton) return;
    if (! mgr.PageBinder.Enabled) return;
    mgr.prev_rix_start = null;
    mgr.prev_rix_end = null;
    mgr.SelectionStartRow = row;
    mgr.SelectionEndRow = row;
    mgr.prev_cix_start = null;
    mgr.prev_cix_end = null;
    mgr.SelectionStartCol = this.cellIndex;
    mgr.SelectionEndCol = this.cellIndex;
    mgr.SelectSource = this.selectsource;
    mgr.CurrentPhase = null;
    mgr.IndicateCellsToSelect (ctrlKeyPressed (event));
    m_MgrWithSelectStart = mgr;
    Qva.addEvent(document,"mouseup",AvqAction_TableEditMouseUp);
    Qva.Select.Active = false;

}

function AvqAction_TableEditMouseUp (event) {
    if (! event) event = window.event;
    var mgr = m_MgrWithSelectStart;
//    
//    var row = this.parentNode;
//    if (row.tagName != 'TR') return;
//    var mgr = row.parentNode.AvqMgr;
//    if (mgr == null) mgr = row.parentNode.parentNode.AvqMgr;
    if (mgr == null) return;
//    if (event.button != mgr.LeftButton) return;
    if (mgr.SelectionStartRow == null) return;
//    if (m_MgrWithSelectStart != null && m_MgrWithSelectStart != mgr) {
//        return;
//    }
    mgr.ClearSelection ();
    if (! mgr.PageBinder.Enabled) return;
//    if (mgr.SelectionStartRow == null) {
//        mgr.SelectionStartRow = row;
//        mgr.SelectionStartCol = this.cellIndex;
//    }
//    if (mgr.SelectSource == this.selectsource) {
//        mgr.SelectionEndRow = row;
//        mgr.SelectionEndCol = this.cellIndex;
//    }
    mgr.SelectRows (ctrlKeyPressed (event));
    Qva.removeEvent(document,"mouseup",AvqAction_TableEditMouseUp);
    Qva.Select.Active = true;
    m_MgrWithSelectStart = null;
}

function TableHeaderDblClick (event) {
    if (! event) { event = window.event; }
    var row = this.parentNode;
    if (row.tagName != 'TR') return;
    var mgr = row.parentNode.AvqMgr;
    if (mgr == null) mgr = row.parentNode.parentNode.AvqMgr;
    if (mgr == null) return;
    this.pressed = false;
    var name = mgr.ColList [this.cellIndex].Name;
    if (mgr.PageBinder.Enabled) {
        mgr.PageBinder.Set (name, "click", name, true);
    } else {
        mgr.PageBinder.PendingDblClickName = name;
    }
}

function avq_action_md (event) {
    if (! event) event = window.event;
    event.cancelBubble = true;
    this.pressed = true;
}

function action_mu (elem) {
    if (! elem.pressed) return;
    elem.pressed = false;
    var action = elem.action;
    if (elem.targetname != null) {
        var binder = Qva.GetBinder (elem.binderid);
        var target = binder.DefaultScope + "." + elem.targetname;
        binder.Set (target, 'position', elem.xx + ":" + elem.yy, false);
        binder.Set (target + "." + action, "action", "", true);
    }
}

function avq_action_mu (event) {
    if (! event) event = window.event;
    if (! this.pressed) return;
    event.cancelBubble = true;
    var _this = this; 
    window.setTimeout (function() { action_mu (_this); }, 200);
}


Qva.ColMgr = { };
Qva.ColMgr.Init = function (parent, cix, cell, name, prefix) {
    this.IsLocal = false;
    this.Index = cix;
    if (cell != null) {
        this.ClassName = cell.className;
        this.Align = cell.align;
        this.Html = cell.innerHTML;
    }
    this.Parent = parent;
    this.CellHeight = -1;
    this.CellWidth = -1;
    Qva.MgrSplit (this, name, prefix)
}

Qva.ColMgr.basic = function (parent, cix, cell, name, prefix) {
    Qva.ColMgr.Init.apply(this, arguments);
    this.IsLocal = true;
}

Qva.ColMgr.basic.prototype.PaintCell = function (line, cell, rix) {
    cell.innerHTML = this.Html;
}

Qva.ColMgr.edit = function (parent, cix, cell, name, prefix) {
    Qva.ColMgr.Init.apply(this, arguments);
}

Qva.ColMgr.edit.prototype.PaintCell = function (line, cell, rix, ignorecolor) {
    cell.style.color = "";
    var cix = this.Index;
    cell.value = line [cix].intval;
    var text = "";
    if (this.Parent.AndMode) {
        if (line [cix].selected) {
            text = "&  ";
            cell.style.paddingLeft = "";
        } else if (line [cix].deselected) {
            text = "!  ";
            cell.style.paddingLeft = "";
        } else {
            cell.style.paddingLeft = "12px";
        }
    }
    text += (line [cix].val != '') ? line [cix].val : ' ';
    var StateClassName = this.Parent.GetSelectionStateClassName (line [cix].selected, ! line [cix].disabled && ! line [cix].locked, line [cix].disabled, line [cix].locked, line [cix].deselected);
    if (this.Parent.Semantic) {
        StateClassName += "_Semantic";
    } else if (this.Parent.AltClass) {
        StateClassName += "_" + this.Parent.AltClass;
    }
    var cellClassName = this.ClassName;
    if (StateClassName != '') cellClassName += " " + StateClassName;
    if (cell.className != cellClassName) cell.className = cellClassName;
    this.Parent.appendCellContent (cell, line [cix], text, cix, cell.value, this);
    cell.title = line [cix].title;
    if (line [cix].selecttype == null) {
        cell.onmousedown = Qva.NoAction;
        cell.onmousemove = Qva.NoAction;
    } else {
        cell.onmousedown = AvqAction_TableEditMouseDown;
        cell.onmousemove = AvqAction_TableEditMouseMove;
        if (line [cix].selecttype == "single") {
             cell.singleselect = true;
        }
        cell.onclick = Qva.CancelAction;
    }
    cell.style.cssText += this.Parent.SetCellStyle (line [cix], rix, cix, ignorecolor && this.Parent.ByValue);
}

Qva.ColMgr.text = function (parent, cix, cell, name, prefix) {
    Qva.ColMgr.Init.apply(this, arguments);
}

Qva.ColMgr.text.prototype.PaintCell = function (line, cell, rix, ignorecolor) {
    var cix = this.Index;
    
    if (line.IsHeader && line.IsHeader == true) {
        if (this.Parent.sortable && this.Parent.sortable == true) {
            cell.ondblclick = TableHeaderDblClick;
        }
    }
    var innertext = (line [cix].val != '') ? line [cix].val : ' ';
    var showstateclass = false;
    if (line [cix].byval) {
        var StateClassName = this.Parent.GetSelectionStateClassName (line [cix].selected, ! line [cix].disabled && ! line [cix].locked, line [cix].disabled, line [cix].locked, line [cix].deselected);
        var cellClassName = this.ClassName;
        if (StateClassName != '') cellClassName += " " + StateClassName;
        if (cell.className != cellClassName) cell.className = cellClassName;
        showstateclass = true;
        cell.style.color = "";
        cell.style.backgroundColor = "";
    }
    ignorecolor = (ignorecolor && this.Parent.ByValue) || showstateclass;
    cell.style.cssText += this.Parent.SetCellStyle (line [cix], rix, cix, ignorecolor);
    if (cell.className && cell.className != "" && ! showstateclass) cell.className = "";
    var ulr = line [cix].url;
    if (ulr) {
        cell.innerText = "";
        var link = document.createElement ("a");
        link.innerText = innertext;
        link.href = ulr;
        link.target = "_blank";
        cell.appendChild (link);
        cell.onclick = Qva.CancelAction;
        cell.onmousedown = Qva.CancelAction;
        cell.onmousemove = Qva.CancelAction;
        cell.style.cursor = "Default";
    } else {
        cell.style.cursor = "";
        if (line [cix].subcell) {
            cell.innerText = "";
        } else {
            cell.innerText = innertext;
        }
        cell.title = line [cix].title;
        if (line [cix].icons.length > 0 && ! line [cix].subcell) {
            this.Parent.appendCellContent (cell, line [cix], line [cix].val, cix, rix, this);
        }
        var selecttype = line [cix].selecttype;
        if (selecttype == null) {
            var action = line [cix].action;
            if (action) {
                cell.binderid = this.Parent.PageBinder.ID;
                cell.onmousedown = avq_action_md;
                cell.onmouseup = avq_action_mu;
                cell.pressed = false;
                cell.action = action;
                cell.targetname = this.Parent.Name;
                cell.xx = cix;
                cell.yy = rix;
                cell.onclick = Qva.CancelAction;
            } else {
                cell.onclick = Qva.NoAction;
                cell.onmousedown = Qva.NoAction;
                cell.onmousemove = Qva.NoAction;
            }
            cell.selectsource = null;
            cell.multiselect = null;
            cell.singleselect = null;
        } else if (selecttype == "input") {
            cell.innerText = "";
            var input = document.createElement ("input");
            input.value = innertext;
            var style = "border:none; height:"
            style += cell.clientHeight;
            style += "px; width:";
            style += cell.clientWidth;
            style += "px; ";
            if (this.Parent.Element.style.fontFamily) {
                style += "font-family:" + this.Parent.Element.style.fontFamily + "; ";
            }
            if (this.Parent.Element.style.fontSize) {
                style += "font-size:" + this.Parent.Element.style.fontSize + "; ";
            }
            input.style.cssText = style;
            input.onmousedown = Qva.CancelAction;
            input.onmouseup = Qva.CancelAction;
            input.onclick = Qva.CancelAction;
            new Qva.Mgr.inputtext (this.Parent.PageBinder, input, this.Parent.Name + ".V" + rix);
            cell.appendChild (input);
        } else {
            cell.onmousedown = AvqAction_TableEditMouseDown;
            cell.onmousemove = AvqAction_TableEditMouseMove;
//            cell.onmouseup = AvqAction_TableEditMouseUp;
            if (selecttype == "multi") {
                cell.multiselect = true;
            } else {
                cell.singleselect = true;
            }
            cell.selectsource = line [cix].selectsource;
        }
    }
}

Qva.ColMgr.check = function (parent, cix, cell, name, prefix) {
    Qva.ColMgr.Init.apply(this, arguments);
}
Qva.ColMgr.check.prototype.PaintCell = function (line, cell, rix) {
    var cix = this.Index;
    
    if (cell.firstChild == null || cell.firstChild.tagName != 'INPUT' || cell.firstChild.type != 'checkbox') {
        cell.innerHTML = '<input class="avqCheckbox" type=checkbox >';
    }
    cell.firstChild.onclick = AvqAction_TableCheck;
    if (this.Parent.ChoiceIx != -1) {
        var lix = rix + this.Parent.PageOffsetForPainting();
        var IsSelected = this.Parent.GetIndex(line) != 0;
        cell.firstChild.checked = IsSelected;
    } else {
        cell.firstChild.checked = line[cix].val != 0;
        cell.firstChild.disabled = line[cix].disabled;
    }
}

Qva.ColMgr.input = function (parent, cix, cell, name, prefix) {
    Qva.ColMgr.Init.apply(this, arguments);
}
Qva.ColMgr.input.prototype.PaintCell = function (line, cell, rix) {
    var cix = this.Index;
    
    if (cell.firstChild == null || cell.firstChild.tagName != 'INPUT' || cell.firstChild.type != 'text') {
        cell.innerHTML = '<input class="avqEdit" style="width:100%" value="" >';
        cell.firstChild.onchange = AvqAction_TableInput;
    }
    cell.firstChild.value = line[cix].val;
    cell.firstChild.disabled = line[cix].disabled;
}

Qva.ColMgr.windowsedit = function (parent, cix, cell, name, prefix) {
    Qva.ColMgr.Init.apply (this, arguments);
}

Qva.ColMgr.windowsedit.prototype.PaintCell = function (line, cell, rix, ignorecolor) {
    cell.style.color = "";
    var cix = this.Index;
    if (line [cix].intval == "-1") {
        cell.innerHTML = "";
        return;
    }
    cell.value = line [cix].intval;
    var text = ""
    if (this.Parent.AndMode) {
        if (line [cix].selected) {
            text = "&  ";
        } else if (line [cix].deselected) {
            text = "!  ";
        }
    }
    text += (line [cix].val != '') ? line [cix].val : ' ';

    var style = this.Parent.Style [line [cix].style];
    var textalignright = (line [cix].isnum ? style.NumAdjust : style.TextAdjust) == "right";
    var radio = line [cix].selecttype == "single";
    var input = null;
    for (var iElem = 0; iElem < cell.childNodes.length; iElem++) {
        if (cell.childNodes [iElem].tagName == "INPUT") {
            input = cell.childNodes [iElem];
        } else {
            cell.removeChild (cell.childNodes [iElem]);
        }
    }
    if (! input) {
        input = document.createElement ("INPUT");
        input.type = radio ? "radio" : "checkbox";
        cell.appendChild (input);
    }
    input.checked = line [cix].selected || line [cix].locked || line [cix].selectedexcluded;
    input.disabled = line [cix].disabled;

    if (textalignright) {
        var span = document.createElement ("span");
        span.innerText = text;
        span.style.position = "absolute";
        span.style.textAlign = "right";
        cell.appendChild  (span);
        var left = cell.offsetLeft - span.offsetWidth - 1;
        if (this.CellWidth != -1) {
            left += this.CellWidth;
        } else {
            left += cell.offsetWidth;
            debugger;
        }
        if (IS_GECKO || IS_OPERA) {
            left -= 3;
        }
        span.style.left = left + "px";
    } else {
        var textnode = document.createTextNode (text);
        cell.appendChild (textnode);
    }
    cell.windowsselectionstyle = true;
    if (this.Parent.Element.disabled || line [cix].locked) {
        cell.onmousedown = Qva.NoAction;
        cell.onmousemove = Qva.NoAction;
    } else {
        cell.onmousedown = AvqAction_TableEditMouseDown;
        cell.onmousemove = AvqAction_TableEditMouseMove;
    }
    if (line [cix].selecttype == "single") {
         cell.singleselect = true;
    }
    ignorecolor = ignorecolor && this.Parent.ByValue;
    var csstext = this.Parent.SetCellStyle (line [cix], rix, cix, ignorecolor);
    if (textalignright) csstext = csstext.replace ("right", "left"); 
    cell.style.cssText += csstext;
}

Qva.ColMgr.action = function (parent, cix, cell, name, prefix, action) {
    Qva.ColMgr.Init.apply(this, arguments);
    this.Action = action;
}
Qva.ColMgr.action.prototype.PaintCell = function (line, cell, rix, ignorecolor) {
    var cix = this.Index;
    if(!cell.firstChild || cell.firstChild.tagName != 'INPUT') {
        cell.innerHTML = '<input type="button" />';
    }
    var button = cell.firstChild;
    if(!button) { debugger; return; }
    button.innerText = (line[cix].val != '') ? line[cix].val : ' ';
    button.Action = this.Action;
    button.onclick = function(event) { eval(this.Action); };
    
    if (this.Parent.InlineStyle) {
        ignorecolor = ignorecolor && this.Parent.ByValue;
        cell.style.cssText += this.Parent.SetCellStyle (line [cix], rix, cix, ignorecolor);
        if (cell.className && cell.className != "") cell.className = "";
    }
}

function AvqAction_TableAction () {
    var box = this;
    var row = box.parentNode;
    if (row.tagName != 'TR') return;
    var mgr = row.parentNode.AvqMgr;
    if (mgr == null) mgr = row.parentNode.parentNode.AvqMgr;
    if (mgr == null) return;
    if (! mgr.PageBinder.Enabled) return;
    var selIx = row.rix;
    var colname = mgr.ColList[box.cellIndex].Name;
    mgr.PageBinder.Set (mgr.Group, 'cell', selIx + ':' + colname, true);
}

Qva.ColMgr.imgaction = function (parent, cix, cell, name, prefix, action) {
    Qva.ColMgr.Init.apply(this, arguments);
}
Qva.ColMgr.imgaction.prototype.PaintCell = function (line, cell, rix, ignorecolor) {
    cell.style.display = (line[this.Index].mode === "hidden") ? 'none' : '';
	cell.innerHTML = this.Html;
    cell.onclick = AvqAction_TableAction;
}

Qva.ColMgr.hidden = function (parent, cix, cell, name, prefix) {
    Qva.ColMgr.Init.apply(this, arguments);
}
Qva.ColMgr.hidden.prototype.PaintCell = function (line, cell, rix) {
    cell.style.display = "none";
    var cix = this.Index;
    cell.innerText = (line[cix].val != '') ? line[cix].val : ' ';
}

Qva.ColMgr.error = function (parent, cix, cell, name, prefix, action) {
    Qva.ColMgr.Init.apply(this, arguments);
    this.IsLocal = true;
}
Qva.ColMgr.error.prototype.PaintCell = function (line, cell, rix, ignorecolor) {
    var col = line[this.Index];
    var msg = col.val;
    cell.style.visibility = (msg && msg != '') ? 'visible' : 'hidden';
    cell.innerHTML = this.Html;
    cell.title = msg;
}

Qva.DragDrop = { };

Qva.DragDrop.mouseOffset = null;
Qva.DragDrop.DropTargets = [];
Qva.DragDrop.DropFrames  = [];
Qva.DragDrop.DropDefault = null;
Qva.DragDrop.curDrag     = null;
Qva.DragDrop.dragHelper  = null;
Qva.DragDrop.curDrop     = null;
Qva.DragDrop.dragType    = null;
Qva.DragDrop.DragStarted = null;

Qva.DragDrop.GetDropTarget = function (mousePos) {
    // check each drop container to see if our target object is "inside" the container
    for(var i = 0; i < Qva.DragDrop.DropTargets.length; ++i){
        var dropTarget = Qva.DragDrop.DropTargets[i].Inside(mousePos, Qva.DragDrop.curDrag.Type);
        if(dropTarget) return dropTarget;
    }
    if (Qva.Unicorn) {
        for (var i = 0; i < Qva.DragDrop.DropFrames.length; ++i) {
            var dropTarget = Qva.DragDrop.DropFrames[i].Inside(mousePos, Qva.DragDrop.curDrag.Type);
            if (dropTarget) return dropTarget;
        }
        if (Qva.DragDrop.DropDefault) {
            return Qva.DragDrop.DropDefault.Inside(mousePos, Qva.DragDrop.curDrag.Type);
        }
    }   
    return null;
}
Qva.DragDrop.Inside = function(cell, mousePos) {
    var cellPos    = Qva.GetPageCoords(cell);
    var cellWidth  = parseInt(cell.offsetWidth);
    var cellHeight = parseInt(cell.offsetHeight);
    return (mousePos.x > cellPos.x && mousePos.x < cellPos.x + cellWidth &&
        mousePos.y > cellPos.y && mousePos.y < cellPos.y + cellHeight);
}

Qva.DragDrop.mouseMove = function (event) {

    event = event || window.event;
    if (event.preventDefault) 
        event.preventDefault();
    else
        event.returnValue = false;
    if (!Qva.DragDrop.curDrag) debugger;

    var d = new Date();
    if (d.getTime() - Qva.MouseDownStartTime < 200) return
    
    var mousePos = { 'x': event.clientX ,
                     'y': event.clientY };
//    if (Qva.DragDrop.curDrag) {
        var target = Qva.DragDrop.dragElement;
        // if the user is just starting to drag the element
        if(!Qva.DragDrop.DragStarted){
            Qva.DragDrop.DragStarted = true;
            // We remove anything that is in our dragHelper DIV so we can put a new item in it.
            while (Qva.DragDrop.dragHelper.firstChild) Qva.DragDrop.dragHelper.removeChild(Qva.DragDrop.dragHelper.firstChild);
            
            // Make a copy of the current item and put it in our drag helper.
            if (Qva.DragDrop.dragType == "cell") {
                Qva.DragDrop.dragHelper.appendChild(target.cloneNode(true));
                Qva.DragDrop.dragHelper.className = "QvDragRect";
                Qva.DragDrop.dragHelper.style.display = 'block';
                // disable dragging from our helper DIV (it's already being dragged)
                Qva.DragDrop.dragHelper.firstChild.dragObj = null;
            } else {
                // Create a table to hold the table row
                var dragRow = target.cloneNode(true);
                // selected index is not cloned
                var arr = target.getElementsByTagName("select");
                if (arr.length>0) {
                    var arrClone = dragRow.getElementsByTagName("select");
                    for (var i = 0; i < arr.length; i++) {
                       arrClone[i].selectedIndex = arr[i].selectedIndex ;
                    }
                }
                // remove any cursor on span elements (otherwise pointer cursor during drag and no drop allowed)
                var arrSpan = dragRow.getElementsByTagName("span");
                for (var i = 0; i < arrSpan.length; i++) {
                   arrSpan[i].style.cursor = "inherit" ;
                }
                // Get colgroup from target
                var tableTarget = target;
                while (tableTarget && tableTarget.nodeName != "TABLE") tableTarget = tableTarget.parentNode;
                if (tableTarget) {
                    var colgroupTarget = tableTarget.firstChild;
                    while (colgroupTarget && colgroupTarget.nodeName != "COLGROUP") colgroupTarget = colgroupTarget.nextSibling;
                }
                var dragTbody = document.createElement('tbody');
                var dragTable = document.createElement('table');
                dragTable.style.width=parseInt(target.offsetWidth) + 'px';
                dragTable.style.height=parseInt(target.offsetHeight) + 'px';
                dragTable.style.tableLayout="fixed";
                dragTbody.appendChild(dragRow);
                if (colgroupTarget) dragTable.appendChild(colgroupTarget.cloneNode(true));
                dragTable.appendChild(dragTbody);
                Qva.DragDrop.dragHelper.appendChild(dragTable);
                Qva.DragDrop.dragHelper.className = "QvDragRect";
                Qva.DragDrop.dragHelper.style.display = 'block';
                Qva.DragDrop.dragHelper.style.fontFamily = 'arial';
                Qva.DragDrop.dragHelper.style.fontSize = '10pt';
            
                 // disable dragging from our helper DIV (it's already being dragged)
                dragRow.dragObj = null;
           }                         
            
        }
//    }
    
    var curDrop = null;
    
    // If we get in here we are dragging something
//    if(Qva.DragDrop.curDrag){
        // move our helper div to wherever the mouse is (adjusted by mouseOffset)
        Qva.DragDrop.dragHelper.style.top  = mousePos.y - Qva.DragDrop.mouseOffset.y + "px";
        Qva.DragDrop.dragHelper.style.left = mousePos.x - Qva.DragDrop.mouseOffset.x + "px";
      
        curDrop = Qva.DragDrop.GetDropTarget(mousePos);
//    }
    
    if(Qva.DragDrop.curDrop != curDrop) {
        if (Qva.DragDrop.curDrop && Qva.DragDrop.curDrop.Element) {
            for (var rowElement = Qva.DragDrop.curDrop.Element.firstChild; rowElement != null; rowElement = rowElement.nextSibling) {
                if (rowElement.nodeName=="TD") {
                    rowElement.className = "";
                    rowElement.style.backgroundImage = "";
                }
            }
        }
        Qva.DragDrop.curDrop = curDrop;
        if(Qva.DragDrop.curDrop) {
            Qva.DragDrop.dragHelper.style.cursor = "";
            var url = Qva.GetBinder(this.BinderId).BuildBinaryUrl (null, null, "dropinsert");
            if (Qva.DragDrop.curDrop.VerticalPosition == "insertafter")
                var className = "DropTarget-Bottom";
            else if (Qva.DragDrop.curDrop.VerticalPosition == "insertbefore")
                var className = "DropTarget-Top";
            else    
                var className = "DropTarget-Open";

            if (Qva.DragDrop.curDrop.Element) {
                for (var rowElement = Qva.DragDrop.curDrop.Element.firstChild; rowElement != null; rowElement = rowElement.nextSibling) {
                    if (rowElement.nodeName=="TD"){
                        rowElement.className = className;
                        rowElement.style.backgroundImage = "url(" + url + ")";
                    } 
                }
            }
        }
    }
    if (!Qva.DragDrop.curDrop && Qva.DragDrop.dragType == "row")
        Qva.DragDrop.dragHelper.style.cursor = "not-allowed";

    
    // this helps prevent items on the page from being highlighted while dragging
    return false;

}

Qva.DragDrop.mouseUp = function (event) {
    if(Qva.DragDrop.curDrag) {
        // hide our helper object - it is no longer needed
        Qva.DragDrop.dragHelper.style.display = 'none';
        if(Qva.DragDrop.curDrop) {
            // restore className in TD elements on drop row
            for (var rowElement = Qva.DragDrop.curDrop.Element.firstChild; rowElement != null; rowElement = rowElement.nextSibling) {
                if (rowElement.nodeName=="TD") {
                    rowElement.className = "";
                    rowElement.style.backgroundImage = "";
               }
            }
            var binder = Qva.GetBinder(Qva.DragDrop.curDrop.Element.BinderId);
            if (binder.Enabled) {
                var target = Qva.DragDrop.curDrop.Element;
                if (typeof (target) != 'string') target = target.Name;
                var verb = Qva.DragDrop.curDrop.VerticalPosition;
                if (!verb) {
                    verb = "dropat";
                    event = event || window.event;
                    var mousePos = { 'x': event.clientX, 'y': event.clientY };
                    var factor = Math.PI;
                    var atY = Math.round(factor * (mousePos.y - Qva.DragDrop.mouseOffset.y)) - 132;
                    var atX = Math.round(factor * (mousePos.x - Qva.DragDrop.mouseOffset.x));
                    target = atX + ':' + atY + ':' + target;
                }
                binder.Set(Qva.DragDrop.curDrag.Name, verb, target, true);
            }
        } else if (Qva.DragDrop.curDrag.DropAt) {
            event = event || window.event;
            var mousePos = { 'x': event.clientX, 'y': event.clientY};
            if (!Qva.DragDrop.Inside(Qva.DragDrop.dragElement, mousePos)) {
                var factor = Math.PI;
                var atY = Math.round(factor * (mousePos.y - Qva.DragDrop.mouseOffset.y)) - 132;
                var atX = Math.round(factor * (mousePos.x - Qva.DragDrop.mouseOffset.x));
                var binder = Qva.GetBinder(Qva.DragDrop.curDrag.BinderId);
                if (binder.Enabled)
                    binder.Set (Qva.DragDrop.curDrag.Name, "dropat", atX + ':' + atY + ':' + Qva.DragDrop.curDrag.Value, true);
            }
        }
    } else if(Qva.DragDrop.curDrop) {
        debugger;
    }
    
    Qva.DragDrop.curDrop     = null;
    Qva.DragDrop.curDrag    = null;
    Qva.DragDrop.DragStarted = null;
    
    Qva.removeEvent(document,"mousemove",Qva.DragDrop.mouseMove);
    Qva.removeEvent(document,"mouseup",Qva.DragDrop.mouseUp);
    Qva.Select.Active = true;
}

Qva.DragDrop.mouseDown = function (event) {
    event = event || window.event;
    if (event.preventDefault) 
        event.preventDefault();
    else
        event.returnValue = false;
   /*
    We are setting target to whatever item the mouse is currently on
    Firefox uses event.target here, MSIE uses event.srcElement
    */
    var target   = event.target || event.srcElement;
    var dragObj = target.dragObj
    if (dragObj) {
        Qva.DragDrop.dragType = "cell";
        Qva.DragDrop.dragElement = target;
     } else {
            while (target && target.nodeName != "TR") target=target.parentNode;
            if (target) {
                var dragObj = target.dragObj;
                if (dragObj) {
                    Qva.DragDrop.dragType = "row";
                    Qva.DragDrop.dragElement = target;
                }
            }
    }
    Qva.DragDrop.curDrag = dragObj;
    Qva.DragDrop.DragStarted = null;
    if (dragObj) {
        var mousePos = {'x': event.clientX ,
                        'y': event.clientY };
        var rowPos = Qva.GetPageCoords(target);
        Qva.DragDrop.mouseOffset = {'x': mousePos.x - Qva.GetScrollLeft()- rowPos.x, 
                                    'y': mousePos.y - Qva.GetScrollTop()- rowPos.y };
        Qva.Select.Active = false;
        Qva.addEvent(document,"mousemove",Qva.DragDrop.mouseMove);
        Qva.addEvent(document,"mouseup",Qva.DragDrop.mouseUp);
        var d = new Date();
        Qva.MouseDownStartTime = d.getTime();

    }

    //prevents text selections in Firefox
    return false;
}

Qva.DragDrop.Init = function(){
	// Create our helper object that will show the item while dragging
	Qva.DragDrop.dragHelper = document.createElement('DIV');
	Qva.DragDrop.dragHelper.style.cssText = 'position:absolute; display:none;';
	Qva.DragDrop.dragHelper.style.zIndex  = 666;
	document.body.appendChild(Qva.DragDrop.dragHelper);
	
}
var old_QvaStart = Qva.Start;
Qva.Start = function() {
    old_QvaStart();
    Qva.DragDrop.Init();
}
Qva.Select = { };
Qva.Select.Active = true;
Qva.Select.mouseDown = function (event) {
    if (!Qva.Select.Active) return;
    
    event = event || window.event;
    var target   = event.target || event.srcElement;
    var cancel = target.disabled || (target.nodeName!="INPUT" && target.nodeName!="SELECT" && target.nodeName!="TEXTAREA");
    if (cancel) {
        if (event.preventDefault) 
            event.preventDefault();
        else
            event.returnValue = false;
        Qva.addEvent(document,"mousemove",Qva.Select.mouseMove);
        Qva.addEvent(document,"mouseup",Qva.Select.mouseUp);
        return false;
    }

}
Qva.Select.mouseMove = function (event) {
    event = event || window.event;
    if (event.preventDefault) 
        event.preventDefault();
    else
        event.returnValue = false;
    return false;
}
Qva.Select.mouseUp = function (event) {
    Qva.removeEvent(document,"mousemove",Qva.Select.mouseMove);
    Qva.removeEvent(document,"mouseup",Qva.Select.mouseUp);
}

document.onmousedown = Qva.Select.mouseDown

Qva.Move = { };
Qva.Move.mouseDown = function (event) {
    if (! event) event = window.event;
    var target   = event.target || event.srcElement;
    var cancel = target.disabled || (target.nodeName!="INPUT" && target.nodeName!="SELECT");
    if (cancel) {
        if (event.preventDefault) 
            event.preventDefault();
        else
            event.returnValue = false;
        if (!target.moveObj) while (!target.moveObj) target=target.parentNode;

        if (target.moveObj) {
            Qva.Move.old_cursor = document.body.style.cursor;
            document.body.style.cursor = "move";
            Qva.Move.moveElement = target;
            Qva.Move.MoveStarted = null;
            Qva.Move.StartX = event.clientX + Qva.GetScrollLeft();
            Qva.Move.StartY = event.clientY + Qva.GetScrollTop();

            Qva.Select.Active = false;
            Qva.addEvent(document,"mousemove",Qva.Move.mouseMove);
            Qva.addEvent(document,"mouseup",Qva.Move.mouseUp);
             var d = new Date();
            Qva.MouseDownStartTime = d.getTime();
            Qva.MouseDown2 = true;
           
        }
        //prevents text selections in Firefox
        return false;
    }
}
Qva.Move.mouseMove = function(event) {
    if (!Qva.MouseDown2) return;

    if (!Qva.Move.moveElement) debugger;
    if (! event) {
        event = window.event;
        event.returnValue = false;
    } else event.preventDefault ();
    var d = new Date();
    if (d.getTime() - Qva.MouseDownStartTime < 200) return

    if (!Qva.Move.MoveStarted) {
        // init move
        Qva.Move.MoveStarted = true;
         //get elements to move
        var arr = Qva.Move.moveElement.moveObj.split(":");
        Qva.Move.curMove = [];
        for (var i = 0; i < arr.length; i++) { 
            var element = (arr[i] != '*') ? document.getElementById(arr[i]) : Qva.Move.moveElement;
           
            Qva.Move.curMove[i] = { 'Element'       : element,
                                    'StartLeft'     : element.offsetLeft,
                                    'StartTop'      : element.offsetTop,
                                    'ClassName'     : element.className};
            element.className += " QvMoveRect";
            element.style.zIndex = 666;
       }
       
    }
    var deltaX = event.clientX + Qva.GetScrollLeft() - Qva.Move.StartX;
    var deltaY = event.clientY + Qva.GetScrollTop() - Qva.Move.StartY;
    for (var i = 0; i < Qva.Move.curMove.length; i++) {
        var newX = Qva.Move.curMove[i].StartLeft + deltaX;
        if (!isNaN(Qva.Move.moveElement.xMax)) newX = Math.min(newX, Qva.Move.moveElement.xMax);
        if (!isNaN(Qva.Move.moveElement.xMin)) newX = Math.max(newX, Qva.Move.moveElement.xMin);
        if (!Qva.Move.moveElement.xOnly) Qva.Move.curMove[i].Element.style.top = Qva.Move.curMove[i].StartTop + deltaY + "px";
        Qva.Move.curMove[i].Element.style.left = newX + "px";
    }
    return false
}

Qva.Move.mouseUp = function (event) {
    event = event || window.event;
    
    Qva.MouseDown2 = false;
    if (Qva.Move.MoveStarted) {
        var deltaX = event.clientX + Qva.GetScrollLeft() - Qva.Move.StartX;
        var deltaY = event.clientY + Qva.GetScrollTop() - Qva.Move.StartY;
        
        var y = Qva.Move.curMove[0].StartTop + deltaY;
        var x = Qva.Move.curMove[0].StartLeft + deltaX;
        
        for (var i = 0; i < Qva.Move.curMove.length; i++) {
            Qva.Move.curMove[i].Element.className = Qva.Move.curMove[i].ClassName;
        }

        var binder = Qva.GetBinder(Qva.Move.moveElement.binderid);
        if (Qva.Move.moveElement.xOnly) {
            binder.Set (Qva.Move.moveElement.Name, "value", x * 2, true);
        } else {
            binder.Set (Qva.Move.moveElement.Name, "moveto", Math.round(x * Qva.Factor) + ':' + Math.round(y * Qva.Factor), true);
        }
      
        Qva.Move.curMove = null;
        Qva.Move.moveElement = null;
        Qva.Move.MoveStarted = null;
      
    }
    document.body.style.cursor = Qva.Move.old_cursor;
    Qva.removeEvent(document,"mousemove",Qva.Move.mouseMove);
    Qva.removeEvent(document,"mouseup",Qva.Move.mouseUp);
    Qva.Select.Active = true;

}
Qva.Resize = {}

Qva.Resize.mouseDown = function (event, frame) {
    if (! event) {
        event = window.event;
        event.returnValue = false;
    } else event.preventDefault ();
    event.cancelBubble = true;
    
    var target = event.target || event.srcElement;
    var at = Qva.GetPageCoords (frame);
    Qva.Resize.ResizeType = target.ResizeType;
    Qva.Resize.Frame = frame;
    var bkgid = frame.id.replace ("_frame", "_bkg");
    var bkgelem = window.document.getElementById (bkgid);
    if (bkgelem) {
        Qva.Resize.BkgElem = bkgelem;
    }
    Qva.Resize.StartX = event.clientX + Qva.GetScrollLeft();
    Qva.Resize.StartY = event.clientY + Qva.GetScrollTop();
    Qva.Resize.StartLeft = Qva.GetScrollLeft() + at.x - 1;
    Qva.Resize.StartTop = Qva.GetScrollTop() + at.y - 1;
    
    Qva.Resize.StartH = getClientHeight(frame);
    Qva.Resize.StartW = getClientWidth(frame);
    if (!Qva.Resize.SizeRect) {
        Qva.Resize.SizeRect = document.createElement ("div");
        Qva.Resize.SizeRect.className = "QvSizeRect";
        Qva.Resize.SizeRect.style.display = '';
        document.body.insertBefore (Qva.Resize.SizeRect, document.body.firstChild);
    } else {
        Qva.Resize.SizeRect.style.display = '';
    }
    Qva.Resize.SizeRect.style.left = this.StartLeft + "px";
    Qva.Resize.SizeRect.style.top = this.StartTop + "px";
    Qva.Resize.SizeRect.style.width = this.StartW + "px";
    Qva.Resize.SizeRect.style.height = this.StartH + "px";
    Qva.Resize.SizeRect.X = null;
    Qva.Resize.SizeRect.Y = null;
    Qva.Resize.SizeRect.W = null;
    Qva.Resize.SizeRect.H = null;
    
    Qva.Resize.old_cursor = document.body.style.cursor;
    document.body.style.cursor = target.style.cursor;
    Qva.Select.Active = false;
    Qva.addEvent(document,"mousemove",Qva.Resize.mouseMove);
    Qva.addEvent(document,"mouseup",Qva.Resize.mouseUp);
}
Qva.Resize.mouseMove = function (event) {

    var minsize = 20;
    if (!Qva.Resize.SizeRect) return;
    if (! event) {
        event = window.event;
        event.returnValue = false;
    } else event.preventDefault ();

    var deltaX = event.clientX + Qva.GetScrollLeft() - Qva.Resize.StartX;
    var deltaY = event.clientY + Qva.GetScrollTop() - Qva.Resize.StartY;
    // change top
    if (Qva.Resize.ResizeType.indexOf("t")!=-1) {
        Qva.Resize.SizeRect.Y = Math.max(minsize, Qva.Resize.StartTop + deltaY);
        Qva.Resize.SizeRect.H = Math.max(minsize, Qva.Resize.StartH - deltaY);
    }
    // change bottom
    if (Qva.Resize.ResizeType.indexOf("b")!=-1) {
        Qva.Resize.SizeRect.H = Math.max(minsize, Qva.Resize.StartH + deltaY);
    }
    // change left
    if (Qva.Resize.ResizeType.indexOf("l")!=-1) {
        Qva.Resize.SizeRect.X = Math.max(minsize, Qva.Resize.StartLeft + deltaX);
        Qva.Resize.SizeRect.W = Math.max(minsize, Qva.Resize.StartW - deltaX);
    }
    // change right
    if (Qva.Resize.ResizeType.indexOf("r")!=-1) {
        Qva.Resize.SizeRect.W = Math.max(minsize, Qva.Resize.StartW + deltaX);
    }

    if (Qva.Resize.SizeRect.Y) Qva.Resize.SizeRect.style.top = Qva.Resize.SizeRect.Y + "px";
    if (Qva.Resize.SizeRect.X) Qva.Resize.SizeRect.style.left = Qva.Resize.SizeRect.X + "px";
    if (Qva.Resize.SizeRect.W) Qva.Resize.SizeRect.style.width = Qva.Resize.SizeRect.W + "px";
    if (Qva.Resize.SizeRect.H) Qva.Resize.SizeRect.style.height = Qva.Resize.SizeRect.H + "px";

}

Qva.Resize.mouseUp = function (event) {
    document.body.style.cursor = Qva.Resize.old_cursor;
    var style = Qva.Resize.ResizeType;
    var width = Math.round((Qva.Resize.SizeRect.W ? Qva.Resize.SizeRect.W : Qva.Resize.StartW) * Qva.Factor);
    var height = Math.round((Qva.Resize.SizeRect.H ? Qva.Resize.SizeRect.H : Qva.Resize.StartH) * Qva.Factor);
    if (Qva.Resize.Frame.maxclientwidth) Qva.Resize.Frame.maxclientwidth = null;
    if (Qva.Resize.Frame.maxclientheight) Qva.Resize.Frame.maxclientheight = null;
    Qva.GetBinder(Qva.Resize.Frame.binderid).Set (Qva.Resize.Frame.Name + ".Caption", "resize", style + ':' + width + ':' + height, true);
    Qva.Resize.SizeRect.style.display = 'none';
    Qva.Resize.Frame = null;
    Qva.removeEvent(document,"mousemove",Qva.Resize.mouseMove);
    Qva.removeEvent(document,"mouseup",Qva.Resize.mouseUp);
    Qva.Select.Active = true;
}


// Build 9.00.7440.8

Qva.Scanner = function (binder, ns) {
    this.DefaultBinder = binder;
    this.Errors = new Array ();
    if (ns) {
        this.NameSpace = ns;
        this.Prefix = ns + ':';
        this.Attr = ns + ':bind';
    } else {
        this.NameSpace = 'avq';
        this.Prefix = 'avq';
        this.Attr = 'avq';
    }
    this.ModeIfNotEnabled = 'n'; // Use "true" non-enabled mode
    Qva.Scanner.instance = this;
}

Qva.Scanner.prototype.Start = function () {
    var binder = this.DefaultBinder || Qva.GetBinder();
    var scope = (binder && (binder.Autoview != null || binder.Kind != null)) ? binder.DefaultScope : null;
    
    //if (?.Benchmark != null) ?.Benchmark.Scan.Start();
    this.Scan(document.body, scope, binder)
    //if (?.Benchmark != null) ?.Benchmark.Scan.Stop();
    
    if (this.Errors.length > 0) {
        var msg = 'Errors:\n' + this.Errors.join ('\n');
        this.Errors.length = 0;
        alert(msg);
    }
}

Qva.Scanner.prototype.Scan = function (elem, parPrefix, binder) {
    if(!elem.getAttribute) return;
    var doc = elem.getAttribute (this.Prefix + 'doc');
    if(doc != null) {
        doc = doc.split(':');
        binder = Qva.GetBinder(doc[0], doc[1]);
        parPrefix = (binder.Autoview != null || binder.Kind != null) ? binder.DefaultScope : null;
    }
    var view = elem.getAttribute (this.Prefix + 'view');
    if(view != null) {
        binder = Qva.GetBinder(view, view);
        parPrefix = (binder.Autoview != null || binder.Kind != null) ? binder.DefaultScope : null;
    }
    
    var prefix = elem.getAttribute (this.Prefix + 'scope');
    if (prefix == null) {
        prefix = parPrefix;
    } else if (prefix.substr(0,1) == '.') {
        prefix = parPrefix + prefix;
    }
    
    var avqatt = elem.getAttribute (this.Attr);
    if (avqatt != null) {
        if (avqatt.indexOf (':') == -1 && avqatt.indexOf ('.') >= 0) {
            avqatt = 'edit:' + avqatt;
        }
        var parts = avqatt.split (':');
        var mgrtype = parts [0].toLowerCase();
        if (mgrtype == 'edit') {
            var alttype = elem.tagName.toLowerCase();
            if (alttype == 'input') alttype += elem.type.toLowerCase();
            if (Qva.Mgr[alttype]) { 
                mgrtype = alttype; 
            } else if (alttype != "span") {
//                alert(alttype); 
            }
        }
        if (Qva.Mgr[mgrtype]) {
            var name = (parts.length > 1) ? parts[1] : null;
            var condition = (parts.length > 2) ? parts.slice(2).join (':') : null;
            var mgr = new Qva.Mgr[mgrtype] (binder, elem, name, prefix, condition);
            if (mgr.Name != null) {
                this.PostManager(mgr);
            } else {
                this.Errors [this.Errors.length] = 'Invalid ' + this.NameSpace + '-attribute: ' + avqatt;
            }
        } else {
            this.Errors [this.Errors.length] = 'Unknown type: ' + mgrtype;
        }
    }
    
    var len = elem.childNodes.length;
    for (var ix = 0; ix < len; ++ix) {
        this.Scan(elem.childNodes[ix], prefix, binder);
    }
}

Qva.Scanner.prototype.PostManager = function (mgr) {
    var elem = mgr.Element;
    mgr.SelectedClassName = elem.getAttribute ('AvqSelected');
    if (mgr.SelectedClassName == null) {
        mgr.SelectedClassName = 'AvqSelected';
    }
    mgr.DeselectedClassName = elem.getAttribute ('AvqDeselected');
    if (mgr.DeselectedClassName == null) {
        mgr.DeselectedClassName = 'AvqDeselected';
    }
    mgr.EnabledClassName = elem.getAttribute ('AvqEnabled');
    if (mgr.EnabledClassName == null) {
        mgr.EnabledClassName = 'AvqEnabled';
    }
    mgr.DisabledClassName = elem.getAttribute ('AvqDisabled');
    if (mgr.DisabledClassName == null) {
        mgr.DisabledClassName = 'AvqDisabled';
    }
    mgr.LockedClassName = elem.getAttribute ('AvqLocked');
    if (mgr.LockedClassName == null) {
        mgr.LockedClassName = 'AvqLocked';
    }
    mgr.TextIfNull = mgr.Element.getAttribute (this.Prefix + 'textifnull');
    mgr.Icon = mgr.Element.getAttribute (this.Prefix + 'icon');
    mgr.ModeIfNotEnabled = this.ModeIfNotEnabled;
    var ifNotEnabled = mgr.Element.getAttribute (this.Prefix + 'ifnotenabled');
    if (ifNotEnabled != null) {
        switch (ifNotEnabled) {
        case "disabled":
            mgr.ModeIfNotEnabled = 'd';
            break;
        case "hidden":
            mgr.ModeIfNotEnabled = 'h';
            break;
        default:
            this.Errors [this.Errors.length] = 'IfNotEnabled is not implemented for ' + ifNotEnabled;
            break;
        }
    }
    var HideIf = mgr.Element.getAttribute (this.Prefix + 'hideif');
    if (HideIf) {
        mgr.HideIf = new Function("value", "text", "return " + HideIf);
    }
    if (mgr.PostScan) mgr.PostScan(this);
}



// Build 9.00.7440.8

Qva.Modal = function(scriptPath) {
    if(typeof scriptPath !== 'string') scriptPath = null;
    this.ScriptPath = scriptPath || '/QvAJAXZfc/htc/';
    this.HideSelects = false;
    this.DefaultPage = "modal/loading.html";
    this.TabIndexes = [];
    this.TabbableTags = ["A","BUTTON","TEXTAREA","INPUT","IFRAME"];
    this.PopupIsShown = false;
    Qva.Modal.instance = this;
}

Qva.Modal.prototype.Show = function(pagebinder, url, width, height) {
    this.PageBinder = pagebinder;
    this.Init();
    document.getElementById("popCloseBox").style.display = "block";
    this.PopupIsShown = true;
    this.DisableTabs();
    this.PopupMask.style.display = "block";
    this.PopupContainer.style.display = "block";
    
    if(width && height) this.SetSize(width, height);
    
    if(pagebinder.Session) {
        // transfer session
        url += ((url.indexOf ('?') == -1) ? '?' : '&') + 'session=' + escape (pagebinder.Session);
    }
    // transfer ticket
    if(pagebinder.Ticket) url = Qva.FixUrl(url, "ticket", pagebinder.Ticket);
    // transfer host
    if (pagebinder.Host) url = Qva.FixUrl(url, "host", pagebinder.Host);
    if (pagebinder.Unicorn) url = Qva.FixUrl(url, "unicorn", "3");
    
    if (Qva.Benchmark) {
        this.Benchmark = new Qva.Benchmark();
    }
    
    // set the url
    this.PopFrame.src = url;
    
    // for IE
    if (this.HideSelects == true) {
        this.HideSelectBoxes();
    }
}

Qva.Modal.prototype.SetSize = function(width, height) {
    // calculate where to place the window on screen
    this.CenterWin(width, height);
    
    var titleBarHeight = parseInt(document.getElementById("popupTitleBar").offsetHeight, 10);
    
    this.PopupContainer.style.width = width + "px";
    this.PopupContainer.style.height = (height+titleBarHeight) + "px";
    
    this.SetMaskSize();
    
    // need to set the width of the iframe to the title bar width because of the dropshadow
    // some oddness was occuring and causing the frame to poke outside the border in IE6
    this.PopFrame.style.width = parseInt(document.getElementById("popupTitleBar").offsetWidth, 10) + "px";
    this.PopFrame.style.height = (height) + "px";
}

Qva.Modal.prototype.Init = function() {
    if (this.PopupMask != null) return;
    // Add the HTML to the body
    
    theBody = document.getElementsByTagName('BODY')[0];
    popmask = document.createElement('div');
    popmask.id = 'popupMask';
    popmask.style.position = 'absolute';
    popcont = document.createElement('div');
    popcont.id = 'popupContainer';
    popcont.style.position = 'absolute';
    popcont.innerHTML = '' +
        '<div id="popupInner">' +
            '<div id="popupTitleBar">' +
                '<div id="popupTitle" style="width:90%"></div>' +
                '<div id="popupControls" style="width:15px">' +
                    '<img src="' + this.ScriptPath + 'modal/close.gif" onclick="Qva.Modal.instance.Close();" id="popCloseBox" />' +
                '</div>' +
            '</div>' +
            '<iframe src="'+ this.ScriptPath + this.DefaultPage +'" style="width:100%;height:100%;background-color:transparent;" scrolling="auto" frameborder="0" allowtransparency="true" id="popupFrame" name="popupFrame" width="100%" height="100%"></iframe>' +
        '</div>';
    theBody.appendChild(popmask);
    theBody.appendChild(popcont);
    
    this.PopupCloseBox = document.getElementById("popCloseBox");
    this.PopupMask = document.getElementById("popupMask");
    var popupContainer = this.PopupContainer = document.getElementById("popupContainer");
    this.PopFrame = document.getElementById("popupFrame");
    
    var popupTitleBar = document.getElementById("popupTitleBar");
    popupTitleBar.onmousedown = function (event) {
        if (!event) event = window.event;
        
        var offsets = Qva.GetOffsets(event, popupContainer);
        
        function EndMove(event) {
            popupTitleBar.onmousemove = null;
            popupTitleBar.onmouseup   = null;
            popupTitleBar.onmouseout  = null;
            return false;
        }
        function MouseMove(event) {
            if (!event) event = window.event;
            var mousePos = { 'x': event.clientX + Qva.GetScrollLeft(),
                             'y': event.clientY + Qva.GetScrollTop() };
            popupContainer.style.left = (mousePos.x - offsets.offsetX) + "px";
            popupContainer.style.top  = (mousePos.y - offsets.offsetY) + "px";
            return false;
        }
        popupTitleBar.onmousemove = MouseMove;
        popupTitleBar.onmouseup   = EndMove;
        popupTitleBar.onmouseout  = EndMove;
        return false;
    };
    
    
    // check to see if this is IE version 6 or lower. hide select boxes if so
    // maybe they'll fix this in version 7?
    var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10);
    if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE") > -1) {
        this.HideSelects = true;
    }
}

// For IE.  Go through predefined tags and disable tabbing into them.
Qva.Modal.prototype.DisableTabs = function() {
    if (document.all) {
        var i = 0;
        for (var j = 0; j < this.TabbableTags.length; j++) {
            var tagElements = document.getElementsByTagName(this.TabbableTags[j]);
            for (var k = 0 ; k < tagElements.length; k++) {
                this.TabIndexes[i] = tagElements[k].tabIndex;
                tagElements[k].tabIndex="-1";
                i++;
            }
        }
    }
}

// For IE. Restore tab-indexes.
Qva.Modal.prototype.RestoreTabs = function() {
    if (document.all) {
        var i = 0;
        for (var j = 0; j < this.TabbableTags.length; j++) {
            var tagElements = document.getElementsByTagName(this.TabbableTags[j]);
            for (var k = 0 ; k < tagElements.length; k++) {
                tagElements[k].tabIndex = this.TabIndexes[i];
                tagElements[k].tabEnabled = true;
                i++;
            }
        }
    }
}

Qva.Modal.prototype.CenterWin = function(width, height) {
    if (this.PopupIsShown) {
        if (width == null || isNaN(width)) {
            width = this.PopupContainer.offsetWidth;
        }
        if (height == null) {
            height = this.PopupContainer.offsetHeight;
        }
        
        var theBody = document.getElementsByTagName("BODY")[0];
        var scTop = parseInt(Qva.GetScrollTop(),10);
        var scLeft = parseInt(theBody.scrollLeft,10);
        
        this.SetMaskSize();
        
        var titleBarHeight = parseInt(document.getElementById("popupTitleBar").offsetHeight, 10);
        
        var fullHeight = Qva.GetViewportHeight();
        var fullWidth = Qva.GetViewportWidth();
        
        this.PopupContainer.style.top = (scTop + ((fullHeight - (height+titleBarHeight)) / 2)) + "px";
        this.PopupContainer.style.left =  (scLeft + ((fullWidth - width) / 2)) + "px";
    }
}

Qva.Modal.prototype.SetMaskSize = function() {
    var theBody = document.getElementsByTagName("BODY")[0];
    
    var fullHeight = Qva.GetViewportHeight();
    var fullWidth = Qva.GetViewportWidth();
    
    // Determine what's bigger, scrollHeight or fullHeight / width
    if (fullHeight > theBody.scrollHeight) {
        popHeight = fullHeight;
    } else {
        popHeight = theBody.scrollHeight;
    }
    
    if (fullWidth > theBody.scrollWidth) {
        popWidth = fullWidth;
    } else {
        popWidth = theBody.scrollWidth;
    }
    
    this.PopupMask.style.height = popHeight + "px";
    this.PopupMask.style.width = popWidth + "px";
}

Qva.Modal.prototype.HideSelectBoxes = function() {
    for(var i = 0; i < document.forms.length; i++) {
        for(var e = 0; e < document.forms[i].length; e++){
            if(document.forms[i].elements[e].tagName == "SELECT") {
                document.forms[i].elements[e].style.visibility="hidden";
            }
        }
    }
}

Qva.Modal.prototype.DisplaySelectBoxes = function() {
    for(var i = 0; i < document.forms.length; i++) {
        for(var e = 0; e < document.forms[i].length; e++){
            if(document.forms[i].elements[e].tagName == "SELECT") {
            document.forms[i].elements[e].style.visibility="visible";
            }
        }
    }
}

Qva.Modal.prototype.Hide = function () {
    this.PopupIsShown = false;
    var theBody = document.getElementsByTagName("BODY")[0];
    theBody.style.overflow = "";
    this.RestoreTabs();
    if (this.PopupMask == null) {
        return;
    }
    this.PopupMask.style.display = "none";
    this.PopupContainer.style.display = "none";
    this.PopFrame.src = this.ScriptPath + this.DefaultPage;
    // display all select boxes
    if (this.HideSelects == true) {
        this.DisplaySelectBoxes();
    }
}

Qva.Modal.prototype.SetTitle = function (text) {
    try {
        document.getElementById("popupTitle").innerText = text;
    } catch(e) {
    }
}

Qva.Modal.prototype.Close = function () {
    this.Hide();
    if (this.PageBinder) {
        if (this.PageBinder.LabelClick) {
            this.PageBinder.Set('.Nothing', 'add', 'nothing', true);
        } else {
            this.PageBinder.Refresh();
        }
    }
}




// VML
var Graphics = {
    'VML': {
        'CreateElement': function (type, parent) {
            var elem = document.createElement("v:" + type);
            elem.unselectable = "on";
            if(parent) parent.appendChild(elem);
            return elem;
        },
        'CreateShape': function (path, coordsize, color, parent) {
            var s = Graphics.VML.CreateElement("shape", parent);
            s.coordsize = coordsize;
            if(color) s.fillcolor = color;
            s.path = path;
            return s;
        },
        'CreateArea': function (size, parent) {
            var area = Graphics.VML.CreateElement("group", parent);
            area.style.width = size[0] + "px";
            area.style.height = size[1] + "px";
            area.coordsize = size.join(",");
            area.style.position = "absolute";
            return area;
        },
        'CreatePolygonObj': function (points, color, parent, pos, size) {
            var path = "m " + points[0][0] + "," + points[0][1] + " l";
            for(var i = 1; i < points.length; ++i) {
                path += " " + points[i][0] + " " + points[i][1];
            }
            path += " x e";
            var polygon = Graphics.VML.CreateShape(path, size.join(","), color, parent);
            polygon.style.width = size[0] + "px";
            polygon.style.height = size[1] + "px";
            polygon.style.position = "absolute";
            polygon.style.left = pos[0] + "px";
            polygon.style.top = pos[1] + "px";
            return polygon;
        },
        'CreatePolygon': function (points, color, parent) {
            return Graphics.VML.CreatePolygonObj(points, color, parent, [0,0], [parent.style.pixelWidth, parent.style.pixelHeight])
        },
        'CreateLine': function (from, to, color, parent, width) {
            var l = Graphics.VML.CreateElement("line", parent);
            l.from = from.join(",");
            l.to = to.join(",");
            if(color) l.strokecolor = color;
            if(width) l.strokeweight = width;
            return l;
        },
        'CreatePolyLine': function (points, color, parent, width) {
            var l = Graphics.VML.CreateElement("polyline", parent);
            l.points = points.join(" ");
            if(color) l.strokecolor = color;
            
            var f = Graphics.VML.CreateElement("fill");
            f.on = "false";
            l.appendChild(f);
            
            if(width) l.strokeweight = width;
            return l;
        },
        'CreateRect': function (pos, size, color, parent, border) {
            var r = Graphics.VML.CreateElement("rect", parent);
            r.fillcolor = color;
            r.style.left   = pos[0] + "px";
            r.style.top    = pos[1] + "px";
            r.style.width  = size[0] + "px";
            r.style.height = size[1] + "px";
            if(!border) Graphics.VML.CreateElement("stroke", r).on = "false";
            return r;
        },
        'FixPolygon': function (polygon, points, size, color) {
            var path = "m " + points[0][0] + "," + points[0][1] + " l";
            for(var i = 1; i < points.length; ++i) {
                path += " " + points[i][0] + " " + points[i][1];
            }
            path += " x e";
            polygon.path = path;

            polygon.coordsize = size.join(",");
            polygon.style.width = size[0] + "px";
            polygon.style.height = size[1] + "px";
        },
        'Init': function () {
            // create xmlns
            if(IE_VERSION >= 8) {
                if (!document.namespaces["v"]) document.namespaces.add("v", "urn:schemas-microsoft-com:vml", "#default#VML");
            } else {
                if (!document.namespaces["v"]) document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
            }
            // setup default css
            if(!Graphics.VML.styleSheet) {
                Graphics.VML.styleSheet = document.createStyleSheet()
                Graphics.VML.styleSheet.cssText = "v\\:*{behavior:url(#default#VML);display: inline-block;}";
            }
        },
        'styleSheet': null
    },

    'Canvas': {
        'CreateArea': function (size, parent) {
            var area = document.createElement("canvas");
            area.style.width = size[0] + "px";
            area.style.height = size[1] + "px";
            area.width = size[0];
            area.height = size[1];
            if(parent) parent.appendChild(area);
            return area;
        },
        'CreatePolygonObj': function (points, color, parent, pos, size) {
            var area = Graphics.Canvas.CreateArea(size, parent);
            area.style.position = "absolute";
            area.style.left = pos[0] + "px";
            area.style.top = pos[1] + "px";
            Graphics.Canvas.CreatePolygon(points, color, area);
            return area;
        },
        'CreatePolygon': function (points, color, parent) {
            var ctx = parent.getContext("2d");
            ctx.fillStyle = color || 'rgb(0,0,0)';
            ctx.beginPath();
            ctx.moveTo(points[0][0], points[0][1]);
            for(var i = 1; i < points.length; ++i) {
                ctx.lineTo(points[i][0], points[i][1]);
            }
            ctx.fill();
        },
        'CreateLine': function (from, to, color, parent, width) {
            var ctx = parent.getContext("2d");
            ctx.lineWidth = width || 1;
            ctx.strokeStyle = color || 'rgb(0,0,0)';
            ctx.beginPath();
            ctx.moveTo(from[0], from[1]);
            ctx.lineTo(to[0], to[1]);
            ctx.stroke();
        },
        'CreatePolyLine': function (points, color, parent, width) {
            if(points.length === 0) return;
            var ctx = parent.getContext("2d");
            ctx.lineWidth = width || 1;
            ctx.strokeStyle = color || 'rgb(0,0,0)';
            ctx.beginPath();
            ctx.moveTo(points[0][0], points[0][1]);
            for(var i = 1; i < points.length; ++i) {
                ctx.lineTo(points[i][0], points[i][1]);
            }
            ctx.stroke();
        },
        'CreateRect': function (pos, size, color, parent, border) {
            var ctx = parent.getContext("2d");
            if(border) {
                ctx.strokeStyle = border === true ? 'rgb(0,0,0)' : border;
                ctx.strokeRect(pos[0], pos[1], size[0], size[1]);
            }
            ctx.fillStyle = color;
            ctx.fillRect(pos[0], pos[1], size[0], size[1]);
        },
        'FixPolygon': function (polygon, points, size, color) {
            polygon.style.width = size[0] + "px";
            polygon.style.height = size[1] + "px";
            polygon.width = size[0];
            polygon.height = size[1];
            //clear
            var ctx = polygon.getContext("2d");
            ctx.clearRect(0, 0, size[0], size[1]);
            Graphics.Canvas.CreatePolygon(points, color, polygon);
        },
        'Init': function () {}
    },

    'SVG': {
        'CreateElement': function (type, parent) {
            var SVG_namespace = 'http://www.w3.org/2000/svg';
            try {
                var elem = document.createElementNS(SVG_namespace, type);
            } catch (e) {
                var elem = document.createElement(type);
                elem.setAttribute("xmlns", SVG_namespace);
            }
            
            if(parent) parent.appendChild(elem);
            return elem;
        },
        'CreateArea': function (size, parent) {
            var area = Graphics.SVG.CreateElement("svg", parent);
            area.setAttribute("width",  size[0] + "px");
            area.setAttribute("height", size[1] + "px");
            area.style.width = size[0] + "px";
            area.style.height = size[1] + "px";
            return area;
        },
        'CreatePolygonObj': function (points, color, parent, pos, size) {
            var area = Graphics.SVG.CreateArea(size, parent);
            area.style.position = "absolute";
            area.style.left = pos[0] + "px";
            area.style.top = pos[1] + "px";
            Graphics.SVG.CreatePolygon(points, color, area);
            return area;
        },
        'CreatePolygon': function (points, color, parent) {
            var polygon = Graphics.SVG.CreateElement("polygon", parent);
            polygon.setAttribute("points", points.join(","));
            polygon.setAttribute("fill", color || "black");
            return polygon;
        },
        'CreateLine': function (from, to, color, parent, width) {
            var line = Graphics.SVG.CreateElement("line", parent);
            line.setAttribute("x1", from[0] + "px");
            line.setAttribute("y1", from[1] + "px");
            line.setAttribute("x2", to[0] + "px");
            line.setAttribute("y2", to[1] + "px");
            line.setAttribute("stroke", color || "black");
            line.setAttribute("strokeWidth", width);
            return line;
        },
        'CreatePolyLine': function (points, color, parent, width) {
            var line = Graphics.SVG.CreateElement("polyline", parent);
            line.setAttribute("points", points.join(","));
            line.setAttribute("stroke", color || "black");
            line.setAttribute("strokeWidth", width);
            line.setAttribute("fill", 'none');
            return line;
        },
        'CreateRect': function (pos, size, color, parent, border) {
            var rect = Graphics.SVG.CreateElement("rect", parent);
            rect.setAttribute("x", pos[0] + "px");
            rect.setAttribute("y", pos[1] + "px");
            rect.setAttribute("width",  size[0] + "px");
            rect.setAttribute("height", size[1] + "px");
            rect.setAttribute("fill", color || "black");
            if(border) { rect.setAttribute("stroke", "black"); }
            return rect;
        },
        'FixPolygon': function () { debugger; },
        'Init': function () {}
    }
};

var useragent = "" + window.window.navigator.userAgent;
if(useragent.indexOf ('MSIE') != -1) {
    var SelectGraphics = function () { return Graphics.VML; }
} else {
    var SelectGraphics = function (type) {
        if(Graphics[type] && type !== 'VML') return Graphics[type];
        return Graphics.Canvas;
    }
}
function SelectInitGraphics(type) {
    var g = SelectGraphics(type);
    g.Init();
    return g;
}

//var UseSVG;
//var useragent = "" + window.window.navigator.userAgent;
//if(useragent.indexOf ('MSIE') != -1) {
//    var CreateArea = CreateArea_VML;
//    var CreatePolygonObj = CreatePolygonObj_VML;
//    var CreatePolygon = CreatePolygon_VML;
//    var CreateLine = CreateLine_VML;
//    var CreatePolyLine = CreatePolyLine_VML;
//    var CreateRect = CreateRect_VML;
//    var FixPolygon = FixPolygon_VML;
//    var Draw_Init = Init_VML;
//} else if(UseSVG === true) {
//    var CreateArea = CreateArea_SVG;
//    var CreatePolygonObj = CreatePolygonObj_SVG;
//    var CreatePolygon = CreatePolygon_SVG;
//    var CreateLine = CreateLine_SVG;
//    var CreatePolyLine = CreatePolyLine_SVG;
//    var CreateRect = CreateRect_SVG;
//    var Draw_Init = Init_SVG;
//} else {
//    var CreateArea = CreateArea_Canvas;
//    var CreatePolygonObj = CreatePolygonObj_Canvas;
//    var CreatePolygon = CreatePolygon_Canvas;
//    var CreateLine = CreateLine_Canvas;
//    var CreatePolyLine = CreatePolyLine_Canvas;
//    var CreateRect = CreateRect_Canvas;
//    var FixPolygon = FixPolygon_Canvas;
//    var Draw_Init = Init_Canvas;
//}

function MeasureText(text, fontSize) {
    if(!MeasureText.div) {
        MeasureText.div = document.createElement("div");
        MeasureText.div.style.position = "absolute";
        MeasureText.div.style.width = "auto";
        MeasureText.div.style.height = "auto";
        MeasureText.div.style.visibility = "hidden";
        document.body.insertBefore (MeasureText.div, document.body.firstChild);
    }
    MeasureText.div.style.fontSize = fontSize;
    MeasureText.div.innerText = text;
    return { 'width': MeasureText.div.offsetWidth, 'height': MeasureText.div.offsetHeight };
}
MeasureText.div = null;


function purge(d) {
    var a = d.attributes, i, l, n;
    if (a) {
        l = a.length;
        for (i = 0; i < l; ++i) {
            n = a[i].name;
            if (typeof d[n] === 'function') {
                d[n] = null;
            }
        }
    }
    a = d.childNodes;
    if (a) {
        l = a.length;
        for (i = 0; i < l; ++i) {
            purge(d.childNodes[i]);
        }
    }
}

function Node() { }
Node.prototype.get = function () { return null; }
Node.prototype.getNum = function (attr) { return parseFloat(this.get(attr)); }
Node.prototype.getBool = function (attr) {
    var val = this.get(attr);
    return val === "true" || val === "on";
}

function ObjectNode(obj) { this.obj = obj; }
ObjectNode.prototype = new Node();
ObjectNode.prototype.get = function (attr) { return this.obj[attr]; }
ObjectNode.prototype.type = "ObjectNode";
function PrefixNode(prefix, node) { this.prefix = prefix; this.node = node }
PrefixNode.prototype.get = function (attr) { return this.node.get(this.prefix + attr); }
PrefixNode.prototype.type = "PrefixNode";
function FunctionNode(funcs) { this.funcs = funcs; }
FunctionNode.prototype.get = function (attr) { return this.funcs[attr] && this.funcs[attr](); }
FunctionNode.prototype.type = "FunctionNode";
function XmlNode(node) { this.node = node; }
XmlNode.prototype.get = function (attr) { return this.node.getAttribute(attr); }
XmlNode.prototype.type = "XmlNode";
function CacheNode(node) { this.node = node; this.cache = {}; }
CacheNode.prototype = new Node();
CacheNode.prototype.get = function (attr) {
    if(this.cache[attr] === undefined) {
        this.cache[attr] = this.node.get(attr);
        if(this.cache[attr] === undefined) this.cache[attr] = null;
    }
    return this.cache[attr];
}
CacheNode.prototype.type = "CacheNode";
function OrNode() { this.values = arguments; }
OrNode.prototype = new Node();
OrNode.prototype.get = function (attr) {
    var val;
    for(var ix = 0; ix < this.values.length; ++ix) {
        val = this.values[ix].get(attr);
        if(val || val === 0) break;
    }
    return val;
}
OrNode.prototype.type = "OrNode";

function GraphObj() { }
GraphObj.prototype = new Node();
GraphObj.prototype.get = function (attr) { return this.data.get(attr); }
GraphObj.prototype.type = "GraphObj";
GraphObj.prototype.draw = function () {};
GraphObj.prototype.init = function (graph, data) {
    this.data = data;
    this.Graph = graph;
}
GraphObj.prototype.xml_init = function (graph, parent, elem) {
    this.init(graph, new OrNode(new XmlNode(elem), parent));
}
GraphObj.prototype.update1 = function () {};
GraphObj.prototype.update2 = function () {};

var graphObjs = { }
function createGraphObj(tagName) {
    var f = graphObjs[tagName];
    return f && new f();
}
function createGraphObjType(name, needPlotarea, base) {
    function f() {}
    f.prototype = new (base || GraphObj)();
    f.prototype.type = name;
    f.prototype.needPlotarea = needPlotarea;
    graphObjs[name] = f;
    return f;
}

function Legend(graph) { this.Graph = graph; }
Legend.prototype = new Node();
Legend.prototype.add = function(item) { this.items[this.items.length] = item; }
Legend.prototype.clear = function() { this.items = []; }
Legend.prototype.update = function(size) {
    if(this.items.length === 0) return;
    this.fontSize = 12;
    this.symbolSize = MeasureText("�g", this.fontSize).height;
    var max_w = 0;
    for(var i = 0; i < this.items.length; ++i) {
        var w = MeasureText(this.items[i].text, this.fontSize).width;
        if(w > max_w) max_w = w;
    }
    var width = 20 + this.symbolSize + max_w;
    
    this.x = size.width - width + 10;
    this.y = size.y;
    
    size.width -= width;
}
Legend.prototype.draw = function() {
    var G = this.Graph.G;

    for(var i = 0; i < this.items.length; ++i) {
        var item = this.items[i];
        
        var x = this.x;
        var y = this.y;
        
        var symbol_size = this.symbolSize;
        y += i * (symbol_size + 2);
        
        var symbol = G.CreateRect([x, y], [symbol_size, symbol_size], item.color, this.Graph.Root, false);
        var label = CreateText(this.Graph, item.text, this.fontSize);
        label.div.style.left = (x + symbol_size + 5) + "px";
        label.div.style.top  = Math.round(y + (symbol_size - label.height) / 2) + "px";
    }
}

function Range(graph, id) { this.datasets = []; this.id = id; this.Graph = graph; }
Range.prototype = new Node();
Range.prototype.get = function (attr) { return this.data.get(attr); }
Range.prototype.getLength = function(l) { 
    l = Math.round(l * Math.abs(this.start - this.end));
    return l + this.end_off - this.start_off; 
}
Range.prototype.scale = function (v, l, rev) {
    v = ScaleFrom(v, this.min, this.max);
    if(this.rev || rev) v = 1 - v;
    v = ScaleTo(v, this.start, this.end);
    return ScaleTo(v, this.start_off, l + this.end_off);
}
Range.prototype.update = function () {
    var from = this.get("from");
    if(from) {
        from = from.split(";");
        for(var i = 0; i < from.length; ++i) {
            from[i] = this.Graph.Datasets[from[i]];
        }
    }
    var data = from || this.datasets;
    
    this.datasets = [];
    
    this.start = 0;
    this.end   = 1;
    this.start_off = 0;
    this.end_off   = 0;
    
    var start = this.get("start") || "10px";
    var end   = this.get("end")   || "-10px";
    if(start.charAt(start.length - 1) === "%") {
        this.start = parseFloat(start) / 100;
    } else if((/px$/).test(start)) {
        this.start_off = parseInt(start);
    } else {
        this.start_off = 10;
    }
    if(end.charAt(end.length - 1) === "%") {
        this.end = parseFloat(end) / 100;
    } else if((/px$/).test(end)) {
        this.end_off = parseInt(end);
    } else {
        this.end_off = -10;
    }

    if(data) {
        var _min = null;
        var _max = null;
        for(var i = 0; i < data.length; ++i) {
            if(_min === null || data[i].min < _min) _min = data[i].min;
            if(_max === null || data[i].max > _max) _max = data[i].max;
        }
    }
    var min = this.get("min") || "100%";
    var max = this.get("max") || "100%";
    if(min == null)
        this.min = _min || 0;
    else if(min.charAt(min.length - 1) === "%")
        this.min = (_min || 0) * parseFloat(min) / 100;
    else
        this.min = parseFloat(min);
    if(max == null)
        this.max = _max || 0;
    else if(max.charAt(max.length - 1) === "%")
        this.max = (_max || 0) * parseFloat(max) / 100;
    else
        this.max = parseFloat(max);
    
    if(this.min === this.max) ++this.max;
}

function Dataset(id) { this.id = id; this.continuous = true; }
Dataset.prototype.xml_update = function(node) {
    
    var subNode = node.firstChild;
    for (; subNode; subNode = subNode.nextSibling) {
        if (subNode.getAttribute('name') == this.id) break;
    }
    
    var counter = 0;
    var map = {};
    
    this.vals = [];
    this.txts = [];
    this.unique = [];
    var min = null;
    var max = null;
    for(var valNode = subNode.childNode; valNode; valNode.nextSibling) {
        if (valNode.nodeName != 'element') continue;
        var txt = valNode.getAttribute("text")
        this.txts[this.txts.length] = txt;
        
        var val;
        if(valNode.getAttribute("isnum") === "true" && this.continuous) {
            val = parseFloat(valNode.getAttribute("value"));
        } else {
            this.continuous = false;
            if(map[txt] == null) {
                this.unique[this.unique.length] = txt;
                map[txt] = counter;
                ++counter;
            }
            val = map[txt];
        }
        if(min === null || val < min) min = val;
        if(max === null || val > max) max = val;
        this.vals[this.vals.length] = val;
    }
    this.min = min;
    this.max = max;
}
Dataset.prototype.getLength = function() { return this.vals.length; }
Dataset.prototype.getVal  = function(i) { return this.vals[i]; }
Dataset.prototype.getText = function(i) { return this.txts[i]; }
Dataset.prototype.getUnique = function() { return this.unique; }

function Graph() { }
Graph.prototype = new Node();
Graph.prototype.getNextColor = function () {
    var c = this.Colors[this.nextColor % this.Colors.length];
    ++this.nextColor;
    return c;
}
Graph.prototype.getToolTip = function () {
    if(!this.tooltip) {
        this.tooltip = document.createElement("div");
        this.tooltip.style.position = "absolute";
        this.tooltip.style.width    = "auto";
        this.tooltip.style.height   = "auto";
        this.tooltip.style.zIndex   = 666;
        this.tooltip.style.backgroundColor = "FFFFCC";
        this.tooltip.style.borderWidth = 1;
        this.tooltip.style.borderColor = "black";
        this.tooltip.style.borderStyle = "solid";
        this.tooltip.style.padding = 3;
        document.body.insertBefore (this.tooltip, document.body.firstChild);
    }
    return this.tooltip;
}
Graph.prototype.addToLegend = function (legendItem) { if(this.Legend) this.Legend.add(legendItem); }
Graph.prototype.addDataset = function (id) {
    if(!id) return;
    if(!this.Datasets[id]) this.Datasets[id] = new Dataset(id);
    return this.Datasets[id];
}
Graph.prototype.getRange = function (id, type) {
    if(!id) id = "__default__" + type;
    if(!this.Ranges[id]) {
        this.Ranges[id] = new Range(this, id);
        this.Ranges[id].data = new Node();
    }
    return this.Ranges[id];
}

Graph.prototype.get = function (attr) { return this.data.get(attr); }
Graph.prototype.init = function (G, htmlRoot) {
    this.G = G;
    this.data = new Node();
    this.ById = {};
    this.HtmlRoot = htmlRoot;
    this.Datasets = {};
    this.Ranges = {};
    this.Colors = ["#3366CC", "#CC3333", "#33CC66", "#CCCC33", "#33CCCC", "#CC66CC", 
                   "#336699", "#993333", "#339966", "#999933"];
}
Graph.prototype.xml_init = function (mgr, elem) {
    this.init(mgr.G, elem.parentNode);
    this.data = new OrNode(new Node(), new XmlNode(elem)); //, defaultNode
    this.Mgr = mgr; // not used
    
    var usePlotarea = false;
    var children = []
    for(var i = 0; i < elem.childNodes.length; ++i) {
        var child = elem.childNodes[i];
        var tagName = CheckNamespace(child);
        if(!tagName) continue;
        
        if(tagName === "dataset") {
            var d = this.addDataset(child.getAttribute("id"));
            if(d) d.continuous = child.getAttribute("continuous") !== "false";
        } else if(tagName === "legend") {
            this.Legend = new Legend(this);
        } else if(tagName === "range") {
            var range = new Range(this);
            range.data = new OrNode(new XmlNode(child), this.data);
            var id = range.get("id");
            range.id = id;
            if(id) this.Ranges[id] = range;
        } else {
            var obj = createGraphObj(tagName);
            if(obj) {
                obj.xml_init(this, this, child);
                if(obj.needPlotarea && !usePlotarea) {
                    children = [];
                    usePlotarea = true;
                }
                if(obj.needPlotarea === usePlotarea) children[children.length] = obj;
            }
        }
    }
    if(usePlotarea) {
        var plotarea = new Plotarea();
        plotarea.init(this, this);
        plotarea.children = children;
        this.children = [plotarea];
    } else {
        this.children = children;
    }
    
    for(var id in this.Datasets) {
        mgr.Owner.Append({ 'Paint' : function() {} }, mgr.Name + '.' + id);
    }
}

Graph.prototype.xml_update = function(node) {
    this.data.values[0] = new XmlNode(node);
    for(var id in this.Datasets) this.Datasets[id].xml_update(node);
}
Graph.prototype.update = function() {
    this.nextColor = 0;
    if(this.Legend) this.Legend.clear();
    for(var i = 0; i < this.children.length; ++i) this.children[i].update1();
    for(var id in this.Ranges) this.Ranges[id].update();
    
    var top_padding = MeasureText("�g", 18).height * 2;
    var bottom_padding = 5;
    var height = this.HtmlRoot.offsetHeight - top_padding - bottom_padding;
    var left_padding = 5;
    var right_padding = 5;
    var width = this.HtmlRoot.offsetWidth - left_padding - right_padding;
    var size = { "x": left_padding, "y": top_padding, "width": width, "height": height };
    
    if(this.Legend) this.Legend.update(size);
    
    var len = this.children.length;
    for(var i = 0; i < len; ++i) {
        var s = { "x": Math.round(size.x + i * size.width / len), "y": size.y, "width": Math.round(size.width / len), "height": size.height };
        this.children[i].update2(s || size);
    }
}
Graph.prototype.draw = function() {
    var G = this.G;
    var div = this.HtmlRoot
    
    var width = div.offsetWidth;
    var height = div.offsetHeight;
    
    var r = document.createElement("div");
    r.style.position = "absolute";
    this.TextRoot = r;
    
    // Create VML root
    this.Root = G.CreateArea([width, height], r);

    // Chart Title
    var label = CreateText(this, this.get("label") || "???", 18);
    label.div.style.top = Math.round(label.height / 2) + "px";
    label.div.style.left = Math.round((width - label.width) / 2) + "px";
    
    for(var i = 0; i < this.children.length; ++i) this.children[i].draw();
    
    if(this.Legend) this.Legend.draw();
    
    if(this.lastDiv) {
        purge(this.lastDiv); // Fix IE memory leak
        div.replaceChild(r, this.lastDiv);
    } else {
        div.appendChild(r);
    }
    this.lastDiv = r;
}

var Plotarea = createGraphObjType("plotarea", false);
Plotarea.prototype.update1 = function () {
    for(var i = 0; i < this.children.length; ++i) this.children[i].update1();
}
Plotarea.prototype.update2 = function (size) {
    for(var i = 0; i < this.children.length; ++i) {
        if(this.children[i].type === "x-axis") {
            size.height -= MeasureText("�g", this.children[i].fontSize).height + 5;
            break;
        }
    }
    
    var l_max_w = 0;
    var r_max_w = 0;
    for(var i = 0; i < this.children.length; ++i) {
        if(this.children[i].type === "y-axis") {
            var w = this.children[i].updateStep(size) + 5;
            if(this.children[i].alt) {
                if(w > r_max_w) r_max_w = w;
            } else {
                if(w > l_max_w) l_max_w = w;
            }
        }
    }
    size.width -= l_max_w + r_max_w;
    size.x += l_max_w;
    
    this.x = size.x;
    this.y = size.y;
    this.width  = size.width;
    this.height = size.height;
    
    for(var i = 0; i < this.children.length; ++i) this.children[i].update2(size);
    
    // Update_Bars
    var range_set = {};
    for(var i = 0; i < this.children.length; ++i) {
        var child = this.children[i];
        if(child.type === "bar") {
            var bar = child;
            if(!range_set[bar.xrange.id]) range_set[bar.xrange.id] = [];
            var l = range_set[bar.xrange.id];
            l[l.length] = bar;
        } else if(child.type === "stack") {
            for(var j = 0; child.children.length; ++j) {
                if(child.children[j].type !== "bar") continue;
                var bar = child.children[j];
                if(!range_set[bar.xrange.id]) range_set[bar.xrange.id] = [];
                var l = range_set[bar.xrange.id];
                l[l.length] = child;
                break;
            }
        }
    }
    
    var bar_dist = 2;
    var cluster_dist = 7;
    
    for(var range_id in range_set) {
        var bars = range_set[range_id];
        var range = this.Graph.Ranges[range_id];
        var width = Math.round(range.getLength(this.width));
        
        var x_len;
        for(var i = 0; !x_len && i < bars.length; ++i) {
            if(bars[i].type === "bar") {
                x_len = this.Graph.Datasets[bars[i].get("x")].getLength();
            } else if(bars[i].type === "stack") {
                for(var j = 0; j < !x_len && bars[i].children.length; ++j) {
                    if(child.children[j].type !== "bar") continue;
                    x_len = this.Graph.Datasets[bars[i].children[j].get("x")].getLength();
                }
            } else { debugger; }
        }
        if(!x_len) { debugger; continue; }
        var y_len = bars.length;
        
        var left = width - ((x_len - 1) * cluster_dist + x_len * (y_len - 1) * bar_dist);
        var bar_width = Math.floor(left / (x_len * y_len));
        var cluster_size = bar_width * y_len + bar_dist * (y_len - 1);
        
        var range_offset = cluster_size / 2;
        range.start_off += range_offset;
        range.end_off   -= range_offset;
        
        for(var i = 0; i < bars.length; ++i) {
            if(bars[i].type === "bar") {
                var bar = bars[i];
                bar.width = bar_width;
                bar.offset = -cluster_size/2 + i*(bar_width+bar_dist);
            } else if(bars[i].type === "stack") {
                for(var j = 0; j < bars[i].children.length; ++j) {
                    if(child.children[j].type !== "bar") continue;
                    var bar = bars[i].children[j];
                    bar.width = bar_width;
                    bar.offset = -cluster_size/2 + i*(bar_width+bar_dist);
                }
            } else { debugger; }
        }
    }
}
Plotarea.prototype.draw = function () {
    var G = this.Graph.G;

    var div = this.Graph.TextRoot;
    var r = document.createElement("div");
    div.appendChild(r);
    
    r.style.position = "absolute";
    r.style.left = this.x + "px";
    r.style.top  = this.y + "px";
    r.style.width  = this.width + "px";
    r.style.height = this.height + "px";
    r.style.overflow = "hidden";
    r.style.backgroundColor = this.get("bgcolor") || "#EDECEC";
    
    this.area = G.CreateArea([this.width, this.height], r);
    
    for(var i = 0; i < this.children.length; ++i) { 
        this.children[i].draw(this); 
    }
}

function Update_Bars(graph) {
    if(graph.flip_orientation) {
        var Width = graph.area.height;
    } else {
        var Width = graph.area.width;
    }
    Width = Math.round(Math.abs(graph.data.x[0].range.end - graph.data.x[0].range.start) * Width);
    
    var x_len = Math.min(graph.data.x[0].length, graph.maxvalues);
    var bar_dist = 2;
    var cluster_dist = 7;

    var y_len = graph.data.y.length;
    if(graph.stacked) y_len = 1;
    
    var left = Width - ((x_len - 1) * cluster_dist + x_len * (y_len - 1) * bar_dist);
    var bar_width = Math.floor(left / (x_len * y_len));
    var cluster_size = bar_width * y_len + bar_dist * (y_len - 1);
    var range_offset = cluster_size / 2 / Width;
    graph.data.x[0].range.end   -= range_offset;
    graph.data.x[0].range.start += range_offset;
    
    for(var i = 0; i < graph.data.y.length; ++i) {
        var bar = graph.data.y[i];
        bar.width = bar_width;
        if(graph.stacked) {
            bar.offset = -bar_width/2;
        } else {
            bar.offset = -cluster_size/2 + i*(bar_width+bar_dist);
        }
        
    }
}

function Axis() {}
Axis.prototype = new GraphObj();
Axis.prototype.init = function(graph, data) {
    GraphObj.prototype.init.apply(this, arguments);
    graph.addDataset(this.get("data"));
    this.fontSize = 12;
    this.axistype = this.type.split("-")[0];
}
Axis.prototype.update1 = function() {
    this.range = this.Graph.getRange(this.get(this.axistype + "range"), this.axistype);
    this.offset = 0;
    this.values = this.get("data") && this.Graph.Datasets[this.get("data")];
    this.continuous = !this.values;
    this.alt = /^alt/.test(this.get("placement"));
    
    this.dist = parseInt(this.get("dist") || 3);
}

var YAxis = createGraphObjType("y-axis", true, Axis);
YAxis.prototype.updateStep = function (size) {
    this.min = this.range.min;
    this.max = this.range.max;
    if(this.min === this.max) { debugger; return; }
    
    var h = Math.round(this.range.getLength(size.height));

    var min = this.min;
    var max = this.max;
    
    var th = MeasureText("0", this.fontSize).height + this.dist;
    var step = 1;
    
    var zero = this.range.scale(0, h);
    while(true) {
        if(Math.abs(this.range.scale(step, h) - zero) >= th) break;
        if(Math.abs(this.range.scale(step * 2, h) - zero) >= th) {
            step *= 2;
            break;
        }
        if(Math.abs(this.range.scale(step * 5, h) - zero) >= th) {
            step *= 5;
            break;
        }
        step *= 10;
    }
    
    var max_w = 0;
    for (var val = min - (min % step - step) % step; val <= max; val += step) {
        var w = MeasureText(val, this.fontSize).width;
        if(w > max_w) max_w = w;
    }
    
    var label = this.get("axis-label");
    if(label) {
        var w = MeasureText(label, this.fontSize).width;
        if(w > max_w) max_w = w;
    }
    
    this.step = step;
    return max_w;
}
YAxis.prototype.draw = function (plotarea) {
    var G = this.Graph.G;

    if(this.continuous) {
        if(this.min <= 0 && 0 <= this.max) {
            var y0 = Math.round(this.range.scale(0, plotarea.height, true));
            G.CreateLine([0, y0], [plotarea.width, y0], null, plotarea.area);
        }
        Continuous_Axis(this.Graph, plotarea, this, Put_Y_AxisLabel);
    } else {
        Discrete_Axis(this.Graph, plotarea, this, Put_Y_AxisLabel);
    }
    var label = this.get("axis-label");
    if(label) {
        var xbase = plotarea.x;
        if(this.alt) xbase += plotarea.width
        
        var label = CreateText(this.Graph, label, this.fontSize);
        if(this.alt) {
            label.div.style.left = (xbase + 5) + "px";
        } else {
            label.div.style.left = (xbase - 5 - label.width) + "px";
}
        label.div.style.top = Math.round(plotarea.y - label.height - 5) + "px";
    }
}

var XAxis = createGraphObjType("x-axis", true, Axis);
XAxis.prototype.update2 = function (size) {
    this.min = this.range.min;
    this.max = this.range.max;
    
    var w = Math.round(this.range.getLength(size.width));
    var min = this.min;
    var max = this.max;
    
    if(this.continuous) {
        var tw = Math.max(MeasureText(min, this.fontSize).width, MeasureText(max, this.fontSize).width);
    } else {
        var tw = 1;
        var l = this.values.getUnique();
        for(var i = 0; i < l.length; ++i) {
            var tw = Math.max(tw, MeasureText(l[i], this.fontSize).width);
        }
    }
    tw += this.dist;
    
    var step = 1;
    
    var zero = this.range.scale(0, w);
    while(true) {
        if(Math.abs(this.range.scale(step, w) - zero) >= tw) break;
        if(Math.abs(this.range.scale(step * 2, w) - zero) >= tw) {
            step *= 2;
            break;
        }
        if(Math.abs(this.range.scale(step * 5, w) - zero) >= tw) {
            step *= 5;
            break;
        }
        step *= 10;
    }
    this.step = step;
}
XAxis.prototype.draw = function (plotarea) {
    var G = this.Graph.G;
    if(this.continuous) {
        if(this.min <= 0 && 0 <= this.max) {
            var x0 = Math.round(this.range.scale(0, plotarea.width));
            G.CreateLine([x0, 0], [x0, plotarea.height], null, plotarea.area);
        }
        Continuous_Axis(this.Graph, plotarea, this, Put_X_AxisLabel)
    } else {
        Discrete_Axis(this.Graph, plotarea, this, Put_X_AxisLabel);
    }
}

function Discrete_Axis(graph, plotarea, axis, putAxisLabel) {
    var txts = axis.values.getUnique();
    var step = axis.step || 1;
    for (var i = 0; i < txts.length; i += step) {
        putAxisLabel(graph, plotarea, i, txts[i], axis);
    }
}
function Continuous_Axis(graph, plotarea, axis, putAxisLabel) {
    var min = axis.min;
    var max = axis.max;
    
    var step = axis.step || 1;
    for (var val = min - (min % step - step) % step; val <= max; val += step) {
        putAxisLabel(graph, plotarea, val, val, axis);
    }
}
function Put_X_AxisLabel(graph, plotarea, val, text, axis) {
    var G = graph.G;
    var xbase = Math.round(axis.range.scale(val, plotarea.width));
    if(axis.showgrid && (val !== 0 || !axis.continuous)) {
        G.CreateLine([xbase, 0], [xbase, plotarea.width], axis.gridcolor, plotarea.area);
    }
    xbase += plotarea.x;

    var ybase = axis.offset + plotarea.y;
    if(!axis.alt) ybase += plotarea.height;
    G.CreateLine([xbase, ybase + (axis.alt ? -1 : 1)], [xbase, ybase], null, graph.Root);

    var fontSize = axis.fontSize;
    var label = CreateText(graph, text, fontSize);
    if(axis.alt) {
        label.div.style.top = (ybase - 5 - label.height) + "px";
    } else {
        label.div.style.top = (ybase + 5) + "px";
    }
    label.div.style.left = Math.round(xbase - label.width / 2) + "px";
}
function Put_Y_AxisLabel(graph, plotarea, val, text, axis) {
    var G = graph.G;
    var ybase = Math.round(axis.range.scale(val, plotarea.height, true));
    if(axis.showgrid && (val !== 0 || !axis.continuous)) {
        G.CreateLine([0, ybase], [plotarea.width, ybase], axis.gridcolor, plotarea.area);
    }
    ybase += plotarea.y;
    
    var xbase = plotarea.x;
    if(axis.alt) xbase += plotarea.width
    G.CreateLine([xbase + (axis.alt ? 1 : -1), ybase], [xbase, ybase], null, graph.Root);
    
    var fontSize = axis.fontSize;
    var label = CreateText(graph, text, fontSize);
    if(axis.alt) {
        label.div.style.left = (xbase + 5) + "px";
    } else {
        label.div.style.left = (xbase - 5 - label.width) + "px";
    }
    label.div.style.top = Math.round(ybase - label.height / 2) + "px";
}

var Stack = createGraphObjType("stack");
Stack.prototype.xml_init = function (graph, parent, elem) {
    GraphObj.prototype.xml_init.apply(this, arguments);
    
    var usePlotarea = false;
    var children = []
    for(var i = 0; i < elem.childNodes.length; ++i) {
        var child = elem.childNodes[i];
        var tagName = CheckNamespace(child);
        if(!tagName) continue;
        
        var obj = createGraphObj(tagName);
        if(obj) {
            obj.xml_init(graph, this, child);
            if(obj.needPlotarea && !usePlotarea) {
                children = [];
                usePlotarea = true;
            }
            if(obj.needPlotarea === usePlotarea) children[children.length] = obj
        }
    }
    this.needPlotarea = usePlotarea
    this.children = children;
}
Stack.prototype.update1 = function () {
    for(var i = this.children.length - 1; i >= 0; --i) this.children[i].update1();
}
Stack.prototype.update2 = function (size) {
    for(var i = 0; i < this.children.length; ++i) this.children[i].update2(size);
}
Stack.prototype.draw = function (plotarea) {
    var stack = [];
    for(var i = 0; i < this.children.length; ++i) {
        this.children[i].draw(plotarea, stack);
    }
}

function updateRange(obj, type) {
    var data = obj.get(type) && obj.Graph.Datasets[obj.get(type)];
    if(data) {
        obj[type + "range"] = obj.Graph.getRange(obj.get(type + "range"), type);
        obj[type + "range"].datasets[obj[type + "range"].datasets.length] = data;
    }
}

var Line = createGraphObjType("line", true);
Line.prototype.init = function (graph) {
    GraphObj.prototype.init.apply(this, arguments);
    var x = this.get("x");
    var y = this.get("y");
    var r = this.get("r");
    var a = this.get("angle");
    if(x && y) {
        graph.addDataset(x);
        graph.addDataset(y);
        this.draw = this.drawXY;
    } else if(r && a) {
        graph.addDataset(r);
        graph.addDataset(a);
        this.draw = this.drawRA;
    }
}
Line.prototype.update1 = function () {
    updateRange(this, "x");
    updateRange(this, "y");
    updateRange(this, "r");
    updateRange(this, "angle");
    this.color = this.get("color") || this.Graph.getNextColor();
    var label = this.get("label");
    if(label) this.Graph.addToLegend({ "text": label, "color": this.color });
}
Line.prototype.drawXY = function (plotarea) {
    var G = this.Graph.G;
    
    var xrange = this.xrange;
    var yrange = this.yrange;
    var xdata = this.Graph.Datasets[this.get("x")];
    var ydata = this.Graph.Datasets[this.get("y")];
    
    var points = [];
    for (var i = 0; i < xdata.getLength(); ++i) {
        var xpos = Math.round(xrange.scale(xdata.getVal(i), plotarea.width));
        var ypos = Math.round(yrange.scale(ydata.getVal(i), plotarea.height, true));
        points[points.length] = [xpos, ypos];
    }
    
    var line = G.CreatePolyLine(points, this.color, plotarea.area, 1.2);
    if(line) { //&& this.getBool("highlight")
        line.onmouseover = function() { line.strokeweight *= 2 }
        line.onmouseout  = function() { line.strokeweight /= 2 }
    }
    return line;
}

var Bar = createGraphObjType("bar", true);
Bar.prototype.init = function (graph) {
    GraphObj.prototype.init.apply(this, arguments);
    graph.addDataset(this.get("x"));
    graph.addDataset(this.get("y"));
}
Bar.prototype.update1 = function () {
    updateRange(this, "x");
    updateRange(this, "y");
    
    this.color = this.get("color") || this.Graph.getNextColor();
    var label = this.get("label");
    if(label) this.Graph.addToLegend({ "text": label, "color": this.color });
    
    this.width = 10;
    this.offset = -5; //- this.width/2
}
Bar.prototype.draw = function (plotarea, stack) {
    var G = this.Graph.G;
    var xrange = this.xrange;
    var yrange = this.yrange;
    var xdata = this.Graph.Datasets[this.get("x")];
    var ydata = this.Graph.Datasets[this.get("y")];

    for(var i = 0; i < xdata.getLength(); ++i) {
        var yval1 = ydata.getVal(i);
        var yval0 = (stack && stack[i]) || 0;
        yval1 += yval0;
        if(stack) stack[i] = yval1;
        
        var xpos   = Math.round(xrange.scale(xdata.getVal(i), plotarea.width));
        var ypos0  = Math.round(yrange.scale(yval0, plotarea.height, true));
        var ypos1  = Math.round(yrange.scale(yval1, plotarea.height, true));
        var x      = xpos + this.offset;
        var y      = Math.min(ypos0, ypos1);
        var width  = this.width;
        var height = Math.abs(ypos0  - ypos1);
        
        var r = G.CreateRect([x, y], [width, height], this.color, plotarea.area, true);
        
        AddToolTip(r, this, { "<dim>": xdata.getText(i), "<expr>": ydata.getText(i) }, "Dim: <dim><br>Expr: <expr>");
    }
}

function AddToolTip(target, obj, data, default_tooltip) {
    var tooltip_txt = obj.get("tooltip");
    
    if(target && tooltip_txt != null && tooltip_txt != "false") {
        if(typeof(tooltip_txt) !== "string" || tooltip_txt == "true") tooltip_txt = default_tooltip || "???";
        var tooltip = obj.Graph.getToolTip();
        
        target.onmouseover = function (event) {
            if (!event) event = window.event;
            
            for(var key in data) {
                tooltip_txt = tooltip_txt.replace(key, data[key]);
            }
            tooltip.innerHTML = tooltip_txt

            tooltip.style.left = (event.clientX + 5) + "px";
            tooltip.style.top  = (event.clientY + 5) + "px";
            tooltip.style.visibility = "visible";
        }
        target.onmousemove = target.onmouseover;
        target.onmouseout = function (event) {
            if (!event) event = window.event;
            
            tooltip.style.visibility = "hidden";
        }
    }
}

var Scatter = createGraphObjType("scatter", true);
Scatter.prototype.init = function (graph) {
    GraphObj.prototype.init.apply(this, arguments);
    graph.addDataset(this.get("x"));
    graph.addDataset(this.get("y"));
    graph.addDataset(this.get("size"));
    graph.addDataset(this.get("color"));
    graph.addDataset(this.get("key"));
}
Scatter.prototype.update1 = function () {
    updateRange(this, "x");
    updateRange(this, "y");
    
    this.colors = (this.get("color") && this.Graph.Datasets[this.get("color")]) || new ColorList(this.Graph);
    addKeysToLegend(this);
}
Scatter.prototype.draw = function (plotarea, stack) {
    var G = this.Graph.G;
    var xrange = this.xrange;
    var yrange = this.yrange;
    var xdata = this.Graph.Datasets[this.get("x")];
    var ydata = this.Graph.Datasets[this.get("y")];

    var size_data = this.get("size") && this.Graph.Datasets[this.get("size")];
    
    for(var i = 0; i < xdata.getLength(); ++i) {
        var xpos = Math.round(xrange.scale(xdata.getVal(i), plotarea.width));
        var ypos = Math.round(yrange.scale(ydata.getVal(i), plotarea.height, true));
        
        var size = size_data ? size_data.getVal(i) : 10;
        
        //var o = CreateVMLElement("oval", plotarea.area);
        var o = G.CreateElement("oval", plotarea.area);
        o.style.left   = Math.round(xpos - size/2) + "px";
        o.style.top    = Math.round(ypos - size/2) + "px";
        o.style.width  = size + "px";
        o.style.height = size + "px";
        o.fillcolor = this.colors.getText(i);
        
        AddToolTip(o, this, { "<x>": xdata.getText(i), "<y>": ydata.getText(i) }, "x: <x><br>y: <y>");
    }
}

function ColorList(graph) { this.colors = []; this.Graph = graph; }
ColorList.prototype.getText = function (i) {
    if(!this.colors[i]) this.colors[i] = this.Graph.getNextColor();
    return this.colors[i];
}
function addKeysToLegend(obj) {
    var keys = obj.get("key") && obj.Graph.Datasets[obj.get("key")];
    if(keys) {
        for(var i = 0; i < keys.getLength(); ++i) {
            obj.Graph.addToLegend({ "text": keys.getText(i), "color": obj.colors.getText(i) });
        }
    }
}

var Pie = createGraphObjType("pie", false);
Pie.prototype.init = function (graph) {
    GraphObj.prototype.init.apply(this, arguments);
    graph.addDataset(this.get("size"));
    graph.addDataset(this.get("color"));
    graph.addDataset(this.get("key"));
}
Pie.prototype.update1 = function () {
    this.colors = (this.get("color") && this.Graph.Datasets[this.get("color")]) || new ColorList(this.Graph);
    addKeysToLegend(this);
}
Pie.prototype.update2 = function (size) {
    this.radius  = Math.round(Math.min(size.width, size.height) / 2);
    this.centerx = size.x + this.radius;
    this.centery = size.y + this.radius;
}
Pie.prototype.draw = function () {
    var G = this.Graph.G;
    var root = this.Graph.Root;

    var radius  = this.radius;
    var centerx = this.centerx;
    var centery = this.centery;
    
    var inner_radius = this.inner_radius || 0;
    
    function each(start, end, color) {
        var startangle = Math.PI * 2 * start - Math.PI/2
        var endangle = Math.PI * 2 * end - Math.PI/2;
        
        var startx = Math.round(centerx + Math.cos(startangle) * radius);
        var starty = Math.round(centery + Math.sin(startangle) * radius);
        var endx = Math.round(centerx + Math.cos(endangle) * radius);
        var endy = Math.round(centery + Math.sin(endangle) * radius);
        
        var path = "wr " + (centerx - radius) + "," + (centery - radius) + "," + (centerx + radius) + "," + (centery + radius) + "," + startx + "," + starty + "," + endx + "," + endy;
        startx = Math.round(centerx + Math.cos(endangle) * inner_radius);
        starty = Math.round(centery + Math.sin(endangle) * inner_radius);
        endx = Math.round(centerx + Math.cos(startangle) * inner_radius);
        endy = Math.round(centery + Math.sin(startangle) * inner_radius);
        path += " at " + (centerx - inner_radius) + "," + (centery - inner_radius) + "," + (centerx + inner_radius) + "," + (centery + inner_radius) + "," + startx + "," + starty + "," + endx + "," + endy + " x e";
        
        var s = G.CreateShape(path, root.coordsize, color, root);
        s.style.width = root.style.width;
        s.style.height = root.style.height;
        return s;
    }
    DrawProportionalChart(this, each);
}

function DrawProportionalChart(obj, each) {
    var size_data = obj.Graph.Datasets[obj.get("size")];
    var color_data = obj.colors;
    var key_data = obj.get("key") && obj.Graph.Datasets[obj.get("key")];
    
    var sum = 0;
    for(var i = 0; i < size_data.getLength(); ++i) sum += size_data.vals[i];
    
    var start = 0;
    for(var i = 0; i < size_data.getLength(); ++i) {
        var diff = size_data.getVal(i);
//        if(key_data) {
//            for(var key = key_data.getText(i); (i < key_data.getLength() - 1) && key_data.getText(i+1) === k_val; ++i) {
//                diff += size_data.getVal(i+1);
//            }
//        }
        var end = start + diff / sum;
        
        var g = each(start, end, color_data.getText(i));
        start = end;
        
        AddToolTip(g, obj, { "<size>": size_data.getText(i) }, "size: <size>");
    }
}

function CreateText(graph, text, fontSize) {
    var attrib = {'position' : "absolute",
                  'fontSize' : fontSize + "px",
                  'width'    : "auto",
                  'height'   : "auto"};
    var label = document.createElement("div");
    for(var k in attrib) { label.style[k] = attrib[k]; }
    label.innerText = text;
    graph.TextRoot.appendChild(label);
    var res = MeasureText(text, fontSize);
    res.div = label;
    return res;
}

function ScaleFrom(v, start, end) { return (v - start) / (end - start);  }
function ScaleTo(v, start, end) { return v * (end - start) + start; }

function CheckNamespace(elem) {
    //return elem.tagUrn === "???";
    if(!elem.tagName) return false;
    var tagName = elem.tagName.toLowerCase();
    if((/^qvg:/i).test(tagName)) {
        return tagName.substr(4);
    } else if(elem.scopeName === "qvg") {
        return tagName;
    } else {
        return false;
    }
}

if(typeof(Qva) !== "undefined") {
    Qva.Mgr.graph = function (owner, elem, name, prefix) {
        if (!Qva.MgrSplit (this, name, prefix)) return;
        
        this.Owner = owner;
        this.Element = elem;
        this.Touched = false;
        this.Dirty = false;
        
        owner.Append (this, this.Name, 'value');
        owner.Append (this, this.Name, 'graph');
        owner.Append (this, this.Name, 'totalsize');
        
        //var type = "SVG";
        //this.G = SelectInitGraphics(type)
        this.G = SelectInitGraphics('SVG');
        //this.G = SelectInitGraphics();
        
        for(var i = 0; i < elem.childNodes.length; ++i) {
            var child = elem.childNodes[i];

            var tagName = CheckNamespace(child);
            if(!tagName) continue;
            if(tagName !== "chart") debugger;
            
            this.Graph = new Graph();
            this.Graph.xml_init(this, child);
            break;
        }
    }

    Qva.Mgr.graph.prototype.Paint = function(mode, node) {
        this.Touched = true;
        var element = this.Element;
        element.style.display = Qva.MgrGetDisplayFromMode(this, mode);
        if (element.style.display == 'none') return;

        this.Node = node;
        if(this.Graph) {
            this.Graph.xml_update(node);
            this.Graph.update();
            this.Graph.draw();
        } else {
            debugger
        }
    }
}


Factlab.CloseFunctionsForPopouts = [];

Factlab.CloseAnyPopoutControls = function() {
    var arr = Factlab.CloseFunctionsForPopouts;
    
    for (var i = 0, max = arr.length; i < max; i++) {
        arr[i]();
    }
}

Factlab.TopFilterHasSelection = false;



Factlab.LoadControlFunctions = [];

Factlab.LoadControls = function(loadKey) {
    var arr = Factlab.LoadControlFunctions;
    
    for (var i = 0, max = arr.length; i < max; i++) {
        arr[i](loadKey);
    }
}

var ICB_NumberFormatter =
{
    Defaults: {
        format: "#,###.00",
        //locale: "us",
        decimalSeparatorAlwaysShown: false
    },

    Format: function(text, options) {

        var options = jQuery.extend({}, ICB_NumberFormatter.Defaults, options);

        if (options.locale) {
            var formatData = formatCodes(options.locale.toLowerCase());

            var dec = formatData.dec;
            var group = formatData.group;
            var neg = formatData.neg;
        }
        else {
            var dec = options.dec;
            var group = options.group;
            var neg = "-";
        }

        var validFormat = "0#-,.";


        // strip all the invalid characters at the beginning and the end
        // of the format, and we'll stick them back on at the end
        // make a special case for the negative sign "-" though, so 
        // we can have formats like -$23.32
        var prefix = "";
        var negativeInFront = false;
        for (var i = 0; i < options.format.length; i++) {
            if (validFormat.indexOf(options.format.charAt(i)) == -1)
                prefix = prefix + options.format.charAt(i);
            else if (i == 0 && options.format.charAt(i) == '-') {
                negativeInFront = true;
                continue;
            }
            else
                break;
        }
        var suffix = "";
        for (var i = options.format.length - 1; i >= 0; i--) {
            if (validFormat.indexOf(options.format.charAt(i)) == -1)
                suffix = options.format.charAt(i) + suffix;
            else
                break;
        }

        options.format = options.format.substring(prefix.length);
        options.format = options.format.substring(0, options.format.length - suffix.length);


        // now we need to convert it into a number
        while (text.indexOf(group) > -1)
            text = text.replace(group, '');
        var number = new Number(text.replace(dec, ".").replace(neg, "-"));

        // special case for percentages
        if (suffix == "%")
            number = number * 100;

        var returnString = "";

        var decimalValue = number % 1;
        if (options.format.indexOf(".") > -1) {
            var decimalPortion = dec;
            var decimalFormat = options.format.substring(options.format.lastIndexOf(".") + 1);
            var decimalString = new String(decimalValue.toFixed(decimalFormat.length));
            decimalString = decimalString.substring(decimalString.lastIndexOf(".") + 1);
            for (var i = 0; i < decimalFormat.length; i++) {
                if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) != '0') {
                    decimalPortion += decimalString.charAt(i);
                    continue;
                }
                else if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) == '0') {
                    var notParsed = decimalString.substring(i);
                    if (notParsed.match('[1-9]')) {
                        decimalPortion += decimalString.charAt(i);
                        continue;
                    }
                    else {
                        break;
                    }
                }
                else if (decimalFormat.charAt(i) == "0") {
                    decimalPortion += decimalString.charAt(i);
                }
            }
            returnString += decimalPortion
        }
        else
            number = Math.round(number);

        var ones = Math.floor(number);
        if (number < 0)
            ones = Math.ceil(number);

        var onePortion = "";
        if (ones == 0) {
            onePortion = "0";
        }
        else {
            // find how many digits are in the group
            var onesFormat = "";
            if (options.format.indexOf(dec) == -1)
                onesFormat = options.format;
            else
                onesFormat = options.format.substring(0, options.format.indexOf(dec));
            var oneText = new String(Math.abs(ones));
            var groupLength = 9999;
            if (onesFormat.lastIndexOf(group) != -1)
                groupLength = onesFormat.length - onesFormat.lastIndexOf(group) - 1;
            var groupCount = 0;
            for (var i = oneText.length - 1; i > -1; i--) {
                onePortion = oneText.charAt(i) + onePortion;

                groupCount++;

                if (groupCount == groupLength && i != 0) {
                    onePortion = group + onePortion;
                    groupCount = 0;
                }

            }
        }
        returnString = onePortion + returnString;

        // handle special case where negative is in front of the invalid
        // characters
        if (number < 0 && negativeInFront && prefix.length > 0) {
            prefix = neg + prefix;
        }
        else if (number < 0) {
            returnString = neg + returnString;
        }

        if (!options.decimalSeparatorAlwaysShown) {
            if (returnString.lastIndexOf(dec) == returnString.length - 1) {
                returnString = returnString.substring(0, returnString.length - 1);
            }
        }
        returnString = prefix + returnString + suffix;

        return returnString;
    }
};

function getbookmark() {
    Qww.BookMark.Mgr.CreateBookMark(null, "MyBookMark", function(bookmarkid) {

        var x = location.protocol + "//" + location.host + location.pathname + "?bookmark=" + bookmarkid

        bookMarkCreated(x);

        // This book mark can be applied be appending it to the pages url, e.g.
        // http://thefactlab/beta3/results.htm?bookmark=" + bookmarkid;
    });
}

/**
@fileOverview
Part of the QlikView WorkBench Javascript Library <br /><br />
Copyright (c) 2009 QlikTech International AB (http://www.qliktech.com)<br /><br />
All Rights Reserved. Email support@qliktech.com for licensing and support information.<br /><br />
@author <a href="mailto:support@qlikview.com">QlikView</a>
*/

/**    
Parent namespace which holds all QlikView WorkBench related functionality.<br />
@namespace
@ignore
*/
Qww = {};
Qww.Ctls = {};

Qww.Graph = {};

/**
Constructs a new Qww.Graph.Mgr button instance.
@class JavaScript class to manage communication with an underlying QlikView chart object. Note that 
currently this chart will be read only (it will not support drag selection).<br />
@param {Object} cfg JSON object to configure ButtonMgr.
@param {String} cfg.ObjectID Id of the chart object in the QlikView document.
@param {String} [cfg.ApplicationID=null] Id/Name of the QlikView document. Note this is <strong>only</strong> necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null.
@param {Function} [cfg.OnUpdate] Function to call whenever an update is received for the chart. Should have the signature 
cfg.OnUpdate(graphMgr, caption, queryStringToChartImage). Note that the queryStringToChartImage needs to be appended to the url to the 
datapump currently being used - e.g. "QvsViewClientEx.ashx" + queryStringToChartImage.
*/
Qww.Graph.Mgr = function(cfg) {

    var _initialised = false;

    var me = this;

    /** 
    Whether the chart is enabled (visible) within the QlikView document. This can be dependent, 
    for example, upon show and hide conditions set for the object in QlikView.
    @deprecated Use Mode.
    @type Bool
    */
    this.Enabled = true;

    /** 
    The state of the object. This can be dependent, for example, upon show and hide conditions set 
    for the object in QlikView.
    @type Qww.QlikViewObjectState
    */
    this.Mode = null;

    /**
    @ignore
    Returns an array of Qww.QvsConnectorSet objects which represents the initiasation which 
    needs to be sent to QlikView server in order to initialise this object.
    @returns {Qww.QvsConnectorSet[]} Array of Qww.QvsConnectorSet objects which represents 
    the initiasation for this object.
    */
    this.GetInitialisationSets = function() {

        var sets = [];

        var objId = cfg.ObjectID;
        var appId = cfg.ApplicationID;

        sets.push(new Qww.QvsConnectorSet(appId, objId, "add", "mode;text;fixedrows;choice;pageoffset;pagesize;totalsize", false));
        sets.push(new Qww.QvsConnectorSet(appId, objId + ".Caption", "add", "mode;text", false));
        sets.push(new Qww.QvsConnectorSet(appId, objId + ".Head", "add", "mode;text", false));
        sets.push(new Qww.QvsConnectorSet(appId, objId + ".Body", "add", "mode;text", false));
        sets.push(new Qww.QvsConnectorSet(appId, objId + ".Graph", "add", "mode;text;ie6false", true));

        return sets;
    };

    function initialise() {

        //var graph = qwwHub.DoAvqSelect(cfg.ApplicationID, cfg.ObjectID);

        if (_initialised == false) {

            qwwHub.DoAllSets(me.GetInitialisationSets());

            _initialised = true;
        }
    };

    this.OnAvqUpdateComplete = function() {

        initialise();

        var node = qwwHub.DoAvqSelect(cfg.ApplicationID, cfg.ObjectID);

        if (node == null) return;

        var captionNode = jQuery("value[name=Caption]", node);

        if (captionNode.length > 0)
            var caption = captionNode[0].getAttribute("label");

        var stampNode = jQuery("value[name=Graph]", node);

        if (stampNode.length > 0)
            var stamp = stampNode[0].getAttribute("stamp");

        me.Enabled = (node.getAttribute("mode") == "enabled");
        me.Mode = node.getAttribute("mode");

        //http://cblaptop/QvAJAXZfc/QvsViewClient.asp?mark=41164352886FEB59&datamode=binary&ident=null&stamp=c0d2f64e58483dbcb7ffd788cbbac956&view=kiva&autoview=SH03&name=Document.CH08.Graph&width=978&height=217
        //http://cblaptop/QvAJAXZfc/QvsViewClient.asp?datamode=binary&stamp=c0d2f64e58483dbcb7ffd788cbbac956&view=kiva&name=Document.CH08.Graph&width=978&height=617
        //                       QvsViewClientEx.ashx?datamode=binary&stamp=4a08985cb8b08528fac835b8b48f055f&view=Entertainment&name=Document.CHRELEASESPERYEAR.Graph&width=400&height=300

        if (cfg.OnUpdate)
            cfg.OnUpdate(me, caption, "?qwwjsonwc=true&datamode=binary&stamp=" + stamp + "&view=" + cfg.View + "&name=Document." + cfg.ObjectID + ".Graph");
    }

    qwwHub.Register(this);
};

Qww.GetSummary = function(arrayOfKeys, object) {

    var s = "";

    for (var i = 0; i < arrayOfKeys.length; i++) {

        s += "<strong>" + arrayOfKeys[i] + "</strong>:" + object[arrayOfKeys[i]];

        if (i < arrayOfKeys.length - 1) s += ", ";
    }

    return s;
};

Qww.Helper = {};

Qww.Helper.GetQueryVariable = function(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split("&");
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable) {
            return pair[1];
        }
    }
    return null;
}

Qww.Helper.DoesArrayContainReference = function(arr, ref) {

    var arrLength = arr.length;
    
    for (var i = 0; i < arrLength; i++) {
        if (arr[i] == ref)
            return true;
    }

    return false;
};



/**
Represents the caption of a QlikView object (for example Chart, Table, TextBox etc.).
@class Represents the caption of a QlikView object (for example Chart, Table, TextBox etc.)<br />
*/
Qww.ObjectCaption = function() {

    /**
    Whether the caption is visible.
    @deprecated Use Mode.
    @type Bool
    */
    this.Enabled = true;

    /**
    Text for the caption.
    @type String
    */
    this.Text = "";

    /** 
    The state of the object. This can be dependent, for example, upon show and hide conditions set 
    for the object in QlikView.
    @type Qww.QlikViewObjectState
    */
    this.Mode = null;
};

Qww.ObjectCaption.prototype.ParseFromXml = function(elem) {

    var captionElem = $("value[name=Caption]", elem);

    if (captionElem.length == 1) {
        elem = captionElem[0];
        this.Enabled = (elem.getAttribute("mode") == "enabled");

        if (this.Mode != Qww.QlikViewObjectState.Hidden) {
            this.Text = elem.getAttribute("label");
        }
    }
    
//    this.Enabled = (elem.getAttribute("mode") == "enabled");

//    if (this.Mode != Qww.QlikViewObjectState.Hidden) {
//        this.Text = elem.getAttribute("label");
//    }

};

/** 
Represents the set of arguments which should be sent to QVS, for example as seen in the xml sent 
to the qvpx protocol: "<set name='object' " LHS='RHS' />"
@class
Represents the set of arguments which should be sent to QVS, for example as seen in the xml sent 
to the qvpx protocol: "<set name='object' " LHS='RHS' />"
@param {String} application Application name which the object belongs to. Can use 
null if there is only one document being connected to on the page.
@param {String} objectId Object ID of the object in the QlikView document.
@param {String} lhs Left hand side of command.
@param {String} rhs Right hand side of command.
@param {Boolean} [isFinal=false] Whether this is the final command in a set.
*/
Qww.QvsConnectorSet = function(application, objectId, lhs, rhs, isFinal) {

    this.Application = application;
    //this.Object = cfg.Application + "." + object;
    this.Object = objectId;
    this.LHS = lhs;
    this.RHS = rhs;
    this.IsFinal = (isFinal == null) ? false : isFinal;
}

/** 
Converts this logical Set command to an actual xml string to be sent to QVS.
@returns {String} XML string representing the command.
*/
Qww.QvsConnectorSet.prototype.ToXml = function() {
    return "<set name=\"" + this.Object + "\" " + this.LHS + "=\"" + this.RHS + "\" />";
}

/** 
Converts this logical Set command to a shorthand summary with : delimeters.
@param {String} lastObject The name of the last object which this method was called. When 
concatenating lots of short hand strings this allows the object ID to be omitted in all 
but the first shorthand representation allowing the string to be shorter.
@returns {String} Shorthand summary string representing the command.
*/
Qww.QvsConnectorSet.prototype.ToShortHand = function(lastObject) {

    if (lastObject == this.Object)
        return ":" + this.LHS + ":" + this.RHS;
    else
        return this.Object + ":" + this.LHS + ":" + this.RHS;
}

QwwJs = {}

//QwwJs.EnsureIdHasHash = function(id) {
//if (id.substring(0, 1) == "#")
//return id;
//else
//return "#" + id;
//};

//QwwJs.EnsureIdDoesntHaveHash = function(id) {
//if (id.substring(0, 1) == "#")
//return id.substring(1, id.length - 1);
//else
//return id;
//};

QwwJs.Alert = function(msg) {
    alert("QWW: " + msg);
};


/**
Creates a new Hub object. <strong>You should NOT create this, a single 
instance is automatically created named qwwHub.</strong>
@constructor
@class Central hub class which other controls and functionality can register with.<br />
*/
Qww.Hub = function() {

    var objectsToCallOnAvqUpdateCompleteOn = new Array();
    var objectsToCallAllOnAvqUpdateCompletesCalledOn = new Array();
    var objectsToCallOnAvqUpdateBeginOn = new Array();
    var objectsToOnDocumentLoadedOn = new Array();
    var qwwLoggerObjects = new Array();

    var allRegisteredObjects = [];

    var me = this;

    var regsiteredControls = new Array();

    this.KeepSessionAliveTimeoutInSeconds = 120;
    var dataSourceIdDictionary = {};
    var defaultApplication;

    var qvDirectConnectors = {};

    this.CustomObjectsInitialised = false;

    /** 
    Whether the Hub should start the QVS communication.
    @type Bool
    @default true
    */
    this.HubShouldStartClient = true;

    /**
    Adds a logged object to the hub whose Trace, Warn and Error methods will be called as appropriate.
    @param {Logger} logger Logger to register with the hub
    @ignore
    @example
    qwwHub.AddLogger(new MyLogger());
    */
    this.AddLogger = function(obj) {
        var arr = qwwLoggerObjects;

        if (!Qww.Helper.DoesArrayContainReference(arr, obj))
            arr[arr.length] = obj;
    };

    this.AddObjectToCallOnAvqUpdateBegin = function(obj) {
        var arr = objectsToCallOnAvqUpdateBeginOn;

        if (!Qww.Helper.DoesArrayContainReference(arr, obj))
            arr[arr.length] = obj;
    };

    this.AddObjectToCallOnAvqUpdateComplete = function(obj) {
        var arr = objectsToCallOnAvqUpdateCompleteOn;

        if (!Qww.Helper.DoesArrayContainReference(arr, obj))
            arr[arr.length] = obj;
    };

    this.AddObjectToCallOnDocumentLoadedOn = function(obj) {
        var arr = objectsToOnDocumentLoadedOn;

        if (!Qww.Helper.DoesArrayContainReference(arr, obj))
            arr[arr.length] = obj;
    };

    this.AddObjectToCallOnAllAvqUpdateCompletesCalled = function(obj) {
        var arr = objectsToCallAllOnAvqUpdateCompletesCalledOn;

        if (!Qww.Helper.DoesArrayContainReference(arr, obj))
            arr[arr.length] = obj;
    };

    /**
    Registers a JavaScript object with the hub.
    @param {Object} obj Object which implements any of the following:
    .OnAvqUpdateComplete
    .OnAvqUpdateBegin
    .OnDocumentLoaded
    @example
    
    this.OnAvqComplete = function(){alert("QVS Updated");};
    this.OnAvqUpdateBegin = function(){alert("QVS About to update");};
    this.OnDocumentLoaded = function(){alert("Document loaded");}
    
    qwwHub.Register(this);
    */
    this.Register = function(obj) {
        if (Qww.Hub.StartMode != Qww.Hub.StartModes.NoQvsClient) {
            if (obj.Cfg && obj.Cfg.ObjectID) {
                if (obj.Cfg.ApplicationID) {
                    obj.Binder = this.GetQvaFromApplicationName(obj.Cfg.ApplicationID);
                }
                else {
                    obj.Binder = this.GetQvaFromApplicationName(defaultApplication);
                }

                if (obj.Binder) {
                    new QvaMgrExternal(obj);
                }
                else {
                    //debugger;
                }
            }

            //if (obj.Binder == null) {
                if (obj.OnAllAvqUpdateCompletesCalled) {
                    this.AddObjectToCallOnAllAvqUpdateCompletesCalled(obj);
                }
            //}
        }
        else {

            if (obj.OnAvqUpdateComplete) {
                this.AddObjectToCallOnAvqUpdateComplete(obj);
            }

            if (obj.OnAllAvqUpdateCompletesCalled) {
                this.AddObjectToCallOnAllAvqUpdateCompletesCalled(obj);
            }
        }


        if (obj.OnAvqUpdateBegin)
            this.AddObjectToCallOnAvqUpdateBegin(obj);

        if (obj.OnDocumentLoaded)
            this.AddObjectToCallOnDocumentLoadedOn(obj);


        allRegisteredObjects.push(obj);

    };

    function callLoggingMethod(method, msg) {
        var arr = qwwLoggerObjects;

        var arrLength = arr.length;

        for (var j = 0; j < arrLength; j++) {

            var o = arr[j];

            if (o[method])
                o[method](msg);
        }
    };

    this.Trace = function(msg) {
        callLoggingMethod("Trace", msg);
    };

    this.Error = function(msg) {
        callLoggingMethod("Error", msg);
    };

    this.CallAllOnDocumentLoadedHandlers = function() {

        var arr = objectsToOnDocumentLoadedOn;

        var arrLength = arr.length;

        for (var j = 0; j < arrLength; j++) {
            var obj = arr[j];

            if (obj.OnDocumentLoaded)
                obj.OnDocumentLoaded();
        }
    };

    //var _isWorkBenchOnlyConnectorInBatchMode = false;

    this.CallAllOnAvqUpdateCompleteHandlers = function() {

        //        if (me.CustomObjectsInitialised == false) {
        //            //
        //            // When used in conjunction with the QvAjax???.js framework, initialising
        //            // all objects in the initial request (i.e. custom with native) the very
        //            // first update from the server didnt seem to fire the OnUpdate event meaning,
        //            // for example, that the flexi grid wouldn't paint until the first selection
        //            // had been made.
        //            //
        //            this.InitialiseCustomObjects();
        //        }

        var arr = objectsToCallOnAvqUpdateCompleteOn;

        //_isWorkBenchOnlyConnectorInBatchMode = true;

        var arrLength = arr.length;

        for (var j = 0; j < arrLength; j++) {
            var o = arr[j];

            if (o.OnAvqUpdateComplete)
                o.OnAvqUpdateComplete();
        }

        var arr = objectsToCallAllOnAvqUpdateCompletesCalledOn;

        var arrLength = arr.length;
        
        for (var j = 0; j < arrLength; j++) {
            var o = arr[j];

            if (o.OnAllAvqUpdateCompletesCalled)
                o.OnAllAvqUpdateCompletesCalled();
        }

        //        //for (var w = 0; w < qvDirectConnectors.length; w++)
        //        if (qvDirectConnectors[defaultApplication] != null)
        //            qvDirectConnectors[defaultApplication].Send();

        //_isWorkBenchOnlyConnectorInBatchMode = false;
    };


    this.CallAllOnAvqUpdateBeginHandlers = function() {
        var arr = objectsToCallOnAvqUpdateBeginOn;
        var arrLength = arr.length;

        for (var j = 0; j < arrLength; j++) {
            var o = arr[j];

            if (o.OnAvqUpdateBegin)
                o.OnAvqUpdateBegin();
        }
    };

    this.OnError = function(msg) {
        alert("QWW Error: " + msg);
        callLoggingMethod("Error", msg);
    };

    this.InitialiseCustomObjects = function() {

        var objectsWithInitialisation = [];

        var arrLength = allRegisteredObjects.length;

        for (var j = 0; j < arrLength; j++) {
            var o = allRegisteredObjects[j];

            if (o.GetInitialisationSets) {
                objectsWithInitialisation.push(o);
            }
        }

        var usingJson = this.Mode == Qww.QvsConnectorMode.CrossDomainUsingJquerygetJSON;
        var usingNativeQvsObjects = (Qww.Hub.StartMode != Qww.Hub.StartModes.NoQvsClient);

        var arrLength = objectsWithInitialisation.length;

        for (var k = 0; k < arrLength; k++) {

            var ignoreIsFinal = this.Mode != Qww.QvsConnectorMode.CrossDomainUsingJquerygetJSON;

            if (k == objectsWithInitialisation.length - 1) {
                if (usingJson == false) {
                    if (usingNativeQvsObjects == true)
                        ignoreIsFinal = true; // because Qva.Start will kick things off
                    else
                        ignoreIsFinal = false; // we want the last isFinal =  true to get sent to the server.
                }
                else {
                    ignoreIsFinal = false; // if we are using json we want the final request for each individual object to be sent.
                }
            }

            this.DoAllSets(objectsWithInitialisation[k].GetInitialisationSets(), ignoreIsFinal);
        };

        this.CustomObjectsInitialised = true;
    };

    this.Start = function() {

        this.InitialiseCustomObjects();

        if (Qww.Hub.StartMode == Qww.Hub.StartModes.NoQvsClient) {

        }
        else if (Qww.Hub.StartMode == Qww.Hub.StartModes.Pre8_5) {

            Avq.Start();

            var timoutInSeconds = this.KeepSessionAliveTimeoutInSeconds * 1;

            if (timoutInSeconds > -1)
                setInterval(function() { avqSet("", "keepalive", "true", true); }, timoutInSeconds * 1000);
        }
        else {
            if (me.HubShouldStartClient == true)
                Qva.Start();
        }
    };

    /**
    Sends through a collection of logical sets to QlikView Server.
    @param {Qww.QvsConnectorSet[]} An array of logical sets to be sent to the server.
    @param {Boolean} Whether this is the final 'set of sets' to be sent (if it is not even 
    if the last set in this batch has isFinal=true, this will be ignored.
    */
    this.DoAllSets = function(arrayOfSets, ignoreIsFinal) {

        var arrLength = arrayOfSets.length;

        for (i = 0; i < arrLength; i++) {

            var s = arrayOfSets[i];

            if (ignoreIsFinal == null || ignoreIsFinal == false) {
                this.DoAvqSet(s.Application, s.Object, s.LHS, s.RHS, s.IsFinal);
            }
            else {
                this.DoAvqSet(s.Application, s.Object, s.LHS, s.RHS, false);
            }
        }
    };

    /** 
    Sends through a set command tto QlikView Server. e.g. 
    &lt;set name="Application.Object" add="text,mode" /&gt;
    @param {String} applicationID Application which object applied to. Set to null if you are not connecting 
    to multiple documents.
    @param {String} object Object identifier which set applies to.
    @param {String} lhs Left hand side argument
    @param {String} rhs Right hand side argument
    @param {Bool} isFinal Whether to send this and any other previously Set commands
    (where isFinal was set to false) now.
    */
    this.DoAvqSet = function(applicationID, objectId, lhs, rhs, isFinal) {
        if (isFinal == null)
            isFinal = true;

        if (applicationID == null || applicationID == "null")
            applicationID = defaultApplication;

        if (Qww.Hub.StartMode == Qww.Hub.StartModes.NoQvsClient) {

            //if (_isWorkBenchOnlyConnectorInBatchMode == true) isFinal = false;

            //qvDirectConnectors[applicationID].Set(objectId, lhs, rhs, isFinal);

            //this.GetQvaFromApplicationName(applicationID).Set(objectId, lhs, rhs, isFinal);
            this.GetQvaFromApplicationName(applicationID).Set(objectId, lhs, rhs, isFinal);
        }
        else if (Qww.Hub.StartMode == Qww.Hub.StartModes.V8_5) {

            //            var dataSourceId = dataSourceIdDictionary[applicationID];

            //            var qva = Qva.GetBinder(dataSourceId);

            var qva = this.GetQvaFromApplicationName(applicationID);

            if (qva) {

                var prefix = "";

                if (objectId != null && objectId.substring(0, 9) != "Document.")
                    prefix = "Document.";

                if (objectId == "bookmark-apply") prefix = "";

                //qva.Set("Document." + objectId, lhs, rhs, isFinal);
                qva.Set(prefix + objectId, lhs, rhs, isFinal);
            }
            else
                Qww.Hub.Break(); // shouldnt be null.
        }
        else {

            var id = AvqView + "." + objectId;

            avqSet(id, lhs, rhs, isFinal);
        }
    };

    this.CreateBookMark = function(applicationID, name, onUpdate) {

        if (applicationID == null || applicationID == "null")
            applicationID = defaultApplication;

        //var dataSourceId = dataSourceIdDictionary[applicationID];

        //var qva = this.GetQvaFromDataSourceID(dataSourceId);
        var qva = this.GetQvaFromApplicationName(applicationID);

        // TODO remove cookie and scope? scope is obsolete and need more info on cookie.
        //var xml = "<update mark=\"\" stamp=\"\" cookie=\"true\" scope=\"Document\" session=\"" + qva.Session + "\" view=\"" + qva.View + "\" ident=\"new:Document.ActiveSheet.StandardActions\" kind=\"bookmark_obj\"></update>";
        var xml = "<update mark=\"\" stamp=\"\" cookie=\"true\" scope=\"Document\" view=\"" + qva.View + "\" ident=\"new:Document.ActiveSheet.StandardActions\" kind=\"bookmark_obj\"></update>";

        var dataPumpUrl = qva.Url + "?mark=&view=" + qva.View;

        $.ajax({
            type: "POST",
            url: dataPumpUrl,
            dataType: "xml",
            data: xml,
            success: function(res) {

                var id = $("value[name='Id']", res).attr("value");

                var x = "<update mark=\"" + qva.Mark + "\" stamp=\"" + qva.Stamp + "\" cookie=\"true\" scope=\"Document\" session=\"" + qva.Session + "\" view=\"" + qva.View + "\" ident=\"" + id + "\" kind=\"bookmark_obj\">";

                x += "<set name=\"Bookmark.Name\" text=\"" + name + "\"/>";
                x += "<set name=\"Bookmark.InfoText\" text=\"" + name + "\"/>";
                x += "<set name=\"Bookmark.ApplyInputFieldValues\" value=\"1\"/>";
                x += "<set name=\"Bookmark.Share\" value=\"1\"/>";
                x += "<set name=\"Bookmark.CreateFromActiveObject\" action=\"\"/>";
                x += "<set name=\"Document.Nothing\" add=\"Nothing\"/></update>";

                $.ajax({
                    type: "POST",
                    url: dataPumpUrl,
                    dataType: "xml",
                    data: x,
                    success: function(res) {

                        var bookMarkId = $("value[name='BookmarkId']", res).attr("value");

                        onUpdate(bookMarkId);

                    }
                });
            }
        });
    };

    /**
    Returns the  specified XML element from the latest set of results.
    @param {String} applicationID Application which object applied to. Set to null if you are not connecting 
    to multiple application.
    @param {String} objectId Path to the object to return from the latest results.
    */
    this.DoAvqSelect = function(applicationID, objectId) {

        if (applicationID == null || applicationID == "null")
            applicationID = defaultApplication;

        if (Qww.Hub.StartMode == Qww.Hub.StartModes.NoQvsClient) {
            //return qvDirectConnectors[applicationID].DoAvqSelect(objectId);
            return this.GetQvaFromApplicationName(applicationID).DoAvqSelect(objectId);
        }
        else if (Qww.Hub.StartMode == Qww.Hub.StartModes.V8_5) {

            //var dataSourceId = dataSourceIdDictionary[applicationID];

            //var qva = Qva.GetBinder(dataSourceId);

            var qva = this.GetQvaFromApplicationName(applicationID);

            if (qva)
                return qva.Select("Document." + objectId);
            else
                Qww.Hub.Break(); // shouldnt be null.
        }
        else
            return AvqSelect(AvqView + "." + objectId);
    };

    /** 
    This sets up a connection with a QlikView document using only the 
    QlikView WorkBench JavaScript files (in other words meaning you don't need 
    to reference any of the Qv????.js files which ship with QlikView Server. This however 
    means that you can only use the controls and features available in the QlikView WorkBench and, 
    for example, do not have access to the 'native' QlikView Server ZFC controls (listbox, table, etc.).    
    @param {Object} cfg JSON Configuration object.
    @param {String} cfg.QlikViewDocument Name of the QlikView document.
    @param {Qww.QvsConnectorMode} [cfg.Mode=Qww.QvsConnector.Mode.Direct] Connection method to use.
    @param {Functin} [cfg.OnUpdateComplete] Function to call when update is received. Accepts one 
    argument which is a reference to the new data.
    @example   
    &lt;script src="../../Javascript/QWW/jquery.js" type="text/javascript"&gt;&lt;/script&gt;
    &lt;script src="../../Javascript/QWW/QwwAllCompressed.js" type="text/javascript"&gt;&lt;/script&gt;
    
    qwwHub.RegisterWorkBenchOnlyDocument({QlikViewDocument: "Entertainment"});
    
    var myFlexiGridCtlMgr = new Qww.Ctls.FlexiGrid.Mgr(
    {   
    "ObjectID" : 'TBDEMO_RESULTS',
    "OnRenderRecord" : onRenderRecord,
    // .... Other config ...
    })
    */
    this.RegisterWorkBenchOnlyDocument = function(cfg) {

        Qww.Hub.StartMode = Qww.Hub.StartModes.NoQvsClient;

        this.Mode = cfg.Mode;

        if (defaultApplication == null)
            defaultApplication = cfg.QlikViewDocument;

        if (qvDirectConnectors[cfg.QlikViewDocument] != null) {
            Qww.Hub.Break();
        }
        else {

            var conn = new Qww.QvsConnector(cfg);

            qvDirectConnectors[cfg.QlikViewDocument] = conn;

            //            conn.Cfg.OnUpdateBegin = function(data) {
            //                me.CallAllOnAvqUpdateBeginHandlers();
            //            };

            //            conn.Cfg.OnUpdateComplete = function(data) {
            //                me.CallAllOnAvqUpdateCompleteHandlers();
            //            };

            conn.Cfg.OnUpdateBegin = me.CallAllOnAvqUpdateBeginHandlers;
            conn.Cfg.OnUpdateComplete = me.CallAllOnAvqUpdateCompleteHandlers;
        }

        return qvDirectConnectors[cfg.QlikViewDocument];
    };

    //    this.GetQvaFromDataSourceID = function(dataSourceId) {
    //        var binder = Qva.GetBinder(dataSourceId);
    //        return binder;
    //    };

    this.GetQvaFromApplicationName = function(applicationName) {

        if (applicationName == null || applicationName == "null") {
            applicationName = defaultApplication;
        }

        if (Qww.Hub.StartMode == Qww.Hub.StartModes.NoQvsClient) {
            return qvDirectConnectors[applicationName];
        }
        else if (Qww.Hub.StartMode == Qww.Hub.StartModes.V8_5) {

            var dataSourceId = dataSourceIdDictionary[applicationName];

            return Qva.GetBinder(dataSourceId);
        }
        else
            return null;
    };


    /**
    Registers a connection with a QlikView document on the server. NOTE that 
    the QvDataSource ASP.NET control calls this method with the approriate arguments. This connection 
    method depends on the  various Qv???.js files shipped with QlikView Server. See {@link Qww.Hub#RegisterWorkBenchOnlyDocument} 
    for a 'light weight' connection method    
    @param {Object} cfg JSON Configuration object.
    @param {String} cfg.QlikViewDocument Name of the QlikView document.
    @param {String} [cfg.AvqAutoview] This is an optional property which allows the 
    server to respond with only the data that is used on a single page to minimize the traffic to the client
    @param {Array} [cfg.CustomIcons] Array of custom icons expressed as an array of {IconCode:'?', ImageUrl:'?'} objects. For 
    example to override the search icon in listboxes specifiy [{IconCode:'CSE', ImageUrl:'images/search.png'}].
    @param {String} [cfg.DataPump=""QvsViewClientEx.ashx"]
    @param {Boolean} [cfg.ShowDefaultRightClickMenu=false] Whether to display the native right click menu.
    @param {Function} showMessageFunction Function to call to display messages (errors, session timeouts etc.) 
    from QlikView Server.
    */
    this.RegisterDocument = function(cfg, showMessageFunction) {

        Qww.Hub.StartMode = Qww.Hub.StartModes.V8_5;

        try {
            var qva = null;

            if (cfg.QvDataSourceID) {

                var qva = Qva.GetBinder(cfg.QvDataSourceID);

                if (qva != null)
                    return qva;

                qva = new Qva.PageBinding(cfg.QvDataSourceID);

                dataSourceIdDictionary[cfg.QlikViewDocument] = cfg.QvDataSourceID;
            }
            else
                qva = new Qva.PageBinding();

            qva.View = cfg.QlikViewDocument;
            qva.IsContained = true;

            if (defaultApplication == null)
                defaultApplication = cfg.QlikViewDocument;

            //if (cfg.AvqAutoview && cfg.AvqAutoview != '')
            qva.Autoview = cfg.AvqAutoview;

            qva.Modal = new Qva.Modal(qva);
            //qva.JSON = true;

            //
            //  Register customer icons.
            //
            if (cfg.CustomIcons != null) {
                for (var i = 0; i < cfg.CustomIcons.length; i++) {
                    var customIcon = cfg.CustomIcons[i];
                    qva.CustomIcons[customIcon.IconCode] = customIcon.ImageUrl;
                };
            };

            if (showMessageFunction)
                qva.ShowMessage = showMessageFunction;

            if (cfg.ShowDefaultRightClickMenu == null || cfg.ShowDefaultRightClickMenu == false) {
                qva.OnCreateContextMenu = function() { };
            }

            if (cfg.DebugSupport == true) {
                qva.Trace = new Qva.Trace(qva);
                qva.DeveloperMode = true;
            }

            //qva.ScriptPath = "./"
            //qva.OnUpdateComplete = function() { me.CallAllOnAvqUpdateCompleteHandlers(); }
            //            qva.OnNewResults = function() { me.CallAllOnAvqUpdateCompleteHandlers(); }

            qva.OnUpdateComplete = me.CallAllOnAvqUpdateCompleteHandlers;

            qva.OnUpdateBegin = function() { me.CallAllOnAvqUpdateBeginHandlers(); }

            //            window.onresize = function() { Qva.SetBackgroundSize(); }

            if (cfg.DataPump && cfg.DataPump != '')
                qva.Remote = cfg.DataPump;
            else
                qva.Remote = "QvsViewClientEx.ashx?QlikViewServerVersion=8_50"; // assume localhost

            new Qva.Scanner(qva);

            qva.AutoViewAppend(null, "toolbar:.StandardActions", "text;toolbar")

            return qva;
        }
        catch (e) {
            alert(e.message);
        }
    };
};

Qww.Hub.ObjectsWithEventSubscriptions = [];

Qww.Hub.Subscribe = function(obj, eventName, func) {

    var foundObj = null;

    var arrLength = Qww.Hub.ObjectsWithEventSubscriptions.length;

    for (var i = 0; i < arrLength; i++) {

        var o = Qww.Hub.ObjectsWithEventSubscriptions[i];

        if (o.Obj === obj) {
            foundObj = o;
            break;
        }
    };

    if (foundObj === null) {
        foundObj = {};
        foundObj.Subs = [];
        foundObj.Obj = obj;

        if (obj[eventName] != null) {
            foundObj.Subs.push(obj[eventName]); // the event already had a handler and we dont want to lost this..
        }

        obj[eventName] = function(a, b, c, d, e, f, g, h, j) {

            var arrLength = foundObj.Subs.length;

            for (var i = 0; i < arrLength; i++) {
                try {
                    foundObj.Subs[i](a, b, c, d, e, f, g, h, j);
                }
                catch (e) {

                }
            }
        };

        Qww.Hub.ObjectsWithEventSubscriptions.push(foundObj);
    }

    foundObj.Subs.push(func);
};

// Start Modes are used to decide what code to run in the Qww.Hub.Start method.
// The global QwwJs_Hub.StartMode defaults to Pre8_5 and will be set by the QvDataSource
// by inserting the relevant javascript if the server version is set to 8.5 or above.

/**
Enumeration containing start modes for the Qww.Hub.
@class Enumeration containing start modes for the Qww.Hub.
*/
Qww.Hub.StartModes = {

    /** 
    QlikView Server 8.2 or earlier.
    @deprecated Deprecated since QVS 8.5 released.
    @constant
    */
    Pre8_5: 'Pre8_5',

    /**
    QlikView Server 8.5 (recommended/default).
    @constant
    */
    V8_5: 'V8_5',

    /**
    This start mode means that only QlikView WorkBench client JavaScript 
    files are being used. This is only valid if QlikView Server 8.5 or later 
    is being used.
    @constant
    */
    NoQvsClient: 'NoQvsClient'
}

Qww.Hub.StartMode = Qww.Hub.StartModes.V8_5;

/**
Global singleton instance of the Qww.Hub. This is created automatically.<br />
@type Qww.Hub
*/
var qwwHub = new Qww.Hub();

Qww.Hub.Break = function() { }

$(document).ready(function() {
    //get url
    for (var id in Qva.binders) {
        if (Qva.binders[id].Remote)
            break;
    }
    // make synchronous empty call to create session cookie 
    //(only a problem if there are more than one data source which resulted in multiple sessions causing page to reconnect)
    if (Qva.binders[id].Remote) {
        $.ajax({
            url: Qva.binders[id].Remote,
            async: false
        });
    }
    qwwHub.Start();
    qwwHub.CallAllOnDocumentLoadedHandlers();

    //    if (Qww.Hub.StartMode == Qww.Hub.StartModes.NoQvsClient)
    //        qwwHub.CallAllOnAvqUpdateCompleteHandlers(); // needed to start everything moving when avq js files are not used.

});

// -------------------------------------------------------

Qww.BasicControlBase = function() {
    this.ObjectName = "NotSet";
};

Qww.BasicControlBase.prototype.Trace = function(msg) {
    qwwHub.Trace(this.ObjectName + ":" + msg);
};

Qww.BasicControlBase.prototype.Error = function(msg) {
    qwwHub.Trace(this.ObjectName + ":" + msg);
};

Qww.BasicControlBase.prototype.UserAlert = function(msg) {
    alert(this.ObjectName + ":" + msg);
};


// -------------------------------------------------------

Qww.ControlBase = function(classPrefix) {
    if(classPrefix == null)
        this.ClassPrefix = "QwwJs_ControlBase";
    else
        this.ClassPrefix = classPrefix;
};

Qww.ControlBase.prototype = new Qww.BasicControlBase();

Qww.ControlBase.prototype.GetImagePath = function(imageName) {

    var websiteRoot = "";

    if (this.Cfg.WebSiteRoot.length > 0)
        websiteRoot = this.Cfg.WebSiteRoot;
    
    return websiteRoot + "QwwStyles/" + this.Cfg.Theme + "/" + this.ClassPrefix + "/" + imageName;
};

Qww.ControlBase.prototype.GetClassNameWithThemePostfix = function(cls) {
    if (this.Cfg.Theme.length == 0)// || this.Cfg.Theme == "Default")
        return this.ClassPrefix + "-" + cls;
    else
        return this.ClassPrefix + "-" + cls + "-" + this.Cfg.Theme;
};

Qww.ControlBase.prototype.GetFullyQualifiedElementID = function(localElementId) {
    if (this.Cfg.ElementIDPrefix.length == 0)
        return "Element" + localElementId;
    else
        return this.Cfg.ElementIDPrefix + localElementId;
};

Qww.ControlBase.prototype.GetElementFromLocalId = function(localElementId) {
    if (this.Cfg.ElementIDPrefix.length == 0)
        return document.getElementById("Element" + localElementId);
    else
        return document.getElementById(this.Cfg.ElementIDPrefix + localElementId);
};

Qww.ControlBase.prototype.GE = function(localElementId) {
    return this.GetElementFromLocalId(localElementId);
};


/*
A shortcut to GetFullyQualifiedElementID adds id='' attribute as well.
*/
Qww.ControlBase.prototype.GID = function(localElementId) {
    return "id='" + this.GetFullyQualifiedElementID(localElementId) + "'";
};

/*
A shortcut to GetClassNameWithThemePostfix with class attribute also.
*/
Qww.ControlBase.prototype.GCN = function(cls) {
    return "class=\'" + this.GetClassNameWithThemePostfix(cls) + "\'";
};


Qww.ControlBase.prototype.GetElement = function(idWithOrWithoutHash) {
if (idWithOrWithoutHash.substring(0, 1) == "#")
return $(idWithOrWithoutHash)[0];
else
return document.getElementById(idWithOrWithoutHash);
};


/**
Enumeration of QlikView Object types (currently limited to only those needed by the Flexi Grid control).
@class Enumeration of QlikView Object types (currently limited to only those needed by the Flexi Grid control).<br />
*/
Qww.QlikViewObjectType = {

    /** 
    @constant
    */
    ListBox: 'ListBox',

    /** 
    @constant
    */
    Chart_Table: 'Chart_Table',

    /** 
    @constant
    */
    TableBox: 'TableBox'
};


/**
Enumeration of states which QlikView objects (or sub-objects, for example object captions) can 
be in.
@class Enumeration of states which QlikView objects (or sub-objects, for example object captions) can 
be in.<br />
*/
Qww.QlikViewObjectState = {

    /**   
    The object is visible and enabled.
    @constant
    */
    Enabled: 'enabled',

    /** 
    The object is visible and disabled.
    @constant
    */
    Disabled: 'disabled',

    /** 
    The object is hidden.
    @constant
    */
    Hidden: 'hidden'
};

/**
Enumeration of modes which can be used by the {@link Qww.QvsConnector} to connect to the QlikView Server Data Pump.
@class Enumeration of modes which can be used by the {@link Qww.QvsConnector} to connect to the QlikView Server Data Pump.<br />
*/
Qww.QvsConnectorMode = {

    /** 
    Connect directly with QlikView Server (uses jquery's ajax methods).
    @constant
    */
    Direct: 'Direct',

    /** 
    @constant
    @ignore
    */
    CrossDomainUsingJquerygetJSON: 'CrossDomainUsingJquerygetJSON'
};

QvaMgrExternal = function(mgr) {
    var cfg = mgr.Cfg;
    var objName = cfg.ObjectID;
    if (objName) {
        var binder = mgr.Binder;
        this.Name = binder.DefaultScope + "." + objName;
        this.Element = mgr;
//        binder.AddManager(this);
        binder.Append(this, this.Name, this.Attr, true);
    }
}
QvaMgrExternal.prototype.Paint = function() {
    if (this.Element.OnAvqUpdateComplete)
        this.Element.OnAvqUpdateComplete();
}


/**
@fileOverview
Part of the QlikView WorkBench Javascript Library <br /><br />
Copyright (c) 2009 QlikTech International AB (http://www.qliktech.com)<br /><br />
All Rights Reserved. Email support@qliktech.com for licensing and support information.<br /><br />
@author <a href="mailto:support@qlikview.com">QlikView</a>
*/

Qww.ListBox = {};

/** 
Creates a new Qww.ListBox.Results instance.
@constructor
@class Represents the results contained in a listbox.<br />
@returns {Qww.ListBox.Results} Qww.ListBox.Results
*/
Qww.ListBox.Results = function() {

    /**
    Array of all the items contained in the current page of the ListBox
    @type Qww.ListBox.Item[]
    */
    this.All = [];

    this.cachedResults = [];
};

Qww.ListBox.Results.prototype.getArrayOfItemsWithState = function(state) {

    if (this.cachedResults[state] == null) {

        var res = [];

        var arrLength = this.All.length;
        
        for (var i = 0; i < arrLength; i++) {

            var item = this.All[i];

            if (item.State == state) res.push(item);
        }

        this.cachedResults[state] = res;

        return res;
    }
    else
        return this.cachedResults[state];
};


/**
Returns an array of the associated items 
in the current page of data.
@type Qww.ListBox.Item[]
*/
Qww.ListBox.Results.prototype.GetAssociated = function() {
    return this.getArrayOfItemsWithState(Qww.ListBox.Mgr.ItemState.Associated);
};

/**
Returns an array of the disabled items 
in the current page of data.
@type Qww.ListBox.Item[]
*/
Qww.ListBox.Results.prototype.GetDisabled = function() {
    return this.getArrayOfItemsWithState(Qww.ListBox.Mgr.ItemState.Disabled);
};

/**
Returns an array of the selected items 
in the current page of data.
@type Qww.ListBox.Item[]
*/
Qww.ListBox.Results.prototype.GetSelected = function() {
    return this.getArrayOfItemsWithState(Qww.ListBox.Mgr.ItemState.Selected);
};


/** 
Returns a summary string showing the number of selected, disabled 
and associated items in the current page of the listbox.
@type String
*/
Qww.ListBox.Results.prototype.GetSummary = function() {

    return "Selected = " + this.GetSelected().length +
    ", Disabled = " + this.GetDisabled().length +
    ", Associated = " + this.GetAssociated().length;
};

///**
//Returns whether the current set of results is equal to the set 
//passed as a parameter.
//@param {Qww.ListBox.Results} listBoxResults Qww.ListBox.Results instance to compare.
//@type Bool
//*/
//Qww.ListBox.Results.prototype.Equals = function(listBoxResults) {

//    if (listBoxResults.All.length != this.All.length)
//        return false;

//    for (i = 0; i < this.All.length; i++)
//        if (this.All[i] != listBoxResults.All[i])
//        return false;

//    return true;
//};

/** 
Constructs a new Qww.ListBox.Item instance.
@constructor
@class Represents an item in the listbox.<br />
@returns {Qww.ListBox.Item} Qww.ListBox.Item
*/
Qww.ListBox.Item = function() {

    /** 
    The state of the listbox item (associated, selected, disabled).        
    @type Qww.ListBox.Mgr.ItemState
    */
    this.State = null;

    /** 
    Whether the listitem has the selectedexcluded=true attribue.
    @type Boolean
    */
    this.SelectedExcluded = false;

    /** 
    The underlying value of the listbox item. This should be used for selecting items by value.
    @see Qww.ListBox.Mgr#MakeSelection
    @see Qww.ListBox.Mgr#MakeSingleSelection
    @type Int
    */
    this.Value = -1;

    /** 
    The text value of the listbox item. This should be used for selecting items by text.
    @see Qww.ListBox.Mgr#MakeSelection
    @see Qww.ListBox.Mgr#MakeSingleSelection
    @type String
    */
    this.Text = "";

    /** 
    Whether the item has the locked attribute set to true.
    @type Boolean
    */
    this.Locked;

    /** 
    The frequency of the listbox item.
    @type Int
    */
    this.Frequency = -1;

    /** 
    The record number of the item. NOTE this is only currently populated when the object is created within 
    a Qww.Ctls.FlexiGrid.Mgr and passed to the OnRenderRecord method.
    @type Int
    */
    this.RecordNumber = -1;

    /** 
    ColleIf the .Text property represents a string of concatenated values (e.g. to mimic columns) then 
    this property will contain an array of cells representing these columns. NOTE that this will be empty
    UNLESS the .ParseCellsFromText method has first been called.
    @type String[]
    */
    this.Cells = [];
};

/** 
If the .Text property represents a string of concatenated values (e.g. to mimic columns) then 
this method will parse the text property and populate the .Cells property with the results.
@param {String} delimitter String to 'split' the .Text on in order to derive the .Cells collections of columns.
*/
Qww.ListBox.Item.prototype.ParseCellsFromText = function(delimitter) {

    var parts = this.Text.split(delimitter);

    this.Cells = [];

    var arrLength = parts.length;
    
    for (var x = 0; x < arrLength; x++) {
        this.Cells[x] = parts[x];
    }
};

/** 
Returns a summary string showing the main properites of the ListBoxItem.
@type String
*/
Qww.ListBox.Item.prototype.GetSummary = function() {

    return Qww.GetSummary(["State", "Value", "Text", "Frequency"], this);
};

/** 
Returns a text summary string for the item.
@type String
*/
Qww.ListBox.Item.prototype.GetSummary = function() {
    return "Text=" + this.Text + ", Value=" + this.Value + ",State=" + Qww.ListBox.Mgr.ItemState.GetStateAsString(this.State);
}

/**
Constructs a new Qww.ListBox.Mgr instance.
@constructor
@class JavaScript class to manage communication with a QlikView ListBox.<br />
@param {Object} cfg JSON object to configure ListBoxMgr.
@param {String} cfg.ObjectID Id of the ListBox in the QlikView document.
@param {String} [cfg.ApplicationID=null] Id/Name of the QlikView document. Note this is <strong>only</strong> necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null.
@param {Int} [cfg.PageSize=20] Number of rows to return in a single page of data.
@param {Bool} [cfg.DoNotInitialise=false] Set this to false if you do not want this particular object to initialise the 
underlying object with QlikView Server. Use this option for example if you are already using another object or control which 
will have already initialised this. In this mode this object will simply parse the existing data for this object as it comese from 
QlikView Server.
@param {Function} [cfg.OnUpdate] Function to call whenever the data is updated.
@returns {Qww.ListBox.Mgr} Qww.ListBox.Mgr
@example
var lbMgr = new Qww.ListBox.Mgr(
{   
ObjectID: "LBLISTBOXID", 
OnUpdate: function(listBoxMgr)
{
var s = "";
    
var allResults = listBoxMgr.Results.All;
    
for(var i = 0; i < allResults.length; i++)
{
var item = allResults[i];

s += item.GetSummary() + ", ";
}
    
$("#summary").html(listBoxMgr.Results.GetSummary() + " - " + s);
}
});
*/
Qww.ListBox.Mgr = function(cfg) {

    var applicationID = cfg.ApplicationID;
    var objectId = cfg.ObjectID;
    var pageSize = cfg.PageSize;

    var _Initialized = false;
    var me = this;

    var lastPageOffset;

    me.Results = new Qww.ListBox.Results();

    /**
    Reference to the configuration object which was used to create construct the object. This 
    allows certain properties to be updated after initial instantiation.
    @type Object
    */
    this.Cfg = cfg;

    var _hasPageSizeBeenSet = false;

    if (pageSize == null)
        pageSize = 20;

    // -------------------------------------------------
    // INTERFACE

    /**
    Clears all selections in the listbox.
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    */
    this.ClearAll = function(isFinal) {
        if (isFinal == null)
            isFinal = true;

        qwwHub.DoAvqSet(applicationID, objectId, "clear", "", isFinal);
    };

    /**
    Makes a single selection in the listbox based on a text or underlying numerical value. 
    @param {String|Int} itemValueOrText Value or Text of listbox item.
    @param {Bool} [valueIsText=false] Set to true if value is text, otherwise use false. Note using values is more 
    reliable however you must know the <em>underlying</em> value of the listbox item. 
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    */
    this.MakeSingleSelection = function(itemValueOrText, valueIsText, isFinal) {
        if (isFinal == null)
            isFinal = true;

        if (valueIsText == null)
            valueIsText = false;

        //Qww.ListBox.Mgr.MakeSingleSelection(objectId, itemValueOrText, valueIsText, isFinal);

        Qww.ListBox.Mgr.MakeSingleSelection(applicationID, objectId, itemValueOrText, valueIsText, lastPageOffset == null, this.windowsselectionstyle);
        //avqSet(objectId, "pageoffset", lastPageOffset, isFinal);

        if (lastPageOffset != null)
            qwwHub.DoAvqSet(applicationID, objectId, "pageoffset", lastPageOffset, isFinal);
    };

    /**
    Adds a selection or selections to the underlying listbox based on the array of text or underlying numerical values passed. 
    @param {String[]|Int[]} arrayOfItems Array of Value or Text items to add to selection.
    @param {Bool} [valueIsText=false] Set to true if value is text, otherwise use false. Note using values is more 
    reliable however you must know the <em>underlying</em> value of the listbox item. 
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    */
    this.AddSelection = function(arrayOfItems, valueIsText, isFinal) {

        if (isFinal == null)
            isFinal = true;

        if (valueIsText == null)
            valueIsText = false;

        Qww.ListBox.Mgr.AddSelection(applicationID, objectId, arrayOfItems, valueIsText, isFinal);

    };

    /**
    Makes a single selection in the listbox based on a text or underlying numerical value. 
    @param {String[]|Int[]} arrayOfItems Array of Value or Text items to select.
    @param {Bool} [valueIsText=false] Set to true if value is text, otherwise use false. Note using values is more 
    reliable however you must know the <em>underlying</em> value of the listbox item. 
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    */
    this.MakeSelection = function(arrayOfItems, valueIsText, isFinal) {

        if (isFinal == null)
            isFinal = true;

        if (valueIsText == null)
            valueIsText = false;

        //Qww.ListBox.Mgr.MakeSelection(applicationID, objectId, arrayOfItems, valueIsText, lastPageOffset == null);
        Qww.ListBox.Mgr.MakeSelection(applicationID, objectId, arrayOfItems, valueIsText, isFinal);

        //        if (lastPageOffset != null)
        //            qwwHub.DoAvqSet(applicationID, objectId, "pageoffset", lastPageOffset, isFinal);
    };

    /**
    Selects all items in the listbox which match the specified search string.
    @param {String} searchString Search string.
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    */
    this.SearchAndClose = function(searchString, isFinal) {
        Qww.ListBox.Mgr.SearchAndClose(applicationID, objectId, searchString, isFinal);
    };

    /**
    Sends a search to the listbox.
    @param {String} searchString Search string.
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    */
    this.Search = function(searchString, isFinal) {
        Qww.ListBox.Mgr.Search(applicationID, objectId, searchString, isFinal);
    };

    /**
    Closes a search operation on the listbox (e.g. selects matches).
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    */
    this.CloseSearch = function(isFinal) {
        Qww.ListBox.Mgr.CloseSearch(applicationID, objectId, isFinal);
    };

    /**
    Aborts a search operation on the listbox.
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    */
    this.AbortSearch = function(isFinal) {
        Qww.ListBox.Mgr.AbortSearch(applicationID, objectId, isFinal);
    };

    //    this.OnAllAvqUpdateCompletesCalled = function() {

    //        if (me.Cfg.OnUpdate) {
    //            if (me.Results.HaveUpdated == true) {
    //                me.Cfg.OnUpdate(me, me.Cfg.OnUpdateData);
    //            }
    //        }
    //    };

    this.OnAvqUpdateComplete = function() {
        me.updateResults();
    };


    function a(s) {
        alert("ListBoxMgr:" + s);
    };

    /**
    @ignore
    Returns an array of Qww.QvsConnectorSet objects which represents the initiasation which 
    needs to be sent to QlikView server in order to initialise this object.
    @returns {Qww.QvsConnectorSet[]} Array of Qww.QvsConnectorSet objects which represents 
    the initiasation for this object.
    */
    this.GetInitialisationSets = function() {

        var sets = [];

        sets.push(new Qww.QvsConnectorSet(applicationID, objectId, "add", "mode;text;pageoffset;pagesize;totalsize;fixedrows", false));
        sets.push(new Qww.QvsConnectorSet(applicationID, objectId + ".Caption", "add", "mode;text", false));
        sets.push(new Qww.QvsConnectorSet(applicationID, objectId, "pagesize", pageSize, false));
        sets.push(new Qww.QvsConnectorSet(applicationID, objectId, "pageoffset", 0, true));

        _hasPageSizeBeenSet = true;

        return sets;
    };

    this.Initialise = function(force) {
        return initialize(force);
    };

    function initialize(force) {

        if (force === undefined) {
            force = false;
        }

        var box = qwwHub.DoAvqSelect(applicationID, objectId);

        //if (box == null) {
        if ((box == null && !_hasPageSizeBeenSet) || force) {

            qwwHub.DoAllSets(me.GetInitialisationSets());

            _hasPageSizeBeenSet = true;

            return false;

            //            //<set name="Document.LBDIRECTOR" add="mode;text;pageoffset;pagesize;totalsize;fixedrows"/>
            //            //<set name="Document.LBDIRECTOR.Caption" add="mode;text"/>
            //            //<set name="Document.LBDIRECTOR" pagesize="20"/>
            //            //<set name="Document.LBDIRECTOR" pageoffset="0"/>

            //            //alert("setting "+ qualifiedId);         
            //            //avqSet(ID, "add", "text;value;choice;pagesize", false);

            //            //qwwHub.DoAvqSet(applicationID, objectId, "add", "mode;choice;label;pageoffset;pagesize;totalsizel;label", false);
            //            qwwHub.DoAvqSet(applicationID, objectId, "add", "mode;text;pageoffset;pagesize;totalsize;fixedrows", false);
            //            qwwHub.DoAvqSet(applicationID, objectId + ".Caption", "add", "mode;text", false);

            //            qwwHub.DoAvqSet(applicationID, objectId, "pagesize", pageSize, false);
            //            _hasPageSizeBeenSet = true;
            //            qwwHub.DoAvqSet(applicationID, objectId, "pageoffset", 0, true);
            //            return false;
        }
        else {
            if (!_hasPageSizeBeenSet) {
                //
                // We would come into this branch if a listbox on the page
                // had already setup this object. Here though we would override the
                // page size which had been set by the list box.
                //
                qwwHub.DoAvqSet(applicationID, objectId, "pagesize", pageSize, true);
                _hasPageSizeBeenSet = true;
            }
        }

        _Initialized = true;

        return true; // handshake - there will not be a new update
    };

    /**
    Calls a standard action on the list box (e.g. clear all, lock selections).
    @param {Qww.ListBox.Mgr.StandardAction} action Action to call    
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    @example
    lbMgr.CallAction(Qww.ListBox.Mgr.StandardAction.ClearAll, true);
    */
    this.CallAction = function(action, isFinal) {

        if (!isFinal)
            isFinal = true;

        Qww.ListBox.Mgr.CallAction(applicationID, objectId, action, isFinal);
    };

    //    /*
    //    Sets the value of the input field. (Only applicable if listbox is setup to show input field value).
    //    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    //    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    //    be sent in one request.
    //    */
    //    this.SetInputField = function(columnIndex, rowIndex, value, isFinal) {

    //        if (isFinal == null)
    //            isFinal = true;

    //        qwwHub.DoAvqSet(applicationID, objectId, "inputvalue", columnIndex + ":" + rowIndex + ":" + value, isFinal);
    //    };


    /**
    The .SelectSingleRecord method of the Qww.Ctls.FlexiGrid.Mgr delegates to this method when 
    a ListBoxMgr is being used as a dataprovider for the flexi grid. This simply calls through to 
    the .SelectSingleRecord method.
    @ignore
    */
    this.SelectSingleRecord = function(val) {
        me.MakeSingleSelection(val, false, true);
    };

    /**
    Set of results for current page of data which the ListBoxMgr is showing.
    @type Qww.ListBox.Results
    */
    this.Results = new Qww.ListBox.Results();

    me.Results.HaveUpdated = true;

    /**
    Returns the current page number which the ListBoxMgr holds data for.
    @property
    @type Int
    */
    this.CurrentPage = 1;

    /** 
    Number of items per page of data received for the listbox.
    @type Int
    */
    this.PageSize = -1;

    /** 
    Number of results for current unclosed search. This will be -1 if a search 
    is not currently being performed.
    @type Int
    */
    this.NumberOfSearchMatches = -1;

    /** 
    The offset of the current page of data.
    @type Int
    */
    this.PageOffset = -1;

    /** 
    This value increments (seems by 2 each time?) every time the state of 
    the underlying listbox changes and will remain the same if you are simple 
    requesting different pages/pageoffsets for the ListBox in a given state.
    @type Int
    */
    this.Stamp = -1;

    /** 
    Total number of items in the listbox.
    @type Int
    */
    this.TotalSize = -1;

    /** 
    The state of the object. This can be dependent, for example, upon show and hide conditions set 
    for the object in QlikView.
    @type Qww.QlikViewObjectState
    */
    this.Mode = "";

    /** 
    Whether the listbox is enabled (visible) within the QlikView document. This can be dependent, 
    for example, upon show and hide conditions set for the object in QlikView.
    @deprecated You should now use Mode.
    @type Bool
    */
    this.Enabled = true;

    /** 
    The number of columns the listbox is configured with.
    @type Number
    */
    this.NumberOfColumns = 1;

    //    /** 
    //    Current Title/Caption of the listbox control.
    //    @type String
    //    */
    //    this.Title = "";

    /** 
    Number of pages of data for the listbox.
    @type Int
    */
    this.NoPages = me.TotalSize / me.PageSize;

    /** 
    Caption for text object.
    @type Qww.ObjectCaption
    */
    this.Caption = new Qww.ObjectCaption();

    /** 
    Moves to the next page of data in the listbox.
    @returns {Bool} Returns true if the page was changed (if the listbox 
    was already set to the last page then false will be returned).
    */
    this.PageDown = function() {

        if (me.CurrentPage > 1) {
            me.SetPage(me.CurrentPage - 1);
            return true;
        }
        else {
            return false;
        }
    };

    /** 
    Moves to the previous page of data in the listbox.
    @returns {Bool} Returns true if the page was changed (if the listbox 
    was already set to the first page then false will be returned).
    */
    this.PageUp = function() {

        if (me.CurrentPage < me.NoPages) {
            me.SetPage(me.CurrentPage + 1);
            return true;
        }
        else {
            return false;
        }
    };

    /** 
    Moves to the page number specified.
    @param {Int} pageNumber Page number to move to.
    */
    this.SetPage = function(pageNumber) {

        me.CurrentPage = pageNumber;

        newOffset = ((pageNumber * 1 - 1) * pageSize);
        //newOffset = ((pageNumber * 1) * pageSize);

        lastPageOffset = newOffset;

        qwwHub.DoAvqSet(applicationID, objectId, "pageoffset", newOffset, true);
    };

    /** 
    Moves to the page offset specified.
    @param {Int} Page offset to move to.
    */
    this.SetPageOffset = function(pageOffset) {

        //        me.CurrentPage = pageNumber;

        //        newOffset = ((pageNumber * 1 - 1) * pageSize);

        lastPageOffset = pageOffset;

        qwwHub.DoAvqSet(applicationID, objectId, "pageoffset", pageOffset, true);
    };

    this.updateResults = function() {

        var previousResults = me.Results;

        me.Results.HaveUpdated = false;

        if (!cfg.DoNotInitialise || cfg.DoNotInitialise == false) {
            if (!_Initialized) {
                if (!initialize()) {
                    return;
                }
            }
        }

        var CH = qwwHub.DoAvqSelect(applicationID, objectId);

        if (CH == null) {
            // This might be called as the result of an OnAvqUpdateComplete
            // which might be for an unrelated table or lisbox, in which case
            // the XML wont contain that for XH
            return;
        }
        //TODO: Check what this is for.
        //        if (CH.getElementsByTagName("value").length == 0) {
        //            // the XML don't contain any changed data for the control
        //            return;
        //        }

        me.Results = new Qww.ListBox.Results();
        me.Results.HaveUpdated = true;

        this.Mode = CH.getAttribute("mode");
        this.Enabled = (this.Mode == "enabled");

        if (this.Enabled == true) {

            this.Caption.ParseFromXml(CH);

            me.PageSize = CH.getAttribute("pagesize") * 1;
            me.PageOffset = (CH.getAttribute("pageoffset") * 1); // +1;
            me.TotalSize = CH.getAttribute("totalsize") * 1;

            me.Stamp = (1 * CH.getAttribute("stamp"));

            me.windowsselectionstyle = (CH.getAttribute("windowsselectionstyle") == "true");

            var matches = CH.getAttribute("numberofmatches");

            if (matches == null) {
                me.NumberOfSearchMatches = -1;
            }
            else {
                me.NumberOfSearchMatches = matches * 1;
            }

            //me.CurrentPage = Math.floor((me.PageOffset - 1) / me.PageSize) + 1;
            me.CurrentPage = Math.floor((me.PageOffset) / me.PageSize) + 1;

            //me.Name = CH.getAttribute("name");        

            var searchable = CH.getAttribute("searchable") * 1;

            me.NoPages = me.TotalSize / me.PageSize;
            me.NoPages = Math.round(me.NoPages + 0.49);

            var all = me.Results.All;

            var obj = $("choice", CH);

            var responseIsJson = false;

            if (obj.length > 0) {
                var vals = obj[0].childNodes;
                me.NumberOfColumns = 1;
            }
            else {
                var vals = $("element", CH);

                if (vals.length == 0) {
                    vals = $("json", CH);

                    if (vals.length > 0)
                        responseIsJson = true;
                }

                me.NumberOfColumns = 0;

                var cols = $("value", CH);

                var arrLength = cols.length;

                for (var i = 0; i < arrLength; i++) {
                    if (cols[i].getAttribute("name") != 'Caption') {
                        me.NumberOfColumns++;
                    }
                }
            }

            var noDummyItems = 0; // if columns are used the last few items might be empty.

            var index = 0;

            if (responseIsJson) {
                vals = eval("([" + vals[0].text + "])")
            }

            var arrLength = vals.length;

            for (var i = 0; i < arrLength; i++) {

                var node = vals[i];

                var newItem = Qww.ListBox.Mgr.GetListItemFromNode(node, responseIsJson);

                if (newItem.Value == -1) {
                    noDummyItems++;
                    continue;
                }
                else {
                    all[index++] = newItem;
                }
            }

            me.TotalSize = (me.NumberOfColumns * me.TotalSize) - noDummyItems;
        }

        //        if (previousResults != null && previousResults.Equals)
        //            me.Results.HaveUpdated = !previousResults.Equals(me.Results);

        me.Results.HaveUpdated = true;

        if (me.Cfg.OnUpdate) {
            if (me.Results.HaveUpdated == true) {
                me.Cfg.OnUpdate(me, me.Cfg.OnUpdateData);
            }
        }
    };

    if (qwwHub)
        qwwHub.Register(this);
};

/**
Returns a html string summary of the main properties of the TableMgr.
*/
Qww.ListBox.Mgr.prototype.GetSummary = function() {

    return "Caption:" + this.Caption.Text + "," + Qww.GetSummary([/*"Text",*/"Enabled", "TotalSize", "PageOffset", "PageSize"
    /*"NoRows", "CurrentPage", "NoPages", "InitialTotalSize",
    "InitialNoPages", "HeaderRowPresent"*/], this);
};

/**
Makes a selection in the listbox based on the array of text or underlying numerical values passed. 
@param {String} applicationId Id/Name of the QlikView document <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.
@param {String} objectID Id of the ListBox in the QlikView document.
@param {String[]|Int[]} arrayOfItems Array of Value or Text items to select.
@param {Bool} [optionalUseText=false] Set to true if value is text, otherwise use false. Note using values is more 
@param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
Set this to false if you intend to call some methods on other objects and would like all the commands to 
be sent in one request.
*/
Qww.ListBox.Mgr.MakeSelection = function(applicationID, objectId, arrayOfItems, optionalUseText, isFinal) {

    if (isFinal == null)
        isFinal = true;

    var mode = "value";

    if (optionalUseText) {
        if (!this.windowsselectionstyle)
            qwwHub.DoAvqSet(applicationID, objectId, "clear", "", true);
        mode = "text";
    }
    else
        if (!this.windowsselectionstyle)
            qwwHub.DoAvqSet(applicationID, objectId, "clear", "", false);

    var arrLength = arrayOfItems.length;
    
    for (var i = 0; i < arrLength; i++) {
        var isActuallyFinal = (isFinal && (i == (arrLength - 1)));

        qwwHub.DoAvqSet(applicationID, objectId, mode, arrayOfItems[i], isActuallyFinal);
    }
}

/**
Adds a selection or selections to the underlying listbox based on the array of text or underlying numerical values passed. 
@param {String} applicationId Id/Name of the QlikView document <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.
@param {String} objectID Id of the ListBox in the QlikView document.
@param {String[]|Int[]} arrayOfItems Array of Value or Text items to additionally select.
@param {Bool} [optionalUseText=false] Set to true if value is text, otherwise use false. Note using values is more 
@param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
Set this to false if you intend to call some methods on other objects and would like all the commands to 
be sent in one request.
*/
Qww.ListBox.Mgr.AddSelection = function(applicationID, objectId, arrayOfItems, optionalUseText, isFinal) {

    if (isFinal == null)
        isFinal = true;

    var mode = "value";

    if (optionalUseText) {
        mode = "text";
    }

    var arrLength = arrayOfItems.length;

    for (var i = 0; i < arrLength; i++) {
    
        var isActuallyFinal = (isFinal && (i == (arrLength - 1)));

        qwwHub.DoAvqSet(applicationID, objectId, mode, arrayOfItems[i], isActuallyFinal);
    }
}

/**
Makes a single selection in the listbox based on a text or underlying numerical value. 
@param {String} applicationId Id/Name of the QlikView document <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.
@param {String} objectID Id of the ListBox in the QlikView document.
@param {String|Int} itemValueOrText Value or Text of item to select.
@param {Bool} [optionalUseText=false] Set to true if value is text, otherwise use false. Note using values is more 
reliable however you must know the <em>underlying</em> value of the listbox item. 
@param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
Set this to false if you intend to call some methods on other objects and would like all the commands to 
be sent in one request.
*/
Qww.ListBox.Mgr.MakeSingleSelection = function(applicationID, objectId, itemValueOrText, optionalUseText, isFinal, windowsselectionstyle) {
    if (isFinal == null)
        isFinal = true;

    if (itemValueOrText == null) {
        qwwHub.DoAvqSet(applicationID, objectId, "clear", "", isFinal);
    }
    else {
        if (optionalUseText) {
            if (!windowsselectionstyle)
                qwwHub.DoAvqSet(applicationID, objectId, "clear", "", true); // in text mode seems we must send clear through separately.
            qwwHub.DoAvqSet(applicationID, objectId, "text", itemValueOrText, isFinal);
        }
        else {
            if (!windowsselectionstyle)
                qwwHub.DoAvqSet(applicationID, objectId, "clear", "", false);
            qwwHub.DoAvqSet(applicationID, objectId, "value", itemValueOrText, isFinal);
        }
    }
};

/** 
@class Enumeration representing the state which each item in the listbox can be in.<br />
*/
Qww.ListBox.Mgr.ItemState = {

    /**
    Item is associated.
    @constant
    */
    Associated: 0,

    /**
    Item is disabled.
    @constant
    */
    Disabled: 1,

    /**
    Item is selected.
    @constant
    */
    Selected: 2
};

/**
Returns a string representation of the state.
@param {Int|Qww.ListBox.Mgr.ItemState} state State value to get string represenation for.
@returns {String} String representation of the state.
*/
Qww.ListBox.Mgr.ItemState.GetStateAsString = function(state) {

    if (state == 0)
        return "Associated";

    if (state == 1)
        return "Disabled";

    if (state == 2)
        return "Selected";

    return "Unknown";
};

/**
Enumeration of standard actions which can be called on a listbox.
@class Enumeration of standard actions which can be called on a listbox.<br />
@see Qww.ListBox.Mgr#CallAction
@example
Qww.ListBox.Mgr.CallAction(null, 'LBID', Qww.ListBox.Mgr.StandardAction.ClearAll);
*/
Qww.ListBox.Mgr.StandardAction = {

    /** 
    @ignore
    @constant
    */
    Minimize: 'MI',

    /** 
    @ignore
    @constant
    */
    Restore: 'RE',

    /** 
    @ignore
    @constant
    */
    Print: 'PR',

    /** 
    @ignore
    @constant
    */
    SendToExcel: 'XL',

    /** 
    Clear all selections in the listbox.
    @constant
    */
    ClearAll: 'CA',

    /** 
    @ignore
    @constant
    */
    Compare: 'CO',

    /** 
    Select all items in the listbox.
    @constant
    */
    SelectAll: 'SA',

    /** 
    Select all currently excluded items (invert selection).
    @constant
    */
    SelectExcluded: 'SE',

    /** 
    Select all possible items.
    @constant
    */
    SelectPossible: 'SP',

    /** 
    Lock the current selections.
    @constant
    */
    LockSelection: 'LS',

    /** 
    UnLock the current selections.
    @constant
    */
    UnlockSelection: 'US'
};

/**
Calls a standard action on the list box (e.g. clear all, lock selections).
@param {String} applicationId Id/Name of the QlikView document <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.
@param {String} objectID Id of the ListBox in the QlikView document.
@param {Qww.ListBox.Mgr.StandardAction} action Action to call    
@param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
Set this to false if you intend to call some methods on other objects and would like all the commands to 
be sent in one request.
@example
Qww.ListBox.Mgr.CallAction(null, 'LBID', Qww.ListBox.Mgr.StandardAction.ClearAll);
*/
Qww.ListBox.Mgr.CallAction = function(applicationID, listBoxId, action, isFinal) {

    if (isFinal == null)
        isFinal = true;

    if (Qww.Hub.StartMode == Qww.Hub.StartModes.Pre8_5)
        qwwHub.DoAvqSet(applicationID, listBoxId + ".Caption." + action, "action", "", isFinal);
    else
        qwwHub.DoAvqSet(applicationID, Qww.ListBox.Mgr.CommandPrefix + listBoxId + "." + action, "action", "", isFinal);

};

/**
Sends a search to the listbox.
@param {String} applicationId Id/Name of the QlikView document <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.
@param {String} objectID Id of the ListBox in the QlikView document.
@param {String} searchString Search string.
@param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
Set this to false if you intend to call some methods on other objects and would like all the commands to 
be sent in one request.
*/
Qww.ListBox.Mgr.Search = function(applicationID, objectId, searchString, isFinal) {
    
    if (isFinal == null)
        isFinal = true;

    searchString = searchString.toString().replace(/>/g, "&gt;");
    searchString = searchString.toString().replace(/</g, "&lt;");

    qwwHub.DoAvqSet(applicationID, Qww.ListBox.Mgr.CommandPrefix + objectId + ".Caption", "pageoffset", "0", false);
    qwwHub.DoAvqSet(applicationID, Qww.ListBox.Mgr.CommandPrefix + objectId + ".Caption", "search", searchString, isFinal);
    //qwwHub.DoAvqSet(applicationID, Qww.ListBox.Mgr.CommandPrefix + objectId + ".Caption", "closesearch", "accept", isFinal);
};

/**
Selects all items in the listbox which match the specified search string.
@param {String} applicationId Id/Name of the QlikView document <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.
@param {String} objectID Id of the ListBox in the QlikView document.
@param {String} searchString Search string.
@param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
Set this to false if you intend to call some methods on other objects and would like all the commands to 
be sent in one request.
*/
Qww.ListBox.Mgr.SearchAndClose = function(applicationID, objectId, searchString, isFinal) {
    if (isFinal == null)
        isFinal = true;

    searchString = searchString.toString().replace(/>/g, "&gt;");
    searchString = searchString.toString().replace(/</g, "&lt;");

    qwwHub.DoAvqSet(applicationID, Qww.ListBox.Mgr.CommandPrefix + objectId + ".Caption", "search", searchString, false);
    qwwHub.DoAvqSet(applicationID, Qww.ListBox.Mgr.CommandPrefix + objectId + ".Caption", "closesearch", "accept", isFinal);
};

/**
Closes a search operation on the listbox (e.g. selects matches).
@param {String} applicationId Id/Name of the QlikView document <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.
@param {String} objectID Id of the ListBox in the QlikView document.
@param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
Set this to false if you intend to call some methods on other objects and would like all the commands to 
be sent in one request.
*/
Qww.ListBox.Mgr.CloseSearch = function(applicationID, objectId, isFinal) {

    if (isFinal == null)
        isFinal = true;

    qwwHub.DoAvqSet(applicationID, Qww.ListBox.Mgr.CommandPrefix + objectId + ".Caption", "closesearch", "accept", isFinal);
};

/**
Aborts a search operation on the listbox.
@param {String} applicationId Id/Name of the QlikView document <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.
@param {String} objectID Id of the ListBox in the QlikView document.
@param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
Set this to false if you intend to call some methods on other objects and would like all the commands to 
be sent in one request.
*/
Qww.ListBox.Mgr.AbortSearch = function(applicationID, objectId, isFinal) {

    if (isFinal == null)
        isFinal = true;

    qwwHub.DoAvqSet(applicationID, Qww.ListBox.Mgr.CommandPrefix + objectId + ".Caption", "closesearch", "abort", isFinal);
};


Qww.ListBox.Mgr.CommandPrefix = 'Document.';

Qww.ListBox.Mgr.GetListItemFromNode = function(node, responseIsJson) {

    var newItem = new Qww.ListBox.Item();

    if (responseIsJson == null || responseIsJson == false) {

        newItem.Value = node.getAttribute("value") * 1;

        if (newItem.Value > -1) {

            newItem.Text = node.getAttribute("title") ? node.getAttribute("title") : node.getAttribute("text");
            newItem.Frequency = node.getAttribute("frequency");

            newItem.Locked = (node.getAttribute("locked") == "yes");

            if (node.getAttribute("selected") != null && node.getAttribute("selected") != "no") //selected
                newItem.State = Qww.ListBox.Mgr.ItemState.Selected;
            else if (node.getAttribute("mode") == "disabled") //excluded
                newItem.State = Qww.ListBox.Mgr.ItemState.Disabled;
            else //associated
                newItem.State = Qww.ListBox.Mgr.ItemState.Associated;

            if (node.getAttribute("selectedexcluded") != null && node.getAttribute("selectedexcluded") != "no") //selectedexcluded
                newItem.SelectedExcluded = true;
            else
                newItem.SelectedExcluded = false;

        }
    }
    else {
        //
        // Experimental code to deserialise a node from a known Json structure.
        //
        newItem.Value = node[0];

        if (newItem.Value > -1) {

            newItem.Text = node[1];
            newItem.Frequency = node[2];

            if (node[3] != null && node[3] != "no") //selected
                newItem.State = Qww.ListBox.Mgr.ItemState.Selected;
            else if (node[4] == "disabled") //excluded
                newItem.State = Qww.ListBox.Mgr.ItemState.Disabled;
            else //associated
                newItem.State = Qww.ListBox.Mgr.ItemState.Associated;
        }
    }

    return newItem;
}

/**
@fileOverview
Part of the QlikView WorkBench Javascript Library <br /><br />
Copyright (c) 2009 QlikTech International AB (http://www.qliktech.com)<br /><br />
All Rights Reserved. Email support@qliktech.com for licensing and support information.<br /><br />
@author <a href="mailto:support@qlikview.com">QlikView</a>
*/

Qww.Table = {};

/** 
Constructs a new Qww.Table.Header instance.
@class Represents a table header.<br />
*/
Qww.Table.Header = function() {

    /**
    Text for the column header.
    @type String
    */
    this.HeaderText = "";

    /**
    Index of the column header within the TableMgr.
    @type Int
    */
    this.HeaderIndex = -1;

    /**
    Index of the column header within the QlikView table. Use this when calling Qww.Table.Mgr.Sort.
    @see Qww.Table.Mgr.Sort
    @type Int
    */
    this.HeaderSortIndex = -1;

    /**
    @ignore
    */
    this.HeaderSortKey = "";

    /**
    Direction which the column is sorted in.
    @type Qww.Table.Header.SortDirection
    */
    this.SortDirection = null;

    /**
    Sort order for the column.
    @type Int
    */
    this.SortOrder = -1;

};

Qww.Table.Header.prototype.GetSummary = function() {

    return "HeaderText:" + this.HeaderText +
        ",HeaderIndex:" + this.HeaderIndex +
        ",HeaderSortIndex:" + this.HeaderSortIndex +
        ",HeaderSortKey:" + this.HeaderSortKey +
        ",SortDirection:" + this.SortDirection +
        ",SortOrder:" + this.SortOrder;
};

/** 
@class Enumeration representing the direction in which a table column is sorted.<br />
*/
Qww.Table.Header.SortDirection = {

    /**
    @constant
    */
    Ascending: "ASI",

    /**
    @constant
    */
    Descending: "DSI",

    /**
    @constant
    */
    Unsorted: "Unsorted"
};

/**
Constructs a new Qww.Table.Row instance.
@class Represents a row of data in the table.<br />
*/
Qww.Table.Row = function() {

    /** 
    Returns whether the row is a header row.
    @type Bool        
    */
    this.IsHeader = false;

    /** 
    Record number for the row.
    @type Int
    @see Qww.Table.Mgr#SelectSingleRecord
    */
    this.RecordNumber = -1;

    /** 
    Array of Qww.Table.Cell objects for the row.<br />
    @type Qww.Table.Cell[]
    */
    this.Cells = [];
};

/**
Returns a summary string of the row.
*/
Qww.Table.Row.prototype.GetSummary = function() {

    var res = "IsHeader:" + this.IsHeader + ",RecordNumber:" + this.RecordNumber + "(Data:";

    for (var i = 0; i < this.Cells.length; i++)
        res += "," + this.Cells[i].Text;

    return res;
};

/**
Constructs a new Qww.Table.Cell instance.
@class Represents a cell within a row of data in the table.<br />
*/
Qww.Table.Cell = function() {

    /**
    Text value of the cell.
    @type String
    */
    this.Text = "";

    //rowItem.Style = elem.getAttribute("style");
    //rowItem.IsNumber = elem.getAttribute("isnum");
    //rowItem.SelectType = elem.getAttribute("selecttype");

};

/** 
Constructs a new Qww.Table.Mgr instance.
@constructor
@class Class to manage communication with a QlikView straight table or table control.<br />
@param {Object} cfg JSON object to configure Qww.Table.Mgr.
@param {String} cfg.ObjectID Id of the table in the QlikView document.
@param {String} [cfg.ApplicationID=null] Id/Name of the QlikView document. Note this is <strong>only</strong> necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null.
@param {Int} [cfg.PageSize=50] Number of rows to return in a single page of data.
@param {Bool} [cfg.DoNotInitialise=false] Set this to false if you do not want this particular object to initialise the 
underlying object with QlikView Server. Use this option for example if you are already using another object or control which 
will have already initialised this. In this mode this object will simply parse the existing data for this object as it comese from 
QlikView Server.
@param {Function} [cfg.OnUpdate] Function to call whenever the data is updated.
@returns {Qww.Table.Mgr} Qww.Table.Mgr
@example
var tblMgr = new Qww.Table.Mgr(
{
// ObjectID of the underlying Table Box 
// in QlikView
ObjectID: "TBDEMO_RESULTS",
// The number of results to download for 
// each page.
PageSize: 30,
// Function to call whenever the data updates.
OnUpdate: showResults
});
*/
Qww.Table.Mgr = function(cfg) {

    var _isInitialized = false;
    var me = this;

    /**
    Reference to the configuration object which was used to create construct the object. This 
    allows certain properties to be updated after initial instantiation.
    @type Object
    */
    this.Cfg = cfg;

    function a(s) {
        QwwJs.Alert("QwwJs_TableMgr:" + s);
    };

    if (!cfg)
        a("No cfgObject specified");

    var pageSize = 50;

    if (cfg.PageSize)
        pageSize = cfg.PageSize;

    if (cfg.ObjectID) {
        var objId = cfg.ObjectID;
    }
    else {
        a("No objectId specified");
        return;
    };

    var applicationId = cfg.ApplicationID;

    this.colsOfResults = new Array();
    this.rowsOfResults = new Array();

    /**
    Collection of header columns for the table.
    @type Qww.Table.Header[]
    */
    this.Headers = new Array();

    this.SupportsSorting = true;

    /** 
    Whether the table is enabled (visible) within the QlikView document. This can be dependent, 
    for example, upon show and hide conditions set for the object in QlikView.
    @deprecated Use Mode.
    @type Bool
    */
    this.Enabled = true;

    /** 
    The state of the object. This can be dependent, for example, upon show and hide conditions set 
    for the object in QlikView.
    @type Qww.QlikViewObjectState
    */
    this.Mode = "";

    /** 
    Total number of rows in the table.
    @type Int
    */
    this.TotalSize = -1;

    /** 
    Page offset of the current page of data.
    @type Int
    */
    this.PageOffset = -1;

    /** 
    Number of rows per page of data received for the table.
    @type Int
    */
    this.PageSize = -1;

    /** 
    Number of rows in the current page of data (note that it may be less than the PageSize if it's the last page of data).
    @type Int
    */
    this.NoRows = -1;


    //    /** 
    //    Current Title/Caption of the table control.
    //    @type String
    //    */
    //    this.Title = "";

    /** 
    Caption for text object.
    @type Qww.ObjectCaption
    */
    this.Caption = new Qww.ObjectCaption();

    /** 
    Number of rows in the current page of data (note that it may be less than the PageSize if it's the last page of data).
    @type Int
    */
    this.NoPages = -1;

    this.HeaderRowPresent = false;

    /**
    Returns the current page number which the TableMgr holds data for.
    @property
    @type Int
    */
    this.CurrentPage = 1;

    this.InitialTotalSize = -1;
    this.InitialNoPages = -1;

    var hasThisTableInitialised = false;

    /**
    @ignore
    Returns an array of Qww.QvsConnectorSet objects which represents the initiasation which 
    needs to be sent to QlikView server in order to initialise this object.
    @returns {Qww.QvsConnectorSet[]} Array of Qww.QvsConnectorSet objects which represents 
    the initiasation for this object.
    */
    this.GetInitialisationSets = function() {

        var sets = [];

        sets.push(new Qww.QvsConnectorSet(applicationId, objId, "add", "mode;text;fixedrows;choice;pageoffset;pagesize;totalsize", false));
        sets.push(new Qww.QvsConnectorSet(applicationId, objId + ".Caption", "add", "mode;text", false));
        sets.push(new Qww.QvsConnectorSet(applicationId, objId + ".Head", "add", "mode;text", false));
        sets.push(new Qww.QvsConnectorSet(applicationId, objId, "pagesize", pageSize, false));
        sets.push(new Qww.QvsConnectorSet(applicationId, objId, "pageoffset", 0, true));

        hasThisTableInitialised = true;

        return sets;
    };

    this.Initialise = function() {

        var box = qwwHub.DoAvqSelect(applicationId, objId);

        // if(box == null)
        //
        // The hasThisTableInitialised test was added because if there was, for example, 
        // an export for print button added to the page for the same table, then this would
        // already have been initialised but not with any columns so not data would ever come 
        // back
        //
        if (box == null && hasThisTableInitialised == false) {

            //<set name="Document.TB01" add="mode;text;fixedrows;choice;pageoffset;pagesize;totalsize"/>
            //<set name="Document.TB01.Caption" add="mode;text"/>
            //<set name="Document.TB01.Head" add="mode;text"/>
            //<set name="Document.TB01.RE" add="mode;action;ie6false"/>
            //<set name="Document.TB01" pagesize="20"/>
            //<set name="Document.TB01" pageoffset="0"/>

            qwwHub.DoAllSets(me.GetInitialisationSets());

            //            // qwwHub.DoAvqSet(applicationId, objId, "add", "mode;pageoffset;pagesize;totalsize", false);
            //            qwwHub.DoAvqSet(applicationId, objId, "add", "mode;text;fixedrows;choice;pageoffset;pagesize;totalsize", false);

            //            qwwHub.DoAvqSet(applicationId, objId + ".Caption", "add", "mode;text", false);
            //            qwwHub.DoAvqSet(applicationId, objId + ".Head", "add", "mode;text", false);

            //            // <set name="Document.TB01.RE" add="mode;action;ie6false"/><
            //            // qwwHub.DoAvqSet(applicationId, objId + ".RE", "add", "mode;action;ie6false", false);

            //            //            if (cfg.ColumnIndexes)
            //            //                for (var i = 0; i < cfg.ColumnIndexes.length; i++)
            //            //                    qwwHub.DoAvqSet(applicationId, objId + ".C" + cfg.ColumnIndexes[i], "add", "mode;text;value", false);

            //            qwwHub.DoAvqSet(applicationId, objId, "pagesize", pageSize, false);
            //            qwwHub.DoAvqSet(applicationId, objId, "pageoffset", 0, true);

            hasThisTableInitialised = true;
            return false;
        }

        _isInitialized = true;
        hasThisTableInitialised = true;

        return true; // handshake - there will not be a new update
    };

    /**
    Selects a single row and column in the table.
    @param {Int} columnIndex Column index of input field.
    @param {Int} rowIndex Row index of input field.
    @param {String|Number} value Value to set input field to.
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    */
    this.SetInputField = function(columnIndex, rowIndex, value, isFinal) {

        if (isFinal == null)
            isFinal = true;

        rowIndex = rowIndex + 1;

        qwwHub.DoAvqSet(applicationId, objId, "inputvalue", columnIndex + ":" + rowIndex + ":" + value, isFinal);
    };

    /**
    Selects a single row and column in the table. Note the .SelectSingleRecord method of the Qww.Ctls.FlexiGrid.Mgr 
    delegates to this method when a TableMgr is being used as a dataprovider for the flexi grid. 
    @param {Int} recordNumber Record number to select.
    @param {Int} [selectColumn=0] Column to select.
    */
    this.SelectSingleRecord = function(recordNumber, selectColumn) {

        if (!selectColumn)
            selectColumn = 0;

        qwwHub.DoAvqSet(applicationId, objId, "rect", selectColumn + ":" + recordNumber + ":1:1", true);
    };

    /** 
    Moves to the page number specified. Note that the first page is 1.
    @param {Int} pageNumber Page number to move to.
    */
    this.SetPage = function(pageNumber) {

        var newOffset;

        this.CurrentPage = pageNumber;

        newOffset = ((pageNumber * 1 - 1) * this.PageSize);

        qwwHub.DoAvqSet(applicationId, objId, "pageoffset", newOffset, true);
    };

    /** 
    Moves to the previous page of data in the table.
    @returns {Bool} Returns true if the page was changed (if the table 
    was already set to the first page then false will be returned).
    */
    this.PageUp = function() {
        if (me.CurrentPage < me.NoPages) {
            this.SetPage(this.CurrentPage + 1);
            return true;
        }
        else {
            return false;
        }
    };

    /** 
    Moves to the next page of data in the table.
    @returns {Bool} Returns true if the page was changed (if the table 
    was already set to the last page then false will be returned).
    */
    this.PageDown = function() {
        if (this.CurrentPage > 1) {
            this.SetPage(this.CurrentPage - 1);
            return true;
        }
        else {
            return false;
        }
    };

    /**
    Returns the specified row for the table.
    @param {Int} rowNumber Index of the row in the table to return. Note this 
    row must be present in the current page of data.
    @returns {Qww.Table.Row} Object representing the table row.
    */
    this.GetRow = function(rowNumber/*, parseAdditionalAllAttributes*/) {

        var req = rowNumber;

        if (this.rowsOfResults[rowNumber] == null) {

            var row = new Qww.Table.Row();

            row.RecordNumber = (1 * this.PageOffset) + (1 * rowNumber);

            var rowToUse = rowNumber;

            if (this.HeaderRowPresent == true) {
                //row.RecordNumber++;
                rowToUse++;
            }

            var arrLength = this.colsOfResults.length;
            
            for (var i = 0; i < arrLength; i++) {

                var colOfResults = this.colsOfResults[i];

                var rowItem = new Qww.Table.Cell();

                if (rowToUse >= colOfResults.length)
                    rowItem.Text = "No data for record " + rowToUse;
                else {
                    var elem = colOfResults[rowToUse];

                    if (!row.IsHeader) {
                        var boolIsHeader = elem.getAttribute("isheader") == "true";
                        row.IsHeader = boolIsHeader;
                    }

                    rowItem.Text = elem.getAttribute("title") ? elem.getAttribute("title") : elem.getAttribute("text");

                    //                    if (parseAdditionalAllAttributes) {
                    //                        rowItem.Style = elem.getAttribute("style");
                    //                        rowItem.IsNumber = elem.getAttribute("isnum");
                    //                        rowItem.SelectType = elem.getAttribute("selecttype");
                    //                    }
                }

                row.Cells[i] = rowItem;
            }

            this.rowsOfResults[rowNumber] = row;
        }

        return this.rowsOfResults[rowNumber];
    };

    /**
    Sort the table data.
    @param {Int} headerSortIndex Column index to sort on.
    @param {Bool} [resetToFirstPage=true] Whether to reset the view to the first page.
    */
    this.Sort = function(headerSortIndex, resetToFirstPage) {

        if (!resetToFirstPage) resetToFirstPage = true;

        qwwHub.DoAvqSet(applicationId, "Document." + objId + ".C" + headerSortIndex, "click", "Document." + objId + ".C" + headerSortIndex, !resetToFirstPage);

        if (resetToFirstPage)
            me.SetPage(1);
    };

    this.OnAvqUpdateComplete = function() {

        if (!cfg.DoNotInitialise || cfg.DoNotInitialise == false) {
            if (!_isInitialized) {
                if (!me.Initialise()) {
                    return;
                }
            }
        }

        var CH = qwwHub.DoAvqSelect(applicationId, objId);

        if (CH == null) {
            // This might be called as the result of an OnAvqUpdateComplete
            // which might be for an unrelated table or lisbox, in which case
            // the XML wont contain that for XH
            return;
        }
        else {

            this.colsOfResults.length = 0;
            this.rowsOfResults.length = 0;

            this.Caption.ParseFromXml(CH);

            var cols = $("value", CH);

            var colIndex = 0;

            var noCols = cols.length;
            
            for (var i = 0; i < noCols; i++) {


                var col = cols[i];

                var name = col.getAttribute("name");

                //                if (name == "Caption")
                //                    this.Title = col.getAttribute("label");

                if (name == "Caption" || name.length > 3 || name.substr(0, 1) != "C")
                    continue;

                var vals = col.childNodes;

                if (vals.length > 0 && vals[0].getAttribute("position") == "top") {

                    var obj = new Qww.Table.Header();

                    obj.HeaderText = vals[0].getAttribute("title") ? vals[0].getAttribute("title") : vals[0].getAttribute("text");
                    obj.HeaderIndex = colIndex;
                    obj.HeaderSortIndex = 1 * (col.getAttribute("name").replace("C", "")); // col;
                    obj.HeaderSortKey = col.getAttribute("name");

                    obj.SortOrder = col.getAttribute("sortorder");

                    obj.SortDirection = "";

                    if (vals[0].childNodes.length > 0) {

                        var children = vals[0].childNodes;

                        var noChildren = children.length;

                        for (j = 0; j < noChildren; j++) {
                            if (children[j].nodeName == "icon") {
                                var iconNode = children[j];
                                var dir = iconNode.getAttribute("stamp");

                                if (dir == "ASI") {
                                    obj.SortDirection = Qww.Table.Header.SortDirection.Ascending; //"asc";
                                    break;
                                }

                                if (dir == "DSI") {
                                    obj.SortDirection = Qww.Table.Header.SortDirection.Descending; //"desc";
                                    break;
                                }
                            }
                        }
                    }
                    else
                        obj.SortDirection = Qww.Table.Header.SortDirection.Unsorted;

                    this.Headers[colIndex] = obj;
                }

                this.colsOfResults[colIndex] = vals;

                colIndex++;
            }

            this.Mode = CH.getAttribute("mode");
            this.Enabled = (this.Mode == "enabled");

            if (vals != null) {
                this.NoRows = vals.length;

                this.PageSize = CH.getAttribute("pagesize") * 1;

                if (this.NoRows > 0) {
                    if (this.colsOfResults[0][0].getAttribute("isheader") == "true") {
                        this.NoRows--;
                        //this.PageSize--;
                        this.HeaderRowPresent = true;
                    }
                    else {
                        this.HeaderRowPresent = false;
                    }
                }
                else {
                    this.HeaderRowPresent = false;
                }

                this.TotalSize = CH.getAttribute("totalsize"); // -1 // this will include the header; used to include header, no more.
                this.PageOffset = CH.getAttribute("pageoffset") * 1;

                if (this.InitialTotalSize == -1)
                    this.InitialTotalSize = this.TotalSize;

                this.NoPages = this.TotalSize / this.PageSize;
                this.NoPages = Math.round(this.NoPages + 0.49);

                if (this.InitialNoPages == -1)
                    this.InitialNoPages = this.NoPages;

                this.CurrentPage = Math.round(this.PageOffset / this.PageSize) + 1;
            }

            if (this.Cfg.OnUpdate)
                this.Cfg.OnUpdate(me);
        }
    };

    if (qwwHub)
        qwwHub.Register(this);
};

/**
Returns a html string summary of the main properties of the TableMgr.
*/
Qww.Table.Mgr.prototype.GetSummary = function() {

    return "Caption:" + this.Caption.Text + ", " + Qww.GetSummary([/*"Title", */"Enabled", "TotalSize", "PageOffset", "PageSize",
                            "NoRows", "CurrentPage", "NoPages", "InitialTotalSize",
                            "InitialNoPages", "HeaderRowPresent"], this);
};


/**
@fileOverview
Part of the QlikView WorkBench Javascript Library <br /><br />
Copyright (c) 2009 QlikTech International AB (http://www.qliktech.com)<br /><br />
All Rights Reserved. Email support@qliktech.com for licensing and support information.<br /><br />
@author <a href="mailto:support@qlikview.com">QlikView</a>
*/

Qww.Button = {};

/**
Constructs a new Qww.Button.Mgr button instance.
@class JavaScript class to manage communication with an underlying QlikView button object.<br />

@param {Object} cfg JSON object to configure ButtonMgr.

@param {String} cfg.ObjectID Id of the button in the QlikView application.

@param {String} [cfg.ApplicationID=null] Id/Name of the QlikView application. Note this is <strong>only</strong> necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null.

@param {Function} [cfg.OnUpdate] Function to call whenever an update is received for the button (for example 
if the button text changes). The function should accept a single parameter which is reference to the ButtonMgr itself.

@returns {Qww.Button.Mgr} Qww.Button.Mgr

@example
var buttonMgr = new Qww.Button.Mgr(
{
"ObjectID" : 'BUCLEAR',
"OnUpdate": function(btnMgr) {

        alert("Qww.Button.Mgr.OnUpdate fired - .Caption = " + 
        btnMgr.Caption + ", .Enabled = " + btnMgr.Enabled);        
    }
});
*/
Qww.Button.Mgr = function(cfg) {

    var _isInitialized = false;

    var me = this;

    /**
    Reference to the configuration object which was used to create construct the object. This 
    allows certain properties to be updated after initial instantiation.
    @type Object
    */
    this.Cfg = cfg;

    /** 
    Whether the button is enabled (visible) within the QlikView application. This can be dependent, 
    for example, upon show and hide conditions set for the object in QlikView.
    @deprecated You should now use Mode.
    @type Bool
    */
    this.Enabled = true;

    /** 
    The state of the object. This can be dependent, for example, upon show and hide conditions set 
    for the object in QlikView.
    @type Qww.QlikViewObjectState
    */
    this.Mode = true;

    /** 
    Current Text/Caption of the button control.
    @type String
    */
    this.Caption = "";

    /**
    @ignore
    Returns an array of Qww.QvsConnectorSet objects which represents the initiasation which 
    needs to be sent to QlikView server in order to initialise this object.
    @returns {Qww.QvsConnectorSet[]} Array of Qww.QvsConnectorSet objects which represents 
    the initiasation for this object.
    */
    this.GetInitialisationSets = function() {

        var sets = [];

        sets.push(new Qww.QvsConnectorSet(cfg.ApplicationID, cfg.ObjectID, "add", "mode;action", true));

        return sets;
    };

    function initialize() {

        var btn = qwwHub.DoAvqSelect(cfg.ApplicationID, cfg.ObjectID);

        if (btn == null) {
            qwwHub.DoAllSets(me.GetInitialisationSets());
            //qwwHub.DoAvqSet(cfg.ApplicationID, cfg.ObjectID, "add", "mode;action", true);
            return false;
        }

        _isInitialized = true;

        return true; // handshake - there will not be a new update
    };

    /**
    Sends a click through to the button.
    @param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
    Set this to false if you intend to call some methods on other objects and would like all the commands to 
    be sent in one request.
    */
    this.SendClick = function(isFinal) {
        if (isFinal == null)
            isFinal = true;

        Qww.Button.Mgr.SendClick(cfg.ApplicationID, cfg.ObjectID, isFinal);
    };


    this.OnAvqUpdateComplete = function() {

        if (!_isInitialized) {
            if (!initialize()) {
                return;
            }
        }

        var CH = qwwHub.DoAvqSelect(cfg.ApplicationID, cfg.ObjectID);

        if (CH == null) {
            // This might be called as the result of an OnAvqUpdateComplete
            // which might be for an unrelated control, in which case
            // the XML wont contain that for XH
            return;
        }
        else {

            this.Enabled = (CH.getAttribute("mode") == "enabled");
            this.Mode = CH.getAttribute("mode");

            this.Caption = CH.getAttribute("title") ? CH.getAttribute("title") : CH.getAttribute("text");

            if (this.Cfg.OnUpdate)
                this.Cfg.OnUpdate(this);
        }
    };

    if (qwwHub)
        qwwHub.Register(this);
};

/**
Sends a click through to the button.
@param {String} applicationId Id/Name of the QlikView application <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.
@param {String} buttonId Id of the button control in the QlikView application.
@param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
Set this to false if you intend to call some methods on other objects and would like all the commands to 
be sent in one request.
*/
Qww.Button.Mgr.SendClick = function(applicationId, buttonId, isFinal)
{    
    if(isFinal == null) 
        isFinal =  true;

    qwwHub.DoAvqSet(applicationId, buttonId, "action", "", isFinal);
};

/**
Enumeration of standard actions which can be called on an application.
@class Enumeration of standard actions which can be called on an application.<br />
@see Qww.Button.Mgr#CallStandardAction
@example
Qww.Button.Mgr.CallStandardAction(null, Qww.Button.Mgr.StandardAction.ClearAll, true);
*/
Qww.Button.Mgr.StandardAction = {

    /** 
    Clear all selections.
    @constant
    */
    ClearAll: 'CA',

    /** 
    Undo last operation.
    @constant
    */
    Back: 'BCK',

    /** 
    Redo last undone operation.
    @constant
    */
    Forward: 'FWD',

    /** 
    Lock all selections.
    @constant
    */
    LockSelections: 'LS',

    /** 
    Unlock all selections.
    @constant
    */
    UnlockSelections: 'US'
};

/**
Sends a click through to the button.
@param {String} applicationId Id/Name of the QlikView application <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.
@param {Qww.Button.Mgr.StandardAction} action Standard action to carry out on QlikView Application.
@param {Bool} [isFinal=true] If this is the final command in this set to send to QlikView Server.
Set this to false if you intend to call some methods on other objects and would like all the commands to 
be sent in one request.
*/
Qww.Button.Mgr.CallStandardAction = function(applicationId, action, isFinal) {

    if (isFinal == null)
        isFinal = true;

    qwwHub.DoAvqSet(applicationId, "Document.StandardActions." + action, "action", "", isFinal);
    //qwwHub.DoAvqSet(applicationId, "ActiveSheet.StandardActions." + action, "action", "", isFinal);
};



/**
@fileOverview
Part of the QlikView WorkBench Javascript Library <br /><br />
Copyright (c) 2009 QlikTech International AB (http://www.qliktech.com)<br /><br />
All Rights Reserved. Email support@qliktech.com for licensing and support information.<br /><br />
@author <a href="mailto:support@qlikview.com">QlikView</a>
*/

Qww.TextObject = {};

/**
Constructs a new Qww.TextObject.Mgr button instance.
@class JavaScript class to manage communication with an underlying QlikView text object.<br />
@param {Object} cfg JSON object to configure ButtonMgr.
@param {String} cfg.ObjectID Id of the text object in the QlikView document.
@param {String} [cfg.ApplicationID=null] Id/Name of the QlikView document. Note this is <strong>only</strong> necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null.
@param {Bool} [cfg.DoNotInitialise=false] Set this to false if you do not want this particular object to initialise the 
underlying object with QlikView Server. Use this option for example if you are already using another object or control which 
will have already initialised this. In this mode this object will simply parse the existing data for this object as it comese from 
QlikView Server.
@param {Function} [cfg.OnUpdate] Function to call whenever an update is received for the button (for example 
if the button text changes). The function should accept a single parameter which is reference to the TextObjectMgr itself.
@example
var txtObj = new Qww.TextObject.Mgr(
{
"ObjectID" : 'TXT_MYTXTBOX',
"OnUpdate": function(oTxt) {

alert("Qww.TextObject.Mgr.OnUpdate fired - .Text = " + 
oTxt.Text + ", .Enabled = " + oTxt.Enabled);        
}
});
*/
Qww.TextObject.Mgr = function(cfg) {

    var objectId = cfg.ObjectID;
    var applicationId = cfg.ApplicationID;

    var _isInitialized = false;
    var me = this;

    /**
    Reference to the configuration object which was used to create construct the object. This 
    allows certain properties to be updated after initial instantiation.
    @type Object
    */
    this.Cfg = cfg;

    /** 
    The state of the object. This can be dependent, for example, upon show and hide conditions set 
    for the object in QlikView.
    @type Qww.QlikViewObjectState
    */
    this.Mode = "";

    /** 
    Whether the text object is enabled (visible) within the QlikView document. This can be dependent, 
    for example, upon show and hide conditions set for the object in QlikView.
    @type Bool
    */
    this.Enabled = true;

    /** 
    Caption for text object.
    @type Qww.ObjectCaption
    */
    this.Caption = new Qww.ObjectCaption();

    /** 
    Text content of the object.
    @type String
    */
    this.Text = "";

    var _isInitialized = false;

    /**
    @ignore
    Returns an array of Qww.QvsConnectorSet objects which represents the initiasation which 
    needs to be sent to QlikView server in order to initialise this object.
    @returns {Qww.QvsConnectorSet[]} Array of Qww.QvsConnectorSet objects which represents 
    the initiasation for this object.
    */
    this.GetInitialisationSets = function() {

        var sets = [];

        sets.push(new Qww.QvsConnectorSet(cfg.ApplicationID, cfg.ObjectID, "add", "mode;text", false));
        sets.push(new Qww.QvsConnectorSet(cfg.ApplicationID, cfg.ObjectID + ".Caption", "add", "mode;text", false));
        sets.push(new Qww.QvsConnectorSet(cfg.ApplicationID, cfg.ObjectID + ".Content", "add", "mode;value", true));

        _isInitialized = true;

        return sets;
    };

    this.Initialise = function() {
        return initialize();
    };

    function initialize() {

        var obj = qwwHub.DoAvqSelect(cfg.ApplicationID, cfg.ObjectID);

        if (obj == null && !_isInitialized) {

            qwwHub.DoAllSets(me.GetInitialisationSets());

            //            qwwHub.DoAvqSet(cfg.ApplicationID, cfg.ObjectID, "add", "mode;text", false);
            //            qwwHub.DoAvqSet(cfg.ApplicationID, cfg.ObjectID + ".Caption", "add", "mode;text", false);
            //            qwwHub.DoAvqSet(cfg.ApplicationID, cfg.ObjectID + ".Content", "add", "mode;value", true);
            return false;
        }

        _isInitialized = true;

        return true; // handshake - there will not be a new update
    };



    this.OnAvqUpdateComplete = function() {

        if (!cfg.DoNotInitialise || cfg.DoNotInitialise == false) {

            if (!_isInitialized) {
                if (!initialize()) {
                    return;
                }
            }
        }

        var CH = qwwHub.DoAvqSelect(cfg.ApplicationID, cfg.ObjectID);

        if (CH == null) {
            return;
        }
        else {

            var contentElem = $("value[name=Content]", CH);

            if (contentElem.length != 1) {
                contentElem = CH;
            }
            else {
                contentElem = contentElem[0];
            }

            this.Mode = contentElem.getAttribute("mode");
            this.Enabled = (contentElem.getAttribute("mode") == "enabled");
            this.Text = contentElem.getAttribute("title") ? contentElem.getAttribute("title") : contentElem.getAttribute("text");

            if (me.Cfg.OnUpdate)
                me.Cfg.OnUpdate(this);
        }
    };

    if (qwwHub)
        qwwHub.Register(this);
};

/**
@fileOverview
Part of the QlikView WorkBench Javascript Library <br /><br />
Copyright (c) 2009 QlikTech International AB (http://www.qliktech.com)<br /><br />
All Rights Reserved. Email support@qliktech.com for licensing and support information.<br /><br />
@author <a href="mailto:support@qlikview.com">QlikView</a>
*/

Qww.BookMark = {};

/**
JavaScript class to provide access to QVS bookmark functionality.
@class JavaScript class to provide access to QVS bookmark functionality.<br />
*/
Qww.BookMark.Mgr = {}

/**
Applies a previously created bookmark.

@param {String} applicationId Id/Name of the QlikView application <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.

@param {String} bookMarkId Id of the bookmark as passed by the onCreated callback passed to the CreateBookMark method.
*/
Qww.BookMark.Mgr.ApplyBookmark = function(applicationId, bookMarkId) {

    // <set name="bookmark-apply" docaction="Server\BM03" />
    //<set name="Document.ActiveSheet.StandardActions.Bookmarks" value="Server\BM01" />

    //qwwHub.DoAvqSet(applicationId, "bookmark-apply", "docaction", bookMarkId, true);

    //<set name="bookmark-apply" docaction="SERVER\BM01" />


    //<update mark="40E37B77D7821600" stamp="40E37C34759203CB" cookie="true" scope="Document" session="{0D37DE79-4968-480C-B526-F105732EE617}" view="cb/cb" autoview="Widget1" ident="null">
    //<set name="Document.ActiveSheet.StandardActions.Bookmarks" value="Server\BM01"/>
    //</update>

    //qwwHub.DoAvqSet(applicationId, "bookmark-apply", "docaction", bookMarkId, true);

    if (bookMarkId.substring(0, 7) != "Server\\") bookMarkId = "Server\\" + bookMarkId;

    qwwHub.DoAvqSet(applicationId, "Document.ActiveSheet.StandardActions.Bookmarks", "value", bookMarkId, true);

    // Version 9..
    //qwwHub.DoAvqSet(applicationId, "ActiveSheet.StandardActions.Bookmarks", "value", bookMarkId, true);
};

Qww.BookMark.Mgr.ApplyBookmarkIfInUrl = function() {

    var id = Qww.Helper.GetQueryVariable("bookmark");

    if (id != null)
        Qww.BookMark.Mgr.ApplyBookmark(null, id);
};

/**
Creates a shared bookmark based on the current selections.

@param {String} applicationId Id/Name of the QlikView application <strong>(note this is only necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null)</strong>.

@param {String} name Name for the bookmark (note this is not currently useful - the id needed is to reapply the 
bookmark is passed via the onCreated callback).

@param {Function} onCreated Callback function to run when the bookmark has been created. The function should accept one 
parameter which is the id of the bookmark created.

@example
Qww.BookMark.Mgr.CreateBookMark(null, "MyBookMark", function(bookmarkid) {
alert("Bookmark created, id = " + bookmarkid);
    
// This book mark can be applied be appending it to the pages url, e.g.
// http://server/page.aspx?bookmark=" + bookmarkid;
});
*/
Qww.BookMark.Mgr.CreateBookMark = function(applicationId, name, onCreated) {

    // Bookmark format:
    // http://cblaptop/Qvplugin/opendoc.htm?document=Films.qvw?bookmark=Server\BM01    

    qwwHub.CreateBookMark(applicationId, name, onCreated);
};

/**
@fileOverview
Part of the QlikView WorkBench Javascript Library <br /><br />
Copyright (c) 2009 QlikTech International AB (http://www.qliktech.com)<br /><br />
All Rights Reserved. Email support@qliktech.com for licensing and support information.<br /><br />
@author <a href="mailto:support@qlikview.com">QlikView</a>
*/

Qww.Ctls.GlobalSearch = {};

/** 
Constructs a new Qww.Ctls.GlobalSearch.Mgr instance.

@class JavaScript control to search across multiple fields (listboxes) within an application. Note that 
you should create copies of the listboxes you wish to use which are utilised only by this control. For example if you are 
already showing LBCOUNTRY as a listbox control on your page, create a copy of this listbox named LBCOUNTRY_SEARCH and use this 
in conjunction with the Qww.Ctls.GlobalSearch.Mgr control.<br />

@param {Object} cfg JSON object to configure Qww.Ctls.GlobalSearch.Mgr.

@param {String} cfg.ResultsElementId Element to show search results in.

@param {String} cfg.SearchTextBoxId ID of text box where search term is entered.

@param {Qww.Ctls.GlobalSearch.Field[]} cfg.Fields Array of fields to search in the QlikView document.

@param {String} [cfg.Theme=Default] Theme to use (this string gets used in css class names, for example QwwJs_GlobalSearch-NoMatchesFound-ThemeName).

@param {Bool} [cfg.AutomaticallyClearSearchString=false] If set to true the search box is cleared whenever results are selected.

@param {Bool} [cfg.CloseSearch=false] If set to true then each time the search command is sent to QlikView Server 
the search will also be 'closed' meaning that the matching listbox items will be selected (and any other QlikView objects 
will be updated accordingly).

@param {Integer} [cfg.SearchInterval=500] Rather than sending new search requests as soon as the user starts typing, the search control 
waits this amount of milliseconds after the last character was typed then sends the search.

@param {Function} [cfg.OnRenderResultsSection] Function to run to render custom results. Function will have the following 
signature: function(results, lbId, lbTitle, lbMatchString, lbNoMatchString, maxLengthOfMatchStringToShow, 
maxNumberOfResultsToShow, lbSelectAllText, lbReduceResultstext).

@param {Function} [cfg.OnInitialised] Function to call when the control has been initialised.

@param {Function} [cfg.OnRenderBegin] Function to call when the control is about to re-render.

@param {Function} [cfg.OnRenderComplete] Function to call when the control is about to complete rendering.

@param {Function} [cfg.OnBeforeCloseSearch] Function to call before the search results close. Should be 
of the form function(searchCtl, isFromCloseButton). The isFromCloseButton is false if the search is closing for 
a reason other than the [X] was clicked, for example when the user clears the search box text the search closes. 
If you return false from this function the closing of the search will be cancelled.

@param {Function} [cfg.OnSearchClosed] Function to call after the search results close. Should be 
of the form function(searchCtl, isFromCloseButton). The isFromCloseButton is false if the search is closing for 
a reason other than the [X] was clicked, for example when the user clears the search box text the search closes. 

@param {Function} [cfg.OnGetSearchString|function(str){return "*" + str + "*";}] Function to call to return the search 
string to be sent to QlikView Server. Defaults to a 'standard' *search_string* pattern. NOTE this is only called when the 
str.length > 0, otherwise '***' will be sent as the search string to clear the search.

@param {Function} [cfg.OnSearchInitiated] Function to call when the search initiates. Useful, for example, to 
show an animated spinner to give the user immediate feedback that a search is in progress.

@param {Function} [cfg.OnSearchCompleted] Function to call after the search has completed. Useful, for example, to 
hide an animated spinner which has been shown on the OnSearchInitiated event.

@param {Function} [me.Cfg.OnSearchPerformed] Function to call when a search is run against the server. The function 
should accept the parameters (Qww.Ctls.GlobalSearch.Mgr, searchString).

@example
var objQvExSearchCtl1 = new Qww.Ctls.GlobalSearch.Mgr(
{
"Fields":[
new Qww.Ctls.GlobalSearch.Field(
{
ObjectID: "LBSEARCHACTORS", 
Title: "Actors", 
MatchText: "Were you looking for the following actors:", 
NoMatchText: "No actors were found. Please refine your search", 
MaxNumberOfLettersToShowInResult: 5,
MaxNumberOfResultsToShow: 7, 
SelectAllText: "Select Them All!",
ReduceResultsText: "Change search text to reduce the results..."
}),
new Qww.Ctls.GlobalSearch.Field(
{
ObjectID: "LBSEARCHDIRECTOR", 
Title: "Directors",
MatchText: "Were you looking for the following directors:", 
NoMatchText: "No directors were found. Please refine your search",
MaxNumberOfLettersToShowInResult: -1,
MaxNumberOfResultsToShow:  -1, 
SelectAllText: "[Select All]",
ReduceResultsText: "lengthen search text to reduce results further..."
})
],
"ResultsElementId" : "QvExSearchCtl1_results",
"SearchTextBoxId" : "QvExSearchCtl1_txtSearch",
"Theme" : "",
"AutomaticallyClearSearchString" : true
});

&lt;div id="ctl00_cphContent_QvExSearchCtl1" class="QwwJs_GlobalSearch-OuterDiv" 
style="display:inline-block;width:150px;"&gt;
&lt;input type="text" id="QvExSearchCtl1_txtSearch" 
class="QwwJs_GlobalSearch-TextBox" style="width:100%;" /&gt;
&lt;div class="QwwJs_GlobalSearch-SearchResults" 
id="QvExSearchCtl1_results" style="z-index:100;position:absolute;display:none;"&gt;
&lt;/div&gt;
&lt;/div&gt;

@returns {Qww.Ctls.GlobalSearch.Mgr} Qww.Ctls.GlobalSearch.Mgr
*/
Qww.Ctls.GlobalSearch.Mgr = function(cfg) {
    var me = this;

    /**
    Reference to the configuration object which was used to create construct the object. This 
    allows certain properties to be updated after initial instantiation.
    @type Object
    */
    this.Cfg = cfg;

    performEmptySearchOnClosing = false;

    this.ClassPrefix = "QwwJs_GlobalSearch";

    if (!this.Cfg.Theme)
        this.Cfg.Theme = "Default";

    var applicationId = cfg.ApplicationID;

    var currentSearch = 0;
    var inSearch = false;
    var str = "";
    var result_text = "";
    var resultsElement;
    var searchBox;

    if (cfg.CloseSearch == null)
        cfg.CloseSearch = false;

    var searchInterval = (cfg.SearchInterval == null) ? 500 : cfg.SearchInterval;

    var automaticallyClearSearchString = false;

    if (this.Cfg.AutomaticallyClearSearchString)
        automaticallyClearSearchString = this.Cfg.AutomaticallyClearSearchString;

    function t(msg) {
        qwwHub.Trace("Qww.Ctls.GlobalSearch.Mgr:" + msg);
    };

    var _lastSearchText;

    function performSearch() {
        inSearch = true;

        if (searchBox.value == _lastSearchText) {
            if (cfg.OnSearchCompleted)
                cfg.OnSearchCompleted(this);
        }
        else {
            me.PerformSearch(searchBox.value);
            _lastSearchText = searchBox.value;
        }
    }

    var _delayedTimerId;

    this.OnDocumentLoaded = function() {
        if (me.Cfg.SearchTextBoxId) {
            searchBox = document.getElementById(this.Cfg.SearchTextBoxId);

            lastText = searchBox.value;

            //
            // Make sure search is cleared when first used.
            //
            searchBox.onclick = function(oEvent) {
                if (this.isFirst == null) {
                    this.value = "";
                    this.isFirst = false;
                }
            };

            searchBox.onkeyup = function(oEvent) {

                if (cfg.OnSearchInitiated)
                    cfg.OnSearchInitiated(this);

                if (_delayedTimerId != null) window.clearTimeout(_delayedTimerId);

                _delayedTimerId = setTimeout(performSearch, searchInterval);

                // Fix for issue where search propogates through to listboxes too.
                if (!oEvent)
                    oEvent = window.event;

                oEvent.cancelBubble = true;
                return false;
                // Fix for issue where search propogates through to listboxes too.
            };
        }

        if (cfg.ResultsElementId) {
            resultsElement = document.getElementById(cfg.ResultsElementId);
            showResults(false);
        }

        if (me.Cfg.OnRenderResultsSection == null)
            me.Cfg.OnRenderResultsSection = onRenderResultsSectionDefault;

        if (me.Cfg.OnRenderResultsHeader == null)
            me.Cfg.OnRenderResultsHeader = onRenderResultsHeaderDefault;

        searchBox.CloseSearch = function(isFromCloseButton) {

            if (performEmptySearchOnClosing == null) performEmptySearchOnClosing = true;

            if (isFromCloseButton == null) isFromCloseButton = false;

            if (cfg.OnBeforeCloseSearch)
                if (cfg.OnBeforeCloseSearch(this, isFromCloseButton) == false)
                return;

            // me.PerformSearch("*"); CB 240409 - Not sure why we needed this but it was causing the
            // selection to fail as the '*' search was running at the end 
            // of any selections.

            abort();

            if (automaticallyClearSearchString == true)
                this.value = "";

            showResults(false);

            if (cfg.OnSearchClosed)
                cfg.OnSearchClosed(this, isFromCloseButton);

            if (cfg.OnSearchCompleted)
                cfg.OnSearchCompleted(this);
        };

        searchBox.MakeSelection = function(id, value) {
            Qww.ListBox.Mgr.MakeSingleSelection(applicationId, id, value);

            //abort();

            //this.CloseSearch();
        };
    };

    /**
    Sets the text in the search box.
    @param {String} txt Text to set.
    */
    this.SetSearchText = function(txt) {
        searchBox.value = txt;
    };

    /**
    Closes the results panel.
    */
    this.CloseSearch = function() {
        searchBox.CloseSearch();
    };

    var haveListBoxesBeenRegistered = false;

    function abort() {
        for (i = 0; i < cfg.Fields.length; i++) {
            val = cfg.Fields[i];
            var objectId = val.ObjectID;
            var isFinal = (i == cfg.Fields.length - 1);
            qwwHub.DoAvqSet(applicationId, objectId, "closesearch", "abort", isFinal);
        }
    }

    //    /**
    //    @ignore
    //    Returns an array of Qww.QvsConnectorSet objects which represents the initiasation which 
    //    needs to be sent to QlikView server in order to initialise this object.
    //    @returns {Qww.QvsConnectorSet[]} Array of Qww.QvsConnectorSet objects which represents 
    //    the initiasation for this object.
    //    */
    //    this.GetInitialisationSets = function() {

    //        var sets = [];

    //        var arrLength = me.Cfg.Fields.length;

    //        for (i = 0; i < arrLength; i++) {

    //            val = me.Cfg.Fields[i];

    //            var maxNoResults = val.MaxNumberOfResultsToShow;

    //            if (!maxNoResults)
    //                maxNoResults = 20;

    //            //addListBox(val.ObjectID, maxNoResults);

    //            //qwwHub.Register(new Qww.ListBox.Mgr({ ObjectID: val.ObjectID, PageSize: maxNoResults }));

    //            sets.push(new Qww.QvsConnectorSet(applicationId, val.ObjectID, "add", "mode;value;pageoffset;pagesize;totalsize", false));
    //            sets.push(new Qww.QvsConnectorSet(applicationId, val.ObjectID + ".C0", "add", "mode;text;", false));
    //            sets.push(new Qww.QvsConnectorSet(applicationId, val.ObjectID, "pagesize", maxNoResults, false));
    //            sets.push(new Qww.QvsConnectorSet(applicationId, val.ObjectID, "pageoffset", "0", (i == me.Cfg.Fields.length - 1)));
    //        }

    //        haveListBoxesBeenRegistered = true;

    //        return sets;
    //    };

    for (i = 0; i < me.Cfg.Fields.length; i++) {

        val = me.Cfg.Fields[i];

        var maxNoResults = val.MaxNumberOfResultsToShow;

        if (!maxNoResults)
            maxNoResults = 20;

        //        qwwHub.Register(
        new Qww.ListBox.Mgr(
            {
                ObjectID: val.ObjectID,
                PageSize: maxNoResults
            }
        );
        //);
    }

    this.OnAllAvqUpdateCompletesCalled = function() {

        //debugger;

        //        if (!haveListBoxesBeenRegistered) {

        //            qwwHub.DoAllSets(me.GetInitialisationSets());

        //            //            if(searchBox)
        //            //                searchBox.disabled = false;

        //            haveListBoxesBeenRegistered = true;
        //        }

        if (inSearch == true) {

            search();

            var arrLength = me.Cfg.Fields.length;

            for (var i = 0; i < arrLength; i++) {

                var field = me.Cfg.Fields[i];

                var lbId = field.ObjectID;

                var results = getResults(lbId);

                //if (results != null) 
                {
                    if (me.Cfg.OnRenderResultsSection) {

                        var lbTitle = field.Title;
                        var lbMatchString = field.MatchText;
                        var lbNoMatchString = field.NoMatchText;
                        var maxLengthOfMatchStringToShow = field.MaxNumberOfLettersToShowInResult;

                        if (maxLengthOfMatchStringToShow <= 0)
                            maxLengthOfMatchStringToShow = null;

                        var maxNumberOfResultsToShow = field.MaxNumberOfResultsToShow;

                        if (maxNumberOfResultsToShow <= 0)
                            maxNumberOfResultsToShow = null;

                        var lbSelectAllText = field.SelectAllText;
                        var lbReduceResultstext = field.ReduceResultsText;

                        result_text += me.Cfg.OnRenderResultsSection(results, lbId, lbTitle, lbMatchString, lbNoMatchString, maxLengthOfMatchStringToShow, maxNumberOfResultsToShow, lbSelectAllText, lbReduceResultstext);
                    }
                    else {
                        result_text += "No OnRenderResultsSection function registered.<br />";
                    }
                }

            };

            if (me.Cfg.OnRenderResultsHeader)
                var headerHtml = me.Cfg.OnRenderResultsHeader();

            resultsElement.innerHTML = headerHtml + result_text;

            var arrLength = me.Cfg.Fields.length;

            for (var i = 0; i < arrLength; i++) {

                var lbId = me.Cfg.Fields[i].ObjectID;
                var element = document.getElementById(lbId + "_results");

                if (element)
                    Qww.Ctls.GlobalSearch.Mgr.HighlightWord(element, str, me.GetClassNameWithThemePostfix("Searchword"));
            }

        }

        if (cfg.OnSearchCompleted)
            cfg.OnSearchCompleted(this);

    };

    this.PerformSearch = function(searchString) {

        t("Searching '" + searchString + "'");

        if (searchString == '') {
            searchString = "*";
        }

        result_text = "";

        if (searchString == str)
            return;
        else
            str = searchString;

        if (str.length == 0) {
            showResults(false);
            search();
        }
        else {
            inSearch = true;
            showResults(true);
            str = searchString;

            inSearch = true;

            search();

            if (searchString == "*")
                searchBox.CloseSearch();
        }
    };

    // START PRIVATE INTERFACE ---------------------------------------------------
    //

    function getCloseSearchJsFunction(isFromCloseButton) {

        if (isFromCloseButton == null) isFromCloseButton = true;

        if (isFromCloseButton == true)
            return "document.getElementById(\"" + cfg.SearchTextBoxId + "\").CloseSearch(true);";
        else
            return "document.getElementById(\"" + cfg.SearchTextBoxId + "\").CloseSearch(false);";
    };

    function onRenderResultsHeaderDefault() {
        return "<span class='" + me.GetClassNameWithThemePostfix("CloseSearchIcon") + "' onclick='" + getCloseSearchJsFunction() + "' style='cursor:pointer;float:right'>[X]</span>";
    };

    function getMakeMultipleSelectionMethodName() {
        return "Qww.ListBox.Mgr.MakeSelection";
    };

    function getMakeSelectionMethodName() {
        return "Qww.ListBox.Mgr.MakeSingleSelection";
        //return "document.getElementById(\"" + cfg.SearchTextBoxId + "\").MakeSelection";
        //return "document.MakeSelection";
    };

    // Default rendering method
    function onRenderResultsSectionDefault(results, id, title, matchString, noMatchString, maxLettersPerResult, maxNumberOfResultsToShow, selectAllText, reduceResultsText) {

        if (results == null) return '';

        var html = "<div style='padding:4px 4px 4px 4px;'>";

        if (results == null || results.length == 0) {
            if (noMatchString)/// <reference path="QwwJs_GlobalSearchMgr.js" />

                html += "<span class='" + me.GetClassNameWithThemePostfix("NoMatchesFound") + "'>" + noMatchString + "</span>";
            else
                html += "<span class='" + me.GetClassNameWithThemePostfix("NoMatchesFound") + "'>" + title + "s</span>";
        }
        else {
            if (matchString)
                html += "<span class='" + me.GetClassNameWithThemePostfix("WereYouLookingFor") + "'>" + matchString + "</span>";
            else
                html += "<span class='" + me.GetClassNameWithThemePostfix("WereYouLookingFor") + "'>Were you looking for " + title + "s matching:</span>";

            html += "<br />";

            if (results.length > 1) {

                var arrayOfItems = [];

                var arrLength = results.length;

                for (i = 0; i < arrLength; i++) {

                    arrayOfItems.push(results[i].Value);

                    //                    if (i < arrLength - 1) {
                    //                        arrayOfItems += ",";
                    //                    }
                }

                arrayOfItems = "[" + arrayOfItems.join(',') + "]";

                var selectAllFunction = getMakeMultipleSelectionMethodName() + "(\"" + applicationId + "\", \"" + id.replace(/\\/, "\\\\") + "\"," + arrayOfItems + ");";

                selectAllFunction = getCloseSearchJsFunction(false) + selectAllFunction;

                if (selectAllText == null)
                    selectAllText = "[Select All]";

                html += " <span onclick='" + selectAllFunction + "' class='" + me.GetClassNameWithThemePostfix("SelectAll") + "'>" + selectAllText + "</span><br />";

            }

            var resultsId = id + "_results";

            html += "<span id='" + resultsId + "'>";

            var wasMaxResultsExceeded = false;

            var arrLength = results.length;

            for (i = 0; i < arrLength; i++) {

                //if(i > cfg.MaxNumberOfResultsPerField - 1){

                if (maxNumberOfResultsToShow != null && i > maxNumberOfResultsToShow - 1) {
                    wasMaxResultsExceeded = true;
                    break;
                }
                else {
                    if (applicationId == null) applicationId = "null";

                    //var selectFunction = "Qww.ListBox.Mgr.MakeSingleSelection(\"" + id + "\"," + results[i].Value + ");";
                    var selectFunction = getMakeSelectionMethodName() + "(\"" + applicationId + "\",\"" + id.replace(/\\/, "\\\\") + "\"," + results[i].Value + ");";
                    //alert(selectFunction);
                    //selectFunction += getCloseSearchJsFunction();
                    selectFunction = getCloseSearchJsFunction() + selectFunction;

                    var text = results[i].Text;

                    if (maxLettersPerResult != null && maxLettersPerResult != '' && maxLettersPerResult != -1 && text.length > maxLettersPerResult)
                        text = text.substring(0, maxLettersPerResult) + "...";


                    html += "<div class='" + me.GetClassNameWithThemePostfix("MatchedItem") + "' onclick='" + selectFunction + "' style='cursor:pointer'>" + text + "</div>";
                }
            }

            html += "</span>";

            if (wasMaxResultsExceeded == true)// && reduceResultsText != '')
                html += "<span class='" + me.GetClassNameWithThemePostfix("TruncatedResults") + "'>" + reduceResultsText + "</span>";
            //html += "<span class='" + me.GetClassNameWithThemePostfix("TruncatedResults") + "'>lengthen search text to reduce results further ...</span>";
        }

        return html + "</div>";
    };

    function showResults(show) {
        // Fading not working
        //var obj = $(this).find('#' + cfg.ResultsElementId);

        if (show == true) {
            //resultsElement.style.display = ''
            $(resultsElement).fadeIn(100);
        }
        else {
            $(resultsElement).fadeOut(100);
            //resultsElement.style.display = 'none'
        }
    };

    //    function highlightWord(node, word) {
    //        // Iterate into this nodes childNodes
    //        if (node.hasChildNodes) {
    //            var hi_cn;

    //            var arrLength = node.childNodes.length;

    //            for (hi_cn = 0; hi_cn < arrLength; hi_cn++) {
    //                highlightWord(node.childNodes[hi_cn], word);
    //            }
    //        }

    //        // And do this node itself
    //        if (node.nodeType == 3) { // text node
    //            tempNodeVal = node.nodeValue.toLowerCase();
    //            tempWordVal = word.toLowerCase();
    //            if (tempNodeVal.indexOf(tempWordVal) != -1) {
    //                pn = node.parentNode;
    //                // check if we're inside a "nosearchhi" zone
    //                checkn = pn;
    //                while (checkn.nodeType != 9 &&
    //			    checkn.nodeName.toLowerCase() != 'body') {
    //                    // 9 = top of doc
    //                    if (checkn.className.match(/\bnosearchhi\b/)) { return; }
    //                    checkn = checkn.parentNode;
    //                }
    //                if (pn.className != me.GetClassNameWithThemePostfix("Searchword")) {
    //                    // word has not already been highlighted!
    //                    nv = node.nodeValue;
    //                    ni = tempNodeVal.indexOf(tempWordVal);
    //                    // Create a load of replacement nodes
    //                    before = document.createTextNode(nv.substr(0, ni));
    //                    docWordVal = nv.substr(ni, word.length);
    //                    after = document.createTextNode(nv.substr(ni + word.length));
    //                    hiwordtext = document.createTextNode(docWordVal);
    //                    hiword = document.createElement("span");
    //                    hiword.className = me.GetClassNameWithThemePostfix("Searchword");
    //                    hiword.appendChild(hiwordtext);
    //                    pn.insertBefore(before, node);
    //                    pn.insertBefore(hiword, node);
    //                    pn.insertBefore(after, node);
    //                    pn.removeChild(node);
    //                }
    //            }
    //        }
    //    };

    //    function addListBox(id, maxNoResults) {
    //        if (qwwHub.DoAvqSelect(applicationId, id) == null) {
    //            qwwHub.DoAvqSet(applicationId, id, "add", "mode;value;pageoffset;pagesize;totalsize", false);
    //            qwwHub.DoAvqSet(applicationId, id + ".C0", "add", "mode;text;", false);
    //            qwwHub.DoAvqSet(applicationId, id, "pagesize", maxNoResults, false);
    //            qwwHub.DoAvqSet(applicationId, id, "pageoffset", "0", false);
    //        }
    //    };

    function getResults(id) {

        var result = qwwHub.DoAvqSelect(applicationId, id);

        if (result != null) {


            //var vals = $("value", result);
            var vals = $("value[name=C0]", result);

            if (vals.length == 0)
                return null;

            var QVListboxValues = vals[0].childNodes;

            var results = new Array();
            var currentIndex = 0;

            var arrLength = QVListboxValues.length;

            for (var i = 0; i < arrLength; i++) {

                var newItem = Qww.ListBox.Mgr.GetListItemFromNode(QVListboxValues[i]);

                if (newItem.Value > -1) {

                    if (cfg.CloseSearch == true && newItem.State == Qww.ListBox.Mgr.ItemState.Selected) {
                        results[currentIndex++] = newItem;
                    }
                    else {
                        results[currentIndex++] = newItem;
                    }

                }
            }

            return results;
        }

        return null;
    };


    function search() {
        if (currentSearch < cfg.Fields.length) {
            var lbId = cfg.Fields[currentSearch].ObjectID;
            //lbId = getFullID(lbId);

            //var search = "*" + str + "*";

            if (str.length == 0)
                var search = "***";
            else {
                if (cfg.OnGetSearchString)
                    var search = cfg.OnGetSearchString(str);
                else
                    var search = "*" + str + "*";
            }

//            qwwHub.DoAvqSet(applicationId, lbId, "pageoffset", "0", false);

            if (cfg.CloseSearch == false)
                qwwHub.DoAvqSet(applicationId, lbId + ".Caption", "search", search, true);
            else {
                qwwHub.DoAvqSet(applicationId, lbId + ".Caption", "search", search, true);

                setTimeout(function() {
                    qwwHub.DoAvqSet(applicationId, lbId, "closesearch", "accept", true);
                }, 200);
            }

            currentSearch++;

            if (currentSearch == 1 && me.Cfg.OnSearchPerformed && search != "***") {
                me.Cfg.OnSearchPerformed(this, search);
            }
        }
        else {
            inSearch = false;
            currentSearch = 0;
        }
    };
    //
    // END PRIVATE INTERFACE ---------------------------------------------------

    qwwHub.Register(this);

    searchBox = document.getElementById(this.Cfg.SearchTextBoxId);

    if (this.Cfg.OnInitialised)
        this.Cfg.OnInitialised(me);
};

Qww.Ctls.GlobalSearch.Mgr.prototype = new Qww.ControlBase();

Qww.Ctls.GlobalSearch.Mgr.HighlightWord = function(node, word, classToHighlightMatches) {
    // Iterate into this nodes childNodes
    if (node.hasChildNodes()) {
        var hi_cn;

        var arrLength = node.childNodes.length;

        for (hi_cn = 0; hi_cn < arrLength; hi_cn++) {
            Qww.Ctls.GlobalSearch.Mgr.HighlightWord(node.childNodes[hi_cn], word, classToHighlightMatches);
        }
    }

    // And do this node itself
    if (node.nodeType == 3) { // text node
        tempNodeVal = node.nodeValue.toLowerCase();
        tempWordVal = word.toLowerCase();
        if (tempNodeVal.indexOf(tempWordVal) != -1) {
            pn = node.parentNode;
            // check if we're inside a "nosearchhi" zone
            checkn = pn;
            while (checkn.nodeType != 9 &&
			    checkn.nodeName.toLowerCase() != 'body') {
                // 9 = top of doc
                if (checkn.className.match(/\bnosearchhi\b/)) { return; }
                checkn = checkn.parentNode;
            }
            if (pn.className != classToHighlightMatches) {
                // word has not already been highlighted!
                nv = node.nodeValue;
                ni = tempNodeVal.indexOf(tempWordVal);
                // Create a load of replacement nodes
                before = document.createTextNode(nv.substr(0, ni));
                docWordVal = nv.substr(ni, word.length);
                after = document.createTextNode(nv.substr(ni + word.length));
                hiwordtext = document.createTextNode(docWordVal);
                hiword = document.createElement("span");
                hiword.className = classToHighlightMatches;
                hiword.appendChild(hiwordtext);
                pn.insertBefore(before, node);
                pn.insertBefore(hiword, node);
                pn.insertBefore(after, node);
                pn.removeChild(node);
            }
        }
    }
};

/**
Constructs a new Qww.Ctls.GlobalSearch.Field instance.
@class Javscript object to represent a field (listbox) which should be searched by the {@link Qww.Ctls.GlobalSearch.Mgr}.<br />
@param {Object} field JSON Object containing information on field.
@param {String} field.ObjectID Id of listbox object in QlikView document to search. Note that it is recommended you create specific copied/instances 
@param {String} [field.Title=field.ObjectID] Title string to use in the search results list above the list of matching entries for this field.
@param {String} [field.MatchText="Were you looking for the following?"] String to use above the list of matching entries for this field.
@param {String} [field.NoMatchText="No Matches found."] String to use when no matches are found against a particular field.
@param {Int} [field.MaxNumberOfLettersToShowInResult=-1] Maximum number of letters to show in a result entry.
@param {Int} [field.MaxNumberOfResultsToShow=10] Maximum number of results to show for the field.
@param {String} [field.SelectAllText="[Select All]"] Text to show for the select all results for this field link.
@param {String} [field.ReduceResultsText="lengthen search text to reduce results further..."] Text to show when more results are available than shown.
*/
Qww.Ctls.GlobalSearch.Field = function(field) {

    /** 
    Id of listbox object in QlikView document to search. Note that it is recommended you create specific copied/instances 
    @type String
    */
    this.ObjectID = field.ObjectID;

    /** 
    Title string to use in the search results list above the list of matching entries for this field.
    @type String
    */
    this.Title = (field.Title) ? field.Title : this.ObjectID;

    /** 
    String to use above the list of matching entries for this field.
    @type String
    */
    this.MatchText = (field.MatchText) ? field.MatchText : "Were you looking for the following?";

    /** 
    String to use when no matches are found against a particular field.
    @type String
    */
    this.NoMatchText = (field.NoMatchText) ? field.NoMatchText : "No Matches found.";

    /** 
    Maximum number of letters to show in a result entry.
    @type Int
    */
    this.MaxNumberOfLettersToShowInResult = (field.MaxNumberOfLettersToShowInResult != null) ? field.MaxNumberOfLettersToShowInResult : -1;

    /** 
    Maximum number of results to show for the field.
    @type Int
    */
    this.MaxNumberOfResultsToShow = (field.MaxNumberOfResultsToShow != null && field.MaxNumberOfResultsToShow != -1) ? field.MaxNumberOfResultsToShow : 10;

    /** 
    Text to show for the select all results for this field link.
    @type String
    */
    this.SelectAllText = (field.SelectAllText) ? field.SelectAllText : "[Select All]";

    /** 
    Text to show when more results are available than shown.
    @type String
    */
    this.ReduceResultsText = (field.ReduceResultsText) ? field.ReduceResultsText : "lengthen search text to reduce results further...";
};

Qww.Ctls.GlobalSearch.Field.FromArgs = function(objectID, title, matchText, noMatchText, maxNumberOfLettersToShowInResult, maxNumberOfResultsToShow, selectAllText, reduceResultsText) {

    var field = {};

    field.ObjectID = objectID;

    field.Title = title;
    field.MatchText = matchText;
    field.NoMatchText = noMatchText;
    field.MaxNumberOfLettersToShowInResult = maxNumberOfLettersToShowInResult;
    field.MaxNumberOfResultsToShow;
    field.SelectAllText = selectAllText;
    field.ReduceResultsText = reduceResultsText;

    return new Qww.Ctls.GlobalSearch.Field(field);
};



Qww.Ctls.DropDown = {};

/**
Constructs a new Qww.DropDown.Mgr instance.
@constructor
@class JavaScript class to render a listbox as a DropDown control.<br />
@param {Object} cfg JSON object to configure the DropDown.
@param {String} cfg.ElementID ID of the html element (e.g. div or span) 
where the drop down should be rendered.
@param {String} cfg.ObjectID Id of the ListBox in the QlikView application.
@param {String} [cfg.Theme='DefaultTheme'] Theme name to be appended to any class names 
used by the control.
@param {Boolean} [cfg.ShowDisabled=false] Whether disabled items should be shown.
@param {Number} [cfg.PageSize=5000] Page size of data to extract from the underlying listbox. 
As the control is not 'paged' this should be large enough to return all the data for the drop 
down in the first (and only) page requested.
@param {Function} [cfg.OnUpdate] Function to call whenever the data/control is updated.
@returns {Qww.DropDown.Mgr} Qww.DropDown.Mgr
*/
Qww.Ctls.DropDown.Mgr = function(cfg) {

    this.parentElement = $('#' + cfg.ElementID);    
    this.selectElementID = cfg.ElementID + "_select";
    this.Cfg = cfg;
    /// <reference path="QwwJs_DropDownCtl.js" />

    var me = this;

    setCfg = function(name, defaultVal) {
        if (cfg[name] == null) cfg[name] = defaultVal;
    }

    //
    // TODO: IMPORTANT - THE LISTBOXES WHICH THE FACTLAB CONTROLS ARE BOUND TO GENERALLY HAVE
    // HIDEEXCLUDED=TRUE HOWEVER THIS MEANS THAT IF THE PAGE SIZE IS SET TO 500 FOR EXAMPLE
    // YOU MAY GET 5 VALID ITEMS AT THE TOP THEN 495 ITEMS ALL WITH EMPTY TEXT AND DISABLED=TRUE
    // IN THE XML WHICH MAKES THE RESPONSE VERY LARGE. HERE WE NEED TO SET A SUITABLE PAGE SIZE
    // WHICH IS LARGE ENOUGH TO SHOW ALL THE ITEMS IN THE LISTBOX/DROPDOWN CONTROL WHICH WOULD
    // CONTAIN THE MOST NUMBER OF AVAILABLE ITEMS IN ORDER TO MINIMISE THE AMOUNT OF DATA IN THE XML
    //
    setCfg("PageSize", 500);
    setCfg("Theme", "DefaultTheme");
    setCfg("ShowDisabled", false);

    //this.pleaseChooseText = new Qww.TextObject.Mgr({ "ObjectID": 'TX_Words_Please_Choose' });

    this.listBoxMgr = new Qww.ListBox.Mgr(
    {    
        ObjectID: cfg.ObjectID,
        PageSize: cfg.PageSize,
        OnUpdate: function(lbm) {
            me.RenderDropDown(lbm);
        }
    });
};

Qww.Ctls.DropDown.Mgr.prototype.isFirstTime = true;

Qww.Ctls.DropDown.Mgr.prototype.GetClassName = function(itemName) {

    return "Qww_Ctls_DropDown-" + itemName + "-" + this.Cfg.Theme;
}

Qww.Ctls.DropDown.Mgr.ScanForAndCreate = function() {

    var dropDowns = jQuery(".Qww_Ctls_DropDown");

    for (var i = 0, max = dropDowns.length; i < max; i++) {

        var elem = dropDowns[i];
        
        var showDisabled = elem.getAttribute('ShowDisabled') == 'true';
        var includeSelectAll = elem.getAttribute('IncludeSelectAll') == 'true';
        var isLanguageSelector = elem.getAttribute('IsLanguageSelector') == 'true';
        var hideArrow = elem.getAttribute('HideArrow') == 'true';

        new Qww.Ctls.DropDown.Mgr({ ObjectID: elem.id, ElementID: elem.id, ShowDisabled: showDisabled, IncludeSelectAll: includeSelectAll, IsLanguageSelector: isLanguageSelector, HideArrow: hideArrow });
    }
};

Qww.Ctls.DropDown.Mgr.prototype.ShowArrowHighlight = function(show) {

    if (show) {
        this.arrowImage.show();
        this.parentElement[0].style.paddingLeft = "0";
    }
    else {
        this.arrowImage.hide();
        this.parentElement[0].style.paddingLeft = this.ARROW_WIDTH;
    }
}

Qww.Ctls.DropDown.Mgr.prototype.RenderDropDown = function(lbm) {

//    if (this.Cfg.ObjectID == 'LB_World_Lab_Bottom_Section_Fact2_Theme') {
//        alert('a');
//        debugger;
//    }
//    
    //
    // Can use lbm.Enabled to test for whether the
    // select should be visible.
    //
    if (lbm.Enabled == false) {

        if (this.Hidden != true) {
            $(this.parentElement).hide();
            this.Hidden = true;
        }

        return;
    }
    else {

        if (this.Hidden != false) {
            $(this.parentElement).show();
            this.Hidden = false;
        }
    }

    this.ARROW_WIDTH = "31px";

    if (this.isFirstTime == true) {

        //this.parentElement[0].style.border = "solid 1px red";
        //this.parentElement[0].style.width = "100px";
        //this.parentElement[0].style.paddingLeft = "50px";
        //this.parentElement[0].style.marginLeft = "50px";
        //this.parentElement[0].style.backroundImage = "url(" + Factlab.ImageRoot + "img/Qww_Ctls_DropDown/rightarrow.gif" + ")";

        //alert(this.parentElement[0].style.backroundImage);

        this.arrowImage = $("<img src='" + Factlab.ImageRoot + "img/Qww_Ctls_DropDown/rightarrow.gif' style='height:20px;width:" + this.ARROW_WIDTH + ";display:none' />");
        this.parentElement.append(this.arrowImage);
        this.parentElement.append("<select class='Qww_Ctls_DropDown_Select' id='" + this.selectElementID + "'></select>");

        this.selectElement = $('#' + this.selectElementID);

        var me = this;

        this.selectElement.change(function(evt) {

            var selectedValue = this.value;

            if (selectedValue == me.previousSelection) return;

            this.previousSelection = selectedValue;

            if (selectedValue > -1) {
                lbm.MakeSingleSelection(selectedValue, false, true);
            }
            else {
                lbm.CallAction(selectedValue, true);
            }
        });

        this.isFirstTime = false;
    }

    this.selectElement.empty();

    var captionText = lbm.Caption.Text;

    if (captionText != null) {
        if (this.Cfg.IncludeSelectAll == false) {
            this.selectElement.append("<option value='" + Qww.ListBox.Mgr.StandardAction.ClearAll + "'>" + captionText + "</option>");
        }
        else {
            var splitCaption = captionText.split('|');
            this.selectElement.append("<option value='" + Qww.ListBox.Mgr.StandardAction.ClearAll + "'>" + splitCaption[0] + "</option>");
            this.selectElement.append("<option value='" + Qww.ListBox.Mgr.StandardAction.SelectAll + "'>" + splitCaption[1] + "</option>");
        }
    }

    var selectedIndex = -1;
    var currentIndex = this.selectElement[0].childNodes.length;

    var selectedCount = 0;
    var itemDropDownCount = 0;

    for (var i = 0, max = lbm.Results.All.length; i < max; i++) {
        var lbi = lbm.Results.All[i];

        if (this.Cfg.IsLanguageSelector == true) {
            if (!(lbi.Text == 'Swedish' || lbi.Text == 'English' || lbi.Text == 'Romanian' || lbi.Text == 'Danish' || lbi.Text == 'Norwegian')) continue;
        }

        if (lbi.State === Qww.ListBox.Mgr.ItemState.Selected) {
            selectedCount++;
        }

        var addItem = !(this.Cfg.ShowDisabled === false && lbi.State === Qww.ListBox.Mgr.ItemState.Disabled);

        if (addItem) {

            var dropDownText = lbi.Text.split('|')[0];

            this.selectElement.append("<option class='" + this.GetClassName("Option-" + Qww.ListBox.Mgr.ItemState.GetStateAsString(lbi.State)) + "' value='" + lbi.Value + "'>" + dropDownText + "</option>");

            if (lbi.State === Qww.ListBox.Mgr.ItemState.Selected) {
                selectedIndex = currentIndex;
            }
            itemDropDownCount++;
            currentIndex++;
        }
    }

    if (itemDropDownCount > 1 && selectedCount > 1)
        selectedIndex = 1;

    if (selectedIndex > -1) {
        this.selectElement[0].selectedIndex = selectedIndex;
    }

    this.previousSelection = this.selectElement[0].value;

    if (!this.Cfg.HideArrow) {
        this.ShowArrowHighlight(selectedIndex == -1);
    }
    else {
        this.ShowArrowHighlight(false);
    }
};

Qww.Ctls.DropDownMultiSelect = {};

/**
Constructs a new Qww.DropDownMultiSelect.Mgr instance.
@constructor
@class JavaScript class to render a listbox as a DropDownMultiSelect control.<br />
@param {Object} cfg JSON object to configure the DropDownMultiSelect.
@param {String} cfg.ElementID ID of the html element (e.g. div or span) 
where the drop down should be rendered.
@param {String} cfg.ObjectID Id of the ListBox in the QlikView application.
@param {String} [cfg.Theme='DefaultTheme'] Theme name to be appended to any class names 
used by the control.
@param {Number} [cfg.PageSize=5000] Page size of data to extract from the underlying listbox. 
As the control is not 'paged' this should be large enough to return all the data for the drop 
down in the first (and only) page requested.
@returns {Qww.DropDownMultiSelect.Mgr} Qww.DropDownMultiSelect.Mgr
*/
Qww.Ctls.DropDownMultiSelect.Mgr = function(cfg) {

    var 
        me = this,
        elemId = cfg.ElementID;

    this.parentElement = $('#' + elemId);
    this.Cfg = cfg;
    qwwHub.Register(this);
    if (cfg.InjectHtml) {

        var titleStyle = '';
        var resultStyle = '';
        var width = this.parentElement[0].style.width.replace("px", "");

        if (cfg.TitleWidth) {
            titleStyle = "style='width:" + cfg.TitleWidth + "'";
            resultStyle = "style='width:" + (width - (1 * (cfg.TitleWidth).replace("px", "")) - 5) + "px;float:right;'";
        }

        var html =
            "<div><div " + titleStyle + " class='Qww_Ctls_DropDownMultiSelect_Title'>Loading...</div>" +
            "<div class='Qww_Ctls_DropDownMultiSelect_ResultsAndDropDown' style='width:1px;float:left;padding-top:3px;'>" +
        //"<img alt='' src='../img/QwwJs_DropDownMultiSelectCtl/DropDownArrowBlack.png' />" +
                "<div class='Qww_Ctls_DropDownMultiSelect_Results'>" +
                    "<div style='height:28px;background-color:#E8E8E8;width:100%;'><img style='float:right;padding-right:10px;padding-top:7px;' src='../img/x.png'><img src='../img/clear.png' style='float:right;cursor:pointer;padding-right:10px;padding-top:7px;' onclick='clearListBox(\"" + cfg.ObjectID + "\")'/></div>" +
                    "<div class='Qww_Ctls_DropDownMultiSelect_Results_Inner'>Loading...</div>" +
        //"<a href='#' class='Qww_Ctls_DropDownMultiSelect_Results_CloseButton'>[X]</a>" +
                "</div>" +
            "</div>" +
            "<div " + resultStyle + "class='Qww_Ctls_DropDownMultiSelect_Selection'></div></div>";

        this.parentElement.html(html);
    }


    this.captionElem = $("#" + elemId + " .Qww_Ctls_DropDownMultiSelect_Title");
    this.resultsDiv = $("#" + elemId + " .Qww_Ctls_DropDownMultiSelect_Results");
    this.resultsInnerDiv = $("#" + elemId + " .Qww_Ctls_DropDownMultiSelect_Results_Inner");
    this.selectionElem = $("#" + elemId + " .Qww_Ctls_DropDownMultiSelect_Selection");
    this.dropDown = $("#" + elemId + " .Qww_Ctls_DropDownMultiSelect_ResultsAndDropDown");

    this.isDirty = true;
    this.ResultsVisible = false;

    function dropDownClicked() {
        me.OnDropDownClicked();

        // return false here so that document level 
        // handler does not fire and close dropdowns.
        return false;
    };

    this.dropDown.click(dropDownClicked);
    this.captionElem.click(dropDownClicked);
    this.selectionElem.click(dropDownClicked);

    Qww.Ctls.DropDownMultiSelect.Mgr.Instances.push(this);

    // Register a function to close this so that other controls
    // can call Factlab.CloseAnyPopoutControls() to hide these as well.
    Factlab.CloseFunctionsForPopouts.push(function() { me.resultsDiv.hide(); });

    setCfg = function(name, defaultVal) {
        if (cfg[name] == null) cfg[name] = defaultVal;
    }

    //
    // TODO: IMPORTANT - THE LISTBOXES WHICH THE FACTLAB CONTROLS ARE BOUND TO GENERALLY HAVE
    // HIDEEXCLUDED=TRUE HOWEVER THIS MEANS THAT IF THE PAGE SIZE IS SET TO 500 FOR EXAMPLE
    // YOU MAY GET 5 VALID ITEMS AT THE TOP THEN 495 ITEMS ALL WITH EMPTY TEXT AND DISABLED=TRUE
    // IN THE XML WHICH MAKES THE RESPONSE VERY LARGE. HERE WE NEED TO SET A SUITABLE PAGE SIZE
    // WHICH IS LARGE ENOUGH TO SHOW ALL THE ITEMS IN THE LISTBOX/DROPDOWN CONTROL WHICH WOULD
    // CONTAIN THE MOST NUMBER OF AVAILABLE ITEMS IN ORDER TO MINIMISE THE AMOUNT OF DATA IN THE XML
    //
    setCfg("PageSize", 500);
    setCfg("Theme", "DefaultTheme");

    if (cfg.LoadKey == null) {
        this.listBoxMgr = new Qww.ListBox.Mgr(
        {
            ObjectID: cfg.ObjectID,
            PageSize: cfg.PageSize,
            OnUpdate: function(lbm) {
                me.OnListBoxUpdated(lbm);
            }
        });
        this.IsLoaded = true;
    }
};

Qww.Ctls.DropDownMultiSelect.Mgr.Load = function(loadKey) {

    if (!this.IsLoaded) {
        var arr = Qww.Ctls.DropDownMultiSelect.Mgr.Instances;

        for (var i = 0, max = arr.length; i < max; i++) {
            var ctl = arr[i];
            if (loadKey == "*" || ctl.Cfg.LoadKey == loadKey) ctl.Load();
        }
    }
}

Factlab.LoadControlFunctions.push(Qww.Ctls.DropDownMultiSelect.Mgr.Load);

Qww.Ctls.DropDownMultiSelect.Mgr.prototype.Load = function() {

    var me = this;

    this.listBoxMgr = new Qww.ListBox.Mgr(
    {
        ObjectID: this.Cfg.ObjectID,
        PageSize: this.Cfg.PageSize,
        OnUpdate: function(lbm) {
            me.OnListBoxUpdated(lbm);
        }
    });

    this.listBoxMgr.Initialise();
    this.IsLoaded = true;
};

Qww.Ctls.DropDownMultiSelect.Mgr.prototype.OnDropDownClicked = function() {

    for (var i = 0, max = Qww.Ctls.DropDownMultiSelect.Mgr.Instances.length; i < max; i++) {
        var instance = Qww.Ctls.DropDownMultiSelect.Mgr.Instances[i];
        if (instance != this) instance.resultsDiv.hide();
    }

    if (this.ResultsVisible == false) {
        this.resultsDiv.show();
        //this.RenderResults();
        this.ResultsVisible = true;
    }
    else {
        this.resultsDiv.hide();
        this.ResultsVisible = false;
    }
}

Qww.Ctls.DropDownMultiSelect.Mgr.ScanForAndCreate = function() {

    var 
        dropDowns = jQuery(".Qww_Ctls_DropDownMultiSelect"),
        elem;

    for (var i = 0, max = dropDowns.length; i < max; i++) {

        elem = dropDowns[i];
        var loadkey = elem.getAttribute('loadkey');
        var injecthtml = !(elem.getAttribute('injecthtml') == 'false');
        var titleWidth = elem.getAttribute('titlewidth');

        new Qww.Ctls.DropDownMultiSelect.Mgr({ ObjectID: elem.id, ElementID: elem.id, InjectHtml: injecthtml, TitleWidth: titleWidth, LoadKey: loadkey});
    }
};

Qww.Ctls.DropDownMultiSelect.Mgr.prototype.RenderResults = function() {

    //return;

    if (this.isDirty == true) {

        var 
            lbm = this.listBoxMgr,
            all = lbm.Results.All,
            passiveCount = 0,
            singlePassiveItem,
            selectedCount = 0,
            singleSelectedItem,
            associatedCount = 0,
            singleAssociatedItem,
            elem = this.resultsInnerDiv;

        //        if (this.onItemClicked == null) {
        //            this.onItemClicked = function() {
        //                var selectedValue = this.getAttribute('lbivalue');
        //                lbm.MakeSingleSelection(selectedValue, false, true); ;
        //                this.className = 'Qww_Ctls_DropDownMultiSelect_Results_Item_State_Updating';
        //                return false;
        //            }
        //        }

        if (this.onItemClicked == null) {
            this.onItemClicked = function(e) {

                var src = e.originalTarget

                if (src == null) src = e.originalEvent.srcElement;

                var selectedValue = src.getAttribute('lbivalue')

                if (src.className != 'Qww_Ctls_DropDownMultiSelect_Results_Item_Disabled') {
                    lbm.MakeSingleSelection(selectedValue, false, true); ;
                    src.className = 'Qww_Ctls_DropDownMultiSelect_Results_Item_State_Updating';
                }
                
                return false;
            }

            elem.click(this.onItemClicked);
        }

        elem.empty();

        var html = [];

        for (var i = 0, max = all.length; i < max; i++) {

            var 
                lbi = all[i],
                text = lbi.Text;

            if (text == '|') {
                continue;
            }

            var state = 'Disabled';

            if (text.indexOf("|") > -1) {
                var parts = text.split('|'),
                    text = parts[1],
                    flag = parts[0];

                if (flag == 'B') {
                    if (Factlab.TopFilterHasSelection && lbi.State == 0) {
                        state = 'Passive';
                    }
                    else {
                        state = 'Associated';
                    }
                }
                else if (flag == 'A') {
                    state = 'Ticked';
                }
                else {
                    // state = 'Disabled'; this is the default.
                }
            }

            switch (state) {
                case 'Ticked':
                    selectedCount++;
                    singleSelectedItem = (text.length >= 12) ? text.substring(0, 9) + '...' : text;
                    break;

                case 'Associated':
                    associatedCount++;
                    singleAssociatedItem = (text.length >= 12) ? text.substring(0, 9) + '...' : text;
                    break;

                case 'Passive':
                    passiveCount++;
                    singlePassiveItem = (text.length >= 12) ? text.substring(0, 9) + '...' : text;
                    break;
            };

            html.push("<div class='Qww_Ctls_DropDownMultiSelect_Results_Item_" + state + "' lbivalue='" + lbi.Value + "'>" + text + "</div>");
        }

        setTimeout(function() { elem.html(html.join('')); });

        if (selectedCount == 0 && associatedCount == 1)
            this.selectionElem.html("<div style='line-height:15px;width:100%;'><img src='../img/selected.png' /><span style='padding-left:3px'>" + singleAssociatedItem + "</span></div>");
        else if (selectedCount == 0 && passiveCount == 1)
            this.selectionElem.html("<div style='line-height:15px;width:100%;'><img src='../img/partiallyselected.png' /><span style='padding-left:3px'>" + singlePassiveItem + "</span></div>");
        else if (selectedCount == 1)
            this.selectionElem.html("<div style='line-height:15px;width:100%;'><img src='../img/selected.png' /><span style='padding-left:3px'>" + singleSelectedItem + "</span></div>");
        else if (selectedCount == 0 && passiveCount > 1)
            this.selectionElem.html("<div class='Passive' style='height:12px;width:100%;'></div>");
        else
            this.selectionElem.html("<div class='Associated' style='height:15px;width:100%;'></div>");

    }

    this.isDirty = false;
}

Qww.Ctls.DropDownMultiSelect.Mgr.prototype.OnAllAvqUpdateCompletesCalled = function() {
    this.PaintListBox();
};

Qww.Ctls.DropDownMultiSelect.Mgr.prototype.PaintListBox = function() {

    var lbm = this.latestListBoxMgr;

    if (lbm == null) { return; }

    this.isDirty = true;
    this.captionElem.text(lbm.Caption.Text);

    //if (this.ResultsVisible == true)
    this.RenderResults();
};

Qww.Ctls.DropDownMultiSelect.Mgr.prototype.OnListBoxUpdated = function(lbm) {
    this.latestListBoxMgr = lbm;
};

Qww.Ctls.DropDownMultiSelect.Mgr.Instances = [];

// Close all instances when user clicks somewhere in the page.
$(document).click(function() {
    for (var i = 0, max = Qww.Ctls.DropDownMultiSelect.Mgr.Instances.length; i < max; i++)
        Qww.Ctls.DropDownMultiSelect.Mgr.Instances[i].resultsDiv.hide();
});


Qww.Ctls.ScrollingMultiSelect = {};

/**
Constructs a new Qww.ScrollingMultiSelect.Mgr instance.
@constructor
@class JavaScript class to render a listbox as a ScrollingMultiSelect control.<br />
@param {Object} cfg JSON object to configure the ScrollingMultiSelect.
@param {String} cfg.ElementID ID of the html element (e.g. div or span) 
where the drop down should be rendered.
@param {String} cfg.ObjectID Id of the ListBox in the QlikView application.
@param {String} [cfg.Theme='DefaultTheme'] Theme name to be appended to any class names 
used by the control.
@param {Number} [cfg.PageSize=5000] Page size of data to extract from the underlying listbox. 
As the control is not 'paged' this should be large enough to return all the data for the drop 
down in the first (and only) page requested.
@returns {Qww.ScrollingMultiSelect.Mgr} Qww.ScrollingMultiSelect.Mgr
*/


Qww.Ctls.ScrollingMultiSelect.Mgr = function(cfg) {

    this.parentElement = $('#' + cfg.ElementID);
    this.Cfg = cfg;
    var me = this;
    
    this.IsDirty = true;
    this.LastTopFilterHasSelection = false;
    
    var elemId = cfg.ElementID;
    this.captionElem = $("#" + elemId + " .Qww_Ctls_ScrollingMultiSelect_Title");
    this.resultsInnerDiv = $("#" + elemId + " .Qww_Ctls_ScrollingMultiSelect_Results");

    setCfg = function(name, defaultVal) {
        if (cfg[name] == null) cfg[name] = defaultVal;
    }

    qwwHub.Register(this);

    Qww.Ctls.ScrollingMultiSelect.Mgr.Instances.push(this);

    //
    // TODO: IMPORTANT - THE LISTBOXES WHICH THE FACTLAB CONTROLS ARE BOUND TO GENERALLY HAVE
    // HIDEEXCLUDED=TRUE HOWEVER THIS MEANS THAT IF THE PAGE SIZE IS SET TO 500 FOR EXAMPLE
    // YOU MAY GET 5 VALID ITEMS AT THE TOP THEN 495 ITEMS ALL WITH EMPTY TEXT AND DISABLED=TRUE
    // IN THE XML WHICH MAKES THE RESPONSE VERY LARGE. HERE WE NEED TO SET A SUITABLE PAGE SIZE
    // WHICH IS LARGE ENOUGH TO SHOW ALL THE ITEMS IN THE LISTBOX/DROPDOWN CONTROL WHICH WOULD
    // CONTAIN THE MOST NUMBER OF AVAILABLE ITEMS IN ORDER TO MINIMISE THE AMOUNT OF DATA IN THE XML
    //
    setCfg("PageSize", 500);
    setCfg("Theme", "DefaultTheme");

    if (cfg.LoadKey == null) {
        this.listBoxMgr = new Qww.ListBox.Mgr(
        {
            ObjectID: this.Cfg.ObjectID,
            PageSize: this.Cfg.PageSize,
            OnUpdate: function(lbm) {
                me.OnListBoxUpdated(lbm);
            }
        });
        this.IsLoaded = true;
    }
};

Qww.Ctls.ScrollingMultiSelect.Mgr.Load = function(loadKey) {

    if (!this.IsLoaded) {
        var arr = Qww.Ctls.ScrollingMultiSelect.Mgr.Instances;

        for (var i = 0, max = arr.length; i < max; i++) {
            var ctl = arr[i];
            if (loadKey == "*" || ctl.Cfg.LoadKey == loadKey) ctl.Load();
        }
    }
}

Factlab.LoadControlFunctions.push(Qww.Ctls.ScrollingMultiSelect.Mgr.Load);

Qww.Ctls.ScrollingMultiSelect.Mgr.prototype.Load = function() {

    var me = this;

    this.listBoxMgr = new Qww.ListBox.Mgr(
    {
        ObjectID: this.Cfg.ObjectID,
        PageSize: this.Cfg.PageSize,
        OnUpdate: function(lbm) {
            me.OnListBoxUpdated(lbm);
        }
    });

    this.listBoxMgr.Initialise();
    this.IsLoaded = true;
};

Qww.Ctls.ScrollingMultiSelect.Mgr.ScanForAndCreate = function() {

    var dropDowns = jQuery(".Qww_Ctls_ScrollingMultiSelect");

    for (var i = 0, max = dropDowns.length; i < max; i++) {

        var elem = dropDowns[i];

        var loadkey = elem.getAttribute('loadkey');
        var injecthtml = !(elem.getAttribute('injecthtml') == 'false');
        new Qww.Ctls.ScrollingMultiSelect.Mgr({ ObjectID: elem.id, ElementID: elem.id, InjectHtml: injecthtml, LoadKey: loadkey });
    }
};


Qww.Ctls.ScrollingMultiSelect.Mgr.prototype.OnAllAvqUpdateCompletesCalled = function() {
    this.PaintListBox();
};

Qww.Ctls.ScrollingMultiSelect.Mgr.prototype.PaintListBox = function() {

    //return;
    //if (!(!this.IsDirty && (this.LastTopFilterHasSelection != Factlab.TopFilterHasSelection)))
    //   return;

    var lbm = this.latestListBoxMgr;
    if (lbm == null) { return; }

    this.captionElem.html("<div><span style='float:left'>" + lbm.Caption.Text + "</span><img src='../img/clear.png' style='float:right;cursor:pointer;' onclick='clearListBox(\"" + lbm.Cfg.ObjectID + "\")'/></div>");
    //this.captionElem.text(lbm.Caption.Text);

    //    if (this.onItemClicked == null) {
    //        this.onItemClicked = function() {
    //            var selectedValue = this.getAttribute('lbivalue');
    //            lbm.MakeSingleSelection(selectedValue, false, true);
    //            this.className = 'Qww_Ctls_ScrollingMultiSelect_Results_Item_State_Updating';
    //            Factlab.CloseAnyPopoutControls();
    //            return false;
    //        }
    //    }

    var 
        elem = this.resultsInnerDiv,
        all = lbm.Results.All,
        html = [];

    if (this.onItemClicked == null) {
        this.onItemClicked = function(e) {

            var src = e.originalTarget
            if (src == null) src = e.originalEvent.srcElement;

            var selectedValue = src.getAttribute('lbivalue')

            if (src.className != 'Qww_Ctls_ScrollingMultiSelect_Results_Item_Disabled') {
                lbm.MakeSingleSelection(selectedValue, false, true);
                src.className = 'Qww_Ctls_ScrollingMultiSelect_Results_Item_State_Updating';
            }

            return false;
        }

        elem.click(this.onItemClicked);
    }

    elem.empty();

    for (var i = 0, max = lbm.Results.All.length; i < max; i++) {

        var 
            lbi = all[i],
            text = lbi.Text;

        if (text == '|') {
            continue;
        }

        var state = "Disabled";

        if (text.indexOf("|") > -1) {
            var 
                parts = text.split('|'),
                text = parts[1],
                flag = parts[0];

            if (flag == 'B') {
                if (Factlab.TopFilterHasSelection && lbi.State == 0) {
                    state = 'Mixed';
                }
                else {
                    state = 'Associated';
                }
            }
            else if (flag == 'A') {
                state = 'Ticked';

            }
            else {
                //state = 'Disabled'; default
            }
        }

        //        var lbElem = $("<div class='Qww_Ctls_ScrollingMultiSelect_Results_Item_" + state + "' lbivalue='" + lbi.Value + "'>" + text + "</div>");

        //        if (state != 'Disabled') {
        //            lbElem.click(this.onItemClicked);
        //        }

        //        elem.append(lbElem);

        html.push("<div class='Qww_Ctls_ScrollingMultiSelect_Results_Item_" + state + "' lbivalue='" + lbi.Value + "'>" + text + "</div>");
    }

    setTimeout(function() { elem.html(html.join('')); });

    this.IsDirty = false;
    this.LastTopFilterHasSelection = Factlab.TopFilterHasSelection;
};

Qww.Ctls.ScrollingMultiSelect.Mgr.prototype.OnListBoxUpdated = function(lbm) {
    this.IsDirty = true;
    this.LastTopFilterHasSelection = Factlab.TopFilterHasSelection;
    this.latestListBoxMgr = lbm;
};

Qww.Ctls.ScrollingMultiSelect.Mgr.Instances = [];




Qww.Ctls.TextObject = {};

/**
Constructs a new Qww.DropDown.Mgr instance.
@constructor
@class JavaScript class to render a listbox as a DropDown control.<br />
@param {Object} cfg JSON object to configure the DropDown.
@param {String} cfg.ElementID ID of the html element (e.g. div or span) 
where the drop down should be rendered.
@param {String} cfg.ObjectID Id of the ListBox in the QlikView application.
@param {String} [cfg.Theme='DefaultTheme'] Theme name to be appended to any class names 
used by the control.
@param {Boolean} [cfg.ShowDisabled=false] Whether disabled items should be shown.
@param {Number} [cfg.PageSize=5000] Page size of data to extract from the underlying listbox. 
As the control is not 'paged' this should be large enough to return all the data for the drop 
down in the first (and only) page requested.
@param {Function} [cfg.OnUpdate] Function to call whenever the data/control is updated.
@returns {Qww.DropDown.Mgr} Qww.DropDown.Mgr
*/
Qww.Ctls.TextObject.Mgr = function(cfg) {

    this.parentElement = $('#' + cfg.ElementID);
    this.parentDOMElement = this.parentElement[0];
    this.Cfg = cfg;
    var me = this;

    setCfg = function(name, defaultVal) {
        if (cfg[name] == null) cfg[name] = defaultVal;
    }
    setCfg("Theme", "DefaultTheme");

    new Qww.TextObject.Mgr(
    {
        ObjectID: cfg.ObjectID,
        OnUpdate: function(txtObj) {
            me.RenderTextObject(txtObj);
        }
    });
};

Qww.Ctls.TextObject.Mgr.ScanForAndCreate = function() {

    var dropDowns = jQuery(".Qww_Ctls_TextObject");

    var noDropDowns = dropDowns.length;

    for (var i = 0; i < noDropDowns; i++) {

        var dd = dropDowns[i];

        var showToolTip = dd.getAttribute('setToolTip') == 'true';

        new Qww.Ctls.TextObject.Mgr({ ObjectID: dd.id, ElementID: dd.id, setToolTip: showToolTip});
    }
};

Qww.Ctls.TextObject.Mgr.prototype.RenderTextObject = function(textObject) {

    if (textObject.Enabled == false) {

        if (this.Hidden != true) {
            this.parentElement.hide();
            this.Hidden = true;
        }
    }
    else {

        if (textObject.Text == null) return;
        //this.parentElement.text(textObject.Text);
        this.parentDOMElement.innerHTML = textObject.Text;
        if (this.Cfg.setToolTip) {
            this.parentDOMElement.setAttribute("title", textObject.Text);
        }

        if (Qww.Ctls.Debug) {
            this.parentDOMElement.setAttribute("title", this.Cfg.ObjectID);
        }

        if (this.Hidden != false) {
            this.parentElement.show();
            this.Hidden = false;
        }
    }
};


// --------- Start of Excel Download Feature --------- //
Qww.Ctls.Excel = {};

Qww.Ctls.Excel.DownloadExcelFile = function(objId) {
    qwwHub.DoAvqSet(null, "Document." + objId + ".Caption.XL", "action", "", true);
    try {
        pageTracker._trackEvent('TableExportedToExcel', objId);
    }
    catch (e) { }

    // Seems the default qvs js libraries take care of monitoring for the
    // response of the above and downloading the excel file. For workbench
    // only version we will need to monitor for response:
    // <?xml version="1.0" encoding="UTF-8" ?>
    //  <result .... >
    //    <open url="http://servname/QvPrint/d2c9f901d9614674bc28ed29964ade38.xls"/>
    //       <object .... 
    // And open accordingly
};
// --------- End of Excel Download Feature --------- //

Qww.Ctls.Button = {};

/**
Constructs a new Qww.Button.Mgr instance. The button will be hidden if the underlying 
QlikView button is hidden. If the underlying QlikView button is disabled the class 'Qww_Ctls_Button_disabled' 
will be added to the button as well as the attribute 'disabled'.
@constructor
@class JavaScript class to render a listbox as a DropDown control.<br />
@param {Object} cfg JSON object to configure the DropDown.
@param {String} cfg.ElementID ID of the html element (e.g. div or span) 
where the drop down should be rendered.
@param {String} cfg.ObjectID Id of the ListBox in the QlikView application.
@param {String} [cfg.Theme='DefaultTheme'] Theme name to be appended to any class names 
used by the control.
@param {Boolean} [cfg.ShowDisabled=false] Whether disabled items should be shown.
@param {Number} [cfg.PageSize=5000] Page size of data to extract from the underlying listbox. 
As the control is not 'paged' this should be large enough to return all the data for the drop 
down in the first (and only) page requested.
@param {Function} [cfg.OnUpdate] Function to call whenever the data/control is updated.
@returns {Qww.DropDown.Mgr} Qww.DropDown.Mgr
*/
Qww.Ctls.Button.Mgr = function(cfg) {

    this.parentElement = $('#' + cfg.ElementID);
    this.Cfg = cfg;
    this.isFirstTime = true;
    var me = this;

    setCfg = function(name, defaultVal) {
        if (cfg[name] == null) cfg[name] = defaultVal;
    }
    setCfg("Theme", "DefaultTheme");

    new Qww.Button.Mgr(
    {
        ObjectID: cfg.ObjectID,
        OnUpdate: function(btnMgr) {
            me.RenderButtonObject(btnMgr);
        }
    });
};

//Qww.Ctls.TextObject.Mgr.prototype.GetClassName = function(itemName) {

//    return "Qww_Ctls_DropDown-" + itemName + "-" + this.Cfg.Theme;
//}

Qww.Ctls.Button.Mgr.ScanForAndCreate = function() {

    var buttons = jQuery(".Qww_Ctls_Button");

    var noButtons = buttons.length;

    //console.log("Buttons = " + noButtons);
    //console.time("Create Buttons");

    for (var i = 0; i < noButtons; i++) {
        var button = buttons[i];
        new Qww.Ctls.Button.Mgr({ ObjectID: button.id, ElementID: button.id });
    }

    //console.timeEnd("Create Buttons");
};

Qww.Ctls.Button.Mgr.prototype.OnClick = function() {
    this.ButtonMgr.SendClick(true);
};

Qww.Ctls.Button.Mgr.prototype.RenderButtonObject = function(btnObj) {

    if (this.button == null) {

        //console.time("Create Button");
        var btn = document.createElement("input");
        btn.setAttribute("type", "button");

        if (Qww.Ctls.Debug) {
            btn.setAttribute("title", this.Cfg.ObjectID);
        }

        btn.ButtonMgr = btnObj;
        this.parentElement.append(btn);
        btn.onclick = this.OnClick;

        this.button = btn;

        //console.timeEnd("Create Button");
    }

    this.button.setAttribute("value", btnObj.Caption);

    if (btnObj.Mode == Qww.QlikViewObjectState.Hidden) {

        if (this.Hidden != true) {
            this.parentElement.hide();
            this.Hidden = true;
        }
    }
    else {

        if (this.Hidden != false) {
            this.parentElement.show();
            this.Hidden = false;
        }

        if (btnObj.Mode == Qww.QlikViewObjectState.Disabled) {
            $(this.button).addClass("Qww_Ctls_Button_disabled").attr("disabled", true);
        }
        else {
            $(this.button).removeClass("Qww_Ctls_Button_disabled").removeAttr("disabled");
        }
    }
};


/**
@fileOverview
Part of the QlikWeb WorkBench Javascript Library (http://www.qlikwebworkbench.com)<br /><br />
Copyright (c) 2009 QlikTech International AB (http://www.qliktech.com)<br /><br />
All Rights Reserved. Email support@qliktech.com for licensing and support information.<br /><br />
@author <a href="mailto:email@industrialcodebox.com">Industrial CodeBox</a>
*/

Qww.Sheet = function() {

    this.Selected = false;

    this.Enabled = false;

    this.Text = "";

    this.Name = "";

    this.Mode = null;
};

Qww.Sheet.CreateFromXmlNode = function(node) {

    var sheet = new Qww.Sheet();

    this.Mode = node.getAttribute("mode");
    this.Enabled = (node.getAttribute("mode") == "enabled");
    this.Text = node.getAttribute("text");
    this.Selected = (node.getAttribute("selected") == "true");
    this.Name = node.getAttribute("name");

    return sheet;
};

/**
Constructs a new Qww.Sheet.Mgr button instance.
@class JavaScript class to manage communication with an underlying QlikView text object.<br />
@param {Object} cfg JSON object to configure ButtonMgr.
@param {String} cfg.ObjectID Id of the text object in the QlikView application.
@param {String} [cfg.ApplicationID=null] Id/Name of the QlikView application. Note this is <strong>only</strong> necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null.
@param {Bool} [cfg.DoNotInitialise=false] Set this to false if you do not want this particular object to initialise the 
underlying object with QlikView Server. Use this option for example if you are already using another object or control which 
will have already initialised this. In this mode this object will simply parse the existing data for this object as it comese from 
QlikView Server.
@param {Function} [cfg.OnUpdate] Function to call whenever an update is received for the button (for example 
if the button text changes). The function should accept a single parameter which is reference to the TextObjectMgr itself.
*/
Qww.Sheet.Mgr = function(cfg) {

    if (cfg == null) cfg = {};

    var _isInitialized = false;
    var me = this;

    setCfg = function(name, defaultVal) {
        if (cfg[name] == null) cfg[name] = defaultVal;
    }

    setCfg("ApplicationID", null);
    setCfg("SheetIDs", []);

    this.Sheets = [];
    this.ManagedElements = [];
    this.ActiveSheetID = null;

    /**
    Reference to the configuration object which was used to create construct the 
    object. This allows certain properties to be updated after initial instantiation.
    @type Object
    */
    this.Cfg = cfg;

    /**
    @ignore
    Returns an array of Qww.QvsConnector.Set objects which represents the initiasation which 
    needs to be sent to QlikView server in order to initialise this object.
    @returns {Qww.QvsConnector.Set[]} Array of Qww.QvsConnector.Set objects which represents 
    the initiasation for this object.
    */
    this.GetInitialisationSets = function() {

        var sets = [];

        var sheetIds = this.Cfg.SheetIDs;

        //        for (var i = 0; i < sheetIds.length; i++) {
        //            //sets.push(new Qww.QvsConnector.Set(this.Cfg.ApplicationID, "Document." + sheetIds[i], "add", "mode;text", i === (sheetIds.length - 1))); 
        //        }
        //        

        //debugger;
        // <set name="Document.ActiveSheet" add="mode;text" clientsizeWH="3988:1844"/>
        sets.push(new Qww.QvsConnectorSet(this.Cfg.ApplicationID, "Document.ActiveSheet", "add", "mode;text", true));

        _isInitialized = true;

        return sets;
    };

    function initialize() {

        if (!_isInitialized) {

            qwwHub.DoAllSets(me.GetInitialisationSets());

            return false;
        }

        _isInitialized = true;

        return true; // handshake - there will not be a new update
    };


    this.OnAllAvqUpdateCompletesCalled = function() {

        if (!cfg.DoNotInitialise || cfg.DoNotInitialise == false) {

            if (!_isInitialized) {
                if (!initialize()) {
                    return;
                }
            }
        }

        for (var i = 0; i < this.ManagedElements.length; i++) {

            var elem = this.ManagedElements[i];
            var sheetID = elem.getAttribute("SheetID");

            if (sheetID == "Loading_Step") {
                $(elem).hide();
            }
            else {
                $(elem).show();
            }
        }


        //        this.Sheets = [];

        //        for (var i = 0; i < this.Cfg.SheetIDs.length; i++) {

        //            var CH = qwwHub.DoAvqSelect(cfg.ApplicationID, this.Cfg.SheetIDs[i]);

        //            if (CH != null) {
        //                this.Sheets.push(Qww.Sheet.CreateFromXmlNode(CH));
        //            }
        //        };

        //        var CH = qwwHub.DoAvqSelect(cfg.ApplicationID, "ActiveSheet");

        //        if (CH != null) {

        //            var prev = this.ActiveSheetID;
        //            this.ActiveSheetID = CH.getAttribute("text");

        //            if (this.ActiveSheetID != null) {
        //                if (this.ActiveSheetID != prev && this.Cfg.OnActiveSheetChanged) {

        //                    this.UpdateManagedElements();
        //                    this.Cfg.OnActiveSheetChanged(this, prev);
        //                }
        //            }
        //        }

        //        if (me.Cfg.OnUpdate)
        //            me.Cfg.OnUpdate(this);
    };

    this.UpdateManagedElements = function() {


        if (this.ActiveSheetID == null) return;

        for (var i = 0; i < this.ManagedElements.length; i++) {

            var elem = this.ManagedElements[i];
            var sheetID = elem.getAttribute("SheetID");

            if (sheetID == "Loading_Step") {
                $(elem).hide();
            }

            continue;

            //            if (this.ActiveSheetID == sheetID) {

            //                if (elem.HiddenBySheetMgr != false) {
            //                    $(elem).show();
            //                    elem.HiddenBySheetMgr = false;
            //                }
            //            }
            //            else {
            //                if (elem.HiddenBySheetMgr != true) {
            //                    $(elem).hide();
            //                    elem.HiddenBySheetMgr = true;
            //                }
            //            }
        }

    };

    this.ScanForPanelsToManage = function() {

        this.ManagedElements = [];
        var elements = jQuery(".Qww_Sheet");

        for (var i = 0; i < elements.length; i++) {
            this.ManagedElements.push(elements[i]);
        }

        this.UpdateManagedElements();
    };

    if (qwwHub)
        qwwHub.Register(this);
};

Qww.Ctls.Chart = {};

/**
Constructs a new Qww.Chart.Mgr instance.
@constructor
@class JavaScript class to render a listbox as a DropDown control.<br />
@param {Object} cfg JSON object to configure the DropDown.
@param {String} cfg.ElementID ID of the html element (e.g. div or span) 
where the drop down should be rendered.
@param {String} cfg.ObjectID Id of the ListBox in the QlikView application.
@returns {Qww.Chart.Mgr} Qww.Chart.Mgr
*/
Qww.Ctls.Chart.Mgr = function(cfg) {

    this.parentElement = $('#' + cfg.ElementID);
    this.Cfg = cfg;

    this.RenderChartObject();
};

Qww.Ctls.Chart.Mgr.ScanForAndCreate = function() {
    var charts = jQuery(".Qww_Ctls_Chart");

    for (var i = 0; i < charts.length; i++) {
        var chart = new Qww.Ctls.Chart.Mgr({ ObjectID: charts[i].id, ElementID: charts[i].id, Width: charts[i].style.width, Height: charts[i].style.height });
    }

};

Qww.Ctls.Chart.Mgr.prototype.RenderChartObject = function() {

    var chartHtml = [];

    chartHtml.push("<span class='Qww_Ctls_Chart' id=" + this.Cfg.ObjectID + ">");
    chartHtml.push("<div avq='frame:." + this.Cfg.ObjectID + "' style='display:none; width:" + this.parentElement[0].style.width + "; height:" + this.parentElement[0].style.height + ";' class='Chart' id='" + this.Cfg.ObjectID + "_frame'>");
    chartHtml.push("<div avq='label:." + this.Cfg.ObjectID + ".Graph' class='graph'>");
    //    chartHtml.push("<img style='width:auto; height:auto;' galleryimg='no' avq='binary:." + this.Cfg.ObjectID + ".Graph'>");
    chartHtml.push("<img style='width:" + this.Cfg.Width + ";height:" + this.Cfg.Height + "' galleryimg='no' avq='binary:." + this.Cfg.ObjectID + ".Graph'>");
    chartHtml.push("</div>");
    chartHtml.push("</div>");
    chartHtml.push("</span>");

    this.parentElement.append(chartHtml.join(''));
};



Qww.Ctls.LeftMenu = {};


/**
Constructs a new Qww.Ctls.LeftMenu.Mgr instance.
@constructor
@class JavaScript class to render a listbox as control.<br />
@param {Object} cfg JSON object to configure the DropDown.
@param {String} cfg.ElementID ID of the html element (e.g. div or span) 
where the control should be rendered.
@param {String} cfg.ObjectID Id of the ListBox in the QlikView application.
@returns {Qww.Ctls.LeftMenu.Mgr} Qww.Chart.Mgr*/
Qww.Ctls.LeftMenu.Mgr = function(cfg) {

    this.parentElement = $('#' + cfg.ElementID);
    this.Cfg = cfg;

    Qww.Ctls.LeftMenu.Mgr.Instances[cfg.ObjectID] = this;
    
    var me = this;

    setCfg = function(name, defaultVal) {
        if (cfg[name] == null) cfg[name] = defaultVal;
    }

    setCfg("PageSize", 5000);
    setCfg("Height", this.parentElement[0].style.height);
    setCfg("Width", this.parentElement[0].style.width);

    this.tableMgr = new Qww.Table.Mgr(
    {
        ObjectID: cfg.ObjectID,
        PageSize: cfg.PageSize,
        OnUpdate: function(tbl) {

            var html = [];

            html.push("<div class='ListBoxEx-TableParent-Default' id='" + me.Cfg.ElementID + "TableParent'><table class='ListBoxEx-Table-Default' style='background-color:white;width:" + me.Cfg.Width + "px;Height:" + me.Cfg.Height + "px'>");

            var noItems = tbl.NoRows;

            for (var i = 0; i < noItems; i++) {

                var row = tbl.GetRow(i);

                html.push("<tr>");

                var itemHtml = '';
                var className = '';
                var itemText = row.Cells[1].Text;
                var itemState = row.Cells[3].Text
                var recordNumber = row.RecordNumber;

                if (itemState == 'false') {
                    className = 'ListBoxEx-Item-Disabled-Default';
                }
                else {
                    className = 'ListBoxEx-Item-Selected-Default';
                }

                if (itemState == 'false') {
                    var tempID = cfg.ObjectID + "_" + recordNumber;
                    //itemHtml = "<span onclick='selectRowIn(" + recordNumber + ");return false;' style='cursor:pointer' class='" + className + "'>" + itemText + "</span>";
                    itemHtml = "<span id='" + tempID + "' style='cursor:pointer' class='" + className + "'>" + itemText + "</span>";
                    //$("#" + tempID).click(function(){tbl.singleSelectRecord(recordNumber,1)});

                }
                else {
                    itemHtml = "<span class='" + className + "'>" + itemText + "</span>";
                }

                html.push("<td>");
                html.push(itemHtml);
                html.push("</td>");

                html.push("</tr>");
            };

            html.push("</table></div>");
            me.parentElement.html(html.join(''));

            for (var j = 0; j < noItems; j++) {
                var row = tbl.GetRow(j);
                var tempID = cfg.ObjectID + "_" + row.RecordNumber;

                $("#" + tempID).click(
                    function(recordNumber) {
                        return function() { tbl.SelectSingleRecord(recordNumber, 1) };
                    } (row.RecordNumber)
                );
            }
        }
    });

    new Qww.TextObject.Mgr(
    {
        ObjectID: cfg.TextObjectCtlID,
        OnUpdate: function(txtObj) {
            me.RightContentPanelVisibility(txtObj);
        }
    });
};


Qww.Ctls.LeftMenu.Mgr.ScanForAndCreate = function() {
    var leftMenus = jQuery(".Qww_Ctls_LeftMenu");

    for (var i = 0; i < leftMenus.length; i++) {

        var menuItem = $(leftMenus[i]);

        var leftMenu = new Qww.Ctls.LeftMenu.Mgr({ ObjectID: leftMenus[i].id, ElementID: leftMenus[i].id, TextObjectCtlID: menuItem.attr('textObjCtlID')});
    }
};


Qww.Ctls.LeftMenu.Mgr.RegisterCallBack = function(id, panelId, callbackName, func) {

    var instance = Qww.Ctls.LeftMenu.Mgr.Instances[id];

    if (instance) {

        if (!instance.CallBacks) {
            instance.CallBacks = {};
        }

        instance.CallBacks[id + "_" + panelId + "_" + callbackName] = func;
    }
};

Qww.Ctls.LeftMenu.Mgr.prototype.RightContentPanelVisibility = function(textObject) {

    if (Qww.Ctls.Debug && textObject.Text == null) {
        debugger;
        alert("Qww.Ctls.LeftMenu.Mgr.prototype.RightContentPanelVisibility: textObject.Text is null, can't run function");
        return;
    }

    var textObjectStatus = textObject.Text.split("|");
    var textObjectStatusLength = textObjectStatus.length;

    for (var i = 0; i < textObjectStatusLength; i = i + 2) {

        var panelId = textObjectStatus[i];

        var currentTextObjectStatus = $("#" + panelId);

        if (textObjectStatus[i + 1] == "true") {

            if (this.CallBacks && this.CallBacks[this.Cfg.ObjectID + "_" + textObjectStatus[i] + "_OnShown"]) {
                this.CallBacks[this.Cfg.ObjectID + "_" + panelId + "_OnShown"]();
            }

            currentTextObjectStatus.show();
            
            //alert(panelId + ' shown');

            var idOfContainerToChangeHeight = currentTextObjectStatus.attr("IdOfContainerHeightToAdjust");

            $("#" + idOfContainerToChangeHeight).height(currentTextObjectStatus.attr("HeightToAdjustContainerTo"));

        }
        else {
            currentTextObjectStatus.hide();
        }
    }
};

Qww.Ctls.LeftMenu.Mgr.Instances = {};

Qww.Ctls.CustomTableRenderer = {};

/**
Constructs a new Qww.Table.Mgr instance.
@constructor
@class Class to manage communication with a QlikView straight table or table control.<br />
@param {Object} cfg JSON object to configure Qww.Table.Mgr.
@param {String} cfg.ObjectID Id of the table in the QlikView application.
@param {String} [cfg.ApplicationID=null] Id/Name of the QlikView application. Note this is <strong>only</strong> necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null.
@param {Int} [cfg.PageSize=50] Number of rows to return in a single page of data.
@param {Bool} [cfg.DoNotInitialise=false] Set this to false if you do not want this particular object to initialise the 
underlying object with QlikView Server. Use this option for example if you are already using another object or control which 
will have already initialised this. In this mode this object will simply parse the existing data for this object as it comese from 
QlikView Server.
@param {Function} [cfg.OnUpdate] Function to call whenever the data is updated.
@returns {Qww.Table.Mgr} Qww.Table.Mgr
*/
Qww.Ctls.CustomTableRenderer.Mgr = function(cfg) { };


Qww.Ctls.CustomTableRenderer.Mgr.ScanForAndCreate = function() {

    var tables = jQuery(".Qww_Ctls_CustomTableRenderer");

    var noTables = tables.length;
    
    for (var i = 0; i < noTables; i++) {

        var tableItem = $(tables[i]);

        var functionName = tableItem.attr('tableRenderFunction');

        var actualFunction = eval(functionName);

        var table = new Qww.Table.Mgr({ ObjectID: tables[i].id, ElementID: tables[i].id, PageSize: tableItem.attr('pageSize'), OnUpdate: actualFunction });
    }
};

Qww.Ctls.CustomCheckBoxList = {};

/**
Constructs a new Qww.Chart.Mgr instance.
@constructor
@class JavaScript class to render a listbox as a DropDown control.<br />
@param {Object} cfg JSON object to configure the DropDown.
@param {String} cfg.ElementID ID of the html element (e.g. div or span) 
where the drop down should be rendered.
@param {String} cfg.ObjectID Id of the ListBox in the QlikView application.
@returns {Qww.Chart.Mgr} Qww.Chart.Mgr
*/


Qww.ListBox.Results.prototype.ConvertPipesToState = function() {

    for (var i = 0; i < this.All.length; i++) {
        
        var item = this.All[i];

        if (item.Text == '|') continue;

        var splitItem = item.Text.split('|');
        if (splitItem.length > 1) {
            //2 = seletected, 0 = associated, 1 = disabled
            item.State = splitItem[splitItem.length - 1];
            item.Text = item.Text.substr(0, item.Text.length - 2);
        }
    }
};

Qww.Ctls.CustomCheckBoxList.Mgr = function(cfg) {

    setCfg = function(name, defaultVal) {
        if (cfg[name] == null) cfg[name] = defaultVal;
    }

    var me = this;

    setCfg("PageSize", 5000);

    var elem = $('#' + cfg.ElementID);

    this.listBoxMgr = new Qww.ListBox.Mgr(
    {
        ObjectID: cfg.ObjectID,
        PageSize: cfg.PageSize,
        OnUpdate: function(lbm) {

            //if (lbm.ObjectID == "LB_StartWizard_National_County_Resident_County_resident") debugger;
            
            if (lbm.Enabled) {

                //debugger;
                lbm.Results.ConvertPipesToState();

                elem.show();

                //                if (icbLogger.IsEnabled)
                //                    var start = icbLogger.GetNow();

                //debugger;
                cfg.OnUpdate(lbm, elem, cfg.ObjectID);

                //                if (icbLogger.IsEnabled) {
                //                    //debugger;
                //                    icbLogger.WriteToFile("C:\\HenriksFunctions.txt", me.OnUpdateFunctionName + ", " + (icbLogger.GetNow() - start).toString());
                //                }
            }
            else
                elem.hide();

        }
    });
};

Qww.Ctls.CustomCheckBoxList.Mgr.ScanForAndCreate = function() {

    var checkBoxLists = jQuery(".Qww_Ctls_CustomCheckBoxList");
    for (var i = 0; i < checkBoxLists.length; i++) {

        var checkBoxList = $(checkBoxLists[i]);

        var functionName = checkBoxList.attr('onRenderFunction');

        var actualFunction = eval(functionName);

        var currentCheckBoxList = new Qww.Ctls.CustomCheckBoxList.Mgr({ ObjectID: checkBoxLists[i].id, ElementID: checkBoxLists[i].id, OnUpdate: actualFunction });

        currentCheckBoxList.OnUpdateFunctionName = functionName;
    }
};


Qww.Ctls.Search = {};
Qww.Ctls.Search.Mgr = {};


//Qww.Ctls.Search.Mgr = function(cfg) {
//debugger;
//    this.parentElement = $('#' + cfg.ElementID);
//    this.Cfg = cfg;
//    var me = this;

//    setCfg = function(name, defaultVal) {
//        if (cfg[name] == null) cfg[name] = defaultVal;
//    }

//    this.globalSearchMgr = new Qww.Ctls.GlobalSearch.Mgr({
//        "Fields":[
//            new Qww.Ctls.GlobalSearch.Field({
//            ObjectID: cfg.ObjectID, 
//            Title: "Facts", 
//            MatchText: "Were you looking for the following facts:", 
//            NoMatchText: "No facts were found. Please refine your search", 
//            MaxNumberOfLettersToShowInResult: 5,
//            MaxNumberOfResultsToShow: 7, 
//            SelectAllText: "Select Them All!",
//            ReduceResultsText: "Change search text to reduce the results..."
//            })],
//        "ResultsElementId" : cfg.ResultElementID,
//        "SearchTextBoxId" : cfg.SearchTextBoxID,
//        "Theme" : "",
//        "AutomaticallyClearSearchString" : true
//    });
//    
//    var html = [];
//    html.push("<div class='GlobalSearch-Parent-Default' id='" +cfg .ElementID + "Parent' style='display:inline-block;width:150px;'>");
//    html.push("<input type='text' id='" + cfg.SearchTextBoxID + "' class='QwwJs_GlobalSearch-TextBox' style='width:100%;' />");
//    html.push("<div class='QwwJs_GlobalSearch-SearchResults' id='" + cfg.ResultElementID + "' style='z-index:100;position:absolute;display:none;'></div>");
//    html.push("</div>");
//    me.parentElement.html(html.join(''));
//};


Qww.Ctls.Search.Mgr.getField = function(listBoxId, searchMatchedTitleId) {
    var obj = new Qww.Ctls.GlobalSearch.Field(
        {
            ObjectID: listBoxId,
            Title: " ",
            MatchText: " ",
            NoMatchText: "-",
            MaxNumberOfLettersToShowInResult: 80,
            MaxNumberOfResultsToShow: 150,
            SelectAllText: " ",
            ReduceResultsText: " "
        });

    var txtObj = new Qww.TextObject.Mgr({ ObjectID: searchMatchedTitleId, OnUpdate: function(txt) {
        obj.MatchText = txt.Text;
    }
    });

    return obj;
}

Qww.Ctls.Search.Mgr.ScanForAndCreate = function() {

    var searches = jQuery(".Qww_Ctls_GlobalSearch");
    var noSearches = searches.length;

    for (var i = 0; i < noSearches; i++) {
        var gsItem = $(searches[i]);

        var ObjectID = searches[i].id;
        var ElementID = ObjectID; // searches[i].id, 
        var ResultElementID = gsItem.attr('resultElementID');
        var SearchTextBoxID = gsItem.attr('searchTextBoxID');
        var searchResultTitleId = gsItem.attr('searchResultTitleId');
        
        var fields = [];

        fields.push(Qww.Ctls.Search.Mgr.getField(ObjectID, searchResultTitleId));

        var html = [];
        html.push("<div class='GlobalSearch-Parent-Default' id='" + ElementID + "Parent' style='display:inline-block;width:300px;'>");
        html.push("<input type='text' id='" + SearchTextBoxID + "' class='QwwJs_GlobalSearch-TextBox-Default' style='width:100%;' /><br />");
        html.push("<div class='QwwJs_GlobalSearch-SearchResults-Default' id='" + ResultElementID + "' style='z-index:250;position:absolute;display:none;'></div>");
        html.push("</div>");

        $('#' + ElementID).html(html.join(''));

        new Qww.Ctls.GlobalSearch.Mgr({
            "Fields": fields,
            "ResultsElementId": ResultElementID,
            "SearchTextBoxId": SearchTextBoxID,
            "Theme": "Default",
            "AutomaticallyClearSearchString": true//,
            
//        new Qww.Ctls.GlobalSearch.Mgr({
//            "Fields": [
//            new Qww.Ctls.GlobalSearch.Field({
//                ObjectID: ObjectID,
//                Title: " ",
//                MatchText: " ",
//                NoMatchText: " ",
//                MaxNumberOfLettersToShowInResult: 80,
//                MaxNumberOfResultsToShow: 150,
//                SelectAllText: " ",
//                ReduceResultsText: " "
//            })],
//            "ResultsElementId": ResultElementID,
//            "SearchTextBoxId": SearchTextBoxID,
//            "Theme": "Default",
//            "AutomaticallyClearSearchString": true//,
            //        OnRenderResultsSection: function(a,b,c)
            //        {
            //            
            //        }
        });

    }
};

Qww.Ctls.Search2 = {};
Qww.Ctls.Search2.Mgr = {};

Qww.Ctls.Search2.Mgr.getField = function(listBoxId, searchMatchedTitleId) {
    var obj = new Qww.Ctls.GlobalSearch.Field(
        {
            ObjectID: listBoxId,
            Title: " ",
            MatchText: " ",
            NoMatchText: "-",
            MaxNumberOfLettersToShowInResult: 80,
            MaxNumberOfResultsToShow: 150,
            SelectAllText: " ",
            ReduceResultsText: " "
        });

    var txtObj = new Qww.TextObject.Mgr({ ObjectID: searchMatchedTitleId, OnUpdate: function(txt) {
        obj.MatchText = txt.Text;
    }
    });
    
    return obj;
}

Qww.Ctls.Search2.Mgr.ScanForAndCreate = function() {

    var searches = jQuery(".Qww_Ctls_GlobalSearch2");
    var noSearches = searches.length;

    for (var i = 0; i < noSearches; i++) {
        var gsItem = $(searches[i]);

        var ObjectID = searches[i].id;
        var ElementID = ObjectID; // searches[i].id, 
        var ResultElementID = gsItem.attr('resultElementID');
        var SearchTextBoxID = gsItem.attr('searchTextBoxID');
        var listBoxIds = gsItem.attr('listboxids');
        var searchResultTitleIds = gsItem.attr('searchResultTitleIds');

        var fields = [];

        if (listBoxIds != null) {
            var ids = listBoxIds.split(",");
            var titleIds = searchResultTitleIds.split(",");

            for (var i = 0; i < ids.length; i++) {
                fields.push(Qww.Ctls.Search2.Mgr.getField(ids[i], titleIds[i]));
            }
        }
        else {
            fields.push(ObjectID);
        }

        var html = [];
        html.push("<div class='GlobalSearch-Parent-Default' id='" + ElementID + "Parent' style='display:inline-block;'>");
        html.push("<input type='text' id='" + SearchTextBoxID + "' class='QwwJs_GlobalSearch-TextBox-Default' style='width:100%;' /><br />");
        html.push("<div class='QwwJs_GlobalSearch-SearchResults-Default' id='" + ResultElementID + "' style='z-index:250;position:absolute;display:none;'></div>");
        html.push("</div>");

        $('#' + ElementID).html(html.join(''));

        new Qww.Ctls.GlobalSearch.Mgr({
            "Fields": fields,
            "ResultsElementId": ResultElementID,
            "SearchTextBoxId": SearchTextBoxID,
            "Theme": "Default",
            "AutomaticallyClearSearchString": true//,
            //        OnRenderResultsSection: function(a,b,c)
            //        {
            //            
            //        }
        });

    }
};

function showResults() {
    window.location = "results.aspx";
}

function bookMarkCreated(bookMarkUrl) {
    //$("#thisBookmarkContent").append(bookMarkUrl); // todo: delete.
    $("#bookMarkLink").attr("href", bookMarkUrl);
    $("#facebookLink").attr("href", "http://www.facebook.com/sharer.php?u=" + bookMarkUrl);
    $("#myspaceLink").attr("href", "http://www.myspace.com/index.cfm?fuseaction=postto&u=" + bookMarkUrl);
    $("#twitterLink").attr("href", "http://twitter.com/home?status=" + bookMarkUrl);
    $("#bookMarkTextArea").attr("value", bookMarkUrl);
};

function bookmarkpopup() {
    var text = $("#bookmarkpopup").text();
    alert(text);

}

function toggleReferenceHelp() {
    $("#refHelp").toggle();
}

function clearListBox(ObjectID) {
    Qww.ListBox.Mgr.CallAction(null, ObjectID, Qww.ListBox.Mgr.StandardAction.ClearAll, true);
};

AlphabetCtl = function(cfg) {

    this.Cfg = cfg;

    if (!this.Ctl) {

        this.Create(cfg.ListBoxMgr, cfg.AlphabetList, cfg.CssPrefix);

        cfg.Element.append(this.Ctl);

        this.Update(cfg.ListBoxMgr);
    }
};

AlphabetCtl.prototype.Create = function(listBox, alpha, cssPrefix) {

    var ctl = $("<div id=" + cssPrefix + ">");

    this.Ctl = ctl;

    var alphaLength = alpha.length;

    var i = 0;

    var me = this;

    $(alpha).each(function() {

        var alphaCharacter = this;

        var letterId = cssPrefix + alphaCharacter.Name;

        var html = "<div class='" + cssPrefix + "NameList letterList'>" +
                        "<div cssPrefix='" + cssPrefix + "' id='" + letterId + "' class='oddRow " + cssPrefix + "Letter'>" + alphaCharacter.Name + "</div>" +
                        "<div class='" + cssPrefix + "Container'></div>" +
                        "</div>";

        var topLevelDiv = $(html);

        ctl.append(topLevelDiv);

        $('#' + letterId, topLevelDiv).click(me.OnLetterClicked);

        if (i == 0) {
            $.cookie(cssPrefix + 'cookieFirst', cssPrefix + "Container" + alphaCharacter.Name);
        }

        i++;
    });

    var allLetters = $("<div class='oddRow " + cssPrefix + "NameList letterList " + cssPrefix + "ALL'>ALL</div>");
    allLetters.cssPrefix = cssPrefix;

    ctl.append(allLetters);

    allLetters.click(function() { showAll(cssPrefix); });

    me.TreeNodes = {};
    me.ImageTreeNodes = {};

    $(alpha).each(function() {

        var alphaCharacter = this;

        var countryContainer = $("<div class='" + cssPrefix + "Container' id='" + cssPrefix + "Container" + alphaCharacter.Name + "' style='display: none;'>");
        ctl.append(countryContainer);

        //Loop through each subcategory and construct the divs
        for (var j = 0; j < alphaCharacter.SubCategories.length; j++) {

            var entry = alphaCharacter.SubCategories[j];

            var imageNodeId = "AlphabetCtlNodeImg_" + cssPrefix + "_" + entry.ListBoxItem.Value;

            // TODO : Delete
            //            var html = "<div class='outerContainer' id='AlphabetCtlNodeContainer_" + cssPrefix + "_" + entry.ListBoxItem.Value + "'>" +
            //                            "<div class='box'><img id='" + imageNodeId + "' /></div>" +
            //                            "<div class='" + cssPrefix + "Entries'>" + entry.Name + "</div>" +
            //                        "</div>";

            var html = "<div class='outerContainer'>" +
                            "<div class='box'><img id='" + imageNodeId + "' /></div>" +
                            "<div class='" + cssPrefix + "Entries'>" + entry.Name + "</div>" +
                        "</div>";

            var outer = $(html);

            outer.ItemValue = entry.ListBoxItem.Value;

            me.TreeNodes[entry.ListBoxItem.Value] = outer;
            me.ImageTreeNodes[entry.ListBoxItem.Value] = $("#" + imageNodeId, outer);

            countryContainer.append(outer);
        }
    });
};

AlphabetCtl.prototype.OnLetterClicked = function() {

    var cssPrefix = this.getAttribute('cssPrefix');
    var charName = this.id.replace(cssPrefix, '');

    var toggleElemName = cssPrefix + "Container" + charName;

    toggleDiv(toggleElemName, cssPrefix);
}

AlphabetCtl.prototype.OnItemClicked = function(a) {

    // todo : should this alert be here? Is this ever called as I dont think we are getting alerts.
    alert('selecting ' + this.ItemValue);
    this.lbm.MakeSingleSelection(this.ItemValue, false, true);

};

AlphabetCtl.prototype.Update = function(lbm) {

    var me = this;

    var outerNodes = me.TreeNodes;
    var imageNodes = me.ImageTreeNodes;

    jQuery(lbm.Results.All).each(function() {

        var item = this;

        var imageNode = imageNodes[item.Value];

        if (imageNode != null) {

            var icon = getCheckBoxIcon(item.State);
            var className = getCheckBoxClass(item.State);

            imageNode.attr("src", icon).attr("class", className);
        }

        var outer = outerNodes[item.Value];

        if (outer != null) {

            if (item.State != Qww.ListBox.Mgr.ItemState.Disabled) {

                outer[0].onclick = function() {

                    //alert('selecting ' + item.Value);
                    lbm.MakeSingleSelection(item.Value, false, true);
                    return false;
                };
            }
            else {
                //outer.click(function() { alert("null"); });
                outer[0].onclick = null;
            }
        }

    });
};

function renderRMYear_ForSpecificYear(tbl, elementIddPrefix, targetElementIdWithoutHash, onBeforeReadMoreAboutYearNumber) {
    var output = [];
    output.push("<table>");

    var tableRowCount = tbl.NoRows
    var tableCellCount;

    for (var i = 0; i < tableRowCount; i++) {
        var row = tbl.GetRow(i);

        if (tableCellCount == null)
            tableCellCount = row.Cells.length;

        for (var c = 0; c < tableCellCount; c++) {
            var text = row.Cells[c].Text;
            switch (c) {
                case 0:
                    text = "<span id='" + elementIddPrefix + "year'>" + text + "</span>";
                    break;
                case 1:
                    text = "<a href='" + text + "' target='_blank' id='" + elementIddPrefix + "wikilink'>" + text + "</a>";
                    break;
                case 2:
                    text = "<a href='" + text + "' target='_blank' id='" + elementIddPrefix + "dnlink'>" + text + "</a>";
                    break;
            }

            output.push("<tr><td valign='top'>" + text + "</td></tr>");
        }
    }
    output.push("</table>");
    //add the html to the element defined in the web page

    $("#" + targetElementIdWithoutHash).html(output.join(""));
    onBeforeReadMoreAboutYear(onBeforeReadMoreAboutYearNumber);
};


function onBeforePopupFact(factNo) {

    var factNumberToUseForSelect = (factNo == 1) ? "" : factNo;

    // todo : delete this line?
    //popUpVisibilityListboxMgr.MakeSingleSelection('CH_World_Lab_Bottom_Section_Fact' + factNumberToUseForSelect + '_Read_More_Subject', true, true);
    populateFactPopupStandardStrings(factNo);
    return false;
}

function MM_openBrWindow(theURL, winName, features) { //v2.0
    window.open(theURL, winName, features);
    return false;
}

function toggleAllResults() {
    if ($("#showAllLink:hidden").length == 0) {
        $("tr").removeClass("initialHide");
        $("#showTopLink").show();
        $("#showAllLink").hide();
    } else {
        $("tr.notTop10").addClass("initialHide");
        $("#showTopLink").hide();
        $("#showAllLink").show();
    }
};

function buildTopBottom5List(tbl, fillId) {

    var output = [];
    //start to construct the table

    var tableRowCount = tbl.NoRows
    if (tableRowCount == -1) { return; }
    var tableCellCount;

    //loop through each table row
    for (var i = 0; i < tableRowCount; i++) {
        var row = tbl.GetRow(i);
        output.push("<span>");

        if (tableCellCount == null)
            tableCellCount = row.Cells.length;

        for (var c = 0; c < tableCellCount; c++) {
            var text = row.Cells[c].Text;
            (i < tableRowCount - 1) ? output.push(text + " / ") : output.push(text);
        }
        output.push("</span>");
    }

    output.push("</span><br/>");
    return output.join("");
}

function renderTopEntiresTable(tbl) {
    var tableHtml = [];
    //start to construct the table
    tableHtml.push("<table style='width:100%;' class='topEntriesTableHeaders'>");
    //loop through the header row
    /***
    for (var i = 0; i < tbl.Headers.length; i++) {
    var obj = tbl.Headers[i];
    tableHtml += "<td valign='top'>" + obj.HeaderText + "</td>";
    }
    */
    var noHeaders = tbl.Headers.length;
    for (var i = 0; i < noHeaders; i++) {

        switch (i) {
            case 0:
                tableHtml.push("<th class='column0'>&nbsp;</th>");
                break;
            case 1:
                tableHtml.push("<th class='column1'>&nbsp;</th>");
                break;
            case 2:
                if (tbl.Headers[i].HeaderText != '-') {
                    tableHtml.push("<th class='column2'><span class='topentriesFact1Header' id='Fact1_Header'></span></th>");
                }
                break;
            case 3:
                if (tbl.Headers[i].HeaderText != '-'){
                tableHtml.push("<th class='column3'><span class='topentriesFact2Header' id='Fact2_Header'></span></th>");
                }
                break;
            case 4:
                if (tbl.Headers[i].HeaderText != '-'){
                tableHtml.push("<th class='column4'><span class='topentriesFact3Header' id='Fact3_Header'></span></th>");
                }
                break;
            default:
                break;
        }
    }
    tableHtml.push("</table>");

    tableHtml.push("<div class='expandingTableContainer'><table style='width:100%;' class='expandingTable'>");

    var tableRowCount = tbl.NoRows
    var tableCellCount;

    //loop through each table row
    for (var i = 0; i < tableRowCount; i++) {
        var row = tbl.GetRow(i);

        //can apply tests so, for example here rows 11+ are hidden. Could apply
        //this with a class and then use jQuery to show and hide rows with a specific class
        /****
        if (i > 10)
        tableHtml += "<tr style='display:none'>";
        else
        tableHtml += "<tr>";
        */
        if ((i % 2) == 0) {
            // even
            if (i > 9) {
                tableHtml.push("<tr class='notTop10 initialHide'>");
            } else {
                tableHtml.push("<tr class='Top10'>");
            }
        } else {
            // odd
            if (i > 9) {
                tableHtml.push("<tr class='oddRow notTop10 initialHide'>");
            } else {
                tableHtml.push("<tr class='oddRow Top10'>");
            }
        }

        if (tableCellCount == null)
            tableCellCount = row.Cells.length;

        for (var c = 0; c < tableCellCount; c++) {

            if (tbl.Headers[c].HeaderText != '-') {
                var text = row.Cells[c].Text;
                tableHtml.push("<td valign='top' class='column" + c + "'>" + text + "</td>");
            }
        }

        tableHtml.push("</tr>");
    }
    tableHtml.push("</table></div>");

    tableHtml.push("<table style='width:100%;' class='topEntriesTableFooter'>");

    //add row for total value:
    tableHtml.push('<tr class="footerRow">');
    tableHtml.push('<td class="column0">&nbsp;</td>');
    tableHtml.push('<td valign="top" class="column1"><span id="injectTotal"></span></td>');

    for (var d = 2; d < tableCellCount; d++) {
        tableHtml.push('<td valign="top" class="column' + d + '"><span id="injectTotalCol' + d + '"></span></td>');
    }

    tableHtml.push('</tr>');
    
    //add row for mean value:
    tableHtml.push('<tr class="footerRow">');
    tableHtml.push('<td class="column0">&nbsp;</td>');
    tableHtml.push('<td valign="top" class="column1"><span id="injectMean"></span></td>');

    for (var d = 2; d < tableCellCount; d++) {
        tableHtml.push('<td valign="top" class="column' + d + '"><span id="injectMeanCol' + d + '"></span></td>');
    }

    tableHtml.push('</tr>');

    //add row for reference country:
    tableHtml.push('<tr class="footerRow">');
    tableHtml.push('<td class="column0">&nbsp;</td>');
    tableHtml.push('<td valign="top" class="column1"><span id="injectRefCountry" class="Reference"></span></td>');

    for (var d = 2; d < tableCellCount; d++) {
        tableHtml.push('<td valign="top" class="column' + d + '"><span id="injectRefCol' + d + '"></span></td>');
    }

    tableHtml.push('</tr>');
    tableHtml.push("</table>");

    //add the html to the element defined in the web page
    $("#CH_World_Lab_Top_Entries").html(tableHtml.join(""));
};

function renderRMSubject_ForSpecificSubject(tbl, elementIddPrefix, onBeforPopupFactNumber, targetElementIdWithoutHash) {
    var output = [];
    output.push("<table>");

    var tableRowCount = tbl.NoRows
    var tableCellCount;

    for (var i = 0; i < tableRowCount; i++) {
        var row = tbl.GetRow(i);

        if (tableCellCount == null)
            tableCellCount = row.Cells.length;

        for (var c = 0; c < tableCellCount; c++) {
            var text = row.Cells[c].Text;
            switch (c) {
                case 0:
                    text = "<span id='" + elementIddPrefix + "ShortDesc'></span> " + text;
                    break;
                case 1:
                    text = "<div id='" + elementIddPrefix + "LongDesc'></div><div class='smallerText'>" + text + "</div>";
                    break;
                case 2:
                    text = "<a href='" + text + "' target='_blank' id='" + elementIddPrefix + "wikiLink'>" + text + "</a>";
                    break;
                case 3:
                    text = "<a href='" + text + "' target='_blank' id='" + elementIddPrefix + "dnLink'>" + text + "</a>";
                    break;
                case 4:
                    text = "<span id='" + elementIddPrefix + "Source'></span> " + text;
                    break;
                case 5:
                    text = "<a href='" + text + "' target='_blank' id='" + elementIddPrefix + "sourceLink'>" + text + "</a>";
                    break;
            }

            output.push("<tr><td valign='top'>" + text + "</td></tr>");
        }
    }
    output.push("</table>");
    //add the html to the element defined in the web page
    $("#" + targetElementIdWithoutHash).html(output.join(""));

    if (onBeforPopupFactNumber == 0) {
        populateWizardFactPopupStandardStrings();
    }
    else {
        onBeforePopupFact(onBeforPopupFactNumber);
    }
};

// todo Rename this more clearly (shouldnt have Countries in the function name?).
function renderRMCountries_WLTS_top_ForSpecificObject(tbl, objectIdWithoutHash) {
    var sPath = window.location.href;
    //var sPage = sPath.substring(sPath.lastIndexOf('\\') + 1);
    var sPage = sPath.substring(0, sPath.lastIndexOf('/'));

    var output = [];
    output.push("<table class='largeTable'>");

    var tableRowCount = tbl.NoRows
    var tableCellCount;
    for (var i = 0; i < tableRowCount; i++) {
        output.push("<tr><td><table class='largeSubTable'>");
        var row = tbl.GetRow(i);

        if (tableCellCount == null)
            tableCellCount = row.Cells.length;

        for (var c = 0; c < tableCellCount; c++) {
            var text = row.Cells[c].Text;

            switch (c) {
                case 0:
                    text = "<span class='rowMainLabel'>" + text + "</span>";
                    break;
                case 1:
                    text = "<a href='" + text + "' target='_blank' class='wikilink'>" + text + "</a>";
                    break;
                case 2:
                    text = "<a href='" + text + "' target='_blank' class='dnlink'>" + text + "</a>";
                    break;
                case 3:
                    text = "<a href='" + text.replace(new RegExp(/\\/g), '/') + "' target='_blank' class='anthemlink'>" + text + "</a>";
                    break;
                case 4:
                    text = "<a href='" + text + "' target='_blank' class='officiallink'>" + text + "</a>";
                    break;
                case 5:
                    text = "<a href='" + text + "' target='_blank' class='tourismlink'>" + text + "</a>";
                    break;
                case 6:
                    text = "<img src='" + '..' + text.replace(new RegExp(/\\/g), '/') + "' />";
                    break;
            }
            output.push("<tr><td>" + text + "</td></tr>");
        }
        output.push("</table></td></tr>");
    }
    output.push("</table>");
    //add the html to the element defined in the web page
    // todo was CH_World_Lab_Top_Section_Summary_Read_More_Countries
    $("#" + objectIdWithoutHash).html(output.join(""));

    // onBeforeReadMoreAboutTheCountries(); // todo delete (left this in function which calls this).
};

function renderRMCountries_WLTS_bottom_ForSpecificObject(tbl, objectIdWithoutHash) {

    var output = [];
    output.push("<table class='largeTable'>");

    var tableRowCount = tbl.NoRows
    var tableCellCount;

    for (var i = 0; i < tableRowCount; i++) {
        output.push("<tr><td><table class='largeSubTable'>");
        var row = tbl.GetRow(i);

        if (tableCellCount == null)
            tableCellCount = row.Cells.length;

        for (var c = 0; c < tableCellCount; c++) {
            var text = row.Cells[c].Text;
            if (c == 0) { text = "<span class='rowMainLabel'>" + text + "</span>"; }
            if (text.substring(0, 4) == 'http') { text = "<a href='" + text + "' target='_blank'>" + text + "</a>"; }
            if (text.substring(-4) == '.GIF') { text = "<img src='" + text + "' />"; }
            output.push("<tr><td>" + text + "</td></tr>");
        }
        output.push("</table></td></tr>");
    }
    output.push("</table>");
    //add the html to the element defined in the web page

    // todo Can't find good match in new application.
    $("#" + objectIdWithoutHash).html(output.join(""));
    // todo delete?
    //$("#CH_World_Lab_Bottom_Section_Summary_Read_More_Countries").html("something about the country");
};

TopLevelsChildrenStatus = {
    AllAvailableSelected: 1,
    AllAvailableUnSeletced: 2,
    Mixed: 3
}

// todo: why is there only one state here?
function getCheckBoxClass(listBoxItemState) {
    if (listBoxItemState == Qww.ListBox.Mgr.ItemState.Disabled) { return "unavailableBox"; }
}

function getCheckBoxIcon(listBoxItemState) {
    if (listBoxItemState == Qww.ListBox.Mgr.ItemState.Associated) { return Factlab.ImageRoot + "img/unavailable.png"; }
    if (listBoxItemState == Qww.ListBox.Mgr.ItemState.Selected) { return Factlab.ImageRoot + "img/Selected.png"; }
    if (listBoxItemState == Qww.ListBox.Mgr.ItemState.Disabled) { return Factlab.ImageRoot + "img/Disabled.png"; }
}

function getCheckBoxImageElement(listBoxItemState) {
    if (item.State == Qww.ListBox.Mgr.ItemState.Associated) { return "<img src=\"" + Factlab.ImageRoot + "img/unavailable.png\" alt=\"Unavailable\">"; }
    if (item.State == Qww.ListBox.Mgr.ItemState.Selected) { return "<img src=\"" + Factlab.ImageRoot + "img/Selected.png\" alt=\"Selected\">"; }
    if (item.State == Qww.ListBox.Mgr.ItemState.Disabled) { return "<img src=\"" + Factlab.ImageRoot + "img/Disabled.png\" alt=\"Disabled\">"; }
}

function getAlphaListObject(fullName, results) {

    var length = results.length;
    var lowerFullName = fullName.toLowerCase();

    for (var i = 0; i < length; i++) {
        if (results[i].Name.toLowerCase() == lowerFullName) {
            if (fullName != " ") {
                return results[i];
            }
        }
    }

    return null;
}

function convertSourceLBItemsToAlpha(listBoxItems) {

    var results = [];
    var length = listBoxItems.length;

    for (var i = 0; i < length; i++) {
        var item = listBoxItems[i];
        var fullName = item.Text;

        var alphaCharacter = getAlphaListObject(fullName, results);

        if (alphaCharacter == null) {
            alphaCharacter = { 'Name': fullName, 'SubCategories': [] };
            results.push(alphaCharacter);
        }

        alphaCharacter.SubCategories.push({ Name: fullName, Value: item.Value, ListBoxItem: item });
    }

    return results;
}


//Turns the array of arrays into a control
function convertToSourceControl(listBox, sourceList, cssPrefix) {
    var ctl = $("<div>");
    var unorderedList = $("<ul class='sourceListResult'>");
    ctl.append(unorderedList);

    var length = sourceList.length;

    for (var i = 0; i < length; i++) {

        var source = sourceList[i];

        //Loop through each subcategory and construct the list items
        var innerLength = source.SubCategories.length;
        var subCats = source.SubCategories;

        for (var j = 0; j < innerLength; j++) {
            var entry = subCats[j];
            var iconDiv = $("<li class='box' id='" + cssPrefix + "Box" + i + "'><img src='" + getCheckBoxIcon(entry.ListBoxItem.State) + "' />" + entry.ListBoxItem.Text + "</li>");

            unorderedList.append(iconDiv);
            //Shouldn't assign a click to a country if its disabled. Due to an issue with the underlying listbox,
            //this can't be turned on yet.
            if (entry.ListBoxItem.State != Qww.ListBox.Mgr.ItemState.Disabled) {
                //
                // We are using a trick here to utilise closue to capture the
                // current value of the loop for use in the onclick funtion
                // when it is called later on:
                // http://www.mennovanslooten.nl/blog/post/62
                //
                // Used also below..
                //
                iconDiv.click(function(subCat) {
                    return function() {
                        listBox.MakeSingleSelection(subCat.Value, false, true);
                    }
                } (entry));
            }
        }
    }
    return ctl;
}

var Factlab_ManagedCtls = {};
function renderManagedControl(controlID, lbm, jQueryElem, objectID) {

    var ctl = Factlab_ManagedCtls[controlID];

    if (ctl != null) {
        ctl.remove();
    }

    var res = convertSourceLBItemsToAlpha(lbm.Results.All);
    ctl = convertToSourceControl(lbm, res, controlID);
    Factlab_ManagedCtls[controlID] = ctl;
    jQueryElem.append(ctl);
}

function renderSources1(lbm, jQueryElem, objectID) {
    // todo : replace reference in html to call the following line directly.
    renderManagedControl("sources1", lbm, jQueryElem, objectID);
}

function renderSources2(lbm, jQueryElem, objectID) {
    renderManagedControl("sources2", lbm, jQueryElem, objectID);
}

function renderSources3(lbm, jQueryElem, objectID) {
    // todo : replace reference in html to call the following line directly.
    renderManagedControl("sources3", lbm, jQueryElem, objectID);
}

function renderSourcesTheme(lbm, jQueryElem, objectID) {
    // todo : replace reference in html to call the following line directly.
    renderManagedControl("sourcesTheme", lbm, jQueryElem, objectID);
}

function renderYearFilter(lbm, jQueryElem, objectID) {
    renderManagedControl("yearFilter", lbm, jQueryElem, objectID);
}

function renderYear1Filter(lbm, jQueryElem, objectID) {
    // todo : replace reference in html to call the following line directly.
    renderManagedControl("year1Filter", lbm, jQueryElem, objectID);
}

function renderYear2Filter(lbm, jQueryElem, objectID) {
    // todo : replace reference in html to call the following line directly.
    renderManagedControl("year2Filter", lbm, jQueryElem, objectID);
}

function renderYear3Filter(lbm, jQueryElem, objectID) {
    // todo : replace reference in html to call the following line directly.
    renderManagedControl("year3Filter", lbm, jQueryElem, objectID);
}

function toggleDiv(toggleElem, cssPrefix, totalItemsInListbox) {
    if ($("#" + cssPrefix + " > div." + cssPrefix + "NameList").length > 0) {   //does the list exist?
        if (toggleElem == "") {                                              //nothing coming in.
            toggleElem = $.cookie(cssPrefix + 'cookie');                        //grab it from the cookie.
            if ($.cookie(cssPrefix + 'cookie') == null) {                        // there is no cookie.
                if (totalItemsInListbox <= 12) {                                 //see how many items are in the whole list. If less than 11, show all.
                    showAll(cssPrefix);
                }
                else {                                                                     
                    toggleElem = $.cookie(cssPrefix + 'cookieFirst');                 //grab the first letter cookie instead.
                    $.cookie(cssPrefix + 'cookie', toggleElem);                       // set the cookie
                }
            } else if ($.cookie(cssPrefix + 'cookie') == "ALL") {               //OR if the cookie is set to ALL
                showAll(cssPrefix);                                             //show all
                return;                                                         //exit function
            }
        } else {                                                            //something coming in.
            $.cookie(cssPrefix + 'cookie', toggleElem);                         //set the cookie
        }

        if (toggleElem != null) {
            var letter = toggleElem.substring(toggleElem.length - 1);           //take the last letter of the string, the *first* letter of the item.
        }

        if (document.getElementById(toggleElem) != null) {
            $("." + cssPrefix + "Container").attr('style', 'display: none;');      // close all others of this kind.
            $("." + cssPrefix + "Letter").removeClass("active");                  //reset all letters.
            $("." + cssPrefix + "ALL").removeClass("active");                     //reset the ALL link
            document.getElementById(toggleElem).style.display = '';           // open the one we want.
            document.getElementById(cssPrefix + letter).className = 'oddRow ' + cssPrefix + 'Letter active'; //set it's letter.
        }
    }
}

function showAll(cssPrefix) {
    if ($("#" + cssPrefix + " > div." + cssPrefix + "NameList").length > 0) { // if this cssPrefix even exists.
        $("." + cssPrefix + "Container").attr("style", "display: ;");         //display all the items
        $("." + cssPrefix + "Letter").removeClass("active");                  //reset all the letters
        $("." + cssPrefix + "ALL").addClass("active");                        //set the "all" link to be active
        $.cookie(cssPrefix + 'cookie', "ALL");                              //set cookie to ALL
    }
}

function convertLBItemsToAlpha(listBoxItems) {

    var results = [];
    var length = listBoxItems.length;
     
    for (var i = 0; i < length; i++) {
        var item = listBoxItems[i];
        var fullName = item.Text;
        var first = fullName.slice(0, 1);
    
        var alphaCharacter = getAlphaListObject(first, results);

        if (alphaCharacter == null && first != '') {
            alphaCharacter = {'Name': first, 'SubCategories': []};
            results.push(alphaCharacter);
        }
    
        if(first != '') {
            alphaCharacter.SubCategories.push({ Name: fullName, Value: item.Value, ListBoxItem: item });
        }
    }
  
    return results;
}

// todo rename Factlab_HierarchyControls for consistency?
var hierarchyControls = {};

function createOrUpdateHierarchyControl(controlName, lbm, jQueryElem, objectID) {

    if (controlName == null) controlName = "generic";
    
    // var ctl = null; // todo : delete? Not sure why this line was here.
    var allResults = lbm.Results.All;
    if (hierarchyControls[controlName] == null) {
        
        var res = convertLBItemsToAlpha(allResults);
        
        alphabetCtl = new AlphabetCtl({ ListBoxMgr: lbm, AlphabetList: res, CssPrefix: controlName, Element: jQueryElem });

        hierarchyControls[controlName] = alphabetCtl;
    }
    else {
        hierarchyControls[controlName].Update(lbm);
    }

    toggleDiv("", controlName,allResults.length);
}

function countryNameList(lbm, jQueryElem, objectID) {
    return createOrUpdateHierarchyControl("country", lbm, jQueryElem, objectID);
}

function capitalNameList(lbm, jQueryElem, objectID) {    
    return createOrUpdateHierarchyControl("capital", lbm, jQueryElem, objectID);
}

function governmentNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("government", lbm, jQueryElem, objectID);
    showAll("government");
    return res;
}

function languageNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("language", lbm, jQueryElem, objectID);
    showAll("language");
    return res;
}

function religionNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("religion", lbm, jQueryElem, objectID);
    showAll("religion");
    return res;
}

function EUMemberNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("EUMember", lbm, jQueryElem, objectID);
    showAll("EUMember");
    return res;
}

function UNMemberNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("UNMember", lbm, jQueryElem, objectID);
    showAll("UNMember");
    return res;
}

function OPECMemberNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("OPECMember", lbm, jQueryElem, objectID);
    showAll("OPECMember");
    return res;
}

function ASEANMemberNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("ASEANMember", lbm, jQueryElem, objectID);
    showAll("ASEANMember");
    return res;
}

function NATOMemberNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("NATOMember", lbm, jQueryElem, objectID);
    showAll("NATOMember");
    return res;
}

function OECDMemberNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("OECDMember", lbm, jQueryElem, objectID);
    showAll("OECDMember");
    return res;
}

function G78MemberNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("G78Member", lbm, jQueryElem, objectID);
    showAll("G78Member");
    return res;
}

function WTOMemberNameList(lbm, jQueryElem, objectID) {
    var res = createOrUpdateHierarchyControl("WTOMember", lbm, jQueryElem, objectID);
    showAll("WTOMember");
    return res;
}

TopLevelObject = function(name) {

    this.Name = name;
    this.SubCategories = [];
};

TopLevelObject.prototype.GetOverallState = function() {

    var countSelected = 0;
    var countAssociated = 0;
    var countDisabled = 0;

    var length = this.SubCategories.length;

    for (var i = 0; i < length; i++) {

        var stateVal = this.SubCategories[i].State;

        if (stateVal == Qww.ListBox.Mgr.ItemState.Associated) countAssociated++;
        if (stateVal == Qww.ListBox.Mgr.ItemState.Selected) countSelected++;
        if (stateVal == Qww.ListBox.Mgr.ItemState.Disabled) countDisabled++;
    }

    if ((countSelected + countDisabled) == this.SubCategories.length) return TopLevelsChildrenStatus.AllAvailableSelected;
    if ((countAssociated + countDisabled) == this.SubCategories.length) return TopLevelsChildrenStatus.AllAvailableUnSeletced;

    // else ...
    return TopLevelsChildrenStatus.Mixed;
};


function getTopLevelObject(lsh, results) 
{
    for (var i = 0; i < results.length; i++) {
        if (results[i].Name == lsh) {
            return results[i];
        }
    }

    return null;
};

function getStateOfAllItems(listBoxItems) 
{
      var counter = 0;
      var selectedCounter = 0;

      var listBoxItems_length = listBoxItems.length;

      for (var i = 0; i < listBoxItems_length; i++) {
          
          var item = listBoxItems[i];
          var parts = item.Text.split("|");

          if (parts.length != 2)
              continue;

          var itemState = item.State;
          
          if (itemState == 2) {
              counter++;
              selectedCounter++;
          }

          if (itemState == 0) {
              counter++;
          }
      };

      if (selectedCounter == counter) {
          return TopLevelsChildrenStatus.AllAvailableSelected;
      }
      else {
          return TopLevelsChildrenStatus.Mixed;
      }
};

function convertConcatenatedLBItemsToHieracrchy(listBoxItems) {

    var results = [];

    var everythingSelected = getStateOfAllItems(listBoxItems);

    var listBoxItems_length = listBoxItems.length;

    for (var i = 0; i < listBoxItems_length; i++) {

        var item = listBoxItems[i];

        if (item.Text == '|') continue;

        var parts = item.Text.split("|");

        if (parts.length != 2) continue;

        //e.g. continent    
        var lhs = parts[0];

        //e.g. country
        var rhs = parts[1];

        var state;

        if (everythingSelected == TopLevelsChildrenStatus.AllAvailableSelected) {
            state = 2;
        }
        else {
            state = item.State;
        }

        //State's values: 2 = selected, 1 = disabled, 0 = associated

        var topLevelObject = getTopLevelObject(lhs, results);

        if (topLevelObject == null) {
            topLevelObject = new TopLevelObject(lhs);
            results.push(topLevelObject);
        }

        topLevelObject.SubCategories.push({ Name: rhs, Value: item.Value, ListBoxItem: item, State: state });
    }

    return results; ;
}

HieracrchicalCtl = function(cfg) {

    this.Cfg = cfg;

    if (this.Ctl == null) {
        this.Create(cfg.ListBoxMgr, cfg.Hierarchy, cfg.CssPrefix);
        cfg.Element.append(this.Ctl);
        this.Update(cfg.ListBoxMgr, cfg.Hierarchy);
    }
};

HieracrchicalCtl.prototype.Update = function(lbm, hierarchy) {

    //    debugger;
    var me = this;

    var outerNodes = me.OuterNodes;
    var imageNodes = me.ImageTreeNodes;

    jQuery(lbm.Results.All).each(function() {

        var item = this;

        var imgNode = imageNodes[item.Value];

        if (imgNode != null) {
            var icon = getCheckBoxIcon(item.State);
            var className = getCheckBoxClass(item.State);
            imgNode.attr("src", icon).attr("class", className);
        }

        var outer = outerNodes[item.Value];

        if (outer != null) {
            //Shouldn't assign a click to a country if its disabled. Due to an issue with the underlying listbox,
            //this can't be turned on yet.
            if (item.State != Qww.ListBox.Mgr.ItemState.Disabled) {

                outer[0].onclick = function() {
                    //alert("Selecting " + item.Value);
                    lbm.MakeSingleSelection(item.Value, false, true);
                    return false;
                };

            }
            else {
                outer[0].onclick = null;
            }
        }
    });

    jQuery(hierarchy).each(function() {

        var topLevel = this;

        // An array of all the values that belong to the banner div, so 
        // in the example of africa, this will be collection of values 
        // for countries like Angola, Kenya, South Africa etc
        var arrToSelect = [];
        var arrToDeselect = [];

        for (var j = 0; j < topLevel.SubCategories.length; j++) {

            var item = topLevel.SubCategories[j];

            if (item.State != 2) {
                arrToSelect.push(item.Value);
            }
            else {
                arrToDeselect.push(item.Value);
            }
        };

        var overallState = topLevel.GetOverallState();

        var icon = "";

        if (overallState == TopLevelsChildrenStatus.AllAvailableSelected) {
            icon = Factlab.ImageRoot + "img/Selected.png";
        }
        else if (overallState == TopLevelsChildrenStatus.AllAvailableUnSeletced) {
            icon = Factlab.ImageRoot + "img/unavailable.png"
        }
        else {
            icon = Factlab.ImageRoot + "img/partiallyselected.png"
        }

        me.TopLevelElements[topLevel.Name].attr('src', icon);

        if (overallState == TopLevelsChildrenStatus.AllAvailableSelected) {
            jQuery(me.SelectDeselectAllElements[topLevel.Name]).each(function() {
                this[0].onclick = function() {
                    //alert("DeSelecting " + arrToDeselect.join(","));
                    lbm.MakeSelection(arrToDeselect, false, true);
                    return false;
                };
            });
        }
        else {
            jQuery(me.SelectDeselectAllElements[topLevel.Name]).each(function() {
                this[0].onclick = function() {
                    //alert("Selecting " + arrToSelect.join(","));
                    lbm.MakeSelection(arrToSelect, false, true);
                    return false;
                };
            });
        }
    });
};

HieracrchicalCtl.prototype.Create = function(listBox, hierarchy, cssPrefix) {

    var ctl = $("<div>");

    this.Ctl = ctl;

    var me = this;

    me.ImageTreeNodes = {};
    me.OuterNodes = {};
    me.SelectDeselectAllElements = {};
    me.TopLevelElements = {};

    jQuery(hierarchy).each(function() {

        var topLevel = this;

        //Start to construct the Banner Div i.e. Africa
        var topLevelDiv = $("<div>");
        ctl.append(topLevelDiv);
        topLevelDiv.addClass(cssPrefix + "Start");

        var rowClass = "oddRow ";

        //Uncomment this to have odd/even row styles on the header
        //      if ((i % 2) == 0) {
        //          rowClass = '';
        //      }

        var expander = $("<div id='" + topLevel.Name.replace(/ /g, "").replace("&", "").replace("/", "") + "' class='" + rowClass + cssPrefix + "Expander'>+</div>");
        topLevelDiv.append(expander);

        expander.click(function() {
            return function() {
                var thisID = this.id.replace(/ /g, "").replace("&", "").replace("/", "");

                if ($('#' + thisID).html() == "+") {
                    $('#' + thisID).html("-");
                    $('.' + thisID).show();
                    //set cookie for last opened region/part of the world/section
                    $.cookie(cssPrefix + 'Expanded', thisID);
                } else {
                    $('#' + thisID).html("+");
                    $('.' + thisID).hide();
                    //remove cookie if this was the last one
                    if ($.cookie(cssPrefix + 'Expanded') == thisID) {
                        $.cookie(cssPrefix + 'Expanded', 'nothing');
                    }
                }


            }
        } (expander));


        var idBase = topLevel.Name.replace(/ /g, "").replace("&", "").replace("/", "");

        var titleDiv = $("<div id='" + idBase + "Name' class='" + rowClass + cssPrefix + "Name'>" + topLevel.Name + "</div>");

        topLevelDiv.append(titleDiv);

        var topTemp = $("<div id='" + idBase + "Box' class='" + rowClass + "Box'></div>");

        topLevelDiv.append(topTemp);

        var topLevelImg = $("<img id='" + idBase + "Image' src='../img/partiallyselected.png' />");

        topTemp.append(topLevelImg);

        me.SelectDeselectAllElements[topLevel.Name] = [topTemp, titleDiv];
        me.TopLevelElements[topLevel.Name] = topLevelImg;

        jQuery(topLevel.SubCategories).each(function() {

            var entry = this;

            var imageId = "HieracrchicalCtl_TreeNodeImage_" + cssPrefix + "_" + entry.Value;

            var outer = $("<div class='" + cssPrefix + "Item " + topLevel.Name.replace(/ /g, "").replace("&", "").replace("/", "") + "'>" +
                        "<div class='" + cssPrefix + "Name'>" + entry.Name + "</div>" +
                        "<div class='box'><img id='" + imageId + "' src='" + getCheckBoxIcon(entry.State) + "' class='" + getCheckBoxClass(entry.State) + "' /></div>" +
                        "</div>");

            topLevelDiv.append(outer);

            me.ImageTreeNodes[entry.Value] = $("#" + imageId, outer);
            me.OuterNodes[entry.Value] = outer;

        });
    });
}


var regionOrPartNameLists = {};

function regionorPartNameList(cssPrefix, lbm, jQueryElem, objectID) {

    var res = convertConcatenatedLBItemsToHieracrchy(lbm.Results.All);

    var initialLoad = (regionOrPartNameLists[cssPrefix] == null);

    if (initialLoad == true) {

        var ctl = new HieracrchicalCtl({ ListBoxMgr: lbm, Hierarchy: res, CssPrefix: cssPrefix, Element: jQueryElem });

        regionOrPartNameLists[cssPrefix] = ctl;
        
        $('.' + cssPrefix + 'Item').hide();

        if (!initialLoad) {
            //open the region that was last opened based on the cookie
            var thisID = $.cookie(cssPrefix + 'Expanded');
            if ($('#' + thisID).html() == "+") {
                $('#' + thisID).html("-");
                $('.' + thisID).show();
            } else {
                $('#' + thisID).html("+");
                $('.' + thisID).hide();
            }
        }
    }
    else {
        regionOrPartNameLists[cssPrefix].Update(lbm, res);
    }
}

function regionNameList(lbm, jQueryElem, objectID) {
    regionorPartNameList("region", lbm, jQueryElem, objectID);
}

function partsNameList(lbm, jQueryElem, objectID) {
    regionorPartNameList("parts", lbm, jQueryElem, objectID);
}

// todo delete?
//var backgroundClass = "evenRowFromJS";

//$("#analysisTop .summaryPair .summaryValue").each(function (i) {
//  if($(this).text() == "-") {
//    //this should not be visible
//    $(this).parent().addClass('initialHide');
//  } else {
//    //this needs the correct background color
//    $(this).parent().removeClass('oddRow');
//    $(this).parent().children().addClass(backgroundClass);
//  }
//  
//  //change the background color for zebra striping
//  if (backgroundClass=="oddRowFromJS") {backgroundClass="evenRowFromJS";} else {backgroundClass="oddRowFromJS";}
//});

// todo delete?
//alert(javascript.href.location);

function populateFactPopupStandardStrings(factNumber) {

    var factNo = (factNumber == 1) ? "" : factNumber;

    //read more about fact1
    $("#RMSubject" + factNo + "Header").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Read_More_Subject2").html());
    $("#subject" + factNumber + "ShortDesc").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Original_Definition").html());
    $("#subject" + factNumber + "LongDesc").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Source").html());
    $("#subject" + factNumber + "wikiLink").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Wikipedia_Subject").html());
    $("#subject" + factNumber + "dnLink").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Article_Search_DN_se_Subject").html());
    $("#subject" + factNumber + "Source").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Source").html());
    $("#subject" + factNumber + "sourceLink").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Source_Web_Site").html());
}

function populateWizardFactPopupStandardStrings() {

    $("#RMSubjectHeader").html($("#TX_StartWizard_World_Theme_Read_More_Subject").html());
    $("#subjectShortDesc").html($("#TX_StartWizard_World_Theme_Original_Definition").html());
    $("#subjectLongDesc").html($("#TX_StartWizard_World_Theme_Source").html());
    $("#subjectwikiLink").html($("#TX_StartWizard_World_Theme_Wikipedia").html());
    $("#subjectdnLink").html($("#TX_StartWizard_World_Theme_Article_Search_DN_se").html());
    $("#subjectSource").html($("#TX_StartWizard_World_Theme_Source").html());
    $("#subjectsourceLink").html($("#TX_StartWizard_World_Theme_Source_Web_Site").html());
}

function onBeforeReadMoreAboutTheCountries() {

    //read more about the countries
    $("#RMCountryTopHeader").html($("#TX_World_Lab_Top_Section_Summary_Read_More_Countries2").html());
    $(".wikilink").html($("#TX_World_Lab_Top_Section_Summary_Wikipedia").html());
    $(".dnlink").html($("#TX_World_Lab_Top_Sectionz_Summary_Article_Search_DN_se").html());
    $(".anthemlink").html($("#TX_World_Lab_Top_Section_Summary_Anthem").html());
    $(".officiallink").html($("#TX_World_Lab_Top_Section_Summary_Official_Web_Site").html());
    $(".tourismlink").html($("#TX_World_Lab_Top_Section_Summary_Tourist_Web_Site").html());
}

function onBeforeReadMoreAboutYear(factNumber) {
    
    var factNo = (factNumber == 1) ? "" : factNumber;
    
    //read more about the countries
    $("#RMYear" + factNumber + "Header").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Read_More_Year_2").html());
    $("#year" + factNumber + "year").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Year").html());
    $("#year" + factNumber + "wikilink").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Wikipedia_Year").html());
    $("#year" + factNumber + "dnlink").html($("#TX_World_Lab_Bottom_Section_Fact" + factNo + "_Article_Search_DN_se_Year").html());
}

qwwHub.Register({ OnAllAvqUpdateCompletesCalled: function() {
    //results only
    if (Factlab.IsResultsPage) {
        setTimeout(
        function() {
            $("#injectTotal").html($("#TX_World_Lab_Top_Section_Top_Entries_Total_Text").html());
            $("#injectMean").html($("#TX_World_Lab_Top_Section_Top_Entries_Mean_value_Text").html());
            $("#injectRefCountry").html($("#TX_World_Lab_Top_Section_Top_Entries_Ref_Country_Name").html());

            if ($("#TX_World_Lab_Top_Section_Top_Entries_Ref_Country_Name").css('display') == 'none') {
                $("#injectRefCountry").hide();
                $("#injectRefCol2").hide();
                $("#injectRefCol3").hide();
                $("#injectRefCol4").hide();
            }
            else {
                $("#injectRefCountry").show();
                $("#injectRefCol2").show();
                $("#injectRefCol3").show();
                $("#injectRefCol4").show();
            }

            if ($('#factContainer1').is(':visible')) {
                $("#Fact1_Header").html($("#TX_World_Lab_Top_Section_Top_Entries_Top_Fact1_Text").html());
                $("#injectTotalCol2").html($("#TX_World_Lab_Top_Section_Top_Entries_Fact1_Total_Cal").html());
                $("#injectMeanCol2").html($("#TX_World_Lab_Top_Section_Top_Entries_Mean_value_Cal").html());
                $("#injectRefCol2").html($("#TX_World_Lab_Top_Section_Top_Entries_Ref_Country_Value").html());
            } else {
                $("#Fact1_Header").html('');
                $("#injectTotalCol2").html('');
                $("#injectMeanCol2").html('');
                $("#injectRefCol2").html('');
            }
            if ($('#factContainer2').is(':visible')) {
                $("#Fact2_Header").html($("#TX_World_Lab_Top_Section_Top_Entries_Top_Fact2_Text").html());
                $("#injectTotalCol3").html($("#TX_World_Lab_Top_Section_Top_Entries_Fact2_Total_Cal").html());
                $("#injectMeanCol3").html($("#TX_World_Lab_Top_Section_Top_Entries_Fact2_Mean_value_Cal").html());
                $("#injectRefCol3").html($("#TX_World_Lab_Top_Section_Top_Entries_Fact2_Ref_Country_Value").html());
            } else {
                $("#Fact2_Header").html('');
                $("#injectTotalCol3").html('');
                $("#injectMeanCol3").html('');
                $("#injectRefCol3").html('');
            }
            if ($('#factContainer3').is(':visible')) {
                $("#Fact3_Header").html($("#TX_World_Lab_Top_Section_Top_Entries_Top_Fact3_Text").html());
                $("#injectTotalCol4").html($("#TX_World_Lab_Top_Section_Top_Entries_Fact3_Total_Cal").html());
                $("#injectMeanCol4").html($("#TX_World_Lab_Top_Section_Top_Entries_Fact3_Mean_value_Cal").html());
                $("#injectRefCol4").html($("#TX_World_Lab_Top_Section_Top_Entries_Fact3_Ref_Country_Value").html());
            } else {
                $("#Fact3_Header").html('');
                $("#injectTotalCol4").html('');
                $("#injectMeanCol4").html('');
                $("#injectRefCol4").html('');
            }
        }, 10);
    }
}
});

top5 = function(tbl) {
    //add the html to the element defined in the web page
    $("#CH_World_Lab_Top_Section_Bar_Chart_Top5").html(buildTopBottom5List(tbl, "#TX_World_Lab_Top_Section_Bar_Chart_Top5"));
    $("#CH_World_Lab_Bottom_Section_Fact_Bar_Chart_Top5").html(buildTopBottom5List(tbl, "#CH_World_Lab_Bottom_Section_Fact_Bar_Chart_Top5"));
    $("#CH_World_Lab_Bottom_Section_Fact2_Bar_Chart_Top5").html(buildTopBottom5List(tbl, "#TX_World_Lab_Bottom_Section_Fact2_Bar_Chart_Top5"));
    $("#CH_World_Lab_Bottom_Section_Fact3_Bar_Chart_Top5").html(buildTopBottom5List(tbl, "#TX_World_Lab_Bottom_Section_Fact3_Bar_Chart_Top5"));
}

function bottom5(tbl) {
    //add the html to the element defined in the web page
    $("#CH_World_Lab_Top_Section_Bar_Chart_Bottom5").html(buildTopBottom5List(tbl, "#TX_World_Lab_Top_Section_Bar_Chart_Bottom5"));
    $("#CH_World_Lab_Bottom_Section_Fact_Bar_Chart_Bottom5").html(buildTopBottom5List(tbl, "#CH_World_Lab_Bottom_Section_Fact_Bar_Chart_Bottom5"));
    $("#CH_World_Lab_Bottom_Section_Fact2_Bar_Chart_Bottom5").html(buildTopBottom5List(tbl, "#TX_World_Lab_Bottom_Section_Fact2_Bar_Chart_Bottom5"));
    $("#CH_World_Lab_Bottom_Section_Fact3_Bar_Chart_Bottom5").html(buildTopBottom5List(tbl, "#TX_World_Lab_Bottom_Section_Fact3_Bar_Chart_Bottom5"));    
};

function renderRMSubject_WLTSF(tbl) {
    renderRMSubject_ForSpecificSubject(tbl, "subject", 0, "CH_StartWizard_World_Theme_Read_More_Subject");
};

function renderRMSubject_WLBSF1(tbl) {
    renderRMSubject_ForSpecificSubject(tbl, "subject1", 1, "CH_World_Lab_Bottom_Section_Fact_Read_More_Subject");
};

function renderRMSubject_WLBSF2(tbl) {
    renderRMSubject_ForSpecificSubject(tbl, "subject2", 2, "CH_World_Lab_Bottom_Section_Fact2_Read_More_Subject");
};

function renderRMSubject_WLBSF3(tbl) {
    renderRMSubject_ForSpecificSubject(tbl, "subject3", 3, "CH_World_Lab_Bottom_Section_Fact3_Read_More_Subject");
};


function renderRMYear(tbl) {
    renderRMYear_ForSpecificYear(tbl, "year1", "CH_World_Lab_Bottom_Section_Fact_Read_More_Year", 1);
};

function renderRMYear2(tbl) {
    renderRMYear_ForSpecificYear(tbl, "year2", "CH_World_Lab_Bottom_Section_Fact2_Read_More_Year", 2);
};

function renderRMYear3(tbl) {
    renderRMYear_ForSpecificYear(tbl, "year3", "CH_World_Lab_Bottom_Section_Fact3_Read_More_Year", 3);
};

function renderRMCountries_WLTS_top(tbl) {
    renderRMCountries_WLTS_top_ForSpecificObject(tbl, "CH_World_Lab_Top_Section_Summary_Read_More_Countries");
    onBeforeReadMoreAboutTheCountries();
};

function renderRMCountries_WLTS_bottom(tbl) {
    renderRMCountries_WLTS_bottom_ForSpecificObject(tbl, "CH_World_Lab_Bottom_Section_Summary_Read_More_Countries");
};

var isPageFirstLoad = true;
qwwHub.Register({ OnAllAvqUpdateCompletesCalled: function() {
    if (isPageFirstLoad) {
        if (Factlab.IsResultsPage) {
            $('#TX_World_Lab_Bottom_Section_Choose_Fact3').hide();
            $('#TX_World_Lab_Bottom_Section_Choose_Fact2').hide();
            //make the results page load nicer visually
            $('#factAdder').removeClass('initialHide');
            $('#factContainer1').removeClass('initialHide');
            $('#countryContainer').removeClass('initialHide');
            $('#Summary').removeClass('initialHide');

            if ($('#TX_World_Lab_Top_Section_Fact2').html().indexOf('>') > -1 || $('#TX_World_Lab_Top_Section_Fact2').html().indexOf('&gt') > -1) {
                $('#factContainer2').removeClass('initialHide');
                $('#remove2').removeClass('initialHide');
                $('#toggle2_pipe').show();
                $('#TX_World_Lab_Bottom_Section_Choose_Fact2').attr('style', 'display: none;');
                $('#TX_World_Lab_Bottom_Section_Choose_Fact3').attr('style', 'display: inline;');

                $('#TX_World_Lab_Bottom_Section_Show_All').removeClass('noBorder');
                $('#TX_World_Lab_Bottom_Section_Show_All').addClass('border');
            } else {
                if ($('#TX_World_Lab_Top_Section_Fact1_Countries').css('display') == 'none') {
                    $('#TX_World_Lab_Bottom_Section_Choose_Fact2').attr('style', 'display: none;');
                }
                else {
                    $('#TX_World_Lab_Bottom_Section_Choose_Fact2').attr('style', 'display: inline;');
                }
                $('#TX_World_Lab_Bottom_Section_Choose_Fact3').attr('style', 'display: none;');
            }

            if ($('#TX_World_Lab_Top_Section_Fact3').html().indexOf('>') > -1 || $('#TX_World_Lab_Top_Section_Fact3').html().indexOf('&gt') > -1) {
                $('#factContainer3').removeClass('initialHide');
                $('#remove2').addClass('initialHide');
                $('#toggle2_pipe').hide();
                $('#remove3').removeClass('initialHide');
                $('#TX_World_Lab_Bottom_Section_Choose_Fact3').attr('style', 'display: none;');

                $('#TX_World_Lab_Bottom_Section_Show_All').removeClass('border');
                $('#TX_World_Lab_Bottom_Section_Show_All').addClass('noBorder');
            }
            isPageFirstLoad = false;
        } else {
            $('.skipLinkWithButtons input').click(function() {
                window.location = "results.aspx";
                return false;
            });
        }
    }

    if (Factlab.IsResultsPage) {
        $('#toogle5Ctl').removeClass('initialHide');
        if ($('#TX_World_Lab_Top_Section_Summary_Flag').attr('style') == 'display: none;' || $('#TX_World_Lab_Top_Section_Summary_Flag').attr('style') == 'DISPLAY: none') {
            $("#singleCountryFlag").attr('style', 'display: none;');
            $("#TX_World_Lab_Top_Section_Summary_Country_Text").attr('style', 'height: 22px; line-height: 22px;');
            $("#TX_World_Lab_Top_Section_Summary_Country").attr('style', 'height: 22px; line-height: 22px;');
            $("#TX_World_Lab_Top_Section_Summary_Read_More_Countries").attr('style', 'height: 22px; line-height: 22px;');
        } else {
            var sPath = window.location.href;
            var sPage = sPath.substring(0, sPath.lastIndexOf('/'));
            $("#singleCountryFlag").attr('src', '..' + $("#TX_World_Lab_Top_Section_Summary_Flag").html().replace(new RegExp(/\\/g), '/'));
            //$("#TX_World_Lab_Top_Section_Summary_Flag").attr('style', 'display: none;');
            $("#singleCountryFlag").attr('style', 'display: inline;');
            $("#TX_World_Lab_Top_Section_Summary_Country_Text").attr('style', 'height: 44px; line-height: 44px;');
            $("#TX_World_Lab_Top_Section_Summary_Country").attr('style', 'height: 44px; line-height: 44px;');
            $("#TX_World_Lab_Top_Section_Summary_Read_More_Countries").attr('style', 'height: 44px; line-height: 44px;');
        }

        if ($('#TX_World_Lab_Top_Section_Summary_Reference_Country_Name').attr('style') == 'display: none;' || $('#TX_World_Lab_Top_Section_Summary_Reference_Country_Name').attr('style') == 'DISPLAY: none') {
            $("#sumCountryTable").attr('style', 'display: none;');
        } else {
            $("#sumCountryTable").attr('style', 'display: block;');
        }
    }
}
});

// individual toggle functions
function toggleFactVisibility(index) {
    var index2 = index;
      
    if (index == 1) { index2 = ''; }

    var isVisible = ($('#toggle' + index + ' #TX_World_Lab_Bottom_Section_Fact' + index2 + '_Show').is(':visible'));

    $('#toggle' + index + '_spinner').show();

    if (isVisible) {
        //$("#fact" + index).show();
        //$('#toggle' + index + ' #TX_World_Lab_Bottom_Section_Fact' + index2 + '_Show').hide();
        //$('#toggle' + index + ' #TX_World_Lab_Bottom_Section_Fact' + index2 + '_Hide').show();
        switch(index)
        {
            case 1:
                fact1VisibilityListboxMgr.MakeSingleSelection('showFact_1', true, true); 
                break;
            case 2:
                fact2VisibilityListboxMgr.MakeSingleSelection('showFact_2', true, true); 
                break;
            case 3:
                fact3VisibilityListboxMgr.MakeSingleSelection('showFact_3', true, true); 
                break;
        }
    } else {
        //$("#fact" + index).hide();
        //$('#toggle' + index + ' #TX_World_Lab_Bottom_Section_Fact' + index2 + '_Show').show();
        //$('#toggle' + index + ' #TX_World_Lab_Bottom_Section_Fact' + index2 + '_Hide').hide();
        switch (index) {
            case 1:
                fact1VisibilityListboxMgr.ClearAll(true); 
                break;
            case 2:
                fact2VisibilityListboxMgr.ClearAll(true); 
                break;
            case 3:
                fact3VisibilityListboxMgr.ClearAll(true); 
                break;
        }
    }
};

$('#toggle1').click(function() {
    toggleFactVisibility(1);
    return false;
});
$('#toggle2').click(function() {
    toggleFactVisibility(2);
    return false;
});
$('#toggle3').click(function() {
    toggleFactVisibility(3);
    return false;
});


$('#toggle5').click(function() {
    //var isVisible = ($('#toggle5 #TX_World_Lab_Top_Section_Selection').is(':visible'));
    //debugger;
    $('#toggle5_spinner').show();
    isVisible = $('#toggle5')[0].IsShowing;
    if (!isVisible) {
        topFilterVisibilityListboxMgr.MakeSingleSelection('showFilter', true, true);

    } else {
        topFilterVisibilityListboxMgr.ClearAll(true);
    }

    return false;
});

// group toggle functions
$('#TX_World_Lab_Bottom_Section_Show_All').click(function() {

    $('#toggle1_spinner').show();
    $('#toggle2_spinner').show();
    $('#toggle3_spinner').show();
    //fact1VisibilityListboxMgr.AddSelection(['showFact_1'], true, false);
    //fact2VisibilityListboxMgr.AddSelection(['showFact_2'], true, false);
    //fact3VisibilityListboxMgr.AddSelection(['showFact_3'], true, true);

    fact1VisibilityListboxMgr.MakeSingleSelection(0, false, true);
    fact2VisibilityListboxMgr.MakeSingleSelection(0, false, true);
    fact3VisibilityListboxMgr.MakeSingleSelection(0, false, true);

    return false;
});

$('#TX_World_Lab_Bottom_Section_Hide_All').click(function() {

    $('#toggle1_spinner').show();
    $('#toggle2_spinner').show();
    $('#toggle3_spinner').show();
    fact1VisibilityListboxMgr.ClearAll(false);
    fact2VisibilityListboxMgr.ClearAll(false);
    fact3VisibilityListboxMgr.ClearAll(true);
});


// add a new fact
$('#TX_World_Lab_Bottom_Section_Choose_Fact2').click(function() {
    $('#factContainer2').removeClass('initialHide');
    //fact2VisibilityListboxMgr.MakeSingleSelection('showFact_2', true, true);
    fact2VisibilityListboxMgr.MakeSingleSelection(0, false, true);

    $('#TX_World_Lab_Bottom_Section_Choose_Fact2').hide();

    //    $('#TX_World_Lab_Bottom_Section_Choose_Fact3').show();
    $("#fact2").hide();

    $("#fact2").slideToggle("slow");
    $('#TX_World_Lab_Bottom_Section_Fact2_Show').hide();
    $('#TX_World_Lab_Bottom_Section_Fact2_Hide').show();

    $('#remove2').removeClass('initialHide');
    $('#toggle2_pipe').show();

    return false;
});

$('#TX_World_Lab_Bottom_Section_Choose_Fact3').click(function() {
    $('#factContainer3').removeClass('initialHide');
    //fact3VisibilityListboxMgr.MakeSingleSelection('showFact_3', true, true);
    fact3VisibilityListboxMgr.MakeSingleSelection(0, false, true);

    $('#TX_World_Lab_Bottom_Section_Choose_Fact3').hide();
    $("#fact3").hide();

    $("#fact3").slideToggle("slow");
    $('#TX_World_Lab_Bottom_Section_Fact3_Show').hide();
    
    $('#TX_World_Lab_Bottom_Section_Fact3_Hide').show();

    $('#remove2').addClass('initialHide');
    $('#toggle2_pipe').hide();
    
    $('#remove3').removeClass('initialHide');
    $('#TX_World_Lab_Bottom_Section_Show_All').removeClass('border');
    $('#TX_World_Lab_Bottom_Section_Show_All').addClass('noBorder');
    return false;
});

// remove a fact
$("#remove2").click(function() {
    $('#factContainer2').addClass('initialHide');
    fact2VisibilityListboxMgr.ClearAll(true);
    /*if ($('#toggle2').html() == "[-]") {$("#fact2").slideToggle("slow");$('#toggle2').html("[+]");}*/
    $("#fact2").hide();

    $('#TX_World_Lab_Bottom_Section_Fact2_Show').show();
    $('#TX_World_Lab_Bottom_Section_Fact2_Hide').hide();

    $('#remove2').addClass('initialHide');
    $('#toggle2_pipe').hide();
    
    // remove fact 2, show add fact 2 button.
    $('#TX_World_Lab_Bottom_Section_Choose_Fact2').show();  //show add fact 2 button
    $('#TX_World_Lab_Bottom_Section_Choose_Fact3').hide(); //hide add fact 3 button

    return false;
});

$("#remove3").click(function() {
    $('#factContainer3').addClass('initialHide');
    fact3VisibilityListboxMgr.ClearAll(true);
    /*if ($('#toggle3').html() == "[-]") {$("#fact3").slideToggle("slow");$('#toggle3').html("[+]");}*/

    $("#fact3").hide();
    $('#TX_World_Lab_Bottom_Section_Fact3_Show').show();

    $('#TX_World_Lab_Bottom_Section_Fact3_Hide').hide();

    $('#remove3').addClass('initialHide');
    
    $('#remove2').removeClass('initialHide');
    $('#toggle2_pipe').show();
    
    // remove fact 3, show add fact 3 button.
    $('#TX_World_Lab_Bottom_Section_Choose_Fact2').hide(); //hide add fact 2 button
    $('#TX_World_Lab_Bottom_Section_Choose_Fact3').show(); //show add fact 3 button

    $('#TX_World_Lab_Bottom_Section_Show_All').removeClass('noBorder');
    $('#TX_World_Lab_Bottom_Section_Show_All').addClass('border');

    return false;
});

/* Script by: www.jtricks.com
 * Version: 20071017
 * Latest version:
 * www.jtricks.com/javascript/navigation/floating.html
 */
var floatingMenuId = 'floatdiv';
var floatingMenu =
{
//    targetX: 920,
    targetY: 10,

    hasInner: typeof(window.innerWidth) == 'number',
    hasElement: typeof(document.documentElement) == 'object'
        && typeof(document.documentElement.clientWidth) == 'number',

    menu:
        document.getElementById
        ? document.getElementById(floatingMenuId)
        : document.all
          ? document.all[floatingMenuId]
          : document.layers[floatingMenuId]
};

floatingMenu.move = function() {
    //  floatingMenu.menu.style.left = floatingMenu.nextX + 'px';
    if (floatingMenu.menu) { // Check added by CB so file could also be used on test pages.
        floatingMenu.menu.style.top = floatingMenu.nextY + 'px';
        floatingMenu.menu.style.zIndex = 0;
    }
}

floatingMenu.computeShifts = function ()
{
    var de = document.documentElement;

//    floatingMenu.shiftX =  
//        floatingMenu.hasInner  
//        ? pageXOffset  
//        : floatingMenu.hasElement  
//          ? de.scrollLeft  
//          : document.body.scrollLeft;  
//    if (floatingMenu.targetX < 0)
//    {
//        floatingMenu.shiftX +=
//            floatingMenu.hasElement
//            ? de.clientWidth
//            : document.body.clientWidth;
//    }

    floatingMenu.shiftY = 
        floatingMenu.hasInner
        ? pageYOffset
        : floatingMenu.hasElement
          ? de.scrollTop
          : document.body.scrollTop;
    if (floatingMenu.targetY < 0)
    {
        if (floatingMenu.hasElement && floatingMenu.hasInner)
        {
            // Handle Opera 8 problems
            floatingMenu.shiftY +=
                de.clientHeight > window.innerHeight
                ? window.innerHeight
                : de.clientHeight
        }
        else
        {
            floatingMenu.shiftY +=
                floatingMenu.hasElement
                ? de.clientHeight
                : document.body.clientHeight;
        }
    }
}
/*
floatingMenu.calculateCornerX = function()
{
    if (floatingMenu.targetX != 'center')
        return floatingMenu.shiftX + floatingMenu.targetX;

    var width = parseInt(floatingMenu.menu.offsetWidth);

    var cornerX =
        floatingMenu.hasElement
        ? (floatingMenu.hasInner
           ? pageXOffset
           : document.documentElement.scrollLeft) + 
          (document.documentElement.clientWidth - width)/2
        : document.body.scrollLeft + 
          (document.body.clientWidth - width)/2;
    return cornerX;
};
*/
floatingMenu.calculateCornerY = function()
{
    if (floatingMenu.targetY != 'center')
        return floatingMenu.shiftY + floatingMenu.targetY;

    var height = parseInt(floatingMenu.menu.offsetHeight);

    // Handle Opera 8 problems
    var clientHeight = 
        floatingMenu.hasElement && floatingMenu.hasInner
        && document.documentElement.clientHeight 
            > window.innerHeight
        ? window.innerHeight
        : document.documentElement.clientHeight

    var cornerY =
        floatingMenu.hasElement
        ? (floatingMenu.hasInner  
           ? pageYOffset
           : document.documentElement.scrollTop) + 
          (clientHeight - height)/2
        : document.body.scrollTop + 
          (document.body.clientHeight - height)/2;
    return cornerY;
};

floatingMenu.doFloat = function()
{
    var stepX, stepY;

    floatingMenu.computeShifts();

  //  var cornerX = floatingMenu.calculateCornerX();

  //  var stepX = (cornerX - floatingMenu.nextX) * .07;
  //  if (Math.abs(stepX) < .5)
  //  {
  //      stepX = cornerX - floatingMenu.nextX;
  //  }

    var cornerY = floatingMenu.calculateCornerY();

    var stepY = (cornerY - floatingMenu.nextY) * .07;
    if (Math.abs(stepY) < .5)
    {
        stepY = cornerY - floatingMenu.nextY;
    }

    if (Math.abs(stepY) > 0)//Math.abs(stepX) > 0 ||
        
    {
//        floatingMenu.nextX += stepX;
        floatingMenu.nextY += stepY;
        floatingMenu.move();
    }

    setTimeout('floatingMenu.doFloat()', 20);
};

// addEvent designed by Aaron Moore
floatingMenu.addEvent = function(element, listener, handler)
{
    if(typeof element[listener] != 'function' || 
       typeof element[listener + '_num'] == 'undefined')
    {
        element[listener + '_num'] = 0;
        if (typeof element[listener] == 'function')
        {
            element[listener + 0] = element[listener];
            element[listener + '_num']++;
        }
        element[listener] = function(e)
        {
            var r = true;
            e = (e) ? e : window.event;
            for(var i = element[listener + '_num'] -1; i >= 0; i--)
            {
                if(element[listener + i](e) == false)
                    r = false;
            }
            return r;
        }
    }

    //if handler is not already stored, assign it
    for(var i = 0; i < element[listener + '_num']; i++)
        if(element[listener + i] == handler)
            return;
    element[listener + element[listener + '_num']] = handler;
    element[listener + '_num']++;
};

floatingMenu.init = function()
{
    floatingMenu.initSecondary();
    floatingMenu.doFloat();
};

// Some browsers init scrollbars only after
// full document load.
floatingMenu.initSecondary = function()
{
    floatingMenu.computeShifts();
  //  floatingMenu.nextX = floatingMenu.calculateCornerX();
    floatingMenu.nextY = floatingMenu.calculateCornerY();
    floatingMenu.move();
}

if (document.layers)
    floatingMenu.addEvent(window, 'onload', floatingMenu.init);
else
{
    floatingMenu.init();
    floatingMenu.addEvent(window, 'onload',
        floatingMenu.initSecondary);
}

$.fn.reorder = function() {
  // random array sort from
  // http://javascript.about.com/library/blsort2.htm
  function randOrd() { return(Math.round(Math.random())-0.5); }

  return($(this).each(function() {
    var $this = $(this);
    var $children = $this.children();
    var childCount = $children.length;

    if (childCount > 1) {
      $children.remove();

      var indices = new Array();
      for (i=0;i<childCount;i++) { indices[indices.length] = i; }
      indices = indices.sort(randOrd);
      $.each(indices,function(j,k) { $this.append($children.eq(k)); });

    }
  }));
}
$('#sponsorList').reorder();

/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
 *       used when the cookie was set.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};

/*
 * Thickbox 3.1 - One Box To Rule Them All.
 * By Cody Lindley (http://www.codylindley.com)
 * Copyright (c) 2007 cody lindley
 * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
*/

// TODO: This image is not being found (i.e. in Fiddler trace). Is it being used, should the path be changed?		  
//var tb_pathToImage = "/loadingAnimation.gif";

/*!!!!!!!!!!!!!!!!! edit below this line at your own risk !!!!!!!!!!!!!!!!!!!!!!!*/

//on page load call tb_init
$(document).ready(function(){   
	tb_init('a.thickbox, area.thickbox, input.thickbox');//pass where to apply thickbox
	imgLoader = new Image();// preload image
	//imgLoader.src = tb_pathToImage;
});

//add thickbox to href & area elements that have a class of .thickbox
function tb_init(domChunk){
    $(domChunk).click(function() {
        var t = this.title || this.name || null;
        var a = this.href || this.alt;
        var g = this.rel || false;
        tb_show(t, a, g);
        this.blur();
        return false;
    });
}

function tb_show(caption, url, imageGroup) {//function called when the user clicks on a thickbox link
    
	try {
		if (typeof document.body.style.maxHeight === "undefined") {//if IE 6
			$("body","html").css({height: "100%", width: "100%"});
			$("html").css("overflow","hidden");
			if (document.getElementById("TB_HideSelect") === null) {//iframe to hide select elements in ie6
				$("body").append("<iframe id='TB_HideSelect'></iframe><div id='TB_overlay'></div><div id='TB_window'></div>");
				$("#TB_overlay").click(tb_remove);
			}
		}else{//all others
			if(document.getElementById("TB_overlay") === null){
				$("body").append("<div id='TB_overlay'></div><div id='TB_window'></div>");
				$("#TB_overlay").click(tb_remove);
			}
		}
		
		if(tb_detectMacXFF()){
			$("#TB_overlay").addClass("TB_overlayMacFFBGHack");//use png overlay so hide flash
		}else{
			$("#TB_overlay").addClass("TB_overlayBG");//use background and opacity
		}
		
		if(caption===null){caption="";}
		$("body").append("<div id='TB_load'><img src='"+imgLoader.src+"' /></div>");//add loader to the page
		$('#TB_load').show();//show loader
		
		var baseURL;
	   if(url.indexOf("?")!==-1){ //ff there is a query string involved
			baseURL = url.substr(0, url.indexOf("?"));
	   }else{ 
	   		baseURL = url;
	   }
	   
	   var urlString = /\.jpg$|\.jpeg$|\.png$|\.gif$|\.bmp$/;
	   var urlType = baseURL.toLowerCase().match(urlString);

		if(urlType == '.jpg' || urlType == '.jpeg' || urlType == '.png' || urlType == '.gif' || urlType == '.bmp'){//code to show images
				
			TB_PrevCaption = "";
			TB_PrevURL = "";
			TB_PrevHTML = "";
			TB_NextCaption = "";
			TB_NextURL = "";
			TB_NextHTML = "";
			TB_imageCount = "";
			TB_FoundURL = false;
			if(imageGroup){
				TB_TempArray = $("a[@rel="+imageGroup+"]").get();
				for (TB_Counter = 0; ((TB_Counter < TB_TempArray.length) && (TB_NextHTML === "")); TB_Counter++) {
					var urlTypeTemp = TB_TempArray[TB_Counter].href.toLowerCase().match(urlString);
						if (!(TB_TempArray[TB_Counter].href == url)) {						
							if (TB_FoundURL) {
								TB_NextCaption = TB_TempArray[TB_Counter].title;
								TB_NextURL = TB_TempArray[TB_Counter].href;
								TB_NextHTML = "<span id='TB_next'>&nbsp;&nbsp;<a href='#'>Next &gt;</a></span>";
							} else {
								TB_PrevCaption = TB_TempArray[TB_Counter].title;
								TB_PrevURL = TB_TempArray[TB_Counter].href;
								TB_PrevHTML = "<span id='TB_prev'>&nbsp;&nbsp;<a href='#'>&lt; Prev</a></span>";
							}
						} else {
							TB_FoundURL = true;
							TB_imageCount = "Image " + (TB_Counter + 1) +" of "+ (TB_TempArray.length);											
						}
				}
			}

			imgPreloader = new Image();
			imgPreloader.onload = function(){		
			imgPreloader.onload = null;
				
			// Resizing large images - orginal by Christian Montoya edited by me.
			var pagesize = tb_getPageSize();
			var x = pagesize[0] - 150;
			var y = pagesize[1] - 150;
			var imageWidth = imgPreloader.width;
			var imageHeight = imgPreloader.height;
			if (imageWidth > x) {
				imageHeight = imageHeight * (x / imageWidth); 
				imageWidth = x; 
				if (imageHeight > y) { 
					imageWidth = imageWidth * (y / imageHeight); 
					imageHeight = y; 
				}
			} else if (imageHeight > y) { 
				imageWidth = imageWidth * (y / imageHeight); 
				imageHeight = y; 
				if (imageWidth > x) { 
					imageHeight = imageHeight * (x / imageWidth); 
					imageWidth = x;
				}
			}
			// End Resizing
			
			TB_WIDTH = imageWidth + 30;
			TB_HEIGHT = imageHeight + 60;
			$("#TB_window").append("<a href='' id='TB_ImageOff' title='Close'><img id='TB_Image' src='" + url + "' width='" + imageWidth + "' height='" + imageHeight + "' alt='" + caption + "'/></a>" + "<div id='TB_caption'>" + caption + "<div id='TB_secondLine'>" + TB_imageCount + TB_PrevHTML + TB_NextHTML + "</div></div><div id='TB_closeWindow'><a href='#' id='TB_closeWindowButton' title='Close'><img src='" + Factlab.ImageRoot + "img/x.png' alt='X'></a></div>"); 
			
			$("#TB_closeWindowButton").click(tb_remove);
			
			if (!(TB_PrevHTML === "")) {
				function goPrev(){
					if($(document).unbind("click",goPrev)){$(document).unbind("click",goPrev);}
					$("#TB_window").remove();
					$("body").append("<div id='TB_window'></div>");
					tb_show(TB_PrevCaption, TB_PrevURL, imageGroup);
					return false;	
				}
				$("#TB_prev").click(goPrev);
			}
			
			if (!(TB_NextHTML === "")) {		
				function goNext(){
					$("#TB_window").remove();
					$("body").append("<div id='TB_window'></div>");
					tb_show(TB_NextCaption, TB_NextURL, imageGroup);				
					return false;	
				}
				$("#TB_next").click(goNext);
				
			}

			document.onkeydown = function(e){ 	
				if (e == null) { // ie
					keycode = event.keyCode;
				} else { // mozilla
					keycode = e.which;
				}
				if(keycode == 27){ // close
					tb_remove();
				} else if(keycode == 190){ // display previous image
					if(!(TB_NextHTML == "")){
						document.onkeydown = "";
						goNext();
					}
				} else if(keycode == 188){ // display next image
					if(!(TB_PrevHTML == "")){
						document.onkeydown = "";
						goPrev();
					}
				}	
			};
			
			tb_position();
			$("#TB_load").remove();
			$("#TB_ImageOff").click(tb_remove);
			$("#TB_window").css({display:"block"}); //for safari using css instead of show
			};
			
			imgPreloader.src = url;
		}else{//code to show html
			
			var queryString = url.replace(/^[^\?]+\??/,'');
			var params = tb_parseQuery( queryString );

			TB_WIDTH = (params['width']*1) + 30 || 630; //defaults to 630 if no paramaters were added to URL
			TB_HEIGHT = (params['height']*1) + 40 || 440; //defaults to 440 if no paramaters were added to URL
			ajaxContentW = TB_WIDTH - 30;
			ajaxContentH = TB_HEIGHT - 45;
			
			if(url.indexOf('TB_iframe') != -1){// either iframe or ajax window		
					urlNoQuery = url.split('TB_');
					$("#TB_iframeContent").remove();
					if(params['modal'] != "true"){//iframe no modal
					    $("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>" + caption + "</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton' title='Close'><img src='" + Factlab.ImageRoot + "img/x.png' alt='X'></a></div></div><iframe frameborder='0' hspace='0' src='" + urlNoQuery[0] + "' id='TB_iframeContent' name='TB_iframeContent" + Math.round(Math.random() * 1000) + "' onload='tb_showIframe()' style='width:" + (ajaxContentW + 29) + "px;height:" + (ajaxContentH + 17) + "px;' > </iframe>");
					}else{//iframe modal
					$("#TB_overlay").unbind();
						$("#TB_window").append("<iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 29)+"px;height:"+(ajaxContentH + 17)+"px;'> </iframe>");
					}
			}else{// not an iframe, ajax
					if($("#TB_window").css("display") != "block"){
						if(params['modal'] != "true"){//ajax no modal
						    $("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>" + caption + "</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton'><img src='" + Factlab.ImageRoot + "img/x.png' alt='X'></a></div></div><div id='TB_ajaxContent' style='width:" + ajaxContentW + "px;height:" + ajaxContentH + "px'></div>");
						}else{//ajax modal
						$("#TB_overlay").unbind();
						$("#TB_window").append("<div id='TB_ajaxContent' class='TB_modal' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px;'></div>");	
						}
					}else{//this means the window is already up, we are just loading new content via ajax
						$("#TB_ajaxContent")[0].style.width = ajaxContentW +"px";
						$("#TB_ajaxContent")[0].style.height = ajaxContentH +"px";
						$("#TB_ajaxContent")[0].scrollTop = 0;
						$("#TB_ajaxWindowTitle").html(caption);
					}
			}
					
			$("#TB_closeWindowButton").click(tb_remove);
			$("#TB_closeWindowButton1").click(tb_remove);
			$("#TB_closeWindowButton2").click(tb_remove);
			$("#TB_closeWindowButton3").click(tb_remove);
			$("#TB_closeWindowButton4").click(tb_remove);
			$("#TB_closeWindowButton5").click(tb_remove);
			$("#TB_closeWindowButton6").click(tb_remove);
			$("#TB_closeWindowButton7").click(tb_remove);
			
				if(url.indexOf('TB_inline') != -1){	
					$("#TB_ajaxContent").append($('#' + params['inlineId']).children());
					$("#TB_window").unload(function () {
						$('#' + params['inlineId']).append( $("#TB_ajaxContent").children() ); // move elements back when you're finished
					});
					tb_position();
					$("#TB_load").remove();
					$("#TB_window").css({display:"block"}); 
				}else if(url.indexOf('TB_iframe') != -1){
					tb_position();
					if($.browser.safari){//safari needs help because it will not fire iframe onload
						$("#TB_load").remove();
						$("#TB_window").css({display:"block"});
					}
				}else{
					$("#TB_ajaxContent").load(url += "&random=" + (new Date().getTime()),function(){//to do a post change this load method
						tb_position();
						$("#TB_load").remove();
						tb_init("#TB_ajaxContent a.thickbox");
						$("#TB_window").css({display:"block"});
					});
				}
			
		}

		if(!params['modal']){
			document.onkeyup = function(e){ 	
				if (e == null) { // ie
					keycode = event.keyCode;
				} else { // mozilla
					keycode = e.which;
				}
				if(keycode == 27){ // close
					tb_remove();
				}	
			};
		}
		
	} catch(e) {
		//nothing here
	}
}

//helper functions below
function tb_showIframe(){
	$("#TB_load").remove();
	$("#TB_window").css({display:"block"});
}

function tb_remove() {
 	$("#TB_imageOff").unbind("click");
	$("#TB_closeWindowButton").unbind("click");
	$("#TB_window").fadeOut("fast",function(){$('#TB_window,#TB_overlay,#TB_HideSelect').trigger("unload").unbind().remove();});
	$("#TB_load").remove();
	if (typeof document.body.style.maxHeight == "undefined") {//if IE 6
		$("body","html").css({height: "auto", width: "auto"});
		$("html").css("overflow","");
	}
	document.onkeydown = "";
	document.onkeyup = "";
	//in here we could clear the listbox
	popUpVisibilityListboxMgr.CallAction('CA', true);
	return false;
}

function tb_position() {
$("#TB_window").css({marginLeft: '-' + parseInt((TB_WIDTH / 2),10) + 'px', width: TB_WIDTH + 'px'});
if ((jQuery.browser.msie && jQuery.browser.version == 8)) { // special case for ie8
    $("#TB_window").css({ marginTop: parseInt(-250, 10) + 'px' });
} else if (!(jQuery.browser.msie && jQuery.browser.version < 7)) { // take away IE6
		$("#TB_window").css({marginTop: '-' + parseInt((TB_HEIGHT / 2),10) + 'px'});
	}
}

function tb_parseQuery ( query ) {
   var Params = {};
   if ( ! query ) {return Params;}// return empty object
   var Pairs = query.split(/[;&]/);
   for ( var i = 0; i < Pairs.length; i++ ) {
      var KeyVal = Pairs[i].split('=');
      if ( ! KeyVal || KeyVal.length != 2 ) {continue;}
      var key = unescape( KeyVal[0] );
      var val = unescape( KeyVal[1] );
      val = val.replace(/\+/g, ' ');
      Params[key] = val;
   }
   return Params;
}

function tb_getPageSize(){
	var de = document.documentElement;
	var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
	var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
	arrayPageSize = [w,h];
	return arrayPageSize;
}

function tb_detectMacXFF() {
  var userAgent = navigator.userAgent.toLowerCase();
  if (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox')!=-1) {
    return true;
  }
}





