/*
* 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) {
        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

if (!Qva.Mgr) Qva.Mgr = {}

Qva.Mgr.toolwindowtable = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
    this.BinderId = owner.ID;
    this.BaseName = owner.Name;
}

Qva.Mgr.toolwindowtable.prototype.Inside = function (pos, type) {
    for (var ix = 0; ix < this.DropTargets.length; ++ix) {
        var cell = this.DropTargets[ix];
//        if (cell.dragAccept != type) continue;
        if (!cell.dropObj) continue;
        if (cell.dropObj.Type != type) continue;
        var cellPos    = Qva.GetPageCoords(cell);
        var cellWidth  = parseInt(cell.offsetWidth);
        var cellHeight = parseInt(cell.offsetHeight);
        if (pos.x > cellPos.x && pos.x < cellPos.x + cellWidth &&
            pos.y > cellPos.y && pos.y < cellPos.y + cellHeight) {
            if (pos.y<cellPos.y + 0.37 * cellHeight)
                var vertPosition = 'insertbefore';
            else if (pos.y>cellPos.y + 0.70 * cellHeight)
                var vertPosition = 'insertafter';
            else
                var vertPosition = 'dragto';
//                var vertPosition = (pos.y>cellPos.y + 0.80 * cellHeight) ?'insertafter' : 'dragto';
            if ((cell.dropObj.DropOn && vertPosition == 'dragto') ||(cell.dropObj.InsertAfter && vertPosition == 'insertafter')||(cell.dropObj.InsertBefore && vertPosition == 'insertbefore'))
                return {'Element':cell,'VerticalPosition':vertPosition};
        }
    }
    return null;
}

Qva.Tooltip = null;
Qva.ShowTooltip = function (event, cell) {
    if (!cell.Tooltip) return;
    if(!Qva.Tooltip) {
        Qva.Tooltip = document.createElement("div");
        Qva.Tooltip.className = "QvHover";
        Qva.Tooltip.style.zIndex = 666;
        Qva.Tooltip.style.display = "none";
        Qva.Tooltip.style.position = "absolute";
        Qva.Tooltip.style.backgroundColor = "#FFFFCC";
        Qva.Tooltip.style.border = "solid 1px black";
        Qva.Tooltip.style.padding = "1px 3px 2px 3px";
        document.body.appendChild(Qva.Tooltip);
    }
    Qva.Tooltip.innerHTML = "";
    var lines = cell.Tooltip;
    for (var i = 0; i < lines.length; i++) {
        var p = document.createElement ("span");
        p.innerText = lines [i];
        Qva.Tooltip.appendChild (p);
        var br = document.createElement ("br");
        Qva.Tooltip.appendChild (br);
    }
    if (!event) event = window.event;
    Qva.Tooltip.style.left = (event.clientX + Qva.GetScrollLeft() + 5) + "px";
    Qva.Tooltip.style.top  = (event.clientY + Qva.GetScrollTop() + 5)  + "px";
    Qva.Tooltip.style.display = "";
}

Qva.HideTooltip = function () {
    if(Qva.Tooltip) Qva.Tooltip.style.display = "none";
}

Qva.Mgr.toolwindowtable.prototype.Paint = function(mode, node) {
    this.Touched = true;
    this.DropTargets = [];
    var table = this.Element;
    var rix = 0;
    var colgroup = table.firstChild;
    while(colgroup.firstChild) colgroup.removeChild(colgroup.firstChild);
    for (var line = node.firstChild; line != null; line = line.nextSibling) {
        if (line.nodeName != 'column') continue;
        var col = document.createElement("col");
        col.width = parseInt(line.getAttribute("width"));
        colgroup.appendChild(col);
    }
//    table.style.borderCollapse = "separate";
    for (var line = node.firstChild; line != null; line = line.nextSibling) {
        if (line.nodeName != 'row') continue;
        var row = (rix < table.rows.length) ? table.rows[rix] : table.insertRow(-1);
        ++rix;
        switch(line.getAttribute("class")) {
        case "header":
            row.className = "ToolProperty-Header";
            break;
        case "navigation":
            row.className = "ToolProperty-Navigation";
            break;
        case "warning":
            row.className = "ToolProperty-Warning";
            break;
        default:
            row.className = "";
            break;
        }
       

        var cix = 0;
        for (var child = line.firstChild; child != null; child = child.nextSibling) {
            var cmd = child.getAttribute("name");
            if (cmd) cmd = this.BaseName + '.' + cmd;
            var cell = (cix < row.cells.length) ? row.cells[cix] : row.insertCell(-1);
            ++cix;
            var indent = child.getAttribute ('indent');
            if (indent) {
                indent = 12 * parseInt(indent);
                cell.style.paddingLeft = indent + 'pt';
            } else {
                cell.style.paddingLeft = '';
            }
            var label = child.getAttribute("label");
            switch(child.getAttribute("class")) {
            case "highlight":
                cell.className = "ToolProperty-Highlight";
                break;
            }

            var colspan = child.getAttribute ('colspan');
            if (colspan) {
                cell.colSpan = parseInt(colspan);
            } else {
                cell.colSpan = 1;
            }
            
            var tips = child.getElementsByTagName ('tooltip');
            var tiplen = tips.length;
            if (tiplen > 0) {
                var tiplist = [];            
                for (var ix = 0; ix < tiplen; ++ix) {
                    tiplist.push(tips[ix].getAttribute('text'));
                }
                cell.Tooltip = tiplist;
                cell.onmouseover = function (event) { Qva.ShowTooltip(event, this); }
                cell.onmouseout = function () { Qva.HideTooltip(); }
            } else {
                cell.Tooltip = null;
            }
            switch(child.nodeName) {
            case 'title':
                cell.innerText = child.getAttribute("text");
                break;
            case 'link':
                cell.innerText = child.getAttribute("text");
                cell.BinderId = this.BinderId;
                cell.Name = cmd;
                cell.className = "ToolProperty-Link";
                cell.onclick = function() {
                    var binder = Qva.GetBinder(this.BinderId);
                    if (!binder.Enabled) return;
                    binder.Set (this.Name, "action", "", true);
                }
                break;
            case 'literal':
                cell.innerHTML = "<span></span>"
                cell.className = "ToolProperty-Literal";
                cell.firstChild.innerText = child.getAttribute("text");
                break;
            case 'text':
            case 'numeric':
                var actor = null;
                if (indent) cell.style.paddingLeft = indent + 'pt';
                if (label) {
                    cell.innerHTML = "<span></span> <input />"
                    cell.firstChild.innerText = label;
                    cell.firstChild.className = "ToolProperty-Label";
                } else {
                    var range = child.getAttribute("range");
                    if (range == 'percent') {
                        cell.innerHTML = "<table cellspacing='0' cellpadding='0' width1='100%' ><tr><td width='30pt' >0%</td><td width='134px'><span style='position:absolute;'><hr style='margin:0pt;position:absolute;width:128px;' /><button style='top:-4px;position:absolute;width:4px;height:9px;background-color:lightgrey;border:solid 1px darkgray'></button></span></td><td width='36pt' align='right'>100%</td></tr></table>"
                        actor = cell.lastChild.rows[0].cells[1].firstChild.lastChild;
                    } else {
                        var hsize = parseInt(child.getAttribute("size"));
                        if (isNaN(hsize)) {
                            cell.innerHTML = "<input/>"
                        } else {
                            cell.innerHTML = "<textarea rows='" + hsize + "'></textarea>"
                        } 
                    }
                    cell.className = "ToolProperty-TextInput";
                }
                if (actor == null) actor = cell.lastChild;
                if (child.nodeName == "numeric" && actor.tagName == 'INPUT') {
                    actor.style.width = "24pt";
                    actor.style.textAlign = 'right';
                }
                actor.Name = cmd;
                if (actor.tagName != 'BUTTON') {
                    actor.BinderId = this.BinderId;
                    actor.readOnly = child.getAttribute("mode") != "enabled";
                    actor.value = child.getAttribute("value");
                    actor.onchange = function () {
                        var binder = Qva.GetBinder(this.BinderId);
                        if (!binder.Enabled) return;
                        binder.Set (this.Name, "value", this.value, true);
                    }
                } else {
                    var pos = parseInt(child.getAttribute("value"));
                    pos = isNaN(pos) ? 0 : pos / 2;
                    actor.style.left = pos + 'px';
                    actor.binderid = this.BinderId;
                    actor.moveObj = '*';
                    actor.xOnly = true;
                    actor.xMin = parseInt(child.getAttribute("min")) / 2;
                    actor.xMax = parseInt(child.getAttribute("max")) / 2;
                    actor.disabled = child.getAttribute("mode") != "enabled";
                    actor.style.cursor = actor.disabled ? '' : 'pointer';
                    actor.onmousedown = Qva.Move.mouseDown;
                }

                break;
            case 'check':
                if (indent) cell.style.paddingLeft = indent + 'pt';
                cell.innerHTML = "<input type='checkbox'/> <span></span>"
                cell.lastChild.innerText = label;
                cell.lastChild.className = "ToolProperty-Label";
                
                var actor = cell.firstChild;
                actor.checked = child.getAttribute("value") == "1";
                actor.disabled = child.getAttribute("mode") != "enabled";
                actor.Name = cmd;
                actor.BinderId = this.BinderId;
                actor.onclick = function () {
                    var binder = Qva.GetBinder(this.BinderId);
                    if (!binder.Enabled) return;
                    binder.Set (this.Name, "value", this.checked ? "1" : "0", true)
                }
                break;
            case 'icon':
                cell.innerHTML = "<img />";
                cell.className = "ToolProperty-IconCell";
                var img = cell.firstChild;
                img.className = "ToolProperty-Icon";
                img.disabled = child.getAttribute("mode") != "enabled";
                if (child.getAttribute("menu") == "true") img.position = cmd;
                var imgstamp = null;
                var imgname = child.getAttribute("image");
                if (child.getAttribute("type") == "radio") {
                    imgstamp = child.getAttribute("stamp");
                    imgname += "." + child.getAttribute("value");
                }
                img.src = Qva.GetBinder(this.BinderId).BuildBinaryUrl(child.getAttribute("path"), imgstamp, imgname + (img.disabled ? ".DISABLED" : ""));
                img.title = label;
                cell.BinderId = this.BinderId;
                cell.Name = cmd;
                img.dragAccept = child.getAttribute("accept");
                if (img.dragAccept) {
                    this.DropTargets[this.DropTargets.length] = img;
                }
                var clickable = true;
                var highlight = true;
                switch(child.getAttribute("type")) {
                case "drag":
                    img.dragObj = { 'Name': cmd, 'Type': child.getAttribute("content"), 'Value': child.getAttribute("value") };
                    if (child.getAttribute("dropat") != null) img.dragObj.DropAt = true;
                    img.BinderId = this.BinderId;
                    img.Name = cmd;
                    img.onmousedown = Qva.DragDrop.mouseDown;
//                  clickable = img.dragAccept != null;
                    break;
                case "drop":
                    img.BinderId = this.BinderId;
                    img.Name = cmd;
                    break;
                case "action":
                    cell.Value = child.getAttribute("value");
                    break;
                case "radio":
                    highlight = false;
                    cell.Value = child.getAttribute("value");
                    if (child.getAttribute("selected") == "true") {
                        cell.className = "ToolProperty-IconSelected";
                    } else {
                        cell.className = "ToolProperty-IconUnselected";
                    }
                    break;
                case null:
                    clickable = false;
                    break;
                default:
                    clickable = false;
                    //alert('x:' + child.getAttribute("type"));
                    break;
                }
                if (clickable) {
                    if (!img.disabled) {
                        if (highlight) {
                            img.onmouseover = function () { this.className = "HighlightImage"; }
                            img.onmouseout = function () { this.className = ""; }
                        }
                        cell.onclick = function() {
                            var binder = Qva.GetBinder(this.BinderId);
                            if (!binder.Enabled) return;
                            if (this.Value != null) {
                                binder.Set (this.Name, "value", this.Value, true);
                            } else {
                                binder.Set (this.Name, "action", "", true);
                            }
                        }
                    }
                }
                break;
            case 'select':
            case 'combo':
                if (label) {
                    cell.innerHTML = "<span></span> <select ></select>"
                    cell.firstChild.innerText = label;
                    cell.firstChild.className = "ToolProperty-Label";
                } else {
                    cell.innerHTML = "<select style='width:100%'></select>"
                }
                var actor = cell.lastChild;
                actor.disabled = child.getAttribute("mode") != "enabled";
                actor.Name = cmd;
                actor.BinderId = this.BinderId;
                actor.onchange = function () {
                    if (this.selectedIndex < 0) return;
                    var binder = Qva.GetBinder(this.BinderId);
                    if (!binder.Enabled) return;
                    var opt = this.options [this.selectedIndex];
                    binder.Set (this.Name, 'value', opt.value, true);
                }
                var choices = child.getElementsByTagName ("option");
                var cholen = choices.length;
                actor.options.length = cholen;
                var currentValue = child.getAttribute("value");
                var found = false;
                for (var ix = 0; ix < cholen; ++ix) {
                    var cho = choices [ix];
                    var opt = actor.options [ix];
                    opt.text = cho.getAttribute("text");
                    opt.value = cho.getAttribute('value');
                    if (opt.value == currentValue) {
                        opt.selected = true;
                        found = true;
                    }
                }
                if (!found) {
                    actor.options.length = cholen + 1;
                    var cho = choices [cholen];
                    var opt = actor.options [cholen];
                    opt.text = "";
                    opt.value = currentValue;
                    opt.selected = true;                    
                }
                if (child.nodeName == "combo") {
                    var selectactor = actor;
                    setTimeout (function () {Qva.Mgr.toolwindowtable.CreateCombobox (selectactor)}, 0);	
                }

                break;
            case 'color':
                cell.disabled = child.getAttribute("mode") != "enabled";
                cell.Name = cmd;
                cell.BinderId = this.BinderId;
                cell.onclick = function () {
                    var binder = Qva.GetBinder(this.BinderId);
                    if (!binder.Enabled) return;
                    binder.Set (this.Name, "value", this.Color, true);
                }
                if (label)
                    cell.title = label;
                var selected = child.getAttribute("selected") == "1";
                cell.innerHTML = "<div>&nbsp</div>"
                cell.Color = child.getAttribute("value");
                cell.firstChild.className = "ToolProperty-Color";
                cell.firstChild.style.backgroundColor = "#" + child.getAttribute("value"); 
                cell.style.backgroundColor = selected ? "Highlight": "Transparent";

                break;
            }
            var warning = child.getAttribute("warning");
            if (warning) {
                var img = document.createElement("IMG");
//                img.src = "htc/Images/Properties/warning.png";
                img.src = Qva.GetBinder(this.BinderId).BuildBinaryUrl(child.getAttribute("path"), null, "warning");
                img.title = warning;
                img.style.paddingLeft = "2pt";
                cell.appendChild(img);
                cell.title = warning;
            }
        }
        while(cix < row.cells.length) row.deleteCell(cix);
        
        // Add drag & drop attributes for row
        var acceptDrop = line.getAttribute("accept");
        var canDrag = (line.getAttribute("type")== "drag") && line.getAttribute("content");
        if (canDrag || acceptDrop) {
            var rowName = line.getAttribute("name");
            if (rowName) rowName = this.BaseName + '.' + rowName;
            row.BinderId = this.BinderId;
            row.Name = rowName;
            if (acceptDrop) {
                var dropTypes = line.getAttribute("at").split(';');
                var dropOn = false;
                var dropBefore = false;
                var dropAfter = false;
                for (var aix = 0; aix < dropTypes.length; aix++) {
                    if (dropTypes[aix] == 'on') dropOn = true;
                    if (dropTypes[aix] == 'before') dropBefore = true;
                    if (dropTypes[aix] == 'after') dropAfter = true;
                }
                row.dropObj = { 'Name': rowName, 'Type': acceptDrop, 'DropOn': dropOn, 'InsertAfter': dropAfter, 'InsertBefore': dropBefore };
                this.DropTargets[this.DropTargets.length] = row;
            }
            if (canDrag) {
                var dragContent = line.getAttribute("content");
                if (line.getAttribute("label")) row.title = line.getAttribute("label");
                row.dragObj = { 'Name': rowName, 'Type': dragContent };
                row.onmouseover = function () { 
                    if(this.className.indexOf("DragTarget")==-1)
                        this.className += " DragTarget"; 
                }               
                row.onmouseout = function () { 
                    //should be " DragTarget" below but initial space doesn't exist in Firefox
                    this.className = this.className.replace("DragTarget","");
                    // trim
                    this.className = this.className.replace(/^\s+|\s+$/g,"")
                }
                row.onmousedown = Qva.DragDrop.mouseDown;
                    
            }
        }

    }
    while(rix < table.rows.length) table.deleteRow(rix);

}

Qva.Mgr.toolwindowbody = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
    this.Managers = {};
    Qva.DragDrop.DropTargets[Qva.DragDrop.DropTargets.length] = this;
}

Qva.Mgr.toolwindowbody.prototype.Scan = function() {
    this.IsCustom = true;
    var scanner = new Qva.Scanner(this);
    scanner.Scan(this.Element, this.Name, this);
}

Qva.Mgr.toolwindowbody.prototype.Inside = function (pos, type) {
    for (var key in this.Managers) {
        var list = this.Managers[key];
        for (var ix = 0; ix < list.length; ++ix) {
            var mgr = list[ix];
            if (!mgr.Inside) continue;
            var fnd = mgr.Inside(pos, type);
            if (fnd != null) return fnd; 
        }
    }
    return null;
}

Qva.Mgr.toolwindowbody.prototype.Paint = function(mode, node, prefix) {
    this.Touched = true;
    if (this.IsCustom) {
        for (var child = node.firstChild; child != null; child = child.nextSibling) {
            var name = child.getAttribute("name");
            var mode = child.getAttribute("mode");
            switch (mode) {
                case "hidden": mode = 'h'; break;
                case "enabled": mode = 'e'; break;
                default: mode = 'd'; break;
            }
            var list = this.Managers[prefix + '.' + name];
            if (list) {
                for (var ix = 0; ix < list.length; ++ix) {
                    var mgr = list[ix];
                    mgr.Paint(mode, child, name);
                }
            }
        }
    }
    var selected = node.getAttribute("value");
    if (selected != this.Selected) {
        this.Managers = {};
        this.Element.innerHTML = "<table width='95%'></table>";
        var table = this.Element.firstChild;
        table.cellpadding = 0;
        table.cellspacing = 0;
        for (var child = node.firstChild; child != null; child = child.nextSibling) {
            if (child.nodeName != 'property') continue;
            var row = table.insertRow(-1);
            var cell = row.insertCell(-1);
            var name = child.getAttribute("name");
            var indent = child.getAttribute('indent');
            if (indent) indent = 12 * parseInt(indent);
            cell.innerHTML = "<table width='98%'><colgroup></colgroup></table>";
            cell.colSpan = 2;
            var mgr = new Qva.Mgr.toolwindowtable(this, cell.firstChild, '.' + name, this.Name);
        }
        this.Body = table.tBodies[0];
        this.Selected = selected;
    }
    for (var child = node.firstChild; child != null; child = child.nextSibling) {
        if (child.nodeName != 'property') continue;
        var name = this.Name + '.' + child.getAttribute('name');
        var list = this.Managers[name];
        if (list != null) {
            var mode = 'd';
            switch (child.getAttribute('mode')) {
                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(child.getAttribute('value'), child.getAttribute('text'))) mgrmode = 'n';
                mgr.Paint(mgrmode, child, name);
            }
        }
    }
    // adjust height to fit frame
    //    var frame = this.Element.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;
    //    this.Element.style.height = parseInt(frame.style.height) - 47 + 'pt';
    //  
}

Qva.Mgr.toolwindowbody.prototype.Append = function () {}

Qva.Mgr.toolwindowbody.prototype.AddManager = function (mgr) {
    mgr.PageBinder = this;
    mgr.Touched = false;
    mgr.Dirty = false;
    var list = this.Managers[mgr.Name];
    if (list == null) {
        list = [];
        this.Managers[mgr.Name] = list;
    }
    list.push(mgr);
}
Qva.Mgr.toolwindownavigation = function (owner, elem, name, prefix) {
    if (!Qva.MgrSplit (this, name, prefix)) return;
    owner.AddManager(this);
    this.Element = elem;
    this.Managers = {};
}

Qva.Mgr.toolwindownavigation.prototype.Paint = function(mode, node) {
    this.Touched = true;
    var div = this.Element;
    if (mode == 'h') {
        div.style.display = 'none';
        return;
    }
    div.style.display = '';
    while (div.firstChild) div.removeChild(div.firstChild);
    div.innerHTML = "";
    var choices = node.getElementsByTagName("option");
    var cholen = choices.length;
    for (var ix = 0; ix < cholen; ++ix) {
        if (ix > 0) {
            var sep = document.createElement("span");
            sep.innerText = " > ";
            div.appendChild(sep);
        }
        var cho = choices[ix];
        var opt = document.createElement("span");
        if (ix < cholen - 1) {
            opt.className = "Navigation-Link";
            opt.BinderId = this.BinderId;
            opt.Name = this.Name;
            opt.Link = cho.getAttribute("value");
            opt.onclick = function() {
                var binder = Qva.GetBinder(this.BinderId);
                if (!binder.Enabled) return;
                binder.Set(this.Name, "value", this.Link, true);
            }
        }
        opt.innerText = cho.getAttribute("text");
        div.appendChild(opt);
    }
}
Qva.Mgr.toolwindowtable.CreateCombobox = function(selectactor) {
    var actor2 = document.createElement ("input");
    actor2.style.border = "none";
    actor2.style.marginTop = "2px";
    actor2.style.marginLeft = "4px";
    actor2.style.position = "absolute";
    actor2.style.height = Math.max(parseInt(selectactor.offsetHeight) - 6, 0) + "px";
    actor2.style.left = parseInt(selectactor.parentNode.offsetLeft) + "px";
    actor2.style.width = Math.max(parseInt(selectactor.offsetWidth) - 21, 0) + "px";
    if (selectactor.selectedIndex>=0) actor2.value = selectactor.options[selectactor.selectedIndex].text;
   
    selectactor.parentNode.appendChild (actor2);
    actor2.Name = selectactor.Name;
    actor2.BinderId = selectactor.BinderId;
    if (selectactor.disabled) {
        actor2.disabled = true;
    } else {
        actor2.onchange = function () {
            var binder = Qva.GetBinder(this.BinderId);
            if (!binder.Enabled) return;
            binder.Set (this.Name, "text", this.value, true);
        }
    }

}

Qva.ToggleToolPane = function(row) {
    var pane = row.nextSibling;
    if (pane.style.display == 'none') {
        row.cells[0].firstChild.src = 'collapse.png';
        pane.style.display = '';
    } else {
    row.cells[0].firstChild.src = 'expand.png';
    pane.style.display = 'none';
}
}

// 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();
        }
    }
}




/*  Copyright Mihai Bazon, 2002-2005  |  www.bazon.net/mishoo
 * -----------------------------------------------------------
 *
 * The DHTML Calendar, version 1.0 "It is happening again"
 *
 * Details and latest version at:
 * www.dynarch.com/projects/calendar
 *
 * This script is developed by Dynarch.com.  Visit us at www.dynarch.com.
 *
 * This script is distributed under the GNU Lesser General Public License.
 * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
 */

// $Id: calendar.js,v 1.51 2005/03/07 16:44:31 mishoo Exp $

/** The Calendar object constructor. */
Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) {
    // member variables
    this.activeDiv = null;
    this.currentDateEl = null;
    this.getDateStatus = null;
    this.getDateToolTip = null;
    this.getDateText = null;
    this.timeout = null;
    this.onSelected = onSelected || null;
    this.onClose = onClose || null;
    this.dragging = false;
    this.hidden = false;
    this.startDate = new Date(1970, 1-1, 1); // 1970-01-01
    this.endDate = new Date(2050, 12-1, 31); // 2050-12-31
    this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
    this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
    this.isPopup = true;
    this.weekNumbers = true;
    this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.
    this.showsOtherMonths = false;
    this.dateStr = dateStr;
    this.ar_days = null;
    this.showsTime = false;
    this.time24 = true;
    this.yearStep = 2;
    this.hiliteToday = true;
    this.multiple = null;
    // HTML elements
    this.table = null;
    this.element = null;
    this.tbody = null;
    this.firstdayname = null;
    // Combo boxes
    this.monthsCombo = null;
    this.yearsCombo = null;
    this.hilitedMonth = null;
    this.activeMonth = null;
    this.hilitedYear = null;
    this.activeYear = null;
    // Information
    this.dateClicked = false;

    // one-time initializations
    if (typeof Calendar._SDN == "undefined") {
        // table of short day names
        if (typeof Calendar._SDN_len == "undefined")
            Calendar._SDN_len = 3;
        var ar = new Array();
        for (var i = 8; i > 0;) {
            ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
        }
        Calendar._SDN = ar;
        // table of short month names
        if (typeof Calendar._SMN_len == "undefined")
            Calendar._SMN_len = 3;
        ar = new Array();
        for (var i = 12; i > 0;) {
            ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
        }
        Calendar._SMN = ar;
    }
};

// ** constants

/// "static", needed for event handlers.
Calendar._C = null;

/// detect a special case of "web browser"
Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&
           !/opera/i.test(navigator.userAgent) );

Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) );

/// detect Opera browser
Calendar.is_opera = /opera/i.test(navigator.userAgent);

/// detect KHTML-based browsers
Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);

// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate
//        library, at some point.

Calendar.getAbsolutePos = function(el) {
    var SL = 0, ST = 0;
    var is_div = /^div$/i.test(el.tagName);
    if (is_div && el.scrollLeft)
        SL = el.scrollLeft;
    if (is_div && el.scrollTop)
        ST = el.scrollTop;
    var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
    if (el.offsetParent) {
        var tmp = this.getAbsolutePos(el.offsetParent);
        r.x += tmp.x;
        r.y += tmp.y;
    }
    return r;
};

Calendar.isRelated = function (el, evt) {
    var related = evt.relatedTarget;
    if (!related) {
        var type = evt.type;
        if (type == "mouseover") {
            related = evt.fromElement;
        } else if (type == "mouseout") {
            related = evt.toElement;
        }
    }
    while (related) {
        if (related == el) {
            return true;
        }
        related = related.parentNode;
    }
    return false;
};

Calendar.removeClass = function(el, className) {
    if (!(el && el.className)) {
        return;
    }
    var cls = el.className.split(" ");
    var ar = new Array();
    for (var i = cls.length; i > 0;) {
        if (cls[--i] != className) {
            ar[ar.length] = cls[i];
        }
    }
    el.className = ar.join(" ");
};

Calendar.addClass = function(el, className) {
    Calendar.removeClass(el, className);
    el.className += " " + className;
};

// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately.
Calendar.getElement = function(ev) {
    var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
    while (f.nodeType != 1 || /^div$/i.test(f.tagName))
        f = f.parentNode;
    return f;
};

Calendar.getTargetElement = function(ev) {
    var f = Calendar.is_ie ? window.event.srcElement : ev.target;
    while (f.nodeType != 1)
        f = f.parentNode;
    return f;
};

Calendar.stopEvent = function(ev) {
    ev || (ev = window.event);
    if (Calendar.is_ie) {
        ev.cancelBubble = true;
        ev.returnValue = false;
    } else {
        ev.preventDefault();
        ev.stopPropagation();
    }
    return false;
};

Calendar.addEvent = function(el, evname, func) {
    if (el.attachEvent) { // IE
        el.attachEvent("on" + evname, func);
    } else if (el.addEventListener) { // Gecko / W3C
        el.addEventListener(evname, func, true);
    } else {
        el["on" + evname] = func;
    }
};

Calendar.removeEvent = function(el, evname, func) {
    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;
    }
};

Calendar.createElement = function(type, parent) {
    var el = null;
    if (document.createElementNS) {
        // use the XHTML namespace; IE won't normally get here unless
        // _they_ "fix" the DOM2 implementation.
        el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
    } else {
        el = document.createElement(type);
    }
    if (typeof parent != "undefined") {
        parent.appendChild(el);
    }
    return el;
};

// END: UTILITY FUNCTIONS

// BEGIN: CALENDAR STATIC FUNCTIONS

/** Internal -- adds a set of events to make some element behave like a button. */
Calendar._add_evs = function(el) {
    with (Calendar) {
        addEvent(el, "mouseover", dayMouseOver);
        addEvent(el, "mousedown", dayMouseDown);
        addEvent(el, "mouseout", dayMouseOut);
        if (is_ie) {
            addEvent(el, "dblclick", dayMouseDblClick);
            el.setAttribute("unselectable", true);
        }
    }
};

Calendar.findMonth = function(el) {
    if (typeof el.month != "undefined") {
        return el;
    } else if (typeof el.parentNode.month != "undefined") {
        return el.parentNode;
    }
    return null;
};

Calendar.findYear = function(el) {
    if (typeof el.year != "undefined") {
        return el;
    } else if (typeof el.parentNode.year != "undefined") {
        return el.parentNode;
    }
    return null;
};

Calendar.showMonthsCombo = function () {
    var cal = Calendar._C;
    if (!cal) return false;
    var cd = cal.activeDiv;
    var mc = cal.monthsCombo;
    if (cal.hilitedMonth) Calendar.removeClass(cal.hilitedMonth, "hilite");
    if (cal.activeMonth) Calendar.removeClass(cal.activeMonth, "active");
    var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
    Calendar.addClass(mon, "active");
    cal.activeMonth = mon;
    var s = mc.style;
    if (cd.navtype < 0)
        s.left = cd.offsetLeft + "px";
    else {
        var mcw = mc.offsetWidth;
        if (typeof mcw == "undefined")
            // Konqueror brain-dead techniques
            mcw = 50;
        s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
    }
    s.top = (cd.offsetTop + cd.offsetHeight) + "px";
    
    var months = cal.monthsCombo.getElementsByTagName("div");
    for(var i = 0; i < 12; ++i) {
        months[i].style.display = "block";
    }
    if(cal.date.getFullYear() == cal.startDate.getFullYear()) {
        for(var i = 0; i < cal.startDate.getMonth(); ++i) {
            months[i].style.display = "none";
        }
    }
    if(cal.date.getFullYear() == cal.endDate.getFullYear()) {
        for(var i = cal.endDate.getMonth() + 1; i < 12; ++i) {
            months[i].style.display = "none";
        }
    }
    
    s.display = "block";
};

Calendar.showYearsCombo = function (fwd) {
    var cal = Calendar._C;
    if (!cal) return false;
    var cd = cal.activeDiv;
    var yc = cal.yearsCombo;
    if (cal.hilitedYear) {
        Calendar.removeClass(cal.hilitedYear, "hilite");
    }
    if (cal.activeYear) {
        Calendar.removeClass(cal.activeYear, "active");
    }
    cal.activeYear = null;
    var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
    var yr = yc.firstChild;
    var show = false;
    for (var i = 12; i > 0; --i) {
        if (Y >= cal.startDate.getFullYear() && Y <= cal.endDate.getFullYear()) {
            yr.innerHTML = Y;
            yr.year = Y;
            yr.style.display = "block";
            show = true;
        } else {
            yr.style.display = "none";
        }
        yr = yr.nextSibling;
        Y += fwd ? cal.yearStep : -cal.yearStep;
    }
    if (show) {
        var s = yc.style;
        s.display = "block";
        if (cd.navtype < 0)
            s.left = cd.offsetLeft + "px";
        else {
            var ycw = yc.offsetWidth;
            if (typeof ycw == "undefined")
                // Konqueror brain-dead techniques
                ycw = 50;
            s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
        }
        s.top = (cd.offsetTop + cd.offsetHeight) + "px";
    }
};

// event handlers

Calendar.tableMouseUp = function(ev) {
    var cal = Calendar._C;
    if (!cal) {
        return false;
    }
    if (cal.timeout) {
        clearTimeout(cal.timeout);
    }
    var el = cal.activeDiv;
    if (!el) {
        return false;
    }
    var target = Calendar.getTargetElement(ev);
    ev || (ev = window.event);
    Calendar.removeClass(el, "active");
    if (target == el || target.parentNode == el) {
        Calendar.cellClick(el, ev);
    }
    var mon = Calendar.findMonth(target);
    var date = null;
    if (mon) {
        date = new Date(cal.date);
        if (mon.month != date.getMonth()) {
            date.setMonth(mon.month);
            cal.setDate(date);
            cal.dateClicked = false;
            cal.callHandler(ev);
        }
    } else {
        var year = Calendar.findYear(target);
        if (year) {
            date = new Date(cal.date);
            if (year.year != date.getFullYear()) {
                date.setFullYear(year.year);
                cal.setDate(date);
                cal.dateClicked = false;
                cal.callHandler(ev);
            }
        }
    }
    with (Calendar) {
        removeEvent(document, "mouseup", tableMouseUp);
        removeEvent(document, "mouseover", tableMouseOver);
        removeEvent(document, "mousemove", tableMouseOver);
        cal._hideCombos();
        _C = null;
        return stopEvent(ev);
    }
};

Calendar.tableMouseOver = function (ev) {
    var cal = Calendar._C;
    if (!cal) {
        return;
    }
    var el = cal.activeDiv;
    var target = Calendar.getTargetElement(ev);
    if (target == el || target.parentNode == el) {
        Calendar.addClass(el, "hilite active");
        Calendar.addClass(el.parentNode, "rowhilite");
    } else {
        if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))
            Calendar.removeClass(el, "active");
        Calendar.removeClass(el, "hilite");
        Calendar.removeClass(el.parentNode, "rowhilite");
    }
    ev || (ev = window.event);
    if (el.navtype == 50 && target != el) {
        var pos = Calendar.getAbsolutePos(el);
        var w = el.offsetWidth;
        var x = ev.clientX;
        var dx;
        var decrease = true;
        if (x > pos.x + w) {
            dx = x - pos.x - w;
            decrease = false;
        } else
            dx = pos.x - x;

        if (dx < 0) dx = 0;
        var range = el._range;
        var current = el._current;
        var count = Math.floor(dx / 10) % range.length;
        for (var i = range.length; --i >= 0;)
            if (range[i] == current)
                break;
        while (count-- > 0)
            if (decrease) {
                if (--i < 0)
                    i = range.length - 1;
            } else if ( ++i >= range.length )
                i = 0;
        var newval = range[i];
        el.innerHTML = newval;

        cal.onUpdateTime(ev);
    }
    var mon = Calendar.findMonth(target);
    if (mon) {
        if (mon.month != cal.date.getMonth()) {
            if (cal.hilitedMonth) {
                Calendar.removeClass(cal.hilitedMonth, "hilite");
            }
            Calendar.addClass(mon, "hilite");
            cal.hilitedMonth = mon;
        } else if (cal.hilitedMonth) {
            Calendar.removeClass(cal.hilitedMonth, "hilite");
        }
    } else {
        if (cal.hilitedMonth) {
            Calendar.removeClass(cal.hilitedMonth, "hilite");
        }
        var year = Calendar.findYear(target);
        if (year) {
            if (year.year != cal.date.getFullYear()) {
                if (cal.hilitedYear) {
                    Calendar.removeClass(cal.hilitedYear, "hilite");
                }
                Calendar.addClass(year, "hilite");
                cal.hilitedYear = year;
            } else if (cal.hilitedYear) {
                Calendar.removeClass(cal.hilitedYear, "hilite");
            }
        } else if (cal.hilitedYear) {
            Calendar.removeClass(cal.hilitedYear, "hilite");
        }
    }
    return Calendar.stopEvent(ev);
};

Calendar.tableMouseDown = function (ev) {
    if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
        return Calendar.stopEvent(ev);
    }
};

Calendar.calDragIt = function (ev) {
    var cal = Calendar._C;
    if (!(cal && cal.dragging)) {
        return false;
    }
    var posX;
    var posY;
    if (Calendar.is_ie) {
        posY = window.event.clientY + document.body.scrollTop;
        posX = window.event.clientX + document.body.scrollLeft;
    } else {
        posX = ev.pageX;
        posY = ev.pageY;
    }
    cal.hideShowCovered();
    var st = cal.element.style;
    st.left = (posX - cal.xOffs) + "px";
    st.top = (posY - cal.yOffs) + "px";
    return Calendar.stopEvent(ev);
};

Calendar.calDragEnd = function (ev) {
    var cal = Calendar._C;
    if (!cal) {
        return false;
    }
    cal.dragging = false;
    with (Calendar) {
        removeEvent(document, "mousemove", calDragIt);
        removeEvent(document, "mouseup", calDragEnd);
        tableMouseUp(ev);
    }
    cal.hideShowCovered();
};

Calendar.dayMouseDown = function(ev) {
    var el = Calendar.getElement(ev);
    if (el.disabled) return false;
    var cal = el.calendar;
    cal.activeDiv = el;
    Calendar._C = cal;
    if (el.navtype != 300) with (Calendar) {
        if (el.navtype == 50) {
            el._current = el.innerHTML;
            addEvent(document, "mousemove", tableMouseOver);
        } else
            addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver);
        addClass(el, "hilite active");
        addEvent(document, "mouseup", tableMouseUp);
    } else if (cal.isPopup) {
        cal._dragStart(ev);
    }
    if (el.navtype == -1 || el.navtype == 1) {
        if (cal.timeout) clearTimeout(cal.timeout);
        cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
    } else if (el.navtype == -2 || el.navtype == 2) {
        if (cal.timeout) clearTimeout(cal.timeout);
        cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
    } else {
        cal.timeout = null;
    }
    return Calendar.stopEvent(ev);
};

Calendar.dayMouseDblClick = function(ev) {
    Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
    if (Calendar.is_ie) {
        document.selection.empty();
    }
};

Calendar.dayMouseOver = function(ev) {
    var el = Calendar.getElement(ev);
    if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) return false;
    if (el.ttip) {
        if (el.ttip.substr(0, 1) == "_") {
            el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
        }
        el.calendar.tooltips.innerHTML = el.ttip;
    }
    if (el.navtype != 300) {
        Calendar.addClass(el, "hilite");
        if (el.caldate) {
            Calendar.addClass(el.parentNode, "rowhilite");
        }
    }
    return Calendar.stopEvent(ev);
};

Calendar.dayMouseOut = function(ev) {
    with (Calendar) {
        var el = getElement(ev);
        if (isRelated(el, ev) || _C || el.disabled)
            return false;
        removeClass(el, "hilite");
        if (el.caldate)
            removeClass(el.parentNode, "rowhilite");
        if (el.calendar)
            el.calendar.tooltips.innerHTML = _TT["SEL_DATE"];
        return stopEvent(ev);
    }
};

/**
 *  A generic "click" handler :) handles all types of buttons defined in this
 *  calendar.
 */
Calendar.cellClick = function(el, ev) {
    var cal = el.calendar;
    var closing = false;
    var newdate = false;
    var date = null;
    if (typeof el.navtype == "undefined") {
        if (cal.currentDateEl) {
            Calendar.removeClass(cal.currentDateEl, "current");
            Calendar.addClass(el, "current");
            closing = (cal.currentDateEl == el);
            if (!closing) {
                cal.currentDateEl = el;
            }
        }
        cal.date.setDateOnly(el.caldate);
        date = cal.date;
        var other_month = !(cal.dateClicked = !el.otherMonth);
        if (!other_month && !cal.currentDateEl)
            cal._toggleMultipleDate(new Date(date));
        else
            newdate = !el.disabled;
        // a date was clicked
        if (other_month)
            cal._init(cal.firstDayOfWeek, date);
    } else {
        if (el.navtype == 200) {
            Calendar.removeClass(el, "hilite");
            cal.callCloseHandler();
            return;
        }
        date = new Date(cal.date);
        if (el.navtype == 0)
            date.setDateOnly(new Date()); // TODAY
        // unless "today" was clicked, we assume no date was clicked so
        // the selected handler will know not to close the calenar when
        // in single-click mode.
        // cal.dateClicked = (el.navtype == 0);
        cal.dateClicked = false;
        var year = date.getFullYear();
        var mon = date.getMonth();
        function setMonth(m) {
            var day = date.getDate();
            var max = date.getMonthDays(m);
            if (day > max) {
                date.setDate(max);
            }
            date.setMonth(m);
        };
        switch (el.navtype) {
            case 400:
            Calendar.removeClass(el, "hilite");
            var text = Calendar._TT["ABOUT"];
            if (typeof text != "undefined") {
                text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
            } else {
                // FIXME: this should be removed as soon as lang files get updated!
                text = "Help and about box text is not translated into this language.\n" +
                    "If you know this language and you feel generous please update\n" +
                    "the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
                    "and send it back to <mihai_bazon@yahoo.com> to get it into the distribution  ;-)\n\n" +
                    "Thank you!\n" +
                    "http://dynarch.com/mishoo/calendar.epl\n";
            }
            alert(text);
            return;
            case -2:
            if (year > cal.startDate.getFullYear()) {
                date.setFullYear(year - 1);
            }
            break;
            case -1:
            if(year == cal.startDate.getFullYear() && mon <= cal.startDate.getMonth()) break;
            if (mon > 0) {
                setMonth(mon - 1);
            } else {
                date.setFullYear(year - 1);
                setMonth(11);
            }
            break;
            case 1:
            if(year == cal.endDate.getFullYear() && mon >= cal.endDate.getMonth()) break;
            if (mon < 11) {
                setMonth(mon + 1);
            } else {
                date.setFullYear(year + 1);
                setMonth(0);
            }
            break;
            case 2:
            if (year < cal.endDate.getFullYear()) {
                date.setFullYear(year + 1);
            }
            break;
            case 100:
            cal.setFirstDayOfWeek(el.fdow);
            return;
            case 50:
            var range = el._range;
            var current = el.innerHTML;
            for (var i = range.length; --i >= 0;)
                if (range[i] == current)
                    break;
            if (ev && ev.shiftKey) {
                if (--i < 0)
                    i = range.length - 1;
            } else if ( ++i >= range.length )
                i = 0;
            var newval = range[i];
            el.innerHTML = newval;
            cal.onUpdateTime(ev);
            return;
            case 0:
            // TODAY will bring us here
            if(typeof cal.getDateStatus == "function") {
                var status = cal.getDateStatus(this, date);
                if(status === true || /disabled/i.test(status)) return false;
            }
            break;
        }
        if (!date.equalsTo(cal.date)) {
            cal.setDate(date);
            newdate = true;
        } else if (el.navtype == 0)
            newdate = closing = true;
    }
    if (newdate) {
        ev && cal.callHandler(ev);
    }
    if (closing) {
        Calendar.removeClass(el, "hilite");
        ev && cal.callCloseHandler();
    }
};

// END: CALENDAR STATIC FUNCTIONS

// BEGIN: CALENDAR OBJECT FUNCTIONS

/**
 *  This function creates the calendar inside the given parent.  If _par is
 *  null than it creates a popup calendar inside the BODY element.  If _par is
 *  an element, be it BODY, then it creates a non-popup calendar (still
 *  hidden).  Some properties need to be set before calling this function.
 */
Calendar.prototype.create = function (_par) {
    var parent = null;
    if (! _par) {
        // default parent is the document body, in which case we create
        // a popup calendar.
        parent = document.getElementsByTagName("body")[0];
        this.isPopup = true;
    } else {
        parent = _par;
        this.isPopup = false;
    }
    this.date = this.dateStr ? new Date(this.dateStr) : new Date();

    var table = Calendar.createElement("table");
    this.table = table;
    table.cellSpacing = 0;
    table.cellPadding = 0;
    table.calendar = this;
    Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);

    var div = Calendar.createElement("div");
    div.style.zIndex = 666;
    this.element = div;
    div.className = "calendar";
    if (this.isPopup) {
        div.style.position = "absolute";
        div.style.display = "none";
    }
    div.appendChild(table);

    var thead = Calendar.createElement("thead", table);
    var cell = null;
    var row = null;

    var cal = this;
    var hh = function (text, cs, navtype) {
        cell = Calendar.createElement("td", row);
        cell.colSpan = cs;
        cell.className = "button";
        if (navtype != 0 && Math.abs(navtype) <= 2)
            cell.className += " nav";
        Calendar._add_evs(cell);
        cell.calendar = cal;
        cell.navtype = navtype;
        cell.innerHTML = "<div unselectable='on'>" + text + "</div>";
        return cell;
    };

    row = Calendar.createElement("tr", thead);
    var title_length = 6;
    (this.isPopup) && --title_length;
    (this.weekNumbers) && ++title_length;

    hh("?", 1, 400).ttip = Calendar._TT["INFO"];
    this.title = hh("", title_length, 300);
    this.title.className = "title";
    if (this.isPopup) {
        this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
        this.title.style.cursor = "move";
        hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
    }

    row = Calendar.createElement("tr", thead);
    row.className = "headrow";

    this._nav_py = hh("&#x00ab;", 1, -2);
    this._nav_py.ttip = Calendar._TT["PREV_YEAR"];

    this._nav_pm = hh("&#x2039;", 1, -1);
    this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];

    this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
    this._nav_now.ttip = Calendar._TT["GO_TODAY"];

    this._nav_nm = hh("&#x203a;", 1, 1);
    this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];

    this._nav_ny = hh("&#x00bb;", 1, 2);
    this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];

    // day names
    row = Calendar.createElement("tr", thead);
    row.className = "daynames";
    if (this.weekNumbers) {
        cell = Calendar.createElement("td", row);
        cell.className = "name wn";
        cell.innerHTML = Calendar._TT["WK"];
    }
    for (var i = 7; i > 0; --i) {
        cell = Calendar.createElement("td", row);
        if (!i) {
            cell.navtype = 100;
            cell.calendar = this;
            Calendar._add_evs(cell);
        }
    }
    this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
    this._displayWeekdays();

    var tbody = Calendar.createElement("tbody", table);
    this.tbody = tbody;

    for (i = 6; i > 0; --i) {
        row = Calendar.createElement("tr", tbody);
        if (this.weekNumbers) {
            cell = Calendar.createElement("td", row);
        }
        for (var j = 7; j > 0; --j) {
            cell = Calendar.createElement("td", row);
            cell.calendar = this;
            Calendar._add_evs(cell);
        }
    }

    if (this.showsTime) {
        row = Calendar.createElement("tr", tbody);
        row.className = "time";

        cell = Calendar.createElement("td", row);
        cell.className = "time";
        cell.colSpan = 2;
        cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";

        cell = Calendar.createElement("td", row);
        cell.className = "time";
        cell.colSpan = this.weekNumbers ? 4 : 3;

        (function(){
            function makeTimePart(className, init, range_start, range_end) {
                var part = Calendar.createElement("span", cell);
                part.className = className;
                part.innerHTML = init;
                part.calendar = cal;
                part.ttip = Calendar._TT["TIME_PART"];
                part.navtype = 50;
                part._range = [];
                if (typeof range_start != "number")
                    part._range = range_start;
                else {
                    for (var i = range_start; i <= range_end; ++i) {
                        var txt;
                        if (i < 10 && range_end >= 10) txt = '0' + i;
                        else txt = '' + i;
                        part._range[part._range.length] = txt;
                    }
                }
                Calendar._add_evs(part);
                return part;
            };
            var hrs = cal.date.getHours();
            var mins = cal.date.getMinutes();
            var t12 = !cal.time24;
            var pm = (hrs > 12);
            if (t12 && pm) hrs -= 12;
            var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
            var span = Calendar.createElement("span", cell);
            span.innerHTML = ":";
            span.className = "colon";
            var M = makeTimePart("minute", mins, 0, 59);
            var AP = null;
            cell = Calendar.createElement("td", row);
            cell.className = "time";
            cell.colSpan = 2;
            if (t12)
                AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
            else
                cell.innerHTML = "&nbsp;";

            cal.onSetTime = function() {
                var pm, hrs = this.date.getHours(),
                    mins = this.date.getMinutes();
                if (t12) {
                    pm = (hrs >= 12);
                    if (pm) hrs -= 12;
                    if (hrs == 0) hrs = 12;
                    AP.innerHTML = pm ? "pm" : "am";
                }
                H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
                M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
            };

            cal.onUpdateTime = function(event) {
                var date = this.date;
                var h = parseInt(H.innerHTML, 10);
                if (t12) {
                    if (/pm/i.test(AP.innerHTML) && h < 12)
                        h += 12;
                    else if (/am/i.test(AP.innerHTML) && h == 12)
                        h = 0;
                }
                var d = date.getDate();
                var m = date.getMonth();
                var y = date.getFullYear();
                date.setHours(h);
                date.setMinutes(parseInt(M.innerHTML, 10));
                date.setFullYear(y);
                date.setMonth(m);
                date.setDate(d);
                this.dateClicked = false;
                this.callHandler(event);
            };
        })();
    } else {
        this.onSetTime = this.onUpdateTime = function() {};
    }

    var tfoot = Calendar.createElement("tfoot", table);

    row = Calendar.createElement("tr", tfoot);
    row.className = "footrow";

    cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
    cell.className = "ttip";
    if (this.isPopup) {
        cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
        cell.style.cursor = "move";
    }
    this.tooltips = cell;

    div = Calendar.createElement("div", this.element);
    this.monthsCombo = div;
    div.className = "combo";
    for (i = 0; i < Calendar._MN.length; ++i) {
        var mn = Calendar.createElement("div");
        mn.className = Calendar.is_ie ? "label-IEfix" : "label";
        mn.month = i;
        mn.innerHTML = Calendar._SMN[i];
        div.appendChild(mn);
    }

    div = Calendar.createElement("div", this.element);
    this.yearsCombo = div;
    div.className = "combo";
    for (i = 12; i > 0; --i) {
        var yr = Calendar.createElement("div");
        yr.className = Calendar.is_ie ? "label-IEfix" : "label";
        div.appendChild(yr);
    }

    this._init(this.firstDayOfWeek, this.date);
    parent.appendChild(this.element);
};

/** keyboard navigation, only for popup calendars */
Calendar._keyEvent = function(ev) {
    var cal = window._dynarch_popupCalendar;
    if (!cal || cal.multiple)
        return false;
    (Calendar.is_ie) && (ev = window.event);
    var act = (Calendar.is_ie || ev.type == "keypress"),
        K = ev.keyCode;
    if (ev.ctrlKey) {
        switch (K) {
            case 37: // KEY left
            act && Calendar.cellClick(cal._nav_pm);
            break;
            case 38: // KEY up
            act && Calendar.cellClick(cal._nav_py);
            break;
            case 39: // KEY right
            act && Calendar.cellClick(cal._nav_nm);
            break;
            case 40: // KEY down
            act && Calendar.cellClick(cal._nav_ny);
            break;
            default:
            return false;
        }
    } else switch (K) {
        case 32: // KEY space (now)
        Calendar.cellClick(cal._nav_now);
        break;
        case 27: // KEY esc
        act && cal.callCloseHandler();
        break;
        case 37: // KEY left
        case 38: // KEY up
        case 39: // KEY right
        case 40: // KEY down
        if (act) {
            var prev, x, y, ne, el, step;
            prev = K == 37 || K == 38;
            step = (K == 37 || K == 39) ? 1 : 7;
            function setVars() {
                el = cal.currentDateEl;
                var p = el.pos;
                x = p & 15;
                y = p >> 4;
                ne = cal.ar_days[y][x];
            };setVars();
            function prevMonth() {
                var date = new Date(cal.date);
                date.setDate(date.getDate() - step);
                cal.setDate(date);
            };
            function nextMonth() {
                var date = new Date(cal.date);
                date.setDate(date.getDate() + step);
                cal.setDate(date);
            };
            while (1) {
                switch (K) {
                    case 37: // KEY left
                    if (--x >= 0)
                        ne = cal.ar_days[y][x];
                    else {
                        x = 6;
                        K = 38;
                        continue;
                    }
                    break;
                    case 38: // KEY up
                    if (--y >= 0)
                        ne = cal.ar_days[y][x];
                    else {
                        prevMonth();
                        setVars();
                    }
                    break;
                    case 39: // KEY right
                    if (++x < 7)
                        ne = cal.ar_days[y][x];
                    else {
                        x = 0;
                        K = 40;
                        continue;
                    }
                    break;
                    case 40: // KEY down
                    if (++y < cal.ar_days.length)
                        ne = cal.ar_days[y][x];
                    else {
                        nextMonth();
                        setVars();
                    }
                    break;
                }
                break;
            }
            if (ne) {
                if (!ne.disabled)
                    Calendar.cellClick(ne);
                else if (prev)
                    prevMonth();
                else
                    nextMonth();
            }
        }
        break;
        case 13: // KEY enter
        if (act)
            Calendar.cellClick(cal.currentDateEl, ev);
        break;
        default:
        return false;
    }
    return Calendar.stopEvent(ev);
};

/**
 *  (RE)Initializes the calendar to the given date and firstDayOfWeek
 */
Calendar.prototype._init = function (firstDayOfWeek, date) {
    var today = new Date();
    var TY = today.getFullYear();
    var TM = today.getMonth();
    var TD = today.getDate();
    this.table.style.visibility = "hidden";
    
    if(Calendar.CompareDate(date, this.startDate) < 0) date = new Date(this.startDate);
    if(Calendar.CompareDate(date, this.endDate) > 0) date = new Date(this.endDate);
    
    this.firstDayOfWeek = firstDayOfWeek;
    this.date = new Date(date);
    var year = date.getFullYear();
    var month = date.getMonth();
    var mday = date.getDate();
    var no_days = date.getMonthDays();

    // calendar voodoo for computing the first day that would actually be
    // displayed in the calendar, even if it's from the previous month.
    // WARNING: this is magic. ;-)
    date.setDate(1);
    var day1 = (date.getDay() - this.firstDayOfWeek) % 7;
    if (day1 < 0) day1 += 7;
    date.setDate(-day1);
    date.setDate(date.getDate() + 1);

    var row = this.tbody.firstChild;
    var MN = Calendar._SMN[month];
    var ar_days = this.ar_days = new Array();
    var weekend = Calendar._TT["WEEKEND"];
    var dates = this.multiple ? (this.datesCells = {}) : null;
    for (var i = 0; i < 6; ++i, row = row.nextSibling) {
        var cell = row.firstChild;
        if (this.weekNumbers) {
            cell.className = "day wn";
            cell.innerHTML = date.getWeekNumber();
            cell = cell.nextSibling;
        }
        row.className = "daysrow";
        var hasdays = false, iday, dpos = ar_days[i] = [];
        for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) {
            iday = date.getDate();
            var wday = date.getDay();
            cell.className = "day";
            cell.pos = i << 4 | j;
            dpos[j] = cell;
            var current_month = (date.getMonth() == month);
            if (!current_month) {
                if (this.showsOtherMonths) {
                    cell.className += " othermonth";
                    cell.otherMonth = true;
                } else {
                    cell.className = "emptycell";
                    cell.innerHTML = "&nbsp;";
                    cell.disabled = true;
                    continue;
                }
            } else {
                cell.otherMonth = false;
                hasdays = true;
            }
            cell.disabled = false;
            cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;
            if (dates)
                dates[date.print("%Y%m%d")] = cell;
            if (this.getDateStatus) {
                var status = this.getDateStatus(this, date);
                if (this.getDateToolTip) {
                    var toolTip = this.getDateToolTip(date, year, month, iday);
                    if (toolTip) cell.title = toolTip;
                }
                if (status === true) {
                    cell.className += " disabled";
                    cell.disabled = true;
                } else {
                    if (/disabled/i.test(status)) cell.disabled = true;
                    cell.className += " " + status;
                }
            }
            if (!cell.disabled) {
                cell.caldate = new Date(date);
                cell.ttip = "_";
                if (!this.multiple && current_month && iday == mday && this.hiliteToday) {
                    cell.className += " current";
                    this.currentDateEl = cell;
                }
                if (date.getFullYear() == TY && date.getMonth() == TM && iday == TD) {
                    cell.className += " today";
                    cell.ttip += Calendar._TT["PART_TODAY"];
                }
                if (weekend.indexOf(wday.toString()) != -1)
                    cell.className += cell.otherMonth ? " oweekend" : " weekend";
            }
        }
        if (!(hasdays || this.showsOtherMonths))
            row.className = "emptyrow";
    }
    this.title.innerHTML = Calendar._MN[month] + ", " + year;
    this.onSetTime();
    this.table.style.visibility = "visible";
    this._initMultipleDates();
    // PROFILE
    // this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms";
};

Calendar.prototype._initMultipleDates = function() {
    if (this.multiple) {
        for (var i in this.multiple) {
            var cell = this.datesCells[i];
            var d = this.multiple[i];
            if (!d)
                continue;
            if (cell)
                cell.className += " current";
        }
    }
};

Calendar.prototype._toggleMultipleDate = function(date) {
    if (this.multiple) {
        var ds = date.print("%Y%m%d");
        var cell = this.datesCells[ds];
        if (cell) {
            var d = this.multiple[ds];
            if (!d) {
                Calendar.addClass(cell, "current");
                this.multiple[ds] = date;
            } else {
                Calendar.removeClass(cell, "current");
                delete this.multiple[ds];
            }
        }
    }
};

Calendar.prototype.setDateToolTipHandler = function (unaryFunction) {
    this.getDateToolTip = unaryFunction;
};

/**
 *  Calls _init function above for going to a certain date (but only if the
 *  date is different than the currently selected one).
 */
Calendar.prototype.setDate = function (date) {
    if (!date.equalsTo(this.date)) {
        this._init(this.firstDayOfWeek, date);
    }
};

/**
 *  Refreshes the calendar.  Useful if the "disabledHandler" function is
 *  dynamic, meaning that the list of disabled date can change at runtime.
 *  Just * call this function if you think that the list of disabled dates
 *  should * change.
 */
Calendar.prototype.refresh = function () {
    this._init(this.firstDayOfWeek, this.date);
};

/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */
Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {
    this._init(firstDayOfWeek, this.date);
    this._displayWeekdays();
};

/**
 *  Allows customization of what dates are enabled.  The "unaryFunction"
 *  parameter must be a function object that receives the date (as a JS Date
 *  object) and returns a boolean value.  If the returned value is true then
 *  the passed date will be marked as disabled.
 */
Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {
    this.getDateStatus = unaryFunction;
};

/** Customization of allowed year range for the calendar. */
Calendar.prototype.setRange = function (a, z) {
    this.startDate = a;
    this.endDate = z;
};

/** Calls the first user handler (selectedHandler). */
Calendar.prototype.callHandler = function (event) {
    if (this.onSelected) {
        this.onSelected(this, event);
    }
};

/** Calls the second user handler (closeHandler). */
Calendar.prototype.callCloseHandler = function () {
    if (this.onClose) {
        this.onClose(this);
    }
    this.hideShowCovered();
};

/** Removes the calendar object from the DOM tree and destroys it. */
Calendar.prototype.destroy = function () {
    var el = this.element.parentNode;
    el.removeChild(this.element);
    Calendar._C = null;
    window._dynarch_popupCalendar = null;
};

/**
 *  Moves the calendar element to a different section in the DOM tree (changes
 *  its parent).
 */
Calendar.prototype.reparent = function (new_parent) {
    var el = this.element;
    el.parentNode.removeChild(el);
    new_parent.appendChild(el);
};

// This gets called when the user presses a mouse button anywhere in the
// document, if the calendar is shown.  If the click was outside the open
// calendar this function closes it.
Calendar._checkCalendar = function(ev) {
    var calendar = window._dynarch_popupCalendar;
    if (!calendar) {
        return false;
    }
    var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
    for (; el != null && el != calendar.element; el = el.parentNode);
    if (el == null) {
        // calls closeHandler which should hide the calendar.
        window._dynarch_popupCalendar.callCloseHandler();
        return Calendar.stopEvent(ev);
    }
};

/** Shows the calendar. */
Calendar.prototype.show = function () {
    var rows = this.table.getElementsByTagName("tr");
    for (var i = rows.length; i > 0;) {
        var row = rows[--i];
        Calendar.removeClass(row, "rowhilite");
        var cells = row.getElementsByTagName("td");
        for (var j = cells.length; j > 0;) {
            var cell = cells[--j];
            Calendar.removeClass(cell, "hilite");
            Calendar.removeClass(cell, "active");
        }
    }
    this.element.style.display = "block";
    this.hidden = false;
    if (this.isPopup) {
        window._dynarch_popupCalendar = this;
        Calendar.addEvent(document, "keydown", Calendar._keyEvent);
        Calendar.addEvent(document, "keypress", Calendar._keyEvent);
        Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
    }
    this.hideShowCovered();
};

/**
 *  Hides the calendar.  Also removes any "hilite" from the class of any TD
 *  element.
 */
Calendar.prototype.hide = function () {
    if (this.isPopup) {
        Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
        Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
        Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
    }
    this.element.style.display = "none";
    this.hidden = true;
    this.hideShowCovered();
};

/**
 *  Shows the calendar at a given absolute position (beware that, depending on
 *  the calendar element style -- position property -- this might be relative
 *  to the parent's containing rectangle).
 */
Calendar.prototype.showAt = function (x, y) {
    var s = this.element.style;
    s.left = x + "px";
    s.top = y + "px";
    this.show();
};

/** Shows the calendar near a given element. */
Calendar.prototype.showAtElement = function (el, opts) {
    var self = this;
    var p = Calendar.getAbsolutePos(el);
    if (!opts || typeof opts != "string") {
        this.showAt(p.x, p.y + el.offsetHeight);
        return true;
    }
    function fixPosition(box) {
        if (box.x < 0)
            box.x = 0;
        if (box.y < 0)
            box.y = 0;
        var cp = document.createElement("div");
        var s = cp.style;
        s.position = "absolute";
        s.right = s.bottom = s.width = s.height = "0px";
        document.body.appendChild(cp);
        var br = Calendar.getAbsolutePos(cp);
        document.body.removeChild(cp);
        if (Calendar.is_ie) {
            br.y += document.body.scrollTop;
            br.x += document.body.scrollLeft;
        } else {
            br.y += window.scrollY;
            br.x += window.scrollX;
        }
        var tmp = box.x + box.width - br.x;
        if (tmp > 0) box.x -= tmp;
        tmp = box.y + box.height - br.y;
        if (tmp > 0) box.y -= tmp;
    };
    this.element.style.display = "block";
    Calendar.continuation_for_the_fucking_khtml_browser = function() {
        var w = self.element.offsetWidth;
        var h = self.element.offsetHeight;
        self.element.style.display = "none";
        var valign = opts.substr(0, 1);
        var halign = "l";
        if (opts.length > 1) {
            halign = opts.substr(1, 1);
        }
        // vertical alignment
        switch (valign) {
            case "T": p.y -= h; break;
            case "B": p.y += el.offsetHeight; break;
            case "C": p.y += (el.offsetHeight - h) / 2; break;
            case "t": p.y += el.offsetHeight - h; break;
            case "b": break; // already there
        }
        // horizontal alignment
        switch (halign) {
            case "L": p.x -= w; break;
            case "R": p.x += el.offsetWidth; break;
            case "C": p.x += (el.offsetWidth - w) / 2; break;
            case "l": p.x += el.offsetWidth - w; break;
            case "r": break; // already there
        }
        p.width = w;
        p.height = h + 40;
        self.monthsCombo.style.display = "none";
        fixPosition(p);
        self.showAt(p.x, p.y);
    };
    if (Calendar.is_khtml) {
        //setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
        setTimeout(Calendar.continuation_for_the_fucking_khtml_browser, 10);      //??
    } else
        Calendar.continuation_for_the_fucking_khtml_browser();
};

/** Customizes the date format. */
Calendar.prototype.setDateFormat = function (str) {
    this.dateFormat = str;
};

/** Customizes the tooltip date format. */
Calendar.prototype.setTtDateFormat = function (str) {
    this.ttDateFormat = str;
};

/**
 *  Tries to identify the date represented in a string.  If successful it also
 *  calls this.setDate which moves the calendar to the given date.
 */
Calendar.prototype.parseDate = function(str, fmt) {
    if (!fmt) fmt = this.dateFormat;
    this.setDate(Date.parseDate(str, fmt));
};

Calendar.prototype.hideShowCovered = function () {
    if (!Calendar.is_ie && !Calendar.is_opera)
        return;
    function getVisib(obj){
        var value = obj.style.visibility;
        if (!value) {
            if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
                if (!Calendar.is_khtml)
                    value = document.defaultView.
                        getComputedStyle(obj, "").getPropertyValue("visibility");
                else
                    value = '';
            } else if (obj.currentStyle) { // IE
                value = obj.currentStyle.visibility;
            } else
                value = '';
        }
        return value;
    };

    var tags = ["applet", "iframe", "select"];
    var el = this.element;

    var p = Calendar.getAbsolutePos(el);
    var EX1 = p.x;
    var EX2 = el.offsetWidth + EX1;
    var EY1 = p.y;
    var EY2 = el.offsetHeight + EY1;

    for (var k = tags.length; k > 0; ) {
        var ar = document.getElementsByTagName(tags[--k]);
        var cc = null;

        for (var i = ar.length; i > 0;) {
            cc = ar[--i];

            p = Calendar.getAbsolutePos(cc);
            var CX1 = p.x;
            var CX2 = cc.offsetWidth + CX1;
            var CY1 = p.y;
            var CY2 = cc.offsetHeight + CY1;

            if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
                if (!cc.__msh_save_visibility) {
                    cc.__msh_save_visibility = getVisib(cc);
                }
                cc.style.visibility = cc.__msh_save_visibility;
            } else {
                if (!cc.__msh_save_visibility) {
                    cc.__msh_save_visibility = getVisib(cc);
                }
                cc.style.visibility = "hidden";
            }
        }
    }
};

/** Internal function; it displays the bar with the names of the weekday. */
Calendar.prototype._displayWeekdays = function () {
    var fdow = this.firstDayOfWeek;
    var cell = this.firstdayname;
    var weekend = Calendar._TT["WEEKEND"];
    for (var i = 0; i < 7; ++i) {
        cell.className = "day name";
        var realday = (i + fdow) % 7;
        if (i) {
            cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
            cell.navtype = 100;
            cell.calendar = this;
            cell.fdow = realday;
            Calendar._add_evs(cell);
        }
        if (weekend.indexOf(realday.toString()) != -1) {
            Calendar.addClass(cell, "weekend");
        }
        cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
        cell = cell.nextSibling;
    }
};

/** Internal function.  Hides all combo boxes that might be displayed. */
Calendar.prototype._hideCombos = function () {
    this.monthsCombo.style.display = "none";
    this.yearsCombo.style.display = "none";
};

/** Internal function.  Starts dragging the element. */
Calendar.prototype._dragStart = function (ev) {
    if (this.dragging) {
        return;
    }
    this.dragging = true;
    var posX;
    var posY;
    if (Calendar.is_ie) {
        posY = window.event.clientY + document.body.scrollTop;
        posX = window.event.clientX + document.body.scrollLeft;
    } else {
        posY = ev.clientY + window.scrollY;
        posX = ev.clientX + window.scrollX;
    }
    var st = this.element.style;
    this.xOffs = posX - parseInt(st.left);
    this.yOffs = posY - parseInt(st.top);
    with (Calendar) {
        addEvent(document, "mousemove", calDragIt);
        addEvent(document, "mouseup", calDragEnd);
    }
};

Calendar.CompareDate = function(d1, d2) {
    if(d1.getFullYear() < d2.getFullYear())
        return -1;
    else if(d1.getFullYear() > d2.getFullYear())
        return 1;
    else if(d1.getMonth() < d2.getMonth())
        return -1
    else if(d1.getMonth() > d2.getMonth())
        return 1;
    else if(d1.getDate() < d2.getDate())
        return -1;
    else if(d1.getDate() > d2.getDate())
        return 1;
    else
        return 0;
}

// BEGIN: DATE OBJECT PATCHES

/** Adds the number of days array to the Date object. */
Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);

/** Constants used for time computations */
Date.SECOND = 1000 /* milliseconds */;
Date.MINUTE = 60 * Date.SECOND;
Date.HOUR   = 60 * Date.MINUTE;
Date.DAY    = 24 * Date.HOUR;
Date.WEEK   =  7 * Date.DAY;

Date.parseDate = function(str, fmt) {
    var today = new Date();
    var y = 0;
    var m = -1;
    var d = 0;
    var a = str.split(/\W+/);
    var b = fmt.match(/%./g);
    var i = 0, j = 0;
    var hr = 0;
    var min = 0;
    for (i = 0; i < a.length; ++i) {
        if (!a[i])
            continue;
        switch (b[i]) {
            case "%d":
            case "%e":
            d = parseInt(a[i], 10);
            break;

            case "%m":
            m = parseInt(a[i], 10) - 1;
            break;

            case "%Y":
            case "%y":
            y = parseInt(a[i], 10);
            (y < 100) && (y += (y > 29) ? 1900 : 2000);
            break;

            case "%b":
            case "%B":
            for (j = 0; j < 12; ++j) {
                if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
            }
            break;

            case "%H":
            case "%I":
            case "%k":
            case "%l":
            hr = parseInt(a[i], 10);
            break;

            case "%P":
            case "%p":
            if (/pm/i.test(a[i]) && hr < 12)
                hr += 12;
            else if (/am/i.test(a[i]) && hr >= 12)
                hr -= 12;
            break;

            case "%M":
            min = parseInt(a[i], 10);
            break;
        }
    }
    if (isNaN(y)) y = today.getFullYear();
    if (isNaN(m)) m = today.getMonth();
    if (isNaN(d)) d = today.getDate();
    if (isNaN(hr)) hr = today.getHours();
    if (isNaN(min)) min = today.getMinutes();
    if (y != 0 && m != -1 && d != 0)
        return new Date(y, m, d, hr, min, 0);
    y = 0; m = -1; d = 0;
    for (i = 0; i < a.length; ++i) {
        if (a[i].search(/[a-zA-Z]+/) != -1) {
            var t = -1;
            for (j = 0; j < 12; ++j) {
                if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
            }
            if (t != -1) {
                if (m != -1) {
                    d = m+1;
                }
                m = t;
            }
        } else if (parseInt(a[i], 10) <= 12 && m == -1) {
            m = a[i]-1;
        } else if (parseInt(a[i], 10) > 31 && y == 0) {
            y = parseInt(a[i], 10);
            (y < 100) && (y += (y > 29) ? 1900 : 2000);
        } else if (d == 0) {
            d = a[i];
        }
    }
    if (y == 0)
        y = today.getFullYear();
    if (m != -1 && d != 0)
        return new Date(y, m, d, hr, min, 0);
    return today;
};

/** Returns the number of days in the current month */
Date.prototype.getMonthDays = function(month) {
    var year = this.getFullYear();
    if (typeof month == "undefined") {
        month = this.getMonth();
    }
    if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
        return 29;
    } else {
        return Date._MD[month];
    }
};

/** Returns the number of day in the year. */
Date.prototype.getDayOfYear = function() {
    var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
    var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
    var time = now - then;
    return Math.floor(time / Date.DAY);
};

/** Returns the number of the week in year, as defined in ISO 8601. */
Date.prototype.getWeekNumber = function() {
    var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
    var DoW = d.getDay();
    d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
    var ms = d.valueOf(); // GMT
    d.setMonth(0);
    d.setDate(4); // Thu in Week 1
    return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
};

/** Checks date and time equality */
Date.prototype.equalsTo = function(date) {
    return ((this.getFullYear() == date.getFullYear()) &&
        (this.getMonth() == date.getMonth()) &&
        (this.getDate() == date.getDate()) &&
        (this.getHours() == date.getHours()) &&
        (this.getMinutes() == date.getMinutes()));
};

/** Set only the year, month, date parts (keep existing time) */
Date.prototype.setDateOnly = function(date) {
    var tmp = new Date(date);
    this.setDate(1);
    this.setFullYear(tmp.getFullYear());
    this.setMonth(tmp.getMonth());
    this.setDate(tmp.getDate());
};

/** Prints the date in a string according to the given format. */
Date.prototype.print = function (str) {
    var m = this.getMonth();
    var d = this.getDate();
    var y = this.getFullYear();
    var wn = this.getWeekNumber();
    var w = this.getDay();
    var s = {};
    var hr = this.getHours();
    var pm = (hr >= 12);
    var ir = (pm) ? (hr - 12) : hr;
    var dy = this.getDayOfYear();
    if (ir == 0)
        ir = 12;
    var min = this.getMinutes();
    var sec = this.getSeconds();
    s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
    s["%A"] = Calendar._DN[w]; // full weekday name
    s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
    s["%B"] = Calendar._MN[m]; // full month name
    // FIXME: %c : preferred date and time representation for the current locale
    s["%C"] = 1 + Math.floor(y / 100); // the century number
    s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
    s["%e"] = d; // the day of the month (range 1 to 31)
    //s["%D"] - later
    // FIXME: %E, %F, %G, %g, %h (man strftime)
    s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
    s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
    s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
    s["%k"] = hr;		// hour, range 0 to 23 (24h format)
    s["%l"] = ir;		// hour, range 1 to 12 (12h format)
    s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
    s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
    s["%n"] = "\n";		// a newline character
    s["%p"] = pm ? "PM" : "AM";
    s["%P"] = pm ? "pm" : "am";
    //s["%r"] - later
    //s["%R"] - later
    s["%s"] = Math.floor(this.getTime() / 1000);
    s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
    s["%t"] = "\t";		// a tab character
    //s["%T"] - later
    s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
    s["%u"] = w + 1;	// the day of the week (range 1 to 7, 1 = MON)
    s["%w"] = w;		// the day of the week (range 0 to 6, 0 = SUN)
    // FIXME: %x : preferred date representation for the current locale without the time
    // FIXME: %X : preferred time representation for the current locale without the date
    s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
    s["%Y"] = y;		// year with the century
    s["%%"] = "%";		// a literal '%' character

    // depend on others
    s["%D"] = s["%m"] + "/" + s["%d"] + "/" + s["%y"]; // FIXED: %D : american date style: %m/%d/%y
    s["%r"] = s["%I"] + ":" + s["%M"] + ":" + s["%S"] + " " + s["%p"]; // FIXED: %r : the time in am/pm notation %I:%M:%S %p
    s["%R"] = s["%H"] + ":" + s["%M"]; // FIXED: %R : the time in 24-hour notation %H:%M
    s["%T"] = s["%H"] + ":" + s["%M"] + ":" + s["%S"]; // FIXED: %T : the time in 24-hour notation (%H:%M:%S)
    
    
    var re = /%./g;
    if (!Calendar.is_ie5 && !Calendar.is_khtml)
        return str.replace(re, function (par) { return s[par] || par; });

    var a = str.match(re);
    for (var i = 0; i < a.length; i++) {
        var tmp = s[a[i]];
        if (tmp) {
            re = new RegExp(a[i], 'g');
            str = str.replace(re, tmp);
        }
    }

    return str;
};

Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
Date.prototype.setFullYear = function(y) {
    var d = new Date(this);
    d.__msh_oldSetFullYear(y);
    if (d.getMonth() != this.getMonth())
        this.setDate(28);
    this.__msh_oldSetFullYear(y);
};

// END: DATE OBJECT PATCHES


// global object that remembers the calendar
window._dynarch_popupCalendar = null;


// ** I18N

// Calendar EN language
// Author: Mihai Bazon, <mihai_bazon@yahoo.com>
// Encoding: any
// Distributed under the same terms as the calendar itself.

// For translators: please use UTF-8 if possible.  We strongly believe that
// Unicode is the answer to a real internationalized world.  Also please
// include your contact information in the header, as can be seen above.

// full day names
Calendar._DN = new Array
("Sunday",
 "Monday",
 "Tuesday",
 "Wednesday",
 "Thursday",
 "Friday",
 "Saturday",
 "Sunday");

// Please note that the following array of short day names (and the same goes
// for short month names, _SMN) isn't absolutely necessary.  We give it here
// for exemplification on how one can customize the short day names, but if
// they are simply the first N letters of the full name you can simply say:
//
//   Calendar._SDN_len = N; // short day name length
//   Calendar._SMN_len = N; // short month name length
//
// If N = 3 then this is not needed either since we assume a value of 3 if not
// present, to be compatible with translation files that were written before
// this feature.

// short day names
Calendar._SDN = new Array
("Sun",
 "Mon",
 "Tue",
 "Wed",
 "Thu",
 "Fri",
 "Sat",
 "Sun");

// First day of the week. "0" means display Sunday first, "1" means display
// Monday first, etc.
Calendar._FD = 0;

// full month names
Calendar._MN = new Array
("January",
 "February",
 "March",
 "April",
 "May",
 "June",
 "July",
 "August",
 "September",
 "October",
 "November",
 "December");

// short month names
Calendar._SMN = new Array
("Jan",
 "Feb",
 "Mar",
 "Apr",
 "May",
 "Jun",
 "Jul",
 "Aug",
 "Sep",
 "Oct",
 "Nov",
 "Dec");

// tooltips
Calendar._TT = {};
Calendar._TT["INFO"] = "About the calendar";

Calendar._TT["ABOUT"] =
"DHTML Date/Time Selector\n" +
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
"For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details." +
"\n\n" +
"Date selection:\n" +
"- Use the \xab, \xbb buttons to select year\n" +
"- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" +
"- Hold mouse button on any of the above buttons for faster selection.";
Calendar._TT["ABOUT_TIME"] = "\n\n" +
"Time selection:\n" +
"- Click on any of the time parts to increase it\n" +
"- or Shift-click to decrease it\n" +
"- or click and drag for faster selection.";

Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)";
Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)";
Calendar._TT["GO_TODAY"] = "Go Today";
Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)";
Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)";
Calendar._TT["SEL_DATE"] = "Select date";
Calendar._TT["DRAG_TO_MOVE"] = "Drag to move";
Calendar._TT["PART_TODAY"] = " (today)";

// the following is to inform that "%s" is to be the first day of week
// %s will be replaced with the day name.
Calendar._TT["DAY_FIRST"] = "Display %s first";

// This may be locale-dependent.  It specifies the week-end days, as an array
// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1
// means Monday, etc.
Calendar._TT["WEEKEND"] = "0,6";

Calendar._TT["CLOSE"] = "Close";
Calendar._TT["TODAY"] = "Today";
Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value";

// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";

Calendar._TT["WK"] = "wk";
Calendar._TT["TIME"] = "Time:";


// Build 9.00.7440.8

function ToDate(str) {
    var s = str.split("-");
    if(s.length === 3) {
        for(var i = 0; i < 3; ++i) {
            while(s[i].charAt(0) === "0") s[i] = s[i].substr(1);
        }
        var y = parseInt(s[0]);
        var m = parseInt(s[1]);
        var d = parseInt(s[2]);
        return new Date(y, m-1, d);
    } else {
        return new Date(str);
    }
}

if (!Qva.Mgr) Qva.Mgr = {}
Qva.Mgr.date = 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');
    
    this.Selected = {};
    var _this = this;
    
    function getDateStatus(cal, date) {
        if(cal.startDate && Calendar.CompareDate(date, cal.startDate) < 0) return true;
        if(cal.endDate && Calendar.CompareDate(date, cal.endDate) > 0) return true;
        var sdate = date.print("%Y-%m-%d");
        if(_this.Selected[sdate]) return "selected";
        return false;
    }
    
    function onSelect(cal, event) {
        if (cal.dateClicked) {
            var ctrlKey = false; //event.ctrlKey; // multiple date dont work
            
            var sdate = cal.date.print("%Y-%m-%d");
            if(ctrlKey) {
                if(_this.Selected[sdate])
                    delete _this.Selected[sdate];
                else
                    _this.Selected[sdate] = cal.date;
                cal.refresh();
            } else {
                _this.Selected = {};
                _this.Selected[sdate] = cal.date;

                _this.Owner.Set(_this.Name, "value", sdate, true);
                
//                avqSet (mgr.Name, "clear", "", false);
//                for (var d in mgr.Selected) {
//                    var v = mgr.Selected[d].getTime();
//                    avqSet(mgr.Name, "value", v, false);
//                }
//                avqLoadBegin();
            }
        } else {
            //fr�ga efter m�jliga datum i vald m�nad(+�r)?
        }
        if (cal.dateClicked && !ctrlKey) cal.callCloseHandler();
    }
    function onClose(cal) { cal.hide(); }
    
    var firstDay = null; // numeric: 0 to 6.  "0" means display Sunday first, "1" means display Monday first, etc.
    var cal = new Calendar(firstDay, null, onSelect, onClose);
    this.Cal = cal;
    
    cal.showsTime = false;
    cal.weekNumbers = true;   // (true/false) if it's true the calendar will display week numbers
    
    cal.showsOtherMonths = true;
    cal.yearStep = 1;
    cal.setRange(new Date(2004, 1-1, 1), new Date(2005, 11-1, 23));
    cal.setDateStatusHandler(getDateStatus);
    cal.getDateText = null; //function() { ... };
    cal.setDateFormat("%m/%d/%Y");
    cal.create();
    
    elem.onclick = function() {
        cal.hide();
        cal.refresh();
        var align = "Tl"; // alignment (defaults to "Bl")
        cal.showAtElement(elem, align);
        return false;
    }
}
Qva.Mgr.date.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.date.prototype.Unlock = Qva.UnlockDisabled;
Qva.Mgr.date.prototype.Paint = function (mode, node) {
    this.Touched = true;
    this.Element.style.display = Qva.MgrGetDisplayFromMode (this, mode);
    
    var cal = this.Cal;
    var values = node.getElementsByTagName("value");
    if (values.length >= 1) {
        var value = values[0];
        var min = ToDate(value.getAttribute("min"));
        var max = ToDate(value.getAttribute("max"));
        if(min && max) cal.setRange(min, max);
        var current = value.getAttribute("current");
        this.Selected = {};
        if(current) {
            var date = ToDate(current);
            var sdate = date.print("%Y-%m-%d");
            this.Selected[sdate] = date;
            cal.setDate(new Date(date));
        }
    }
    //cal.refresh();
    this.Unlock ();
}


// 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;



if (!Qva.Mgr) Qva.Mgr = {}
Qva.Mgr.slider = function (owner, elem, name, prefix) {

    if (!Qva.MgrSplit (this, name, prefix)) return;
    this.Element = elem;
    this.Touched = false;
    owner.AddManager (this);
    
    this.G = SelectInitGraphics();
}
Qva.Mgr.slider.prototype.Lock = Qva.LockDisabled;
Qva.Mgr.slider.prototype.Unlock = Qva.UnlockDisabled;

Qva.Mgr.slider.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 objectframeNode = element.parentNode;
    if (element.tagName == "DIV") {
        var newheight = parseInt (getContentMaxHeight (element));
        if (! isNaN (newheight)) {
            element.style.height = newheight + "px";
        }
        setContentWidth (objectframeNode);
    }
    setStyle (node, element);
    for(var child = node.firstChild; child; child = child.nextSibling) {
        if (child.nodeName == "layout") {
            this.Node = child;
        } else if (child.nodeName == "choice") {
            if(!this.Choice) this.Choice = [];
            var index = 0;
            for(var elem = child.firstChild; elem; elem = elem.nextSibling) {
                this.Choice[index++] = elem.getAttribute("text");
            }
            this.Choice.length = index;
        }
    }
    Qva.QueuePostPaintMessage (this);
}

Qva.Mgr.slider.tooltip = null;

Qva.Mgr.slider.prototype.PostPaint = function () {
    var mgr = this;
    var div = this.Element;
    var node = this.Node;
    var swap = true;
    var dir = node.getAttribute("orientation") || "horizontal";
    var slider_color = node.getAttribute("color") || "#AABCDD";
    var tics = null;
    var thumb = null;
    var arrows = null;
    for(var child = node.firstChild; child; child = child.nextSibling) {
        if (tics == null && child.nodeName == 'tics') tics = child;
        if (thumb == null && child.nodeName == "thumb") thumb = child;
        if (arrows == null && child.nodeName == "arrows") arrows = child;
    }
    var max = parseFloat(node.getAttribute("max"));
    var min = parseFloat(node.getAttribute("min"));
    var current_min = parseFloat(node.getAttribute("current_min"));
    var current_max = parseFloat(node.getAttribute("current_max"));
    var userange = node.getAttribute("selectionrange") == "multi";
    var selectionvalid = node.getAttribute("selectionvalid") == "true" && !isNaN(current_min) && !isNaN(current_max);
    if (min == max) return;
    
    var step = node.getAttribute("step");
    if(step) step = parseFloat(step);
    
    var top = div.offsetTop;
    var width = div.clientWidth;
    var objectframeNode = div.parentNode;
    var height = objectframeNode.clientHeight - top;
    var fontSize = objectframeNode.style.fontSize;
    
    var length = dir == "horizontal" ? width : height;
    var offset = 19;
    
    var _left =   dir == "horizontal" ? "left"   : "top";
    var _top =    dir == "horizontal" ? "top"    : "left";
    var _width =  dir == "horizontal" ? "width"  : "height";
    var _height = dir == "horizontal" ? "height" : "width";
    
    var _line =        dir == "horizontal" ? height - 15 : 12;
    var _textAlign =   dir == "horizontal" ? "center"    : "left";
    var _textTop =     dir == "horizontal" ? _line - 28  : _line + 23;

    var _oPos = dir == "horizontal" ? "left"    : "top";
    var _mPos = dir == "horizontal" ? "clientX" : "clientY";
    
    var _thumb = dir == "horizontal"
                 ? [[0,4], [4,0], [8,4], [8,12], [0,12]]
                 : [[0,0], [8,0], [12,4] ,[8,8], [0,8]];
    var fix_point = dir == "horizontal" 
                    ? function (x, y) { return [x, y]; }
                    : function (y, x) { return [x, y]; };
    
    var sign = dir == "horizontal" ? -1  : 1;
    var _ticStart = _line + sign * 10;
    var _ticMajorEnd = _ticStart + sign * 13;
    var _ticMinorEnd = _ticStart + sign * 7;
    
    var root = document.createElement("div");
    root.style.width = width + "px";
    root.style.height = height + "px";
    var slider = mgr.G.CreateArea([width, height], root);
    
    var l = mgr.G.CreateLine(fix_point(offset, _line), fix_point(length - offset, _line), slider_color, slider, 4);
    if(!l) l = slider;
    
    var tics_space = length - 2 * (offset + 5);
    var valueCount = max - min + 1;
    var dval = tics_space / (valueCount - 1);
    if(tics) {
        var color = tics.getAttribute("color") || "#A4A4A4";
        function create_line(pos, start, end) { mgr.G.CreateLine(fix_point(pos, end), fix_point(pos, start), color, slider); };
        
        var labelCount = parseInt(tics.getAttribute("labels"));
        var majorCount = parseInt(tics.getAttribute("major"));
        if(majorCount < 2) majorCount = 0;
        var minorCount = parseInt(tics.getAttribute("minor"));
        if(minorCount < 0) minorCount = 0;
        
        var iv = 0;
        var labels = tics.getElementsByTagName("label");
        
        var dmajor = tics_space / (majorCount - 1);
        for(var imajor = 0; imajor < majorCount; ++imajor) {
            var labelnode = labels[iv++];
            var pos;
            if (labelnode && labelnode.getAttribute("index")) {
                pos = Math.round (offset + 5 + parseInt (labelnode.getAttribute("index")) * dval);
            } else {
                pos = Math.round (offset + 5 + imajor * dmajor);
            }
            if (dir == "horizontal") {
                create_line(pos, _ticStart + 3, _ticMajorEnd + 3, color);
            } else {
                create_line(pos, _ticStart - 3, _ticMajorEnd - 3, color);
            }
            if (labelCount > 0 && imajor % labelCount == 0 && labelnode) {
                var text = labelnode.getAttribute("text");
                
                var size = MeasureText(text, fontSize);
                var attrib = {"position": "absolute",
                              "fontSize": fontSize,
                              "overflow": "visible",
                              "color": color,
                              "fontFamily": div.style.fontFamily,
                              "textAlign": _textAlign };
                attrib[_left] = (dir == "horizontal" ? Math.round(pos - size.width/2) : Math.floor(pos - size.height/2) + 2) + "px";
                attrib[_top] = (dir == "horizontal" ? Math.max (Math.round(_textTop - size.height/2), 0) : _textTop) + "px";
                attrib["width"] = size.width + "px";
                attrib["height"] = size.height + "px";
                
                var label = document.createElement("div");
                for(var k in attrib) { label.style[k] = attrib[k]; }
                label.innerText = text;
                root.appendChild(label);
            }
            if(imajor == majorCount - 1) continue;
            
            var dminor = dmajor / (minorCount + 1);
            for(var iminor = 1; iminor <= minorCount; ++iminor) {
                var pos2 = Math.round(pos + iminor * dminor);
                create_line(pos2, _ticStart, _ticMinorEnd, color);
            }
        }
    }
    if(Qva.Mgr.slider.tooltip === null) {
        Qva.Mgr.slider.tooltip = document.createElement("div");
        Qva.Mgr.slider.tooltip.style.position = "absolute";
        Qva.Mgr.slider.tooltip.style.width    = "auto";
        Qva.Mgr.slider.tooltip.style.height   = "auto";
        Qva.Mgr.slider.tooltip.style.zIndex   = 666;
        Qva.Mgr.slider.tooltip.style.backgroundColor = "#FFFFCC";
        Qva.Mgr.slider.tooltip.style.borderWidth = "1px";
        Qva.Mgr.slider.tooltip.style.borderColor = "black";
        Qva.Mgr.slider.tooltip.style.borderStyle = "solid";
        Qva.Mgr.slider.tooltip.style.padding = "3px";
        document.body.insertBefore (Qva.Mgr.slider.tooltip, document.body.firstChild);
    }
    Qva.Mgr.slider.tooltip.style.visibility = "hidden";

    var thumb_color = thumb.getAttribute("color") || "#3796FF";
    var thumb_pos = fix_point(30, _line - 6);
    var thumb_size = fix_point(8, 12);
    
    var thumb = mgr.G.CreatePolygonObj (_thumb, thumb_color, root, thumb_pos, thumb_size);
    thumb.style.cursor = "inherit";
    function val_to_pos(val) {
        if(max == min) return 0;
        return (thumb.maxVal - thumb.minVal) * (val - min) / (max - min) + thumb.minVal; 
    }
    function pos_to_val(pos) {
        return (pos - thumb.minVal) * (max - min) / (thumb.maxVal - thumb.minVal) + min;
    }
    function fix_thumb(min, max, end, done) {
        thumb._min = min;
        thumb._max = max;
        
        var min_range = 8;
        var range = Math.round(val_to_pos(max) - val_to_pos(min));
        
        if(range > min_range) {
            _fix_thumb(min, range);
        } else if(end == "min") {
            _fix_thumb(max, 0);
            if(done) thumb._min = thumb._max;
        } else {
            _fix_thumb(min, 0);
            if(done) thumb._max = thumb._min;
        }
    }
    function _fix_thumb(min, range) {
        thumb.style[_oPos] = Math.round(val_to_pos(min)) + "px";
        if(range > 0) {
            var path = [[4,0], [8,4], [range,4], [range+4,0], [range+4,12], [range,8], [8,8], [4,12]];
            if(dir != "horizontal") {
                for(var i = 0; i < path.length; ++i) {
                    var temp = path[i][0];
                    path[i][0] = path[i][1];
                    path[i][1] = temp;
                }
            }
            mgr.G.FixPolygon(thumb, path, fix_point(range+8, 12), thumb_color);
        } else {
            mgr.G.FixPolygon(thumb, _thumb, thumb_size, thumb_color);
        }
    }
    if(userange) {
        thumb.onmouseover = function(event) {
            if (Qva.Select.Active) {
                if(!event) event = window.event;

                var diff = 3;
                var pos = Qva.GetPageCoords(thumb);
                var i = dir === "horizontal" ? "x" : "y";
                var l = thumb._min == thumb._max ? 0 : 8;
                
                if(Math.abs(pos[i] - event[_mPos]) < diff) {
                    document.body.style.cursor = dir === "horizontal" ? "w-resize" : "n-resize";
                } else if(Math.abs(pos[i] + (parseFloat(thumb.style[_width]) - l) - event[_mPos]) < diff) {
                    document.body.style.cursor = dir === "horizontal" ? "e-resize" : "s-resize";
                } else {
                    document.body.style.cursor = "pointer";
                }
            }
        }
        thumb.onmousemove = thumb.onmouseover;
        thumb.onmouseout = function() { if (Qva.Select.Active) document.body.style.cursor = "default" }
    }
    
    thumb._setPos = function(done) {
        var val = [thumb._min, thumb._max];
        
        if(step) {
            val [0] = (val [0] + step / 2) - ((val [0] + step / 2) % step);
            val [1] = (val [1] + step / 2) - ((val [1] + step / 2) % step);
        }
        
        if(done) {
            var setvalue = thumb.lastValue != val[0] || thumb.lastValue != val[1];
            Qva.Mgr.slider.tooltip.style.visibility = "hidden";
            if(userange) {
                val = val [0] + ":" + val [1];
            } else {
                val = val [0];
            }
            if(setvalue) mgr.PageBinder.Set (mgr.Name, 'value', val, true);
        } else {
            var pos = Qva.GetAbsolutePageCoords(thumb);
            
            val[0] = Math.round(val[0] * 100) / 100;
            val[1] = Math.round(val[1] * 100) / 100;
            
            if(userange) {
                if(mgr.Choice) {
                    Qva.Mgr.slider.tooltip.innerHTML = "Min: " + (mgr.Choice[val[0]] || "?") + "<br/>" + "Max: " + (mgr.Choice[val[1]] || "?");
                } else {
                    Qva.Mgr.slider.tooltip.innerHTML = "Min: " + val[0] + "<br/>" + "Max: " + val[1];
                }
            } else {
                Qva.Mgr.slider.tooltip.innerText = mgr.Choice ? (mgr.Choice[val[0]] || "?") : val[0];
            }
            if(dir == "horizontal") {
                Qva.Mgr.slider.tooltip.style.left = (pos.x - 5) + "px";
                Qva.Mgr.slider.tooltip.style.top  = (pos.y - 50) + "px";
            } else {
                Qva.Mgr.slider.tooltip.style.left = (pos.x + 50) + "px";
                Qva.Mgr.slider.tooltip.style.top  = (pos.y - 5) + "px";
            }
            Qva.Mgr.slider.tooltip.style.visibility = "visible";
        }
    }
    thumb.setPos = function(npos, done) {
        if (npos < thumb.minVal) npos = thumb.minVal;
        if (npos > thumb.maxVal) npos = thumb.maxVal;
        var m = pos_to_val(npos);
        if (!isNaN(m)) fix_thumb(m, m, "max", done);
        thumb._setPos(done);
    }
    thumb.onmousedown = function(event) {
        if (!event) event = window.event;
        switch(document.body.style.cursor) {
            case "w-resize":
            case "n-resize":
                thumb.setPos = function(npos, done) {
                    var t_max = val_to_pos(thumb._max);
                    if(t_max < npos) npos = t_max;
                    if(npos < thumb.minVal) npos = thumb.minVal;
                    fix_thumb(pos_to_val(npos), thumb._max, "min", done);
                    thumb._setPos(done)
                }
                break;
            case "e-resize":
            case "s-resize":
                var t_len = parseFloat(thumb.style[_width]) - 8;
                thumb.setPos = function(npos, done) {
                    npos += t_len;
                    var t_min = val_to_pos(thumb._min);
                    if(npos < t_min) npos = t_min;
                    if(thumb.maxVal < npos) npos = thumb.maxVal;
                    fix_thumb(thumb._min, pos_to_val(npos), "max", done);
                    thumb._setPos(done)
                }
                break;
            default:
                var t_len = parseFloat(thumb.style[_width]) - 8;
                var range = thumb._max - thumb._min;
                thumb.setPos = function(npos, done) {
                    var t_end = thumb.maxVal - t_len;
                    if (npos < thumb.minVal) npos = thumb.minVal;
                    if (npos > t_end) npos = t_end
                    var m = pos_to_val(npos);
                    if (!isNaN(m)) fix_thumb(m, m + range, "max", done);
                    thumb._setPos(done);
                }
                break;
        }
        var x = parseFloat(thumb.style[_oPos]);
        thumb.mouseZero = event[_mPos] - x;
        thumb._setPos(false);
        
        function SlideEnd(event) {
            if (!event) event = window.event;
            var npos = event[_mPos] - thumb.mouseZero;
            thumb.setPos(npos, true);
            Qva.removeEvent(document,"mousemove",SlideDrag);
            Qva.removeEvent(document,"mouseup",SlideEnd);
            Qva.Select.Active = true;
        }
        function SlideDrag(event) {
            if (!event) event = window.event;
            var npos = event[_mPos] - thumb.mouseZero;
            thumb.setPos(npos)
        }
        Qva.Select.Active = false;
        Qva.addEvent(document,"mousemove",SlideDrag);
        Qva.addEvent(document,"mouseup",SlideEnd);
        event.cancelBubble = true;
        return false;
    }
    
    thumb.minVal = 17 + 3;
    thumb.maxVal = parseFloat(thumb.parentNode.style[_width]) - parseFloat(thumb.style[_width]) - 17 - 3;
    thumb.lastValue = current_min == current_max ? current_min : -1;
    if(selectionvalid) {
        fix_thumb(current_min, current_max, "max", true);
    } else {
        thumb.style.visibility = "hidden";
        l.onmouseover = function (event) {
            var old_onmousedown = thumb.onmousedown;
            var old_onmouseover = thumb.onmouseover;
            var old_onmousemove = thumb.onmousemove;
            var old_onmouseout = thumb.onmouseout;
            
            thumb.onmouseover = null;
            thumb.onmousedown = function(event) {
                thumb.style.visibility = "visible";
                thumb.onmouseout = null;
                thumb.onmousemove = null;
                l.onmouseover = null;
                l.onmousemove = null;
                l.onmouseout = null;
                
                thumb.onmousedown = old_onmousedown;
                thumb.onmouseover = old_onmouseover;
                thumb.onmousemove = old_onmousemove;
                thumb.onmouseout = old_onmouseout;
                if(userange) document.body.style.cursor = "e-resize";
                old_onmousedown(event);
            };
            thumb.onmouseout = function() {
                thumb.style.visibility = "hidden";
                thumb.onmouseout = null;
                thumb.onmousemove = null;
                l.onmousemove = null;
                l.onmouseout = null;
                Qva.Mgr.slider.tooltip.style.visibility = "hidden";
            };
            thumb.onmousemove = function(event) {
                if(!event) event = window.event;
                var x = dir == "horizontal" ? "x" : "y";
                var npos = event[_mPos] - (Qva.GetPageCoords(div)[x] + 4);
                thumb.setPos(npos, false);
            };
            l.onmouseout = function(event) {
                if(!event) event = window.event;
                if(!event.toElement) { debugger; }
                if(event.toElement !== thumb) {
                    thumb.onmouseout();
                }
            };
            l.onmousemove = thumb.onmousemove;
            thumb.onmousemove(event);
            thumb.style.visibility = "visible";
        };
    }
    
    function create_arrow(side, color) {
        var x0 = side == "start" ? 0 : 10;
        var x2 = side == "start" ? 10 : 0;
        
        var points = [fix_point(x0,0), fix_point(x2,6), fix_point(x0,12)];
        var pos = fix_point(side == "start" ? (length - 15) : 5, _line - 6);
        var size = fix_point(10,12);
        var arrow = mgr.G.CreatePolygonObj(points, color, root, pos, size);

        var diff = userange ? 1 : (step != null ? step : 1);
        if(side !== "start") diff = -diff;
        arrow.onmousedown = function () { 
            if(thumb._min != -1 && thumb._min + diff >= min && thumb._max + diff <= max) {
                thumb._min += diff;
                thumb._max += diff;
                thumb._setPos(true);
            }
        };
    };
    
    if(arrows) {
        var arrow_color = arrows.getAttribute("color") || "#0080C0";
        create_arrow("start", arrow_color);
        create_arrow("end", arrow_color);
    }
    
    if(swap && div.firstChild) {
        div.replaceChild(root, div.firstChild);
    } else {
        div.appendChild(root);
    }
}

// End Slider


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
        }
    }
}


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;
    }
};

/**
@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;
    };

    function initialize() {

        var box = qwwHub.DoAvqSelect(applicationID, objectId);

        //if (box == null) {
        if (box == null && !_hasPageSizeBeenSet) {

            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;
    };

    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", 250);
    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; i < dropDowns.length; i++) {

        var elem = dropDowns[i];

        var showDisabled = elem.getAttribute('ShowDisabled') == 'true';
        var includeSelectAll = elem.getAttribute('IncludeSelectAll') == 'true';
        var isLanguageSelector = elem.getAttribute('IsLanguageSelector') == 'true';

        new Qww.Ctls.DropDown.Mgr({ ObjectID: elem.id, ElementID: elem.id, ShowDisabled: showDisabled, IncludeSelectAll: includeSelectAll, IsLanguageSelector: isLanguageSelector });
    }
};

Qww.Ctls.DropDown.Mgr.prototype.RenderDropDown = function(lbm) {

    //
    // 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;
        }
    }

    if (this.isFirstTime == true) {

        this.parentElement.append("<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; i < lbm.TotalSize; i++) {
    for (var i = 0; i < lbm.Results.All.length; 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;
};


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.innerText = 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;
                }
            }
        }

        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 (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;

    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.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 currentTextObjectStatus = $("#" + textObjectStatus[i]);

        if (textObjectStatus[i + 1] == "true") {
            currentTextObjectStatus.show();

            var idOfContainerToChangeHeight = currentTextObjectStatus.attr("IdOfContainerHeightToAdjust");

            $("#" + idOfContainerToChangeHeight).height(currentTextObjectStatus.attr("HeightToAdjustContainerTo"));

        }
        else {
            currentTextObjectStatus.hide();
        }
    }
};

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;
    }
};


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;
    });
}

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.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 html = [];
        html.push("<div class='GlobalSearch-Parent-Default' id='" + ElementID + "Parent' style='display:inline-block;width:150px;'>");
        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": [
            new Qww.Ctls.GlobalSearch.Field({
                ObjectID: ObjectID,
                Title: " ",
                MatchText: " ",
                NoMatchText: " ",
                MaxNumberOfLettersToShowInResult: 58,
                MaxNumberOfResultsToShow: 150,
                SelectAllText: " ",
                ReduceResultsText: " "
            })],
            "ResultsElementId": ResultElementID,
            "SearchTextBoxId": SearchTextBoxID,
            "Theme": "Default",
            "AutomaticallyClearSearchString": true//,
            //        OnRenderResultsSection: function(a,b,c)
            //        {
            //            
            //        }
        });

    }
};

Qww.Ctls.GoogleMap = {};

Qww.Ctls.GoogleMap.Mgr = function(cfg) {


    var IMAGE_ROOT = "../img/map_pins/";

    this.parentElement = $('#' + cfg.ElementID);
    this.Cfg = cfg;
    var me = this;

    function updateMapFromListBox(lbm) {

        me.EnsureMapIsInitialised();

        if (me.map == null) return;

        var items = lbm.Results.All;
        var noItems = items.length;

        if (me.PinsVsValues == null) {

            me.PinsVsValues = {};

            var disableAutoPan = true;
            var infowindow = new google.maps.InfoWindow({ content: "", 'disableAutoPan': disableAutoPan });

            for (var i = 0; i < noItems; i++) {

                var item = items[i];

                var parts = item.Text.split("|");
                var status = parts[0];
                var kommun = parts[1];
                var lat = parts[2].replace(",", ".");
                var lon = parts[3].replace(",", ".");

                var myLatlng = new google.maps.LatLng(lat, lon)

                var marker = new google.maps.Marker({
                    position: myLatlng,
                    map: me.map,
                    icon: IMAGE_ROOT + "marker1.png",
                    title: kommun
                });

                marker.map = me.map;
                marker.infowindow = infowindow;
                marker.ListBoxMgr = me.ListBoxMgr;
                marker.ListBoxItem = item;

                google.maps.event.addListener(marker, 'click', me.OnPinClick);
                google.maps.event.addListener(marker, 'mouseout', me.HideInfoWindow);
                google.maps.event.addListener(marker, 'mouseover', me.ShowInfoWindow);

                me.PinsVsValues[item.Value] = marker;
            };

            me.FitToAllPins();
        }
        else {
            for (var i = 0; i < noItems; i++) {

                var item = items[i];

                var marker = me.PinsVsValues[item.Value];

                if (marker == null) continue;

                if (item.State == Qww.ListBox.Mgr.ItemState.Disabled && !marker.icon != "marker1_disabled.png") {
                    marker.setIcon(IMAGE_ROOT + "marker1_disabled.png");
                }
                else {
                    if (marker.icon != IMAGE_ROOT + "marker1.png") {
                        marker.setIcon(IMAGE_ROOT + "marker1.png");
                    }
                }
            }
        }
    };

    function onListBoxUpdated(lbm) {

        //        if (me.TemplatePopupHtml == null) {
        //            me.ListBoxNeedsUpdating = true;
        //            return;
        //        };

        updateMapFromListBox(lbm);

        //document.body.style.cursor = 'default';

        if (me.Cfg.OnUpdate) {
            me.Cfg.OnUpdate(me);
        }
    }

    //    new Qww.TextObject.Mgr(
    //    {
    //        ObjectID: 'TX_Dictionary_amMap_SingleFactPopUp',
    //        OnUpdate: function(txtObject) {
    //            me.TemplatePopupHtml = txtObject.Text;

    //            if (me.ListBoxNeedsUpdating != null) {
    //                updateMapFromListBox(this.ListBoxMgr);
    //            }
    //        }
    //    });


    this.ListBoxMgr = new Qww.ListBox.Mgr(
    {
        ObjectID: cfg.ObjectID,
        PageSize: 1000,
        OnUpdate: onListBoxUpdated
    });

    Qww.Ctls.GoogleMap.Mgr.Mrgs[cfg.ElementID] = this;
};

Qww.Ctls.GoogleMap.Mgr.ScanForAndCreate = function() {

    var googleMaps = jQuery(".Qww_Ctls_GoogleMap");

    for (var i = 0; i < googleMaps.length; i++) {
        var map = new Qww.Ctls.GoogleMap.Mgr({ ObjectID: googleMaps[i].id, ElementID: googleMaps[i].id });

        if (document.Qww_Ctls_GoogleMaps == null) {
            document.Qww_Ctls_GoogleMaps = {};
        }

        document.Qww_Ctls_GoogleMaps[googleMaps[i].id] = map;
    }
};

Qww.Ctls.GoogleMap.Mgr.prototype.ShowInfoWindow = function() {
    this.infowindow.content = this.title;
    this.infowindow.open(this.map, this);
};

Qww.Ctls.GoogleMap.Mgr.prototype.HideInfoWindow = function() {
    this.infowindow.close();
};

Qww.Ctls.GoogleMap.Mgr.prototype.OnPinClick = function() {
    this.ListBoxMgr.MakeSingleSelection(this.ListBoxItem.Value, false, true);
};

Qww.Ctls.GoogleMap.Mgr.prototype.Log = function() {

    var html = [];
    for (var key in this.PinsVsValues) {
        var item = this.PinsVsValues[key].ListBoxItem;
        html.push("<span class='State_" + item.State + "'>[" + item.Value + " " + item.State + " " + item.Text + "]</span>");
    };

    jQuery('#xx').empty();
    jQuery('#xx').html(html.join(''));
};

Qww.Ctls.GoogleMap.Mgr.prototype.FitToAllPins = function() {

    var latMax = lonMax = -10000;
    var latMin = lonMin = 10000;
 
    for (var key in this.PinsVsValues) {
        var latLng = this.PinsVsValues[key].getPosition();
        var lat = latLng.lat();
        var lon = latLng.lng();

        if (lat > latMax) latMax = lat;
        if (lat < latMin) latMin = lat;
        if (lon > lonMax) lonMax = lon;
        if (lon < lonMin) lonMin = lon;
    }

    this.map.fitBounds(new google.maps.LatLngBounds(new google.maps.LatLng(latMin, lonMin), new google.maps.LatLng(latMax, lonMax)));
}

Qww.Ctls.GoogleMap.Mgr.prototype.EnsureMapIsInitialised = function() {

    if (this.map == null && this.ListBoxMgr.Enabled == true) 
    {    
        var latlng = new google.maps.LatLng(63.397, 18);
        
        var myOptions = {
            //zoom: 5,
            //center: latlng,
            mapTypeId: google.maps.MapTypeId.TERRAIN
        };

        this.map = new google.maps.Map(document.getElementById(this.Cfg.ElementID), myOptions);
    }
};

Qww.Ctls.GoogleMap.Mgr.Mrgs = {};

/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();if(!(navigator.plugins && navigator.mimeTypes.length)) window[this.getAttribute('id')] = document.getElementById(this.getAttribute('id'));return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;


Qww.Ctls.AmMap = {};

//// REGISTER MOUSE CLICK ON AN OBJECT
//// amRegisterClick(map_id, object_id, title, value)
//// This function is called when user clicks on some object - area, movie or label.  
//function amRegisterClick(map_id, object_id, title, value) {
//    //document.getElementById("objectid").value = object_id;
//    alert(map_id + ' ' + object_id + ' ' + title + ' ' + value);
//}

function amMapCompleted(map_id) {

    var elementId = map_id.toString().substr(0, map_id.toString().length - ("_map").length);

    var ctl = Qww.Ctls.AmMap.Mgr.Mrgs[elementId];

    var flash = document.getElementById(map_id);

    ctl.SetDataInterface = flash;
    
    if (ctl.QueuedData != null) {
        flash.setData(ctl.QueuedData);
        ctl.QueuedData = null;
    }

}

/**
Constructs a new Qww.AmMap.Mgr instance.
@constructor
@class JavaScript class to render an AmMap control.<br />
@param {Object} cfg JSON object to configure the control.
@param {String} cfg.ElementID ID of the html element (e.g. div or span) where the 
map should be placed.
@param {String} cfg.ObjectID Id of the ListBox in the QlikView application.
@param {Function} [cfg.OnUpdate] Function to call whenever the data/control is updated. The 
handler will be passed a single argument which is a reference to this object itself.
@returns {Qww.AmMap.Mgr} Qww.AmMap.Mgr
*/
Qww.Ctls.AmMap.Mgr = function(cfg) {

    this.parentElement = $('#' + cfg.ElementID);
    this.Cfg = cfg;
    var me = this;

    function updateMapFromListBox(lbm) {

        me.EnsureMapIsInitialised();

        var items = lbm.Results.All;
        var noItems = items.length;

        var xml = [];

        //me.flash.addVariable("map_data", "<map map_file='maps/world.swf'><areas></areas></map>");

        var maskFull = lbm.Caption.Text;

        var parts = maskFull.split("|");

        var mask = parts[1];
        var maskGroupChar = parts[3];
        var maskDecChar = parts[2];

        //
        // Can also set other data in xml, e.g. zoom='330%' zoom_x='-122.69%' zoom_y='-91.75%'
        // See http://www.ammap.com for full details.
        //
        
        xml.push("<map map_file='maps/world.swf'><areas>");
        for (var i = 0; i < noItems; i++) {

            var item = items[i];

            var parts = item.Text.split("|");
            var status = parts[0];
            var country = parts[1];
            var code = parts[2];
            var populationSize = parts[3];

            if (populationSize == null) continue;
            populationSize = ICB_NumberFormatter.Format(populationSize, { format: mask, group: maskGroupChar, dec: maskDecChar }); ;

            var flagFileName = parts[4];
            var capital = parts[5];
            var factValue = parts[6];
            var factValue2 = parts[7];
            var factValue3 = parts[8];
            var text = me.TemplatePopupHtml;
            text = text.split("|");

            var textToShow;

            if (status == Qww.ListBox.Mgr.ItemState.Disabled)
                textToShow = text[1];
            else
                textToShow = text[0];

            textToShow = textToShow.replace("[Flag]", "<img src=&quot;\\images\\flags\\" + flagFileName + ".gif&quot; width=&quot;30&quot; height=&quot;20&quot;>");
            //textToShow = textToShow.replace("[Flag]", flagFileName);
            textToShow = textToShow.replace("[country]", country);
            textToShow = textToShow.replace("[population]", populationSize);
            textToShow = textToShow.replace("[capital]", capital);
            textToShow = textToShow.replace("[factvalue]", factValue);
            textToShow = textToShow.replace("[factvalue2]", factValue2);
            textToShow = textToShow.replace("[factvalue3]", factValue3);

            //var text = "<b>" + country + "</b>(" + parts[2] + ")(" + Qww.ListBox.Mgr.ItemState.GetStateAsString(item.State) + ")" + parts[3];

            //var text = 'hello';

            textToShow = textToShow.replace(/</g, "&lt;");
            textToShow = textToShow.replace(/>/g, "&gt;");
            textToShow = textToShow.replace("'", "");
            textToShow = textToShow.replace("'", "");

            var colour = "";

            if (status == Qww.ListBox.Mgr.ItemState.Selected) {
                colour = "#db221d";
            }
            else if (status == Qww.ListBox.Mgr.ItemState.Associated) {
                colour = "#4B7299";
            }
            else {
                colour = "#6f6f6f";
            }

            //xml.push("<area title='" + text + "' mc_name='" + code + "' color='" + colour + "' url='javascript:alert(\"" + country.replace("'", "&#39") + " clicked\")'></area>");

            var url = '';

            if (status != Qww.ListBox.Mgr.ItemState.Disabled) {
                url = "url='javascript:Qww.Ctls.AmMap.Mgr.Click(\"" + me.Cfg.ElementID + "\", " + item.Value + ");'";
                //url = "url='javascript:alert();'";
            }
            //var js = '';

            //
            // With everything
            //
            //xml.push("<area oid=" + item.Value + " title='" + text + "' mc_name='" + code + "' color='" + colour + "' " + url + "></area>");

            //
            // With title
            //
            xml.push("<area mc_name='" + code + "' color='" + colour + "' title='" + textToShow + "' " + url + "></area>");

            //
            // Without title
            //
            //xml.push("<area mc_name='" + code + "' color='" + colour + "' " + url + "></area>");

            //xml.push("<area oid=" + item.Value + " mc_name='" + code + "'></area>");
        };

        xml.push("</areas></map>");

        //var escapedXml = escape(xml.join(''));
        var escapedXml = xml.join('');

        if (me.SetDataInterface != null && me.SetDataInterface.setData) {
            me.SetDataInterface.setData(escapedXml);
        }
        else {
            me.QueuedData = escapedXml;
        }
    };

    function onListBoxUpdated(lbm) {

        if (me.TemplatePopupHtml == null) {
            me.ListBoxNeedsUpdating = true;
            return;
        };


        updateMapFromListBox(lbm);

        //document.body.style.cursor = 'default';

        if (me.Cfg.OnUpdate) {
            me.Cfg.OnUpdate(me);
        }
    }

    //put text object

    new Qww.TextObject.Mgr(
    {
        ObjectID: 'TX_Dictionary_amMap_SingleFactPopUp',
        OnUpdate: function(txtObject) {
            me.TemplatePopupHtml = txtObject.Text;

            if (me.ListBoxNeedsUpdating != null) {
                updateMapFromListBox(this.ListBoxMgr);
            }
        }
    });


    this.ListBoxMgr = new Qww.ListBox.Mgr(
    {
        ObjectID: cfg.ObjectID,
        PageSize: 1000,
        OnUpdate: onListBoxUpdated
    });

    //    $(document).ready(function() {
    //        me.RenderMap();
    //    });

    Qww.Ctls.AmMap.Mgr.Mrgs[cfg.ElementID] = this;

};

Qww.Ctls.AmMap.Mgr.ScanForAndCreate = function() {

    var amMaps = jQuery(".Qww_Ctls_AmMap");

    for (var i = 0; i < amMaps.length; i++) {
        var map = new Qww.Ctls.AmMap.Mgr({ ObjectID: amMaps[i].id, ElementID: amMaps[i].id });

        if (document.Qww_Ctls_AmMaps == null) {
            document.Qww_Ctls_AmMaps = {};
        }

        document.Qww_Ctls_AmMaps[amMaps[i].id] = map;
    }
};

var f;

Qww.Ctls.AmMap.Mgr.prototype.EnsureMapIsInitialised = function() {

    if (this.map == null && this.ListBoxMgr.Enabled == true) {

        var outerDivId = this.Cfg.ElementID + "_flash";

        this.parentElement.html("<div id=\"" + outerDivId + "\"><strong>You need to upgrade your Flash Player</strong></div>");

        //        this.flash = new SWFObject(Qww.Ctls.AmMap.Mgr.AmMapRoot + "ammap.swf", this.Cfg.ElementID + "_ammap", "600", "350", "8", "#444444");
        this.flash = new SWFObject(Qww.Ctls.AmMap.Mgr.AmMapRoot + "ammap.swf", this.Cfg.ElementID + "_map", "650", "350", "8", "#bad4e8");

        //this.flash = new SWFObject("ammap/ammap.swf", this.Cfg.ElementID + "_ammap", this.parentElement[0].style.width, this.parentElement[0].style.height, "8", "#444444"); ;
        //this.flash = new SWFObject("ammap/ammap.swf", this.Cfg.ElementID + "_ammap", this.parentElement[0].style.width.replace('px', ''), this.parentElement[0].style.height.width.replace('px', ''), "8", "#444444"); ;

        //
        // The ID passed for the second argument here seems to be
        // that passed to the function amMapCompleted(map_id) {
        // at the top.
        //
        this.flash.addVariable("map_id", this.Cfg.ElementID + "_map");
        this.flash.addVariable("path", Qww.Ctls.AmMap.Mgr.AmMapRoot);
        this.flash.addVariable("settings_file", escape(Qww.Ctls.AmMap.Mgr.AmMapRoot + "ammap_settingsicb.xml"));                  // you can set two or more different settings files here (separated by commas)

        this.flash.addVariable("data_file", escape(Qww.Ctls.AmMap.Mgr.AmMapRoot + "ammap_data.xml"));
        this.flash.addParam("wmode", "opaque");

        this.flash.addVariable("map_data", "<map map_file='maps/world.swf'><areas></areas></map>");

        this.flash.write(outerDivId);

        this.map = true;
    }
};

Qww.Ctls.AmMap.Mgr.prototype.Click = function(val) {
    //debugger;
    //document.body.style.cursor = 'wait';
    this.ListBoxMgr.MakeSingleSelection(val, false, true);
};

Qww.Ctls.AmMap.Mgr.Click = function(elementId, val) {
    Qww.Ctls.AmMap.Mgr.Mrgs[elementId].Click(val);
};

Qww.Ctls.AmMap.Mgr.AmMapRoot = "../inc/mapping/ammap/";
Qww.Ctls.AmMap.Mgr.Mrgs = {};

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);
};

Factlab.IsResultsPage = function() {

    if (window.location.href.indexOf("/results.aspx") > -1) return true;

    return false;
};

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:
                tableHtml.push("<th class='column2'><span id='Fact1_Header'></span></th>");
                break;
            case 3:
                tableHtml.push("<th class='column3'><span id='Fact2_Header'></span></th>");
                break;
            case 4:
                tableHtml.push("<th class='column4'><span 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"></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(""));

    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 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 ($('#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_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) {
        //results only
        if (Factlab.IsResultsPage()) {
            $('#TX_World_Lab_Bottom_Section_Add_Fact3').hide();

            $("#fact1").hide();
            $("#fact2").hide();
            $("#fact3").hide();
            $("#fact4").hide();

            /*
            $('#toggle1').html('<img src="img/down.png">');
            $('#toggle2').html('<img src="img/down.png">');
            $('#toggle3').html('<img src="img/down.png">');
            $('#toggle4').html('<img src="img/down.png">');
            */
            $('#toggle1 #TX_World_Lab_Bottom_Section_Fact_Show').show();
            $('#toggle1 #TX_World_Lab_Bottom_Section_Fact_Hide').hide();
            $('#toggle2 #TX_World_Lab_Bottom_Section_Fact2_Show').show();
            $('#toggle2 #TX_World_Lab_Bottom_Section_Fact2_Hide').hide();
            $('#toggle3 #TX_World_Lab_Bottom_Section_Fact3_Show').show();
            $('#toggle3 #TX_World_Lab_Bottom_Section_Fact3_Hide').hide();
            $('#toggle4 #TX_World_Lab_Top_Section_Show').show();
            $('#toggle4 #TX_World_Lab_Top_Section_Hide').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().length > 0) {
                $('#factContainer2').removeClass('initialHide');
                $('#remove2').removeClass('initialHide');
                $('#TX_World_Lab_Bottom_Section_Add_Fact').attr('style', 'display: none;');
                $('#TX_World_Lab_Bottom_Section_Add_Fact3').attr('style', 'display: inline;');

                $('#TX_World_Lab_Bottom_Section_Show_All').removeClass('noBorder');
                $('#TX_World_Lab_Bottom_Section_Show_All').addClass('border');
            } else {
                $('#TX_World_Lab_Bottom_Section_Add_Fact').attr('style', 'display: inline;');
                $('#TX_World_Lab_Bottom_Section_Add_Fact3').attr('style', 'display: none;');
            }

            if ($('#TX_World_Lab_Top_Section_Fact3').html().length > 0) {
                $('#factContainer3').removeClass('initialHide');
                $('#remove2').addClass('initialHide');
                $('#remove3').removeClass('initialHide');
                $('#TX_World_Lab_Bottom_Section_Add_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()) {
        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'));

    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();
    } 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();
    }
};
$('#toggle1').click(function() {
    toggleFactVisibility(1);
    return false;
});
$('#toggle2').click(function() {
    toggleFactVisibility(2);
    return false;
});
$('#toggle3').click(function() {
    toggleFactVisibility(3);
    return false;
});
$('#toggle4').click(function() {
    //toggleFactVisibility(4);
    var isVisible = ($('#toggle4 #TX_World_Lab_Top_Section_Show').is(':visible'));

    if (isVisible) {
        $("#fact4").show();
        $('#toggle4 #TX_World_Lab_Top_Section_Show').hide();
        $('#toggle4 #TX_World_Lab_Top_Section_Hide').show();
    } else {
        $("#fact4").hide();
        $('#toggle4 #TX_World_Lab_Top_Section_Show').show();
        $('#toggle4 #TX_World_Lab_Top_Section_Hide').hide();
    }

    return false;
});


// group toggle functions
$('#TX_World_Lab_Bottom_Section_Show_All').click(function() {
    $("#fact1").show();
    $("#fact2").show();
    $("#fact3").show();
    $("#fact4").show();

    $('#toggle1 #TX_World_Lab_Bottom_Section_Fact_Show').hide();
    $('#toggle1 #TX_World_Lab_Bottom_Section_Fact_Hide').show();
    $('#toggle2 #TX_World_Lab_Bottom_Section_Fact2_Show').hide();
    $('#toggle2 #TX_World_Lab_Bottom_Section_Fact2_Hide').show();
    $('#toggle3 #TX_World_Lab_Bottom_Section_Fact3_Show').hide();
    $('#toggle3 #TX_World_Lab_Bottom_Section_Fact3_Hide').show();
    $('#toggle4 #TX_World_Lab_Top_Section_Show').hide();
    $('#toggle4 #TX_World_Lab_Top_Section_Hide').show();

    return false;
});
$('#TX_World_Lab_Bottom_Section_Hide_All').click(function() {
    $("#fact1").hide();
    $("#fact2").hide();
    $("#fact3").hide();
    $("#fact4").hide();

    $('#toggle1 #TX_World_Lab_Bottom_Section_Fact_Show').show();
    $('#toggle1 #TX_World_Lab_Bottom_Section_Fact_Hide').hide();
    $('#toggle2 #TX_World_Lab_Bottom_Section_Fact2_Show').show();
    $('#toggle2 #TX_World_Lab_Bottom_Section_Fact2_Hide').hide();
    $('#toggle3 #TX_World_Lab_Bottom_Section_Fact3_Show').show();
    $('#toggle3 #TX_World_Lab_Bottom_Section_Fact3_Hide').hide();
    $('#toggle4 #TX_World_Lab_Top_Section_Show').show();
    $('#toggle4 #TX_World_Lab_Top_Section_Hide').hide();

    return false;
});

// add a new fact
$('#TX_World_Lab_Bottom_Section_Add_Fact').click(function() {
    $('#factContainer2').removeClass('initialHide');

    $('#TX_World_Lab_Bottom_Section_Add_Fact').hide();
    //$('#TX_World_Lab_Bottom_Section_Add_Fact3').show();
    $('#TX_World_Lab_Bottom_Section_Add_Fact3').show();
    $("#fact2").hide();

    $("#fact2").slideToggle("slow");
    $('#toggle2 #TX_World_Lab_Bottom_Section_Fact2_Show').hide();
    $('#toggle2 #TX_World_Lab_Bottom_Section_Fact2_Hide').show();

    $('#remove2').removeClass('initialHide');

    return false;
});

$('#TX_World_Lab_Bottom_Section_Add_Fact3').click(function() {
    $('#factContainer3').removeClass('initialHide');
    $('#TX_World_Lab_Bottom_Section_Add_Fact3').hide();
    $("#fact3").hide();

    $("#fact3").slideToggle("slow");
    $('#toggle3 #TX_World_Lab_Bottom_Section_Fact3_Show').hide();
    $('#toggle3 #TX_World_Lab_Bottom_Section_Fact3_Hide').show();

    $('#remove2').addClass('initialHide');
    $('#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');

    /*if ($('#toggle2').html() == "[-]") {$("#fact2").slideToggle("slow");$('#toggle2').html("[+]");}*/
    $("#fact2").hide();

    $('#toggle2 #TX_World_Lab_Bottom_Section_Fact2_Show').show();
    $('#toggle2 #TX_World_Lab_Bottom_Section_Fact2_Hide').hide();

    $('#remove2').addClass('initialHide');

    // remove fact 2, show add fact 2 button.
    $('#TX_World_Lab_Bottom_Section_Add_Fact').show();  //show add fact 2 button
    $('#TX_World_Lab_Bottom_Section_Add_Fact3').hide(); //hide add fact 3 button

    return false;
});
$("#remove3").click(function() {
    $('#factContainer3').addClass('initialHide');

    /*if ($('#toggle3').html() == "[-]") {$("#fact3").slideToggle("slow");$('#toggle3').html("[+]");}*/

    $("#fact3").hide();
    $('#toggle3 #TX_World_Lab_Bottom_Section_Fact3_Show').show();
    $('#toggle3 #TX_World_Lab_Bottom_Section_Fact3_Hide').hide();

    $('#remove3').addClass('initialHide');
    $('#remove2').removeClass('initialHide');

    // remove fact 3, show add fact 3 button.
    $('#TX_World_Lab_Bottom_Section_Add_Fact').hide(); //hide add fact 2 button
    $('#TX_World_Lab_Bottom_Section_Add_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;
  }
}




