/* START OF FILE - ..\oatPivot\oat_loader.src.js - */
/*
 *  $Id: loader.js,v 1.29 2008/03/20 09:48:02 source Exp $
 *
 *  This file is part of the OpenLink Software Ajax Toolkit (OAT) project.
 *
 *  Copyright (C) 2005-2007 OpenLink Software
 *
 *  See LICENSE file for details.
 */

//if (OAT.checkInternetExplorerVersion()){
if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {

	window.OAT = {};

	var uR = "";
	for (var i = 0; i < jQuery('script').length; i++) {
		var js_url = jQuery('script')[i].src
		if (js_url.indexOf("gxpivotjs") > 0) {
			uR = js_url
			break;
		}
	}

	OAT.rP = uR.substring(0, uR.indexOf("QueryViewer/oatPivot"));


	//load japanese lenguage character images files
	if ((gx.languageCode == "jap") || (gx.languageCode == "jpn") || (gx.languageCode == "jp") || (gx.languageCode == "ja") || (gx.languageCode == "jpx")
		|| (gx.languageCode == "ain") || (gx.languageCode == "jpns") || (gx.languageCode == "ams") || (gx.languageCode == 'japanese')
		|| (gx.languageCode == "JAP") || (gx.languageCode == "JP") || (gx.languageCode == "JA") || (gx.languageCode == "JPN")
		|| (gx.languageCode == "ja-JP") || (gx.languageCode == "ja_JP") || (gx.languageCode == "jp")) {




		var b = gx.util.resourceUrl(OAT.rP + 'QueryViewer/oatPivot/downloadify/' + 'jsPDF_japanese.js', true);


		var d = document.getElementsByTagName("head")[0] || document.documentElement;
		var s = d.getElementsByTagName("script");
		var prevLoad = false;
		for (var i = 0; s.length > i; i++) {
			if (s[i].src == b) {
				prevLoad = true;
			}
		}
		if (!prevLoad) {
			var e = document.createElement("script");
			e.type = "text/javascript";
			e.src = b;
			e.onerror = function () {
				var e = document.createElement("script");
				e.type = "text/javascript";
				e.src = gx.util.resourceUrl(OAT.rP + 'QueryViewer/oatPivot/downloadify/' + 'jsPDF_japanese.src.js', true);
				var d = document.getElementsByTagName("head")[0] || document.documentElement;
				d.insertBefore(e, d.lastChild);
			};
			e.onreadystatechange = function () {
				var document = this.readyState;
				if (document === "loaded" || document === "complete") {
					e.onreadystatechange = null;
				}
			};
			d.insertBefore(e, d.lastChild);
		}
	}
	/*
		OAT.Loader.preInit(callback) - do something when everything is loaded
		OAT.Loader.loadFeatures(features,callback) - do something when features are loaded
		OAT.Loader.loadedLibs = ["ajax2","window",...]
		
		Contains: 
		* OAT
		* OAT.Preferences
		* OAT.Dom
		* OAT.Event
		* OAT.Style
		* OAT.Browser
		* OAT.Loader
		* OAT.Files
		* OAT.Dependencies
		* OAT.MSG
		* OAT.Debug
	*/
	var featureList = ["pivot", "grid", "statistics"];
	/* global namespace */


	OAT.Preferences = {
		showAjax: 1, /* show Ajax window even if not explicitly requested by application? */
		useCursors: 1, /* scrollable cursors */
		windowTypeOverride: 0, /* do not guess window type */
		xsltPath: "../xslt/",
		//imagePath: "../images/",
		imagePath: gx.util.resourceUrl(OAT.rP + 'QueryViewer/oatPivot/images/', true),
		//stylePath: "../styles/",
		stylePath: gx.util.resourceUrl(OAT.rP + 'QueryViewer/oatPivot/css/', true),
		version: "19.03.2008",
		httpError: 1, /* show http errors */
		allowDefaultResize: 1,
		allowDefaultDrag: 1
	}

	OAT.$ = function (something) {
		if (typeof (something) == "string") {
			var elm = document.getElementById(something);
		} else {
			var elm = something;
		}
		if (something instanceof Array) {
			var elm = [];
			for (var i = 0; i < something.length; i++) { elm.push(OAT.$(something[i])); }
		}
		if (!elm) return false;
		return elm;
	}

	OAT.$$ = function (className, root) {
		var e = root || document;
		var elms = e.getElementsByTagName("*");
		var matches = [];

		if (OAT.Dom.isClass(e, className)) { matches.push(e); }
		for (var i = 0; i < elms.length; i++) {
			if (OAT.Dom.isClass(elms[i], className)) { matches.push(elms[i]); }
		}
		return matches;
	}

	OAT.$v = function (something) {
		var e = OAT.$(something);
		if (!e) return false;
		if (!("value" in e)) return false;
		return e.value;
	}


	/* several helpful prototypes */
	Array.prototype.findIndex = function (str) {
		for (var i = 0; i < this.length; i++) if (this[i] == str) { return i; }
		return -1;
	}

	String.prototype.trimpivot = function () {
		var result = this.match(/^ *(.*?) *$/);
		return (result ? result[1] : this);
	}


	OAT.addTextNode = function (node, text) {
		var txtNode = document.createTextNode(text)
		var nodeJ = jQuery('<span id="span_txt_pivot"></span>')[0]
		nodeJ.appendChild(txtNode)
		node.appendChild(nodeJ)
	}
	
	
	OAT.addImageNode = function(parent, icon_name, style, id)
	{
		var icon = document.createElement("i");
		if (id!=undefined){
			icon.setAttribute("id", id);
		}
		icon.setAttribute("class", "material-icons");
		icon.setAttribute("style", style)
		icon.textContent = icon_name;  
		parent.appendChild(icon);	
	}

	OAT.replaceTextNode = function (node, text) {
		while (node.firstChild) {
			node.removeChild(node.firstChild);
		}
		var txtNode = document.createTextNode(text)
		node.appendChild(txtNode)
	}

	OAT.removeIconFont = function (text) {
		return text.replace(/arrow_drop_up/g,'').replace(/arrow_drop_down/g,'').replace(/indeterminate_check_box/g,'').replace(/add_box/g,'');
	}

	OAT.ApplyPictureValue = function (value, type, defaultPicture, picture) { /* function responsible for set pictures */
		if (value == "#NuN#") {
			var defaultNull = defaultPicture.getAttribute("textForNullValues");
			if (defaultNull == "") {
				return "\u00A0";
			}
			if (defaultNull != undefined) {
				return defaultNull;
			}
			return "\u00A0";

		}
		
			var decimalSeparator = (defaultPicture.getAttribute("decimalSeparator") != undefined && defaultPicture.getAttribute("decimalSeparator") != null) ? defaultPicture.getAttribute("decimalSeparator") : ".";
			var decimalPlaces = (defaultPicture.getAttribute("decimalPlaces") != undefined && defaultPicture.getAttribute("decimalPlaces") != null) ? defaultPicture.getAttribute("decimalPlaces") : 2;
			var thseparator = defaultPicture.getAttribute("thousandsSeparator")
			var defaultdate = defaultPicture.getAttribute("dateFormat")
			var newValue = value;
			var lastCharacter = false;

			var hasprefix = false;
			var prefix = "";
			if ((type == "integer") || (type == "real")) {
				if ((picture != undefined) || (picture != null)) {
					if ((picture[0] != "Z") || (picture[0] != "9") || (picture[0] != ",") || (picture[0] != ".")) {
						hasprefix = true;
						var index = 0;
						while ((picture.length > index) && (picture[index] != "Z") && (picture[index] != "9") && (picture[index] != ",") && (picture[index] != ".")) {
							index++;
						}
						prefix = picture.substring(0, index);
						picture = picture.substring(index);
					}
				}
			}

			var hassufix = false;
			var sufix = "";
			if ((type == "integer") || (type == "real")) {
				if ((picture != undefined) || (picture != null)) {
					if ((picture[picture.length - 1] != "Z") || (picture[picture.length - 1] != "9") || (picture[picture.length - 1] != ",") || (picture[picture.length - 1] != ".")) {
						hassufix = true;
						var index = picture.length - 1;
						while ((index > -1) && (picture[index] != "Z") && (picture[index] != "9") && (picture[index] != ",") && (picture[index] != ".")) {
							index--;
						}
						sufix = picture.substring(index + 1);
						picture = picture.substring(0, index + 1);
					}
				}
			}

			switch (type) {
				case "integer":
					decimalPlaces = 0;
				case "real":
					
					if ((picture != undefined) && (picture != "")) {
						
						var newValue = qv.util.formatNumber(parseFloat(value), decimalPlaces, picture, false);
						
					} else {
						var valueSplit = value.split(".");
						var useSeparator = true;
						if ((picture == "") && (type == "integer")) {
							useSeparator = false;
						}
						
						if (type == "real") {
							newValue = parseFloat(value).toFixed(2);
							valueSplit = newValue.split(".");
						}
					
						newValue = valueSplit[0];
					


						var z_pos = -1;
						if ((picture != undefined) && (picture != "")) {
							var picteSplit = picture.split(".");
							if (picteSplit.length > 1)
								z_pos = picteSplit[1].indexOf("Z");
						}

						if (valueSplit[1] == null) {
							if (useSeparator) {
								var numoblig = decimalPlaces;
								if (z_pos != -1) {
									numoblig = z_pos;
								}
								if (numoblig > 0) {
									newValue = newValue + decimalSeparator;
									for (var i = 0; i < numoblig; i++) {
										newValue = newValue + "0";
									}
								}
							}
						} else {
							if (useSeparator) {

								if (z_pos === -1) { //only 9s in decimal picture
									if (valueSplit[1].length < decimalPlaces) {
										newValue = newValue + decimalSeparator + valueSplit[1];
										for (var i = 0; i < decimalPlaces - valueSplit[1].length; i++) {
											newValue = newValue + "0";
										}

									} else {
										if (valueSplit[1].length > decimalPlaces) {
											var newArray = "";
											for (var i = 0; i < decimalPlaces; i++) {
												newArray = newArray + valueSplit[1].charAt(i);
											}
											newValue = newValue + decimalSeparator + newArray;
										} else {
											newValue = newValue + decimalSeparator + valueSplit[1];
										}
									}
								} else {
									var numberoblig = z_pos;
									if (valueSplit[1].length < decimalPlaces) {
										if ((valueSplit[1].length > 0) || (numberoblig > 0)) {
											newValue = newValue + decimalSeparator + valueSplit[1];
											for (var i = 0; i < numberoblig - valueSplit[1].length; i++) {
												newValue = newValue + "0";
											}
										}
									} else { //idem sin Z
										if (valueSplit[1].length > decimalPlaces) {
											var newArray = "";
											for (var i = 0; i < decimalPlaces; i++) {
												newArray = newArray + valueSplit[1].charAt(i);
											}
											newValue = newValue + decimalSeparator + newArray;
										} else {
											newValue = newValue + decimalSeparator + valueSplit[1];
										}
									}
								}

							}
						}

					}
					break;
				case "date":
					if (value == "") return "";
					if (picture === "") {
						var dates = value.split("-");
						var newValue = value;
						if ((defaultdate != undefined) && (defaultdate != null)) {//if default picture
							pict = defaultdate.split("");
							newValue = "";
							for (var i = 0; i <= 2; i++) {
								if (pict[i] === "M")
									newValue = newValue + dates[1];
								if (pict[i] === "D")
									newValue = newValue + dates[2];
								if (pict[i] === "Y")
									newValue = newValue + dates[0];
								if (i != 2)
									newValue = newValue + "/";
							}
						} else {
							newValue = dates[1] + "/" + dates[2] + "/" + dates[0];
						}
					} else {

						var valueSplit = value.split("-");
						newValue = "";
						if (picture == "99/99/9999") {
							if (valueSplit[0].length == 4) {
								if ((defaultdate == undefined) || (defaultdate == null) || (defaultdate == "MDY")) {
									newValue = valueSplit[1] + "/" + valueSplit[2] + "/" + valueSplit[0];
								} else if ((defaultdate != undefined) && (defaultdate == "YMD")) { //for japanese
									newValue = valueSplit[0] + "/" + valueSplit[1] + "/" + valueSplit[2];
								} else { //DMY
									newValue = valueSplit[2] + "/" + valueSplit[1] + "/" + valueSplit[0];
								}
							} else {
								newValue = value;
								while (newValue.indexOf("-") != -1) {
									newValue.replace("-", "/");
								}
							}
						} else

							if (picture == "99/99/99") {
								if (valueSplit[0].length == 4) {
									valueSplit[0] = valueSplit[0].substr(valueSplit[0].length - 2, 2);
								}
								if ((defaultdate == undefined) || (defaultdate == null) || (defaultdate == "MDY")) {
									newValue = valueSplit[1] + "/" + valueSplit[2] + "/" + valueSplit[0];
								} else if ((defaultdate != undefined) && (defaultdate == "YMD")) { //for japanese
									newValue = valueSplit[0] + "/" + valueSplit[1] + "/" + valueSplit[2];
								} else { //DMY
									newValue = valueSplit[2] + "/" + valueSplit[1] + "/" + valueSplit[0];
								}
							} else if (picture == "9999/99/99") {
								if ((defaultdate == undefined) || (defaultdate == null) || (defaultdate == "MDY")) {
									newValue = valueSplit[1] + "/" + valueSplit[2] + "/" + valueSplit[0];
								} else if ((defaultdate != undefined) && (defaultdate == "YMD")) { //for japanese
									newValue = valueSplit[0] + "/" + valueSplit[1] + "/" + valueSplit[2];
								} else { //DMY
									newValue = valueSplit[2] + "/" + valueSplit[1] + "/" + valueSplit[0];
								}
							}
							else {
								if (valueSplit[0].length == 4) {
									valueSplit[0] = valueSplit[0].substr(valueSplit[0].length - 2, 2);
								}
								if ((defaultdate == undefined) || (defaultdate == null) || (defaultdate == "MDY")) {
									newValue = valueSplit[1] + "/" + valueSplit[2] + "/" + valueSplit[0];
								} else if ((defaultdate != undefined) && (defaultdate == "YMD")) { //for japanese
									newValue = valueSplit[0] + "/" + valueSplit[1] + "/" + valueSplit[2];
								} else { //DMY
									newValue = valueSplit[2] + "/" + valueSplit[1] + "/" + valueSplit[0];
								}
							}



					}

					break; // End execution
				case "datetime":
					if (value == "") return "";
					var dividevalue = value.split("T");//separate date from hour
					if (value.indexOf("T") === -1) {
						dividevalue = value.split(" ");
					}
					//formatting date
					if (picture === "") {
						var dates = dividevalue[0].split("-");
						var newValue = value;
						if ((defaultdate != undefined) && (defaultdate != null)) {//if default picture
							pict = defaultdate.split("");
							newValue = "";
							for (var i = 0; i <= 2; i++) {
								if (pict[i] === "M")
									newValue = newValue + dates[1];
								if (pict[i] === "D")
									newValue = newValue + dates[2];
								if (pict[i] === "Y")
									newValue = newValue + dates[0];
								if (i != 2)
									newValue = newValue + "/";
							}
						} else {
							newValue = dates[1] + "/" + dates[2] + "/" + dates[0];
						}
					} else {
						var dividepicture = picture.split(" ");
						var valueSplit = dividevalue[0].split("-");
						newValue = "";
						if (dividepicture[0] == "99/99/9999") {
							if (valueSplit[0].length == 4) {
								if ((defaultdate == undefined) || (defaultdate == null) || (defaultdate == "MDY")) {
									newValue = valueSplit[1] + "/" + valueSplit[2] + "/" + valueSplit[0];
								} else if ((defaultdate != undefined) && (defaultdate == "YMD")) { //for japanese
									newValue = valueSplit[0] + "/" + valueSplit[1] + "/" + valueSplit[2];
								} else { //DMY
									newValue = valueSplit[2] + "/" + valueSplit[1] + "/" + valueSplit[0];
								}
							} else {
								newValue = value;
								while (newValue.indexOf("-") != -1) {
									newValue.replace("-", "/");
								}
							}
						} else

							if (dividepicture[0] == "99/99/99") {
								if (valueSplit[0].length == 4) {
									valueSplit[0] = valueSplit[0].substr(valueSplit[0].length - 2, 2);
								}
								if ((defaultdate == undefined) || (defaultdate == null) || (defaultdate == "MDY")) {
									newValue = valueSplit[1] + "/" + valueSplit[2] + "/" + valueSplit[0];
								} else if ((defaultdate != undefined) && (defaultdate == "YMD")) { //for japanese
									newValue = valueSplit[0] + "/" + valueSplit[1] + "/" + valueSplit[2];
								} else { //DMY
									newValue = valueSplit[2] + "/" + valueSplit[1] + "/" + valueSplit[0];
								}
							} else
								if (dividepicture[0] == "9999/99/99")
									if ((defaultdate == undefined) || (defaultdate == null) || (defaultdate == "MDY")) {
										newValue = valueSplit[1] + "/" + valueSplit[2] + "/" + valueSplit[0];
									} else if ((defaultdate != undefined) && (defaultdate == "YMD")) { //for japanese
										newValue = valueSplit[0] + "/" + valueSplit[1] + "/" + valueSplit[2];
									} else { //DMY
										newValue = valueSplit[2] + "/" + valueSplit[1] + "/" + valueSplit[0];
									}
								else {

									newValue = "";
								}
					}

					//formating hour

					if (picture === "") {
						if (dividevalue.length > 1) {
							var hourandms = dividevalue[1].split(".");

							newValue = newValue + " " + hourandms[0]
						}
					} else {
						var dividepicture = picture.split(" ");
						if ((picture.split(" ").length < 2) && (dividepicture[0] != "99/99/9999") && (dividepicture[0] != "9999/99/99") && (dividepicture[0] != "99/99/99")) {
							dividepicture.push(picture)
						}

						if (dividepicture.length > 1) {
							var digits;
							if (dividevalue.length > 1) {
								var hourandms = dividevalue[1].split(".");

								digits = hourandms[0].split(":");

								if (digits.length < 2) {
									digits[1] = "00";
									digits[2] = "00";
								}
								if (digits.length < 3) {
									digits[2] = "00";
								}
								if (hourandms.length < 2) {
									digits[3] = "000"
								} else {
									digits[3] = hourandms[1]
								}
							} else {
								digits = new Array(3)
								digits[0] = "00";
								digits[1] = "00";
								digits[2] = "00";
								digits[3] = "000";
							}



							switch (dividepicture[1]) {
								case "99":
									newValue = newValue + " " + digits[0];
									break;
								case "99:99":
									newValue = newValue + " " + digits[0] + ":" + digits[1];
									break;
								case "99:99:99":
									newValue = newValue + " " + digits[0] + ":" + digits[1] + ":" + digits[2];
									break;
								case "99:99:99.999":
									newValue = newValue + " " + digits[0] + ":" + digits[1] + ":" + digits[2] + "." + digits[3];
									break
								default:
									newValue = newValue + " " + digits[0] + ":" + digits[1] + ":" + digits[2];
							}

						}
					}
					break;
				case "character":
					newValue = OAT.Dom.fromSafeXML(value);
					if (picture == "@!") {
						newValue = value.toUpperCase();
					}
					break;
				default:

			}

			if (hasprefix) {
				newValue = prefix + newValue;
			}
			if (hassufix) {
				newValue = newValue + sufix;
			}

			return newValue;
		}
	
	
	//Allow Selection methods 
	OAT.SetSelectedNodeBackgroundColor = function(node, color, $container){
		OAT.ClearSelectedNodes($container)
		OAT.SetNodeBackgroundColor(node, color);
	}
	
	OAT.ClearSelectedNodes = function($container) {
		/*$container.find(".gx-qv-selected-element").each(function (index, value) {
			var previousColor = jQuery(value).attr("previousBackgroundColor");
			jQuery(value).css({backgroundColor: previousColor});
		});*/
		
		$container.find(".gx-qv-selected-element").removeClass("gx-qv-selected-element");
	}
	
	OAT.SetNodeBackgroundColor = function(node, color){
		if (!jQuery(node).hasClass("gx-qv-selected-element")){
			//var backgroundColor = jQuery(node).css("background-color");
			//jQuery(node).attr("previousBackgroundColor", backgroundColor);
		
			//jQuery(node).css({backgroundColor: color});
			jQuery(node).addClass("gx-qv-selected-element");
		}
	}
	
	OAT.IsNodeSelected = function(node){
		return jQuery(node).hasClass("gx-qv-selected-element")
	}
	
	OAT.SelectAllRow = function(row, color, avoid){
		for (var cell = 0; cell < row.children.length; cell++){
			if ((avoid == undefined) || (avoid != cell))
				OAT.SetNodeBackgroundColor(row.children[cell], color)
		}
	}
	//picture methods

	OAT.Dom = { /* DOM common object */
		create: function (tagName, styleObj, className) {
			var elm = document.createElement(tagName);
			if (styleObj) {
				for (prop in styleObj) { elm.style[prop] = styleObj[prop]; }
			}
			if (className) { elm.className = className; }
			return elm;
		},

		createNS: function (ns, tagName) {
			if (document.createElementNS) {
				var elm = document.createElementNS(ns, tagName);
			} else {
				var elm = document.createElement(tagName);
				elm.setAttribute("xmlns", ns);
			}
			return elm;
		},

		text: function (text) {
			var elm = document.createTextNode(text);
			return elm;
		},

		button: function (label) {
			var b = OAT.Dom.create("input");
			b.type = "button";
			b.value = label;
			return b;
		},

		radio: function (name) {
			if (OAT.Browser.isIE) {
				var elm = document.createElement('<input type="radio" name="' + name + '" />');
				return elm;
			} else {
				var elm = OAT.Dom.create("input");
				elm.name = name;
				elm.type = "radio";
				return elm;
			}
		},

		image: function (src, srcBlank, w, h) {
			w = (w ? w + 'px' : 'auto');
			h = (h ? h + 'px' : 'auto');
			var elm = OAT.Dom.create("img", { width: w, height: h });
			OAT.Dom.imageSrc(elm, src, srcBlank);
			return elm;
		},

		imageSrc: function (element, src, srcBlank) {
			var elm = OAT.$(element);
			var png = !!src.toLowerCase().match(/png$/);
			elm.src = src;
		},
		option: function (name, value, parent) {
			var opt = OAT.Dom.create("option");
			OAT.addTextNode(opt, name)
			opt.value = value;
			if (parent) { OAT.$(parent).appendChild(opt); }
			return opt;
		},
		append: function () {
			for (var i = 0; i < arguments.length; i++) {
				var arr = arguments[i];
				if (!(arr instanceof Array)) { continue; }
				if (arr.length < 2) { continue; }
				var parent = OAT.$(arr[0]);
				for (var j = 1; j < arr.length; j++) {
					var children = arr[j];
					if (!(children instanceof Array)) { children = [children]; }
					for (var k = 0; k < children.length; k++) {
						var child = children[k];
						parent.appendChild(OAT.$(child));
					}
				}
			}
		},

		hide: function (element) {
			if (arguments.length > 1) {
				for (var i = 0; i < arguments.length; i++) { OAT.Dom.hide(arguments[i]); }
				return;
			}
			if (element instanceof Array) {
				for (var i = 0; i < element.length; i++) { OAT.Dom.hide(element[i]); }
				return;
			}
			var elm = OAT.$(element);
			if (!elm) { return; }
			/* ie input hack */
			var inputs_ = elm.getElementsByTagName("input");
			var inputs = [];
			for (var i = 0; i < inputs_.length; i++) { inputs.push(inputs_[i]); }
			if (elm.tagName.toLowerCase() == "input") { inputs.push(elm); }
			for (var i = 0; i < inputs.length; i++) {
				var inp = inputs[i];
				if (inp.type == "radio" || inp.type == "checkbox") {
					if (!inp.__checked) { inp.__checked = (inp.checked ? "1" : "0"); }
				}
			}
			elm.style.display = "none";
		},

		show: function (element) {
			if (arguments.length > 1) {
				for (var i = 0; i < arguments.length; i++) { OAT.Dom.show(arguments[i]); }
				return;
			}
			if (element instanceof Array) {
				for (var i = 0; i < element.length; i++) { OAT.Dom.show(element[i]); }
				return;
			}
			var elm = OAT.$(element);
			if (!elm) { return; }
			elm.style.display = "";
			/* ie input hack */
			var inputs_ = elm.getElementsByTagName("input");
			var inputs = [];
			for (var i = 0; i < inputs_.length; i++) { inputs.push(inputs_[i]); }
			if (elm.tagName.toLowerCase() == "input") { inputs.push(elm); }
			for (var i = 0; i < inputs.length; i++) {
				var inp = inputs[i];
				if (inp.type == "radio" || inp.type == "checkbox") {
					if (inp["__checked"] && inp.__checked === "1") { inp.checked = true; }
					if (inp["__checked"] && inp.__checked === "0") { inp.checked = false; }
					inp.__checked = false;
				}
			}
		},

		clear: function (element) {
			var elm = OAT.$(element);
			while (elm.firstChild) { elm.removeChild(elm.firstChild); }
		},

		unlink: function (element) {
			var elm = OAT.$(element);
			if (!elm) { return; }
			if (!elm.parentNode) { return; }
			elm.parentNode.removeChild(elm);
		},

		center: function (element, x, y, reference) {
			var elm = OAT.$(element);
			var p = elm.offsetParent;
			if (reference) { p = reference; }
			if (!p) { return; }
			var par_dims = (p == document.body || p.tagName.toLowerCase() == "html" ? OAT.Dom.getViewport() : OAT.Dom.getWH(p));
			var dims = OAT.Dom.getWH(elm);
			var new_x = Math.round(par_dims[0] / 2 - dims[0] / 2);
			var new_y = Math.round(par_dims[1] / 2 - dims[1] / 2);
			if (new_y < 0) { new_y = 30; }
			var s = OAT.Dom.getScroll();
			if (p == document.body || p.tagName.toLowerCase() == "html") {
				new_x += s[0];
				new_y += s[1];
			}
			if (x) { elm.style.left = new_x + "px"; }
			if (y) { elm.style.top = new_y + "px"; }
		},

		isChild: function (child, parent) {
			var c_elm = OAT.$(child);
			var p_elm = OAT.$(parent);
			/* walk up from the child. if we find parent element, return true */
			var node = c_elm.parentNode;
			do {
				if (!node) { return false; }
				if (node == p_elm) { return true; }
				node = node.parentNode;
			} while (node != document.body && node != document);
			return false;
		},

		isKonqueror: function () { return (navigator.userAgent.match(/konqueror/i) ? true : false); },
		isKHTML: function () { return (navigator.userAgent.match(/khtml/i) ? true : false); },
		isIE: function () { return (document.attachEvent && !document.addEventListener ? true : false); },
		isIE7: function () { return (navigator.userAgent.match(/msie 7/i) ? true : false); },
		isIE6: function () { return (OAT.Dom.isIE() && !OAT.Dom.isIE7()); },
		isGecko: function () { return ((!OAT.Dom.isKHTML() && navigator.userAgent.match(/Gecko/i)) ? true : false); },
		isOpera: function () { return (navigator.userAgent.match(/Opera/) ? true : false); },
		isWebKit: function () { return (navigator.userAgent.match(/AppleWebKit/) ? true : false); },
		isMac: function () { return (navigator.platform.toString().match(/mac/i) ? true : false); },
		isLinux: function () { return (navigator.platform.toString().match(/linux/i) ? true : false); },
		isWindows: function () { return (navigator.userAgent.toString().match(/windows/i) ? true : false); },

		color: function (str) {
			var hex2dec = function (hex) { return parseInt(hex, 16); }
			/* returns [col1,col2,col3] in decimal */
			if (str.match(/#/)) {
				/* hex */
				if (str.length == 4) {
					var tmpstr = "#" + str.charAt(1) + str.charAt(1) + str.charAt(2) + str.charAt(2) + str.charAt(3) + str.charAt(3);
				} else {
					var tmpstr = str;
				}
				var tmp = tmpstr.match(/#(..)(..)(..)/);
				return [hex2dec(tmp[1]), hex2dec(tmp[2]), hex2dec(tmp[3])];
			} else {
				/* decimal */
				var tmp = str.match(/\(([^,]*),([^,]*),([^\)]*)/);
				return [parseInt(tmp[1]), parseInt(tmp[2]), parseInt(tmp[3])];
			}
		},

		isClass: function (something, className) {
			var elm = OAT.$(something);
			if (!elm) { return false; }
			if (className == "*") { return true; }
			if (className == "") { return false; }
			if (!elm.className) { return false; }
			var arr = elm.className.split(" ");
			var index = arr.findIndex(className);
			return (index != -1);
		},

		addClass: function (something, className) {
			var elm = OAT.$(something);
			if (!elm) { return; }
			if (OAT.Dom.isClass(elm, className)) { return; }
			var arr = elm.className.split(" ");
			arr.push(className);
			if (arr[0] == "") { arr.splice(0, 1); }
			elm.className = arr.join(" ");
		},

		setIdPropertyValue: function (something, value) {
			var elm = OAT.$(something);
			if (!elm) { return; }
			elm.id = value;
		},

		removeClass: function (something, className) {
			var elm = OAT.$(something);
			if (!elm) { return; }
			if (!OAT.Dom.isClass(elm, className)) { return; } /* cannot remove non-existing class */
			if (className == "*") { elm.className = ""; } /* should not occur */
			var arr = elm.className.split(" ");
			var index = arr.findIndex(className);
			if (index == -1) { return; } /* should NOT occur! */
			arr.splice(index, 1);
			elm.className = arr.join(" ");
		},

		getViewport: function () {
			if (OAT.Browser.isWebKit) {
				return [window.innerWidth, window.innerHeight];
			}
			if (OAT.Browser.isOpera || document.compatMode == "BackCompat") {
				return [document.body.clientWidth, document.body.clientHeight];
			} else {
				return [document.documentElement.clientWidth, document.documentElement.clientHeight];
			}
		},

		position: function (something) {
			var elm = OAT.$(something);
			var parent = elm.offsetParent;
			if (elm == document.body || elm == document || !parent) { return OAT.Dom.getLT(elm); }
			var parent_coords = OAT.Dom.position(parent);
			var c = OAT.Dom.getLT(elm);
			/*
			var x = elm.offsetLeft - elm.scrollLeft + parent_coords[0];
			var y = elm.offsetTop - elm.scrollTop + parent_coords[1];
			*/

			/*
			this is interesting: Opera with no scrolling reports scrollLeft/Top equal to offsetLeft/Top for <input> elements
			*/
			var x = c[0];
			var y = c[1];
			if (!OAT.Browser.isOpera || elm.scrollTop != elm.offsetTop || elm.scrollLeft != elm.offsetLeft) {
				x -= elm.scrollLeft;
				y -= elm.scrollTop;
			}

			if (OAT.Browser.isWebKit && parent == document.body && OAT.Dom.style(elm, "position") == "absolute") { return [x, y]; }

			x += parent_coords[0];
			y += parent_coords[1];
			return [x, y];
		},

		getLT: function (something) {
			var elm = OAT.$(something);
			var curr_x, curr_y;
			if (elm.style.left && elm.style.position != "relative") {
				curr_x = parseInt(elm.style.left);
			} else {
				curr_x = elm.offsetLeft;
			}
			if (elm.style.top && elm.style.position != "relative") {
				curr_y = parseInt(elm.style.top);
			} else {
				curr_y = elm.offsetTop;
			}
			return [curr_x, curr_y];
		},

		getWH: function (something) {
			/*
			This is tricky: we need to measure current element's width & height.
			If this property was already set (thus available directly through elm.style),
			everything is ok.
			If nothing was set yet:
			* IE stores this information in offsetWidth and offsetHeight
			* Gecko doesn't count borders into offsetWidth and offsetHeight
			Thus, we need another means for counting real dimensions.
			*/
			var curr_w, curr_h;
			var elm = OAT.$(something);
			if (elm.style.width && !elm.style.width.match(/%/) && elm.style.width != "auto") {
				curr_w = parseInt(elm.style.width);
			} else if (OAT.Style.get(elm, "width") && !OAT.Browser.isIE) {
				curr_w = Math.round(parseFloat(OAT.Style.get(elm, "width")));
			} else {
				curr_w = elm.offsetWidth;
				if (elm.tagName.toLowerCase() == "input") { curr_w += 5; }
			}

			if (elm.style.height && !elm.style.height.match(/%/) && elm.style.height != "auto") {
				curr_h = parseInt(elm.style.height);
			} else if (OAT.Style.get(elm, "height") && !OAT.Browser.isIE) {
				curr_h = Math.round(parseFloat(OAT.Style.get(elm, "height")));
			} else {
				curr_h = elm.offsetHeight;
				if (elm.tagName.toLowerCase() == "input") { curr_h += 5; }
			}

			/* one more bonus - if we are getting height of document.body, take window size */
			if (elm == document.body) {
				curr_h = (OAT.Browser.isIE ? document.body.clientHeight : window.innerHeight);
			}
			return [curr_w, curr_h];
		},

		moveBy: function (element, dx, dy) {
			var curr_x, curr_y;
			var elm = OAT.$(element);
			/*
			If the element is not anchored to left top corner, strange things will happen during resizing;
			therefore, we need to make sure it is anchored properly.
			*/
			if (OAT.Dom.style(elm, "position") == "absolute") {
				if (!elm.style.left) {
					elm.style.left = elm.offsetLeft + "px";
					elm.style.right = "";
				}
				if (!elm.style.top) {
					elm.style.top = elm.offsetTop + "px";
					elm.style.bottom = "";
				}
			}
			var tmp = OAT.Dom.getLT(elm);
			curr_x = tmp[0];
			curr_y = tmp[1];
			var x = curr_x + dx;
			var y = curr_y + dy;
			elm.style.left = x + "px";
			elm.style.top = y + "px";
		},

		resizeBy: function (element, dx, dy) {
			var curr_w, curr_h;
			var elm = OAT.$(element);
			/*
			If the element is not anchored to left top corner, strange things will happen during resizing;
			therefore, we need to make sure it is anchored properly.
			*/
			if (OAT.Dom.style(elm, "position") == "absolute" && dx) {
				if (!elm.style.left) {
					elm.style.left = elm.offsetLeft + "px";
					elm.style.right = "";
				}
				if (!elm.style.top && dy) {
					elm.style.top = elm.offsetTop + "px";
					elm.style.bottom = "";
				}
			}
			var tmp = OAT.Dom.getWH(elm);
			curr_w = tmp[0];
			curr_h = tmp[1];
			var w = curr_w + dx;
			var h = curr_h + dy;
			if (dx) { elm.style.width = w + "px"; }
			if (dy) { elm.style.height = h + "px"; }
		},

		decodeImage: function (data) {
			var decoded = OAT.Crypto.base64d(data);
			var mime = "image/";
			switch (decoded.charAt(1)) {
				case "I": mime += "gif"; break;
				case "P": mime += "png"; break;
				case "M": mime += "bmp"; break;
				default: mime += "jpeg"; break;

			}
			var src = "data:" + mime + ";base64," + data;
			return src;
		},

		removeSelection: function () {
			var selObj = false;
			if (document.getSelection && !OAT.Browser.isGecko) { selObj = document.getSelection(); }
			if (window.getSelection) { selObj = window.getSelection(); }
			if (document.selection) { selObj = document.selection; }
			if (selObj) {
				if (selObj.empty) { selObj.empty(); }
				if (selObj.removeAllRanges) { selObj.removeAllRanges(); }
			}
		},

		getScroll: function () {
			var l = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
			var t = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
			return [l, t];
		},

		getFreeSpace: function (x, y) {
			var scroll = OAT.Dom.getScroll();
			var port = OAT.Dom.getViewport();
			var spaceLeft = x - scroll[0];
			var spaceRight = port[0] - x + scroll[0];
			var spaceTop = y - scroll[1];
			var spaceBottom = port[1] - y + scroll[1];
			var left = (spaceLeft > spaceRight);
			var top = (spaceTop > spaceBottom);
			return [left, top];

		},

		toSafeXML: function (str) {
			if (typeof (str) != "string") { return str; }
			return str.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;");
		},

		fromSafeXML: function (str) {
			return str.replace(/&amp;/g, "&").replace(/&gt;/g, ">").replace(/&lt;/g, "<");
		},

		uriParams: function () {
			var result = {};
			var s = location.search;
			if (s.length > 1) { s = s.substring(1); }
			if (!s) { return result; }
			var parts = s.split("&");
			for (var i = 0; i < parts.length; i++) {
				var part = parts[i];
				if (!part) { continue; }
				var index = part.indexOf("=");
				if (index == -1) { result[decodeURIComponent(part)] = ""; continue; } /* not a pair */

				var key = part.substring(0, index);
				var val = part.substring(index + 1);
				key = decodeURIComponent(key);
				val = decodeURIComponent(val);

				var r = false;
				if ((r = key.match(/(.*)\[\]$/))) {
					key = r[1];
					if (key in result) {
						result[key].push(val);
					} else {
						result[key] = [val];
					}
				} else {
					result[key] = val;
				}
			}
			return result;
		},

		changeHref: function (elm, newHref) {
			/* opera cannot do this with elements not being part of the page :/ */
			var ok = false;
			var e = OAT.$(elm);
			var node = e;
			while (node.parentNode) {
				node = node.parentNode;
				if (node == document.body) { ok = true; }
			}
			if (ok) {
				e.href = newHref;
			} else if (e.parentNode) {
				var oldParent = e.parentNode;
				var next = e.nextSibling;
				document.body.appendChild(e);
				e.href = newHref;
				OAT.Dom.unlink(e);
				oldParent.insertBefore(e, next);
			} else {
				document.body.appendChild(e);
				e.href = newHref;
				OAT.Dom.unlink(e);
			}
		},

		makePosition: function (elm) {
			var e = OAT.$(elm);
			if (OAT.Dom.style(e, "position") != "absolute") {
				e.style.position = "relative";
			}
		}
	}

	OAT.Style = { /* Style helper */
		include: function (file, relativePath, force) {
			if (!file) return;
			file = relativePath + 'QueryViewer/oatPivot/css/' + file; /*OAT.Preferences.stylePath*/
			if (!force) { /* prevent loading when already loaded */
				var styles = document.getElementsByTagName('link');
				var host = location.protocol + '//' + location.host;
				for (var i = 0; i < styles.length; i++)
					if (file == styles[i].getAttribute('href') || host + file == styles[i].getAttribute('href'))
						return;
			}
			var elm = OAT.Dom.create("link");
			elm.rel = "stylesheet";
			elm.type = "text/css";
			elm.href = file;
			//document.getElementsByTagName("head")[0].appendChild(elm);
			jQuery("head").prepend(elm);
			if (gx.util.browser.isIE()) {
				var reference = "Resources/English/GeneXusXEv2.css";
				for (var i = 0; i <= styles.length - 1; i++) {
					var id = styles[i].getAttribute("id");
					if (id === "gxtheme_css_reference") {
						reference = styles[i].getAttribute("href");
					}
				}
				jQuery("head").prepend(jQuery('<link id="gxtheme_css_reference" rel="stylesheet" type="text/css" href="' + reference + '" />'))
			}
		},

		get: function (elm, property) {
			var element = OAT.$(elm);
			if (document.defaultView && document.defaultView.getComputedStyle) {
				var cs = document.defaultView.getComputedStyle(element, '');
				if (!cs) { return true; }
				return cs[property];
			} else {
				try {
					var out = element.currentStyle[property];
				} catch (e) {
					var out = element.getExpression(property);
				}
				return out;
			}
		},

		background: function (element, src) {
			var elm = OAT.$(element);
			var png = !!src.toLowerCase().match(/png$/);
			if (png && OAT.Browser.isIE) {
				elm.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='crop')";
			} else {
				elm.style.backgroundImage = "url(" + src + ")";
			}
		},

		apply: function (something, obj) {
			var elm = OAT.$(something);
			if (!elm) { return; }
			for (var p in obj) { elm.style[p] = obj[p]; }
		},

		opacity: function (element, opacity) {
			var o = Math.max(opacity, 0);
			var elm = OAT.$(element);
			if (OAT.Browser.isIE) {
				elm.style.filter = "alpha(opacity=" + Math.round(o * 100) + ")";
			} else {
				elm.style.opacity = o;
			}
		}
	}
	OAT.Dom.style = OAT.Style.get; /* backward compatibility */
	OAT.Dom.applyStyle = OAT.Style.apply; /* backward compatibility */

	OAT.Browser = { /* Browser helper */
		isIE: OAT.Dom.isIE(),
		isIE6: OAT.Dom.isIE6(),
		isIE7: OAT.Dom.isIE7(),
		isGecko: OAT.Dom.isGecko(),
		isOpera: OAT.Dom.isOpera(),
		isKonqueror: OAT.Dom.isKonqueror(),
		isKHTML: OAT.Dom.isKHTML(),
		isWebKit: OAT.Dom.isWebKit(),
		isMac: OAT.Dom.isMac(),
		isLinux: OAT.Dom.isLinux(),
		isWindows: OAT.Dom.isWindows()
	}

	OAT.Event = { /* Event helper */
		attach: function (elm, event, callback) {
			var element = OAT.$(elm);
			if (element.addEventListener) {	/* gecko */
				element.addEventListener(event, callback, false);
			} else if (element.attachEvent) { /* ie */
				element.attachEvent("on" + event, callback);
			} else { /* ??? */
				element["on" + event] = callback;
			}
		},
		detach: function (elm, event, callback) {
			var element = OAT.$(elm);
			if (element.removeEventListener) { /* gecko */
				element.removeEventListener(event, callback, false);
			} else if (element.detachEvent) { /* ie */
				element.detachEvent("on" + event, callback);
			} else { /* ??? */
				element["on" + event] = false;
			}
		},
		source: function (event) {
			return (event.target ? event.target : event.srcElement);
		},
		cancel: function (event) {
			event.cancelBubble = true;
			if (event.stopPropagation) { event.stopPropagation(); }
		},
		position: function (event) {
			var scroll = OAT.Dom.getScroll();
			return [event.clientX + scroll[0], event.clientY + scroll[1]];
		},
		prevent: function (event) {
			if (event.preventDefault) { event.preventDefault(); }
			if (gx.util.browser.isIE()) {
				event.returnValue = false;
			}
		}
	}
	OAT.Dom.attach = OAT.Event.attach;
	OAT.Dom.detach = OAT.Event.detach;
	OAT.Dom.source = OAT.Event.source;
	OAT.Dom.eventPos = OAT.Event.position;
	OAT.Dom.prevent = OAT.Event.prevent;

	OAT.Loader = { /* first part of loader object */
		toolkitPath: false,
		loadOccurred: 0, /* was window.onload fired? */
		openAjax: false, /* OpenAjax.js included? */

		include: function (file) {
			var path = OAT.Loader.toolkitPath || "";
			var value = (typeof (file) == "object" ? file : [file]);
			for (var i = 0; i < value.length; i++) {
				var name = path + value[i];
				var script = document.createElement("script");
				script.src = name;
				document.getElementsByTagName("head")[0].appendChild(script);
			}
		},

		findPath: function () { /* scan for loader.js and OpenAjax.js */
			/*
			var head = document.getElementsByTagName("head")[0];
			var children = head.childNodes;
			for (var i = 0; i < children.length; i++) {
			var s = children[i];
			if (s.nodeType != 1 || s.tagName.toLowerCase() != "script") { continue; }
			var re = false;
			if ((re = s.src.match(/^(.*)loader\.js$/))) { OAT.Loader.toolkitPath = re[1]; }
			if ((re = s.src.match(/^(.*)OpenAjax.js$/))) { OAT.Loader.openAjax = true; }
			}
			*/
			OAT.Loader.toolkitPath = gx.util.resourceUrl(OAT.rP + 'QueryViewer/oatPivot/js/', true);
		},

		startOpenAjax: function () {
			OpenAjax.hub.registerLibrary("oat", "http://www.openlinksw.com/oat", "1.0");
		}
	}

	OAT.MSG = { /* messages */
		DEBUG: 0,
		OAT_DEBUG: 0,
		OAT_LOAD: 1,
		ANIMATION_STOP: 2,
		TREE_EXPAND: 3,
		TREE_COLLAPSE: 4,
		DS_RECORD_PREADVANCE: 5,
		DS_RECORD_ADVANCE: 6,
		DS_PAGE_PREADVANCE: 7,
		DS_PAGE_ADVANCE: 8,
		AJAX_START: 9,
		AJAX_ERROR: 10,
		GD_START: 11,
		GD_ABORT: 12,
		GD_END: 13,
		DOCK_DRAG: 14,
		DOCK_REMOVE: 15,
		SLB_OPENED: 16,
		SLB_CLOSED: 17,
		registry: [],
		attach: function (sender, msg, callback) {
			if (!sender) { return; }
			OAT.MSG.registry.push([sender, msg, callback]);
		},
		detach: function (sender, msg, callback) {
			if (!sender) { return; }
			var index = -1;
			for (var i = 0; i < OAT.MSG.registry.length; i++) {
				var rec = OAT.MSG.registry[i];
				if (rec[0] == sender && rec[1] == msg && rec[2] == callback) { index = i; }
			}
			if (index != -1) { OAT.MSG.registry.splice(index, 1); }
		},
		send: function (sender, msg, event) {
			for (var i = 0; i < OAT.MSG.registry.length; i++) {
				var record = OAT.MSG.registry[i];
				var senderOK = (sender == record[0] || record[0] == "*");
				if (!senderOK) { continue; }
				var msgOK = (msg == record[1] || record[1] == "*");
				if (!msgOK && record[1].toString().match(/\*/)) { /* try regexp match */
					var re = new RegExp(record[1]);
					var str = "";
					for (var p in OAT.MSG) {
						var v = OAT.MSG[p];
						if (v == msg) { str = p; }
					}
					if (str.match(re)) { msgOK = true; }
				} /* regexp */
				if (msgOK) { record[2](sender, msg, event); }
			} /* for all listeners */
		} /* send message */
	}

	OAT.Debug = {
		data: [],
		attach: function (sender, msg) {
			OAT.MSG.attach(sender, msg, OAT.Debug.listen);
		},
		listen: function (sender, msg, event) {
			var name = "n/a";
			for (var p in OAT.MSG) {
				var v = OAT.MSG[p];
				if (typeof (v) == "number" && v == msg) { name = p; }
			}
			OAT.Debug.data.push([sender, name, event]);
		}
	}
	//OAT.Debug.attach("*",OAT.MSG.OAT_DEBUG);

	/*
		OAT Load:
		1) check path
		2) listen for window.onload (or ask OpenAjax to do this)
		3) include bootstrap
		--
		4) prepare set of files to be included
		5) wait until all are loaded
		(5.5) if window is loaded, load proper window type
		6) everything is loaded and window.onload occurred:
			6a) execute window._init, if present
			6b) start declarative scanner, if present
			6c) execute window.init, if present
	*/
	OAT.Loader.findPath();
	if (OAT.Loader.openAjax) { OAT.Loader.startOpenAjax(); }
	//OAT.Event.attach(window,"load",function(){OAT.Loader.loadOccurred = 1;});

	OAT.Event.attach(window, "load", function () {
		OAT.Loader.loadOccurred = 1;
		OAT.Loader.callListeners();
	});

	//OAT.Loader.include("bootstrap.js");
	//OAT.Loader.include("jquery.tablePagination.0.5.min.js");

	//OAT.Loader.include("jquery.columnfilter.js");

	OAT.Loader.listeners = new Array();
	OAT.Loader.addListener = function (callback) {
		if (OAT.Loader.loadOccurred == 1)
			callback(); // Habr�a que ser un poco m�s defensivo ac�, chequer que el typeof sea function
		else {
			OAT.Loader.listeners.push(callback);
		}
	};

	OAT.Loader.callListeners = function () {
		for (var i = 0, len = this.listeners.length; i < len; i++)
			OAT.Loader.listeners[i](); // Habr�a que ser un poco m�s defensivo ac�, chequear que el typeof sea function
	};

}
/* END OF FILE - ..\oatPivot\oat_loader.src.js - */
/* START OF FILE - ..\oatPivot\downloadify.src.js - */

//downlodify files

/*
  Downloadify: Client Side File Creation
  JavaScript + Flash Library
  
  Version: 0.2

  Copyright (c) 2009 Douglas C. Neiner

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/
if ((!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion())) {

	if ((gx.util.browser.isIE() && 9 == gx.util.browser.ieVersion())) {

		(function () {
			Downloadify = window.Downloadify = {
				queue: {},
				uid: new Date().getTime(),
				getTextForSave: function (queue) {
					var obj = Downloadify.queue[queue];
					if (obj) return obj.getData();
					return "";
				},
				getFileNameForSave: function (queue) {
					var obj = Downloadify.queue[queue];
					if (obj) return obj.getFilename();
					return "";
				},
				getDataTypeForSave: function (queue) {
					var obj = Downloadify.queue[queue];
					if (obj) return obj.getDataType();
					return "";
				},
				saveComplete: function (queue) {
					var obj = Downloadify.queue[queue];
					if (obj) obj.complete();
					return true;
				},
				saveCancel: function (queue) {
					var obj = Downloadify.queue[queue];
					if (obj) obj.cancel();
					return true;
				},
				saveError: function (queue) {
					var obj = Downloadify.queue[queue];
					if (obj) obj.error();
					return true;
				},
				addToQueue: function (container) {
					Downloadify.queue[container.queue_name] = container;
				},
				// Concept adapted from: http://tinyurl.com/yzsyfto
				// SWF object runs off of ID's, so this is the good way to get a unique ID
				getUID: function (el) {
					if (el.id == "") el.id = 'downloadify_' + Downloadify.uid++;
					return el.id;
				}
			};

			Downloadify.create = function (idOrDOM, options) {
				var el = (typeof (idOrDOM) == "string" ? document.getElementById(idOrDOM) : idOrDOM);
				return new Downloadify.Container(el, options);
			};

			Downloadify.Container = function (el, options) {
				var base = this;

				base.el = el;
				base.enabled = true;
				base.dataCallback = null;
				base.filenameCallback = null;
				base.data = null;
				base.filename = null;

				var init = function () {
					base.options = options;

					if (!base.options.append) base.el.innerHTML = "";

					base.flashContainer = document.createElement('span');
					base.el.appendChild(base.flashContainer);

					base.queue_name = Downloadify.getUID(base.flashContainer);

					if (typeof (base.options.filename) === "function")
						base.filenameCallback = base.options.filename;
					else if (base.options.filename)
						base.filename = base.options.filename;

					if (typeof (base.options.data) === "function")
						base.dataCallback = base.options.data;
					else if (base.options.data)
						base.data = base.options.data;


					var flashVars = {
						queue_name: base.queue_name,
						width: base.options.width,
						height: base.options.height
					};

					var params = {
						allowScriptAccess: 'always'
					};

					var attributes = {
						id: base.flashContainer.id,
						name: base.flashContainer.id
					};

					if (base.options.enabled === false) base.enabled = false;

					if (base.options.transparent === true) params.wmode = "transparent";

					if (base.options.downloadImage) flashVars.downloadImage = base.options.downloadImage;

					swfobject.embedSWF(base.options.swf, base.flashContainer.id, base.options.width, base.options.height, "10", null, flashVars, params, attributes);

					Downloadify.addToQueue(base);
				};

				base.enable = function () {
					var swf = document.getElementById(base.flashContainer.id);
					swf.setEnabled(true);
					base.enabled = true;
				};

				base.disable = function () {
					var swf = document.getElementById(base.flashContainer.id);
					swf.setEnabled(false);
					base.enabled = false;
				};

				base.getData = function () {
					if (!base.enabled) return "";
					if (base.dataCallback) return base.dataCallback();
					else if (base.data) return base.data;
					else return "";
				};

				base.getFilename = function () {
					if (base.filenameCallback) return base.filenameCallback();
					else if (base.filename) return base.filename;
					else return "";
				};

				base.getDataType = function () {
					if (base.options.dataType) return base.options.dataType;
					return "string";
				};

				base.complete = function () {
					if (typeof (base.options.onComplete) === "function") base.options.onComplete();
				};

				base.cancel = function () {
					if (typeof (base.options.onCancel) === "function") base.options.onCancel();
				};

				base.error = function () {
					if (typeof (base.options.onError) === "function") base.options.onError();
				};

				init();
			};

			Downloadify.defaultOptions = {
				swf: 'media/downloadify.swf',
				downloadImage: 'images/download_file.png',
				width: 100,
				height: 30,
				transparent: true,
				append: false,
				dataType: "string"
			};
		})();

		// Support for jQuery
		if (typeof (jQuery) != "undefined") {
			(function ($) {
				$.fn.downloadify = function (options) {
					return this.each(function () {
						options = $.extend({}, Downloadify.defaultOptions, options);
						var dl = Downloadify.create(this, options);
						$(this).data('Downloadify', dl);
					});
				};
			})(jQuery);
		};

		/* mootools helper */
		if (typeof (MooTools) != 'undefined') {
			Element.implement({
				downloadify: function (options) {
					options = $merge(Downloadify.defaultOptions, options);
					return this.store('Downloadify', Downloadify.create(this, options));
				}
			});
		};


		/*	SWFObject v2.2 <http://code.google.com/p/swfobject/> 
			is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> 
		*/

		var swfobject = function () {
			var D = "undefined", r = "object", S = "Shockwave Flash", W = "ShockwaveFlash.ShockwaveFlash", q = "application/x-shockwave-flash", R = "SWFObjectExprInst", x = "onreadystatechange", O = window, j = document, t = navigator, T = false, U = [h], o = [], N = [], I = [], l, Q, E, B, J = false, a = false, n, G, m = true, M = function () {
				var aa = typeof j.getElementById != D && typeof j.getElementsByTagName != D && typeof j.createElement != D, ah = t.userAgent.toLowerCase(), Y = t.platform.toLowerCase(), ae = Y ? /win/.test(Y) : /win/.test(ah), ac = Y ? /mac/.test(Y) : /mac/.test(ah), af = /webkit/.test(ah) ? parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, X = !+"\v1", ag = [0, 0, 0], ab = null;
				if (typeof t.plugins != D && typeof t.plugins[S] == r) {
					ab = t.plugins[S].description;
					if (ab && !(typeof t.mimeTypes != D && t.mimeTypes[q] && !t.mimeTypes[q].enabledPlugin)) {
						T = true;
						X = false;
						ab = ab.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
						ag[0] = parseInt(ab.replace(/^(.*)\..*$/, "$1"), 10);
						ag[1] = parseInt(ab.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
						ag[2] = /[a-zA-Z]/.test(ab) ? parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0
					}
				} else {
					if (typeof O.ActiveXObject != D) {
						try {
							var ad = new ActiveXObject(W);
							if (ad) {
								ab = ad.GetVariable("$version");
								if (ab) {
									X = true;
									ab = ab.split(" ")[1].split(",");
									ag = [parseInt(ab[0], 10), parseInt(ab[1], 10), parseInt(ab[2], 10)]
								}
							}
						} catch (Z) {
						}
					}
				}
				return {
					w3: aa,
					pv: ag,
					wk: af,
					ie: X,
					win: ae,
					mac: ac
				}
			}(), k = function () {
				if (!M.w3) {
					return
				}
				if ((typeof j.readyState != D && j.readyState == "complete") || (typeof j.readyState == D && (j.getElementsByTagName("body")[0] || j.body))) {
					f()
				}
				if (!J) {
					if (typeof j.addEventListener != D) {
						j.addEventListener("DOMContentLoaded", f, false)
					}
					if (M.ie && M.win) {
						j.attachEvent(x, function () {
							if (j.readyState == "complete") {
								j.detachEvent(x, arguments.callee);
								f()
							}
						});
						if (O == top) {
							(function () {
								if (J) {
									return
								}
								try {
									j.documentElement.doScroll("left")
								} catch (X) {
									setTimeout(arguments.callee, 0);
									return
								}
								f()
							})()
						}
					}
					if (M.wk) {
						(function () {
							if (J) {
								return
							}
							if (!/loaded|complete/.test(j.readyState)) {
								setTimeout(arguments.callee, 0);
								return
							}
							f()
						})()
					}
					s(f)
				}
			}();
			function f() {
				if (J) {
					return
				}
				try {
					var Z = j.getElementsByTagName("body")[0].appendChild(C("span"));
					Z.parentNode.removeChild(Z)
				} catch (aa) {
					return
				}
				J = true;
				var X = U.length;
				for (var Y = 0; Y < X; Y++) {
					U[Y]()
				}
			}

			function K(X) {
				if (J) {
					X()
				} else {
					U[U.length] = X
				}
			}

			function s(Y) {
				if (typeof O.addEventListener != D) {
					O.addEventListener("load", Y, false)
				} else {
					if (typeof j.addEventListener != D) {
						j.addEventListener("load", Y, false)
					} else {
						if (typeof O.attachEvent != D) {
							i(O, "onload", Y)
						} else {
							if (typeof O.onload == "function") {
								var X = O.onload;
								O.onload = function () {
									X();
									Y()
								}
							} else {
								O.onload = Y
							}
						}
					}
				}
			}

			function h() {
				if (T) {
					V()
				} else {
					H()
				}
			}

			function V() {
				var X = j.getElementsByTagName("body")[0];
				var aa = C(r);
				aa.setAttribute("type", q);
				var Z = X.appendChild(aa);
				if (Z) {
					var Y = 0;
					(function () {
						if (typeof Z.GetVariable != D) {
							var ab = Z.GetVariable("$version");
							if (ab) {
								ab = ab.split(" ")[1].split(",");
								M.pv = [parseInt(ab[0], 10), parseInt(ab[1], 10), parseInt(ab[2], 10)]
							}
						} else {
							if (Y < 10) {
								Y++;
								setTimeout(arguments.callee, 10);
								return
							}
						}
						X.removeChild(aa);
						Z = null;
						H()
					})()
				} else {
					H()
				}
			}

			function H() {
				var ag = o.length;
				if (ag > 0) {
					for (var af = 0; af < ag; af++) {
						var Y = o[af].id;
						var ab = o[af].callbackFn;
						var aa = {
							success: false,
							id: Y
						};
						if (M.pv[0] > 0) {
							var ae = c(Y);
							if (ae) {
								if (F(o[af].swfVersion) && !(M.wk && M.wk < 312)) {
									w(Y, true);
									if (ab) {
										aa.success = true;
										aa.ref = z(Y);
										ab(aa)
									}
								} else {
									if (o[af].expressInstall && A()) {
										var ai = {};
										ai.data = o[af].expressInstall;
										ai.width = ae.getAttribute("width") || "0";
										ai.height = ae.getAttribute("height") || "0";
										if (ae.getAttribute("class")) {
											ai.styleclass = ae.getAttribute("class")
										}
										if (ae.getAttribute("align")) {
											ai.align = ae.getAttribute("align")
										}
										var ah = {};
										var X = ae.getElementsByTagName("param");
										var ac = X.length;
										for (var ad = 0; ad < ac; ad++) {
											if (X[ad].getAttribute("name").toLowerCase() != "movie") {
												ah[X[ad].getAttribute("name")] = X[ad].getAttribute("value")
											}
										}
										P(ai, ah, Y, ab)
									} else {
										p(ae);
										if (ab) {
											ab(aa)
										}
									}
								}
							}
						} else {
							w(Y, true);
							if (ab) {
								var Z = z(Y);
								if (Z && typeof Z.SetVariable != D) {
									aa.success = true;
									aa.ref = Z
								}
								ab(aa)
							}
						}
					}
				}
			}

			function z(aa) {
				var X = null;
				var Y = c(aa);
				if (Y && Y.nodeName == "OBJECT") {
					if (typeof Y.SetVariable != D) {
						X = Y
					} else {
						var Z = Y.getElementsByTagName(r)[0];
						if (Z) {
							X = Z
						}
					}
				}
				return X
			}

			function A() {
				return !a && F("6.0.65") && (M.win || M.mac) && !(M.wk && M.wk < 312)
			}

			function P(aa, ab, X, Z) {
				a = true;
				E = Z || null;
				B = {
					success: false,
					id: X
				};
				var ae = c(X);
				if (ae) {
					if (ae.nodeName == "OBJECT") {
						l = g(ae);
						Q = null
					} else {
						l = ae;
						Q = X
					}
					aa.id = R;
					if (typeof aa.width == D || (!/%$/.test(aa.width) && parseInt(aa.width, 10) < 310)) {
						aa.width = "310"
					}
					if (typeof aa.height == D || (!/%$/.test(aa.height) && parseInt(aa.height, 10) < 137)) {
						aa.height = "137"
					}
					j.title = j.title.slice(0, 47) + " - Flash Player Installation";
					var ad = M.ie && M.win ? "ActiveX" : "PlugIn", ac = "MMredirectURL=" + O.location.toString().replace(/&/g, "%26") + "&MMplayerType=" + ad + "&MMdoctitle=" + j.title;
					if (typeof ab.flashvars != D) {
						ab.flashvars += "&" + ac
					} else {
						ab.flashvars = ac
					}
					if (M.ie && M.win && ae.readyState != 4) {
						var Y = C("div");
						X += "SWFObjectNew";
						Y.setAttribute("id", X);
						ae.parentNode.insertBefore(Y, ae);
						ae.style.display = "none";
						(function () {
							if (ae.readyState == 4) {
								ae.parentNode.removeChild(ae)
							} else {
								setTimeout(arguments.callee, 10)
							}
						})()
					}
					u(aa, ab, X)
				}
			}

			function p(Y) {
				if (M.ie && M.win && Y.readyState != 4) {
					var X = C("div");
					Y.parentNode.insertBefore(X, Y);
					X.parentNode.replaceChild(g(Y), X);
					Y.style.display = "none";
					(function () {
						if (Y.readyState == 4) {
							Y.parentNode.removeChild(Y)
						} else {
							setTimeout(arguments.callee, 10)
						}
					})()
				} else {
					Y.parentNode.replaceChild(g(Y), Y)
				}
			}

			function g(ab) {
				var aa = C("div");
				if (M.win && M.ie) {
					aa.innerHTML = ab.innerHTML
				} else {
					var Y = ab.getElementsByTagName(r)[0];
					if (Y) {
						var ad = Y.childNodes;
						if (ad) {
							var X = ad.length;
							for (var Z = 0; Z < X; Z++) {
								if (!(ad[Z].nodeType == 1 && ad[Z].nodeName == "PARAM") && !(ad[Z].nodeType == 8)) {
									aa.appendChild(ad[Z].cloneNode(true))
								}
							}
						}
					}
				}
				return aa
			}

			function u(ai, ag, Y) {
				var X, aa = c(Y);
				if (M.wk && M.wk < 312) {
					return X
				}
				if (aa) {
					if (typeof ai.id == D) {
						ai.id = Y
					}
					if (M.ie && M.win) {
						var ah = "";
						for (var ae in ai) {
							if (ai[ae] != Object.prototype[ae]) {
								if (ae.toLowerCase() == "data") {
									ag.movie = ai[ae]
								} else {
									if (ae.toLowerCase() == "styleclass") {
										ah += ' class="' + ai[ae] + '"'
									} else {
										if (ae.toLowerCase() != "classid") {
											ah += " " + ae + '="' + ai[ae] + '"'
										}
									}
								}
							}
						}
						var af = "";
						for (var ad in ag) {
							if (ag[ad] != Object.prototype[ad]) {
								af += '<param name="' + ad + '" value="' + ag[ad] + '" />'
							}
						}
						aa.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + ah + ">" + af + "</object>";
						N[N.length] = ai.id;
						X = c(ai.id)
					} else {
						var Z = C(r);
						Z.setAttribute("type", q);
						for (var ac in ai) {
							if (ai[ac] != Object.prototype[ac]) {
								if (ac.toLowerCase() == "styleclass") {
									Z.setAttribute("class", ai[ac])
								} else {
									if (ac.toLowerCase() != "classid") {
										Z.setAttribute(ac, ai[ac])
									}
								}
							}
						}
						for (var ab in ag) {
							if (ag[ab] != Object.prototype[ab] && ab.toLowerCase() != "movie") {
								e(Z, ab, ag[ab])
							}
						}
						aa.parentNode.replaceChild(Z, aa);
						X = Z
					}
				}
				return X
			}

			function e(Z, X, Y) {
				var aa = C("param");
				aa.setAttribute("name", X);
				aa.setAttribute("value", Y);
				Z.appendChild(aa)
			}

			function y(Y) {
				var X = c(Y);
				if (X && X.nodeName == "OBJECT") {
					if (M.ie && M.win) {
						X.style.display = "none";
						(function () {
							if (X.readyState == 4) {
								b(Y)
							} else {
								setTimeout(arguments.callee, 10)
							}
						})()
					} else {
						X.parentNode.removeChild(X)
					}
				}
			}

			function b(Z) {
				var Y = c(Z);
				if (Y) {
					for (var X in Y) {
						if (typeof Y[X] == "function") {
							Y[X] = null
						}
					}
					Y.parentNode.removeChild(Y)
				}
			}

			function c(Z) {
				var X = null;
				try {
					X = j.getElementById(Z)
				} catch (Y) {
				}
				return X
			}

			function C(X) {
				return j.createElement(X)
			}

			function i(Z, X, Y) {
				Z.attachEvent(X, Y);
				I[I.length] = [Z, X, Y]
			}

			function F(Z) {
				var Y = M.pv, X = Z.split(".");
				X[0] = parseInt(X[0], 10);
				X[1] = parseInt(X[1], 10) || 0;
				X[2] = parseInt(X[2], 10) || 0;
				return (Y[0] > X[0] || (Y[0] == X[0] && Y[1] > X[1]) || (Y[0] == X[0] && Y[1] == X[1] && Y[2] >= X[2])) ? true : false
			}

			function v(ac, Y, ad, ab) {
				if (M.ie && M.mac) {
					return
				}
				var aa = j.getElementsByTagName("head")[0];
				if (!aa) {
					return
				}
				var X = (ad && typeof ad == "string") ? ad : "screen";
				if (ab) {
					n = null;
					G = null
				}
				if (!n || G != X) {
					var Z = C("style");
					Z.setAttribute("type", "text/css");
					Z.setAttribute("media", X);
					n = aa.appendChild(Z);
					if (M.ie && M.win && typeof j.styleSheets != D && j.styleSheets.length > 0) {
						n = j.styleSheets[j.styleSheets.length - 1]
					}
					G = X
				}
				if (M.ie && M.win) {
					if (n && typeof n.addRule == r) {
						n.addRule(ac, Y)
					}
				} else {
					if (n && typeof j.createTextNode != D) {
						n.appendChild(j.createTextNode(ac + " {" + Y + "}"))
					}
				}
			}

			function w(Z, X) {
				if (!m) {
					return
				}
				var Y = X ? "visible" : "hidden";
				if (J && c(Z)) {
					c(Z).style.visibility = Y
				} else {
					v("#" + Z, "visibility:" + Y)
				}
			}

			function L(Y) {
				var Z = /[\\\"<>\.;]/;
				var X = Z.exec(Y) != null;
				return X && typeof encodeURIComponent != D ? encodeURIComponent(Y) : Y
			}

			var d = function () {
				if (M.ie && M.win) {
					window.attachEvent("onunload", function () {
						var ac = I.length;
						for (var ab = 0; ab < ac; ab++) {
							I[ab][0].detachEvent(I[ab][1], I[ab][2])
						}
						var Z = N.length;
						for (var aa = 0; aa < Z; aa++) {
							y(N[aa])
						}
						for (var Y in M) {
							M[Y] = null
						}
						M = null;
						for (var X in swfobject) {
							swfobject[X] = null
						}
						swfobject = null
					})
				}
			}();
			return {
				registerObject: function (ab, X, aa, Z) {
					if (M.w3 && ab && X) {
						var Y = {};
						Y.id = ab;
						Y.swfVersion = X;
						Y.expressInstall = aa;
						Y.callbackFn = Z;
						o[o.length] = Y;
						w(ab, false)
					} else {
						if (Z) {
							Z({
								success: false,
								id: ab
							})
						}
					}
				},
				getObjectById: function (X) {
					if (M.w3) {
						return z(X)
					}
				},
				embedSWF: function (ab, ah, ae, ag, Y, aa, Z, ad, af, ac) {
					var X = {
						success: false,
						id: ah
					};
					if (M.w3 && !(M.wk && M.wk < 312) && ab && ah && ae && ag && Y) {
						w(ah, false);
						K(function () {
							ae += "";
							ag += "";
							var aj = {};
							if (af && typeof af === r) {
								for (var al in af) {
									aj[al] = af[al]
								}
							}
							aj.data = ab;
							aj.width = ae;
							aj.height = ag;
							var am = {};
							if (ad && typeof ad === r) {
								for (var ak in ad) {
									am[ak] = ad[ak]
								}
							}
							if (Z && typeof Z === r) {
								for (var ai in Z) {
									if (typeof am.flashvars != D) {
										am.flashvars += "&" + ai + "=" + Z[ai]
									} else {
										am.flashvars = ai + "=" + Z[ai]
									}
								}
							}
							if (F(Y)) {
								var an = u(aj, am, ah);
								if (aj.id == ah) {
									w(ah, true)
								}
								X.success = true;
								X.ref = an
							} else {
								if (aa && A()) {
									aj.data = aa;
									P(aj, am, ah, ac);
									return
								} else {
									w(ah, true)
								}
							}
							if (ac) {
								ac(X)
							}
						})
					} else {
						if (ac) {
							ac(X)
						}
					}
				},
				switchOffAutoHideShow: function () {
					m = false
				},
				ua: M,
				getFlashPlayerVersion: function () {
					return {
						major: M.pv[0],
						minor: M.pv[1],
						release: M.pv[2]
					}
				},
				hasFlashPlayerVersion: F,
				createSWF: function (Z, Y, X) {
					if (M.w3) {
						return u(Z, Y, X)
					} else {
						return undefined
					}
				},
				showExpressInstall: function (Z, aa, X, Y) {
					if (M.w3 && A()) {
						P(Z, aa, X, Y)
					}
				},
				removeSWF: function (X) {
					if (M.w3) {
						y(X)
					}
				},
				createCSS: function (aa, Z, Y, X) {
					if (M.w3) {
						v(aa, Z, Y, X)
					}
				},
				addDomLoadEvent: K,
				addLoadEvent: s,
				getQueryParamValue: function (aa) {
					var Z = j.location.search || j.location.hash;
					if (Z) {
						if (/\?/.test(Z)) {
							Z = Z.split("?")[1]
						}
						if (aa == null) {
							return L(Z)
						}
						var Y = Z.split("&");
						for (var X = 0; X < Y.length; X++) {
							if (Y[X].substring(0, Y[X].indexOf("=")) == aa) {
								return L(Y[X].substring((Y[X].indexOf("=") + 1)))
							}
						}
					}
					return ""
				},
				expressInstallCallback: function () {
					if (a) {
						var X = c(R);
						if (X && l) {
							X.parentNode.replaceChild(l, X);
							if (Q) {
								w(Q, true);
								if (M.ie && M.win) {
									l.style.display = "block"
								}
							}
							if (E) {
								E(B)
							}
						}
						a = false
					}
				}
			}
		}();

	}//IE == 9

}//not IE<9
/* END OF FILE - ..\oatPivot\downloadify.src.js - */
/* START OF FILE - ..\oatPivot\jsPDF.src.js - */

/*
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * ====================================================================
 */

if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {

	/**
	Creates new jsPDF document object instance
	@class
	@param orientation One of "portrait" or "landscape" (or shortcuts "p" (Default), "l")
	@param unit Measurement unit to be used when coordinates are specified. One of "pt" (points), "mm" (Default), "cm", "in"
	@param format One of 'a3', 'a4' (Default),'a5' ,'letter' ,'legal'
	@returns {jsPDF}
	@name jsPDF
	*/
	var jsPDF = (function () {
		'use strict';
		/*jslint browser:true, plusplus: true, bitwise: true, nomen: true */
		/*global document: false, btoa, atob, zpipe, Uint8Array, ArrayBuffer, Blob, saveAs, adler32cs, Deflater */

		// this will run on <=IE9, possibly some niche browsers
		// new webkit-based, FireFox, IE10 already have native version of this.
		if (typeof btoa === 'undefined') {
			window.btoa = function (data) {
				// DO NOT ADD UTF8 ENCODING CODE HERE!!!!

				// UTF8 encoding encodes bytes over char code 128
				// and, essentially, turns an 8-bit binary streams
				// (that base64 can deal with) into 7-bit binary streams.
				// (by default server does not know that and does not recode the data back to 8bit)
				// You destroy your data.

				// binary streams like jpeg image data etc, while stored in JavaScript strings,
				// (which are 16bit arrays) are in 8bit format already.
				// You do NOT need to char-encode that before base64 encoding.

				// if you, by act of fate
				// have string which has individual characters with code
				// above 255 (pure unicode chars), encode that BEFORE you base64 here.
				// you can use absolutely any approch there, as long as in the end,
				// base64 gets an 8bit (char codes 0 - 255) stream.
				// when you get it on the server after un-base64, you must
				// UNencode it too, to get back to 16, 32bit or whatever original bin stream.

				// Note, Yes, JavaScript strings are, in most cases UCS-2 -
				// 16-bit character arrays. This does not mean, however,
				// that you always have to UTF8 it before base64.
				// it means that if you have actual characters anywhere in
				// that string that have char code above 255, you need to
				// recode *entire* string from 16-bit (or 32bit) to 8-bit array.
				// You can do binary split to UTF16 (BE or LE)
				// you can do utf8, you can split the thing by hand and prepend BOM to it,
				// but whatever you do, make sure you mirror the opposite on
				// the server. If server does not expect to post-process un-base64
				// 8-bit binary stream, think very very hard about messing around with encoding.

				// so, long story short:
				// DO NOT ADD UTF8 ENCODING CODE HERE!!!!



				var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
					b64a = b64.split(''),
					o1,
					o2,
					o3,
					h1,
					h2,
					h3,
					h4,
					bits,
					i = 0,
					ac = 0,
					enc = "",
					tmp_arr = [],
					r;

				do { // pack three octets into four hexets
					o1 = data.charCodeAt(i++);
					o2 = data.charCodeAt(i++);
					o3 = data.charCodeAt(i++);

					bits = o1 << 16 | o2 << 8 | o3;

					h1 = bits >> 18 & 0x3f;
					h2 = bits >> 12 & 0x3f;
					h3 = bits >> 6 & 0x3f;
					h4 = bits & 0x3f;

					// use hexets to index into b64, and append result to encoded string
					tmp_arr[ac++] = b64a[h1] + b64a[h2] + b64a[h3] + b64a[h4];
				} while (i < data.length);

				enc = tmp_arr.join('');
				r = data.length % 3;
				return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
				// end of base64 encoder MIT, GPL
			};
		}

		if (typeof atob === 'undefined') {
			window.atob = function (data) {
				// http://kevin.vanzonneveld.net
				// +   original by: Tyler Akins (http://rumkin.com)
				// +   improved by: Thunder.m
				// +      input by: Aman Gupta
				// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
				// +   bugfixed by: Onno Marsman
				// +   bugfixed by: Pellentesque Malesuada
				// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
				// +      input by: Brett Zamir (http://brett-zamir.me)
				// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
				// *     example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
				// *     returns 1: 'Kevin van Zonneveld'
				// mozilla has this native
				// - but breaks in 2.0.0.12!
				//if (typeof this.window['atob'] == 'function') {
				//    return atob(data);
				//}
				var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
					o1,
					o2,
					o3,
					h1,
					h2,
					h3,
					h4,
					bits,
					i = 0,
					ac = 0,
					dec = "",
					tmp_arr = [];

				if (!data) {
					return data;
				}

				data += '';

				do { // unpack four hexets into three octets using index points in b64
					h1 = b64.indexOf(data.charAt(i++));
					h2 = b64.indexOf(data.charAt(i++));
					h3 = b64.indexOf(data.charAt(i++));
					h4 = b64.indexOf(data.charAt(i++));

					bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;

					o1 = bits >> 16 & 0xff;
					o2 = bits >> 8 & 0xff;
					o3 = bits & 0xff;

					if (h3 === 64) {
						tmp_arr[ac++] = String.fromCharCode(o1);
					} else if (h4 === 64) {
						tmp_arr[ac++] = String.fromCharCode(o1, o2);
					} else {
						tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
					}
				} while (i < data.length);
				dec = tmp_arr.join('');
				return dec;
			};
		}

		var getObjectLength = typeof Object.keys === 'function' ?
			function (object) {
				return Object.keys(object).length;
			} :
			function (object) {
				var i = 0, e;
				for (e in object) {
					if (object.hasOwnProperty(e)) {
						i++;
					}
				}
				return i;
			},

			/**
			PubSub implementation
			
			@class
			@name PubSub
			*/
			PubSub = function (context) {

				/**
				@private
				@fieldOf PubSub
				*/
				this.topics = {};
				/**
				Stores what will be `this` within the callback functions.
	
				@private
				@fieldOf PubSub#
				*/
				this.context = context;
				/**
				Allows caller to emit an event and pass arguments to event listeners.
				@public
				@function
				@param topic {String} Name of the channel on which to voice this event
				@param args Any number of arguments you want to pass to the listeners of this event.
				@methodOf PubSub#
				@name publish
				*/
				this.publish = function (topic, args) {
					if (this.topics[topic]) {
						var currentTopic = this.topics[topic],
							toremove = [],
							fn,
							i,
							l,
							pair,
							emptyFunc = function () { };
						args = Array.prototype.slice.call(arguments, 1);
						for (i = 0, l = currentTopic.length; i < l; i++) {
							pair = currentTopic[i]; // this is a [function, once_flag] array
							fn = pair[0];
							if (pair[1]) { /* 'run once' flag set */
								pair[0] = emptyFunc;
								toremove.push(i);
							}
							fn.apply(this.context, args);
						}
						for (i = 0, l = toremove.length; i < l; i++) {
							currentTopic.splice(toremove[i], 1);
						}
					}
				};
				/**
				Allows listener code to subscribe to channel and be called when data is available
				@public
				@function
				@param topic {String} Name of the channel on which to voice this event
				@param callback {Function} Executable (function pointer) that will be ran when event is voiced on this channel.
				@param once {Boolean} (optional. False by default) Flag indicating if the function is to be triggered only once.
				@returns {Object} A token object that cen be used for unsubscribing.
				@methodOf PubSub#
				@name subscribe
				*/
				this.subscribe = function (topic, callback, once) {
					if (!this.topics[topic]) {
						this.topics[topic] = [[callback, once]];
					} else {
						this.topics[topic].push([callback, once]);
					}
					return {
						"topic": topic,
						"callback": callback
					};
				};
				/**
				Allows listener code to unsubscribe from a channel
				@public
				@function
				@param token {Object} A token object that was returned by `subscribe` method
				@methodOf PubSub#
				@name unsubscribe
				*/
				this.unsubscribe = function (token) {
					if (this.topics[token.topic]) {
						var currentTopic = this.topics[token.topic], i, l;

						for (i = 0, l = currentTopic.length; i < l; i++) {
							if (currentTopic[i][0] === token.callback) {
								currentTopic.splice(i, 1);
							}
						}
					}
				};
			};


		/**
		@constructor
		@private
		*/
		function jsPDF(orientation, unit, format, compressPdf, wdt, hgt) { /** String orientation, String unit, String format, Boolean compressed */

			// Default parameter values
			if (typeof orientation === 'undefined') {
				orientation = 'p';
			} else {
				orientation = orientation.toString().toLowerCase();
			}
			if (typeof unit === 'undefined') { unit = 'mm'; }
			if (typeof format === 'undefined') { format = 'a4'; }
			if (typeof compressPdf === 'undefined' && typeof zpipe === 'undefined') { compressPdf = false; }

			var format_as_string = format.toString().toLowerCase(),
				version = '0.9.0rc2',
				content = [],
				content_length = 0,
				compress = compressPdf,
				pdfVersion = '1.3', // PDF Version
				pageFormats = { // Size in pt of various paper formats
					'a3': [841.89, 1190.55],
					'a4': [wdt, hgt],//[595.28, 841.89],
					'a5': [420.94, 595.28],
					'letter': [612, 792],
					'legal': [612, 1008]
				},
				textColor = '0 g',
				drawColor = '0 G',
				page = 0,
				pages = [],
				objectNumber = 2, // 'n' Current object number
				outToPages = false, // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content
				offsets = [], // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes.
				fonts = {}, // collection of font objects, where key is fontKey - a dynamically created label for a given font.
				fontmap = {}, // mapping structure fontName > fontStyle > font key - performance layer. See addFont()
				activeFontSize = 16,
				activeFontKey, // will be string representing the KEY of the font as combination of fontName + fontStyle
				lineWidth = 0.200025, // 2mm
				pageHeight,
				pageWidth,
				k, // Scale factor
				documentProperties = { 'title': '', 'subject': '', 'author': '', 'keywords': '', 'creator': '' },
				lineCapID = 0,
				lineJoinID = 0,
				API = {},
				events = new PubSub(API),
				tmp,
				plugin,
				/////////////////////
				// Private functions
				/////////////////////
				// simplified (speedier) replacement for sprintf's %.2f conversion
				f2 = function (number) {
					return number.toFixed(2);
				},
				// simplified (speedier) replacement for sprintf's %.3f conversion
				f3 = function (number) {
					return number.toFixed(3);
				},
				// simplified (speedier) replacement for sprintf's %02d
				padd2 = function (number) {
					var n = (number).toFixed(0);
					if (number < 10) {
						return '0' + n;
					} else {
						return n;
					}
				},
				// simplified (speedier) replacement for sprintf's %02d
				padd10 = function (number) {
					var n = (number).toFixed(0);
					if (n.length < 10) {
						return new Array(11 - n.length).join('0') + n;
					} else {
						return n;
					}
				},
				out = function (string) {
					if (outToPages) { /* set by beginPage */
						pages[page].push(string);
					} else {
						content.push(string);
						content_length += string.length + 1; // +1 is for '\n' that will be used to join contents of content
					}
				},
				newObject = function () {
					// Begin a new object
					objectNumber++;
					offsets[objectNumber] = content_length;
					out(objectNumber + ' 0 obj');
					return objectNumber;
				},
				putStream = function (str) {
					out('stream');
					out(str);
					out('endstream');
				},
				wPt,
				hPt,
				kids,
				i,
				putPages = function () {
					wPt = pageWidth * k;
					hPt = pageHeight * k;

					// outToPages = false as set in endDocument(). out() writes to content.

					var n, p, arr, uint, i, deflater, adler32;
					for (n = 1; n <= page; n++) {
						newObject();
						out('<</Type /Page');
						out('/Parent 1 0 R');
						out('/Resources 2 0 R');
						out('/Contents ' + (objectNumber + 1) + ' 0 R>>');
						out('endobj');

						// Page content
						p = pages[n].join('\n');
						newObject();
						if (compress) {
							arr = [];
							for (i = 0; i < p.length; ++i) {
								arr[i] = p.charCodeAt(i);
							}
							adler32 = adler32cs.from(p);
							deflater = new Deflater(6);
							deflater.append(new Uint8Array(arr));
							p = deflater.flush();
							arr = [new Uint8Array([120, 156]), new Uint8Array(p),
							new Uint8Array([adler32 & 0xFF, (adler32 >> 8) & 0xFF, (adler32 >> 16) & 0xFF, (adler32 >> 24) & 0xFF])];
							p = '';
							for (i in arr) {
								if (arr.hasOwnProperty(i)) {
									p += String.fromCharCode.apply(null, arr[i]);
								}
							}
							out('<</Length ' + p.length + ' /Filter [/FlateDecode]>>');
						} else {
							out('<</Length ' + p.length + '>>');
						}
						putStream(p);
						out('endobj');
					}
					offsets[1] = content_length;
					out('1 0 obj');
					out('<</Type /Pages');
					kids = '/Kids [';
					for (i = 0; i < page; i++) {
						kids += (3 + 2 * i) + ' 0 R ';
					}
					out(kids + ']');
					out('/Count ' + page);
					out('/MediaBox [0 0 ' + f2(wPt) + ' ' + f2(hPt) + ']');
					out('>>');
					out('endobj');
				},
				putFont = function (font) {
					font.objectNumber = newObject();
					out('<</BaseFont/' + font.PostScriptName + '/Type/Font');
					if (typeof font.encoding === 'string') {
						out('/Encoding/' + font.encoding);
					}
					out('/Subtype/Type1>>');
					out('endobj');
				},
				putFonts = function () {
					var fontKey;
					for (fontKey in fonts) {
						if (fonts.hasOwnProperty(fontKey)) {
							putFont(fonts[fontKey]);
						}
					}
				},
				putXobjectDict = function () {
					// Loop through images, or other data objects
					events.publish('putXobjectDict');
				},
				putResourceDictionary = function () {
					out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
					out('/Font <<');
					// Do this for each font, the '1' bit is the index of the font
					var fontKey;
					for (fontKey in fonts) {
						if (fonts.hasOwnProperty(fontKey)) {
							out('/' + fontKey + ' ' + fonts[fontKey].objectNumber + ' 0 R');
						}
					}
					out('>>');
					out('/XObject <<');
					putXobjectDict();
					out('>>');
				},
				putResources = function () {
					putFonts();
					events.publish('putResources');
					// Resource dictionary
					offsets[2] = content_length;
					out('2 0 obj');
					out('<<');
					putResourceDictionary();
					out('>>');
					out('endobj');
					events.publish('postPutResources');
				},
				addToFontDictionary = function (fontKey, fontName, fontStyle) {
					// this is mapping structure for quick font key lookup.
					// returns the KEY of the font (ex: "F1") for a given pair of font name and type (ex: "Arial". "Italic")
					var undef;
					if (fontmap[fontName] === undef) {
						fontmap[fontName] = {}; // fontStyle is a var interpreted and converted to appropriate string. don't wrap in quotes.
					}
					fontmap[fontName][fontStyle] = fontKey;
				},
				/**
				FontObject describes a particular font as member of an instnace of jsPDF
	
				It's a collection of properties like 'id' (to be used in PDF stream),
				'fontName' (font's family name), 'fontStyle' (font's style variant label)
	
				@class
				@public
				@property id {String} PDF-document-instance-specific label assinged to the font.
				@property PostScriptName {String} PDF specification full name for the font
				@property encoding {Object} Encoding_name-to-Font_metrics_object mapping.
				@name FontObject
				*/
				FontObject = {},
				addFont = function (PostScriptName, fontName, fontStyle, encoding) {
					var fontKey = 'F' + (getObjectLength(fonts) + 1).toString(10),
						// This is FontObject
						font = fonts[fontKey] = {
							'id': fontKey,
							// , 'objectNumber':   will be set by putFont()
							'PostScriptName': PostScriptName,
							'fontName': fontName,
							'fontStyle': fontStyle,
							'encoding': encoding,
							'metadata': {}
						};

					addToFontDictionary(fontKey, fontName, fontStyle);

					events.publish('addFont', font);

					return fontKey;
				},
				addFonts = function () {

					var HELVETICA = "helvetica",
						TIMES = "times",
						COURIER = "courier",
						NORMAL = "normal",
						BOLD = "bold",
						ITALIC = "italic",
						BOLD_ITALIC = "bolditalic",
						encoding = 'StandardEncoding',
						standardFonts = [
							['Helvetica', HELVETICA, NORMAL],
							['Helvetica-Bold', HELVETICA, BOLD],
							['Helvetica-Oblique', HELVETICA, ITALIC],
							['Helvetica-BoldOblique', HELVETICA, BOLD_ITALIC],
							['Courier', COURIER, NORMAL],
							['Courier-Bold', COURIER, BOLD],
							['Courier-Oblique', COURIER, ITALIC],
							['Courier-BoldOblique', COURIER, BOLD_ITALIC],
							['Times-Roman', TIMES, NORMAL],
							['Times-Bold', TIMES, BOLD],
							['Times-Italic', TIMES, ITALIC],
							['Times-BoldItalic', TIMES, BOLD_ITALIC]
						],
						i,
						l,
						fontKey,
						parts;
					for (i = 0, l = standardFonts.length; i < l; i++) {
						fontKey = addFont(
							standardFonts[i][0],
							standardFonts[i][1],
							standardFonts[i][2],
							encoding
						);

						// adding aliases for standard fonts, this time matching the capitalization
						parts = standardFonts[i][0].split('-');
						addToFontDictionary(fontKey, parts[0], parts[1] || '');
					}

					events.publish('addFonts', { 'fonts': fonts, 'dictionary': fontmap });
				},
				/**
	
				@public
				@function
				@param text {String}
				@param flags {Object} Encoding flags.
				@returns {String} Encoded string
				*/
				to8bitStream = function (text, flags) {
					/* PDF 1.3 spec:
					"For text strings encoded in Unicode, the first two bytes must be 254 followed by
					255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts
					with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely
					to be a meaningful beginning of a word or phrase.) The remainder of the
					string consists of Unicode character codes, according to the UTF-16 encoding
					specified in the Unicode standard, version 2.0. Commonly used Unicode values
					are represented as 2 bytes per character, with the high-order byte appearing first
					in the string."
	
					In other words, if there are chars in a string with char code above 255, we
					recode the string to UCS2 BE - string doubles in length and BOM is prepended.
	
					HOWEVER!
					Actual *content* (body) text (as opposed to strings used in document properties etc)
					does NOT expect BOM. There, it is treated as a literal GID (Glyph ID)
	
					Because of Adobe's focus on "you subset your fonts!" you are not supposed to have
					a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could
					fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode
					code page. There, however, all characters in the stream are treated as GIDs,
					including BOM, which is the reason we need to skip BOM in content text (i.e. that
					that is tied to a font).
	
					To signal this "special" PDFEscape / to8bitStream handling mode,
					API.text() function sets (unless you overwrite it with manual values
					given to API.text(.., flags) )
						flags.autoencode = true
						flags.noBOM = true
	
					*/

					/*
					`flags` properties relied upon:
					.sourceEncoding = string with encoding label.
						"Unicode" by default. = encoding of the incoming text.
						pass some non-existing encoding name
						(ex: 'Do not touch my strings! I know what I am doing.')
						to make encoding code skip the encoding step.
					.outputEncoding = Either valid PDF encoding name
						(must be supported by jsPDF font metrics, otherwise no encoding)
						or a JS object, where key = sourceCharCode, value = outputCharCode
						missing keys will be treated as: sourceCharCode === outputCharCode
					.noBOM
						See comment higher above for explanation for why this is important
					.autoencode
						See comment higher above for explanation for why this is important
					*/

					var i, l, undef, sourceEncoding, encodingBlock, outputEncoding, newtext, isUnicode, ch, bch;

					if (flags === undef) {
						flags = {};
					}

					sourceEncoding = flags.sourceEncoding ? sourceEncoding : 'Unicode';

					outputEncoding = flags.outputEncoding;

					// This 'encoding' section relies on font metrics format
					// attached to font objects by, among others,
					// "Willow Systems' standard_font_metrics plugin"
					// see jspdf.plugin.standard_font_metrics.js for format
					// of the font.metadata.encoding Object.
					// It should be something like
					//   .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}}
					//   .widths = {0:width, code:width, ..., 'fof':divisor}
					//   .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...}
					if ((flags.autoencode || outputEncoding) &&
						fonts[activeFontKey].metadata &&
						fonts[activeFontKey].metadata[sourceEncoding] &&
						fonts[activeFontKey].metadata[sourceEncoding].encoding
					) {
						encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding;

						// each font has default encoding. Some have it clearly defined.
						if (!outputEncoding && fonts[activeFontKey].encoding) {
							outputEncoding = fonts[activeFontKey].encoding;
						}

						// Hmmm, the above did not work? Let's try again, in different place.
						if (!outputEncoding && encodingBlock.codePages) {
							outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default
						}

						if (typeof outputEncoding === 'string') {
							outputEncoding = encodingBlock[outputEncoding];
						}
						// we want output encoding to be a JS Object, where
						// key = sourceEncoding's character code and
						// value = outputEncoding's character code.
						if (outputEncoding) {
							isUnicode = false;
							newtext = [];
							for (i = 0, l = text.length; i < l; i++) {
								ch = outputEncoding[text.charCodeAt(i)];
								if (ch) {
									newtext.push(
										String.fromCharCode(ch)
									);
								} else {
									newtext.push(
										text[i]
									);
								}

								// since we are looping over chars anyway, might as well
								// check for residual unicodeness
								if (newtext[i].charCodeAt(0) >> 8) { /* more than 255 */
									isUnicode = true;
								}
							}
							text = newtext.join('');
						}
					}

					i = text.length;
					// isUnicode may be set to false above. Hence the triple-equal to undefined
					while (isUnicode === undef && i !== 0) {
						if (text.charCodeAt(i - 1) >> 8) { /* more than 255 */
							isUnicode = true;
						}
						i--;
					}
					if (!isUnicode) {
						return text;
					} else {
						newtext = flags.noBOM ? [] : [254, 255];
						for (i = 0, l = text.length; i < l; i++) {
							ch = text.charCodeAt(i);
							bch = ch >> 8; // divide by 256
							if (bch >> 8) { /* something left after dividing by 256 second time */
								throw new Error("Character at position " + i.toString(10) + " of string '" + text + "' exceeds 16bits. Cannot be encoded into UCS-2 BE");
							}
							newtext.push(bch);
							newtext.push(ch - (bch << 8));
						}
						return String.fromCharCode.apply(undef, newtext);
					}
				},
				// Replace '/', '(', and ')' with pdf-safe versions
				pdfEscape = function (text, flags) {
					// doing to8bitStream does NOT make this PDF display unicode text. For that
					// we also need to reference a unicode font and embed it - royal pain in the rear.

					// There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars,
					// which JavaScript Strings are happy to provide. So, while we still cannot display
					// 2-byte characters property, at least CONDITIONALLY converting (entire string containing)
					// 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF
					// is still parseable.
					// This will allow immediate support for unicode in document properties strings.
					return to8bitStream(text, flags).replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
				},
				putInfo = function () {
					out('/Producer (jsPDF ' + version + ')');
					if (documentProperties.title) {
						out('/Title (' + pdfEscape(documentProperties.title) + ')');
					}
					if (documentProperties.subject) {
						out('/Subject (' + pdfEscape(documentProperties.subject) + ')');
					}
					if (documentProperties.author) {
						out('/Author (' + pdfEscape(documentProperties.author) + ')');
					}
					if (documentProperties.keywords) {
						out('/Keywords (' + pdfEscape(documentProperties.keywords) + ')');
					}
					if (documentProperties.creator) {
						out('/Creator (' + pdfEscape(documentProperties.creator) + ')');
					}
					var created = new Date();
					out('/CreationDate (D:' +
						[
							created.getFullYear(),
							padd2(created.getMonth() + 1),
							padd2(created.getDate()),
							padd2(created.getHours()),
							padd2(created.getMinutes()),
							padd2(created.getSeconds())
						].join('') +
						')'
					);
				},
				putCatalog = function () {
					out('/Type /Catalog');
					out('/Pages 1 0 R');
					// @TODO: Add zoom and layout modes
					out('/OpenAction [3 0 R /FitH null]');
					out('/PageLayout /OneColumn');
					events.publish('putCatalog');
				},
				putTrailer = function () {
					out('/Size ' + (objectNumber + 1));
					out('/Root ' + objectNumber + ' 0 R');
					out('/Info ' + (objectNumber - 1) + ' 0 R');
				},
				beginPage = function () {
					page++;
					// Do dimension stuff
					outToPages = true;
					pages[page] = [];
				},
				_addPage = function () {
					beginPage();
					// Set line width
					out(f2(lineWidth * k) + ' w');
					// Set draw color
					out(drawColor);
					// resurrecting non-default line caps, joins
					if (lineCapID !== 0) {
						out(lineCapID.toString(10) + ' J');
					}
					if (lineJoinID !== 0) {
						out(lineJoinID.toString(10) + ' j');
					}
					events.publish('addPage', { 'pageNumber': page });
				},
				/**
				Returns a document-specific font key - a label assigned to a
				font name + font type combination at the time the font was added
				to the font inventory.
	
				Font key is used as label for the desired font for a block of text
				to be added to the PDF document stream.
				@private
				@function
				@param fontName {String} can be undefined on "falthy" to indicate "use current"
				@param fontStyle {String} can be undefined on "falthy" to indicate "use current"
				@returns {String} Font key.
				*/
				getFont = function (fontName, fontStyle) {
					var key, undef;

					if (fontName === undef) {
						fontName = fonts[activeFontKey].fontName;
					}
					if (fontStyle === undef) {
						fontStyle = fonts[activeFontKey].fontStyle;
					}

					try {
						key = fontmap[fontName][fontStyle]; // returns a string like 'F3' - the KEY corresponding tot he font + type combination.
					} catch (e) {
						key = undef;
					}
					if (!key) {
						throw new Error("Unable to look up font label for font '" + fontName + "', '" + fontStyle + "'. Refer to getFontList() for available fonts.");
					}

					return key;
				},
				buildDocument = function () {

					outToPages = false; // switches out() to content
					content = [];
					offsets = [];

					// putHeader()
					out('%PDF-' + pdfVersion);

					putPages();

					putResources();

					// Info
					newObject();
					out('<<');
					putInfo();
					out('>>');
					out('endobj');

					// Catalog
					newObject();
					out('<<');
					putCatalog();
					out('>>');
					out('endobj');

					// Cross-ref
					var o = content_length, i;
					out('xref');
					out('0 ' + (objectNumber + 1));
					out('0000000000 65535 f ');
					for (i = 1; i <= objectNumber; i++) {
						out(padd10(offsets[i]) + ' 00000 n ');
					}
					// Trailer
					out('trailer');
					out('<<');
					putTrailer();
					out('>>');
					out('startxref');
					out(o);
					out('%%EOF');

					outToPages = true;

					return content.join('\n');
				},
				getStyle = function (style) {
					// see Path-Painting Operators of PDF spec
					var op = 'S'; // stroke
					if (style === 'F') {
						op = 'f'; // fill
					} else if (style === 'FD' || style === 'DF') {
						op = 'B'; // both
					}
					return op;
				},

				/**
				Generates the PDF document.
				Possible values:
					datauristring (alias dataurlstring) - Data-Url-formatted data returned as string.
					datauri (alias datauri) - Data-Url-formatted data pushed into current window's location (effectively reloading the window with contents of the PDF).
	
				If `type` argument is undefined, output is raw body of resulting PDF returned as a string.
	
				@param {String} type A string identifying one of the possible output types.
				@param {Object} options An object providing some additional signalling to PDF generator.
				@function
				@returns {jsPDF}
				@methodOf jsPDF#
				@name output
				*/
				output = function (type, options) {

					//for safari type -dataurlnewwindow-

					var undef, data, length, array, i, blob;
					switch (type) {
						case undef:
							return buildDocument();
						case 'save':
							if (navigator.getUserMedia) {
								if (window.URL === undefined) {
									return API.output('dataurlnewwindow');
								} else if (window.URL.createObjectURL === undefined) {
									return API.output('dataurlnewwindow');
								}
							}
							data = buildDocument();

							// Need to add the file to BlobBuilder as a Uint8Array
							length = data.length;
							array = new Uint8Array(new ArrayBuffer(length));

							for (i = 0; i < length; i++) {
								array[i] = data.charCodeAt(i);
							}

							blob = new Blob([array], { type: "application/pdf" });

							saveAs(blob, options);
							break;
						case 'datauristring':
						case 'dataurlstring':
							return 'data:application/pdf;base64,' + btoa(buildDocument());
						case 'datauri':
						case 'dataurl':
							document.location.href = 'data:application/pdf;base64,' + btoa(buildDocument());
							break;
						case 'dataurlnewwindow':
							window.open('data:application/pdf;base64,' + btoa(buildDocument()));
							break;
						default:
							throw new Error('Output type "' + type + '" is not supported.');
					}
					// @TODO: Add different output options

				};

			if (unit === 'pt') {
				k = 1;
			} else if (unit === 'mm') {
				k = 72 / 25.4;
			} else if (unit === 'cm') {
				k = 72 / 2.54;
			} else if (unit === 'in') {
				k = 72;
			} else {
				throw ('Invalid unit: ' + unit);
			}

			// Dimensions are stored as user units and converted to points on output
			if (pageFormats.hasOwnProperty(format_as_string)) {
				pageHeight = pageFormats[format_as_string][1] / k;
				pageWidth = pageFormats[format_as_string][0] / k;
			} else {
				try {
					pageHeight = format[1];
					pageWidth = format[0];
				} catch (err) {
					throw ('Invalid format: ' + format);
				}
			}

			if (orientation === 'p' || orientation === 'portrait') {
				orientation = 'p';
				if (pageWidth > pageHeight) {
					tmp = pageWidth;
					pageWidth = pageHeight;
					pageHeight = tmp;
				}
			} else if (orientation === 'l' || orientation === 'landscape') {
				orientation = 'l';
				if (pageHeight > pageWidth) {
					tmp = pageWidth;
					pageWidth = pageHeight;
					pageHeight = tmp;
				}
			} else {
				throw ('Invalid orientation: ' + orientation);
			}



			//---------------------------------------
			// Public API

			/*
			Object exposing internal API to plugins
			@public
			*/
			API.internal = {
				'pdfEscape': pdfEscape,
				'getStyle': getStyle,
				/**
				Returns {FontObject} describing a particular font.
				@public
				@function
				@param fontName {String} (Optional) Font's family name
				@param fontStyle {String} (Optional) Font's style variation name (Example:"Italic")
				@returns {FontObject}
				*/
				'getFont': function () { return fonts[getFont.apply(API, arguments)]; },
				'getFontSize': function () { return activeFontSize; },
				'btoa': btoa,
				'write': function (string1, string2, string3, etc) {
					out(
						arguments.length === 1 ? string1 : Array.prototype.join.call(arguments, ' ')
					);
				},
				'getCoordinateString': function (value) {
					return f2(value * k);
				},
				'getVerticalCoordinateString': function (value) {
					return f2((pageHeight - value) * k);
				},
				'collections': {},
				'newObject': newObject,
				'putStream': putStream,
				'events': events,
				// ratio that you use in multiplication of a given "size" number to arrive to 'point'
				// units of measurement.
				// scaleFactor is set at initialization of the document and calculated against the stated
				// default measurement units for the document.
				// If default is "mm", k is the number that will turn number in 'mm' into 'points' number.
				// through multiplication.
				'scaleFactor': k,
				'pageSize': { 'width': pageWidth, 'height': pageHeight },
				'output': function (type, options) {
					return output(type, options);
				}
			};

			/**
			Adds (and transfers the focus to) new page to the PDF document.
			@function
			@returns {jsPDF}
	
			@methodOf jsPDF#
			@name addPage
			 */
			API.addPage = function () {
				_addPage();
				return this;
			};

			/**
			Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings.
			@function
			@param {String|Array} text String or array of strings to be added to the page. Each line is shifted one line down per font, spacing settings declared before this call.
			@param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
			@param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
			@param {Object} flags Collection of settings signalling how the text must be encoded. Defaults are sane. If you think you want to pass some flags, you likely can read the source.
			@returns {jsPDF}
			@methodOf jsPDF#
			@name text
			 */
			API.text = function (text, x, y, flags) {
				/**
				 * Inserts something like this into PDF
					BT
					/F1 16 Tf  % Font name + size
					16 TL % How many units down for next line in multiline text
					0 g % color
					28.35 813.54 Td % position
					(line one) Tj
					T* (line two) Tj
					T* (line three) Tj
					ET
				*/

				var undef, _first, _second, _third, newtext, str, i;
				// Pre-August-2012 the order of arguments was function(x, y, text, flags)
				// in effort to make all calls have similar signature like
				//   function(data, coordinates... , miscellaneous)
				// this method had its args flipped.
				// code below allows backward compatibility with old arg order.
				if (typeof text === 'number') {
					_first = y;
					_second = text;
					_third = x;

					text = _first;
					x = _second;
					y = _third;
				}

				// If there are any newlines in text, we assume
				// the user wanted to print multiple lines, so break the
				// text up into an array.  If the text is already an array,
				// we assume the user knows what they are doing.
				if (typeof text === 'string' && text.match(/[\n\r]/)) {
					text = text.split(/\r\n|\r|\n/g);
				}

				if (typeof flags === 'undefined') {
					flags = { 'noBOM': true, 'autoencode': true };
				} else {

					if (flags.noBOM === undef) {
						flags.noBOM = true;
					}

					if (flags.autoencode === undef) {
						flags.autoencode = true;
					}

				}

				if (typeof text === 'string') {
					str = pdfEscape(text, flags);
				} else if (text instanceof Array) {  /* Array */
					// we don't want to destroy  original text array, so cloning it
					newtext = text.concat();
					// we do array.join('text that must not be PDFescaped")
					// thus, pdfEscape each component separately
					for (i = newtext.length - 1; i !== -1; i--) {
						newtext[i] = pdfEscape(newtext[i], flags);
					}
					str = newtext.join(") Tj\nT* (");
				} else {
					throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.');
				}
				// Using "'" ("go next line and render text" mark) would save space but would complicate our rendering code, templates

				// BT .. ET does NOT have default settings for Tf. You must state that explicitely every time for BT .. ET
				// if you want text transformation matrix (+ multiline) to work reliably (which reads sizes of things from font declarations)
				// Thus, there is NO useful, *reliable* concept of "default" font for a page.
				// The fact that "default" (reuse font used before) font worked before in basic cases is an accident
				// - readers dealing smartly with brokenness of jsPDF's markup.
				out(
					'BT\n/' +
					activeFontKey + ' ' + activeFontSize + ' Tf\n' + // font face, style, size
					activeFontSize + ' TL\n' + // line spacing
					textColor +
					'\n' + f2(x * k) + ' ' + f2((pageHeight - y) * k) + ' Td\n(' +
					str +
					') Tj\nET'
				);
				return this;
			};

			API.line = function (x1, y1, x2, y2) {
				out(
					f2(x1 * k) + ' ' + f2((pageHeight - y1) * k) + ' m ' +
					f2(x2 * k) + ' ' + f2((pageHeight - y2) * k) + ' l S'
				);
				return this;
			};

			/**
			Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates.
			All data points in `lines` are relative to last line origin.
			`x`, `y` become x1,y1 for first line / curve in the set.
			For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point.
			For bezier curves you need to specify [x2,y2,x3,y3,x4,y4] - vectors to control points 1, 2, ending point. All vectors are against the start of the curve - x1,y1.
	
			@example .lines([[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 212,110, 10) // line, line, bezier curve, line
			@param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves).
			@param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
			@param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
			@param {Number} scale (Defaults to [1.0,1.0]) x,y Scaling factor for all vectors. Elements can be any floating number Sub-one makes drawing smaller. Over-one grows the drawing. Negative flips the direction.
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name lines
			 */
			API.lines = function (lines, x, y, scale, style) {
				var undef, _first, _second, _third, scalex, scaley, i, l, leg, x2, y2, x3, y3, x4, y4;

				// Pre-August-2012 the order of arguments was function(x, y, lines, scale, style)
				// in effort to make all calls have similar signature like
				//   function(content, coordinateX, coordinateY , miscellaneous)
				// this method had its args flipped.
				// code below allows backward compatibility with old arg order.
				if (typeof lines === 'number') {
					_first = y;
					_second = lines;
					_third = x;

					lines = _first;
					x = _second;
					y = _third;
				}

				style = getStyle(style);
				scale = scale === undef ? [1, 1] : scale;

				// starting point
				out(f3(x * k) + ' ' + f3((pageHeight - y) * k) + ' m ');

				scalex = scale[0];
				scaley = scale[1];
				l = lines.length;
				//, x2, y2 // bezier only. In page default measurement "units", *after* scaling
				//, x3, y3 // bezier only. In page default measurement "units", *after* scaling
				// ending point for all, lines and bezier. . In page default measurement "units", *after* scaling
				x4 = x; // last / ending point = starting point for first item.
				y4 = y; // last / ending point = starting point for first item.

				for (i = 0; i < l; i++) {
					leg = lines[i];
					if (leg.length === 2) {
						// simple line
						x4 = leg[0] * scalex + x4; // here last x4 was prior ending point
						y4 = leg[1] * scaley + y4; // here last y4 was prior ending point
						out(f3(x4 * k) + ' ' + f3((pageHeight - y4) * k) + ' l');
					} else {
						// bezier curve
						x2 = leg[0] * scalex + x4; // here last x4 is prior ending point
						y2 = leg[1] * scaley + y4; // here last y4 is prior ending point
						x3 = leg[2] * scalex + x4; // here last x4 is prior ending point
						y3 = leg[3] * scaley + y4; // here last y4 is prior ending point
						x4 = leg[4] * scalex + x4; // here last x4 was prior ending point
						y4 = leg[5] * scaley + y4; // here last y4 was prior ending point
						out(
							f3(x2 * k) + ' ' +
							f3((pageHeight - y2) * k) + ' ' +
							f3(x3 * k) + ' ' +
							f3((pageHeight - y3) * k) + ' ' +
							f3(x4 * k) + ' ' +
							f3((pageHeight - y4) * k) + ' c'
						);
					}
				}
				// stroking / filling / both the path
				out(style);
				return this;
			};

			/**
			Adds a rectangle to PDF
	
			@param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
			@param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
			@param {Number} w Width (in units declared at inception of PDF document)
			@param {Number} h Height (in units declared at inception of PDF document)
			@param {String} style (Defaults to active fill/stroke style) A string signalling if stroke, fill or both are to be applied.
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name rect
			 */
			API.rect = function (x, y, w, h, style) {
				var op = getStyle(style);
				out([
					f2(x * k),
					f2((pageHeight - y) * k),
					f2(w * k),
					f2(-h * k),
					're',
					op
				].join(' '));
				return this;
			};

			/**
			Adds a properties to the PDF document
	
			@param {Object} A property_name-to-property_value object structure.
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name setProperties
			 */
			API.setProperties = function (properties) {
				// copying only those properties we can render.
				var property;
				for (property in documentProperties) {
					if (documentProperties.hasOwnProperty(property) && properties[property]) {
						documentProperties[property] = properties[property];
					}
				}
				return this;
			};

			/**
			Sets font size for upcoming text elements.
	
			@param {Number} size Font size in points.
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name setFontSize
			 */
			API.setFontSize = function (size) {
				activeFontSize = size;
				return this;
			};

			/**
			Sets text font face, variant for upcoming text elements.
			See output of jsPDF.getFontList() for possible font names, styles.
	
			@param {String} fontName Font name or family. Example: "times"
			@param {String} fontStyle Font style or variant. Example: "italic"
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name setFont
			 */
			API.setFont = function (fontName, fontStyle) {
				activeFontKey = getFont(fontName, fontStyle);
				// if font is not found, the above line blows up and we never go further
				return this;
			};

			/**
			Switches font style or variant for upcoming text elements,
			while keeping the font face or family same.
			See output of jsPDF.getFontList() for possible font names, styles.
	
			@param {String} style Font style or variant. Example: "italic"
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name setFontStyle
			 */
			API.setFontStyle = API.setFontType = function (style) {
				var undef;
				activeFontKey = getFont(undef, style);
				// if font is not found, the above line blows up and we never go further
				return this;
			};

			/**
			Returns an object - a tree of fontName to fontStyle relationships available to
			active PDF document.
	
			@public
			@function
			@returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... }
			@methodOf jsPDF#
			@name getFontList
			*/
			API.getFontList = function () {
				// TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
				var list = {},
					fontName,
					fontStyle,
					tmp;

				for (fontName in fontmap) {
					if (fontmap.hasOwnProperty(fontName)) {
						list[fontName] = tmp = [];
						for (fontStyle in fontmap[fontName]) {
							if (fontmap[fontName].hasOwnProperty(fontStyle)) {
								tmp.push(fontStyle);
							}
						}
					}
				}

				return list;
			};

			/**
			Sets line width for upcoming lines.
	
			@param {Number} width Line width (in units declared at inception of PDF document)
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name setLineWidth
			 */
			API.setLineWidth = function (width) {
				out((width * k).toFixed(2) + ' w');
				return this;
			};

			/**
			Sets the stroke color for upcoming elements.
	
			Depending on the number of arguments given, Gray, RGB, or CMYK
			color space is implied.
	
			When only ch1 is given, "Gray" color space is implied and it
			must be a value in the range from 0.00 (solid black) to to 1.00 (white)
			if values are communicated as String types, or in range from 0 (black)
			to 255 (white) if communicated as Number type.
			The RGB-like 0-255 range is provided for backward compatibility.
	
			When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
			value must be in the range from 0.00 (minimum intensity) to to 1.00
			(max intensity) if values are communicated as String types, or
			from 0 (min intensity) to to 255 (max intensity) if values are communicated
			as Number types.
			The RGB-like 0-255 range is provided for backward compatibility.
	
			When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
			value must be a in the range from 0.00 (0% concentration) to to
			1.00 (100% concentration)
	
			Because JavaScript treats fixed point numbers badly (rounds to
			floating point nearest to binary representation) it is highly advised to
			communicate the fractional numbers as String types, not JavaScript Number type.
	
			@param {Number|String} ch1 Color channel value
			@param {Number|String} ch2 Color channel value
			@param {Number|String} ch3 Color channel value
			@param {Number|String} ch4 Color channel value
	
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name setDrawColor
			 */
			API.setDrawColor = function (ch1, ch2, ch3, ch4) {
				var color;
				if (ch2 === undefined || (ch4 === undefined && ch1 === ch2 === ch3)) {
					// Gray color space.
					if (typeof ch1 === 'string') {
						color = ch1 + ' G';
					} else {
						color = f2(ch1 / 255) + ' G';
					}
				} else if (ch4 === undefined) {
					// RGB
					if (typeof ch1 === 'string') {
						color = [ch1, ch2, ch3, 'RG'].join(' ');
					} else {
						color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), 'RG'].join(' ');
					}
				} else {
					// CMYK
					if (typeof ch1 === 'string') {
						color = [ch1, ch2, ch3, ch4, 'K'].join(' ');
					} else {
						color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), 'K'].join(' ');
					}
				}

				out(color);
				return this;
			};

			/**
			Sets the fill color for upcoming elements.
	
			Depending on the number of arguments given, Gray, RGB, or CMYK
			color space is implied.
	
			When only ch1 is given, "Gray" color space is implied and it
			must be a value in the range from 0.00 (solid black) to to 1.00 (white)
			if values are communicated as String types, or in range from 0 (black)
			to 255 (white) if communicated as Number type.
			The RGB-like 0-255 range is provided for backward compatibility.
	
			When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
			value must be in the range from 0.00 (minimum intensity) to to 1.00
			(max intensity) if values are communicated as String types, or
			from 0 (min intensity) to to 255 (max intensity) if values are communicated
			as Number types.
			The RGB-like 0-255 range is provided for backward compatibility.
	
			When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
			value must be a in the range from 0.00 (0% concentration) to to
			1.00 (100% concentration)
	
			Because JavaScript treats fixed point numbers badly (rounds to
			floating point nearest to binary representation) it is highly advised to
			communicate the fractional numbers as String types, not JavaScript Number type.
	
			@param {Number|String} ch1 Color channel value
			@param {Number|String} ch2 Color channel value
			@param {Number|String} ch3 Color channel value
			@param {Number|String} ch4 Color channel value
	
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name setFillColor
			 */
			API.setFillColor = function (ch1, ch2, ch3, ch4) {
				var color;

				if (ch2 === undefined || (ch4 === undefined && ch1 === ch2 === ch3)) {
					// Gray color space.
					if (typeof ch1 === 'string') {
						color = ch1 + ' g';
					} else {
						color = f2(ch1 / 255) + ' g';
					}
				} else if (ch4 === undefined) {
					// RGB
					if (typeof ch1 === 'string') {
						color = [ch1, ch2, ch3, 'rg'].join(' ');
					} else {
						color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), 'rg'].join(' ');
					}
				} else {
					// CMYK
					if (typeof ch1 === 'string') {
						color = [ch1, ch2, ch3, ch4, 'k'].join(' ');
					} else {
						color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), 'k'].join(' ');
					}
				}

				out(color);
				return this;
			};

			/**
			Sets the text color for upcoming elements.
			If only one, first argument is given,
			treats the value as gray-scale color value.
	
			@param {Number} r Red channel color value in range 0-255
			@param {Number} g Green channel color value in range 0-255
			@param {Number} b Blue channel color value in range 0-255
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name setTextColor
			*/
			API.setTextColor = function (r, g, b) {
				if ((r === 0 && g === 0 && b === 0) || (typeof g === 'undefined')) {
					textColor = f3(r / 255) + ' g';
				} else {
					textColor = [f3(r / 255), f3(g / 255), f3(b / 255), 'rg'].join(' ');
				}
				return this;
			};

			/**
			Is an Object providing a mapping from human-readable to
			integer flag values designating the varieties of line cap
			and join styles.
	
			@returns {Object}
			@fieldOf jsPDF#
			@name CapJoinStyles
			*/
			API.CapJoinStyles = {
				0: 0,
				'butt': 0,
				'but': 0,
				'bevel': 0,
				1: 1,
				'round': 1,
				'rounded': 1,
				'circle': 1,
				2: 2,
				'projecting': 2,
				'project': 2,
				'square': 2,
				'milter': 2
			};

			/**
			Sets the line cap styles
			See {jsPDF.CapJoinStyles} for variants
	
			@param {String|Number} style A string or number identifying the type of line cap
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name setLineCap
			*/
			API.setLineCap = function (style) {
				var id = this.CapJoinStyles[style];
				if (id === undefined) {
					throw new Error("Line cap style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
				}
				lineCapID = id;
				out(id.toString(10) + ' J');

				return this;
			};

			/**
			Sets the line join styles
			See {jsPDF.CapJoinStyles} for variants
	
			@param {String|Number} style A string or number identifying the type of line join
			@function
			@returns {jsPDF}
			@methodOf jsPDF#
			@name setLineJoin
			*/
			API.setLineJoin = function (style) {
				var id = this.CapJoinStyles[style];
				if (id === undefined) {
					throw new Error("Line join style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
				}
				lineJoinID = id;
				out(id.toString(10) + ' j');

				return this;
			};

			// Output is both an internal (for plugins) and external function
			API.output = output;

			/**
			 * Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf')
			 * @param  {String} filename The filename including extension.
			 *
			 * @function
			 * @returns {jsPDF}
			 * @methodOf jsPDF#
			 * @name save
			 */
			API.save = function (filename) {
				API.output('save', filename);
			};

			// applying plugins (more methods) ON TOP of built-in API.
			// this is intentional as we allow plugins to override
			// built-ins
			for (plugin in jsPDF.API) {
				if (jsPDF.API.hasOwnProperty(plugin)) {
					if (plugin === 'events' && jsPDF.API.events.length) {
						(function (events, newEvents) {

							// jsPDF.API.events is a JS Array of Arrays
							// where each Array is a pair of event name, handler
							// Events were added by plugins to the jsPDF instantiator.
							// These are always added to the new instance and some ran
							// during instantiation.

							var eventname, handler_and_args, i;

							for (i = newEvents.length - 1; i !== -1; i--) {
								// subscribe takes 3 args: 'topic', function, runonce_flag
								// if undefined, runonce is false.
								// users can attach callback directly,
								// or they can attach an array with [callback, runonce_flag]
								// that's what the "apply" magic is for below.
								eventname = newEvents[i][0];
								handler_and_args = newEvents[i][1];
								events.subscribe.apply(
									events,
									[eventname].concat(
										typeof handler_and_args === 'function' ?
											[handler_and_args] :
											handler_and_args
									)
								);
							}
						}(events, jsPDF.API.events));
					} else {
						API[plugin] = jsPDF.API[plugin];
					}
				}
			}

			/////////////////////////////////////////
			// continuing initilisation of jsPDF Document object
			/////////////////////////////////////////


			// Add the first page automatically
			addFonts();
			activeFontKey = 'F1';
			_addPage();

			events.publish('initialized');

			return API;
		}


		/**
		jsPDF.API is a STATIC property of jsPDF class.
		jsPDF.API is an object you can add methods and properties to.
		The methods / properties you add will show up in new jsPDF objects.
		
		One property is prepopulated. It is the 'events' Object. Plugin authors can add topics, callbacks to this object. These will be reassigned to all new instances of jsPDF.
		Examples:
			jsPDF.API.events['initialized'] = function(){ 'this' is API object }
			jsPDF.API.events['addFont'] = function(added_font_object){ 'this' is API object }
		
		@static
		@public
		@memberOf jsPDF
		@name API
		
		@example
			jsPDF.API.mymethod = function(){
				// 'this' will be ref to internal API object. see jsPDF source
				// , so you can refer to built-in methods like so:
				//     this.line(....)
				//     this.text(....)
			}
			var pdfdoc = new jsPDF()
			pdfdoc.mymethod() // <- !!!!!!
		*/
		jsPDF.API = { 'events': [] };

		return jsPDF;
	}());



	var Base64 = {

		// private property
		_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

		// public method for encoding
		encode: function (input) {
			var output = "";
			var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
			var i = 0;

			input = Base64._utf8_encode(input);

			while (i < input.length) {

				chr1 = input.charCodeAt(i++);
				chr2 = input.charCodeAt(i++);
				chr3 = input.charCodeAt(i++);

				enc1 = chr1 >> 2;
				enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
				enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
				enc4 = chr3 & 63;

				if (isNaN(chr2)) {
					enc3 = enc4 = 64;
				} else if (isNaN(chr3)) {
					enc4 = 64;
				}

				output = output +
					this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
					this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

			}

			return output;
		},

		// public method for decoding
		decode: function (input) {
			var output = "";
			var chr1, chr2, chr3;
			var enc1, enc2, enc3, enc4;
			var i = 0;

			input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

			while (i < input.length) {

				enc1 = this._keyStr.indexOf(input.charAt(i++));
				enc2 = this._keyStr.indexOf(input.charAt(i++));
				enc3 = this._keyStr.indexOf(input.charAt(i++));
				enc4 = this._keyStr.indexOf(input.charAt(i++));

				chr1 = (enc1 << 2) | (enc2 >> 4);
				chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
				chr3 = ((enc3 & 3) << 6) | enc4;

				output = output + String.fromCharCode(chr1);

				if (enc3 != 64) {
					output = output + String.fromCharCode(chr2);
				}
				if (enc4 != 64) {
					output = output + String.fromCharCode(chr3);
				}

			}

			output = Base64._utf8_decode(output);

			return output;

		},

		// private method for UTF-8 encoding
		_utf8_encode: function (string) {
			string = string.replace(/\r\n/g, "\n");
			var utftext = "";

			for (var n = 0; n < string.length; n++) {

				var c = string.charCodeAt(n);

				if (c < 128) {
					utftext += String.fromCharCode(c);
				}
				else if ((c > 127) && (c < 2048)) {
					utftext += String.fromCharCode((c >> 6) | 192);
					utftext += String.fromCharCode((c & 63) | 128);
				}
				else {
					utftext += String.fromCharCode((c >> 12) | 224);
					utftext += String.fromCharCode(((c >> 6) & 63) | 128);
					utftext += String.fromCharCode((c & 63) | 128);
				}

			}

			return utftext;
		},

		// private method for UTF-8 decoding
		_utf8_decode: function (utftext) {
			var string = "";
			var i = 0;
			var c = c1 = c2 = 0;

			while (i < utftext.length) {

				c = utftext.charCodeAt(i);

				if (c < 128) {
					string += String.fromCharCode(c);
					i++;
				}
				else if ((c > 191) && (c < 224)) {
					c2 = utftext.charCodeAt(i + 1);
					string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
					i += 2;
				}
				else {
					c2 = utftext.charCodeAt(i + 1);
					c3 = utftext.charCodeAt(i + 2);
					string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
					i += 3;
				}

			}

			return string;
		}

	};



	function sprintf() {
		// Return a formatted string  
		// 
		// version: 903.3016
		// discuss at: http://phpjs.org/functions/sprintf
		// +   original by: Ash Searle (http://hexmen.com/blog/)
		// + namespaced by: Michael White (http://getsprink.com)
		// +    tweaked by: Jack
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +      input by: Paulo Ricardo F. Santos
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +      input by: Brett Zamir (http://brettz9.blogspot.com)
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// *     example 1: sprintf("%01.2f", 123.1);
		// *     returns 1: 123.10
		// *     example 2: sprintf("[%10s]", 'monkey');
		// *     returns 2: '[    monkey]'
		// *     example 3: sprintf("[%'#10s]", 'monkey');
		// *     returns 3: '[####monkey]'
		var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
		var a = arguments, i = 0, format = a[i++];

		// pad()
		var pad = function (str, len, chr, leftJustify) {
			if (!chr) chr = ' ';
			var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
			return leftJustify ? str + padding : padding + str;
		};

		// justify()
		var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) {
			var diff = minWidth - value.length;
			if (diff > 0) {
				if (leftJustify || !zeroPad) {
					value = pad(value, minWidth, customPadChar, leftJustify);
				} else {
					value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
				}
			}
			return value;
		};

		// formatBaseX()
		var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
			// Note: casts negative numbers to positive ones
			var number = value >>> 0;
			prefix = prefix && number && { '2': '0b', '8': '0', '16': '0x' }[base] || '';
			value = prefix + pad(number.toString(base), precision || 0, '0', false);
			return justify(value, prefix, leftJustify, minWidth, zeroPad);
		};

		// formatString()
		var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) {
			if (precision != null) {
				value = value.slice(0, precision);
			}
			return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
		};

		// doFormat()
		var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) {
			var number;
			var prefix;
			var method;
			var textTransform;
			var value;

			if (substring == '%%') return '%';

			// parse flags
			var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, customPadChar = ' ';
			var flagsl = flags.length;
			for (var j = 0; flags && j < flagsl; j++) switch (flags.charAt(j)) {
				case ' ': positivePrefix = ' '; break;
				case '+': positivePrefix = '+'; break;
				case '-': leftJustify = true; break;
				case "'": customPadChar = flags.charAt(j + 1); break;
				case '0': zeroPad = true; break;
				case '#': prefixBaseX = true; break;
			}

			// parameters may be null, undefined, empty-string or real valued
			// we want to ignore null, undefined and empty-string values
			if (!minWidth) {
				minWidth = 0;
			} else if (minWidth == '*') {
				minWidth = +a[i++];
			} else if (minWidth.charAt(0) == '*') {
				minWidth = +a[minWidth.slice(1, -1)];
			} else {
				minWidth = +minWidth;
			}

			// Note: undocumented perl feature:
			if (minWidth < 0) {
				minWidth = -minWidth;
				leftJustify = true;
			}

			if (!isFinite(minWidth)) {
				throw new Error('sprintf: (minimum-)width must be finite');
			}

			if (!precision) {
				precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void (0);
			} else if (precision == '*') {
				precision = +a[i++];
			} else if (precision.charAt(0) == '*') {
				precision = +a[precision.slice(1, -1)];
			} else {
				precision = +precision;
			}

			// grab value using valueIndex if required?
			value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];

			switch (type) {
				case 's': return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);
				case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
				case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
				case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
				case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
				case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
				case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
				case 'i':
				case 'd': {
					number = parseInt(+value);
					prefix = number < 0 ? '-' : positivePrefix;
					value = prefix + pad(String(Math.abs(number)), precision, '0', false);
					return justify(value, prefix, leftJustify, minWidth, zeroPad);
				}
				case 'e':
				case 'E':
				case 'f':
				case 'F':
				case 'g':
				case 'G': {
					number = +value;
					prefix = number < 0 ? '-' : positivePrefix;
					method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
					textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
					value = prefix + Math.abs(number)[method](precision);
					return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
				}
				default: return substring;
			}
		};

		return format.replace(regex, doFormat);
	}







	; (function (jsPDFAPI) {
		'use strict'

		var namespace = 'addImage_'

		// takes a string imgData containing the raw bytes of
		// a jpeg image and returns [width, height]
		// Algorithm from: http://www.64lines.com/jpeg-width-height
		var getJpegSize = function (imgData) {
			'use strict'
			var width, height;
			// Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
			if (!imgData.charCodeAt(0) === 0xff ||
				!imgData.charCodeAt(1) === 0xd8 ||
				!imgData.charCodeAt(2) === 0xff ||
				!imgData.charCodeAt(3) === 0xe0 ||
				!imgData.charCodeAt(6) === 'J'.charCodeAt(0) ||
				!imgData.charCodeAt(7) === 'F'.charCodeAt(0) ||
				!imgData.charCodeAt(8) === 'I'.charCodeAt(0) ||
				!imgData.charCodeAt(9) === 'F'.charCodeAt(0) ||
				!imgData.charCodeAt(10) === 0x00) {
				throw new Error('getJpegSize requires a binary jpeg file')
			}
			var blockLength = imgData.charCodeAt(4) * 256 + imgData.charCodeAt(5);
			var i = 4, len = imgData.length;
			while (i < len) {
				i += blockLength;
				if (imgData.charCodeAt(i) !== 0xff) {
					throw new Error('getJpegSize could not find the size of the image');
				}
				if (imgData.charCodeAt(i + 1) === 0xc0) {
					height = imgData.charCodeAt(i + 5) * 256 + imgData.charCodeAt(i + 6);
					width = imgData.charCodeAt(i + 7) * 256 + imgData.charCodeAt(i + 8);
					return [width, height];
				} else {
					i += 2;
					blockLength = imgData.charCodeAt(i) * 256 + imgData.charCodeAt(i + 1)
				}
			}
		}
			// Image functionality ported from pdf.js
			, putImage = function (img) {
				var objectNumber = this.internal.newObject()
					, out = this.internal.write
					, putStream = this.internal.putStream

				img['n'] = objectNumber

				out('<</Type /XObject')
				out('/Subtype /Image')
				out('/Width ' + img['w'])
				out('/Height ' + img['h'])
				if (img['cs'] === 'Indexed') {
					out('/ColorSpace [/Indexed /DeviceRGB '
						+ (img['pal'].length / 3 - 1) + ' ' + (objectNumber + 1)
						+ ' 0 R]');
				} else {
					out('/ColorSpace /' + img['cs']);
					if (img['cs'] === 'DeviceCMYK') {
						out('/Decode [1 0 1 0 1 0 1 0]');
					}
				}
				out('/BitsPerComponent ' + img['bpc']);
				if ('f' in img) {
					out('/Filter /' + img['f']);
				}
				if ('dp' in img) {
					out('/DecodeParms <<' + img['dp'] + '>>');
				}
				if ('trns' in img && img['trns'].constructor == Array) {
					var trns = '';
					for (var i = 0; i < img['trns'].length; i++) {
						trns += (img[trns][i] + ' ' + img['trns'][i] + ' ');
						out('/Mask [' + trns + ']');
					}
				}
				if ('smask' in img) {
					out('/SMask ' + (objectNumber + 1) + ' 0 R');
				}
				out('/Length ' + img['data'].length + '>>');

				putStream(img['data']);

				out('endobj');
			}
			, putResourcesCallback = function () {
				var images = this.internal.collections[namespace + 'images']
				for (var i in images) {
					putImage.call(this, images[i])
				}
			}
			, putXObjectsDictCallback = function () {
				var images = this.internal.collections[namespace + 'images']
					, out = this.internal.write
					, image
				for (var i in images) {
					image = images[i]
					out(
						'/I' + image['i']
						, image['n']
						, '0'
						, 'R'
					)
				}
			}

		jsPDFAPI.addImage = function (imageData, format, x, y, w, h) {
			'use strict'
			if (typeof imageData === 'object' && imageData.nodeType === 1) {
				var canvas = document.createElement('canvas');
				canvas.width = imageData.clientWidth;
				canvas.height = imageData.clientHeight;

				var ctx = canvas.getContext('2d');
				if (!ctx) {
					throw ('addImage requires canvas to be supported by browser.');
				}
				ctx.drawImage(imageData, 0, 0, canvas.width, canvas.height);
				imageData = canvas.toDataURL('image/jpeg');
				format = "JPEG";
			}
			if (format.toUpperCase() !== 'JPEG') {
				throw new Error('addImage currently only supports format \'JPEG\', not \'' + format + '\'');
			}

			var imageIndex
				, images = this.internal.collections[namespace + 'images']
				, coord = this.internal.getCoordinateString
				, vcoord = this.internal.getVerticalCoordinateString;

			// Detect if the imageData is raw binary or Data URL
			if (imageData.substring(0, 23) === 'data:image/jpeg;base64,') {
				imageData = atob(imageData.replace('data:image/jpeg;base64,', ''));
			}

			if (images) {
				// this is NOT the first time this method is ran on this instance of jsPDF object.
				imageIndex = Object.keys ?
					Object.keys(images).length :
					(function (o) {
						var i = 0
						for (var e in o) { if (o.hasOwnProperty(e)) { i++ } }
						return i
					})(images)
			} else {
				// this is the first time this method is ran on this instance of jsPDF object.
				imageIndex = 0
				this.internal.collections[namespace + 'images'] = images = {}
				this.internal.events.subscribe('putResources', putResourcesCallback)
				this.internal.events.subscribe('putXobjectDict', putXObjectsDictCallback)
			}

			var dims = getJpegSize(imageData);
			var info = {
				w: dims[0],
				h: dims[1],
				cs: 'DeviceRGB',
				bpc: 8,
				f: 'DCTDecode',
				i: imageIndex,
				data: imageData
				// n: objectNumber will be added by putImage code

			};
			images[imageIndex] = info
			if (!w && !h) {
				w = -96;
				h = -96;
			}
			if (w < 0) {
				w = (-1) * info['w'] * 72 / w / this.internal.scaleFactor;
			}
			if (h < 0) {
				h = (-1) * info['h'] * 72 / h / this.internal.scaleFactor;
			}
			if (w === 0) {
				w = h * info['w'] / info['h'];
			}
			if (h === 0) {
				h = w * info['h'] / info['w'];
			}

			this.internal.write(
				'q'
				, coord(w)
				, '0 0'
				, coord(h) // TODO: check if this should be shifted by vcoord
				, coord(x)
				, vcoord(y + h)
				, 'cm /I' + info['i']
				, 'Do Q'
			)

			return this
		}


	})(jsPDF.API)








}
/* END OF FILE - ..\oatPivot\jsPDF.src.js - */
/* START OF FILE - ..\oatPivot\jsPDF_encoding.src.js - */
//FILE jspdf_encoding

/** @preserve 
jsPDF standard_fonts_metrics plugin
Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
MIT license.
*/
/**
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * ====================================================================
 */
if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {

	; (function (API) {
		'use strict'



		/**
		Uncompresses data compressed into custom, base16-like format. 
		@public
		@function
		@param
		@returns {Type}
		*/
		var uncompress = function (data) {

			var decoded = '0123456789abcdef'
				, encoded = 'klmnopqrstuvwxyz'
				, mapping = {}

			for (var i = 0; i < encoded.length; i++) {
				mapping[encoded[i]] = decoded[i]
			}

			var undef
				, output = {}
				, sign = 1
				, stringparts // undef. will be [] in string mode

				, activeobject = output
				, parentchain = []
				, parent_key_pair
				, keyparts = ''
				, valueparts = ''
				, key // undef. will be Truthy when Key is resolved.
				, datalen = data.length - 1 // stripping ending }
				, ch

			i = 1 // stripping starting {

			while (i != datalen) {
				// - { } ' are special.

				ch = data[i]
				i += 1

				if (ch == "'") {
					if (stringparts) {
						// end of string mode
						key = stringparts.join('')
						stringparts = undef
					} else {
						// start of string mode
						stringparts = []
					}
				} else if (stringparts) {
					stringparts.push(ch)
				} else if (ch == '{') {
					// start of object
					parentchain.push([activeobject, key])
					activeobject = {}
					key = undef
				} else if (ch == '}') {
					// end of object
					parent_key_pair = parentchain.pop()
					parent_key_pair[0][parent_key_pair[1]] = activeobject
					key = undef
					activeobject = parent_key_pair[0]
				} else if (ch == '-') {
					sign = -1
				} else {
					// must be number
					if (key === undef) {
						if (mapping.hasOwnProperty(ch)) {
							keyparts += mapping[ch]
							key = parseInt(keyparts, 16) * sign
							sign = +1
							keyparts = ''
						} else {
							keyparts += ch
						}
					} else {
						if (mapping.hasOwnProperty(ch)) {
							valueparts += mapping[ch]
							activeobject[key] = parseInt(valueparts, 16) * sign
							sign = +1
							key = undef
							valueparts = ''
						} else {
							valueparts += ch
						}
					}
				}
			} // end while

			return output
		}

		// encoding = 'Unicode' 
		// NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE. NO clever BOM behavior
		// Actual 16bit char codes used.
		// no multi-byte logic here

		// Unicode characters to WinAnsiEncoding:
		// {402: 131, 8211: 150, 8212: 151, 8216: 145, 8217: 146, 8218: 130, 8220: 147, 8221: 148, 8222: 132, 8224: 134, 8225: 135, 8226: 149, 8230: 133, 8364: 128, 8240:137, 8249: 139, 8250: 155, 710: 136, 8482: 153, 338: 140, 339: 156, 732: 152, 352: 138, 353: 154, 376: 159, 381: 142, 382: 158}
		// as you can see, all Unicode chars are outside of 0-255 range. No char code conflicts.
		// this means that you can give Win cp1252 encoded strings to jsPDF for rendering directly
		// as well as give strings with some (supported by these fonts) Unicode characters and 
		// these will be mapped to win cp1252 
		// for example, you can send char code (cp1252) 0x80 or (unicode) 0x20AC, getting "Euro" glyph displayed in both cases.

		var encodingBlock = {
			'codePages': ['WinAnsiEncoding']
			, 'WinAnsiEncoding': uncompress("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}")
		}
			, encodings = {
				'Unicode': {
					'Courier': encodingBlock
					, 'Courier-Bold': encodingBlock
					, 'Courier-BoldOblique': encodingBlock
					, 'Courier-Oblique': encodingBlock
					, 'Helvetica': encodingBlock
					, 'Helvetica-Bold': encodingBlock
					, 'Helvetica-BoldOblique': encodingBlock
					, 'Helvetica-Oblique': encodingBlock
					, 'Times-Roman': encodingBlock
					, 'Times-Bold': encodingBlock
					, 'Times-BoldItalic': encodingBlock
					, 'Times-Italic': encodingBlock
					//	, 'Symbol'
					//	, 'ZapfDingbats'
				}
			}
			/** 
			Resources:
			Font metrics data is reprocessed derivative of contents of
			"Font Metrics for PDF Core 14 Fonts" package, which exhibits the following copyright and license:
			
			Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
			
			This file and the 14 PostScript(R) AFM files it accompanies may be used,
			copied, and distributed for any purpose and without charge, with or without
			modification, provided that all copyright notices are retained; that the AFM
			files are not distributed without this file; that all modifications to this
			file or any of the AFM files are prominently noted in the modified file(s);
			and that this paragraph is not modified. Adobe Systems has no responsibility
			or obligation to support the use of the AFM files.
			
			*/
			, fontMetrics = {
				'Unicode': {
					// all sizing numbers are n/fontMetricsFractionOf = one font size unit
					// this means that if fontMetricsFractionOf = 1000, and letter A's width is 476, it's
					// width is 476/1000 or 47.6% of its height (regardless of font size)
					// At this time this value applies to "widths" and "kerning" numbers.

					// char code 0 represents "default" (average) width - use it for chars missing in this table.
					// key 'fof' represents the "fontMetricsFractionOf" value

					'Courier-Oblique': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
					, 'Times-BoldItalic': uncompress("{'widths'{k3o2q4ycx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2r202m2n2n3m2o3m2p5n202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5n4l4m4m4m4n4m4o4s4p4m4q4m4r4s4s4y4t2r4u3m4v4m4w3x4x5t4y4s4z4s5k3x5l4s5m4m5n3r5o3x5p4s5q4m5r5t5s4m5t3x5u3x5v2l5w1w5x2l5y3t5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q2l6r3m6s3r6t1w6u1w6v3m6w1w6x4y6y3r6z3m7k3m7l3m7m2r7n2r7o1w7p3r7q2w7r4m7s3m7t2w7u2r7v2n7w1q7x2n7y3t202l3mcl4mal2ram3man3mao3map3mar3mas2lat4uau1uav3maw3way4uaz2lbk2sbl3t'fof'6obo2lbp3tbq3mbr1tbs2lbu1ybv3mbz3mck4m202k3mcm4mcn4mco4mcp4mcq5ycr4mcs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz2w203k6o212m6o2dw2l2cq2l3t3m3u2l17s3x19m3m}'kerning'{cl{4qu5kt5qt5rs17ss5ts}201s{201ss}201t{cks4lscmscnscoscpscls2wu2yu201ts}201x{2wu2yu}2k{201ts}2w{4qx5kx5ou5qx5rs17su5tu}2x{17su5tu5ou}2y{4qx5kx5ou5qx5rs17ss5ts}'fof'-6ofn{17sw5tw5ou5qw5rs}7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qs}3v{17su5tu5os5qs}7p{17su5tu}ck{4qu5kt5qt5rs17ss5ts}4l{4qu5kt5qt5rs17ss5ts}cm{4qu5kt5qt5rs17ss5ts}cn{4qu5kt5qt5rs17ss5ts}co{4qu5kt5qt5rs17ss5ts}cp{4qu5kt5qt5rs17ss5ts}6l{4qu5ou5qw5rt17su5tu}5q{ckuclucmucnucoucpu4lu}5r{ckuclucmucnucoucpu4lu}7q{cksclscmscnscoscps4ls}6p{4qu5ou5qw5rt17sw5tw}ek{4qu5ou5qw5rt17su5tu}el{4qu5ou5qw5rt17su5tu}em{4qu5ou5qw5rt17su5tu}en{4qu5ou5qw5rt17su5tu}eo{4qu5ou5qw5rt17su5tu}ep{4qu5ou5qw5rt17su5tu}es{17ss5ts5qs4qu}et{4qu5ou5qw5rt17sw5tw}eu{4qu5ou5qw5rt17ss5ts}ev{17ss5ts5qs4qu}6z{17sw5tw5ou5qw5rs}fm{17sw5tw5ou5qw5rs}7n{201ts}fo{17sw5tw5ou5qw5rs}fp{17sw5tw5ou5qw5rs}fq{17sw5tw5ou5qw5rs}7r{cksclscmscnscoscps4ls}fs{17sw5tw5ou5qw5rs}ft{17su5tu}fu{17su5tu}fv{17su5tu}fw{17su5tu}fz{cksclscmscnscoscps4ls}}}")
					, 'Helvetica-Bold': uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}")
					, 'Courier': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
					, 'Courier-BoldOblique': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
					, 'Times-Bold': uncompress("{'widths'{k3q2q5ncx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2l202m2n2n3m2o3m2p6o202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5x4l4s4m4m4n4s4o4s4p4m4q3x4r4y4s4y4t2r4u3m4v4y4w4m4x5y4y4s4z4y5k3x5l4y5m4s5n3r5o4m5p4s5q4s5r6o5s4s5t4s5u4m5v2l5w1w5x2l5y3u5z3m6k2l6l3m6m3r6n2w6o3r6p2w6q2l6r3m6s3r6t1w6u2l6v3r6w1w6x5n6y3r6z3m7k3r7l3r7m2w7n2r7o2l7p3r7q3m7r4s7s3m7t3m7u2w7v2r7w1q7x2r7y3o202l3mcl4sal2lam3man3mao3map3mar3mas2lat4uau1yav3maw3tay4uaz2lbk2sbl3t'fof'6obo2lbp3rbr1tbs2lbu2lbv3mbz3mck4s202k3mcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3rek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3m3u2l17s4s19m3m}'kerning'{cl{4qt5ks5ot5qy5rw17sv5tv}201t{cks4lscmscnscoscpscls4wv}2k{201ts}2w{4qu5ku7mu5os5qx5ru17su5tu}2x{17su5tu5ou5qs}2y{4qv5kv7mu5ot5qz5ru17su5tu}'fof'-6o7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qu}3v{17su5tu5os5qu}fu{17su5tu5ou5qu}7p{17su5tu5ou5qu}ck{4qt5ks5ot5qy5rw17sv5tv}4l{4qt5ks5ot5qy5rw17sv5tv}cm{4qt5ks5ot5qy5rw17sv5tv}cn{4qt5ks5ot5qy5rw17sv5tv}co{4qt5ks5ot5qy5rw17sv5tv}cp{4qt5ks5ot5qy5rw17sv5tv}6l{17st5tt5ou5qu}17s{ckuclucmucnucoucpu4lu4wu}5o{ckuclucmucnucoucpu4lu4wu}5q{ckzclzcmzcnzcozcpz4lz4wu}5r{ckxclxcmxcnxcoxcpx4lx4wu}5t{ckuclucmucnucoucpu4lu4wu}7q{ckuclucmucnucoucpu4lu}6p{17sw5tw5ou5qu}ek{17st5tt5qu}el{17st5tt5ou5qu}em{17st5tt5qu}en{17st5tt5qu}eo{17st5tt5qu}ep{17st5tt5ou5qu}es{17ss5ts5qu}et{17sw5tw5ou5qu}eu{17sw5tw5ou5qu}ev{17ss5ts5qu}6z{17sw5tw5ou5qu5rs}fm{17sw5tw5ou5qu5rs}fn{17sw5tw5ou5qu5rs}fo{17sw5tw5ou5qu5rs}fp{17sw5tw5ou5qu5rs}fq{17sw5tw5ou5qu5rs}7r{cktcltcmtcntcotcpt4lt5os}fs{17sw5tw5ou5qu5rs}ft{17su5tu5ou5qu}7m{5os}fv{17su5tu5ou5qu}fw{17su5tu5ou5qu}fz{cksclscmscnscoscps4ls}}}")
					//, 'Symbol': uncompress("{'widths'{k3uaw4r19m3m2k1t2l2l202m2y2n3m2p5n202q6o3k3m2s2l2t2l2v3r2w1t3m3m2y1t2z1wbk2sbl3r'fof'6o3n3m3o3m3p3m3q3m3r3m3s3m3t3m3u1w3v1w3w3r3x3r3y3r3z2wbp3t3l3m5v2l5x2l5z3m2q4yfr3r7v3k7w1o7x3k}'kerning'{'fof'-6o}}")
					, 'Helvetica': uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}")
					, 'Helvetica-BoldOblique': uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}")
					//, 'ZapfDingbats': uncompress("{'widths'{k4u2k1w'fof'6o}'kerning'{'fof'-6o}}")
					, 'Courier-Bold': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
					, 'Times-Italic': uncompress("{'widths'{k3n2q4ycx2l201n3m201o5t201s2l201t2l201u2l201w3r201x3r201y3r2k1t2l2l202m2n2n3m2o3m2p5n202q5t2r1p2s2l2t2l2u3m2v4n2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w4n3x4n3y4n3z3m4k5w4l3x4m3x4n4m4o4s4p3x4q3x4r4s4s4s4t2l4u2w4v4m4w3r4x5n4y4m4z4s5k3x5l4s5m3x5n3m5o3r5p4s5q3x5r5n5s3x5t3r5u3r5v2r5w1w5x2r5y2u5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q1w6r3m6s3m6t1w6u1w6v2w6w1w6x4s6y3m6z3m7k3m7l3m7m2r7n2r7o1w7p3m7q2w7r4m7s2w7t2w7u2r7v2s7w1v7x2s7y3q202l3mcl3xal2ram3man3mao3map3mar3mas2lat4wau1vav3maw4nay4waz2lbk2sbl4n'fof'6obo2lbp3mbq3obr1tbs2lbu1zbv3mbz3mck3x202k3mcm3xcn3xco3xcp3xcq5tcr4mcs3xct3xcu3xcv3xcw2l2m2ucy2lcz2ldl4mdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr4nfs3mft3mfu3mfv3mfw3mfz2w203k6o212m6m2dw2l2cq2l3t3m3u2l17s3r19m3m}'kerning'{cl{5kt4qw}201s{201sw}201t{201tw2wy2yy6q-t}201x{2wy2yy}2k{201tw}2w{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}2x{17ss5ts5os}2y{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}'fof'-6o6t{17ss5ts5qs}7t{5os}3v{5qs}7p{17su5tu5qs}ck{5kt4qw}4l{5kt4qw}cm{5kt4qw}cn{5kt4qw}co{5kt4qw}cp{5kt4qw}6l{4qs5ks5ou5qw5ru17su5tu}17s{2ks}5q{ckvclvcmvcnvcovcpv4lv}5r{ckuclucmucnucoucpu4lu}5t{2ks}6p{4qs5ks5ou5qw5ru17su5tu}ek{4qs5ks5ou5qw5ru17su5tu}el{4qs5ks5ou5qw5ru17su5tu}em{4qs5ks5ou5qw5ru17su5tu}en{4qs5ks5ou5qw5ru17su5tu}eo{4qs5ks5ou5qw5ru17su5tu}ep{4qs5ks5ou5qw5ru17su5tu}es{5ks5qs4qs}et{4qs5ks5ou5qw5ru17su5tu}eu{4qs5ks5qw5ru17su5tu}ev{5ks5qs4qs}ex{17ss5ts5qs}6z{4qv5ks5ou5qw5ru17su5tu}fm{4qv5ks5ou5qw5ru17su5tu}fn{4qv5ks5ou5qw5ru17su5tu}fo{4qv5ks5ou5qw5ru17su5tu}fp{4qv5ks5ou5qw5ru17su5tu}fq{4qv5ks5ou5qw5ru17su5tu}7r{5os}fs{4qv5ks5ou5qw5ru17su5tu}ft{17su5tu5qs}fu{17su5tu5qs}fv{17su5tu5qs}fw{17su5tu5qs}}}")
					, 'Times-Roman': uncompress("{'widths'{k3n2q4ycx2l201n3m201o6o201s2l201t2l201u2l201w2w201x2w201y2w2k1t2l2l202m2n2n3m2o3m2p5n202q6o2r1m2s2l2t2l2u3m2v3s2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v1w3w3s3x3s3y3s3z2w4k5w4l4s4m4m4n4m4o4s4p3x4q3r4r4s4s4s4t2l4u2r4v4s4w3x4x5t4y4s4z4s5k3r5l4s5m4m5n3r5o3x5p4s5q4s5r5y5s4s5t4s5u3x5v2l5w1w5x2l5y2z5z3m6k2l6l2w6m3m6n2w6o3m6p2w6q2l6r3m6s3m6t1w6u1w6v3m6w1w6x4y6y3m6z3m7k3m7l3m7m2l7n2r7o1w7p3m7q3m7r4s7s3m7t3m7u2w7v3k7w1o7x3k7y3q202l3mcl4sal2lam3man3mao3map3mar3mas2lat4wau1vav3maw3say4waz2lbk2sbl3s'fof'6obo2lbp3mbq2xbr1tbs2lbu1zbv3mbz2wck4s202k3mcm4scn4sco4scp4scq5tcr4mcs3xct3xcu3xcv3xcw2l2m2tcy2lcz2ldl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek2wel2wem2wen2weo2wep2weq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr3sfs3mft3mfu3mfv3mfw3mfz3m203k6o212m6m2dw2l2cq2l3t3m3u1w17s4s19m3m}'kerning'{cl{4qs5ku17sw5ou5qy5rw201ss5tw201ws}201s{201ss}201t{ckw4lwcmwcnwcowcpwclw4wu201ts}2k{201ts}2w{4qs5kw5os5qx5ru17sx5tx}2x{17sw5tw5ou5qu}2y{4qs5kw5os5qx5ru17sx5tx}'fof'-6o7t{ckuclucmucnucoucpu4lu5os5rs}3u{17su5tu5qs}3v{17su5tu5qs}7p{17sw5tw5qs}ck{4qs5ku17sw5ou5qy5rw201ss5tw201ws}4l{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cm{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cn{4qs5ku17sw5ou5qy5rw201ss5tw201ws}co{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cp{4qs5ku17sw5ou5qy5rw201ss5tw201ws}6l{17su5tu5os5qw5rs}17s{2ktclvcmvcnvcovcpv4lv4wuckv}5o{ckwclwcmwcnwcowcpw4lw4wu}5q{ckyclycmycnycoycpy4ly4wu5ms}5r{cktcltcmtcntcotcpt4lt4ws}5t{2ktclvcmvcnvcovcpv4lv4wuckv}7q{cksclscmscnscoscps4ls}6p{17su5tu5qw5rs}ek{5qs5rs}el{17su5tu5os5qw5rs}em{17su5tu5os5qs5rs}en{17su5qs5rs}eo{5qs5rs}ep{17su5tu5os5qw5rs}es{5qs}et{17su5tu5qw5rs}eu{17su5tu5qs5rs}ev{5qs}6z{17sv5tv5os5qx5rs}fm{5os5qt5rs}fn{17sv5tv5os5qx5rs}fo{17sv5tv5os5qx5rs}fp{5os5qt5rs}fq{5os5qt5rs}7r{ckuclucmucnucoucpu4lu5os}fs{17sv5tv5os5qx5rs}ft{17ss5ts5qs}fu{17sw5tw5qs}fv{17sw5tw5qs}fw{17ss5ts5qs}fz{ckuclucmucnucoucpu4lu5os5rs}}}")
					, 'Helvetica-Oblique': uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}")
				}
			};

		/*
		This event handler is fired when a new jsPDF object is initialized
		This event handler appends metrics data to standard fonts within
		that jsPDF instance. The metrics are mapped over Unicode character
		codes, NOT CIDs or other codes matching the StandardEncoding table of the
		standard PDF fonts.
		Future:
		Also included is the encoding maping table, converting Unicode (UCS-2, UTF-16)
		char codes to StandardEncoding character codes. The encoding table is to be used
		somewhere around "pdfEscape" call.
		*/

		API.events.push([
			'addFonts'
			, function (fontManagementObjects) {
				// fontManagementObjects is {
				//	'fonts':font_ID-keyed hash of font objects
				//	, 'dictionary': lookup object, linking ["FontFamily"]['Style'] to font ID
				//}
				var font
					, fontID
					, metrics
					, unicode_section
					, encoding = 'Unicode'
					, encodingBlock

				for (fontID in fontManagementObjects.fonts) {
					if (fontManagementObjects.fonts.hasOwnProperty(fontID)) {
						font = fontManagementObjects.fonts[fontID]

						// // we only ship 'Unicode' mappings and metrics. No need for loop.
						// // still, leaving this for the future.

						// for (encoding in fontMetrics){
						// 	if (fontMetrics.hasOwnProperty(encoding)) {

						metrics = fontMetrics[encoding][font.PostScriptName]
						if (metrics) {
							if (font.metadata[encoding]) {
								unicode_section = font.metadata[encoding]
							} else {
								unicode_section = font.metadata[encoding] = {}
							}

							unicode_section.widths = metrics.widths
							unicode_section.kerning = metrics.kerning
						}
						// 	}
						// }
						// for (encoding in encodings){
						// 	if (encodings.hasOwnProperty(encoding)) {
						encodingBlock = encodings[encoding][font.PostScriptName]
						if (encodingBlock) {
							if (font.metadata[encoding]) {
								unicode_section = font.metadata[encoding]
							} else {
								unicode_section = font.metadata[encoding] = {}
							}

							unicode_section.encoding = encodingBlock
							if (encodingBlock.codePages && encodingBlock.codePages.length) {
								font.encoding = encodingBlock.codePages[0]
							}
						}
						// 	}
						// }
					}
				}
			}
		]) // end of adding event handler

	})(jsPDF.API);








	/** @preserve 
	jsPDF split_text_to_size plugin
	Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
	MIT license.
	*/
	/**
	 * Permission is hereby granted, free of charge, to any person obtaining
	 * a copy of this software and associated documentation files (the
	 * "Software"), to deal in the Software without restriction, including
	 * without limitation the rights to use, copy, modify, merge, publish,
	 * distribute, sublicense, and/or sell copies of the Software, and to
	 * permit persons to whom the Software is furnished to do so, subject to
	 * the following conditions:
	 * 
	 * The above copyright notice and this permission notice shall be
	 * included in all copies or substantial portions of the Software.
	 * 
	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
	 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
	 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
	 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
	 * ====================================================================
	 */

	; (function (API) {
		'use strict'

		/**
		Returns an array of length matching length of the 'word' string, with each
		cell ocupied by the width of the char in that position.
		
		@function
		@param word {String}
		@param widths {Object}
		@param kerning {Object}
		@returns {Array}
		*/
		var getCharWidthsArray = API.getCharWidthsArray = function (text, options) {

			if (!options) {
				options = {}
			}

			var widths = options.widths ? options.widths : this.internal.getFont().metadata.Unicode.widths
				, widthsFractionOf = widths.fof ? widths.fof : 1
				, kerning = options.kerning ? options.kerning : this.internal.getFont().metadata.Unicode.kerning
				, kerningFractionOf = kerning.fof ? kerning.fof : 1

			// console.log("widths, kergnings", widths, kerning)

			var i, l
				, char_code
				, char_width
				, prior_char_code = 0 // for kerning
				, default_char_width = widths[0] || widthsFractionOf
				, output = []

			for (i = 0, l = text.length; i < l; i++) {
				char_code = text.charCodeAt(i)
				output.push(
					(widths[char_code] || default_char_width) / widthsFractionOf +
					(kerning[char_code] && kerning[char_code][prior_char_code] || 0) / kerningFractionOf
				)
				prior_char_code = char_code
			}

			return output
		}
		var getArraySum = function (array) {
			var i = array.length
				, output = 0
			while (i) {
				; i--;
				output += array[i]
			}
			return output
		}
		/**
		Returns a widths of string in a given font, if the font size is set as 1 point.
		
		In other words, this is "proportional" value. For 1 unit of font size, the length
		of the string will be that much.
		
		Multiply by font size to get actual width in *points*
		Then divide by 72 to get inches or divide by (72/25.6) to get 'mm' etc.
		
		@public
		@function
		@param
		@returns {Type}
		*/
		var getStringUnitWidth = API.getStringUnitWidth = function (text, options) {
			return getArraySum(getCharWidthsArray.call(this, text, options))
		}

		/** 
		returns array of lines
		*/
		var splitLongWord = function (word, widths_array, firstLineMaxLen, maxLen) {
			var answer = []

			// 1st, chop off the piece that can fit on the hanging line.
			var i = 0
				, l = word.length
				, workingLen = 0
			while (i !== l && workingLen + widths_array[i] < firstLineMaxLen) {
				workingLen += widths_array[i]
					; i++;
			}
			// this is first line.
			answer.push(word.slice(0, i))

			// 2nd. Split the rest into maxLen pieces.
			var startOfLine = i
			workingLen = 0
			while (i !== l) {
				if (workingLen + widths_array[i] > maxLen) {
					answer.push(word.slice(startOfLine, i))
					workingLen = 0
					startOfLine = i
				}
				workingLen += widths_array[i]
					; i++;
			}
			if (startOfLine !== i) {
				answer.push(word.slice(startOfLine, i))
			}

			return answer
		}

		// Note, all sizing inputs for this function must be in "font measurement units"
		// By default, for PDF, it's "point".
		var splitParagraphIntoLines = function (text, maxlen, options) {
			// at this time works only on Western scripts, ones with space char
			// separating the words. Feel free to expand.

			if (!options) {
				options = {}
			}

			var spaceCharWidth = getCharWidthsArray(' ', options)[0]

			var words = text.split(' ')

			var line = []
				, lines = [line]
				, line_length = options.textIndent || 0
				, separator_length = 0
				, current_word_length = 0
				, word
				, widths_array

			var i, l, tmp
			for (i = 0, l = words.length; i < l; i++) {
				word = words[i]
				widths_array = getCharWidthsArray(word, options)
				current_word_length = getArraySum(widths_array)

				if (line_length + separator_length + current_word_length > maxlen) {
					if (current_word_length > maxlen) {
						// this happens when you have space-less long URLs for example.
						// we just chop these to size. We do NOT insert hiphens
						tmp = splitLongWord(word, widths_array, maxlen - (line_length + separator_length), maxlen)
						// first line we add to existing line object
						line.push(tmp.shift()) // it's ok to have extra space indicator there
						// last line we make into new line object
						line = [tmp.pop()]
						// lines in the middle we apped to lines object as whole lines
						while (tmp.length) {
							lines.push([tmp.shift()]) // single fragment occupies whole line
						}
						current_word_length = getArraySum(widths_array.slice(word.length - line[0].length))
					} else {
						// just put it on a new line
						line = [word]
					}

					// now we attach new line to lines
					lines.push(line)

					line_length = current_word_length
					separator_length = spaceCharWidth

				} else {
					line.push(word)

					line_length += separator_length + current_word_length
					separator_length = spaceCharWidth
				}
			}

			var output = []
			for (i = 0, l = lines.length; i < l; i++) {
				output.push(lines[i].join(' '))
			}
			return output

		}

		/**
		Splits a given string into an array of strings. Uses 'size' value
		(in measurement units declared as default for the jsPDF instance)
		and the font's "widths" and "Kerning" tables, where availabe, to
		determine display length of a given string for a given font.
		
		We use character's 100% of unit size (height) as width when Width
		table or other default width is not available.
		
		@public
		@function
		@param text {String} Unencoded, regular JavaScript (Unicode, UTF-16 / UCS-2) string.
		@param size {Number} Nominal number, measured in units default to this instance of jsPDF.
		@param options {Object} Optional flags needed for chopper to do the right thing.
		@returns {Array} with strings chopped to size.
		*/
		API.splitTextToSize = function (text, maxlen, options) {
			'use strict'

			if (!options) {
				options = {}
			}

			var fsize = options.fontSize || this.internal.getFontSize()
				, newOptions = (function (options) {
					var widths = { 0: 1 }
						, kerning = {}

					if (!options.widths || !options.kerning) {
						var f = this.internal.getFont(options.fontName, options.fontStyle)
							, encoding = 'Unicode'
						// NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE
						// Actual JavaScript-native String's 16bit char codes used.
						// no multi-byte logic here

						if (f.metadata[encoding]) {
							return {
								widths: f.metadata[encoding].widths || widths
								, kerning: f.metadata[encoding].kerning || kerning
							}
						}
					} else {
						return {
							widths: options.widths
							, kerning: options.kerning
						}
					}

					// then use default values
					return {
						widths: widths
						, kerning: kerning
					}
				}).call(this, options)

			// first we split on end-of-line chars
			var paragraphs
			if (text.match(/[\n\r]/)) {
				paragraphs = text.split(/\r\n|\r|\n/g)
			} else {
				paragraphs = [text]
			}

			// now we convert size (max length of line) into "font size units"
			// at present time, the "font size unit" is always 'point'
			// 'proportional' means, "in proportion to font size"
			var fontUnit_maxLen = 1.0 * this.internal.scaleFactor * maxlen / fsize
			// at this time, fsize is always in "points" regardless of the default measurement unit of the doc.
			// this may change in the future?
			// until then, proportional_maxlen is likely to be in 'points'

			// If first line is to be indented (shorter or longer) than maxLen 
			// we indicate that by using CSS-style "text-indent" option.
			// here it's in font units too (which is likely 'points')
			// it can be negative (which makes the first line longer than maxLen)
			newOptions.textIndent = options.textIndent ?
				options.textIndent * 1.0 * this.internal.scaleFactor / fsize :
				0

			var i, l
				, output = []
			for (i = 0, l = paragraphs.length; i < l; i++) {
				output = output.concat(
					splitParagraphIntoLines(
						paragraphs[i]
						, fontUnit_maxLen
						, newOptions
					)
				)
			}

			return output
		}

	})(jsPDF.API);



	/** @preserve
	jsPDF Silly SVG plugin
	Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
	*/
	/**
	 * Permission is hereby granted, free of charge, to any person obtaining
	 * a copy of this software and associated documentation files (the
	 * "Software"), to deal in the Software without restriction, including
	 * without limitation the rights to use, copy, modify, merge, publish,
	 * distribute, sublicense, and/or sell copies of the Software, and to
	 * permit persons to whom the Software is furnished to do so, subject to
	 * the following conditions:
	 * 
	 * The above copyright notice and this permission notice shall be
	 * included in all copies or substantial portions of the Software.
	 * 
	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
	 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
	 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
	 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
	 * ====================================================================
	 */

	; (function (jsPDFAPI) {
		'use strict'

		/**
		Parses SVG XML and converts only some of the SVG elements into
		PDF elements.
		
		Supports:
		 paths
		
		@public
		@function
		@param
		@returns {Type}
		*/
		jsPDFAPI.addSVG = function (svgtext, x, y, w, h) {
			// 'this' is _jsPDF object returned when jsPDF is inited (new jsPDF())

			var undef

			if (x === undef || x === undef) {
				throw new Error("addSVG needs values for 'x' and 'y'")
			}

			function InjectCSS(cssbody, document) {
				var styletag = document.createElement('style')
				styletag.type = 'text/css'
				if (styletag.styleSheet) {
					// ie
					styletag.styleSheet.cssText = cssbody
				} else {
					// others
					styletag.appendChild(document.createTextNode(cssbody))
				}
				document.getElementsByTagName("head")[0].appendChild(styletag)
			}

			function createWorkerNode(document) {

				var frameID = 'childframe' // Date.now().toString() + '_' + (Math.random() * 100).toString()
					, frame = document.createElement('iframe')

				InjectCSS(
					'.jsPDF_sillysvg_iframe {display:none;position:absolute;}'
					, document
				)

				frame.name = frameID
				frame.setAttribute("width", 0)
				frame.setAttribute("height", 0)
				frame.setAttribute("frameborder", "0")
				frame.setAttribute("scrolling", "no")
				frame.setAttribute("seamless", "seamless")
				frame.setAttribute("class", "jsPDF_sillysvg_iframe")

				document.body.appendChild(frame)

				return frame
			}

			function attachSVGToWorkerNode(svgtext, frame) {
				var framedoc = (frame.contentWindow || frame.contentDocument).document
				framedoc.write(svgtext)
				framedoc.close()
				return framedoc.getElementsByTagName('svg')[0]
			}

			function convertPathToPDFLinesArgs(path) {
				'use strict'
				// we will use 'lines' method call. it needs:
				// - starting coordinate pair
				// - array of arrays of vector shifts (2-len for line, 6 len for bezier)
				// - scale array [horizontal, vertical] ratios
				// - style (stroke, fill, both)

				var x = parseFloat(path[1])
					, y = parseFloat(path[2])
					, vectors = []
					, position = 3
					, len = path.length

				while (position < len) {
					if (path[position] === 'c') {
						vectors.push([
							parseFloat(path[position + 1])
							, parseFloat(path[position + 2])
							, parseFloat(path[position + 3])
							, parseFloat(path[position + 4])
							, parseFloat(path[position + 5])
							, parseFloat(path[position + 6])
						])
						position += 7
					} else if (path[position] === 'l') {
						vectors.push([
							parseFloat(path[position + 1])
							, parseFloat(path[position + 2])
						])
						position += 3
					} else {
						position += 1
					}
				}
				return [x, y, vectors]
			}

			var workernode = createWorkerNode(document)
				, svgnode = attachSVGToWorkerNode(svgtext, workernode)
				, scale = [1, 1]
				, svgw = parseFloat(svgnode.getAttribute('width'))
				, svgh = parseFloat(svgnode.getAttribute('height'))

			if (svgw && svgh) {
				// setting both w and h makes image stretch to size.
				// this may distort the image, but fits your demanded size
				if (w && h) {
					scale = [w / svgw, h / svgh]
				}
				// if only one is set, that value is set as max and SVG 
				// is scaled proportionately.
				else if (w) {
					scale = [w / svgw, w / svgw]
				} else if (h) {
					scale = [h / svgh, h / svgh]
				}
			}

			var i, l, tmp
				, linesargs
				, items = svgnode.childNodes
			for (i = 0, l = items.length; i < l; i++) {
				tmp = items[i]
				if (tmp.tagName && tmp.tagName.toUpperCase() === 'PATH') {
					linesargs = convertPathToPDFLinesArgs(tmp.getAttribute("d").split(' '))
					// path start x coordinate
					linesargs[0] = linesargs[0] * scale[0] + x // where x is upper left X of image
					// path start y coordinate
					linesargs[1] = linesargs[1] * scale[1] + y // where y is upper left Y of image
					// the rest of lines are vectors. these will adjust with scale value auto.
					this.lines.call(
						this
						, linesargs[2] // lines
						, linesargs[0] // starting x
						, linesargs[1] // starting y
						, scale
					)
				}
			}

			// clean up
			// workernode.parentNode.removeChild(workernode)

			return this
		}

	})(jsPDF.API)

}

/** ==================================================================== 
 * jsPDF JavaScript plugin
 * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * ====================================================================
 */

/*global jsPDF */
/* END OF FILE - ..\oatPivot\jsPDF_encoding.src.js - */
/* START OF FILE - ..\oatPivot\jsPDF_output.src.js - */

//FILE jspdf_output


/** ====================================================================
 * jsPDF IE Below 9 Shim plugin 0.1.0
 * Known to be compatible with jsPDF 0.9.0
 *
 * Copyright (c) 2013 James Hall, james@snapshotmedia.co.uk
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * ====================================================================
 */
if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {

	; (function (API) {
		'use strict'

		var name = 'jsPDF IE Below 9 Shim plugin';
		// Shim in IE6-9 support
		API.output = function (type, options) {

			// If not IE then return early
			return this.internal.output(type, options);

			/*var filename = 'Output.pdf';
			switch (type) {
				case 'datauristring':
				case 'dataurlstring':
				case 'datauri':
				case 'dataurl':
				case 'dataurlnewwindow':
					console.log(name + ': Data URIs are not supported on IE6-9.');
					break;
				case 'save':
					filename = options;
					break;
			}*/

			// @TODO: IE shim 


		};



	})(jsPDF.API)








	/* FileSaver.js
	 * A saveAs() FileSaver implementation.
	 * 2013-01-23
	 * 
	 * By Eli Grey, http://eligrey.com
	 * License: X11/MIT
	 *   See LICENSE.md
	 */

	/*global self */
	/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
	  plusplus: true */

	/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */

	var saveAs = saveAs
		|| (navigator.msSaveBlob && navigator.msSaveBlob.bind(navigator))
		|| (function (view) {
			"use strict";
			var
				doc = view.document
				// only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
				, get_URL = function () {
					return view.URL || view.webkitURL || view;
				}
				, URL = view.URL || view.webkitURL || view
				, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
				, can_use_save_link = "download" in save_link
				, click = function (node) {
					var event = doc.createEvent("MouseEvents");
					event.initMouseEvent(
						"click", true, false, view, 0, 0, 0, 0, 0
						, false, false, false, false, 0, null
					);
					return node.dispatchEvent(event); // false if event was cancelled
				}
				, webkit_req_fs = view.webkitRequestFileSystem
				, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
				, throw_outside = function (ex) {
					(view.setImmediate || view.setTimeout)(function () {
						throw ex;
					}, 0);
				}
				, force_saveable_type = "application/octet-stream"
				, fs_min_size = 0
				, deletion_queue = []
				, process_deletion_queue = function () {
					var i = deletion_queue.length;
					while (i--) {
						var file = deletion_queue[i];
						if (typeof file === "string") { // file is an object URL
							URL.revokeObjectURL(file);
						} else { // file is a File
							file.remove();
						}
					}
					deletion_queue.length = 0; // clear queue
				}
				, dispatch = function (filesaver, event_types, event) {
					event_types = [].concat(event_types);
					var i = event_types.length;
					while (i--) {
						var listener = filesaver["on" + event_types[i]];
						if (typeof listener === "function") {
							try {
								listener.call(filesaver, event || filesaver);
							} catch (ex) {
								throw_outside(ex);
							}
						}
					}
				}
				, FileSaver = function (blob, name) {
					// First try a.download, then web filesystem, then object URLs
					var
						filesaver = this
						, type = blob.type
						, blob_changed = false
						, object_url
						, target_view
						, get_object_url = function () {
							var object_url = get_URL().createObjectURL(blob);
							deletion_queue.push(object_url);
							return object_url;
						}
						, dispatch_all = function () {
							dispatch(filesaver, "writestart progress write writeend".split(" "));
						}
						// on any filesys errors revert to saving with object URLs
						, fs_error = function () {
							// don't create more object URLs than needed
							if (blob_changed || !object_url) {
								object_url = get_object_url(blob);
							}
							if (target_view) {
								target_view.location.href = object_url;
							}
							filesaver.readyState = filesaver.DONE;
							dispatch_all();
						}
						, abortable = function (func) {
							return function () {
								if (filesaver.readyState !== filesaver.DONE) {
									return func.apply(this, arguments);
								}
							};
						}
						, create_if_not_found = { create: true, exclusive: false }
						, slice
						;
					filesaver.readyState = filesaver.INIT;
					if (!name) {
						name = "download";
					}
					if (can_use_save_link) {
						object_url = get_object_url(blob);
						save_link.href = object_url;
						save_link.download = name;
						if (click(save_link)) {
							filesaver.readyState = filesaver.DONE;
							dispatch_all();
							return;
						}
					}
					// Object and web filesystem URLs have a problem saving in Google Chrome when
					// viewed in a tab, so I force save with application/octet-stream
					// http://code.google.com/p/chromium/issues/detail?id=91158
					if (view.chrome && type && type !== force_saveable_type) {
						slice = blob.slice || blob.webkitSlice;
						blob = slice.call(blob, 0, blob.size, force_saveable_type);
						blob_changed = true;
					}
					// Since I can't be sure that the guessed media type will trigger a download
					// in WebKit, I append .download to the filename.
					// https://bugs.webkit.org/show_bug.cgi?id=65440
					if (webkit_req_fs && name !== "download") {
						name += ".download";
					}
					if (type === force_saveable_type || webkit_req_fs) {
						target_view = view;
					} else {
						//	target_view = view.open();
					}
					if (!req_fs) {
						fs_error();
						return;
					}
					fs_min_size += blob.size;
					req_fs(view.TEMPORARY, fs_min_size, abortable(function (fs) {
						fs.root.getDirectory("saved", create_if_not_found, abortable(function (dir) {
							var save = function () {
								dir.getFile(name, create_if_not_found, abortable(function (file) {
									file.createWriter(abortable(function (writer) {
										writer.onwriteend = function (event) {
											target_view.location.href = file.toURL();
											deletion_queue.push(file);
											filesaver.readyState = filesaver.DONE;
											dispatch(filesaver, "writeend", event);
										};
										writer.onerror = function () {
											var error = writer.error;
											if (error.code !== error.ABORT_ERR) {
												fs_error();
											}
										};
										"writestart progress write abort".split(" ").forEach(function (event) {
											writer["on" + event] = filesaver["on" + event];
										});
										writer.write(blob);
										filesaver.abort = function () {
											writer.abort();
											filesaver.readyState = filesaver.DONE;
										};
										filesaver.readyState = filesaver.WRITING;
									}), fs_error);
								}), fs_error);
							};
							dir.getFile(name, { create: false }, abortable(function (file) {
								// delete file if it already exists
								file.remove();
								save();
							}), abortable(function (ex) {
								if (ex.code === ex.NOT_FOUND_ERR) {
									save();
								} else {
									fs_error();
								}
							}));
						}), fs_error);
					}), fs_error);
				}
				, FS_proto = FileSaver.prototype
				, saveAs = function (blob, name) {
					return new FileSaver(blob, name);
				}
				;
			FS_proto.abort = function () {
				var filesaver = this;
				filesaver.readyState = filesaver.DONE;
				dispatch(filesaver, "abort");
			};
			FS_proto.readyState = FS_proto.INIT = 0;
			FS_proto.WRITING = 1;
			FS_proto.DONE = 2;

			FS_proto.error =
				FS_proto.onwritestart =
				FS_proto.onprogress =
				FS_proto.onwrite =
				FS_proto.onabort =
				FS_proto.onerror =
				FS_proto.onwriteend =
				null;

			view.addEventListener("unload", process_deletion_queue, false);
			return saveAs;
		}(self));



	/*
	 Copyright (c) 2013 Gildas Lormeau. All rights reserved.
	
	 Redistribution and use in source and binary forms, with or without
	 modification, are permitted provided that the following conditions are met:
	
	 1. Redistributions of source code must retain the above copyright notice,
	 this list of conditions and the following disclaimer.
	
	 2. Redistributions in binary form must reproduce the above copyright 
	 notice, this list of conditions and the following disclaimer in 
	 the documentation and/or other materials provided with the distribution.
	
	 3. The names of the authors may not be used to endorse or promote products
	 derived from this software without specific prior written permission.
	
	 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
	 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
	 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
	 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
	 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
	 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
	 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
	 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	 */

	/*
	 * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
	 * JZlib is based on zlib-1.1.3, so all credit should go authors
	 * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
	 * and contributors of zlib.
	 */

	// Global

	var MAX_BITS = 15;
	var D_CODES = 30;
	var BL_CODES = 19;

	var LENGTH_CODES = 29;
	var LITERALS = 256;
	var L_CODES = (LITERALS + 1 + LENGTH_CODES);
	var HEAP_SIZE = (2 * L_CODES + 1);

	var END_BLOCK = 256;

	// Bit length codes must not exceed MAX_BL_BITS bits
	var MAX_BL_BITS = 7;

	// repeat previous bit length 3-6 times (2 bits of repeat count)
	var REP_3_6 = 16;

	// repeat a zero length 3-10 times (3 bits of repeat count)
	var REPZ_3_10 = 17;

	// repeat a zero length 11-138 times (7 bits of repeat count)
	var REPZ_11_138 = 18;

	// The lengths of the bit length codes are sent in order of decreasing
	// probability, to avoid transmitting the lengths for unused bit
	// length codes.

	var Buf_size = 8 * 2;

	// JZlib version : "1.0.2"
	var Z_DEFAULT_COMPRESSION = -1;

	// compression strategy
	var Z_FILTERED = 1;
	var Z_HUFFMAN_ONLY = 2;
	var Z_DEFAULT_STRATEGY = 0;

	var Z_NO_FLUSH = 0;
	var Z_PARTIAL_FLUSH = 1;
	var Z_FULL_FLUSH = 3;
	var Z_FINISH = 4;

	var Z_OK = 0;
	var Z_STREAM_END = 1;
	var Z_NEED_DICT = 2;
	var Z_STREAM_ERROR = -2;
	var Z_DATA_ERROR = -3;
	var Z_BUF_ERROR = -5;

	// Tree

	// see definition of array dist_code below
	var _dist_code = [0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
		10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
		12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
		13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
		14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
		14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
		15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19,
		20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
		24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
		26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
		27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
		28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29,
		29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
		29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29];

	function Tree() {
		'use strict';
		var that = this;

		// dyn_tree; // the dynamic tree
		// max_code; // largest code with non zero frequency
		// stat_desc; // the corresponding static tree

		// Compute the optimal bit lengths for a tree and update the total bit
		// length
		// for the current block.
		// IN assertion: the fields freq and dad are set, heap[heap_max] and
		// above are the tree nodes sorted by increasing frequency.
		// OUT assertions: the field len is set to the optimal bit length, the
		// array bl_count contains the frequencies for each bit length.
		// The length opt_len is updated; static_len is also updated if stree is
		// not null.
		function gen_bitlen(s) {
			var tree = that.dyn_tree;
			var stree = that.stat_desc.static_tree;
			var extra = that.stat_desc.extra_bits;
			var base = that.stat_desc.extra_base;
			var max_length = that.stat_desc.max_length;
			var h; // heap index
			var n, m; // iterate over the tree elements
			var bits; // bit length
			var xbits; // extra bits
			var f; // frequency
			var overflow = 0; // number of elements with bit length too large

			for (bits = 0; bits <= MAX_BITS; bits++)
				s.bl_count[bits] = 0;

			// In a first pass, compute the optimal bit lengths (which may
			// overflow in the case of the bit length tree).
			tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap

			for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
				n = s.heap[h];
				bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
				if (bits > max_length) {
					bits = max_length;
					overflow++;
				}
				tree[n * 2 + 1] = bits;
				// We overwrite tree[n*2+1] which is no longer needed

				if (n > that.max_code)
					continue; // not a leaf node

				s.bl_count[bits]++;
				xbits = 0;
				if (n >= base)
					xbits = extra[n - base];
				f = tree[n * 2];
				s.opt_len += f * (bits + xbits);
				if (stree)
					s.static_len += f * (stree[n * 2 + 1] + xbits);
			}
			if (overflow === 0)
				return;

			// This happens for example on obj2 and pic of the Calgary corpus
			// Find the first bit length which could increase:
			do {
				bits = max_length - 1;
				while (s.bl_count[bits] === 0)
					bits--;
				s.bl_count[bits]--; // move one leaf down the tree
				s.bl_count[bits + 1] += 2; // move one overflow item as its brother
				s.bl_count[max_length]--;
				// The brother of the overflow item also moves one step up,
				// but this does not affect bl_count[max_length]
				overflow -= 2;
			} while (overflow > 0);

			for (bits = max_length; bits !== 0; bits--) {
				n = s.bl_count[bits];
				while (n !== 0) {
					m = s.heap[--h];
					if (m > that.max_code)
						continue;
					if (tree[m * 2 + 1] != bits) {
						s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];
						tree[m * 2 + 1] = bits;
					}
					n--;
				}
			}
		}

		// Reverse the first len bits of a code, using straightforward code (a
		// faster
		// method would use a table)
		// IN assertion: 1 <= len <= 15
		function bi_reverse(code, // the value to invert
			len // its bit length
		) {
			var res = 0;
			do {
				res |= code & 1;
				code >>>= 1;
				res <<= 1;
			} while (--len > 0);
			return res >>> 1;
		}

		// Generate the codes for a given tree and bit counts (which need not be
		// optimal).
		// IN assertion: the array bl_count contains the bit length statistics for
		// the given tree and the field len is set for all tree elements.
		// OUT assertion: the field code is set for all tree elements of non
		// zero code length.
		function gen_codes(tree, // the tree to decorate
			max_code, // largest code with non zero frequency
			bl_count // number of codes at each bit length
		) {
			var next_code = []; // next code value for each
			// bit length
			var code = 0; // running code value
			var bits; // bit index
			var n; // code index
			var len;

			// The distribution counts are first used to generate the code values
			// without bit reversal.
			for (bits = 1; bits <= MAX_BITS; bits++) {
				next_code[bits] = code = ((code + bl_count[bits - 1]) << 1);
			}

			// Check that the bit counts in bl_count are consistent. The last code
			// must be all ones.
			// Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
			// "inconsistent bit counts");
			// Tracev((stderr,"\ngen_codes: max_code %d ", max_code));

			for (n = 0; n <= max_code; n++) {
				len = tree[n * 2 + 1];
				if (len === 0)
					continue;
				// Now reverse the bits
				tree[n * 2] = bi_reverse(next_code[len]++, len);
			}
		}

		// Construct one Huffman tree and assigns the code bit strings and lengths.
		// Update the total bit length for the current block.
		// IN assertion: the field freq is set for all tree elements.
		// OUT assertions: the fields len and code are set to the optimal bit length
		// and corresponding code. The length opt_len is updated; static_len is
		// also updated if stree is not null. The field max_code is set.
		that.build_tree = function (s) {
			var tree = that.dyn_tree;
			var stree = that.stat_desc.static_tree;
			var elems = that.stat_desc.elems;
			var n, m; // iterate over heap elements
			var max_code = -1; // largest code with non zero frequency
			var node; // new node being created

			// Construct the initial heap, with least frequent element in
			// heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
			// heap[0] is not used.
			s.heap_len = 0;
			s.heap_max = HEAP_SIZE;

			for (n = 0; n < elems; n++) {
				if (tree[n * 2] !== 0) {
					s.heap[++s.heap_len] = max_code = n;
					s.depth[n] = 0;
				} else {
					tree[n * 2 + 1] = 0;
				}
			}

			// The pkzip format requires that at least one distance code exists,
			// and that at least one bit should be sent even if there is only one
			// possible code. So to avoid special checks later on we force at least
			// two codes of non zero frequency.
			while (s.heap_len < 2) {
				node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;
				tree[node * 2] = 1;
				s.depth[node] = 0;
				s.opt_len--;
				if (stree)
					s.static_len -= stree[node * 2 + 1];
				// node is 0 or 1 so it does not have extra bits
			}
			that.max_code = max_code;

			// The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
			// establish sub-heaps of increasing lengths:

			for (n = Math.floor(s.heap_len / 2); n >= 1; n--)
				s.pqdownheap(tree, n);

			// Construct the Huffman tree by repeatedly combining the least two
			// frequent nodes.

			node = elems; // next internal node of the tree
			do {
				// n = node of least frequency
				n = s.heap[1];
				s.heap[1] = s.heap[s.heap_len--];
				s.pqdownheap(tree, 1);
				m = s.heap[1]; // m = node of next least frequency

				s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
				s.heap[--s.heap_max] = m;

				// Create a new node father of n and m
				tree[node * 2] = (tree[n * 2] + tree[m * 2]);
				s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;
				tree[n * 2 + 1] = tree[m * 2 + 1] = node;

				// and insert the new node in the heap
				s.heap[1] = node++;
				s.pqdownheap(tree, 1);
			} while (s.heap_len >= 2);

			s.heap[--s.heap_max] = s.heap[1];

			// At this point, the fields freq and dad are set. We can now
			// generate the bit lengths.

			gen_bitlen(s);

			// The field len is now set, we can generate the bit codes
			gen_codes(tree, that.max_code, s.bl_count);
		};

	}

	Tree._length_code = [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16,
		16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,
		20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
		22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
		24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
		25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
		26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28];

	Tree.base_length = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0];

	Tree.base_dist = [0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384,
		24576];

	// Mapping from a distance to a distance code. dist is the distance - 1 and
	// must not have side effects. _dist_code[256] and _dist_code[257] are never
	// used.
	Tree.d_code = function (dist) {
		return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >>> 7)]);
	};

	// extra bits for each length code
	Tree.extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0];

	// extra bits for each distance code
	Tree.extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13];

	// extra bits for each bit length code
	Tree.extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7];

	Tree.bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];

	// StaticTree

	function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {
		var that = this;
		that.static_tree = static_tree;
		that.extra_bits = extra_bits;
		that.extra_base = extra_base;
		that.elems = elems;
		that.max_length = max_length;
	}

	StaticTree.static_ltree = [12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8, 2, 8,
		130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, 202, 8, 42,
		8, 170, 8, 106, 8, 234, 8, 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8,
		22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
		222, 8, 62, 8, 190, 8, 126, 8, 254, 8, 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113,
		8, 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8, 5, 8, 133, 8,
		69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, 77, 8, 205, 8, 45, 8,
		173, 8, 109, 8, 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9,
		51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, 171, 9,
		427, 9, 107, 9, 363, 9, 235, 9, 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379,
		9, 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9, 23,
		9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, 271, 9, 143, 9,
		399, 9, 79, 9, 335, 9, 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9,
		223, 9, 479, 9, 63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, 72, 7,
		40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8,
		99, 8, 227, 8];

	StaticTree.static_dtree = [0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5, 1, 5, 17, 5, 9, 5,
		25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5];

	StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);

	StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);

	StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS);

	// Deflate

	var MAX_MEM_LEVEL = 9;
	var DEF_MEM_LEVEL = 8;

	function Config(good_length, max_lazy, nice_length, max_chain, func) {
		var that = this;
		that.good_length = good_length;
		that.max_lazy = max_lazy;
		that.nice_length = nice_length;
		that.max_chain = max_chain;
		that.func = func;
	}

	var STORED = 0;
	var FAST = 1;
	var SLOW = 2;
	var config_table = [new Config(0, 0, 0, 0, STORED), new Config(4, 4, 8, 4, FAST), new Config(4, 5, 16, 8, FAST), new Config(4, 6, 32, 32, FAST),
	new Config(4, 4, 16, 16, SLOW), new Config(8, 16, 32, 32, SLOW), new Config(8, 16, 128, 128, SLOW), new Config(8, 32, 128, 256, SLOW),
	new Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW)];

	var z_errmsg = ["need dictionary", // Z_NEED_DICT
		// 2
		"stream end", // Z_STREAM_END 1
		"", // Z_OK 0
		"", // Z_ERRNO (-1)
		"stream error", // Z_STREAM_ERROR (-2)
		"data error", // Z_DATA_ERROR (-3)
		"", // Z_MEM_ERROR (-4)
		"buffer error", // Z_BUF_ERROR (-5)
		"",// Z_VERSION_ERROR (-6)
		""];

	// block not completed, need more input or more output
	var NeedMore = 0;

	// block flush performed
	var BlockDone = 1;

	// finish started, need only more output at next deflate
	var FinishStarted = 2;

	// finish done, accept no more input or output
	var FinishDone = 3;

	// preset dictionary flag in zlib header
	var PRESET_DICT = 0x20;

	var INIT_STATE = 42;
	var BUSY_STATE = 113;
	var FINISH_STATE = 666;

	// The deflate compression method
	var Z_DEFLATED = 8;

	var STORED_BLOCK = 0;
	var STATIC_TREES = 1;
	var DYN_TREES = 2;

	var MIN_MATCH = 3;
	var MAX_MATCH = 258;
	var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);

	function smaller(tree, n, m, depth) {
		var tn2 = tree[n * 2];
		var tm2 = tree[m * 2];
		return (tn2 < tm2 || (tn2 == tm2 && depth[n] <= depth[m]));
	}

	function Deflate() {

		var that = this;
		var strm; // pointer back to this zlib stream
		var status; // as the name implies
		// pending_buf; // output still pending
		var pending_buf_size; // size of pending_buf
		// pending_out; // next pending byte to output to the stream
		// pending; // nb of bytes in the pending buffer
		var method; // STORED (for zip only) or DEFLATED
		var last_flush; // value of flush param for previous deflate call

		var w_size; // LZ77 window size (32K by default)
		var w_bits; // log2(w_size) (8..16)
		var w_mask; // w_size - 1

		var window;
		// Sliding window. Input bytes are read into the second half of the window,
		// and move to the first half later to keep a dictionary of at least wSize
		// bytes. With this organization, matches are limited to a distance of
		// wSize-MAX_MATCH bytes, but this ensures that IO is always
		// performed with a length multiple of the block size. Also, it limits
		// the window size to 64K, which is quite useful on MSDOS.
		// To do: use the user input buffer as sliding window.

		var window_size;
		// Actual size of window: 2*wSize, except when the user input buffer
		// is directly used as sliding window.

		var prev;
		// Link to older string with same hash index. To limit the size of this
		// array to 64K, this link is maintained only for the last 32K strings.
		// An index in this array is thus a window index modulo 32K.

		var head; // Heads of the hash chains or NIL.

		var ins_h; // hash index of string to be inserted
		var hash_size; // number of elements in hash table
		var hash_bits; // log2(hash_size)
		var hash_mask; // hash_size-1

		// Number of bits by which ins_h must be shifted at each input
		// step. It must be such that after MIN_MATCH steps, the oldest
		// byte no longer takes part in the hash key, that is:
		// hash_shift * MIN_MATCH >= hash_bits
		var hash_shift;

		// Window position at the beginning of the current output block. Gets
		// negative when the window is moved backwards.

		var block_start;

		var match_length; // length of best match
		var prev_match; // previous match
		var match_available; // set if previous match exists
		var strstart; // start of string to insert
		var match_start; // start of matching string
		var lookahead; // number of valid bytes ahead in window

		// Length of the best match at previous step. Matches not greater than this
		// are discarded. This is used in the lazy match evaluation.
		var prev_length;

		// To speed up deflation, hash chains are never searched beyond this
		// length. A higher limit improves compression ratio but degrades the speed.
		var max_chain_length;

		// Attempt to find a better match only when the current match is strictly
		// smaller than this value. This mechanism is used only for compression
		// levels >= 4.
		var max_lazy_match;

		// Insert new strings in the hash table only if the match length is not
		// greater than this length. This saves time but degrades compression.
		// max_insert_length is used only for compression levels <= 3.

		var level; // compression level (1..9)
		var strategy; // favor or force Huffman coding

		// Use a faster search when the previous match is longer than this
		var good_match;

		// Stop searching when current match exceeds this
		var nice_match;

		var dyn_ltree; // literal and length tree
		var dyn_dtree; // distance tree
		var bl_tree; // Huffman tree for bit lengths

		var l_desc = new Tree(); // desc for literal tree
		var d_desc = new Tree(); // desc for distance tree
		var bl_desc = new Tree(); // desc for bit length tree

		// that.heap_len; // number of elements in the heap
		// that.heap_max; // element of largest frequency
		// The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
		// The same heap array is used to build all trees.

		// Depth of each subtree used as tie breaker for trees of equal frequency
		that.depth = [];

		var l_buf; // index for literals or lengths */

		// Size of match buffer for literals/lengths. There are 4 reasons for
		// limiting lit_bufsize to 64K:
		// - frequencies can be kept in 16 bit counters
		// - if compression is not successful for the first block, all input
		// data is still in the window so we can still emit a stored block even
		// when input comes from standard input. (This can also be done for
		// all blocks if lit_bufsize is not greater than 32K.)
		// - if compression is not successful for a file smaller than 64K, we can
		// even emit a stored file instead of a stored block (saving 5 bytes).
		// This is applicable only for zip (not gzip or zlib).
		// - creating new Huffman trees less frequently may not provide fast
		// adaptation to changes in the input data statistics. (Take for
		// example a binary file with poorly compressible code followed by
		// a highly compressible string table.) Smaller buffer sizes give
		// fast adaptation but have of course the overhead of transmitting
		// trees more frequently.
		// - I can't count above 4
		var lit_bufsize;

		var last_lit; // running index in l_buf

		// Buffer for distances. To simplify the code, d_buf and l_buf have
		// the same number of elements. To use different lengths, an extra flag
		// array would be necessary.

		var d_buf; // index of pendig_buf

		// that.opt_len; // bit length of current block with optimal trees
		// that.static_len; // bit length of current block with static trees
		var matches; // number of string matches in current block
		var last_eob_len; // bit length of EOB code for last block

		// Output buffer. bits are inserted starting at the bottom (least
		// significant bits).
		var bi_buf;

		// Number of valid bits in bi_buf. All bits above the last valid bit
		// are always zero.
		var bi_valid;

		// number of codes at each bit length for an optimal tree
		that.bl_count = [];

		// heap used to build the Huffman trees
		that.heap = [];

		dyn_ltree = [];
		dyn_dtree = [];
		bl_tree = [];

		function lm_init() {
			var i;
			window_size = 2 * w_size;

			head[hash_size - 1] = 0;
			for (i = 0; i < hash_size - 1; i++) {
				head[i] = 0;
			}

			// Set the default configuration parameters:
			max_lazy_match = config_table[level].max_lazy;
			good_match = config_table[level].good_length;
			nice_match = config_table[level].nice_length;
			max_chain_length = config_table[level].max_chain;

			strstart = 0;
			block_start = 0;
			lookahead = 0;
			match_length = prev_length = MIN_MATCH - 1;
			match_available = 0;
			ins_h = 0;
		}

		function init_block() {
			var i;
			// Initialize the trees.
			for (i = 0; i < L_CODES; i++)
				dyn_ltree[i * 2] = 0;
			for (i = 0; i < D_CODES; i++)
				dyn_dtree[i * 2] = 0;
			for (i = 0; i < BL_CODES; i++)
				bl_tree[i * 2] = 0;

			dyn_ltree[END_BLOCK * 2] = 1;
			that.opt_len = that.static_len = 0;
			last_lit = matches = 0;
		}

		// Initialize the tree data structures for a new zlib stream.
		function tr_init() {

			l_desc.dyn_tree = dyn_ltree;
			l_desc.stat_desc = StaticTree.static_l_desc;

			d_desc.dyn_tree = dyn_dtree;
			d_desc.stat_desc = StaticTree.static_d_desc;

			bl_desc.dyn_tree = bl_tree;
			bl_desc.stat_desc = StaticTree.static_bl_desc;

			bi_buf = 0;
			bi_valid = 0;
			last_eob_len = 8; // enough lookahead for inflate

			// Initialize the first block of the first file:
			init_block();
		}

		// Restore the heap property by moving down the tree starting at node k,
		// exchanging a node with the smallest of its two sons if necessary,
		// stopping
		// when the heap property is re-established (each father smaller than its
		// two sons).
		that.pqdownheap = function (tree, // the tree to restore
			k // node to move down
		) {
			var heap = that.heap;
			var v = heap[k];
			var j = k << 1; // left son of k
			while (j <= that.heap_len) {
				// Set j to the smallest of the two sons:
				if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {
					j++;
				}
				// Exit if v is smaller than both sons
				if (smaller(tree, v, heap[j], that.depth))
					break;

				// Exchange v with the smallest son
				heap[k] = heap[j];
				k = j;
				// And continue down the tree, setting j to the left son of k
				j <<= 1;
			}
			heap[k] = v;
		};

		// Scan a literal or distance tree to determine the frequencies of the codes
		// in the bit length tree.
		function scan_tree(tree,// the tree to be scanned
			max_code // and its largest code of non zero frequency
		) {
			var n; // iterates over all tree elements
			var prevlen = -1; // last emitted length
			var curlen; // length of current code
			var nextlen = tree[0 * 2 + 1]; // length of next code
			var count = 0; // repeat count of the current code
			var max_count = 7; // max repeat count
			var min_count = 4; // min repeat count

			if (nextlen === 0) {
				max_count = 138;
				min_count = 3;
			}
			tree[(max_code + 1) * 2 + 1] = 0xffff; // guard

			for (n = 0; n <= max_code; n++) {
				curlen = nextlen;
				nextlen = tree[(n + 1) * 2 + 1];
				if (++count < max_count && curlen == nextlen) {
					continue;
				} else if (count < min_count) {
					bl_tree[curlen * 2] += count;
				} else if (curlen !== 0) {
					if (curlen != prevlen)
						bl_tree[curlen * 2]++;
					bl_tree[REP_3_6 * 2]++;
				} else if (count <= 10) {
					bl_tree[REPZ_3_10 * 2]++;
				} else {
					bl_tree[REPZ_11_138 * 2]++;
				}
				count = 0;
				prevlen = curlen;
				if (nextlen === 0) {
					max_count = 138;
					min_count = 3;
				} else if (curlen == nextlen) {
					max_count = 6;
					min_count = 3;
				} else {
					max_count = 7;
					min_count = 4;
				}
			}
		}

		// Construct the Huffman tree for the bit lengths and return the index in
		// bl_order of the last bit length code to send.
		function build_bl_tree() {
			var max_blindex; // index of last bit length code of non zero freq

			// Determine the bit length frequencies for literal and distance trees
			scan_tree(dyn_ltree, l_desc.max_code);
			scan_tree(dyn_dtree, d_desc.max_code);

			// Build the bit length tree:
			bl_desc.build_tree(that);
			// opt_len now includes the length of the tree representations, except
			// the lengths of the bit lengths codes and the 5+5+4 bits for the
			// counts.

			// Determine the number of bit length codes to send. The pkzip format
			// requires that at least 4 bit length codes be sent. (appnote.txt says
			// 3 but the actual value used is 4.)
			for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
				if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0)
					break;
			}
			// Update opt_len to include the bit length tree and counts
			that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;

			return max_blindex;
		}

		// Output a byte on the stream.
		// IN assertion: there is enough room in pending_buf.
		function put_byte(p) {
			that.pending_buf[that.pending++] = p;
		}

		function put_short(w) {
			put_byte(w & 0xff);
			put_byte((w >>> 8) & 0xff);
		}

		function putShortMSB(b) {
			put_byte((b >> 8) & 0xff);
			put_byte((b & 0xff) & 0xff);
		}

		function send_bits(value, length) {
			var val, len = length;
			if (bi_valid > Buf_size - len) {
				val = value;
				// bi_buf |= (val << bi_valid);
				bi_buf |= ((val << bi_valid) & 0xffff);
				put_short(bi_buf);
				bi_buf = val >>> (Buf_size - bi_valid);
				bi_valid += len - Buf_size;
			} else {
				// bi_buf |= (value) << bi_valid;
				bi_buf |= (((value) << bi_valid) & 0xffff);
				bi_valid += len;
			}
		}

		function send_code(c, tree) {
			var c2 = c * 2;
			send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff);
		}

		// Send a literal or distance tree in compressed form, using the codes in
		// bl_tree.
		function send_tree(tree,// the tree to be sent
			max_code // and its largest code of non zero frequency
		) {
			var n; // iterates over all tree elements
			var prevlen = -1; // last emitted length
			var curlen; // length of current code
			var nextlen = tree[0 * 2 + 1]; // length of next code
			var count = 0; // repeat count of the current code
			var max_count = 7; // max repeat count
			var min_count = 4; // min repeat count

			if (nextlen === 0) {
				max_count = 138;
				min_count = 3;
			}

			for (n = 0; n <= max_code; n++) {
				curlen = nextlen;
				nextlen = tree[(n + 1) * 2 + 1];
				if (++count < max_count && curlen == nextlen) {
					continue;
				} else if (count < min_count) {
					do {
						send_code(curlen, bl_tree);
					} while (--count !== 0);
				} else if (curlen !== 0) {
					if (curlen != prevlen) {
						send_code(curlen, bl_tree);
						count--;
					}
					send_code(REP_3_6, bl_tree);
					send_bits(count - 3, 2);
				} else if (count <= 10) {
					send_code(REPZ_3_10, bl_tree);
					send_bits(count - 3, 3);
				} else {
					send_code(REPZ_11_138, bl_tree);
					send_bits(count - 11, 7);
				}
				count = 0;
				prevlen = curlen;
				if (nextlen === 0) {
					max_count = 138;
					min_count = 3;
				} else if (curlen == nextlen) {
					max_count = 6;
					min_count = 3;
				} else {
					max_count = 7;
					min_count = 4;
				}
			}
		}

		// Send the header for a block using dynamic Huffman trees: the counts, the
		// lengths of the bit length codes, the literal tree and the distance tree.
		// IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
		function send_all_trees(lcodes, dcodes, blcodes) {
			var rank; // index in bl_order

			send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
			send_bits(dcodes - 1, 5);
			send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
			for (rank = 0; rank < blcodes; rank++) {
				send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
			}
			send_tree(dyn_ltree, lcodes - 1); // literal tree
			send_tree(dyn_dtree, dcodes - 1); // distance tree
		}

		// Flush the bit buffer, keeping at most 7 bits in it.
		function bi_flush() {
			if (bi_valid == 16) {
				put_short(bi_buf);
				bi_buf = 0;
				bi_valid = 0;
			} else if (bi_valid >= 8) {
				put_byte(bi_buf & 0xff);
				bi_buf >>>= 8;
				bi_valid -= 8;
			}
		}

		// Send one empty static block to give enough lookahead for inflate.
		// This takes 10 bits, of which 7 may remain in the bit buffer.
		// The current inflate code requires 9 bits of lookahead. If the
		// last two codes for the previous block (real code plus EOB) were coded
		// on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
		// the last real code. In this case we send two empty static blocks instead
		// of one. (There are no problems if the previous block is stored or fixed.)
		// To simplify the code, we assume the worst case of last real code encoded
		// on one bit only.
		function _tr_align() {
			send_bits(STATIC_TREES << 1, 3);
			send_code(END_BLOCK, StaticTree.static_ltree);

			bi_flush();

			// Of the 10 bits for the empty block, we have already sent
			// (10 - bi_valid) bits. The lookahead for the last real code (before
			// the EOB of the previous block) was thus at least one plus the length
			// of the EOB plus what we have just sent of the empty static block.
			if (1 + last_eob_len + 10 - bi_valid < 9) {
				send_bits(STATIC_TREES << 1, 3);
				send_code(END_BLOCK, StaticTree.static_ltree);
				bi_flush();
			}
			last_eob_len = 7;
		}

		// Save the match info and tally the frequency counts. Return true if
		// the current block must be flushed.
		function _tr_tally(dist, // distance of matched string
			lc // match length-MIN_MATCH or unmatched char (if dist==0)
		) {
			var out_length, in_length, dcode;
			that.pending_buf[d_buf + last_lit * 2] = (dist >>> 8) & 0xff;
			that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff;

			that.pending_buf[l_buf + last_lit] = lc & 0xff;
			last_lit++;

			if (dist === 0) {
				// lc is the unmatched char
				dyn_ltree[lc * 2]++;
			} else {
				matches++;
				// Here, lc is the match length - MIN_MATCH
				dist--; // dist = match distance - 1
				dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
				dyn_dtree[Tree.d_code(dist) * 2]++;
			}

			if ((last_lit & 0x1fff) === 0 && level > 2) {
				// Compute an upper bound for the compressed length
				out_length = last_lit * 8;
				in_length = strstart - block_start;
				for (dcode = 0; dcode < D_CODES; dcode++) {
					out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);
				}
				out_length >>>= 3;
				if ((matches < Math.floor(last_lit / 2)) && out_length < Math.floor(in_length / 2))
					return true;
			}

			return (last_lit == lit_bufsize - 1);
			// We avoid equality with lit_bufsize because of wraparound at 64K
			// on 16 bit machines and because stored blocks are restricted to
			// 64K-1 bytes.
		}

		// Send the block data compressed using the given Huffman trees
		function compress_block(ltree, dtree) {
			var dist; // distance of matched string
			var lc; // match length or unmatched char (if dist === 0)
			var lx = 0; // running index in l_buf
			var code; // the code to send
			var extra; // number of extra bits to send

			if (last_lit !== 0) {
				do {
					dist = ((that.pending_buf[d_buf + lx * 2] << 8) & 0xff00) | (that.pending_buf[d_buf + lx * 2 + 1] & 0xff);
					lc = (that.pending_buf[l_buf + lx]) & 0xff;
					lx++;

					if (dist === 0) {
						send_code(lc, ltree); // send a literal byte
					} else {
						// Here, lc is the match length - MIN_MATCH
						code = Tree._length_code[lc];

						send_code(code + LITERALS + 1, ltree); // send the length
						// code
						extra = Tree.extra_lbits[code];
						if (extra !== 0) {
							lc -= Tree.base_length[code];
							send_bits(lc, extra); // send the extra length bits
						}
						dist--; // dist is now the match distance - 1
						code = Tree.d_code(dist);

						send_code(code, dtree); // send the distance code
						extra = Tree.extra_dbits[code];
						if (extra !== 0) {
							dist -= Tree.base_dist[code];
							send_bits(dist, extra); // send the extra distance bits
						}
					} // literal or match pair ?

					// Check that the overlay between pending_buf and d_buf+l_buf is
					// ok:
				} while (lx < last_lit);
			}

			send_code(END_BLOCK, ltree);
			last_eob_len = ltree[END_BLOCK * 2 + 1];
		}

		// Flush the bit buffer and align the output on a byte boundary
		function bi_windup() {
			if (bi_valid > 8) {
				put_short(bi_buf);
			} else if (bi_valid > 0) {
				put_byte(bi_buf & 0xff);
			}
			bi_buf = 0;
			bi_valid = 0;
		}

		// Copy a stored block, storing first the length and its
		// one's complement if requested.
		function copy_block(buf, // the input data
			len, // its length
			header // true if block header must be written
		) {
			bi_windup(); // align on byte boundary
			last_eob_len = 8; // enough lookahead for inflate

			if (header) {
				put_short(len);
				put_short(~len);
			}

			that.pending_buf.set(window.subarray(buf, buf + len), that.pending);
			that.pending += len;
		}

		// Send a stored block
		function _tr_stored_block(buf, // input block
			stored_len, // length of input block
			eof // true if this is the last block for a file
		) {
			send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
			copy_block(buf, stored_len, true); // with header
		}

		// Determine the best encoding for the current block: dynamic trees, static
		// trees or store, and output the encoded block to the zip file.
		function _tr_flush_block(buf, // input block, or NULL if too old
			stored_len, // length of input block
			eof // true if this is the last block for a file
		) {
			var opt_lenb, static_lenb;// opt_len and static_len in bytes
			var max_blindex = 0; // index of last bit length code of non zero freq

			// Build the Huffman trees unless a stored block is forced
			if (level > 0) {
				// Construct the literal and distance trees
				l_desc.build_tree(that);

				d_desc.build_tree(that);

				// At this point, opt_len and static_len are the total bit lengths
				// of
				// the compressed block data, excluding the tree representations.

				// Build the bit length tree for the above two trees, and get the
				// index
				// in bl_order of the last bit length code to send.
				max_blindex = build_bl_tree();

				// Determine the best encoding. Compute first the block length in
				// bytes
				opt_lenb = (that.opt_len + 3 + 7) >>> 3;
				static_lenb = (that.static_len + 3 + 7) >>> 3;

				if (static_lenb <= opt_lenb)
					opt_lenb = static_lenb;
			} else {
				opt_lenb = static_lenb = stored_len + 5; // force a stored block
			}

			if ((stored_len + 4 <= opt_lenb) && buf != -1) {
				// 4: two words for the lengths
				// The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
				// Otherwise we can't have processed more than WSIZE input bytes
				// since
				// the last block flush, because compression would have been
				// successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
				// transform a block into a stored block.
				_tr_stored_block(buf, stored_len, eof);
			} else if (static_lenb == opt_lenb) {
				send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
				compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
			} else {
				send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
				send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
				compress_block(dyn_ltree, dyn_dtree);
			}

			// The above check is made mod 2^32, for files larger than 512 MB
			// and uLong implemented on 32 bits.

			init_block();

			if (eof) {
				bi_windup();
			}
		}

		function flush_block_only(eof) {
			_tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);
			block_start = strstart;
			strm.flush_pending();
		}

		// Fill the window when the lookahead becomes insufficient.
		// Updates strstart and lookahead.
		//
		// IN assertion: lookahead < MIN_LOOKAHEAD
		// OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
		// At least one byte has been read, or avail_in === 0; reads are
		// performed for at least two bytes (required for the zip translate_eol
		// option -- not supported here).
		function fill_window() {
			var n, m;
			var p;
			var more; // Amount of free space at the end of the window.

			do {
				more = (window_size - lookahead - strstart);

				// Deal with !@#$% 64K limit:
				if (more === 0 && strstart === 0 && lookahead === 0) {
					more = w_size;
				} else if (more == -1) {
					// Very unlikely, but possible on 16 bit machine if strstart ==
					// 0
					// and lookahead == 1 (input done one byte at time)
					more--;

					// If the window is almost full and there is insufficient
					// lookahead,
					// move the upper half to the lower one to make room in the
					// upper half.
				} else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
					window.set(window.subarray(w_size, w_size + w_size), 0);

					match_start -= w_size;
					strstart -= w_size; // we now have strstart >= MAX_DIST
					block_start -= w_size;

					// Slide the hash table (could be avoided with 32 bit values
					// at the expense of memory usage). We slide even when level ==
					// 0
					// to keep the hash table consistent if we switch back to level
					// > 0
					// later. (Using level 0 permanently is not an optimal usage of
					// zlib, so we don't care about this pathological case.)

					n = hash_size;
					p = n;
					do {
						m = (head[--p] & 0xffff);
						head[p] = (m >= w_size ? m - w_size : 0);
					} while (--n !== 0);

					n = w_size;
					p = n;
					do {
						m = (prev[--p] & 0xffff);
						prev[p] = (m >= w_size ? m - w_size : 0);
						// If n is not on any hash chain, prev[n] is garbage but
						// its value will never be used.
					} while (--n !== 0);
					more += w_size;
				}

				if (strm.avail_in === 0)
					return;

				// If there was no sliding:
				// strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
				// more == window_size - lookahead - strstart
				// => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
				// => more >= window_size - 2*WSIZE + 2
				// In the BIG_MEM or MMAP case (not yet supported),
				// window_size == input_size + MIN_LOOKAHEAD &&
				// strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
				// Otherwise, window_size == 2*WSIZE so more >= 2.
				// If there was sliding, more >= WSIZE. So in all cases, more >= 2.

				n = strm.read_buf(window, strstart + lookahead, more);
				lookahead += n;

				// Initialize the hash value now that we have some input:
				if (lookahead >= MIN_MATCH) {
					ins_h = window[strstart] & 0xff;
					ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
				}
				// If the whole input has less than MIN_MATCH bytes, ins_h is
				// garbage,
				// but this is not important since only literal bytes will be
				// emitted.
			} while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);
		}

		// Copy without compression as much as possible from the input stream,
		// return
		// the current block state.
		// This function does not insert new strings in the dictionary since
		// uncompressible data is probably not useful. This function is used
		// only for the level=0 compression option.
		// NOTE: this function should be optimized to avoid extra copying from
		// window to pending_buf.
		function deflate_stored(flush) {
			// Stored blocks are limited to 0xffff bytes, pending_buf is limited
			// to pending_buf_size, and each stored block has a 5 byte header:

			var max_block_size = 0xffff;
			var max_start;

			if (max_block_size > pending_buf_size - 5) {
				max_block_size = pending_buf_size - 5;
			}

			// Copy as much as possible from input to output:
			while (true) {
				// Fill the window as much as possible:
				if (lookahead <= 1) {
					fill_window();
					if (lookahead === 0 && flush == Z_NO_FLUSH)
						return NeedMore;
					if (lookahead === 0)
						break; // flush the current block
				}

				strstart += lookahead;
				lookahead = 0;

				// Emit a stored block if pending_buf will be full:
				max_start = block_start + max_block_size;
				if (strstart === 0 || strstart >= max_start) {
					// strstart === 0 is possible when wraparound on 16-bit machine
					lookahead = (strstart - max_start);
					strstart = max_start;

					flush_block_only(false);
					if (strm.avail_out === 0)
						return NeedMore;

				}

				// Flush if we may have to slide, otherwise block_start may become
				// negative and the data will be gone:
				if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
					flush_block_only(false);
					if (strm.avail_out === 0)
						return NeedMore;
				}
			}

			flush_block_only(flush == Z_FINISH);
			if (strm.avail_out === 0)
				return (flush == Z_FINISH) ? FinishStarted : NeedMore;

			return flush == Z_FINISH ? FinishDone : BlockDone;
		}

		function longest_match(cur_match) {
			var chain_length = max_chain_length; // max hash chain length
			var scan = strstart; // current string
			var match; // matched string
			var len; // length of current match
			var best_len = prev_length; // best match length so far
			var limit = strstart > (w_size - MIN_LOOKAHEAD) ? strstart - (w_size - MIN_LOOKAHEAD) : 0;
			var _nice_match = nice_match;

			// Stop when cur_match becomes <= limit. To simplify the code,
			// we prevent matches with the string of window index 0.

			var wmask = w_mask;

			var strend = strstart + MAX_MATCH;
			var scan_end1 = window[scan + best_len - 1];
			var scan_end = window[scan + best_len];

			// The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of
			// 16.
			// It is easy to get rid of this optimization if necessary.

			// Do not waste too much time if we already have a good match:
			if (prev_length >= good_match) {
				chain_length >>= 2;
			}

			// Do not look for matches beyond the end of the input. This is
			// necessary
			// to make deflate deterministic.
			if (_nice_match > lookahead)
				_nice_match = lookahead;

			do {
				match = cur_match;

				// Skip to next match if the match length cannot increase
				// or if the match length is less than 2:
				if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan]
					|| window[++match] != window[scan + 1])
					continue;

				// The check at best_len-1 can be removed because it will be made
				// again later. (This heuristic is not always a win.)
				// It is not necessary to compare scan[2] and match[2] since they
				// are always equal when the other bytes match, given that
				// the hash keys are equal and that HASH_BITS >= 8.
				scan += 2;
				match++;

				// We check for insufficient lookahead only every 8th comparison;
				// the 256th check will be made at strstart+258.
				do {
				} while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
				&& window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
				&& window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend);

				len = MAX_MATCH - (strend - scan);
				scan = strend - MAX_MATCH;

				if (len > best_len) {
					match_start = cur_match;
					best_len = len;
					if (len >= _nice_match)
						break;
					scan_end1 = window[scan + best_len - 1];
					scan_end = window[scan + best_len];
				}

			} while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit && --chain_length !== 0);

			if (best_len <= lookahead)
				return best_len;
			return lookahead;
		}

		// Compress as much as possible from the input stream, return the current
		// block state.
		// This function does not perform lazy evaluation of matches and inserts
		// new strings in the dictionary only for unmatched strings or for short
		// matches. It is used only for the fast compression options.
		function deflate_fast(flush) {
			// short hash_head = 0; // head of the hash chain
			var hash_head = 0; // head of the hash chain
			var bflush; // set if current block must be flushed

			while (true) {
				// Make sure that we always have enough lookahead, except
				// at the end of the input file. We need MAX_MATCH bytes
				// for the next match, plus MIN_MATCH bytes to insert the
				// string following the next match.
				if (lookahead < MIN_LOOKAHEAD) {
					fill_window();
					if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
						return NeedMore;
					}
					if (lookahead === 0)
						break; // flush the current block
				}

				// Insert the string window[strstart .. strstart+2] in the
				// dictionary, and set hash_head to the head of the hash chain:
				if (lookahead >= MIN_MATCH) {
					ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;

					// prev[strstart&w_mask]=hash_head=head[ins_h];
					hash_head = (head[ins_h] & 0xffff);
					prev[strstart & w_mask] = head[ins_h];
					head[ins_h] = strstart;
				}

				// Find the longest match, discarding those <= prev_length.
				// At this point we have always match_length < MIN_MATCH

				if (hash_head !== 0 && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
					// To simplify the code, we prevent matches with the string
					// of window index 0 (in particular we have to avoid a match
					// of the string with itself at the start of the input file).
					if (strategy != Z_HUFFMAN_ONLY) {
						match_length = longest_match(hash_head);
					}
					// longest_match() sets match_start
				}
				if (match_length >= MIN_MATCH) {
					// check_match(strstart, match_start, match_length);

					bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);

					lookahead -= match_length;

					// Insert new strings in the hash table only if the match length
					// is not too large. This saves time but degrades compression.
					if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {
						match_length--; // string at strstart already in hash table
						do {
							strstart++;

							ins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
							// prev[strstart&w_mask]=hash_head=head[ins_h];
							hash_head = (head[ins_h] & 0xffff);
							prev[strstart & w_mask] = head[ins_h];
							head[ins_h] = strstart;

							// strstart never exceeds WSIZE-MAX_MATCH, so there are
							// always MIN_MATCH bytes ahead.
						} while (--match_length !== 0);
						strstart++;
					} else {
						strstart += match_length;
						match_length = 0;
						ins_h = window[strstart] & 0xff;

						ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
						// If lookahead < MIN_MATCH, ins_h is garbage, but it does
						// not
						// matter since it will be recomputed at next deflate call.
					}
				} else {
					// No match, output a literal byte

					bflush = _tr_tally(0, window[strstart] & 0xff);
					lookahead--;
					strstart++;
				}
				if (bflush) {

					flush_block_only(false);
					if (strm.avail_out === 0)
						return NeedMore;
				}
			}

			flush_block_only(flush == Z_FINISH);
			if (strm.avail_out === 0) {
				if (flush == Z_FINISH)
					return FinishStarted;
				else
					return NeedMore;
			}
			return flush == Z_FINISH ? FinishDone : BlockDone;
		}

		// Same as above, but achieves better compression. We use a lazy
		// evaluation for matches: a match is finally adopted only if there is
		// no better match at the next window position.
		function deflate_slow(flush) {
			// short hash_head = 0; // head of hash chain
			var hash_head = 0; // head of hash chain
			var bflush; // set if current block must be flushed
			var max_insert;

			// Process the input block.
			while (true) {
				// Make sure that we always have enough lookahead, except
				// at the end of the input file. We need MAX_MATCH bytes
				// for the next match, plus MIN_MATCH bytes to insert the
				// string following the next match.

				if (lookahead < MIN_LOOKAHEAD) {
					fill_window();
					if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
						return NeedMore;
					}
					if (lookahead === 0)
						break; // flush the current block
				}

				// Insert the string window[strstart .. strstart+2] in the
				// dictionary, and set hash_head to the head of the hash chain:

				if (lookahead >= MIN_MATCH) {
					ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
					// prev[strstart&w_mask]=hash_head=head[ins_h];
					hash_head = (head[ins_h] & 0xffff);
					prev[strstart & w_mask] = head[ins_h];
					head[ins_h] = strstart;
				}

				// Find the longest match, discarding those <= prev_length.
				prev_length = match_length;
				prev_match = match_start;
				match_length = MIN_MATCH - 1;

				if (hash_head !== 0 && prev_length < max_lazy_match && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
					// To simplify the code, we prevent matches with the string
					// of window index 0 (in particular we have to avoid a match
					// of the string with itself at the start of the input file).

					if (strategy != Z_HUFFMAN_ONLY) {
						match_length = longest_match(hash_head);
					}
					// longest_match() sets match_start

					if (match_length <= 5 && (strategy == Z_FILTERED || (match_length == MIN_MATCH && strstart - match_start > 4096))) {

						// If prev_match is also MIN_MATCH, match_start is garbage
						// but we will ignore the current match anyway.
						match_length = MIN_MATCH - 1;
					}
				}

				// If there was a match at the previous step and the current
				// match is not better, output the previous match:
				if (prev_length >= MIN_MATCH && match_length <= prev_length) {
					max_insert = strstart + lookahead - MIN_MATCH;
					// Do not insert strings in hash table beyond this.

					// check_match(strstart-1, prev_match, prev_length);

					bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);

					// Insert in hash table all strings up to the end of the match.
					// strstart-1 and strstart are already inserted. If there is not
					// enough lookahead, the last two strings are not inserted in
					// the hash table.
					lookahead -= prev_length - 1;
					prev_length -= 2;
					do {
						if (++strstart <= max_insert) {
							ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
							// prev[strstart&w_mask]=hash_head=head[ins_h];
							hash_head = (head[ins_h] & 0xffff);
							prev[strstart & w_mask] = head[ins_h];
							head[ins_h] = strstart;
						}
					} while (--prev_length !== 0);
					match_available = 0;
					match_length = MIN_MATCH - 1;
					strstart++;

					if (bflush) {
						flush_block_only(false);
						if (strm.avail_out === 0)
							return NeedMore;
					}
				} else if (match_available !== 0) {

					// If there was no match at the previous position, output a
					// single literal. If there was a match but the current match
					// is longer, truncate the previous match to a single literal.

					bflush = _tr_tally(0, window[strstart - 1] & 0xff);

					if (bflush) {
						flush_block_only(false);
					}
					strstart++;
					lookahead--;
					if (strm.avail_out === 0)
						return NeedMore;
				} else {
					// There is no previous match to compare with, wait for
					// the next step to decide.

					match_available = 1;
					strstart++;
					lookahead--;
				}
			}

			if (match_available !== 0) {
				bflush = _tr_tally(0, window[strstart - 1] & 0xff);
				match_available = 0;
			}
			flush_block_only(flush == Z_FINISH);

			if (strm.avail_out === 0) {
				if (flush == Z_FINISH)
					return FinishStarted;
				else
					return NeedMore;
			}

			return flush == Z_FINISH ? FinishDone : BlockDone;
		}

		function deflateReset(strm) {
			strm.total_in = strm.total_out = 0;
			strm.msg = null; //

			that.pending = 0;
			that.pending_out = 0;

			status = BUSY_STATE;

			last_flush = Z_NO_FLUSH;

			tr_init();
			lm_init();
			return Z_OK;
		}

		that.deflateInit = function (strm, _level, bits, _method, memLevel, _strategy) {
			if (!_method)
				_method = Z_DEFLATED;
			if (!memLevel)
				memLevel = DEF_MEM_LEVEL;
			if (!_strategy)
				_strategy = Z_DEFAULT_STRATEGY;

			// byte[] my_version=ZLIB_VERSION;

			//
			// if (!version || version[0] != my_version[0]
			// || stream_size != sizeof(z_stream)) {
			// return Z_VERSION_ERROR;
			// }

			strm.msg = null;

			if (_level == Z_DEFAULT_COMPRESSION)
				_level = 6;

			if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0
				|| _strategy > Z_HUFFMAN_ONLY) {
				return Z_STREAM_ERROR;
			}

			strm.dstate = that;

			w_bits = bits;
			w_size = 1 << w_bits;
			w_mask = w_size - 1;

			hash_bits = memLevel + 7;
			hash_size = 1 << hash_bits;
			hash_mask = hash_size - 1;
			hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);

			window = new Uint8Array(w_size * 2);
			prev = [];
			head = [];

			lit_bufsize = 1 << (memLevel + 6); // 16K elements by default

			// We overlay pending_buf and d_buf+l_buf. This works since the average
			// output size for (length,distance) codes is <= 24 bits.
			that.pending_buf = new Uint8Array(lit_bufsize * 4);
			pending_buf_size = lit_bufsize * 4;

			d_buf = Math.floor(lit_bufsize / 2);
			l_buf = (1 + 2) * lit_bufsize;

			level = _level;

			strategy = _strategy;
			method = _method & 0xff;

			return deflateReset(strm);
		};

		that.deflateEnd = function () {
			if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
				return Z_STREAM_ERROR;
			}
			// Deallocate in reverse order of allocations:
			that.pending_buf = null;
			head = null;
			prev = null;
			window = null;
			// free
			that.dstate = null;
			return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
		};

		that.deflateParams = function (strm, _level, _strategy) {
			var err = Z_OK;

			if (_level == Z_DEFAULT_COMPRESSION) {
				_level = 6;
			}
			if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
				return Z_STREAM_ERROR;
			}

			if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) {
				// Flush the last buffer:
				err = strm.deflate(Z_PARTIAL_FLUSH);
			}

			if (level != _level) {
				level = _level;
				max_lazy_match = config_table[level].max_lazy;
				good_match = config_table[level].good_length;
				nice_match = config_table[level].nice_length;
				max_chain_length = config_table[level].max_chain;
			}
			strategy = _strategy;
			return err;
		};

		that.deflateSetDictionary = function (strm, dictionary, dictLength) {
			var length = dictLength;
			var n, index = 0;

			if (!dictionary || status != INIT_STATE)
				return Z_STREAM_ERROR;

			if (length < MIN_MATCH)
				return Z_OK;
			if (length > w_size - MIN_LOOKAHEAD) {
				length = w_size - MIN_LOOKAHEAD;
				index = dictLength - length; // use the tail of the dictionary
			}
			window.set(dictionary.subarray(index, index + length), 0);

			strstart = length;
			block_start = length;

			// Insert all strings in the hash table (except for the last two bytes).
			// s->lookahead stays null, so s->ins_h will be recomputed at the next
			// call of fill_window.

			ins_h = window[0] & 0xff;
			ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask;

			for (n = 0; n <= length - MIN_MATCH; n++) {
				ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
				prev[n & w_mask] = head[ins_h];
				head[ins_h] = n;
			}
			return Z_OK;
		};

		that.deflate = function (_strm, flush) {
			var i, header, level_flags, old_flush, bstate;

			if (flush > Z_FINISH || flush < 0) {
				return Z_STREAM_ERROR;
			}

			if (!_strm.next_out || (!_strm.next_in && _strm.avail_in !== 0) || (status == FINISH_STATE && flush != Z_FINISH)) {
				_strm.msg = z_errmsg[Z_NEED_DICT - (Z_STREAM_ERROR)];
				return Z_STREAM_ERROR;
			}
			if (_strm.avail_out === 0) {
				_strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
				return Z_BUF_ERROR;
			}

			strm = _strm; // just in case
			old_flush = last_flush;
			last_flush = flush;

			// Write the zlib header
			if (status == INIT_STATE) {
				header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;
				level_flags = ((level - 1) & 0xff) >> 1;

				if (level_flags > 3)
					level_flags = 3;
				header |= (level_flags << 6);
				if (strstart !== 0)
					header |= PRESET_DICT;
				header += 31 - (header % 31);

				status = BUSY_STATE;
				putShortMSB(header);
			}

			// Flush as much pending output as possible
			if (that.pending !== 0) {
				strm.flush_pending();
				if (strm.avail_out === 0) {
					// console.log(" avail_out==0");
					// Since avail_out is 0, deflate will be called again with
					// more output space, but possibly with both pending and
					// avail_in equal to zero. There won't be anything to do,
					// but this is not an error situation so make sure we
					// return OK instead of BUF_ERROR at next call of deflate:
					last_flush = -1;
					return Z_OK;
				}

				// Make sure there is something to do and avoid duplicate
				// consecutive
				// flushes. For repeated and useless calls with Z_FINISH, we keep
				// returning Z_STREAM_END instead of Z_BUFF_ERROR.
			} else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {
				strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
				return Z_BUF_ERROR;
			}

			// User must not provide more input after the first FINISH:
			if (status == FINISH_STATE && strm.avail_in !== 0) {
				_strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
				return Z_BUF_ERROR;
			}

			// Start a new block or continue the current one.
			if (strm.avail_in !== 0 || lookahead !== 0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) {
				bstate = -1;
				switch (config_table[level].func) {
					case STORED:
						bstate = deflate_stored(flush);
						break;
					case FAST:
						bstate = deflate_fast(flush);
						break;
					case SLOW:
						bstate = deflate_slow(flush);
						break;
					default:
				}

				if (bstate == FinishStarted || bstate == FinishDone) {
					status = FINISH_STATE;
				}
				if (bstate == NeedMore || bstate == FinishStarted) {
					if (strm.avail_out === 0) {
						last_flush = -1; // avoid BUF_ERROR next call, see above
					}
					return Z_OK;
					// If flush != Z_NO_FLUSH && avail_out === 0, the next call
					// of deflate should use the same flush parameter to make sure
					// that the flush is complete. So we don't have to output an
					// empty block here, this will be done at next call. This also
					// ensures that for a very small output buffer, we emit at most
					// one empty block.
				}

				if (bstate == BlockDone) {
					if (flush == Z_PARTIAL_FLUSH) {
						_tr_align();
					} else { // FULL_FLUSH or SYNC_FLUSH
						_tr_stored_block(0, 0, false);
						// For a full flush, this empty block will be recognized
						// as a special marker by inflate_sync().
						if (flush == Z_FULL_FLUSH) {
							// state.head[s.hash_size-1]=0;
							for (i = 0; i < hash_size/*-1*/; i++)
								// forget history
								head[i] = 0;
						}
					}
					strm.flush_pending();
					if (strm.avail_out === 0) {
						last_flush = -1; // avoid BUF_ERROR at next call, see above
						return Z_OK;
					}
				}
			}

			if (flush != Z_FINISH)
				return Z_OK;
			return Z_STREAM_END;
		};
	}

	// ZStream

	function ZStream() {
		var that = this;
		that.next_in_index = 0;
		that.next_out_index = 0;
		// that.next_in; // next input byte
		that.avail_in = 0; // number of bytes available at next_in
		that.total_in = 0; // total nb of input bytes read so far
		// that.next_out; // next output byte should be put there
		that.avail_out = 0; // remaining free space at next_out
		that.total_out = 0; // total nb of bytes output so far
		// that.msg;
		// that.dstate;
	}

	ZStream.prototype = {
		deflateInit: function (level, bits) {
			var that = this;
			that.dstate = new Deflate();
			if (!bits)
				bits = MAX_BITS;
			return that.dstate.deflateInit(that, level, bits);
		},

		deflate: function (flush) {
			var that = this;
			if (!that.dstate) {
				return Z_STREAM_ERROR;
			}
			return that.dstate.deflate(that, flush);
		},

		deflateEnd: function () {
			var that = this;
			if (!that.dstate)
				return Z_STREAM_ERROR;
			var ret = that.dstate.deflateEnd();
			that.dstate = null;
			return ret;
		},

		deflateParams: function (level, strategy) {
			var that = this;
			if (!that.dstate)
				return Z_STREAM_ERROR;
			return that.dstate.deflateParams(that, level, strategy);
		},

		deflateSetDictionary: function (dictionary, dictLength) {
			var that = this;
			if (!that.dstate)
				return Z_STREAM_ERROR;
			return that.dstate.deflateSetDictionary(that, dictionary, dictLength);
		},

		// Read a new buffer from the current input stream, update the
		// total number of bytes read. All deflate() input goes through
		// this function so some applications may wish to modify it to avoid
		// allocating a large strm->next_in buffer and copying from it.
		// (See also flush_pending()).
		read_buf: function (buf, start, size) {
			var that = this;
			var len = that.avail_in;
			if (len > size)
				len = size;
			if (len === 0)
				return 0;
			that.avail_in -= len;
			buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);
			that.next_in_index += len;
			that.total_in += len;
			return len;
		},

		// Flush as much pending output as possible. All deflate() output goes
		// through this function so some applications may wish to modify it
		// to avoid allocating a large strm->next_out buffer and copying into it.
		// (See also read_buf()).
		flush_pending: function () {
			var that = this;
			var len = that.dstate.pending;

			if (len > that.avail_out)
				len = that.avail_out;
			if (len === 0)
				return;

			// if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index
			// || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index +
			// len)) {
			// console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " +
			// that.next_out_index + ", " + len);
			// console.log("avail_out=" + that.avail_out);
			// }

			that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);

			that.next_out_index += len;
			that.dstate.pending_out += len;
			that.total_out += len;
			that.avail_out -= len;
			that.dstate.pending -= len;
			if (that.dstate.pending === 0) {
				that.dstate.pending_out = 0;
			}
		}
	};

	// Deflater

	function Deflater(level) {
		var that = this;
		var z = new ZStream();
		var bufsize = 512;
		var flush = Z_NO_FLUSH;
		var buf = new Uint8Array(bufsize);

		if (typeof level == "undefined")
			level = Z_DEFAULT_COMPRESSION;
		z.deflateInit(level);
		z.next_out = buf;

		that.append = function (data, onprogress) {
			var err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;
			if (!data.length)
				return;
			z.next_in_index = 0;
			z.next_in = data;
			z.avail_in = data.length;
			do {
				z.next_out_index = 0;
				z.avail_out = bufsize;
				err = z.deflate(flush);
				if (err != Z_OK)
					throw "deflating: " + z.msg;
				if (z.next_out_index)
					if (z.next_out_index == bufsize)
						buffers.push(new Uint8Array(buf));
					else
						buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
				bufferSize += z.next_out_index;
				if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
					onprogress(z.next_in_index);
					lastIndex = z.next_in_index;
				}
			} while (z.avail_in > 0 || z.avail_out === 0);
			array = new Uint8Array(bufferSize);
			buffers.forEach(function (chunk) {
				array.set(chunk, bufferIndex);
				bufferIndex += chunk.length;
			});
			return array;
		};
		that.flush = function () {
			var err, buffers = [], bufferIndex = 0, bufferSize = 0, array;
			do {
				z.next_out_index = 0;
				z.avail_out = bufsize;
				err = z.deflate(Z_FINISH);
				if (err != Z_STREAM_END && err != Z_OK)
					throw "deflating: " + z.msg;
				if (bufsize - z.avail_out > 0)
					buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
				bufferSize += z.next_out_index;
			} while (z.avail_in > 0 || z.avail_out === 0);
			z.deflateEnd();
			array = new Uint8Array(bufferSize);
			buffers.forEach(function (chunk) {
				array.set(chunk, bufferIndex);
				bufferIndex += chunk.length;
			});
			return array;
		};
	}


	/*
	 * Copyright (c) 2012 chick307 <chick307@gmail.com>
	 *
	 * Licensed under the MIT License.
	 * http://opensource.org/licenses/mit-license
	 */

	var fVoid = function (global, callback) {
		if (typeof module === 'object') {
			module.exports = callback();
		} else if (typeof define === 'function') {
			define(callback);
		} else {
			global.adler32cs = callback();
		}
	}(this, function () {
		var _hasArrayBuffer = typeof ArrayBuffer === 'function' &&
			typeof Uint8Array === 'function';

		var _Buffer = null, _isBuffer = (function () {
			if (!_hasArrayBuffer)
				return function _isBuffer() { return false };

			try {
				var buffer = require('buffer');
				if (typeof buffer.Buffer === 'function')
					_Buffer = buffer.Buffer;
			} catch (error) { }

			return function _isBuffer(value) {
				return value instanceof ArrayBuffer ||
					_Buffer !== null && value instanceof _Buffer;
			};
		}());

		var _utf8ToBinary = (function () {
			if (_Buffer !== null) {
				return function _utf8ToBinary(utf8String) {
					return new _Buffer(utf8String, 'utf8').toString('binary');
				};
			} else {
				return function _utf8ToBinary(utf8String) {
					return unescape(encodeURIComponent(utf8String));
				};
			}
		}());

		var MOD = 65521;

		var _update = function _update(checksum, binaryString) {
			var a = checksum & 0xFFFF, b = checksum >>> 16;
			for (var i = 0, length = binaryString.length; i < length; i++) {
				a = (a + (binaryString.charCodeAt(i) & 0xFF)) % MOD;
				b = (b + a) % MOD;
			}
			return (b << 16 | a) >>> 0;
		};

		var _updateUint8Array = function _updateUint8Array(checksum, uint8Array) {
			var a = checksum & 0xFFFF, b = checksum >>> 16;
			for (var i = 0, length = uint8Array.length, x; i < length; i++) {
				a = (a + uint8Array[i]) % MOD;
				b = (b + a) % MOD;
			}
			return (b << 16 | a) >>> 0
		};

		var exports = {};

		var Adler32 = exports.Adler32 = (function () {
			var ctor = function Adler32(checksum) {
				if (!(this instanceof ctor)) {
					throw new TypeError(
						'Constructor cannot called be as a function.');
				}
				if (!isFinite(checksum = checksum == null ? 1 : +checksum)) {
					throw new Error(
						'First arguments needs to be a finite number.');
				}
				this.checksum = checksum >>> 0;
			};

			var proto = ctor.prototype = {};
			proto.constructor = ctor;

			ctor.from = function (from) {
				from.prototype = proto;
				return from;
			}(function from(binaryString) {
				if (!(this instanceof ctor)) {
					throw new TypeError(
						'Constructor cannot called be as a function.');
				}
				if (binaryString == null)
					throw new Error('First argument needs to be a string.');
				this.checksum = _update(1, binaryString.toString());
			});

			ctor.fromUtf8 = function (fromUtf8) {
				fromUtf8.prototype = proto;
				return fromUtf8;
			}(function fromUtf8(utf8String) {
				if (!(this instanceof ctor)) {
					throw new TypeError(
						'Constructor cannot called be as a function.');
				}
				if (utf8String == null)
					throw new Error('First argument needs to be a string.');
				var binaryString = _utf8ToBinary(utf8String.toString());
				this.checksum = _update(1, binaryString);
			});

			if (_hasArrayBuffer) {
				ctor.fromBuffer = function (fromBuffer) {
					fromBuffer.prototype = proto;
					return fromBuffer;
				}(function fromBuffer(buffer) {
					if (!(this instanceof ctor)) {
						throw new TypeError(
							'Constructor cannot called be as a function.');
					}
					if (!_isBuffer(buffer))
						throw new Error('First argument needs to be ArrayBuffer.');
					var array = new Uint8Array(buffer);
					return this.checksum = _updateUint8Array(1, array);
				});
			}

			proto.update = function update(binaryString) {
				if (binaryString == null)
					throw new Error('First argument needs to be a string.');
				binaryString = binaryString.toString();
				return this.checksum = _update(this.checksum, binaryString);
			};

			proto.updateUtf8 = function updateUtf8(utf8String) {
				if (utf8String == null)
					throw new Error('First argument needs to be a string.');
				var binaryString = _utf8ToBinary(utf8String.toString());
				return this.checksum = _update(this.checksum, binaryString);
			};

			if (_hasArrayBuffer) {
				proto.updateBuffer = function updateBuffer(buffer) {
					if (!_isBuffer(buffer))
						throw new Error('First argument needs to be ArrayBuffer.');
					var array = new Uint8Array(buffer);
					return this.checksum = _updateUint8Array(this.checksum, array);
				};
			}

			proto.clone = function clone() {
				return new Adler32(this.checksum);
			};

			return ctor;
		}());

		exports.from = function from(binaryString) {
			if (binaryString == null)
				throw new Error('First argument needs to be a string.');
			return _update(1, binaryString.toString());
		};

		exports.fromUtf8 = function fromUtf8(utf8String) {
			if (utf8String == null)
				throw new Error('First argument needs to be a string.');
			var binaryString = _utf8ToBinary(utf8String.toString());
			return _update(1, binaryString);
		};

		if (_hasArrayBuffer) {
			exports.fromBuffer = function fromBuffer(buffer) {
				if (!_isBuffer(buffer))
					throw new Error('First argument need to be ArrayBuffer.');
				var array = new Uint8Array(buffer);
				return _updateUint8Array(1, array);
			};
		}

		return exports;
	});




	var JSZip = function (data, options) { this.files = {}; this.root = ""; if (data) this.load(data, options); }
	JSZip.signature = { LOCAL_FILE_HEADER: "\x50\x4b\x03\x04", CENTRAL_FILE_HEADER: "\x50\x4b\x01\x02", CENTRAL_DIRECTORY_END: "\x50\x4b\x05\x06", ZIP64_CENTRAL_DIRECTORY_LOCATOR: "\x50\x4b\x06\x07", ZIP64_CENTRAL_DIRECTORY_END: "\x50\x4b\x06\x06", DATA_DESCRIPTOR: "\x50\x4b\x07\x08" }; JSZip.defaults = { base64: false, binary: false, dir: false, date: null }; JSZip.prototype = (function () {
		var ZipObject = function (name, data, options) { this.name = name; this.data = data; this.options = options; }; ZipObject.prototype = {
			asText: function () { return this.options.binary ? JSZip.prototype.utf8decode(this.data) : this.data; }, asBinary: function () { return this.options.binary ? this.data : JSZip.prototype.utf8encode(this.data); }
		}; var decToHex = function (dec, bytes) {
			var hex = "", i; for (i = 0; i < bytes; i++) { hex += String.fromCharCode(dec & 0xff); dec = dec >>> 8; }
			return hex;
		}; var extend = function () {
			var result = {}, i, attr; for (i = 0; i < arguments.length; i++) {
				for (attr in arguments[i]) {
					if (typeof result[attr] === "undefined") { result[attr] = arguments[i][attr]; }
				}
			}
			return result;
		}; var prepareFileAttrs = function (o) { o = o || {}; if (o.base64 === true && o.binary == null) o.binary = true; o = extend(o, JSZip.defaults); o.date = o.date || new Date(); return o; }
		var fileAdd = function (name, data, o) { var parent = parentFolder(name); if (parent) folderAdd.call(this, parent); o = prepareFileAttrs(o); return this.files[name] = { name: name, data: data, options: o }; }; var parentFolder = function (path) {
			if (path.slice(-1) == '/') { path = path.substring(0, path.length - 1); }
			var lastSlash = path.lastIndexOf('/'); return (lastSlash > 0) ? path.substring(0, lastSlash) : "";
		}; var folderAdd = function (name) {
			if (name.slice(-1) != "/") name += "/"; if (!this.files[name]) { var parent = parentFolder(name); if (parent) folderAdd.call(this, parent); fileAdd.call(this, name, '', { dir: true }); }
			return this.files[name];
		}; var prepareLocalHeaderData = function (file, utfEncodedFileName, compressionType) { var useUTF8 = utfEncodedFileName !== file.name, data = file.data, o = file.options, dosTime, dosDate; dosTime = o.date.getHours(); dosTime = dosTime << 6; dosTime = dosTime | o.date.getMinutes(); dosTime = dosTime << 5; dosTime = dosTime | o.date.getSeconds() / 2; dosDate = o.date.getFullYear() - 1980; dosDate = dosDate << 4; dosDate = dosDate | (o.date.getMonth() + 1); dosDate = dosDate << 5; dosDate = dosDate | o.date.getDate(); if (o.base64 === true) data = JSZipBase64.decode(data); if (o.binary === false) data = this.utf8encode(data); var compression = JSZip.compressions[compressionType]; var compressedData = compression.compress(data); var header = ""; header += "\x0A\x00"; header += useUTF8 ? "\x00\x08" : "\x00\x00"; header += compression.magic; header += decToHex(dosTime, 2); header += decToHex(dosDate, 2); header += decToHex(this.crc32(data), 4); header += decToHex(compressedData.length, 4); header += decToHex(data.length, 4); header += decToHex(utfEncodedFileName.length, 2); header += "\x00\x00"; return { header: header, compressedData: compressedData }; }; return {
			load: function (stream, options) { throw new Error("Load method is not defined. Is the file jszip-load.js included ?"); }, filter: function (search) {
				var result = [], filename, relativePath, file, fileClone; for (filename in this.files) {
					file = this.files[filename]; fileClone = new ZipObject(file.name, file.data, extend(file.options)); relativePath = filename.slice(this.root.length, filename.length); if (filename.slice(0, this.root.length) === this.root && search(relativePath, fileClone)) { result.push(fileClone); }
				}
				return result;
			}, file: function (name, data, o) {
				if (arguments.length === 1) {
					if (name instanceof RegExp) { var regexp = name; return this.filter(function (relativePath, file) { return !file.options.dir && regexp.test(relativePath); }); }
					else { return this.filter(function (relativePath, file) { return !file.options.dir && relativePath === name; })[0] || null; }
				}
				else { name = this.root + name; fileAdd.call(this, name, data, o); }
				return this;
			}, folder: function (arg) {
				if (!arg) { throw new Error("folder : wrong argument"); }
				if (arg instanceof RegExp) { return this.filter(function (relativePath, file) { return file.options.dir && arg.test(relativePath); }); }
				var name = this.root + arg; var newFolder = folderAdd.call(this, name); var ret = this.clone(); ret.root = newFolder.name; return ret;
			}, remove: function (name) {
				name = this.root + name; var file = this.files[name]; if (!file) { if (name.slice(-1) != "/") name += "/"; file = this.files[name]; }
				if (file) {
					if (!file.options.dir) { delete this.files[name]; }
					else {
						var kids = this.filter(function (relativePath, file) { return file.name.slice(0, name.length) === name; }); for (var i = 0; i < kids.length; i++) { delete this.files[kids[i].name]; }
					}
				}
				return this;
			}, generate: function (options) {
				options = extend(options || {}, { base64: true, compression: "STORE" }); var compression = options.compression.toUpperCase(); var directory = [], files = [], fileOffset = 0; if (!JSZip.compressions[compression]) { throw compression + " is not a valid compression method !"; }
				for (var name in this.files) {
					if (!this.files.hasOwnProperty(name)) { continue; }
					var file = this.files[name]; var utfEncodedFileName = this.utf8encode(file.name); var fileRecord = "", dirRecord = "", data = prepareLocalHeaderData.call(this, file, utfEncodedFileName, compression); fileRecord = JSZip.signature.LOCAL_FILE_HEADER + data.header + utfEncodedFileName + data.compressedData; dirRecord = JSZip.signature.CENTRAL_FILE_HEADER + "\x14\x00" +
						data.header + "\x00\x00" + "\x00\x00" + "\x00\x00" +
						(this.files[name].dir === true ? "\x10\x00\x00\x00" : "\x00\x00\x00\x00") +
						decToHex(fileOffset, 4) +
						utfEncodedFileName; fileOffset += fileRecord.length; files.push(fileRecord); directory.push(dirRecord);
				}
				var fileData = files.join(""); var dirData = directory.join(""); var dirEnd = ""; dirEnd = JSZip.signature.CENTRAL_DIRECTORY_END + "\x00\x00" + "\x00\x00" +
					decToHex(files.length, 2) +
					decToHex(files.length, 2) +
					decToHex(dirData.length, 4) +
					decToHex(fileData.length, 4) + "\x00\x00"; var zip = fileData + dirData + dirEnd; return (options.base64) ? JSZipBase64.encode(zip) : zip;
			}, crc32: function (str, crc) {
				if (str === "" || typeof str === "undefined") return 0; var table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D"; if (typeof (crc) == "undefined") { crc = 0; }
				var x = 0; var y = 0; crc = crc ^ (-1); for (var i = 0, iTop = str.length; i < iTop; i++) { y = (crc ^ str.charCodeAt(i)) & 0xFF; x = "0x" + table.substr(y * 9, 8); crc = (crc >>> 8) ^ x; }
				return crc ^ (-1);
			}, clone: function () {
				var newObj = new JSZip(); for (var i in this) {
					if (typeof this[i] !== "function") { newObj[i] = this[i]; }
				}
				return newObj;
			}, utf8encode: function (string) {
				string = string.replace(/\r\n/g, "\n"); var utftext = ""; for (var n = 0; n < string.length; n++) {
					var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); }
					else if ((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); }
					else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); }
				}
				return utftext;
			}, utf8decode: function (utftext) {
				var string = ""; var i = 0; var c = 0, c1 = 0, c2 = 0, c3 = 0; while (i < utftext.length) {
					c = utftext.charCodeAt(i); if (c < 128) { string += String.fromCharCode(c); i++; }
					else if ((c > 191) && (c < 224)) { c2 = utftext.charCodeAt(i + 1); string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); i += 2; }
					else { c2 = utftext.charCodeAt(i + 1); c3 = utftext.charCodeAt(i + 2); string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); i += 3; }
				}
				return string;
			}
		};
	})(); JSZip.compressions = {
		"STORE": {
			magic: "\x00\x00", compress: function (content) { return content; }, uncompress: function (content) { return content; }
		}
	}; var JSZipBase64 = function () {
		var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; return {
			encode: function (input, utf8) {
				var output = ""; var chr1, chr2, chr3, enc1, enc2, enc3, enc4; var i = 0; while (i < input.length) {
					chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; }
					output = output +
						_keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
						_keyStr.charAt(enc3) + _keyStr.charAt(enc4);
				}
				return output;
			}, decode: function (input, utf8) {
				var output = ""; var chr1, chr2, chr3; var enc1, enc2, enc3, enc4; var i = 0; input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); while (i < input.length) {
					enc1 = _keyStr.indexOf(input.charAt(i++)); enc2 = _keyStr.indexOf(input.charAt(i++)); enc3 = _keyStr.indexOf(input.charAt(i++)); enc4 = _keyStr.indexOf(input.charAt(i++)); chr1 = (enc1 << 2) | (enc2 >> 4); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr3 = ((enc3 & 3) << 6) | enc4; output = output + String.fromCharCode(chr1); if (enc3 != 64) { output = output + String.fromCharCode(chr2); }
					if (enc4 != 64) { output = output + String.fromCharCode(chr3); }
				}
				return output;
			}
		};
	}();


	if (!JSZip) { throw "JSZip not defined"; }
	(function () {
		var zip_WSIZE = 32768; var zip_STORED_BLOCK = 0; var zip_STATIC_TREES = 1; var zip_DYN_TREES = 2; var zip_DEFAULT_LEVEL = 6; var zip_FULL_SEARCH = true; var zip_INBUFSIZ = 32768; var zip_INBUF_EXTRA = 64; var zip_OUTBUFSIZ = 1024 * 8; var zip_window_size = 2 * zip_WSIZE; var zip_MIN_MATCH = 3; var zip_MAX_MATCH = 258; var zip_BITS = 16; var zip_LIT_BUFSIZE = 0x2000; var zip_HASH_BITS = 13; if (zip_LIT_BUFSIZE > zip_INBUFSIZ)
			alert("error: zip_INBUFSIZ is too small"); if ((zip_WSIZE << 1) > (1 << zip_BITS))
			alert("error: zip_WSIZE is too large"); if (zip_HASH_BITS > zip_BITS - 1)
			alert("error: zip_HASH_BITS is too large"); if (zip_HASH_BITS < 8 || zip_MAX_MATCH != 258)
			alert("error: Code too clever"); var zip_DIST_BUFSIZE = zip_LIT_BUFSIZE; var zip_HASH_SIZE = 1 << zip_HASH_BITS; var zip_HASH_MASK = zip_HASH_SIZE - 1; var zip_WMASK = zip_WSIZE - 1; var zip_NIL = 0; var zip_TOO_FAR = 4096; var zip_MIN_LOOKAHEAD = zip_MAX_MATCH + zip_MIN_MATCH + 1; var zip_MAX_DIST = zip_WSIZE - zip_MIN_LOOKAHEAD; var zip_SMALLEST = 1; var zip_MAX_BITS = 15; var zip_MAX_BL_BITS = 7; var zip_LENGTH_CODES = 29; var zip_LITERALS = 256; var zip_END_BLOCK = 256; var zip_L_CODES = zip_LITERALS + 1 + zip_LENGTH_CODES; var zip_D_CODES = 30; var zip_BL_CODES = 19; var zip_REP_3_6 = 16; var zip_REPZ_3_10 = 17; var zip_REPZ_11_138 = 18; var zip_HEAP_SIZE = 2 * zip_L_CODES + 1; var zip_H_SHIFT = parseInt((zip_HASH_BITS + zip_MIN_MATCH - 1) / zip_MIN_MATCH); var zip_free_queue; var zip_qhead, zip_qtail; var zip_initflag; var zip_outbuf = null; var zip_outcnt, zip_outoff; var zip_complete; var zip_window; var zip_d_buf; var zip_l_buf; var zip_prev; var zip_bi_buf; var zip_bi_valid; var zip_block_start; var zip_ins_h; var zip_hash_head; var zip_prev_match; var zip_match_available; var zip_match_length; var zip_prev_length; var zip_strstart; var zip_match_start; var zip_eofile; var zip_lookahead; var zip_max_chain_length; var zip_max_lazy_match; var zip_compr_level; var zip_good_match; var zip_nice_match; var zip_dyn_ltree; var zip_dyn_dtree; var zip_static_ltree; var zip_static_dtree; var zip_bl_tree; var zip_l_desc; var zip_d_desc; var zip_bl_desc; var zip_bl_count; var zip_heap; var zip_heap_len; var zip_heap_max; var zip_depth; var zip_length_code; var zip_dist_code; var zip_base_length; var zip_base_dist; var zip_flag_buf; var zip_last_lit; var zip_last_dist; var zip_last_flags; var zip_flags; var zip_flag_bit; var zip_opt_len; var zip_static_len; var zip_deflate_data; var zip_deflate_pos; var zip_DeflateCT = function () { this.fc = 0; this.dl = 0; }
		var zip_DeflateTreeDesc = function () { this.dyn_tree = null; this.static_tree = null; this.extra_bits = null; this.extra_base = 0; this.elems = 0; this.max_length = 0; this.max_code = 0; }
		var zip_DeflateConfiguration = function (a, b, c, d) { this.good_length = a; this.max_lazy = b; this.nice_length = c; this.max_chain = d; }
		var zip_DeflateBuffer = function () { this.next = null; this.len = 0; this.ptr = new Array(zip_OUTBUFSIZ); this.off = 0; }
		var zip_extra_lbits = new Array(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0); var zip_extra_dbits = new Array(0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13); var zip_extra_blbits = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7); var zip_bl_order = new Array(16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15); var zip_configuration_table = new Array(new zip_DeflateConfiguration(0, 0, 0, 0), new zip_DeflateConfiguration(4, 4, 8, 4), new zip_DeflateConfiguration(4, 5, 16, 8), new zip_DeflateConfiguration(4, 6, 32, 32), new zip_DeflateConfiguration(4, 4, 16, 16), new zip_DeflateConfiguration(8, 16, 32, 32), new zip_DeflateConfiguration(8, 16, 128, 128), new zip_DeflateConfiguration(8, 32, 128, 256), new zip_DeflateConfiguration(32, 128, 258, 1024), new zip_DeflateConfiguration(32, 258, 258, 4096)); var zip_deflate_start = function (level) {
			var i; if (!level)
				level = zip_DEFAULT_LEVEL; else if (level < 1)
				level = 1; else if (level > 9)
				level = 9; zip_compr_level = level; zip_initflag = false; zip_eofile = false; if (zip_outbuf != null)
				return; zip_free_queue = zip_qhead = zip_qtail = null; zip_outbuf = new Array(zip_OUTBUFSIZ); zip_window = new Array(zip_window_size); zip_d_buf = new Array(zip_DIST_BUFSIZE); zip_l_buf = new Array(zip_INBUFSIZ + zip_INBUF_EXTRA); zip_prev = new Array(1 << zip_BITS); zip_dyn_ltree = new Array(zip_HEAP_SIZE); for (i = 0; i < zip_HEAP_SIZE; i++)
				zip_dyn_ltree[i] = new zip_DeflateCT(); zip_dyn_dtree = new Array(2 * zip_D_CODES + 1); for (i = 0; i < 2 * zip_D_CODES + 1; i++)
				zip_dyn_dtree[i] = new zip_DeflateCT(); zip_static_ltree = new Array(zip_L_CODES + 2); for (i = 0; i < zip_L_CODES + 2; i++)
				zip_static_ltree[i] = new zip_DeflateCT(); zip_static_dtree = new Array(zip_D_CODES); for (i = 0; i < zip_D_CODES; i++)
				zip_static_dtree[i] = new zip_DeflateCT(); zip_bl_tree = new Array(2 * zip_BL_CODES + 1); for (i = 0; i < 2 * zip_BL_CODES + 1; i++)
				zip_bl_tree[i] = new zip_DeflateCT(); zip_l_desc = new zip_DeflateTreeDesc(); zip_d_desc = new zip_DeflateTreeDesc(); zip_bl_desc = new zip_DeflateTreeDesc(); zip_bl_count = new Array(zip_MAX_BITS + 1); zip_heap = new Array(2 * zip_L_CODES + 1); zip_depth = new Array(2 * zip_L_CODES + 1); zip_length_code = new Array(zip_MAX_MATCH - zip_MIN_MATCH + 1); zip_dist_code = new Array(512); zip_base_length = new Array(zip_LENGTH_CODES); zip_base_dist = new Array(zip_D_CODES); zip_flag_buf = new Array(parseInt(zip_LIT_BUFSIZE / 8));
		}
		var zip_deflate_end = function () { zip_free_queue = zip_qhead = zip_qtail = null; zip_outbuf = null; zip_window = null; zip_d_buf = null; zip_l_buf = null; zip_prev = null; zip_dyn_ltree = null; zip_dyn_dtree = null; zip_static_ltree = null; zip_static_dtree = null; zip_bl_tree = null; zip_l_desc = null; zip_d_desc = null; zip_bl_desc = null; zip_bl_count = null; zip_heap = null; zip_depth = null; zip_length_code = null; zip_dist_code = null; zip_base_length = null; zip_base_dist = null; zip_flag_buf = null; }
		var zip_reuse_queue = function (p) { p.next = zip_free_queue; zip_free_queue = p; }
		var zip_new_queue = function () {
			var p; if (zip_free_queue != null) { p = zip_free_queue; zip_free_queue = zip_free_queue.next; }
			else
				p = new zip_DeflateBuffer(); p.next = null; p.len = p.off = 0; return p;
		}
		var zip_head1 = function (i) { return zip_prev[zip_WSIZE + i]; }
		var zip_head2 = function (i, val) { return zip_prev[zip_WSIZE + i] = val; }
		var zip_put_byte = function (c) {
		zip_outbuf[zip_outoff + zip_outcnt++] = c; if (zip_outoff + zip_outcnt == zip_OUTBUFSIZ)
			zip_qoutbuf();
		}
		var zip_put_short = function (w) { w &= 0xffff; if (zip_outoff + zip_outcnt < zip_OUTBUFSIZ - 2) { zip_outbuf[zip_outoff + zip_outcnt++] = (w & 0xff); zip_outbuf[zip_outoff + zip_outcnt++] = (w >>> 8); } else { zip_put_byte(w & 0xff); zip_put_byte(w >>> 8); } }
		var zip_INSERT_STRING = function () { zip_ins_h = ((zip_ins_h << zip_H_SHIFT) ^ (zip_window[zip_strstart + zip_MIN_MATCH - 1] & 0xff)) & zip_HASH_MASK; zip_hash_head = zip_head1(zip_ins_h); zip_prev[zip_strstart & zip_WMASK] = zip_hash_head; zip_head2(zip_ins_h, zip_strstart); }
		var zip_SEND_CODE = function (c, tree) { zip_send_bits(tree[c].fc, tree[c].dl); }
		var zip_D_CODE = function (dist) { return (dist < 256 ? zip_dist_code[dist] : zip_dist_code[256 + (dist >> 7)]) & 0xff; }
		var zip_SMALLER = function (tree, n, m) { return tree[n].fc < tree[m].fc || (tree[n].fc == tree[m].fc && zip_depth[n] <= zip_depth[m]); }
		var zip_read_buff = function (buff, offset, n) {
			var i; for (i = 0; i < n && zip_deflate_pos < zip_deflate_data.length; i++)
				buff[offset + i] = zip_deflate_data.charCodeAt(zip_deflate_pos++) & 0xff; return i;
		}
		var zip_lm_init = function () {
			var j; for (j = 0; j < zip_HASH_SIZE; j++)
				zip_prev[zip_WSIZE + j] = 0; zip_max_lazy_match = zip_configuration_table[zip_compr_level].max_lazy; zip_good_match = zip_configuration_table[zip_compr_level].good_length; if (!zip_FULL_SEARCH)
				zip_nice_match = zip_configuration_table[zip_compr_level].nice_length; zip_max_chain_length = zip_configuration_table[zip_compr_level].max_chain; zip_strstart = 0; zip_block_start = 0; zip_lookahead = zip_read_buff(zip_window, 0, 2 * zip_WSIZE); if (zip_lookahead <= 0) { zip_eofile = true; zip_lookahead = 0; return; }
			zip_eofile = false; while (zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile)
				zip_fill_window(); zip_ins_h = 0; for (j = 0; j < zip_MIN_MATCH - 1; j++) { zip_ins_h = ((zip_ins_h << zip_H_SHIFT) ^ (zip_window[j] & 0xff)) & zip_HASH_MASK; }
		}
		var zip_longest_match = function (cur_match) {
			var chain_length = zip_max_chain_length; var scanp = zip_strstart; var matchp; var len; var best_len = zip_prev_length; var limit = (zip_strstart > zip_MAX_DIST ? zip_strstart - zip_MAX_DIST : zip_NIL); var strendp = zip_strstart + zip_MAX_MATCH; var scan_end1 = zip_window[scanp + best_len - 1]; var scan_end = zip_window[scanp + best_len]; if (zip_prev_length >= zip_good_match)
				chain_length >>= 2; do {
					matchp = cur_match; if (zip_window[matchp + best_len] != scan_end || zip_window[matchp + best_len - 1] != scan_end1 || zip_window[matchp] != zip_window[scanp] || zip_window[++matchp] != zip_window[scanp + 1]) { continue; }
					scanp += 2; matchp++; do { } while (zip_window[++scanp] == zip_window[++matchp] && zip_window[++scanp] == zip_window[++matchp] && zip_window[++scanp] == zip_window[++matchp] && zip_window[++scanp] == zip_window[++matchp] && zip_window[++scanp] == zip_window[++matchp] && zip_window[++scanp] == zip_window[++matchp] && zip_window[++scanp] == zip_window[++matchp] && zip_window[++scanp] == zip_window[++matchp] && scanp < strendp); len = zip_MAX_MATCH - (strendp - scanp); scanp = strendp - zip_MAX_MATCH; if (len > best_len) {
						zip_match_start = cur_match; best_len = len; if (zip_FULL_SEARCH) { if (len >= zip_MAX_MATCH) break; } else { if (len >= zip_nice_match) break; }
						scan_end1 = zip_window[scanp + best_len - 1]; scan_end = zip_window[scanp + best_len];
					}
				} while ((cur_match = zip_prev[cur_match & zip_WMASK]) > limit && --chain_length != 0); return best_len;
		}
		var zip_fill_window = function () {
			var n, m; var more = zip_window_size - zip_lookahead - zip_strstart; if (more == -1) { more--; } else if (zip_strstart >= zip_WSIZE + zip_MAX_DIST) {
				for (n = 0; n < zip_WSIZE; n++)
					zip_window[n] = zip_window[n + zip_WSIZE]; zip_match_start -= zip_WSIZE; zip_strstart -= zip_WSIZE; zip_block_start -= zip_WSIZE; for (n = 0; n < zip_HASH_SIZE; n++) { m = zip_head1(n); zip_head2(n, m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL); }
				for (n = 0; n < zip_WSIZE; n++) { m = zip_prev[n]; zip_prev[n] = (m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL); }
				more += zip_WSIZE;
			}
			if (!zip_eofile) {
				n = zip_read_buff(zip_window, zip_strstart + zip_lookahead, more); if (n <= 0)
					zip_eofile = true; else
					zip_lookahead += n;
			}
		}
		var zip_deflate_fast = function () {
			while (zip_lookahead != 0 && zip_qhead == null) {
				var flush; zip_INSERT_STRING(); if (zip_hash_head != zip_NIL && zip_strstart - zip_hash_head <= zip_MAX_DIST) {
					zip_match_length = zip_longest_match(zip_hash_head); if (zip_match_length > zip_lookahead)
						zip_match_length = zip_lookahead;
				}
				if (zip_match_length >= zip_MIN_MATCH) { flush = zip_ct_tally(zip_strstart - zip_match_start, zip_match_length - zip_MIN_MATCH); zip_lookahead -= zip_match_length; if (zip_match_length <= zip_max_lazy_match) { zip_match_length--; do { zip_strstart++; zip_INSERT_STRING(); } while (--zip_match_length != 0); zip_strstart++; } else { zip_strstart += zip_match_length; zip_match_length = 0; zip_ins_h = zip_window[zip_strstart] & 0xff; zip_ins_h = ((zip_ins_h << zip_H_SHIFT) ^ (zip_window[zip_strstart + 1] & 0xff)) & zip_HASH_MASK; } } else { flush = zip_ct_tally(0, zip_window[zip_strstart] & 0xff); zip_lookahead--; zip_strstart++; }
				if (flush) { zip_flush_block(0); zip_block_start = zip_strstart; }
				while (zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile)
					zip_fill_window();
			}
		}
		var zip_deflate_better = function () {
			while (zip_lookahead != 0 && zip_qhead == null) {
				zip_INSERT_STRING(); zip_prev_length = zip_match_length; zip_prev_match = zip_match_start; zip_match_length = zip_MIN_MATCH - 1; if (zip_hash_head != zip_NIL && zip_prev_length < zip_max_lazy_match && zip_strstart - zip_hash_head <= zip_MAX_DIST) {
					zip_match_length = zip_longest_match(zip_hash_head); if (zip_match_length > zip_lookahead)
						zip_match_length = zip_lookahead; if (zip_match_length == zip_MIN_MATCH && zip_strstart - zip_match_start > zip_TOO_FAR) { zip_match_length--; }
				}
				if (zip_prev_length >= zip_MIN_MATCH && zip_match_length <= zip_prev_length) { var flush; flush = zip_ct_tally(zip_strstart - 1 - zip_prev_match, zip_prev_length - zip_MIN_MATCH); zip_lookahead -= zip_prev_length - 1; zip_prev_length -= 2; do { zip_strstart++; zip_INSERT_STRING(); } while (--zip_prev_length != 0); zip_match_available = 0; zip_match_length = zip_MIN_MATCH - 1; zip_strstart++; if (flush) { zip_flush_block(0); zip_block_start = zip_strstart; } } else if (zip_match_available != 0) {
					if (zip_ct_tally(0, zip_window[zip_strstart - 1] & 0xff)) { zip_flush_block(0); zip_block_start = zip_strstart; }
					zip_strstart++; zip_lookahead--;
				} else { zip_match_available = 1; zip_strstart++; zip_lookahead--; }
				while (zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile)
					zip_fill_window();
			}
		}
		var zip_init_deflate = function () {
			if (zip_eofile)
				return; zip_bi_buf = 0; zip_bi_valid = 0; zip_ct_init(); zip_lm_init(); zip_qhead = null; zip_outcnt = 0; zip_outoff = 0; if (zip_compr_level <= 3) { zip_prev_length = zip_MIN_MATCH - 1; zip_match_length = 0; }
			else { zip_match_length = zip_MIN_MATCH - 1; zip_match_available = 0; }
			zip_complete = false;
		}
		var zip_deflate_internal = function (buff, off, buff_size) {
			var n; if (!zip_initflag) { zip_init_deflate(); zip_initflag = true; if (zip_lookahead == 0) { zip_complete = true; return 0; } }
			if ((n = zip_qcopy(buff, off, buff_size)) == buff_size)
				return buff_size; if (zip_complete)
				return n; if (zip_compr_level <= 3)
				zip_deflate_fast(); else
				zip_deflate_better(); if (zip_lookahead == 0) {
					if (zip_match_available != 0)
						zip_ct_tally(0, zip_window[zip_strstart - 1] & 0xff); zip_flush_block(1); zip_complete = true;
				}
			return n + zip_qcopy(buff, n + off, buff_size - n);
		}
		var zip_qcopy = function (buff, off, buff_size) {
			var n, i, j; n = 0; while (zip_qhead != null && n < buff_size) {
				i = buff_size - n; if (i > zip_qhead.len)
					i = zip_qhead.len; for (j = 0; j < i; j++)
					buff[off + n + j] = zip_qhead.ptr[zip_qhead.off + j]; zip_qhead.off += i; zip_qhead.len -= i; n += i; if (zip_qhead.len == 0) { var p; p = zip_qhead; zip_qhead = zip_qhead.next; zip_reuse_queue(p); }
			}
			if (n == buff_size)
				return n; if (zip_outoff < zip_outcnt) {
					i = buff_size - n; if (i > zip_outcnt - zip_outoff)
						i = zip_outcnt - zip_outoff; for (j = 0; j < i; j++)
						buff[off + n + j] = zip_outbuf[zip_outoff + j]; zip_outoff += i; n += i; if (zip_outcnt == zip_outoff)
						zip_outcnt = zip_outoff = 0;
				}
			return n;
		}
		var zip_ct_init = function () {
			var n; var bits; var length; var code; var dist; if (zip_static_dtree[0].dl != 0) return; zip_l_desc.dyn_tree = zip_dyn_ltree; zip_l_desc.static_tree = zip_static_ltree; zip_l_desc.extra_bits = zip_extra_lbits; zip_l_desc.extra_base = zip_LITERALS + 1; zip_l_desc.elems = zip_L_CODES; zip_l_desc.max_length = zip_MAX_BITS; zip_l_desc.max_code = 0; zip_d_desc.dyn_tree = zip_dyn_dtree; zip_d_desc.static_tree = zip_static_dtree; zip_d_desc.extra_bits = zip_extra_dbits; zip_d_desc.extra_base = 0; zip_d_desc.elems = zip_D_CODES; zip_d_desc.max_length = zip_MAX_BITS; zip_d_desc.max_code = 0; zip_bl_desc.dyn_tree = zip_bl_tree; zip_bl_desc.static_tree = null; zip_bl_desc.extra_bits = zip_extra_blbits; zip_bl_desc.extra_base = 0; zip_bl_desc.elems = zip_BL_CODES; zip_bl_desc.max_length = zip_MAX_BL_BITS; zip_bl_desc.max_code = 0; length = 0; for (code = 0; code < zip_LENGTH_CODES - 1; code++) {
			zip_base_length[code] = length; for (n = 0; n < (1 << zip_extra_lbits[code]); n++)
				zip_length_code[length++] = code;
			}
			zip_length_code[length - 1] = code; dist = 0; for (code = 0; code < 16; code++) { zip_base_dist[code] = dist; for (n = 0; n < (1 << zip_extra_dbits[code]); n++) { zip_dist_code[dist++] = code; } }
			dist >>= 7; for (; code < zip_D_CODES; code++) {
			zip_base_dist[code] = dist << 7; for (n = 0; n < (1 << (zip_extra_dbits[code] - 7)); n++)
				zip_dist_code[256 + dist++] = code;
			}
			for (bits = 0; bits <= zip_MAX_BITS; bits++)
				zip_bl_count[bits] = 0; n = 0; while (n <= 143) { zip_static_ltree[n++].dl = 8; zip_bl_count[8]++; }
			while (n <= 255) { zip_static_ltree[n++].dl = 9; zip_bl_count[9]++; }
			while (n <= 279) { zip_static_ltree[n++].dl = 7; zip_bl_count[7]++; }
			while (n <= 287) { zip_static_ltree[n++].dl = 8; zip_bl_count[8]++; }
			zip_gen_codes(zip_static_ltree, zip_L_CODES + 1); for (n = 0; n < zip_D_CODES; n++) { zip_static_dtree[n].dl = 5; zip_static_dtree[n].fc = zip_bi_reverse(n, 5); }
			zip_init_block();
		}
		var zip_init_block = function () { var n; for (n = 0; n < zip_L_CODES; n++)zip_dyn_ltree[n].fc = 0; for (n = 0; n < zip_D_CODES; n++)zip_dyn_dtree[n].fc = 0; for (n = 0; n < zip_BL_CODES; n++)zip_bl_tree[n].fc = 0; zip_dyn_ltree[zip_END_BLOCK].fc = 1; zip_opt_len = zip_static_len = 0; zip_last_lit = zip_last_dist = zip_last_flags = 0; zip_flags = 0; zip_flag_bit = 1; }
		var zip_pqdownheap = function (tree, k) {
			var v = zip_heap[k]; var j = k << 1; while (j <= zip_heap_len) {
				if (j < zip_heap_len && zip_SMALLER(tree, zip_heap[j + 1], zip_heap[j]))
					j++; if (zip_SMALLER(tree, v, zip_heap[j]))
					break; zip_heap[k] = zip_heap[j]; k = j; j <<= 1;
			}
			zip_heap[k] = v;
		}
		var zip_gen_bitlen = function (desc) {
			var tree = desc.dyn_tree; var extra = desc.extra_bits; var base = desc.extra_base; var max_code = desc.max_code; var max_length = desc.max_length; var stree = desc.static_tree; var h; var n, m; var bits; var xbits; var f; var overflow = 0; for (bits = 0; bits <= zip_MAX_BITS; bits++)
				zip_bl_count[bits] = 0; tree[zip_heap[zip_heap_max]].dl = 0; for (h = zip_heap_max + 1; h < zip_HEAP_SIZE; h++) {
					n = zip_heap[h]; bits = tree[tree[n].dl].dl + 1; if (bits > max_length) { bits = max_length; overflow++; }
					tree[n].dl = bits; if (n > max_code)
						continue; zip_bl_count[bits]++; xbits = 0; if (n >= base)
						xbits = extra[n - base]; f = tree[n].fc; zip_opt_len += f * (bits + xbits); if (stree != null)
						zip_static_len += f * (stree[n].dl + xbits);
				}
			if (overflow == 0)
				return; do {
					bits = max_length - 1; while (zip_bl_count[bits] == 0)
						bits--; zip_bl_count[bits]--; zip_bl_count[bits + 1] += 2; zip_bl_count[max_length]--; overflow -= 2;
				} while (overflow > 0); for (bits = max_length; bits != 0; bits--) {
					n = zip_bl_count[bits]; while (n != 0) {
						m = zip_heap[--h]; if (m > max_code)
							continue; if (tree[m].dl != bits) { zip_opt_len += (bits - tree[m].dl) * tree[m].fc; tree[m].fc = bits; }
						n--;
					}
				}
		}
		var zip_gen_codes = function (tree, max_code) {
			var next_code = new Array(zip_MAX_BITS + 1); var code = 0; var bits; var n; for (bits = 1; bits <= zip_MAX_BITS; bits++) { code = ((code + zip_bl_count[bits - 1]) << 1); next_code[bits] = code; }
			for (n = 0; n <= max_code; n++) {
				var len = tree[n].dl; if (len == 0)
					continue; tree[n].fc = zip_bi_reverse(next_code[len]++, len);
			}
		}
		var zip_build_tree = function (desc) {
			var tree = desc.dyn_tree; var stree = desc.static_tree; var elems = desc.elems; var n, m; var max_code = -1; var node = elems; zip_heap_len = 0; zip_heap_max = zip_HEAP_SIZE; for (n = 0; n < elems; n++) {
				if (tree[n].fc != 0) { zip_heap[++zip_heap_len] = max_code = n; zip_depth[n] = 0; } else
					tree[n].dl = 0;
			}
			while (zip_heap_len < 2) {
				var xnew = zip_heap[++zip_heap_len] = (max_code < 2 ? ++max_code : 0); tree[xnew].fc = 1; zip_depth[xnew] = 0; zip_opt_len--; if (stree != null)
					zip_static_len -= stree[xnew].dl;
			}
			desc.max_code = max_code; for (n = zip_heap_len >> 1; n >= 1; n--)
				zip_pqdownheap(tree, n); do {
					n = zip_heap[zip_SMALLEST]; zip_heap[zip_SMALLEST] = zip_heap[zip_heap_len--]; zip_pqdownheap(tree, zip_SMALLEST); m = zip_heap[zip_SMALLEST]; zip_heap[--zip_heap_max] = n; zip_heap[--zip_heap_max] = m; tree[node].fc = tree[n].fc + tree[m].fc; if (zip_depth[n] > zip_depth[m] + 1)
						zip_depth[node] = zip_depth[n]; else
						zip_depth[node] = zip_depth[m] + 1; tree[n].dl = tree[m].dl = node; zip_heap[zip_SMALLEST] = node++; zip_pqdownheap(tree, zip_SMALLEST);
				} while (zip_heap_len >= 2); zip_heap[--zip_heap_max] = zip_heap[zip_SMALLEST]; zip_gen_bitlen(desc); zip_gen_codes(tree, max_code);
		}
		var zip_scan_tree = function (tree, max_code) {
			var n; var prevlen = -1; var curlen; var nextlen = tree[0].dl; var count = 0; var max_count = 7; var min_count = 4; if (nextlen == 0) { max_count = 138; min_count = 3; }
			tree[max_code + 1].dl = 0xffff; for (n = 0; n <= max_code; n++) {
				curlen = nextlen; nextlen = tree[n + 1].dl; if (++count < max_count && curlen == nextlen)
					continue; else if (count < min_count)
					zip_bl_tree[curlen].fc += count; else if (curlen != 0) {
						if (curlen != prevlen)
							zip_bl_tree[curlen].fc++; zip_bl_tree[zip_REP_3_6].fc++;
					} else if (count <= 10)
					zip_bl_tree[zip_REPZ_3_10].fc++; else
					zip_bl_tree[zip_REPZ_11_138].fc++; count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138; min_count = 3; } else if (curlen == nextlen) { max_count = 6; min_count = 3; } else { max_count = 7; min_count = 4; }
			}
		}
		var zip_send_tree = function (tree, max_code) {
			var n; var prevlen = -1; var curlen; var nextlen = tree[0].dl; var count = 0; var max_count = 7; var min_count = 4; if (nextlen == 0) { max_count = 138; min_count = 3; }
			for (n = 0; n <= max_code; n++) {
				curlen = nextlen; nextlen = tree[n + 1].dl; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { zip_SEND_CODE(curlen, zip_bl_tree); } while (--count != 0); } else if (curlen != 0) {
					if (curlen != prevlen) { zip_SEND_CODE(curlen, zip_bl_tree); count--; }
					zip_SEND_CODE(zip_REP_3_6, zip_bl_tree); zip_send_bits(count - 3, 2);
				} else if (count <= 10) { zip_SEND_CODE(zip_REPZ_3_10, zip_bl_tree); zip_send_bits(count - 3, 3); } else { zip_SEND_CODE(zip_REPZ_11_138, zip_bl_tree); zip_send_bits(count - 11, 7); }
				count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138; min_count = 3; } else if (curlen == nextlen) { max_count = 6; min_count = 3; } else { max_count = 7; min_count = 4; }
			}
		}
		var zip_build_bl_tree = function () {
			var max_blindex; zip_scan_tree(zip_dyn_ltree, zip_l_desc.max_code); zip_scan_tree(zip_dyn_dtree, zip_d_desc.max_code); zip_build_tree(zip_bl_desc); for (max_blindex = zip_BL_CODES - 1; max_blindex >= 3; max_blindex--) { if (zip_bl_tree[zip_bl_order[max_blindex]].dl != 0) break; }
			zip_opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; return max_blindex;
		}
		var zip_send_all_trees = function (lcodes, dcodes, blcodes) {
			var rank; zip_send_bits(lcodes - 257, 5); zip_send_bits(dcodes - 1, 5); zip_send_bits(blcodes - 4, 4); for (rank = 0; rank < blcodes; rank++) { zip_send_bits(zip_bl_tree[zip_bl_order[rank]].dl, 3); }
			zip_send_tree(zip_dyn_ltree, lcodes - 1); zip_send_tree(zip_dyn_dtree, dcodes - 1);
		}
		var zip_flush_block = function (eof) {
			var opt_lenb, static_lenb; var max_blindex; var stored_len; stored_len = zip_strstart - zip_block_start; zip_flag_buf[zip_last_flags] = zip_flags; zip_build_tree(zip_l_desc); zip_build_tree(zip_d_desc); max_blindex = zip_build_bl_tree(); opt_lenb = (zip_opt_len + 3 + 7) >> 3; static_lenb = (zip_static_len + 3 + 7) >> 3; if (static_lenb <= opt_lenb)
				opt_lenb = static_lenb; if (stored_len + 4 <= opt_lenb && zip_block_start >= 0) {
					var i; zip_send_bits((zip_STORED_BLOCK << 1) + eof, 3); zip_bi_windup(); zip_put_short(stored_len); zip_put_short(~stored_len); for (i = 0; i < stored_len; i++)
						zip_put_byte(zip_window[zip_block_start + i]);
				} else if (static_lenb == opt_lenb) { zip_send_bits((zip_STATIC_TREES << 1) + eof, 3); zip_compress_block(zip_static_ltree, zip_static_dtree); } else { zip_send_bits((zip_DYN_TREES << 1) + eof, 3); zip_send_all_trees(zip_l_desc.max_code + 1, zip_d_desc.max_code + 1, max_blindex + 1); zip_compress_block(zip_dyn_ltree, zip_dyn_dtree); }
			zip_init_block(); if (eof != 0)
				zip_bi_windup();
		}
		var zip_ct_tally = function (dist, lc) {
		zip_l_buf[zip_last_lit++] = lc; if (dist == 0) { zip_dyn_ltree[lc].fc++; } else { dist--; zip_dyn_ltree[zip_length_code[lc] + zip_LITERALS + 1].fc++; zip_dyn_dtree[zip_D_CODE(dist)].fc++; zip_d_buf[zip_last_dist++] = dist; zip_flags |= zip_flag_bit; }
			zip_flag_bit <<= 1; if ((zip_last_lit & 7) == 0) { zip_flag_buf[zip_last_flags++] = zip_flags; zip_flags = 0; zip_flag_bit = 1; }
			if (zip_compr_level > 2 && (zip_last_lit & 0xfff) == 0) {
				var out_length = zip_last_lit * 8; var in_length = zip_strstart - zip_block_start; var dcode; for (dcode = 0; dcode < zip_D_CODES; dcode++) { out_length += zip_dyn_dtree[dcode].fc * (5 + zip_extra_dbits[dcode]); }
				out_length >>= 3; if (zip_last_dist < parseInt(zip_last_lit / 2) && out_length < parseInt(in_length / 2))
					return true;
			}
			return (zip_last_lit == zip_LIT_BUFSIZE - 1 || zip_last_dist == zip_DIST_BUFSIZE);
		}
		var zip_compress_block = function (ltree, dtree) {
			var dist; var lc; var lx = 0; var dx = 0; var fx = 0; var flag = 0; var code; var extra; if (zip_last_lit != 0) do {
				if ((lx & 7) == 0)
					flag = zip_flag_buf[fx++]; lc = zip_l_buf[lx++] & 0xff; if ((flag & 1) == 0) { zip_SEND_CODE(lc, ltree); } else {
						code = zip_length_code[lc]; zip_SEND_CODE(code + zip_LITERALS + 1, ltree); extra = zip_extra_lbits[code]; if (extra != 0) { lc -= zip_base_length[code]; zip_send_bits(lc, extra); }
						dist = zip_d_buf[dx++]; code = zip_D_CODE(dist); zip_SEND_CODE(code, dtree); extra = zip_extra_dbits[code]; if (extra != 0) { dist -= zip_base_dist[code]; zip_send_bits(dist, extra); }
					}
				flag >>= 1;
			} while (lx < zip_last_lit); zip_SEND_CODE(zip_END_BLOCK, ltree);
		}
		var zip_Buf_size = 16; var zip_send_bits = function (value, length) { if (zip_bi_valid > zip_Buf_size - length) { zip_bi_buf |= (value << zip_bi_valid); zip_put_short(zip_bi_buf); zip_bi_buf = (value >> (zip_Buf_size - zip_bi_valid)); zip_bi_valid += length - zip_Buf_size; } else { zip_bi_buf |= value << zip_bi_valid; zip_bi_valid += length; } }
		var zip_bi_reverse = function (code, len) { var res = 0; do { res |= code & 1; code >>= 1; res <<= 1; } while (--len > 0); return res >> 1; }
		var zip_bi_windup = function () {
			if (zip_bi_valid > 8) { zip_put_short(zip_bi_buf); } else if (zip_bi_valid > 0) { zip_put_byte(zip_bi_buf); }
			zip_bi_buf = 0; zip_bi_valid = 0;
		}
		var zip_qoutbuf = function () {
			if (zip_outcnt != 0) {
				var q, i; q = zip_new_queue(); if (zip_qhead == null)
					zip_qhead = zip_qtail = q; else
					zip_qtail = zip_qtail.next = q; q.len = zip_outcnt - zip_outoff; for (i = 0; i < q.len; i++)
					q.ptr[i] = zip_outbuf[zip_outoff + i]; zip_outcnt = zip_outoff = 0;
			}
		}
		var zip_deflate = function (str, level) {
			var i, j; zip_deflate_data = str; zip_deflate_pos = 0; if (typeof level == "undefined")
				level = zip_DEFAULT_LEVEL; zip_deflate_start(level); var buff = new Array(1024); var aout = []; while ((i = zip_deflate_internal(buff, 0, buff.length)) > 0) {
					var cbuf = new Array(i); for (j = 0; j < i; j++) { cbuf[j] = String.fromCharCode(buff[j]); }
					aout[aout.length] = cbuf.join("");
				}
			zip_deflate_data = null; return aout.join("");
		}
		if (!JSZip.compressions["DEFLATE"]) { JSZip.compressions["DEFLATE"] = { magic: "\x08\x00", compress: zip_deflate } } else { JSZip.compressions["DEFLATE"].compress = zip_deflate; }
	})();


	if (!JSZip) { throw "JSZip not defined"; }
	(function () {
		var zip_fixed_bd; var zip_WSIZE = 32768; var zip_STORED_BLOCK = 0; var zip_STATIC_TREES = 1; var zip_DYN_TREES = 2; var zip_lbits = 9; var zip_dbits = 6; var zip_INBUFSIZ = 32768; var zip_INBUF_EXTRA = 64; var zip_slide; var zip_wp; var zip_fixed_tl = null; var zip_fixed_td; var zip_fixed_bl, fixed_bd; var zip_bit_buf; var zip_bit_len; var zip_method; var zip_eof; var zip_copy_leng; var zip_copy_dist; var zip_tl, zip_td; var zip_bl, zip_bd; var zip_inflate_data; var zip_inflate_pos; var zip_MASK_BITS = new Array(0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff); var zip_cplens = new Array(3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0); var zip_cplext = new Array(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99); var zip_cpdist = new Array(1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577); var zip_cpdext = new Array(0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13); var zip_border = new Array(16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15); function zip_HuftList() { this.next = null; this.list = null; }
		function zip_HuftNode() { this.e = 0; this.b = 0; this.n = 0; this.t = null; }
		function zip_HuftBuild(b, n, s, d, e, mm) {
		this.BMAX = 16; this.N_MAX = 288; this.status = 0; this.root = null; this.m = 0; {
			var a; var c = new Array(this.BMAX + 1); var el; var f; var g; var h; var i; var j; var k; var lx = new Array(this.BMAX + 1); var p; var pidx; var q; var r = new zip_HuftNode(); var u = new Array(this.BMAX); var v = new Array(this.N_MAX); var w; var x = new Array(this.BMAX + 1); var xp; var y; var z; var o; var tail; tail = this.root = null; for (i = 0; i < c.length; i++)
				c[i] = 0; for (i = 0; i < lx.length; i++)
				lx[i] = 0; for (i = 0; i < u.length; i++)
				u[i] = null; for (i = 0; i < v.length; i++)
				v[i] = 0; for (i = 0; i < x.length; i++)
				x[i] = 0; el = n > 256 ? b[256] : this.BMAX; p = b; pidx = 0; i = n; do { c[p[pidx]]++; pidx++; } while (--i > 0); if (c[0] == n) { this.root = null; this.m = 0; this.status = 0; return; }
			for (j = 1; j <= this.BMAX; j++)
				if (c[j] != 0)
					break; k = j; if (mm < j)
				mm = j; for (i = this.BMAX; i != 0; i--)
				if (c[i] != 0)
					break; g = i; if (mm > i)
				mm = i; for (y = 1 << j; j < i; j++ , y <<= 1)
				if ((y -= c[j]) < 0) { this.status = 2; this.m = mm; return; }
			if ((y -= c[i]) < 0) { this.status = 2; this.m = mm; return; }
			c[i] += y; x[1] = j = 0; p = c; pidx = 1; xp = 2; while (--i > 0)
				x[xp++] = (j += p[pidx++]); p = b; pidx = 0; i = 0; do {
					if ((j = p[pidx++]) != 0)
						v[x[j]++] = i;
				} while (++i < n); n = x[g]; x[0] = i = 0; p = v; pidx = 0; h = -1; w = lx[0] = 0; q = null; z = 0; for (; k <= g; k++) {
					a = c[k]; while (a-- > 0) {
						while (k > w + lx[1 + h]) {
							w += lx[1 + h]; h++; z = (z = g - w) > mm ? mm : z; if ((f = 1 << (j = k - w)) > a + 1) {
								f -= a + 1; xp = k; while (++j < z) {
									if ((f <<= 1) <= c[++xp])
										break; f -= c[xp];
								}
							}
							if (w + j > el && w < el)
								j = el - w; z = 1 << j; lx[1 + h] = j; q = new Array(z); for (o = 0; o < z; o++) { q[o] = new zip_HuftNode(); }
							if (tail == null)
								tail = this.root = new zip_HuftList(); else
								tail = tail.next = new zip_HuftList(); tail.next = null; tail.list = q; u[h] = q; if (h > 0) { x[h] = i; r.b = lx[h]; r.e = 16 + j; r.t = q; j = (i & ((1 << w) - 1)) >> (w - lx[h]); u[h - 1][j].e = r.e; u[h - 1][j].b = r.b; u[h - 1][j].n = r.n; u[h - 1][j].t = r.t; }
						}
						r.b = k - w; if (pidx >= n)
							r.e = 99; else if (p[pidx] < s) { r.e = (p[pidx] < 256 ? 16 : 15); r.n = p[pidx++]; } else { r.e = e[p[pidx] - s]; r.n = d[p[pidx++] - s]; }
						f = 1 << (k - w); for (j = i >> w; j < z; j += f) { q[j].e = r.e; q[j].b = r.b; q[j].n = r.n; q[j].t = r.t; }
						for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
							i ^= j; i ^= j; while ((i & ((1 << w) - 1)) != x[h]) { w -= lx[h]; h--; }
					}
				}
			this.m = lx[1]; this.status = ((y != 0 && g != 1) ? 1 : 0);
		}
		}
		function zip_GET_BYTE() {
			if (zip_inflate_data.length == zip_inflate_pos)
				return -1; return zip_inflate_data.charCodeAt(zip_inflate_pos++) & 0xff;
		}
		function zip_NEEDBITS(n) { while (zip_bit_len < n) { zip_bit_buf |= zip_GET_BYTE() << zip_bit_len; zip_bit_len += 8; } }
		function zip_GETBITS(n) { return zip_bit_buf & zip_MASK_BITS[n]; }
		function zip_DUMPBITS(n) { zip_bit_buf >>= n; zip_bit_len -= n; }
		function zip_inflate_codes(buff, off, size) {
			var e; var t; var n; if (size == 0)
				return 0; n = 0; for (; ;) {
					zip_NEEDBITS(zip_bl); t = zip_tl.list[zip_GETBITS(zip_bl)]; e = t.e; while (e > 16) {
						if (e == 99)
							return -1; zip_DUMPBITS(t.b); e -= 16; zip_NEEDBITS(e); t = t.t[zip_GETBITS(e)]; e = t.e;
					}
					zip_DUMPBITS(t.b); if (e == 16) {
						zip_wp &= zip_WSIZE - 1; buff[off + n++] = zip_slide[zip_wp++] = t.n; if (n == size)
							return size; continue;
					}
					if (e == 15)
						break; zip_NEEDBITS(e); zip_copy_leng = t.n + zip_GETBITS(e); zip_DUMPBITS(e); zip_NEEDBITS(zip_bd); t = zip_td.list[zip_GETBITS(zip_bd)]; e = t.e; while (e > 16) {
							if (e == 99)
								return -1; zip_DUMPBITS(t.b); e -= 16; zip_NEEDBITS(e); t = t.t[zip_GETBITS(e)]; e = t.e;
						}
					zip_DUMPBITS(t.b); zip_NEEDBITS(e); zip_copy_dist = zip_wp - t.n - zip_GETBITS(e); zip_DUMPBITS(e); while (zip_copy_leng > 0 && n < size) { zip_copy_leng--; zip_copy_dist &= zip_WSIZE - 1; zip_wp &= zip_WSIZE - 1; buff[off + n++] = zip_slide[zip_wp++] = zip_slide[zip_copy_dist++]; }
					if (n == size)
						return size;
				}
			zip_method = -1; return n;
		}
		function zip_inflate_stored(buff, off, size) {
			var n; n = zip_bit_len & 7; zip_DUMPBITS(n); zip_NEEDBITS(16); n = zip_GETBITS(16); zip_DUMPBITS(16); zip_NEEDBITS(16); if (n != ((~zip_bit_buf) & 0xffff))
				return -1; zip_DUMPBITS(16); zip_copy_leng = n; n = 0; while (zip_copy_leng > 0 && n < size) { zip_copy_leng--; zip_wp &= zip_WSIZE - 1; zip_NEEDBITS(8); buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8); zip_DUMPBITS(8); }
			if (zip_copy_leng == 0)
				zip_method = -1; return n;
		}
		function zip_inflate_fixed(buff, off, size) {
			if (zip_fixed_tl == null) {
				var i; var l = new Array(288); var h; for (i = 0; i < 144; i++)
					l[i] = 8; for (; i < 256; i++)
					l[i] = 9; for (; i < 280; i++)
					l[i] = 7; for (; i < 288; i++)
					l[i] = 8; zip_fixed_bl = 7; h = new zip_HuftBuild(l, 288, 257, zip_cplens, zip_cplext, zip_fixed_bl); if (h.status != 0) { alert("HufBuild error: " + h.status); return -1; }
				zip_fixed_tl = h.root; zip_fixed_bl = h.m; for (i = 0; i < 30; i++)
					l[i] = 5; zip_fixed_bd = 5; h = new zip_HuftBuild(l, 30, 0, zip_cpdist, zip_cpdext, zip_fixed_bd); if (h.status > 1) { zip_fixed_tl = null; alert("HufBuild error: " + h.status); return -1; }
				zip_fixed_td = h.root; zip_fixed_bd = h.m;
			}
			zip_tl = zip_fixed_tl; zip_td = zip_fixed_td; zip_bl = zip_fixed_bl; zip_bd = zip_fixed_bd; return zip_inflate_codes(buff, off, size);
		}
		function zip_inflate_dynamic(buff, off, size) {
			var i; var j; var l; var n; var t; var nb; var nl; var nd; var ll = new Array(286 + 30); var h; for (i = 0; i < ll.length; i++)
				ll[i] = 0; zip_NEEDBITS(5); nl = 257 + zip_GETBITS(5); zip_DUMPBITS(5); zip_NEEDBITS(5); nd = 1 + zip_GETBITS(5); zip_DUMPBITS(5); zip_NEEDBITS(4); nb = 4 + zip_GETBITS(4); zip_DUMPBITS(4); if (nl > 286 || nd > 30)
				return -1; for (j = 0; j < nb; j++) { zip_NEEDBITS(3); ll[zip_border[j]] = zip_GETBITS(3); zip_DUMPBITS(3); }
			for (; j < 19; j++)
				ll[zip_border[j]] = 0; zip_bl = 7; h = new zip_HuftBuild(ll, 19, 19, null, null, zip_bl); if (h.status != 0)
				return -1; zip_tl = h.root; zip_bl = h.m; n = nl + nd; i = l = 0; while (i < n) {
					zip_NEEDBITS(zip_bl); t = zip_tl.list[zip_GETBITS(zip_bl)]; j = t.b; zip_DUMPBITS(j); j = t.n; if (j < 16)
						ll[i++] = l = j; else if (j == 16) {
							zip_NEEDBITS(2); j = 3 + zip_GETBITS(2); zip_DUMPBITS(2); if (i + j > n)
								return -1; while (j-- > 0)
								ll[i++] = l;
						} else if (j == 17) {
							zip_NEEDBITS(3); j = 3 + zip_GETBITS(3); zip_DUMPBITS(3); if (i + j > n)
								return -1; while (j-- > 0)
								ll[i++] = 0; l = 0;
						} else {
							zip_NEEDBITS(7); j = 11 + zip_GETBITS(7); zip_DUMPBITS(7); if (i + j > n)
								return -1; while (j-- > 0)
							ll[i++] = 0; l = 0;
					}
				}
			zip_bl = zip_lbits; h = new zip_HuftBuild(ll, nl, 257, zip_cplens, zip_cplext, zip_bl); if (zip_bl == 0)
				h.status = 1; if (h.status != 0) {/*if(h.status==1);*/return -1; }
			zip_tl = h.root; zip_bl = h.m; for (i = 0; i < nd; i++)
				ll[i] = ll[i + nl]; zip_bd = zip_dbits; h = new zip_HuftBuild(ll, nd, 0, zip_cpdist, zip_cpdext, zip_bd); zip_td = h.root; zip_bd = h.m; if (zip_bd == 0 && nl > 257) { return -1; }
			//if(h.status==1){;}
			if (h.status != 0)
				return -1; return zip_inflate_codes(buff, off, size);
		}
		function zip_inflate_start() {
			var i; if (zip_slide == null)
				zip_slide = new Array(2 * zip_WSIZE); zip_wp = 0; zip_bit_buf = 0; zip_bit_len = 0; zip_method = -1; zip_eof = false; zip_copy_leng = zip_copy_dist = 0; zip_tl = null;
		}
		function zip_inflate_internal(buff, off, size) {
			var n, i; n = 0; while (n < size) {
				if (zip_eof && zip_method == -1)
					return n; if (zip_copy_leng > 0) {
						if (zip_method != zip_STORED_BLOCK) { while (zip_copy_leng > 0 && n < size) { zip_copy_leng--; zip_copy_dist &= zip_WSIZE - 1; zip_wp &= zip_WSIZE - 1; buff[off + n++] = zip_slide[zip_wp++] = zip_slide[zip_copy_dist++]; } } else {
							while (zip_copy_leng > 0 && n < size) { zip_copy_leng--; zip_wp &= zip_WSIZE - 1; zip_NEEDBITS(8); buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8); zip_DUMPBITS(8); }
							if (zip_copy_leng == 0)
								zip_method = -1;
						}
						if (n == size)
							return n;
					}
				if (zip_method == -1) {
					if (zip_eof)
						break; zip_NEEDBITS(1); if (zip_GETBITS(1) != 0)
						zip_eof = true; zip_DUMPBITS(1); zip_NEEDBITS(2); zip_method = zip_GETBITS(2); zip_DUMPBITS(2); zip_tl = null; zip_copy_leng = 0;
				}
				switch (zip_method) {
					case 0: i = zip_inflate_stored(buff, off + n, size - n); break; case 1: if (zip_tl != null)
						i = zip_inflate_codes(buff, off + n, size - n); else
						i = zip_inflate_fixed(buff, off + n, size - n); break; case 2: if (zip_tl != null)
							i = zip_inflate_codes(buff, off + n, size - n); else
							i = zip_inflate_dynamic(buff, off + n, size - n); break; default: i = -1; break;
				}
				if (i == -1) {
					if (zip_eof)
						return 0; return -1;
				}
				n += i;
			}
			return n;
		}
		function zip_inflate(str) {
			var out, buff; var i, j; zip_inflate_start(); zip_inflate_data = str; zip_inflate_pos = 0; buff = new Array(1024); out = ""; while ((i = zip_inflate_internal(buff, 0, buff.length)) > 0) {
				for (j = 0; j < i; j++)
					out += String.fromCharCode(buff[j]);
			}
			zip_inflate_data = null; return out;
		}
		if (!JSZip.compressions["DEFLATE"]) { JSZip.compressions["DEFLATE"] = { magic: "\x08\x00", uncompress: zip_inflate } } else { JSZip.compressions["DEFLATE"].uncompress = zip_inflate; }
	})();



	(function () {
		var pretty = function (str) {
			var res = '', code, i; for (i = 0; i < str.length; i++) { code = str.charCodeAt(i); res += '\\x' + (code < 10 ? "0" : "") + code.toString(16); }
			return res;
		}; var findCompression = function (compressionMethod) {
			for (var method in JSZip.compressions) {
				if (JSZip.compressions[method].magic === compressionMethod) { return JSZip.compressions[method]; }
			}
			return null;
		}; function StreamReader(stream) { this.stream = stream; this.index = 0; }
		StreamReader.prototype = {
			checkOffset: function (offset) { this.checkIndex(this.index + offset); }, checkIndex: function (newIndex) {
				if (this.stream.length < newIndex || newIndex < 0) {
					throw new Error("End of stream reached (stream length = " +
						this.stream.length + ", asked index = " +
						(newIndex) + "). Corrupted zip ?");
				}
			}, setIndex: function (newIndex) { this.checkIndex(newIndex); this.index = newIndex; }, eof: function () { return this.index >= this.stream.length; }, byteAt: function (i) { return this.stream.charCodeAt(i) & 0xff; }, readByte: function () { this.checkOffset(1); return this.byteAt(1 + this.index++); }, readInt: function (size) {
				var result = 0, i; this.checkOffset(size); for (i = size - 1; i >= 0; i--) { result = (result << 8) + this.byteAt(this.index + i); }
				this.index += size; return result;
			}, readString: function (size) {
				var result = "", i, code; this.checkOffset(size); for (i = 0; i < size; i++) { code = this.byteAt(this.index + i); result += String.fromCharCode(code); }
				this.index += size; return result;
			}, readDate: function () { var dostime = this.readInt(4); return new Date(((dostime >> 25) & 0x7f) + 1980, ((dostime >> 21) & 0x0f) - 1, (dostime >> 16) & 0x1f, (dostime >> 11) & 0x1f, (dostime >> 5) & 0x3f, (dostime & 0x1f) << 1); }
		}; function ZipEntry(options, loadOptions) { this.options = options; this.loadOptions = loadOptions; }
		ZipEntry.prototype = {
			isEncrypted: function () { return (this.bitFlag & 0x0001) === 0x0001; }, hasDataDescriptor: function () { return (this.bitFlag & 0x0008) === 0x0008; }, useUTF8: function () { return (this.bitFlag & 0x0800) === 0x0800; }, isZIP64: function () { return this.options.zip64; }, readLocalPartHeader: function (reader) {
			this.versionNeeded = reader.readInt(2); this.bitFlag = reader.readInt(2); this.compressionMethod = reader.readString(2); this.date = reader.readDate(); this.crc32 = reader.readInt(4); this.compressedSize = reader.readInt(4); this.uncompressedSize = reader.readInt(4); this.fileNameLength = reader.readInt(2); this.extraFieldsLength = reader.readInt(2); if (this.isEncrypted()) { throw new Error("Encrypted zip are not supported"); }
			}, readLocalPart: function (reader) {
				var compression; this.readLocalPartHeader(reader); this.fileName = reader.readString(this.fileNameLength); this.readExtraFields(reader); if (!this.hasDataDescriptor()) { this.compressedFileData = reader.readString(this.compressedSize); }
				else {
				this.compressedFileData = this.findDataUntilDataDescriptor(reader); this.crc32 = reader.readInt(4); this.compressedSize = reader.readInt(this.isZIP64() ? 8 : 4); this.uncompressedSize = reader.readInt(this.isZIP64() ? 8 : 4); if (this.compressedFileData.length !== this.compressedSize) { throw new Error("Bug : data descriptor incorrectly read (size mismatch)"); }
				}
				this.uncompressedFileData = null; compression = findCompression(this.compressionMethod); if (compression === null) { throw new Error("Corrupted zip : compression " + pretty(this.compressionMethod) + " unknown (inner file : " + this.fileName + ")"); }
				this.uncompressedFileData = compression.uncompress(this.compressedFileData); if (this.loadOptions.checkCRC32 && JSZip.prototype.crc32(this.uncompressedFileData) !== this.crc32) { throw new Error("Corrupted zip : CRC32 mismatch"); }
				if (this.useUTF8()) { this.fileName = JSZip.prototype.utf8decode(this.fileName); }
			}, findDataUntilDataDescriptor: function (reader) {
				var data = "", buffer = reader.readString(4), aByte; while (buffer !== JSZip.signature.DATA_DESCRIPTOR) { aByte = reader.readString(1); data += buffer.slice(0, 1); buffer = (buffer + aByte).slice(-4); }
				return data;
			}, readCentralPart: function (reader) {
			this.versionMadeBy = reader.readString(2); this.readLocalPartHeader(reader); this.fileCommentLength = reader.readInt(2); this.diskNumberStart = reader.readInt(2); this.internalFileAttributes = reader.readInt(2); this.externalFileAttributes = reader.readInt(4); this.localHeaderOffset = reader.readInt(4); this.fileName = reader.readString(this.fileNameLength); this.readExtraFields(reader); this.fileComment = reader.readString(this.fileCommentLength); if (this.useUTF8()) { this.fileName = JSZip.prototype.utf8decode(this.fileName); this.fileComment = JSZip.prototype.utf8decode(this.fileComment); }
				this.dir = this.externalFileAttributes & 0x00000010 ? true : false;
			}, parseZIP64ExtraField: function (reader) {
				var extraReader = new StreamReader(this.extraFields[0x0001].value); if (this.uncompressedSize === -1) { this.uncompressedSize = extraReader.readInt(8); }
				if (this.compressedSize === -1) { this.compressedSize = extraReader.readInt(8); }
				if (this.localHeaderOffset === -1) { this.localHeaderOffset = extraReader.readInt(8); }
				if (this.diskNumberStart === -1) { this.diskNumberStart = extraReader.readInt(4); }
			}, readExtraFields: function (reader) {
				var start = reader.index, extraFieldId, extraFieldLength, extraFieldValue; this.extraFields = this.extraFields || {}; while (reader.index < start + this.extraFieldsLength) { extraFieldId = reader.readInt(2); extraFieldLength = reader.readInt(2); extraFieldValue = reader.readString(extraFieldLength); this.extraFields[extraFieldId] = { id: extraFieldId, length: extraFieldLength, value: extraFieldValue }; }
				if (this.isZIP64() && this.extraFields[0x0001]) { this.parseZIP64ExtraField(reader); }
			}
		}; function ZipEntries(data, loadOptions) { this.files = []; this.loadOptions = loadOptions; if (data) this.load(data); }
		ZipEntries.prototype = {
			checkSignature: function (expectedSignature) {
				var signature = this.reader.readString(4); if (signature !== expectedSignature) { throw new Error("Corrupted zip or bug : unexpected signature " + "(" + pretty(signature) + ", expected " + pretty(expectedSignature) + ")"); }
			}, readBlockEndOfCentral: function () { this.diskNumber = this.reader.readInt(2); this.diskWithCentralDirStart = this.reader.readInt(2); this.centralDirRecordsOnThisDisk = this.reader.readInt(2); this.centralDirRecords = this.reader.readInt(2); this.centralDirSize = this.reader.readInt(4); this.centralDirOffset = this.reader.readInt(4); this.zipCommentLength = this.reader.readInt(2); this.zipComment = this.reader.readString(this.zipCommentLength); }, readBlockZip64EndOfCentral: function () {
			this.zip64EndOfCentralSize = this.reader.readInt(8); this.versionMadeBy = this.reader.readString(2); this.versionNeeded = this.reader.readInt(2); this.diskNumber = this.reader.readInt(4); this.diskWithCentralDirStart = this.reader.readInt(4); this.centralDirRecordsOnThisDisk = this.reader.readInt(8); this.centralDirRecords = this.reader.readInt(8); this.centralDirSize = this.reader.readInt(8); this.centralDirOffset = this.reader.readInt(8); this.zip64ExtensibleData = {}; var extraDataSize = this.zip64EndOfCentralSize - 44, index = 0, extraFieldId, extraFieldLength, extraFieldValue; while (index < extraDataSize) { extraFieldId = this.reader.readInt(2); extraFieldLength = this.reader.readInt(4); extraFieldValue = this.reader.readString(extraFieldLength); this.zip64ExtensibleData[extraFieldId] = { id: extraFieldId, length: extraFieldLength, value: extraFieldValue }; }
			}, readBlockZip64EndOfCentralLocator: function () {
			this.diskWithZip64CentralDirStart = this.reader.readInt(4); this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); this.disksCount = this.reader.readInt(4); if (this.disksCount > 1) { throw new Error("Multi-volumes zip are not supported"); }
			}, readLocalFiles: function () {
				var i, file; for (i = 0; i < this.files.length; i++) { file = this.files[i]; this.reader.setIndex(file.localHeaderOffset); this.checkSignature(JSZip.signature.LOCAL_FILE_HEADER); file.readLocalPart(this.reader); }
			}, readCentralDir: function () {
				var file; this.reader.setIndex(this.centralDirOffset); while (this.reader.readString(4) === JSZip.signature.CENTRAL_FILE_HEADER) { file = new ZipEntry({ zip64: this.zip64 }, this.loadOptions); file.readCentralPart(this.reader); this.files.push(file); }
			}, readEndOfCentral: function () {
				var offset = this.reader.stream.lastIndexOf(JSZip.signature.ZIP64_CENTRAL_DIRECTORY_LOCATOR); if (offset === -1) {
				this.zip64 = false; offset = this.reader.stream.lastIndexOf(JSZip.signature.CENTRAL_DIRECTORY_END); if (offset === -1) { throw new Error("Corrupted zip : can't find end of central directory"); }
					this.reader.setIndex(offset); this.checkSignature(JSZip.signature.CENTRAL_DIRECTORY_END); this.readBlockEndOfCentral();
				}
				else { this.zip64 = true; this.reader.setIndex(offset); this.checkSignature(JSZip.signature.ZIP64_CENTRAL_DIRECTORY_LOCATOR); this.readBlockZip64EndOfCentralLocator(); this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); this.checkSignature(JSZip.signature.ZIP64_CENTRAL_DIRECTORY_END); this.readBlockZip64EndOfCentral(); }
			}, load: function (data) { this.reader = new StreamReader(data); this.readEndOfCentral(); this.readCentralDir(); this.readLocalFiles(); }
		}; JSZip.prototype.load = function (data, options) {
			var files, zipEntries, i, input; options = options || {}; if (options.base64) { data = JSZipBase64.decode(data); }
			zipEntries = new ZipEntries(data, options); files = zipEntries.files; for (i in files) { input = files[i]; this.file(input.fileName, input.uncompressedFileData, { binary: true, date: input.date, dir: input.dir }); }
			return this;
		};
	})();


	/*
	var JSZip = null
	if (typeof require === 'function') {
		JSZip = require('node-zip');
	}*/

	//----------------------------------------------------------
	// Copyright (C) Microsoft Corporation. All rights reserved.
	// Released under the Microsoft Office Extensible File License
	// https://raw.github.com/stephen-hardy/xlsx.js/master/LICENSE.txt
	//----------------------------------------------------------
	function xlsx(file) {
		'use strict'; // v2.3.0

		var defaultFontName = 'Calibri';
		var defaultFontSize = 11;
		var defaultFontColor = "000000";

		var result, zip = new JSZip(), zipTime, processTime, s, f, i, j, k, l, t, w, sharedStrings, styles, index, data, val, style, borders, border, borderIndex, fonts, font, fontIndex,
			docProps, xl, xlWorksheets, worksheet, contentTypes = [[], []], props = [], xlRels = [], worksheets = [], id, columns, cols, colWidth, cell, row, merges, merged,
			numFmts = ['General', '0', '0.00', '#,##0', '#,##0.00', , , , , '0%', '0.00%', '0.00E+00', '# ?/?', '# ??/??', 'mm-dd-yy', 'd-mmm-yy', 'd-mmm', 'mmm-yy', 'h:mm AM/PM', 'h:mm:ss AM/PM',
				'h:mm', 'h:mm:ss', 'm/d/yy h:mm', , , , , , , , , , , , , , , '#,##0 ;(#,##0)', '#,##0 ;[Red](#,##0)', '#,##0.00;(#,##0.00)', '#,##0.00;[Red](#,##0.00)', , , , , 'mm:ss', '[h]:mm:ss', 'mmss.0', '##0.0E+0', '@'],
			alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

		function numAlpha(i) {
			var t = Math.floor(i / 26) - 1; return (t > -1 ? numAlpha(t) : '') + alphabet.charAt(i % 26);
		}

		function alphaNum(s) {
			var t = 0; if (s.length === 2) { t = alphaNum(s.charAt(0)) + 1; } return t * 26 + alphabet.indexOf(s.substr(-1));
		}

		function convertDate(input) {
			return typeof input === 'object' ? ((input - new Date(1900, 0, 0)) / 86400000) + 1 : new Date(+new Date(1900, 0, 0) + (input - 1) * 86400000);
		}

		function typeOf(obj) {
			return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
		}

		function getAttr(s, n) {
			s = s.substr(s.indexOf(n + '="') + n.length + 2); return s.substring(0, s.indexOf('"'));
		}

		function escapeXML(s) {
			return (s || '').replace(/&(?!(lt|gt))/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;');
		} // see http://www.w3.org/TR/xml/#syntax

		function unescapeXML(s) {
			return (s || '').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&#x27;/g, '\'');
		}

		if (file.pivot) {
			processTime = Date.now();

			//file _rels/.rels
			zip.folder('_rels').file('.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
				+ '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>'
				+ '<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>'
				+ '<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>'
				+ '</Relationships>');

			//files folder docProps
			docProps = zip.folder('docProps');
			docProps.file('core.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
				+ '<dc:creator>gonzalo</dc:creator>'
				+ '<dcterms:created xsi:type="dcterms:W3CDTF">2010-12-23T01:32:21Z</dcterms:created>'
				+ '<cp:lastModifiedBy>xperTools</cp:lastModifiedBy>'
				+ '<dcterms:modified xsi:type="dcterms:W3CDTF">2010-02-23T01:32:21Z</dcterms:modified>'
				+ '</cp:coreProperties>')
			docProps.file('app.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">'
				+ '<DocSecurity>0</DocSecurity>'
				+ '<ScaleCrop>false</ScaleCrop>'
				+ '<HeadingPairs>'
				+ '<vt:vector size="2" baseType="variant">'
				+ '<vt:variant>'
				+ '<vt:lpstr>Hojas de cálculo</vt:lpstr>'
				+ '</vt:variant>'
				+ '<vt:variant>'
				+ '<vt:i4>2</vt:i4>'
				+ '</vt:variant>'
				+ '</vt:vector>'
				+ '</HeadingPairs>'
				+ '<TitlesOfParts>'
				+ '<vt:vector size="2" baseType="lpstr">'
				+ '<vt:lpstr>PivotTable</vt:lpstr>'
				+ '<vt:lpstr>SourceData</vt:lpstr>'
				+ '</vt:vector>'
				+ '</TitlesOfParts>'
				+ '<LinksUpToDate>false</LinksUpToDate>'
				+ '<SharedDoc>false</SharedDoc>'
				+ '<HyperlinksChanged>false</HyperlinksChanged>'
				+ '<AppVersion>12.0000</AppVersion>'
				+ '</Properties>');


			// [Content_Types].xml
			zip.file('[Content_Types].xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'
				+ '<Default Extension="xml" ContentType="application/xml"/>'
				+ '<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>'
				+ '<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>'
				+ '<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>'
				+ '<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>'
				+ '<Override PartName="/xl/worksheets/sheet2.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>'
				+ '<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>'
				+ '<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>'
				+ '<Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>'
				+ '<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>'
				+ '<Override PartName="/xl/pivotTables/pivotTable1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"/>'
				+ '<Override PartName="/xl/pivotCache/pivotCacheDefinition1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"/>'
				+ '<Override PartName="/xl/pivotCache/pivotCacheRecords1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"/>'
				+ '</Types>');


			//xl folder	
			xl = zip.folder('xl');

			// xl/_rels/workbook.xml.rels
			xl.folder('_rels').file('workbook.xml.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
				+ '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>'
				+ '<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet2.xml"/>'
				+ '<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition" Target="pivotCache/pivotCacheDefinition1.xml"/>'
				+ '<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>'
				+ '<Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>'
				+ '<Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>'
				+ '</Relationships>');

			//pivot cache folder
			var folderPivotCache = xl.folder('pivotCache').file('pivotCacheRecords1.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<pivotCacheRecords xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
				+ '</pivotCacheRecords>');


			folderPivotCache.file('pivotCacheDefinition1.xml', file.pivotCacheDefinition)


			folderPivotCache.folder('_rels').file('pivotCacheDefinition1.xml.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
				+ '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheRecords" Target="pivotCacheRecords1.xml"/>'
				+ '</Relationships>')



			//folder pivot table	
			var folderPivotTable = xl.folder('pivotTables').file('pivotTable1.xml', file.pivotTable1);

			folderPivotTable.folder('_rels').file('pivotTable1.xml.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
				+ '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition" Target="../pivotCache/pivotCacheDefinition1.xml"/>'
				+ '</Relationships>');

			//folder theme file theme1.xml
			xl.folder('theme').file('theme1.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<a:theme name="Tema de Office" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"/>');

			//xl/worksheets
			xlWorksheets = xl.folder('worksheets');
			xlWorksheets.file('sheet1.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
				+ '<sheetData/>'
				+ '</worksheet>');



			// Content dependent
			styles = new Array(1);
			borders = new Array(1);
			fonts = new Array(1);
			var fills = "";
			var fillNumber = 1;
			w = file.worksheets.length;
			while (w--) {
				// Generate worksheet (gather sharedStrings), and possibly table files, then generate entries for constant files below
				id = w + 1;
				// Generate sheetX.xml in var s
				worksheet = file.worksheets[w]; data = worksheet.data;
				s = '';
				columns = [];
				merges = [];
				i = -1; l = data.length;
				while (++i < l) {
					j = -1; k = data[i].length;
					s += '<row r="' + (i + 1) + '" x14ac:dyDescent="0.25">';
					while (++j < k) {
						var isString = false;
						cell = data[i][j]; val = cell.hasOwnProperty('value') ? cell.value : cell; t = '';
						// supported styles: borders, hAlign, formatCode and font style
						style = {
							borders: cell.borders,
							hAlign: cell.hAlign,
							vAlign: cell.vAlign,
							bold: cell.bold,
							italic: cell.italic,
							fontColor: cell.fontColor,
							fontName: cell.fontName,
							fontSize: cell.fontSize,
							fill: cell.fill,
							formatCode: cell.formatCode || 'General'
						};
						colWidth = 0;
						if (( ((cell.isString) || (val && typeof val === 'string' && !isFinite(val))) && !(cell.genexusType == 'date') && !(cell.genexusType == 'datetime')) || (cell.genexusType == 'character')) {
							// If value is string, and not string of just a number
							val = escapeXML(val);
							t = 'inlineStr';
							isString = true;
						} else if (typeof val === 'boolean') {
							val = (val ? 1 : 0); t = 'b';
							colWidth = 1;
						} else if ((typeOf(val) === 'date') || (cell.genexusType == 'date') || (cell.genexusType == 'datetime')) {
							
							if (cell.genexusType == 'date'){
								var pars  = val.split("-")
								
								if (!(cell.genexusPicture) || (cell.genexusPicture == "99/99/99")){
									val = pars[1] + "/" + pars[2] + "/" + pars[0].substring(2)
								}
								if (cell.genexusPicture == "99/99/9999"){
									val = pars[1] + "/" + pars[2] + "/" + pars[0]
								}
								if (cell.genexusPicture == "9999/99/99"){
									val = pars[0] + "/" + pars[1] + "/" + pars[2]
								}
							} else {
								var datetimepars  = val.split(" ")
								var pars = datetimepars[0].split("-")
								datePars = datetimepars[1].split(":")
								
								if (!cell.genexusPicture){
									val = pars[1] + "/" + pars[2] + "/" + pars[0].substring(2) + " " + datePars[0] + ":" + datePars[1] 
								} else {
									var picturePars = cell.genexusPicture.split(" ")
									
									if (picturePars[0] == "99/99/99"){
										val = pars[1] + "/" + pars[2] + "/" + pars[0].substring(2)
									}
									if (picturePars[0] == "99/99/9999"){
										val = pars[1] + "/" + pars[2] + "/" + pars[0]
									}
									if (picturePars[0] == "9999/99/99"){
										val = pars[0] + "/" + pars[1] + "/" + pars[2]
									}	
									
									if (picturePars[1] == "99")
									{
										val = val + " " + datePars[0]
									}
									if (picturePars[1] == "99:99")
									{
										val = val + " " + datePars[0] + ":" + datePars[1] 								
									}
									if (picturePars[1] == "99:99:99")
									{
										val = val + " " + datePars[0] + ":" + datePars[1] + ":" + datePars[2].split(".")[0]
									}								
									if (picturePars[1] == "99:99:99.999")
									{
										val = val + " " + datePars[0] + ":" + datePars[1] + ":" + datePars[2]
									}
								}
							}
							t = 'inlineStr';
							isString = true;
							style.hAlign = "right"
							
						} else if (typeof val === 'object') {
							// unsupported value
							val = null
						} else {
							// number, or string which is a number 
							colWidth = ('' + val).length;
						}

						// use stringified version as unic and reproductible style signature
						style = JSON.stringify(style);
						index = styles.indexOf(style);
						if (index < 0) {
							style = styles.push(style) - 1;
						} else {
							style = index;
						}
						// keeps largest cell in column, and autoWidth flag that may be set on any cell
						if (columns[j] == null) {
							columns[j] = { autoWidth: false, max: 0 };
						}
						if (cell.autoWidth) {
							columns[j].autoWidth = true
						}
						if (colWidth > columns[j].max) {
							columns[j].max = colWidth;
						}
						// store merges if needed and add missing cells. Cannot have rowSpan AND colSpan
						if (cell.colSpan > 1) {
							// horizontal merge. ex: B12:E12. Add missing cells (with same attribute but value) to current row
							merges.push([numAlpha(j) + (i + 1), numAlpha(j + cell.colSpan - 1) + (i + 1)]);
							merged = [j, 0]
							for (var m = 0; m < cell.colSpan - 1; m++) {
								merged.push(cell);
							}
							data[i].splice.apply(data[i], merged);
							k += cell.colSpan - 1;
						} else if (cell.rowSpan > 1) {
							// vertical merge. ex: B12:B15. Add missing cells (with same attribute but value) to next columns
							for (var m = 1; m < cell.rowSpan; m++) {
								if (data[i + m]) {
									data[i + m].splice(j, 0, cell)
								} else {
									// read the end of data
									cell.rowSpan = m;
									break;
								}
							}
							merges.push([numAlpha(j) + (i + 1), numAlpha(j) + (i + cell.rowSpan)]);
						}
						if (cell.rowSpan > 1 || cell.colSpan > 1) {
							// deletes value, rowSpan and colSpan from cell to avoid refering it from copied cells
							delete cell.value;
							delete cell.rowSpan;
							delete cell.colSpan;
						}
						s += '<c r="' + numAlpha(j) + (i + 1) + '"' + (style ? ' s="' + style + '"' : '') + (t ? ' t="' + t + '"' : '');
						if (val != null) {
							if (isString) {
								s += '>' + (cell.formula ? '<f>' + cell.formula + '</f>' : '') + '<is><t>' + val + '</t></is></c>';
							} else {
								s += '>' + (cell.formula ? '<f>' + cell.formula + '</f>' : '') + '<v>' + val + '</v></c>';
							}
						} else {
							s += '/>';
						}
					}
					s += '</row>';
				}

				cols = []
				for (i = 0; i < columns.length; i++) {
					if (columns[i].autoWidth) {
						cols.push('<col min="', i + 1, '" max="', i + 1, '" width="', columns[i].max, '" bestFit="1"/>');
					}
				}
				// only add cols definition if not empty
				if (cols.length > 0) {
					cols = ['<cols>'].concat(cols, ['</cols>']).join('');
				}

				s = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">'
					+ '<dimension ref="A1:' + numAlpha(data[0].length - 1) + data.length + '"/><sheetViews><sheetView ' + (w === file.activeWorksheet ? 'tabSelected="1" ' : '')
					+ ' workbookViewId="0"/></sheetViews><sheetFormatPr defaultRowHeight="15" x14ac:dyDescent="0.25"/>'
					+ cols
					+ '<sheetData>'
					+ s
					+ '</sheetData>';
				if (merges.length > 0) {
					s += '<mergeCells count="' + merges.length + '">';
					for (i = 0; i < merges.length; i++) {
						s += '<mergeCell ref="' + merges[i].join(':') + '"/>';
					}
					s += '</mergeCells>';
				}
				s += '<pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>';
				if (worksheet.table) {
					s += '<tableParts count="1"><tablePart r:id="rId1"/></tableParts>';
				}
				xlWorksheets.file('sheet2.xml', s + '</worksheet>');
			}
			//xlWorksheets.file('sheet2.xml', file.Sheet2);

			// xl/styles.xml
			i = styles.length; t = [];
			var fillIndex = 2;
			var actualFill = 0;
			while (--i) {
				// Don't process index 0, already added
				style = JSON.parse(styles[i]);

				// cell formating, refer to it if necessary
				if (style.formatCode !== 'General') {
					index = numFmts.indexOf(style.formatCode);
					if (index < 0) {
						index = 164 + t.length;
						t.push('<numFmt formatCode="' + style.formatCode + '" numFmtId="' + index + '"/>');
					}
					style.formatCode = index
				} else {
					style.formatCode = 0
				}

				// border declaration: add a new declaration and refer to it in style
				borderIndex = 0
				if (style.borders) {
					border = ['<border>']
					// order is significative
					for (var edge in { left: 0, right: 0, top: 0, bottom: 0, diagonal: 0 }) {
						if (style.borders[edge]) {
							var color = style.borders[edge];
							// add transparency if missing
							if (color.length === 6) {
								color = 'FF' + color;
							}
							border.push('<', edge, ' style="thin">', '<color rgb="', style.borders[edge], '"/></', edge, '>');
						} else {
							border.push('<', edge, '/>');
						}
					}
					border.push('</border>');
					border = border.join('');
					// try to reuse existing border
					borderIndex = borders.indexOf(border);
					if (borderIndex < 0) {
						borderIndex = borders.push(border) - 1;
					}
				}

				// font declaration: add a new declaration and refer to it in style
				fontIndex = 0
				if (style.bold || style.italic || style.fontSize || style.fontName || style.fontColor) {
					font = ['<font>']
					if (style.bold) {
						font.push('<b/>');
					}
					if (style.italic) {
						font.push('<i/>');
					}
					font.push('<sz val="', style.fontSize || defaultFontSize, '"/>');
					var colString =
						font.push('<color rgb="FF', style.fontColor || defaultFontColor, '"/>');
					font.push('<name val="', style.fontName || defaultFontName, '"/>');
					font.push('<family val="2"/>', '</font>');
					font = font.join('');
					// try to reuse existing font
					fontIndex = fonts.indexOf(font);
					if (fontIndex < 0) {
						fontIndex = fonts.push(font) - 1;
					}
				}

				//fill declaration: add a new declaration and refer to it in style
				actualFill = 0;
				if (style.fill) {
					fills = fills + '<fill><patternFill patternType="solid"><fgColor rgb="FF' + style.fill + '"/>'
						+ '<bgColor indexed="64"/></patternFill></fill>'
					fillNumber++;
					actualFill = fillNumber;
				}

				// declares style, and refer to optionnal formatCode, font and borders
				styles[i] = ['<xf xfId="0" borderId="', //fillId="0"  
					borderIndex,
					'" fontId="',
					fontIndex,
					'" numFmtId="',
					style.formatCode,
					'" fillId="',
					actualFill,
					'" ',
					(style.hAlign || style.vAlign ? 'applyAlignment="1" ' : ' '),
					(style.formatCode > 0 ? 'applyNumberFormat="1" ' : ' '),
					(borderIndex > 0 ? 'applyBorder="1" ' : ' '),
					(fontIndex > 0 ? 'applyFont="1" ' : ' '),
					(actualFill > 0 ? 'applyFill="1" ' : ' '),
					'>'
				];
				if (style.hAlign || style.vAlign) {
					styles[i].push('<alignment');
					if (style.hAlign) {
						styles[i].push(' horizontal="', style.hAlign, '"');
					}
					if (style.vAlign) {
						styles[i].push(' vertical="', style.vAlign, '"');
					}
					styles[i].push('/>');
				}
				styles[i].push('</xf>');
				styles[i] = styles[i].join('');
			}
			t = t.length ? '<numFmts count="' + t.length + '">' + t.join('') + '</numFmts>' : '';

			if (file.style != "") {
				t = file.style //TODO: concat with the previous number format
			}
			var multStyle = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">'
				+ t + '<fonts count="' + fonts.length + '" x14ac:knownFonts="1"><font><sz val="' + defaultFontSize + '"/><color theme="1"/><name val="' + defaultFontName + '"/><family val="2"/>'
				+ '<scheme val="minor"/></font>' + fonts.join('') + '</fonts>'
				+ '<fills><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill>' + fills + '</fills>'
				+ '<borders count="' + borders.length + '"><border><left/><right/><top/><bottom/><diagonal/></border>'
				+ borders.join('') + '</borders><cellStyleXfs count="1">'
				+ '<xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs><cellXfs count="' + styles.length + '"><xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/>'
				+ styles.join('') + '</cellXfs><cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>' //<dxfs count="0"/>'
			if (file.dfx != undefined) {
				multStyle = multStyle + '<dxfs>' + file.dfx + '</dxfs>';
			} else {
				multStyle = multStyle + '<dxfs count="0"/>'
			}
			multStyle = multStyle + '<tableStyles count="0" defaultTableStyle="TableStyleMedium2" defaultPivotStyle="PivotStyleLight16"/>'
				+ '<extLst><ext uri="{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main">'
				+ '<x14:slicerStyles defaultSlicerStyle="SlicerStyleLight1"/></ext></extLst></styleSheet>'

			xl.file('styles.xml', multStyle)
			//xl.file('styles.xml', file.style);

			xlWorksheets.folder('_rels').file('sheet1.xml.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable" Target="../pivotTables/pivotTable1.xml"/></Relationships>')

			//shared strings
			xl.file('sharedStrings.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">'
				+ '</sst>')


			//workwood
			xl.file('workbook.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
				+ '<fileVersion appName="xl" lastEdited="4" lowestEdited="4" rupBuild="4506"/>'
				+ '<workbookPr defaultThemeVersion="124226"/>'
				+ '<bookViews>'
				+ '<workbookView xWindow="360" yWindow="555" windowWidth="21015" windowHeight="9405"/>'
				+ '</bookViews>'
				+ '<sheets>'
				+ '<sheet name="PivotTable" sheetId="1" r:id="rId1"/>'
				+ '<sheet name="SourceData" sheetId="2" r:id="rId2"/>'
				+ '</sheets>'
				+ '<calcPr calcId="125725"/>'
				+ '<pivotCaches>'
				+ '<pivotCache cacheId="5" r:id="rId3"/>'
				+ '</pivotCaches>'
				+ '<fileRecoveryPr repairLoad="1"/>'
				+ '</workbook>');


			//xl styles



			processTime = Date.now() - processTime;
			zipTime = Date.now();
			result = {
				base64: zip.generate({ compression: 'STORE' }), zipTime: Date.now() - zipTime, processTime: processTime,
				href: function () { return 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,' + this.base64; }
			};
		} else {
			// Save
			processTime = Date.now();
			sharedStrings = [[], 0];
			// Fully static
			zip.folder('_rels').file('.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>');
			docProps = zip.folder('docProps');

			xl = zip.folder('xl');
			xl.folder('theme').file('theme1.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme"><a:themeElements><a:clrScheme name="Office"><a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1><a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1><a:dk2><a:srgbClr val="1F497D"/></a:dk2><a:lt2><a:srgbClr val="EEECE1"/></a:lt2><a:accent1><a:srgbClr val="4F81BD"/></a:accent1><a:accent2><a:srgbClr val="C0504D"/></a:accent2><a:accent3><a:srgbClr val="9BBB59"/></a:accent3><a:accent4><a:srgbClr val="8064A2"/></a:accent4><a:accent5><a:srgbClr val="4BACC6"/></a:accent5><a:accent6><a:srgbClr val="F79646"/></a:accent6><a:hlink><a:srgbClr val="0000FF"/></a:hlink><a:folHlink><a:srgbClr val="800080"/></a:folHlink></a:clrScheme><a:fontScheme name="Office"><a:majorFont><a:latin typeface="Cambria"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="MS P????"/><a:font script="Hang" typeface="?? ??"/><a:font script="Hans" typeface="??"/><a:font script="Hant" typeface="????"/><a:font script="Arab" typeface="Times New Roman"/><a:font script="Hebr" typeface="Times New Roman"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="MoolBoran"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Times New Roman"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/></a:majorFont><a:minorFont><a:latin typeface="Calibri"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="MS P????"/><a:font script="Hang" typeface="?? ??"/><a:font script="Hans" typeface="??"/><a:font script="Hant" typeface="????"/><a:font script="Arab" typeface="Arial"/><a:font script="Hebr" typeface="Arial"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="DaunPenh"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Arial"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/></a:minorFont></a:fontScheme><a:fmtScheme name="Office"><a:fillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000"/><a:satMod val="350000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="1"/></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:shade val="51000"/><a:satMod val="130000"/></a:schemeClr></a:gs><a:gs pos="80000"><a:schemeClr val="phClr"><a:shade val="93000"/><a:satMod val="130000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="94000"/><a:satMod val="135000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="0"/></a:gradFill></a:fillStyleLst><a:lnStyleLst><a:ln w="9525" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"><a:shade val="95000"/><a:satMod val="105000"/></a:schemeClr></a:solidFill><a:prstDash val="solid"/></a:ln><a:ln w="25400" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln><a:ln w="38100" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln></a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="20000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="38000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw></a:effectLst><a:scene3d><a:camera prst="orthographicFront"><a:rot lat="0" lon="0" rev="0"/></a:camera><a:lightRig rig="threePt" dir="t"><a:rot lat="0" lon="0" rev="1200000"/></a:lightRig></a:scene3d><a:sp3d><a:bevelT w="63500" h="25400"/></a:sp3d></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000"/><a:satMod val="350000"/></a:schemeClr></a:gs><a:gs pos="40000"><a:schemeClr val="phClr"><a:tint val="45000"/><a:shade val="99000"/><a:satMod val="350000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000"/><a:satMod val="255000"/></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="-80000" r="50000" b="180000"/></a:path></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="30000"/><a:satMod val="200000"/></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000"/></a:path></a:gradFill></a:bgFillStyleLst></a:fmtScheme></a:themeElements><a:objectDefaults/><a:extraClrSchemeLst/></a:theme>');
			xlWorksheets = xl.folder('worksheets');

			// Not content dependent
			docProps.file('core.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dc:creator>'
				+ (file.creator || 'XLSX.js') + '</dc:creator><cp:lastModifiedBy>' + (file.lastModifiedBy || 'XLSX.js') + '</cp:lastModifiedBy><dcterms:created xsi:type="dcterms:W3CDTF">'
				+ (file.created || new Date()).toISOString() + '</dcterms:created><dcterms:modified xsi:type="dcterms:W3CDTF">' + (file.modified || new Date()).toISOString() + '</dcterms:modified></cp:coreProperties>');

			// Content dependent
			styles = new Array(1);
			borders = new Array(1);
			fonts = new Array(1);
			var fills = "";
			var fillNumber = 1;
			w = file.worksheets.length;
			while (w--) {
				// Generate worksheet (gather sharedStrings), and possibly table files, then generate entries for constant files below
				id = w + 1;
				// Generate sheetX.xml in var s
				worksheet = file.worksheets[w]; data = worksheet.data;
				s = '';
				columns = [];
				merges = [];
				i = -1; l = data.length;
				while (++i < l) {
					j = -1; k = data[i].length;
					s += '<row r="' + (i + 1) + '" x14ac:dyDescent="0.25">';
					while (++j < k) {
						cell = data[i][j]; val = cell.hasOwnProperty('value') ? cell.value : cell; t = '';
						// supported styles: borders, hAlign, formatCode and font style
						style = {
							borders: cell.borders,
							hAlign: cell.hAlign,
							vAlign: cell.vAlign,
							bold: cell.bold,
							italic: cell.italic,
							fontColor: cell.fontColor,
							fontName: cell.fontName,
							fontSize: cell.fontSize,
							fill: cell.fill,
							formatCode: cell.formatCode || 'General'
						};
						colWidth = 0;
						if ((val && typeof val === 'string' && !isFinite(val) && !(cell.genexusType == 'date') && !(cell.genexusType == 'datetime')) || (cell.genexusType == 'character'))  {
							// If value is string, and not string of just a number, place a sharedString reference instead of the value
							val = escapeXML(val);
							sharedStrings[1]++; // Increment total count, unique count derived from sharedStrings[0].length
							index = sharedStrings[0].indexOf(val);
							colWidth = val.length;
							if (index < 0) {
								index = sharedStrings[0].push(val) - 1;
							}
							val = index;
							t = 's';
						} else if (typeof val === 'boolean') {
							val = (val ? 1 : 0); t = 'b';
							colWidth = 1;
						} else if ((typeOf(val) === 'date') /*|| (cell.genexusType == 'date') */){
							var pars  = val.split("-")
							var datePars;
							if (cell.genexusType == "datetime") {
								var datetimepars  = val.split(" ")
								pars = datetimepars[0].split("-")
								datePars = datetimepars[1].split(":")
							}
							var dt = null;
							//var dt = new Date(pars[0], parseInt(pars[1])-1, parseInt(pars[2])+1) //, 5+1, 30-15, 0-9);
							if (cell.genexusType == 'datetime'){
								dt = new Date(pars[0], parseInt(pars[1])-1, parseInt(pars[2]), parseInt(datePars[0])+1, parseInt(datePars[1])-15, parseInt(datePars[2])-9);
								
							} else {
								dt = new Date(pars[0], parseInt(pars[1])-1, parseInt(pars[2])+1)
							}
							val = convertDate(dt);//convertDate(val);
							if (cell.genexusType == 'date') {
								val = parseInt(val)
								style.formatCode = cell.formatCode || 'mm/dd/yy';
							} else {
								style.formatCode = cell.formatCode || 'mm/dd/yy hh:mm';
							}
							
							colWidth = cell.formatCode.length + 1;
						} else if ((cell.genexusType == 'date') || (cell.genexusType == "datetime")) {
							if (cell.genexusType == 'date'){
								var pars  = val.split("-")
								
								if (!(cell.genexusPicture) || (cell.genexusPicture == "99/99/99")){
									val = pars[1] + "/" + pars[2] + "/" + pars[0].substring(2)
								}
								if (cell.genexusPicture == "99/99/9999"){
									val = pars[1] + "/" + pars[2] + "/" + pars[0]
								}
								if (cell.genexusPicture == "9999/99/99"){
									val = pars[0] + "/" + pars[1] + "/" + pars[2]
								}
							} else {
								var datetimepars  = val.split(" ")
								var pars = datetimepars[0].split("-")
								datePars = datetimepars[1].split(":")
								
								if (!cell.genexusPicture){
									val = pars[1] + "/" + pars[2] + "/" + pars[0].substring(2) + " " + datePars[0] + ":" + datePars[1] 
								} else {
									var picturePars = cell.genexusPicture.split(" ")
									
									if (picturePars[0] == "99/99/99"){
										val = pars[1] + "/" + pars[2] + "/" + pars[0].substring(2)
									}
									if (picturePars[0] == "99/99/9999"){
										val = pars[1] + "/" + pars[2] + "/" + pars[0]
									}
									if (picturePars[0] == "9999/99/99"){
										val = pars[0] + "/" + pars[1] + "/" + pars[2]
									}	
									
									if (picturePars[1] == "99")
									{
										val = val + " " + datePars[0]
									}
									if (picturePars[1] == "99:99")
									{
										val = val + " " + datePars[0] + ":" + datePars[1] 								
									}
									if (picturePars[1] == "99:99:99")
									{
										val = val + " " + datePars[0] + ":" + datePars[1] + ":" + datePars[2].split(".")[0]
									}								
									if (picturePars[1] == "99:99:99.999")
									{
										val = val + " " + datePars[0] + ":" + datePars[1] + ":" + datePars[2]
									}
								}
							}
							
							
							val = escapeXML(val);
							sharedStrings[1]++; // Increment total count, unique count derived from sharedStrings[0].length
							index = sharedStrings[0].indexOf(val);
							colWidth = val.length;
							if (index < 0) {
								index = sharedStrings[0].push(val) - 1;
							}
							val = index;
							t = 's';
							style.formatCode = 'General'
							style.hAlign = 'right'
						} else if (typeof val === 'object') {
							// unsupported value
							val = null
						} else {
							// number, or string which is a number 
							colWidth = ('' + val).length;
						}

						// use stringified version as unic and reproductible style signature
						style = JSON.stringify(style);
						index = styles.indexOf(style);
						if (index < 0) {
							style = styles.push(style) - 1;
						} else {
							style = index;
						}
						// keeps largest cell in column, and autoWidth flag that may be set on any cell
						if (columns[j] == null) {
							columns[j] = { autoWidth: false, max: 0 };
						}
						if ((cell.autoWidth) || (cell.genexusType == 'date') || (cell.genexusType == 'datetime')) {
							//auto width for date and datetime columns
							columns[j].autoWidth = true
						}
						if (colWidth > columns[j].max) {
							columns[j].max = colWidth;
						}
						// store merges if needed and add missing cells. Cannot have rowSpan AND colSpan
						if (cell.colSpan > 1) {
							// horizontal merge. ex: B12:E12. Add missing cells (with same attribute but value) to current row
							merges.push([numAlpha(j) + (i + 1), numAlpha(j + cell.colSpan - 1) + (i + 1)]);
							merged = [j, 0]
							for (var m = 0; m < cell.colSpan - 1; m++) {
								merged.push(cell);
							}
							data[i].splice.apply(data[i], merged);
							k += cell.colSpan - 1;
						} else if (cell.rowSpan > 1) {
							// vertical merge. ex: B12:B15. Add missing cells (with same attribute but value) to next columns
							for (var m = 1; m < cell.rowSpan; m++) {
								if (data[i + m]) {
									data[i + m].splice(j, 0, cell)
								} else {
									// readh the end of data
									cell.rowSpan = m;
									break;
								}
							}
							merges.push([numAlpha(j) + (i + 1), numAlpha(j) + (i + cell.rowSpan)]);
						}
						if (cell.rowSpan > 1 || cell.colSpan > 1) {
							// deletes value, rowSpan and colSpan from cell to avoid refering it from copied cells
							delete cell.value;
							delete cell.rowSpan;
							delete cell.colSpan;
						}
						s += '<c r="' + numAlpha(j) + (i + 1) + '"' + (style ? ' s="' + style + '"' : '') + (t ? ' t="' + t + '"' : '');
						if (val != null) {
							s += '>' + (cell.formula ? '<f>' + cell.formula + '</f>' : '') + '<v>' + val + '</v></c>';
						} else {
							s += '/>';
						}
					}
					s += '</row>';
				}

				cols = []
				for (i = 0; i < columns.length; i++) {
					if (columns[i].autoWidth) {
						cols.push('<col min="', i + 1, '" max="', i + 1, '" width="', columns[i].max, '" bestFit="1"/>');
					}
				}
				// only add cols definition if not empty
				if (cols.length > 0) {
					cols = ['<cols>'].concat(cols, ['</cols>']).join('');
				}

				s = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">'
					+ '<dimension ref="A1:' + numAlpha(data[0].length - 1) + data.length + '"/><sheetViews><sheetView ' + (w === file.activeWorksheet ? 'tabSelected="1" ' : '')
					+ ' workbookViewId="0"/></sheetViews><sheetFormatPr defaultRowHeight="15" x14ac:dyDescent="0.25"/>'
					+ cols
					+ '<sheetData>'
					+ s
					+ '</sheetData>';
				if (merges.length > 0) {
					s += '<mergeCells count="' + merges.length + '">';
					for (i = 0; i < merges.length; i++) {
						s += '<mergeCell ref="' + merges[i].join(':') + '"/>';
					}
					s += '</mergeCells>';
				}
				s += '<pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>';
				if (worksheet.table) {
					s += '<tableParts count="1"><tablePart r:id="rId1"/></tableParts>';
				}
				xlWorksheets.file('sheet' + id + '.xml', s + '</worksheet>');

				if (worksheet.table) {
					i = -1; l = data[0].length; t = numAlpha(data[0].length - 1) + data.length;
					s = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><table xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" id="' + id
						+ '" name="Table' + id + '" displayName="Table' + id + '" ref="A1:' + t + '" totalsRowShown="0"><autoFilter ref="A1:' + t + '"/><tableColumns count="' + data[0].length + '">';
					while (++i < l) {
						s += '<tableColumn id="' + (i + 1) + '" name="' + (data[0][i].hasOwnProperty('value') ? data[0][i].value : data[0][i]) + '"/>';
					}
					s += '</tableColumns><tableStyleInfo name="TableStyleMedium2" showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0"/></table>';

					xl.folder('tables').file('table' + id + '.xml', s);
					xlWorksheets.folder('_rels').file('sheet' + id + '.xml.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/table" Target="../tables/table' + id + '.xml"/></Relationships>');
					contentTypes[1].unshift('<Override PartName="/xl/tables/table' + id + '.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"/>');
				}

				contentTypes[0].unshift('<Override PartName="/xl/worksheets/sheet' + id + '.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>');
				props.unshift(escapeXML(worksheet.name) || 'Sheet' + id);
				xlRels.unshift('<Relationship Id="rId' + id + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet' + id + '.xml"/>');
				worksheets.unshift('<sheet name="' + (escapeXML(worksheet.name) || 'Sheet' + id) + '" sheetId="' + id + '" r:id="rId' + id + '"/>');
			}

			// xl/styles.xml
			i = styles.length; t = [];
			var fillIndex = 2;
			var actualFill = 0;
			while (--i) {
				// Don't process index 0, already added
				style = JSON.parse(styles[i]);

				// cell formating, refer to it if necessary
				if (style.formatCode !== 'General') {
					index = numFmts.indexOf(style.formatCode);
					if (index < 0) {
						index = 164 + t.length;
						t.push('<numFmt formatCode="' + style.formatCode + '" numFmtId="' + index + '"/>');
					}
					style.formatCode = index
				} else {
					style.formatCode = 0
				}

				// border declaration: add a new declaration and refer to it in style
				borderIndex = 0
				if (style.borders) {
					border = ['<border>']
					// order is significative
					for (var edge in { left: 0, right: 0, top: 0, bottom: 0, diagonal: 0 }) {
						if (style.borders[edge]) {
							var color = style.borders[edge];
							// add transparency if missing
							if (color.length === 6) {
								color = 'FF' + color;
							}
							border.push('<', edge, ' style="thin">', '<color rgb="', style.borders[edge], '"/></', edge, '>');
						} else {
							border.push('<', edge, '/>');
						}
					}
					border.push('</border>');
					border = border.join('');
					// try to reuse existing border
					borderIndex = borders.indexOf(border);
					if (borderIndex < 0) {
						borderIndex = borders.push(border) - 1;
					}
				}

				// font declaration: add a new declaration and refer to it in style
				fontIndex = 0
				if (style.bold || style.italic || style.fontSize || style.fontName || style.fontColor) {
					font = ['<font>']
					if (style.bold) {
						font.push('<b/>');
					}
					if (style.italic) {
						font.push('<i/>');
					}
					font.push('<sz val="', style.fontSize || defaultFontSize, '"/>');
					var colString =
						font.push('<color rgb="FF', style.fontColor || defaultFontColor, '"/>');
					font.push('<name val="', style.fontName || defaultFontName, '"/>');
					font.push('<family val="2"/>', '</font>');
					font = font.join('');
					// try to reuse existing font
					fontIndex = fonts.indexOf(font);
					if (fontIndex < 0) {
						fontIndex = fonts.push(font) - 1;
					}
				}

				//fill declaration: add a new declaration and refer to it in style
				actualFill = 0;
				if (style.fill) {
					fills = fills + '<fill><patternFill patternType="solid"><fgColor rgb="FF' + style.fill + '"/>'
						+ '<bgColor indexed="64"/></patternFill></fill>'
					fillNumber++;
					actualFill = fillNumber;
				}

				// declares style, and refer to optionnal formatCode, font and borders
				styles[i] = ['<xf xfId="0" borderId="', //fillId="0"  
					borderIndex,
					'" fontId="',
					fontIndex,
					'" numFmtId="',
					style.formatCode,
					'" fillId="',
					actualFill,
					'" ',
					(style.hAlign || style.vAlign ? 'applyAlignment="1" ' : ' '),
					(style.formatCode > 0 ? 'applyNumberFormat="1" ' : ' '),
					(borderIndex > 0 ? 'applyBorder="1" ' : ' '),
					(fontIndex > 0 ? 'applyFont="1" ' : ' '),
					(actualFill > 0 ? 'applyFill="1" ' : ' '),
					'>'
				];
				if (style.hAlign || style.vAlign) {
					styles[i].push('<alignment');
					if (style.hAlign) {
						styles[i].push(' horizontal="', style.hAlign, '"');
					}
					if (style.vAlign) {
						styles[i].push(' vertical="', style.vAlign, '"');
					}
					styles[i].push('/>');
				}
				styles[i].push('</xf>');
				styles[i] = styles[i].join('');
			}
			t = t.length ? '<numFmts count="' + t.length + '">' + t.join('') + '</numFmts>' : '';

			xl.file('styles.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">'
				+ t + '<fonts count="' + fonts.length + '" x14ac:knownFonts="1"><font><sz val="' + defaultFontSize + '"/><color theme="1"/><name val="' + defaultFontName + '"/><family val="2"/>'
				+ '<scheme val="minor"/></font>' + fonts.join('') + '</fonts>'
	/*count="2"*/ + '<fills><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill>' + fills + '</fills>'
				+ '<borders count="' + borders.length + '"><border><left/><right/><top/><bottom/><diagonal/></border>'
				+ borders.join('') + '</borders><cellStyleXfs count="1">'
				+ '<xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs><cellXfs count="' + styles.length + '"><xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/>'
				+ styles.join('') + '</cellXfs><cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles><dxfs count="0"/>'
				+ '<tableStyles count="0" defaultTableStyle="TableStyleMedium2" defaultPivotStyle="PivotStyleLight16"/>'
				+ '<extLst><ext uri="{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main">'
				+ '<x14:slicerStyles defaultSlicerStyle="SlicerStyleLight1"/></ext></extLst></styleSheet>');

			// [Content_Types].xml
			zip.file('[Content_Types].xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>'
				+ contentTypes[0].join('') + '<Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/><Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/><Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>'
				+ contentTypes[1].join('') + '<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/><Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/></Types>');

			// docProps/app.xml
			docProps.file('app.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><Application>XLSX.js</Application><DocSecurity>0</DocSecurity><ScaleCrop>false</ScaleCrop><HeadingPairs><vt:vector size="2" baseType="variant"><vt:variant><vt:lpstr>Worksheets</vt:lpstr></vt:variant><vt:variant><vt:i4>'
				+ file.worksheets.length + '</vt:i4></vt:variant></vt:vector></HeadingPairs><TitlesOfParts><vt:vector size="' + props.length + '" baseType="lpstr"><vt:lpstr>' + props.join('</vt:lpstr><vt:lpstr>')
				+ '</vt:lpstr></vt:vector></TitlesOfParts><Manager></Manager><Company>Microsoft Corporation</Company><LinksUpToDate>false</LinksUpToDate><SharedDoc>false</SharedDoc><HyperlinksChanged>false</HyperlinksChanged><AppVersion>1.0</AppVersion></Properties>');

			// xl/_rels/workbook.xml.rels
			xl.folder('_rels').file('workbook.xml.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
				+ xlRels.join('') + '<Relationship Id="rId' + (xlRels.length + 1) + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>'
				+ '<Relationship Id="rId' + (xlRels.length + 2) + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>'
				+ '<Relationship Id="rId' + (xlRels.length + 3) + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/></Relationships>');

			// xl/sharedStrings.xml
			xl.file('sharedStrings.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="'
				+ sharedStrings[1] + '" uniqueCount="' + sharedStrings[0].length + '"><si><t>' + sharedStrings[0].join('</t></si><si><t>') + '</t></si></sst>');

			// xl/workbook.xml
			xl.file('workbook.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
				+ '<fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="9303"/><workbookPr defaultThemeVersion="124226"/><bookViews><workbookView '
				+ (file.activeWorksheet ? 'activeTab="' + file.activeWorksheet + '" ' : '') + 'xWindow="480" yWindow="60" windowWidth="18195" windowHeight="8505"/></bookViews><sheets>'
				+ worksheets.join('') + '</sheets><calcPr calcId="145621"/></workbook>');

			processTime = Date.now() - processTime;
			zipTime = Date.now();
			result = {
				base64: zip.generate({ compression: 'DEFLATE' }), zipTime: Date.now() - zipTime, processTime: processTime,
				href: function () { return 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,' + this.base64; }
			};
		}
		return result;
	}

	// NodeJs export
	if (typeof exports === 'object' && typeof module === 'object') {
		module.exports = xlsx;
	}

	OAT.GeneratePDFOutput = function (self, fileName) {
		var totalColSpan = -1;
		var tablemarginleft = 10;
		var tablemargintop = 13;
		var cellwidth = 25;
		var y = -1;

		//calc max length of paper
		var hgt = tablemargintop + jQuery("#" + self.controlName + "_" + self.query + " tr").length * 30 + 5;
		if (hgt < 841) {
			hgt = 841;
		}

		//calc max width of paper
		var wdt = 0;

		var title_row = true;
		var row_num = 0
		while ((title_row) && (row_num < jQuery("#" + self.controlName + "_" + self.query + " tr").length)) {
			if (jQuery("#" + self.controlName + "_" + self.query + " tr")[row_num].getAttribute("title_row") != "true")
				title_row = false
			else
				row_num++
		}

		var tRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[row_num];

		if (tRow == undefined) {
			tRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[0];
		}
		//var tRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[jQuery("#" + self.controlName + "_" + self.query + " tr").length-1];
		for (var j = 0; j < tRow.children.length; j++) {
			if (tRow.children[j].getAttribute('colspan') != null) {
				wdt = wdt + parseInt(tRow.children[j].getAttribute('colspan'));
			} else {
				wdt = wdt + 1;
			}
		}
		wdt = tablemarginleft + wdt * (cellwidth + 48) + 5;
		if (wdt < 595) {
			wdt = 595;
		}



		//calculate columns width
		var columnsWidth = [];
		for (var i = 0; i < jQuery("#" + self.controlName + "_" + self.query + " tr").length; i++) {//for every row

			var colspan = -1;
			totalColSpan = -1;

			//calcular el desplazamiento hacia la derecha de la fila, cuando en las filas superiores hay celdas con rowspan mayor a 1
			var desp = 0;
			for (var prevR = 0; prevR < i; prevR++) {	 //empiezo desde la de mas arriba
				var tRowprev = jQuery("#" + self.controlName + "_" + self.query + " tr")[prevR]; //obtengo la fila

				for (var prevC = 0; prevC < tRowprev.children.length; prevC++) {
					var prevRowSpan = tRowprev.children[prevC].getAttribute('rowspan'); //obtengo el rowspan
					if ((prevRowSpan != null) && (parseInt(prevRowSpan) > (i - prevR))) { //si el rowspan alcanza a esta fila
						// el desplazamiento es 1 o el colspan de la celda de arriba
						var prevColSpan = tRowprev.children[prevC].getAttribute('colspan'); //obtengo el rowspan
						if (prevColSpan === null) {
							desp = 1 + desp;
						} else {
							desp = parseInt(prevColSpan) + desp;
						}
					}
				}
			}

			colspan = desp - 1;
			var tRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[i];
			for (var j = 0; j < tRow.children.length; j++) { //for every column
				colspan++;
				var childText = OAT.removeIconFont(tRow.children[j].textContent.replace(/^\s+|\s+$/g, ''));
				var hidden = tRow.children[j].getAttribute('hidden');

				if (hidden === null) {

					var row = tRow.children[j].getAttribute('rowspan');
					var col = tRow.children[j].getAttribute('colspan');

					var oldCol = colspan;
					if (columnsWidth[oldCol] == undefined) {
						columnsWidth[oldCol] = cellwidth;
					}

					if (((row === null) && (col === null)) || ((j === tRow.children.length - 1) && (col === '3'))) {
						if ((col != null) && (childText === "")) {
							colspan = parseInt(col) + colspan - 1;
						}
					} else if (col === null) {
					} else if (row === null) {
						colspan = parseInt(col) + colspan - 1;
					} else {
						colspan = parseInt(col) + colspan - 1;
					}

					//japanese characters
					var jChar = 0;
					var carInicialesNoJap = 0
					var posC = 0;
					while ((posC < childText.length) && (childText.charCodeAt(posC) < 1000)) {
						carInicialesNoJap++;
						posC++;
					}
					jChar = childText.length - carInicialesNoJap;
					//for (var p = 0; p < childText.length; p++){
					//	if (childText.charCodeAt(p) > 1000){
					//		jChar++;
					//	}
					//} 

					if (jChar == 0) {
						if ((childText.length > 14) && ((col == null) || (i == 0) || (parseInt(col) < 2))) {
							if ((childText.length * 1.68) > columnsWidth[oldCol]) {
								columnsWidth[oldCol] = childText.length * 1.68;//la proporcion aurea?
							}
						}
					} else {
						//calculate for japanese space
						var w = jChar * 3.10 + (childText.length - jChar) * 2.00;
						if ((w > columnsWidth[oldCol]) && ((col == null) || (i == 0) || (parseInt(col) < 2))) {
							columnsWidth[oldCol] = w;//la proporcion aurea?
						}
					}
				}
				totalColSpan = colspan;
			}
		}
		//recalculate widht
		var nw = 0
		for (var cWP = 0; cWP < columnsWidth.length; cWP++) {
			nw = nw + columnsWidth[cWP] * 2.5 + 48;
		}
		nw = tablemarginleft + nw + 5;
		if (nw > wdt) {
			wdt = nw;
		}

		var getXOffset = function (colspan, columnsWidth) {
			if (colspan > columnsWidth.length) {
				colspan = columnsWidth.length
			}
			var offset = 0;
			for (var cWP = 0; cWP < colspan; cWP++) {
				offset = offset + columnsWidth[cWP];
			}
			return offset;
		}

		var getYOffset = function (rowspan, rowsHeight) {
			/*if (rowspan > rowsHeight.length){
				rowspan = rowspan.length;
			}*/
			var offsety = 0;
			for (var j = 0; j < rowspan; j++) {
				offsety = offsety + columnsWith[i];
			}
			return offsety;
		}


		//draw pivot on PDF
		var doc;
		if (wdt <= 595) {
			doc = new jsPDF('portrait', 'mm', 'a4', false, wdt, 792)//hgt); //landscape or portrait  //con 792 son 26 filas por hoja
		} else if ((wdt > 595) && (wdt < 792)) {
			doc = new jsPDF('landscape', 'mm', 'a4', false, 793, 792)//hgt); //landscape or portrait	
		} else {
			doc = new jsPDF('landscape', 'mm', 'a4', false, wdt, 792)//hgt); //landscape or portrait
		}


		doc.setFontSize(8);
		var spanSobrantes = [];
		if (jQuery("#" + self.controlName + "_" + self.query + " tr")[1 + self.colConditions.length] != undefined) {
			for (var n = 0; n < jQuery("#" + self.controlName + "_" + self.query + " tr")[1 + self.colConditions.length].children.length; n++) { spanSobrantes[n] = 0 }
		} else {
			for (var n = 0; n < jQuery("#" + self.controlName + "_" + self.query + " tr")[self.colConditions.length].children.length; n++) { spanSobrantes[n] = 0 }
		}
		for (var i = 0; i < jQuery("#" + self.controlName + "_" + self.query + " tr").length; i++) {//for every row
			//nroFilaHoja++; 

			var colspan = -1;
			totalColSpan = -1;
			y++;
			//calcular el desplazamiento hacia la derecha de la fila, cuando en las filas superiores hay celdas con rowspan mayor a 1
			var desp = 0;
			for (var prevR = 0; prevR < i; prevR++) {	 //empiezo desde la de mas arriba
				var tRowprev = jQuery("#" + self.controlName + "_" + self.query + " tr")[prevR]; //obtengo la fila

				for (var prevC = 0; prevC < tRowprev.children.length; prevC++) {
					var prevRowSpan = tRowprev.children[prevC].getAttribute('rowspan'); //obtengo el rowspan
					if ((prevRowSpan != null) && (parseInt(prevRowSpan) > (i - prevR))) { //si el rowspan alcanza a esta fila
						// el desplazamiento es 1 o el colspan de la celda de arriba
						var prevColSpan = tRowprev.children[prevC].getAttribute('colspan'); //obtengo el rowspan
						if (prevColSpan === null) {
							desp = 1 + desp;
						} else {
							desp = parseInt(prevColSpan) + desp;
						}
					}
				}
			}

			colspan = desp - 1;
			var tRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[i];
			var jR = -1;
			for (var j = 0; j < tRow.children.length; j++) {

				var childText = OAT.removeIconFont(tRow.children[j].textContent.replace(/^\s+|\s+$/g, '')); 
				var hidden = tRow.children[j].getAttribute('hidden');
				var ignore = tRow.children[j].getAttribute('pivotcorrect')


				//set styles
				var hasBackground = false;
				doc.setDrawColor(0, 0, 0);
				doc.setTextColor(0, 0, 0);
				doc.setFontStyle('normal')
				var IsTextAlignRight = (!isNaN(parseFloat(childText)) ||
					((childText == "-") && ((tRow.children[j].getAttribute("style") == undefined) || (tRow.children[j].getAttribute("style").indexOf("text-align: left") == -1))));
				var textWidht = 0;
				textWidht = doc.getStringUnitWidth(childText)
				if ((tRow.children[j].getAttribute("style") != undefined) && (tRow.children[j].getAttribute("style") != null)) {
					var attributes = tRow.children[j].getAttribute("style").split(";");
					for (var at = 0; at < attributes.length; at++) {
						var detail = attributes[at].split(":");
						if (detail[0].replace(/^\s+|\s+$/g, '') === "color") {
							var rgb = detail[1].replace(/^\s+|\s+$/g, '');
							rgb = rgb.substring(4, rgb.length);
							rgb = rgb.substring(0, rgb.length - 1);
							doc.setTextColor(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]));

						} else if (detail[0].replace(/^\s+|\s+$/g, '') === "text-align") {
							//var alg = detail[1].replace(/^\s+|\s+$/g, '');
							//cellObject.vAlign = alg;
							IsTextAlignRight = (detail[1].replace(/^\s+|\s+$/g, '') == "right")
						} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-style") {
							doc.setFontStyle('italic')
						} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-weight") {
							if (detail[1].replace(/^\s+|\s+$/g, '') === "bold") {
								doc.setFontStyle('bold')
							}
						} else if (detail[0].replace(/^\s+|\s+$/g, '') === "background-color") {
							var rgb = detail[1].replace(/^\s+|\s+$/g, '');
							rgb = rgb.substring(4, rgb.length);
							rgb = rgb.substring(0, rgb.length - 1);
							doc.setFillColor(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]));
							//doc.setDrawColor( parseInt(rgb.split(",")[0]) , parseInt(rgb.split(",")[1]) , parseInt(rgb.split(",")[2]) );
							hasBackground = true;
						} else if (detail[0].replace(/^\s+|\s+$/g, '') === "border-color") {
							var rgb = detail[1].replace(/^\s+|\s+$/g, '');
							rgb = rgb.substring(4, rgb.length);
							rgb = rgb.substring(0, rgb.length - 1);

							doc.setDrawColor(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]));
						}

					}
				}


				var imgTxtData = []
				var lastTxt = "", posInitLastTxt = -1
				var previousCharCode = 0
				if (childText.charCodeAt(0) > 1000) {
					for (var cNo = 0; cNo < childText.length; cNo++) {
						if (((previousCharCode == 58) || (previousCharCode == 65306)) && (childText.charCodeAt(cNo) == 32)) {
							imgTxtData[cNo] = "ToDelete"
						} else {
							imgTxtData[cNo] = OAT.getCharacterImg(childText.charCodeAt(cNo))
							previousCharCode = childText.charCodeAt(cNo)
						}
						if (childText.charCodeAt(cNo) < 1000) {
							lastTxt = lastTxt + childText[cNo]
							if (posInitLastTxt == -1) posInitLastTxt = cNo;
						} else {
							lastTxt = ""
							posInitLastTxt = -1
						}
					}
				} else {
					var posI = -1;
					//cNo = 0;
					for (var p = 1; p < childText.length; p++) {
						if (childText.charCodeAt(p) > 1000) {
							posI = p;
							break;
						}
					}
					if (posI > 0) {
						var tempchildText = childText.substring(0, posI);
						var posE = 0
						for (var cNo = posI; cNo < childText.length; cNo++) {
							if (childText.charCodeAt(cNo) < 1000) {
								lastTxt = lastTxt + childText[cNo]
								if (posInitLastTxt == -1) posInitLastTxt = cNo - posI;
							} else {
								lastTxt = ""
								posInitLastTxt = -1
							}
							if (((previousCharCode == 58) || (previousCharCode == 65306)) && (childText.charCodeAt(cNo) == 32)) {
								imgTxtData[posE] = "ToDelete"
							} else {
								imgTxtData[posE] = OAT.getCharacterImg(childText.charCodeAt(cNo))
								previousCharCode = childText.charCodeAt(cNo)
							}
							posE++;
						}
						childText = tempchildText;
					}
				}
				try {
					if ((posInitLastTxt != -1) && (!IsTextAlignRight)) {
						imgTxtData = imgTxtData.slice(0, posInitLastTxt);
					}
				} catch (Error) { }

				while ((imgTxtData.length > 0) && (imgTxtData.indexOf("ToDelete") != -1)) {
					var indexTDel = imgTxtData.indexOf("ToDelete")
					imgTxtData.splice(indexTDel, 1);
				}

				if ((hidden === null) && (!ignore)) {

					colspan++;
					var row = tRow.children[j].getAttribute('rowspan');
					var col = tRow.children[j].getAttribute('colspan');
					jR = jR + 1;
					if (row && ((y + parseInt(row)) > 26)) { //si excedo a la hoja
						var exceso = y + parseInt(row) - 26
						row = parseInt(row) - exceso
						spanSobrantes[jR + desp] = exceso
					}
					/*for very long text*/
					var colN = 1;
					if (col != null) colN = parseInt(col);
					if ((j === tRow.children.length - 1) && (colN === 3) && (self.colConditions.length == 0)) colN = 1;
					var textinic = null; var textend = null;
					/*if (childText.length > 22*colN){
						doc.setFontSize(6);
						textinic = childText.substring(0,21);
						textend  = childText.substring(21,childText.length);
					}*/

					var oldCol = colspan;
					if (((row === null) && (col === null)) || ((j === tRow.children.length - 1) && (col === '3') && (self.colConditions.length == 0))) {

						if (hasBackground) {
							var preColsPan = colspan;
							if ((col != null) && (childText === "")) {
								preColsPan = parseInt(col) + colspan - 1;
							}

							doc.rect(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, getXOffset(preColsPan + 1, columnsWidth) - getXOffset(oldCol, columnsWidth), 10, 'F');
						}

						var preImage = 0;
						if (childText.charCodeAt(0) < 1000) {
							preImage = childText.length * 1.4 + 2
							if (IsTextAlignRight) {
								doc.text(tablemarginleft + getXOffset(colspan + 1, columnsWidth) - textWidht * 3 - 4, tablemargintop + y * 10, childText);
							} else {
								doc.text(tablemarginleft + getXOffset(colspan, columnsWidth), tablemargintop + y * 10, childText);
							}
						}
						if (imgTxtData.length > 0) {
							for (var cNo = 0; cNo < imgTxtData.length; cNo++) {
								doc.addImage(imgTxtData[cNo], 'JPEG', tablemarginleft + getXOffset(colspan, columnsWidth) + preImage + cNo * 2.5, tablemargintop + y * 10 - 2.3, 2.5, 2.5);
							}
						}

						if ((posInitLastTxt != -1) && (!IsTextAlignRight)) { //add last text
							doc.text(tablemarginleft + getXOffset(colspan, columnsWidth) + preImage + imgTxtData.length * 2.5, tablemargintop + y * 10, lastTxt);
						}

						if ((col != null) && (childText === "")) {
							colspan = parseInt(col) + colspan - 1;
						}
						//draw rectangle border
						doc.line(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset((colspan + 1), columnsWidth), tablemargintop + y * 10 - 7); //top border
						doc.line(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 + 3); //left border

					} else if (col === null) {

						if (hasBackground) {
							if (row === null) {
								doc.rect(tablemarginleft - 2 + getXOffset(colspan, columnsWidth), tablemargintop + y * 10 - 7, cellwidth, 10, 'F');
							} else {
								doc.rect(tablemarginleft - 2 + getXOffset(colspan, columnsWidth), tablemargintop + y * 10 - 7, cellwidth, 10 + (parseInt(row) - 1) * 10, 'F');
							}
						}
						var preImage = 0;
						if (childText.charCodeAt(0) < 1000) {
							preImage = childText.length * 1.4 + 2
							doc.text(tablemarginleft + getXOffset(colspan, columnsWidth), tablemargintop + y * 10, childText);

						}
						if (imgTxtData.length > 0) {
							for (var cNo = 0; cNo < imgTxtData.length; cNo++) {
								doc.addImage(imgTxtData[cNo], 'JPEG', tablemarginleft + getXOffset(colspan, columnsWidth) + preImage + cNo * 2.5, tablemargintop + y * 10 - 2.3, 2.5, 2.5);
							}
						}

						if ((posInitLastTxt != -1) && (!IsTextAlignRight)) { //add last text
							doc.text(tablemarginleft + getXOffset(colspan, columnsWidth) + preImage + imgTxtData.length * 2.5, tablemargintop + y * 10, lastTxt);
						}

						doc.line(tablemarginleft - 2 + getXOffset(colspan, columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset((colspan + 1), columnsWidth), tablemargintop + y * 10 - 7); //top border
						if (row === null) {
							doc.line(tablemarginleft - 2 + getXOffset(colspan, columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset(colspan, columnsWidth), tablemargintop + y * 10 + 3); //left border
						} else {
							doc.line(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + (y + parseInt(row) - 1) * 10 + 3); //left border
						}
					} else if (row === null) {

						if (hasBackground) {
							var prevColsSpan = parseInt(col) + colspan - 1;
							doc.rect(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, getXOffset((prevColsSpan + 1), columnsWidth) - getXOffset(oldCol, columnsWidth), 10, 'F');
						}
						var preImage = 0;
						if (childText.charCodeAt(0) < 1000) {
							preImage = childText.length * 1.4 + 2
							doc.text(tablemarginleft + getXOffset(colspan, columnsWidth), tablemargintop + y * 10, childText);

						}
						if (imgTxtData.length > 0) {
							for (var cNo = 0; cNo < imgTxtData.length; cNo++) {
								doc.addImage(imgTxtData[cNo], 'JPEG', tablemarginleft + getXOffset(colspan, columnsWidth) + preImage + cNo * 2.5, tablemargintop + y * 10 - 2.3, 2.5, 2.5);
							}
						}

						if ((posInitLastTxt != -1) && (!IsTextAlignRight)) { //add last text
							doc.text(tablemarginleft + getXOffset(colspan, columnsWidth) + preImage + imgTxtData.length * 2.5, tablemargintop + y * 10, lastTxt);
						}

						colspan = parseInt(col) + colspan - 1;

						doc.line(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset((colspan + 1), columnsWidth), tablemargintop + y * 10 - 7); //top border
						doc.line(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 + 3); //left border
					} else {
						if (hasBackground) {
							var prevColsSpan = parseInt(col) + colspan - 1;
							if (row === null) {
								doc.rect(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, getXOffset((prevColsSpan + 1), columnsWidth) - getXOffset(oldCol, columnsWidth), 10, 'F');
							} else {
								doc.rect(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, getXOffset((prevColsSpan + 1), columnsWidth) - getXOffset(oldCol, columnsWidth), (parseInt(row) - 1) * 10, 'F');
							}
						}
						var preImage = 0;
						if (childText.charCodeAt(0) < 1000) {
							preImage = childText.length * 1.4 + 2
							doc.text(tablemarginleft /*- 2*/ + getXOffset(colspan, columnsWidth), tablemargintop + y * 10, childText);
						}
						if (imgTxtData.length > 0) {
							for (var cNo = 0; cNo < imgTxtData.length; cNo++) {
								doc.addImage(imgTxtData[cNo], 'JPEG', tablemarginleft /*- 2*/ + getXOffset(colspan, columnsWidth) + preImage + cNo * 2.5, tablemargintop + y * 10 - 2.3, 2.5, 2.5);
							}
						}

						if ((posInitLastTxt != -1) && (!IsTextAlignRight)) { //add last text
							doc.text(tablemarginleft /*- 2*/ + getXOffset(colspan, columnsWidth) + preImage + imgTxtData.length * 2.5, tablemargintop + y * 10, lastTxt);
						}

						colspan = parseInt(col) + colspan - 1;

						doc.line(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset((colspan + 1), columnsWidth), tablemargintop + y * 10 - 7); //top border
						if (row === null) {
							doc.line(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 + 3); //left border
						} else {
							doc.line(tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset(oldCol, columnsWidth), tablemargintop + (y + parseInt(row) - 1) * 10 + 3); //left border
						}
					}
				}

				doc.setFontSize(8);

				totalColSpan = colspan;
				//last right border
				if (j === tRow.children.length - 1) {
					doc.line(tablemarginleft - 2 + getXOffset((colspan + 1), columnsWidth), tablemargintop + y * 10 - 7, tablemarginleft - 2 + getXOffset((colspan + 1), columnsWidth), tablemargintop + y * 10 + 3);
				}

			}
			if (y >= 25) {
				doc.setDrawColor(0, 0, 0)
				//bottom last line
				doc.line(tablemarginleft - 2, tablemargintop + (y + 1) * 10 - 7, tablemarginleft - 2 + getXOffset((totalColSpan + 1), columnsWidth), tablemargintop + (y + 1) * 10 - 7);
				y = 0
				doc.addPage()
				//add sobrantes
				for (var t = 0; t < spanSobrantes.length; t++) {
					if (!isNaN(spanSobrantes[t])) {
						if (spanSobrantes[t] >= 25) {
							spanSobrantes[t] = spanSobrantes[t] - 25
							doc.line(tablemarginleft - 2 + getXOffset(t, columnsWidth), tablemargintop + (1) * 10 - 7, tablemarginleft - 2 + getXOffset((t + 1), columnsWidth), tablemargintop + (1) * 10 - 7); //top border
							doc.line(tablemarginleft - 2 + getXOffset(t, columnsWidth), tablemargintop + (1) * 10 - 7, tablemarginleft - 2 + getXOffset(t, columnsWidth), tablemargintop + ((1) + 25 - 1) * 10 + 3); //left border
						} else {
							doc.line(tablemarginleft - 2 + getXOffset(t, columnsWidth), tablemargintop + (1) * 10 - 7, tablemarginleft - 2 + getXOffset((t + 1), columnsWidth), tablemargintop + (1) * 10 - 7); //top border
							doc.line(tablemarginleft - 2 + getXOffset(t, columnsWidth), tablemargintop + (1) * 10 - 7, tablemarginleft - 2 + getXOffset(t, columnsWidth), tablemargintop + ((1) + spanSobrantes[t] - 1) * 10 + 3); //left border
							spanSobrantes[t] = 0
						}
					}
				}
				//spanSobrantes = [] 
			}

		}
		doc.setDrawColor(0, 0, 0)
		//bottom last line
		doc.line(tablemarginleft - 2, tablemargintop + (y + 1) * 10 - 7, tablemarginleft - 2 + getXOffset((totalColSpan + 1), columnsWidth), tablemargintop + (y + 1) * 10 - 7);

		if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari
			doc.output('dataurlnewwindow');
		} else if (!gx.util.browser.isIE() || (9 < gx.util.browser.ieVersion())) {
			doc.save(fileName + '.pdf');
		} else {
			return doc.output();
		}


	}

	removeComas = function (value, self) { //TODO: also remove $ and none digital or . characters
		var newValue = ""; actPos = 0;

		var decimalSeparator = self.defaultPicture.getAttribute("decimalSeparator");

		for (var poVal = 0; poVal < value.length; poVal++) {
			if ((value[poVal] == "0") || (value[poVal] == "1") || (value[poVal] == "2")
				|| (value[poVal] == "3") || (value[poVal] == "4") || (value[poVal] == "5")
				|| (value[poVal] == "6") || (value[poVal] == "7") || (value[poVal] == "8")
				|| (value[poVal] == "9") || (value[poVal] == decimalSeparator/*"."*/) || (value[poVal] == "-")) {
				newValue = newValue + value[poVal];
			}
		}

		if (decimalSeparator != ".") {
			var tempValue = "";
			for (var poVal = 0; poVal < newValue.length; poVal++) {
				if (newValue[poVal] == decimalSeparator) {
					tempValue = tempValue + '.';
				} else {
					tempValue = tempValue + newValue[poVal];
				}
			}
			newValue = tempValue;
		}
		//while (value.indexOf(",") != -1){
		//	value = value.slice(0, value.indexOf(",")) + value.slice(value.indexOf(",")+1); 
		//}
		return newValue;
	}
	
	
	cleanDistinctValue = function (value, self, ind) {
		if (value == "#NuN#") {
			return " ";
		} else {
			var replaceAmp = true;
			if (value.indexOf(">") > -1) {
				value = value.replace(/\>/g,"&lt;")
				replaceAmp = false
			} 
			if (value.indexOf("<") > -1) {
				value = value.replace(/\</g,"&gt;")
				replaceAmp = false
			}
			
			if ((value.indexOf("%") > -1) && (ind != undefined)) {
				return value.replace(/\&/g, "&amp;").replace(/"/g, "&quot;").replace(/\%/g, "%" + ind).trimpivot() 
			} else {
				value = value.replace(/"/g, "&quot;")
				if (replaceAmp){
					value = value.replace(/\&/g, "&amp;")
				}
				
				if (value.indexOf("&amp;lt;") > -1){
					value = value.replace(/\&amp\;lt\;/g, "&lt;")
				}
				
				return value.trimpivot()
				
			}
		}
	}
	
	var headers = [];
	getMeasureTitle = function(value, pos){
		if (headers[pos] != undefined)
		{
			return headers[pos]
		} 
		else
		{
			return value
		}
	}
	
	createExcelROWITEMS = function (item, level, pfvi, lastRowLevel, originalLevel) {
		if (level === 0) {
			var index = pfvi[lastRowLevel].indexOf(item.value);
			var rs = ""
			if (originalLevel === 0) {
				rs = "<i>"
			} else {
				rs = "<i r=\"" + originalLevel + "\">";
			}
			if (index > 0) {
				return rs + "<x v=\"" + index + "\"/></i>";
			} else {
				return rs + "<x/></i>";
			}
		} else {
			level--;
			var str = ""
			for (var i = 0; i < item.items.length; i++) {
				str = str + createExcelROWITEMS(item.items[i], level, pfvi, lastRowLevel, originalLevel);
			}
			return str;
		}
	}

	createExcelCOLITEMS = function (item, level, pfvi, lastRowLevel, originalLevel) {
		if (level === 0) {
			var index = pfvi[lastRowLevel].indexOf(item.value.trimpivot());
			var rs = ""
			for (var iCV = 0; iCV < measures.length; iCV++) {
				if (originalLevel === 0) {
					rs = "<i>"
				} else {
					rs = "<i r=\"" + originalLevel + "\">";
				}
				//if (index > 0){
				rs = rs + "<x v=\"" + index + "\"/>";
				//} else {
				//	rs =  rs +"<x/></i>";
				//}
				if (measures.length > 1) {
					rs = rs + "<x/>";
				}
				rs = rs + "</i>";
			}
			return rs;
		} else {
			level--;
			var str = ""
			for (var i = 0; i < item.items.length; i++) {
				str = str + createExcelROWITEMS(item.items[i], level, pfvi, lastRowLevel, originalLevel);
			}
			return str;
		}
	}

	OAT.GenerateExcelOutput = function (fileName, self, measures) {
		function componentToHex(c) {
			var hex = c.toString(16);
			return hex.length == 1 ? "0" + hex : hex;
		}

		function rgbToHex(r, g, b) {
			return componentToHex(r) + componentToHex(g) + componentToHex(b);
		}

		function getStyles(attributes) {
			var styleObject = {};
			for (var at = 0; at < attributes.length; at++) {
				var detail = attributes[at].split(":");
				if (detail[0].replace(/^\s+|\s+$/g, '') === "color") {
					var rgb = detail[1].replace(/^\s+|\s+$/g, '');
					rgb = rgb.substring(4, rgb.length);
					rgb = rgb.substring(0, rgb.length - 1);
					var hex = rgbToHex(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]))
					styleObject.fontColor = hex;
				} else if (detail[0].replace(/^\s+|\s+$/g, '') === "text-align") {
					var alg = detail[1].replace(/^\s+|\s+$/g, '');
					styleObject.vAlign = alg;
				} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-style") {
					if (detail[1].replace(/^\s+|\s+$/g, '') === "italic") {
						styleObject.italic = 1;
					}
				} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-weight") {
					if (detail[1].replace(/^\s+|\s+$/g, '') === "bold") {
						styleObject.bold = 1;
					}
				} else if (detail[0].replace(/^\s+|\s+$/g, '') === "background-color") {
					var rgb = detail[1].replace(/^\s+|\s+$/g, '');
					rgb = rgb.substring(4, rgb.length);
					rgb = rgb.substring(0, rgb.length - 1);
					var hex = rgbToHex(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]))
					styleObject.fill = hex;
				}
			}
			return styleObject;
		}

		var getMeasureIdentifier = function (self, value) {
			for (var name in self.formulaInfo.itemPosition) {
				if (self.formulaInfo.itemPosition[name] == value) {
					return name;
				}
			}
		}

		//search repeat column header
		headers = []
		var previous = []
		for (var iCV = 0; iCV < measures.length; iCV++) {
			for(var pos = 0; pos < previous.length; pos++){
				if (previous[pos] == cleanDistinctValue(measures[iCV].getAttribute("displayName"), self, measures[iCV].getAttribute("name")))
				{
					headers[iCV] = 	cleanDistinctValue(measures[iCV].getAttribute("displayName"), self, measures[iCV].getAttribute("name")) + " (" + measures[iCV].getAttribute("dataField") + ")"
				}
			}
			previous.push(cleanDistinctValue(measures[iCV].getAttribute("displayName"), self, measures[iCV].getAttribute("name"))) 
		}
		//	

		dataTable = [];
		//headers
		dataRow = [];
		for (var col = 0; col < self.columns.length; col++) {
			var cellObject = { value: cleanDistinctValue(self.columns[col].getAttribute("displayName"), self, self.columns[col].getAttribute("name")) };
			cellObject.isString = 1;
			dataRow.push(cellObject)
		}
		for (var iCV = 0; iCV < measures.length; iCV++) {
			if (!self.formulaInfo.measureFormula[iCV].hasFormula) {
				var cellObject = { value: cleanDistinctValue( getMeasureTitle(measures[iCV].getAttribute("displayName"), iCV), self, measures[iCV].getAttribute("name")) };
				dataRow.push(cellObject)
			}
		}

		var formMeasures = [];
		if (self.formulaInfo.cantFormulaMeasures > 0) {
			for (var fI = 0; fI < self.formulaInfo.measureFormula.length; fI++) {
				if (self.formulaInfo.measureFormula[fI].hasFormula) {
					for (var mI = 0; mI < self.formulaInfo.measureFormula[fI].relatedMeasures.length; mI++) {
						var numMeasure = self.formulaInfo.measureFormula[fI].relatedMeasures[mI]
						if (formMeasures.indexOf(numMeasure) == -1) {
							formMeasures.push(numMeasure)
						}
					}
				}
			}
			formMeasures.sort();
			for (var iCV = 0; iCV < formMeasures.length; iCV++) {
				var cellObject = { value: getMeasureIdentifier(self, formMeasures[iCV]) };
				dataRow.push(cellObject)
			}
		}

		dataTable.push(dataRow);

		var dataToShow = self.GeneralDataRows//self.filteredData
		if (self.autoPaging) {
			dataToShow = self.RowsWhenMoveToFilter
		}
		if (self.formulaInfo.cantFormulaMeasures > 0) {
			dataToShow = self.recordForFormula
		}



		//values
		for (var rN = 0; rN < dataToShow.length; rN++) {
			dataRow = [];
			for (var col = 0; col < self.columns.length; col++) {
				//var pos = parseInt(this.columns[col].getAttribute("dataField").substring(1, this.columns[col].getAttribute("dataField").length)) -1;
				//if (isNaN(pos)){
				var pos = self.conditions[col].dataRowPosition
				//}
				var value = dataToShow[rN][pos];  //value is parse in PDJ.js
				if (value == "#NuN#") { value = " " }
				var cellObject = { value: value };
				cellObject.isString = 1;

				var th = OAT.Dom.create("th", {}, "");
				th = self.applyFormatValues(th, dataToShow[rN][pos], pos)
				if (th.getAttribute("style") != undefined) {
					var attributes = th.getAttribute("style").split(";");
					for (var at = 0; at < attributes.length; at++) {
						var detail = attributes[at].split(":");
						if (detail[0].replace(/^\s+|\s+$/g, '') === "color") {
							var rgb = detail[1].replace(/^\s+|\s+$/g, '');
							rgb = rgb.substring(4, rgb.length);
							rgb = rgb.substring(0, rgb.length - 1);
							var hex = rgbToHex(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]))
							cellObject.fontColor = hex;
						} else if (detail[0].replace(/^\s+|\s+$/g, '') === "text-align") {
							var alg = detail[1].replace(/^\s+|\s+$/g, '');
							cellObject.vAlign = alg;
						} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-style") {
							if (detail[1].replace(/^\s+|\s+$/g, '') === "italic") {
								cellObject.italic = 1;
							}
						} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-weight") {
							if (detail[1].replace(/^\s+|\s+$/g, '') === "bold") {
								cellObject.bold = 1;
							}
						} else if (detail[0].replace(/^\s+|\s+$/g, '') === "background-color") {
							var rgb = detail[1].replace(/^\s+|\s+$/g, '');
							rgb = rgb.substring(4, rgb.length);
							rgb = rgb.substring(0, rgb.length - 1);
							var hex = rgbToHex(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]))
							cellObject.fill = hex;
						}
					}
				}
				cellObject.genexusType = self.columns[col].getAttribute("dataType");
				cellObject.genexusPicture = self.columns[col].getAttribute("picture");
				dataRow.push(cellObject)
			}
			for (var iCV = 0; iCV < measures.length; iCV++) {
				if (!self.formulaInfo.measureFormula[iCV].hasFormula) {
					var pos = self.columns.length + iCV;

					var value = dataToShow[rN][pos];
					value = self.defaultPictureValue(value, (iCV == measures.length - 1), iCV)
					value = removeComas(value, self);
					var cellObject = { value: value };

					var td = OAT.Dom.create("td", {}, "");
					td = self.applyConditionalFormats(td, dataToShow[rN][pos], (iCV === (measures.length - 1)) ? true : false, iCV)
					if (td.getAttribute("style") != undefined) {
						var attributes = td.getAttribute("style").split(";");
						for (var at = 0; at < attributes.length; at++) {
							var detail = attributes[at].split(":");
							if (detail[0].replace(/^\s+|\s+$/g, '') === "color") {
								var rgb = detail[1].replace(/^\s+|\s+$/g, '');
								rgb = rgb.substring(4, rgb.length);
								rgb = rgb.substring(0, rgb.length - 1);
								var hex = rgbToHex(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]))
								cellObject.fontColor = hex;
							} else if (detail[0].replace(/^\s+|\s+$/g, '') === "text-align") {
								var alg = detail[1].replace(/^\s+|\s+$/g, '');
								cellObject.vAlign = alg;
							} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-style") {
								if (detail[1].replace(/^\s+|\s+$/g, '') === "italic") {
									cellObject.italic = 1;
								}
							} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-weight") {
								if (detail[1].replace(/^\s+|\s+$/g, '') === "bold") {
									cellObject.bold = 1;
								}
							} else if (detail[0].replace(/^\s+|\s+$/g, '') === "background-color") {
								var rgb = detail[1].replace(/^\s+|\s+$/g, '');
								rgb = rgb.substring(4, rgb.length);
								rgb = rgb.substring(0, rgb.length - 1);
								var hex = rgbToHex(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]))
								cellObject.fill = hex;
							}
						}
					}
					/*nuevo*/
					cellObject.genexusType = measures[iCV].getAttribute("dataType");
					cellObject.genexusPicture = measures[iCV].getAttribute("picture");
					dataRow.push(cellObject)
				}
			}

			for (var formItem = 0; formItem < formMeasures.length; formItem++) {
				dataRow.push({ value: dataToShow[rN][formMeasures[formItem]] })
			}
			
			
			
			dataTable.push(dataRow);
		}


		var stylesList = [];
		var columnWithStyle = [];
		var styleId = 1
		for (var col = 0; col < self.columns.length; col++) {
			columnWithStyle[col] = 0;
			var th = OAT.Dom.create("th", {}, "");
			//var pos = parseInt(this.columns[col].getAttribute("dataField").substring(1, this.columns[col].getAttribute("dataField").length)) -1;
			//if (isNaN(pos)){
			var pos = self.conditions[col].dataRowPosition
			//}
			th = self.applyFormatValues(th, dataToShow[0][pos], pos)

			if (th.getAttribute("style") != undefined) {
				var attributes = th.getAttribute("style").split(";");
				var styleObject = getStyles(attributes);
				if ((styleObject.fontColor != undefined) || (styleObject.italic != undefined) || (styleObject.bold != undefined)) {
					columnWithStyle[col] = styleId;
					styleId++;
					stylesList.push(styleObject);
				}
			}
		}

		var measuresWidthStyle = [];
		for (var ms = 0; ms < measures.length; ms++) {
			measuresWidthStyle[ms] = 0;
			var td = OAT.Dom.create("td", {}, "");
			//var pos = parseInt(measures[ms].getAttribute("dataField").substring(1, measures[ms].getAttribute("dataField").length /*- 1*/)) -1;
			//if (isNaN(pos)){
			var pos = self.columns.length + ms;
			//}
			td = self.applyConditionalFormats(td, dataToShow[0][pos], (ms === (measures.length - 1)) ? true : false, ms)

			if (td.getAttribute("style") != undefined) {
				var attributes = td.getAttribute("style").split(";");
				var styleObject = getStyles(attributes);
				if ((styleObject.fontColor != undefined) || (styleObject.italic != undefined) || (styleObject.bold != undefined)) {
					measuresWidthStyle[ms] = styleId;
					styleId++;
					stylesList.push(styleObject);
				}
			}
		}



		var withStyles = (stylesList.length > 0);
		var letras = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD'];
		var lastPos = letras[(measures.length + self.columns.length) - 1] + (dataToShow.length + 1 + 2);
		//xl/pivotTables/pivotTable1.xml string definition
		var firstDataRow = self.colConditions.length + 2;
		var firstDataCol = (((self.colConditions.length > 0)) ? self.colConditions.length : 1);

		var hasFormula = false;
		var totalsExportPivotPdfOptions = " ";
		for (var fIdx = 0; fIdx < self.formulaInfo.measureFormula.length; fIdx++) {
			if (self.formulaInfo.measureFormula[fIdx].hasFormula) {
				hasFormula = true;
			}
		} //rowGrandTotals="0" colGrandTotals="0"
		//if (hasFormula){
		//totalsExportPivotPdfOptions = 'rowGrandTotals="0" colGrandTotals="0"'
		//}

		var dataToShow = self.GeneralDataRows
		if (self.autoPaging) {
			dataToShow = self.RowsWhenMoveToFilter
		}

		var sheet;
		//--------------
		if (self.columns.length < 0) {

			var xlpivotTable1 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<pivotTableDefinition name="Tabla dinamica1" cacheId="5" dataCaption="' + gx.getMessage("GXPL_QViewerJSValue") + '" createdVersion="3" updatedVersion="3" minRefreshableVersion="3" applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" showCalcMbrs="0" useAutoFormatting="1" itemPrintTitles="1" indent="0" outline="1" outlineData="1" multipleFieldFilters="0" rowHeaderCaption="Make" ' + totalsExportPivotPdfOptions + 'xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">'
				+ "<location ref=\"A1:" + lastPos + "\" firstHeaderRow=\"1\" firstDataRow=\"" + firstDataRow + "\" firstDataCol=\"" + firstDataCol + "\"/>"
				+ "<pivotFields>"
			var pfi = [];
			var pfvi = [];
			var pfviExclude = [];

			var rowLevel = -1;
			var lastRowLevel = 0;
			var colLevel = -1;
			var lastColLevel = 0;
			for (var iCV = 0; iCV < self.columns.length; iCV++) {

				var position = 'axisRow';
				if (self.rowConditions.findIndex(iCV) != -1) {
					position = 'axisRow';
					rowLevel++;
					lastRowLevel = iCV;
				} else if (self.colConditions.findIndex(iCV) != -1) {
					position = 'axisCol';
					colLevel++;
					lastColLevel = iCV;
				} else {
					position = 'axisRow';
					rowLevel++;
					lastRowLevel = iCV;
				}

				var formulaOptionString = '';
				var formulaItemString = "<item t=\"default\"/>"
				//if (hasFormula){
				//formulaOptionString = 'defaultSubtotal=\"0\"'
				//formulaItemString = ""
				//}  
				xlpivotTable1 = xlpivotTable1 + "<pivotField axis=\"" + position + "\" showAll=\"0\" " + formulaOptionString + ">" + //numFmtId=\"" + 163 + "\"
					"<items>"
				var pfvl; var pfvlExclude;
				if (self.conditions[iCV].distinctValues != undefined) {
					pfvl = []; pfvlExclude = [];
					for (var val = 0; val < self.conditions[iCV].distinctValues.length; val++) {
						//pfvl.push(self.conditions[iCV].distinctValues[val].replace(/\&/g, "&amp;").replace(/"/g, "&quot;"));
						pfvl.push(cleanDistinctValue(self.conditions[iCV].distinctValues[val], self));
						var hiddenString = "";
						if (self.conditions[iCV].blackList.findIndex(self.conditions[iCV].distinctValues[val]) != -1) {
							hiddenString = " h=\"1\"";
							pfvlExclude.push(cleanDistinctValue(self.conditions[iCV].distinctValues[val], self));
						}
						xlpivotTable1 = xlpivotTable1 + "<item x=\"" + val + "\" " + hiddenString + " />";
					}
					xlpivotTable1 = xlpivotTable1 + formulaItemString//"<item t=\"default\"/>"
						+ "</items>"
						+ "</pivotField>";
				}
				pfvi[iCV] = pfvl;
				pfviExclude[iCV] = pfvlExclude[iCV]
				pfi.push(iCV);
			}

			for (var iCV = 0; iCV < measures.length; iCV++) {
				xlpivotTable1 = xlpivotTable1 + "<pivotField dataField=\"1\" showAll=\"0\"/>"; //numFmtId=\"" + 163 + "\"
				pfi.push(cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"), iCV), self, measures[iCV].getAttribute("name")));
			}

			xlpivotTable1 = xlpivotTable1 + "</pivotFields>"
			xlpivotTable1 = xlpivotTable1 + "<rowFields>"
			for (var iCV = 0; iCV < self.columns.length; iCV++) {
				if ((self.rowConditions.findIndex(iCV) != -1) || (self.filterIndexes.findIndex(iCV) != -1)) {
					xlpivotTable1 = xlpivotTable1 + "<field x=\"" + 0 + "\"/>";
				}
			}
			xlpivotTable1 = xlpivotTable1 + "</rowFields>"

			xlpivotTable1 = xlpivotTable1 + "<rowItems>"
			for (var it = 0; it < self.rowStructure.items.length; it++) {
				xlpivotTable1 = xlpivotTable1 + createExcelROWITEMS(self.rowStructure.items[it], rowLevel, pfvi, lastRowLevel, rowLevel)
			}
			xlpivotTable1 = xlpivotTable1 + "<i t=\"grand\"><x/></i>"
				+ "</rowItems>"

			if ((((colLevel > -1)) || ((measures.length > 1)))) {
				xlpivotTable1 = xlpivotTable1 + "<colFields>"

				for (var iCV = 0; iCV < self.columns.length; iCV++) {
					if (self.colConditions.findIndex(iCV) != -1) {
						var pos = pfi.indexOf(iCV);
						xlpivotTable1 = xlpivotTable1 + "<field x=\"" + pos + "\"/>";
					}
				}
				if (measures.length > 1) {
					xlpivotTable1 = xlpivotTable1 + "<field x=\"-2\"/>";
				};

				xlpivotTable1 = xlpivotTable1 + "</colFields>"
			}

			//col items
			xlpivotTable1 = xlpivotTable1 + "<colItems>"
			if (self.colStructure.items) {
				for (var it = 0; it < self.colStructure.items.length; it++) {
					xlpivotTable1 = xlpivotTable1 + createExcelCOLITEMS(self.colStructure.items[it], colLevel, pfvi, lastColLevel, colLevel)
				}
			} else {
				for (var iCV = 0; iCV < measures.length; iCV++) {
					xlpivotTable1 = xlpivotTable1 + '<i/>';
				}
			}
			xlpivotTable1 = xlpivotTable1 + "</colItems>"

			xlpivotTable1 = xlpivotTable1 + "<dataFields>"
			for (var iCV = 0; iCV < measures.length; iCV++) {
				xlpivotTable1 = xlpivotTable1 + "<dataField name=\"" + cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"), iCV), self, measures[iCV].getAttribute("name")) + "\" fld=\"" + (iCV + self.columns.length) + "\"/>" //\" subtotal=\"sum\" numFmtId=\"163\"		
			}

			xlpivotTable1 = xlpivotTable1 + "</dataFields>"


			if (withStyles) {
				xlpivotTable1 = xlpivotTable1 + '<formats>'
				//format for columns
				for (var iCV = 0; iCV < self.columns.length; iCV++) {
					if (columnWithStyle[iCV] > 0) {
						xlpivotTable1 = xlpivotTable1 + '<format dxfId="' + columnWithStyle[iCV] + '">' + '<pivotArea dataOnly="0" labelOnly="1" fieldPosition="0">' + '<references ><reference field="0">'

						if (self.conditions[iCV].distinctValues != undefined) {
							for (var val = 0; val < self.conditions[iCV].distinctValues.length; val++) {
								xlpivotTable1 = xlpivotTable1 + '<x v="' + val + '"/>';
							}
						}
						xlpivotTable1 = xlpivotTable1 + '</reference></references>' + '</pivotArea>' + '</format>'
					}
				}

				for (var it = 0; it < measures.length; it++) {
					if (measuresWidthStyle[it] > 0) {
						xlpivotTable1 = xlpivotTable1 + '<format dxfId="' + measuresWidthStyle[it] + '">'
						xlpivotTable1 = xlpivotTable1 + '<pivotArea  fieldPosition="0">'
						xlpivotTable1 = xlpivotTable1 + '<references>'
						xlpivotTable1 = xlpivotTable1 + '<reference field="4294967294" selected="0">'
						xlpivotTable1 = xlpivotTable1 + '<x v="' + it + '"/></reference>'
						xlpivotTable1 = xlpivotTable1 + '<reference field="0">'
						for (var p = 0; p < self.rowStructure.items.length; p++) {
							xlpivotTable1 = xlpivotTable1 + '<x v="' + p + '"/>'
						}
						xlpivotTable1 = xlpivotTable1 + '</reference>'
						xlpivotTable1 = xlpivotTable1 + '</references></pivotArea>'
						xlpivotTable1 = xlpivotTable1 + '</format>'
					}
				}
				xlpivotTable1 = xlpivotTable1 + '</formats>'
			}

			xlpivotTable1 = xlpivotTable1 + "<pivotTableStyleInfo name=\"PivotStyleLight16\" showRowHeaders=\"1\" showColHeaders=\"1\" showRowStripes=\"0\" showColStripes=\"0\" showLastColumn=\"1\"/>"
				+ "</pivotTableDefinition>"

			var xlstyle = '<dxf><font><color rgb="FFCCCCCC" /></font></dxf>';
			if (withStyles) {
				for (var s = 0; s < stylesList.length; s++) {
					xlstyle = xlstyle + '<dxf><font>'
					if (stylesList[s].bold != undefined) {
						xlstyle = xlstyle + '<b/>'
					}
					if (stylesList[s].italic != undefined) {
						xlstyle = xlstyle + '<i/>'
					}
					if (stylesList[s].fontColor != undefined) {
						xlstyle = xlstyle + '<color rgb="FF' + stylesList[s].fontColor + '"/>'
					}
					xlstyle = xlstyle + '</font></dxf>';
				}
			}
			var dfxStr = xlstyle;
			//xl/pivotCache/cacheRecords
			var cacheRecords = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<pivotCacheRecords xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
			for (var rN = 0; rN < dataToShow.length; rN++) {
				cacheRecords = cacheRecords + "<r>"

				for (var col = 0; col < self.columns.length; col++) {
					var vvalue = pfvi[col].indexOf(dataToShow[rN][col])
					cacheRecords = cacheRecords + '<x v="' + vvalue + '"/>'
				}

				for (var iCV = 0; iCV < measures.length; iCV++) {
					var pos = self.columns.length + iCV;
					var value = self.defaultPictureValue(dataToShow[rN][pos], (iCV == measures.length - 1), iCV)
					value = removeComas(value, self);
					value = cleanDistinctValue(value, self)
					//value.replace(/\&/g, "&amp;").replace(/"/g, "&quot;")
					cacheRecords = cacheRecords + '<n v=\"' + value + '"/>';
				}
				cacheRecords = cacheRecords + "</r>"
			}
			cacheRecords = cacheRecords + '</pivotCacheRecords>';


			//xl/pivotCache/cacheDefinition
			var cacheDefinition = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<pivotCacheDefinition r:id="rId1" refreshOnLoad="1" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
				+ '<cacheSource type="worksheet">'

			cacheDefinition = cacheDefinition + '<worksheetSource ref="A1:' + letras[self.columns.length + measures.length - 1] + (dataToShow.length + 1) + '" sheet="SourceData"/>'
			cacheDefinition = cacheDefinition + '</cacheSource>'
			cacheDefinition = cacheDefinition + '<cacheFields count="' + (self.columns.length + measures.length) + '">'
			for (var col = 0; col < self.columns.length; col++) {
				cacheDefinition = cacheDefinition + '<cacheField name="' + cleanDistinctValue(self.columns[col].getAttribute("displayName"), self, self.columns[col].getAttribute("name")).replace(/</g, '&lt;').replace(/>/g, '&gt;') + '" numFmtId="0">'
				cacheDefinition = cacheDefinition + '<sharedItems count="' + self.conditions[col].distinctValues.length + '">'
				for (var val = 0; val < self.conditions[col].distinctValues.length; val++) {
					cacheDefinition = cacheDefinition + '<s v="' + cleanDistinctValue(self.conditions[col].distinctValues[val], self)/*self.conditions[col].distinctValues[val].replace(/\&/g, "&amp;").replace(/"/g, "&quot;")*/ + '"/>';
				}
				cacheDefinition = cacheDefinition + '</sharedItems>'
				cacheDefinition = cacheDefinition + '</cacheField>'
			}
			for (var iCV = 0; iCV < measures.length; iCV++) {
				cacheDefinition = cacheDefinition + '<cacheField name="' + cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"),iCV), self, measures[iCV].getAttribute("name")) + '" numFmtId="0">'
				cacheDefinition = cacheDefinition + '<sharedItems/>'
				cacheDefinition = cacheDefinition + '</cacheField>'
			}
			cacheDefinition = cacheDefinition + '</cacheFields>'
			cacheDefinition = cacheDefinition + '</pivotCacheDefinition>'

			//xl - woorksheet - sheet2
			var sheet2 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
				+ '<dimension ref="A1:' + letras[self.columns.length + measures.length - 1] + (dataToShow.length + 1) + '"/>'
				+ '<sheetViews>'
				+ '<sheetView workbookViewId="0"/>'
				+ '</sheetViews>'
				+ '<sheetData>'
			var rowNumber = 1;
			var colNumber = 0;
			//headers
			sheet2 = sheet2 + '<row r="' + rowNumber + '" span="1:3">'
			for (var col = 0; col < self.columns.length; col++) {
				sheet2 = sheet2 + '<c t="inlineStr" r="' + letras[colNumber] + rowNumber + '">'
				sheet2 = sheet2 + '<is><t>' + cleanDistinctValue(self.columns[col].getAttribute("displayName"), self, self.columns[col].getAttribute("name")) + '</t></is>'
				sheet2 = sheet2 + '</c>'
				colNumber++;
			}
			for (var iCV = 0; iCV < measures.length; iCV++) {
				sheet2 = sheet2 + '<c t="inlineStr" r="' + letras[colNumber] + rowNumber + '">'
				sheet2 = sheet2 + '<is><t>' + cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"),iCV), self, measures[iCV].getAttribute("name")) + '</t></is>'
				sheet2 = sheet2 + '</c>'
				colNumber++;
			}
			sheet2 = sheet2 + '</row>'

			for (var rN = 0; rN < dataToShow.length; rN++) {
				colNumber = 0;
				rowNumber++;
				sheet2 = sheet2 + '<row r="' + rowNumber + '" span="1:3">'
				for (var col = 0; col < self.columns.length; col++) {
					var pos = self.conditions[col].dataRowPosition
					var value = cleanDistinctValue(dataToShow[rN][pos], self)

					sheet2 = sheet2 + '<c t="inlineStr" r="' + letras[colNumber] + rowNumber + '">'
					sheet2 = sheet2 + '<is><t>' + value + '</t></is>'
					sheet2 = sheet2 + '</c>'
					colNumber++;
				}

				for (var iCV = 0; iCV < measures.length; iCV++) {
					pos = self.columns.length + iCV;
					var value = self.defaultPictureValue(dataToShow[rN][pos], (iCV == measures.length - 1), iCV)
					value = removeComas(value, self);
					value = cleanDistinctValue(value);
					if ((measures[iCV].getAttribute('dataType') === "real") || (measures[iCV].getAttribute('dataType') === "integer")) {
						sheet2 = sheet2 + '<c r="' + letras[colNumber] + rowNumber + '">'
						sheet2 = sheet2 + '<v>' + value + '</v>'
						sheet2 = sheet2 + '</c>'
					} else {
						sheet2 = sheet2 + '<c t="inlineStr" r="' + letras[colNumber] + rowNumber + '">'
						sheet2 = sheet2 + '<is><t>' + value + '</t></is>'
						sheet2 = sheet2 + '</c>'
					}
					colNumber++;
				}
				sheet2 = sheet2 + '</row>'
			}

			sheet2 = sheet2 + '</sheetData>'
			sheet2 = sheet2 + '</worksheet>'

			sheet = xlsx({
				creator: 'Genexus',
				lastModifiedBy: 'Genexus',
				pivot: true,
				pivotCacheDefinition: cacheDefinition,
				pivotTable1: xlpivotTable1,
				Sheet2: sheet2,
				style: xlstyle,
				dfx: dfxStr,
				worksheets: [{
					data: dataTable,
					name: 'Sheet 1'
				}]
			});

			if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari
				window.location = sheet.href();
			} else if (!gx.util.browser.isIE() || (9 < gx.util.browser.ieVersion())) {
				//window.location = sheet.href();
				var byteCharacters = atob(sheet.base64);
				function charCodeFromCharacter(c) {
					return c.charCodeAt(0);
				}

				var byteNumbers = Array.prototype.map.call(byteCharacters, charCodeFromCharacter);
				var uint8Data = new Uint8Array(byteNumbers);

				var blob = new Blob([uint8Data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
				saveAs(blob, fileName + ".xlsx");
			} else {
				return sheet.base64;
			}
			/*if (!gx.util.browser.isIE()){
				window.location = sheet.href();
			} else {
				return sheet.base64; //sheet.base64;		
			}*/

		} else {

			//xl/pivotTables/pivotTable1.xml string definition
			var firstDataRow = self.colConditions.length + 1;
			var firstDataCol = (((self.colConditions.length > 0)) ? self.colConditions.length : 1);
			if ((self.filterIndexes.length > 0) && (self.rowConditions.length + 1 == measures.length)) {
				firstDataCol = 0;
			}

			if ((self.rowConditions.length + self.filterIndexes.length) == 0) {
				firstDataRow = 1;
				firstDataCol = 1;
			}

			var varRef = "1"
			var pageInfo = ""
			if (self.filterIndexes.length > 0) {
				firstDataRow = firstDataRow + self.filterIndexes.length;
				pageInfo = " rowPageCount=\"" + self.filterIndexes.length + "'\" colPageCount=\"1\" "
				varRef = firstDataRow + 1
			}

			var rowLabel = "";
			if (self.rowConditions.length > 0) {
				var firstRow = self.rowConditions[0]
				if (self.columns.length > firstRow) {
					rowLabel = ' rowHeaderCaption="' + cleanDistinctValue(self.columns[firstRow].getAttribute("displayName"), self, self.columns[firstRow].getAttribute("name")) + '" ';
				}
			}
			if (self.colConditions.length > 0) {
				var firstCol = self.colConditions[0]
				if (self.columns.length > firstCol) {
					rowLabel = rowLabel + ' colHeaderCaption="' + cleanDistinctValue(self.columns[firstCol].getAttribute("displayName"), self, self.columns[firstCol].getAttribute("name")) + '" ';
				}
			}
			var xlpivotTable1 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'
				+ '<pivotTableDefinition name="Tabla dinamica1" cacheId="5" dataCaption="' + gx.getMessage("GXPL_QViewerJSValue") + '" createdVersion="3" updatedVersion="3" minRefreshableVersion="3" applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" showCalcMbrs="0" useAutoFormatting="1" itemPrintTitles="1" indent="0" outline="1" outlineData="1" multipleFieldFilters="0" '
				//+' rowHeaderCaption="' + rowLabel + '" ' + totalsExportPivotPdfOptions + ' xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">\n'
				+ rowLabel + ' ' + totalsExportPivotPdfOptions + ' xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">\n'
				+ "<location "
				+ "ref=\"A" + varRef + "\""//ref=\"A1\"' 
				+ " firstHeaderRow=\"1\" firstDataRow=\"" + firstDataRow + "\" firstDataCol=\"" + firstDataCol + "\" "
				+ pageInfo
				+ "/>\n"
				+ "<pivotFields>\n"
			var pfi = [];
			var pfvi = [];
			var pfviExclude = [];

			if (self.formulaInfo.cantFormulaMeasures == 0) {
				for (var iCV = 0; iCV < measures.length; iCV++) {
					var numFmt = 163
					if (measures[iCV].getAttribute('picture') != "") {
						numFmt = 164 + iCV
					}
					xlpivotTable1 = xlpivotTable1 + "<pivotField dataField=\"1\" showAll=\"0\"  numFmtId=\"" + numFmt + "\"/>\n";

					pfi.push(cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"), iCV), self, measures[iCV].getAttribute("name")));
				}
			}

			var rowLevel = -1;
			var lastRowLevel = 0;
			var colLevel = -1;
			var lastColLevel = 0;

			
			for (var filter = 0; filter < self.filterIndexes.length; filter++) {
				var iCV = self.filterIndexes[filter];

				position = 'axisPage';

				var formulaOptionString = 'numFmtId="163"';
				var formulaItemString = "<item t=\"default\"/>\n"
				

				xlpivotTable1 = xlpivotTable1 + "<pivotField axis=\"" + position + "\" showAll=\"0\" " + formulaOptionString + " >\n"
					+ "<items>\n"
				var pfvl; var pfvlExclude;
				if (self.conditions[iCV].distinctValues != undefined) {
					pfvl = []; pfvlExclude = [];
					var distValues = self.conditions[iCV].distinctValues
					
					var pos = 0;
					for (var val = 0; val < distValues.length; val++) {
						if (!((distValues[val] == '') && (distValues.findIndex("#NuN#") != -1))) {//and  ( distValues.findIndex("#NuN#") != -1) )  )  {  //se omite un valor porque con el #NUN# el '' queda de mas 

							pfvl.push(cleanDistinctValue(distValues[val], self));
							var hiddenString = "";
							if (self.conditions[iCV].blackList.findIndex(distValues[val]) != -1) {
								hiddenString = " h=\"1\"";
								pfvlExclude.push(cleanDistinctValue(distValues[val], self));
							}
							xlpivotTable1 = xlpivotTable1 + "<item x=\"" + pos + "\" " + hiddenString + " />\n";

							pos = pos + 1;
						}
					}
					xlpivotTable1 = xlpivotTable1 + formulaItemString /*+ "<item t=\"default\"/>"*/
						+ "</items>\n"
						+ "</pivotField>\n";
				}
				pfvi[iCV] = pfvl;
				pfviExclude[iCV] = pfvlExclude[iCV]
				pfi.push(iCV);
			}
			

			for (var iCV = 0; iCV < self.columns.length; iCV++) {
				if (self.filterIndexes.indexOf(iCV) == -1) { //C-L
					var position = 'axisRow';
					if ((self.rowConditions.findIndex(iCV) != -1) || (((self.rowConditions.length + self.filterIndexes.length) == 0))) {
						position = 'axisRow';
						rowLevel++;
						lastRowLevel = iCV;
					} else if (self.colConditions.findIndex(iCV) != -1) {
						position = 'axisCol';
						colLevel++;
						lastColLevel = iCV;
					} else {
						position = 'axisPage';		
						
					}
					var formulaOptionString = 'numFmtId="163"';
					var formulaItemString = "<item t=\"default\"/>\n"
					

					xlpivotTable1 = xlpivotTable1 + "<pivotField axis=\"" + position + "\" showAll=\"0\" " + formulaOptionString + " >\n"
						+ "<items>\n"
					var pfvl; var pfvlExclude;
					if (self.conditions[iCV].distinctValues != undefined) {
						pfvl = []; pfvlExclude = [];
						var distValues = self.conditions[iCV].distinctValues
						
						var pos = 0;
						for (var val = 0; val < distValues.length; val++) {
							if (!((distValues[val] == '') && (distValues.findIndex("#NuN#") != -1))) {
								
								pfvl.push(cleanDistinctValue(distValues[val], self));
								var hiddenString = "";
								if (self.conditions[iCV].blackList.findIndex(distValues[val]) != -1) {
									hiddenString = " h=\"1\"";
									pfvlExclude.push(cleanDistinctValue(distValues[val], self));
								}
								xlpivotTable1 = xlpivotTable1 + "<item x=\"" + pos + "\" " + hiddenString + " />";
								pos = pos + 1
							}
						}
						xlpivotTable1 = xlpivotTable1 + formulaItemString /*+ "<item t=\"default\"/>"*/
							+ "</items>\n"
							+ "</pivotField>\n";
					}
					pfvi[iCV] = pfvl;
					pfviExclude[iCV] = pfvlExclude[iCV]
					pfi.push(iCV);
				}
			}


			if (self.formulaInfo.cantFormulaMeasures > 0) {
				for (var iCV = 0; iCV < measures.length; iCV++) { //first visible measures
					var numFmt = 163
					if (measures[iCV].getAttribute('picture') != "") {
						numFmt = 164 + iCV
					}
					if (!self.formulaInfo.measureFormula[iCV].hasFormula) {

						xlpivotTable1 = xlpivotTable1 + "<pivotField dataField=\"1\" showAll=\"0\"  numFmtId=\"" + numFmt + "\"/>\n";

						pfi.push(cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"),iCV), self, measures[iCV].getAttribute("name")));
					}
				}

				for (var iCV = 0; iCV < formMeasures.length; iCV++) {//add hidden measures for formula
					xlpivotTable1 = xlpivotTable1 + '<pivotField showAll="0" defaultSubtotal="0"/>\n'
				}

				for (var iCV = 0; iCV < measures.length; iCV++) { //second formula measures
					if (self.formulaInfo.measureFormula[iCV].hasFormula) {
						xlpivotTable1 = xlpivotTable1 + '<pivotField dataField="1" dragToRow="0" dragToCol="0" dragToPage="0" showAll="0" defaultSubtotal="0" numFmtId="' + numFmt + '"/>\n'
					}
				}
			}


			xlpivotTable1 = xlpivotTable1 + "</pivotFields>\n"

			if ((self.rowConditions.length + 1 != measures.length)) {
				xlpivotTable1 = xlpivotTable1 + "<rowFields>\n"
				for (var iCV = 0; iCV < self.columns.length; iCV++) {
					if ((self.rowConditions.findIndex(iCV) != -1) /*|| (self.filterIndexes.find(iCV)!=-1)*/ //<-- cambio
						|| (((self.rowConditions.length + self.filterIndexes.length) == 0))
					) {
						var pos = pfi.indexOf(iCV);
						xlpivotTable1 = xlpivotTable1 + "<field x=\"" + pos + "\"/>\n";
					}
				}
				xlpivotTable1 = xlpivotTable1 + "</rowFields>\n"
			}


			xlpivotTable1 = xlpivotTable1 + "<rowItems>\n"
			for (var it = 0; it < self.rowStructure.items.length; it++) {
				xlpivotTable1 = xlpivotTable1 + createExcelROWITEMS(self.rowStructure.items[it], rowLevel, pfvi, lastRowLevel, rowLevel)
			}

			xlpivotTable1 = xlpivotTable1 + "<i t=\"grand\"><x/></i>\n"
				+ "</rowItems>\n"

			if ((((colLevel > -1)) || ((measures.length > 1)))) {
				xlpivotTable1 = xlpivotTable1 + "<colFields>\n"

				for (var iCV = 0; iCV < self.columns.length; iCV++) {
					if ((self.colConditions.findIndex(iCV) != -1) && ((((self.rowConditions.length + self.filterIndexes.length) != 0)))) {
						var pos = pfi.indexOf(iCV);
						xlpivotTable1 = xlpivotTable1 + "<field x=\"" + pos + "\"/>\n";
					}
				}
				if (measures.length > 1) {
					xlpivotTable1 = xlpivotTable1 + "<field x=\"-2\"/>\n";
				};
				//<field x="-2"/>
				xlpivotTable1 = xlpivotTable1 + "</colFields>\n"
			}

			//col items
			xlpivotTable1 = xlpivotTable1 + "<colItems>\n"
			if ((self.colStructure.items) && ((self.rowConditions.length + self.filterIndexes.length) != 0)) {
				for (var it = 0; it < self.colStructure.items.length; it++) {
					xlpivotTable1 = xlpivotTable1 + createExcelCOLITEMS(self.colStructure.items[it], colLevel, pfvi, lastColLevel, colLevel)
				}
			} else {
				for (var iCV = 0; iCV < measures.length; iCV++) {
					xlpivotTable1 = xlpivotTable1 + '<i/>\n';
				}
			}
			xlpivotTable1 = xlpivotTable1 + "</colItems>\n"

			if (self.filterIndexes.length > 0) {
				xlpivotTable1 = xlpivotTable1 + "<pageFields>\n"
				for (var find = 0; find < self.filterIndexes.length; find++) {
					xlpivotTable1 = xlpivotTable1 + "<pageField fld=\"" + (measures.length + find) + "\" hier=\"-1\"/>\n" //C-L +find
				}
				xlpivotTable1 = xlpivotTable1 + "</pageFields>\n"
			}

			xlpivotTable1 = xlpivotTable1 + "<dataFields>\n"
			var colFormYaAgregada = 0; var numColFormula = 0;
			for (var iCV = 0; iCV < measures.length; iCV++) {
				var numFmt = 163
				if (measures[iCV].getAttribute('picture') != "") {
					numFmt = 164 + iCV
				}
				if (!self.formulaInfo.measureFormula[iCV].hasFormula) {
					var addWhenFormula = 0;
					if (self.formulaInfo.cantFormulaMeasures > 0) addWhenFormula = self.columns.length - colFormYaAgregada//self.columns.length
					var space = "";
					if (measures[iCV].getAttribute("displayName").indexOf("%") > -1) {
						for (var t = 0; t < iCV; t++) {
							space = space + " ";
						}
						xlpivotTable1 = xlpivotTable1 + "<dataField name=\"" + measures[iCV].getAttribute("displayName") + space + "\" fld=\"" + (iCV + addWhenFormula) + "\" subtotal=\"" + measures[iCV].getAttribute("aggregation") + "\" numFmtId=\"" + numFmt + "\"/>\n"
					} else {
						xlpivotTable1 = xlpivotTable1 + "<dataField name=\"" + cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"), iCV), self, measures[iCV].getAttribute("name")).replace(/</g, '&lt;').replace(/>/g, '&gt;') + "\" fld=\"" + (iCV + addWhenFormula) + "\" subtotal=\"" + measures[iCV].getAttribute("aggregation") + "\" numFmtId=\"" + numFmt + "\"/>\n"
					}
				} else {
					colFormYaAgregada++;
					var numFmt = 163
					if (measures[iCV].getAttribute('picture') != "") {
						numFmt = 164 + iCV
					}
					if (self.formulaInfo.measureFormula[iCV].hasFormula) {
						if (measures[iCV].getAttribute("displayName").indexOf("%") > -1) {
							for (var t = 0; t < iCV; t++) {
								space = space + " ";
							}
							xlpivotTable1 = xlpivotTable1 + "<dataField name=\"" + measures[iCV].getAttribute("displayName").replace(/</g, '&lt;').replace(/>/g, '&gt;') + space + " \" fld=\"" + (iCV + self.columns.length + formMeasures.length) + "\" numFmtId=\"" + numFmt + "\" baseField=\"0\" baseItem=\"0\"/>\n"
						} else {
							//get cantidad de mesaures de formulas
							var cantMeasureForm = 0;
							var cantNoMeasures = 0
							for (var t = 0; t < self.formulaInfo.measureFormula.length; t++) {
								if (self.formulaInfo.measureFormula[t].hasFormula) {
									cantMeasureForm = cantMeasureForm + self.formulaInfo.measureFormula[t].relatedMeasures.length
								} else {
									cantNoMeasures++
								}
							}

							var lastPosition = cantMeasureForm + cantNoMeasures + self.columns.length + numColFormula//self.formulaInfo.measureFormula[iCV].relatedMeasures.length
							var fld = lastPosition //self.formulaInfo.measureFormula[iCV].relatedMeasures[lastPosition-1]
							xlpivotTable1 = xlpivotTable1 + "<dataField name=\"" + cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"), iCV), self, measures[iCV].getAttribute("name")) + " \" fld=\"" + fld + "\" numFmtId=\"" + numFmt + "\" baseField=\"0\" baseItem=\"0\"/>\n"

							numColFormula++;
						}
					}

				}

			}

			/*for (var iCV = 0; iCV < measures.length; iCV++) {
				var numFmt = 163
				if (measures[iCV].getAttribute('picture') != ""){
					numFmt = 164 + iCV
				}
				if (self.formulaInfo.measureFormula[iCV].hasFormula){
					if (measures[iCV].getAttribute("displayName").indexOf("%")>-1){
						for (var t=0; t < iCV; t++){
							space = space + " ";
						}
						xlpivotTable1 = xlpivotTable1 + "<dataField name=\""+ measures[iCV].getAttribute("displayName") + space +" \" fld=\"" + (iCV + self.columns.length + formMeasures.length) + "\" numFmtId=\"" + numFmt + "\" baseField=\"0\" baseItem=\"0\"/>\n"
					} else {
						xlpivotTable1 = xlpivotTable1 + "<dataField name=\""+ cleanDistinctValue(measures[iCV].getAttribute("displayName"),self,measures[iCV].getAttribute("name")) +" \" fld=\"" + (iCV + self.columns.length + formMeasures.length) + "\" numFmtId=\"" + numFmt + "\" baseField=\"0\" baseItem=\"0\"/>\n"
					}
				} 
			}*/

			xlpivotTable1 = xlpivotTable1 + "</dataFields>\n"
				+ "<pivotTableStyleInfo name=\"PivotStyleLight16\" showRowHeaders=\"1\" showColHeaders=\"1\" showRowStripes=\"0\" showColStripes=\"0\" showLastColumn=\"1\"/>\n"
				+ "</pivotTableDefinition>\n"


			//xl/pivotCache/cacheRecords
			var cacheRecords = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'
				+ '<pivotCacheRecords xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
			for (var rN = 0; rN < dataToShow.length; rN++) {
				cacheRecords = cacheRecords + "<r>"

				for (var col = 0; col < self.columns.length; col++) {
					var vvalue = pfvi[col].indexOf(cleanDistinctValue(dataToShow[rN][col], self))//self.GeneralDataRows[rN][col].replace(/\&/g, "&amp;").replace(/"/g, "&quot;"))
					cacheRecords = cacheRecords + '<x v="' + vvalue + '"/>'
				}

				for (var iCV = 0; iCV < measures.length; iCV++) {
					var pos = self.columns.length + iCV;

					var value = self.defaultPictureValue(dataToShow[rN][pos], (iCV == measures.length - 1), iCV)
					value = removeComas(value, self);
					value = cleanDistinctValue(value, self)//value.replace(/\&/g, "&amp;").replace(/"/g, "&quot;")
					cacheRecords = cacheRecords + '<n v=\"' + value + '"/>';

				}
				cacheRecords = cacheRecords + "</r>"
			}
			cacheRecords = cacheRecords + '</pivotCacheRecords>';


			//xl/pivotCache/cacheDefinition
			var cacheDefinition = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'
				+ '<pivotCacheDefinition r:id="rId1" refreshOnLoad="1" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">\n'
				+ '<cacheSource type="worksheet">\n'
			var letras = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD'];
			cacheDefinition = cacheDefinition + '<worksheetSource ref="A1:' + letras[self.columns.length + measures.length - 1 - self.formulaInfo.cantFormulaMeasures + formMeasures.length] + (dataToShow.length + 1) + '" sheet="SourceData"/>\n'
			cacheDefinition = cacheDefinition + '</cacheSource>\n'
			cacheDefinition = cacheDefinition + '<cacheFields count="' + (self.columns.length + measures.length + formMeasures.length) + '">\n'
			if (self.formulaInfo.cantFormulaMeasures == 0) {
				for (var iCV = 0; iCV < measures.length; iCV++) {
					cacheDefinition = cacheDefinition + '<cacheField name="' + cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"),iCV), self, measures[iCV].getAttribute("name")).replace(/\</g, '&lt;').replace(/\>/g, '&gt;') + '" numFmtId="0">\n'
					cacheDefinition = cacheDefinition + '<sharedItems/>\n'
					cacheDefinition = cacheDefinition + '</cacheField>\n'
				}
			}

			//C-L
			for (var filter = 0; filter < self.filterIndexes.length; filter++) {
				var col = self.filterIndexes[filter];

				//containmixed
				var mixed = "";
				for (var val = 0; val < self.GeneralDistinctValues[col].length; val++) {
					if (!isNaN(self.GeneralDistinctValues[col][val])) {
						mixed = ' containsMixedTypes="1" containsString="1" containsNumber="1" containsInteger="1" ';
						break;
					}
				}
				if (mixed != "") {
					var onlyNumber = true;
					for (var val = 0; val < self.GeneralDistinctValues[col].length; val++) {
						if (isNaN(self.GeneralDistinctValues[col][val])) {
							onlyNumber = false;
							break;
						}
					}
					if (onlyNumber) {
						mixed = ' containsSemiMixedTypes="0" containsString="0" containsNumber="1" containsInteger="1" ';
					}
				}

				cacheDefinition = cacheDefinition + '<cacheField name="' + cleanDistinctValue(self.columns[col].getAttribute("displayName"), self, self.columns[col].getAttribute("name")) + '" numFmtId="0">\n'
				cacheDefinition = cacheDefinition + '<sharedItems ' + mixed + ' count="' + self.GeneralDistinctValues[col].length + '">\n'
				for (var val = 0; val < self.GeneralDistinctValues[col].length; val++) {
					if (!isNaN(self.GeneralDistinctValues[col][val])) {
						cacheDefinition = cacheDefinition + '<n v="' + cleanDistinctValue(self.GeneralDistinctValues[col][val], self) + '"/>\n';
					} else {
						cacheDefinition = cacheDefinition + '<s v="' + cleanDistinctValue(self.GeneralDistinctValues[col][val], self) + '"/>\n';
					}
				}
				cacheDefinition = cacheDefinition + '</sharedItems>\n'
				cacheDefinition = cacheDefinition + '</cacheField>\n'
			}
			//C-L

			for (var col = 0; col < self.columns.length; col++) {
				if (self.filterIndexes.indexOf(col) == -1) { //C-L
					cacheDefinition = cacheDefinition + '<cacheField name="' + cleanDistinctValue(self.columns[col].getAttribute("displayName"), self, self.columns[col].getAttribute("name")) + '" numFmtId="0">\n'
					cacheDefinition = cacheDefinition + '<sharedItems count="' + self.conditions[col].distinctValues.length + '">\n'
					for (var val = 0; val < self.conditions[col].distinctValues.length; val++) {
						cacheDefinition = cacheDefinition + '<s v="' + cleanDistinctValue(self.conditions[col].distinctValues[val], self)/*.replace(/\</g,"&lt;").replace(/\>/g,"&gt;")*//*self.conditions[col].distinctValues[val].replace(/\&/g, "&amp;").replace(/"/g, "&quot;")*/ + '"/>\n';
					}
					cacheDefinition = cacheDefinition + '</sharedItems>\n'
					cacheDefinition = cacheDefinition + '</cacheField>\n'
				} //C-L
			}

			if (self.formulaInfo.cantFormulaMeasures > 0) {
				for (var iCV = 0; iCV < measures.length; iCV++) {
					if (!self.formulaInfo.measureFormula[iCV].hasFormula) {  //normal measures
						cacheDefinition = cacheDefinition + '<cacheField name="' + cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"),iCV), self, measures[iCV].getAttribute("name")) + '" numFmtId="165">\n'
						cacheDefinition = cacheDefinition + '<sharedItems/>\n'
						cacheDefinition = cacheDefinition + '</cacheField>\n'
					}// else {
					//cacheDefinition = cacheDefinition + '<cacheField name="' + measures[iCV].getAttribute("displayName") + '" numFmtId="165" formula="\'Vendido\'/\'Planificado\'" databaseField="0"/>\n'	
					//}
				}



				for (var iCV = 0; iCV < formMeasures.length; iCV++) {//add hidden measures for formula
					cacheDefinition = cacheDefinition + '<cacheField name="' + getMeasureIdentifier(self, formMeasures[iCV]) + '" numFmtId="0">\n' +
						//<sharedItems containsSemiMixedTypes="0" containsString="0" containsNumber="1" containsInteger="1" minValue="100" maxValue="1100"/>
						'</cacheField>\n'
				}


				for (var iCV = 0; iCV < measures.length; iCV++) { //formula measures
					if (self.formulaInfo.measureFormula[iCV].hasFormula) {
						cacheDefinition = cacheDefinition + '<cacheField name="' + cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"),iCV), self, measures[iCV].getAttribute("name")) + '" numFmtId="165" formula="' + self.formulaInfo.measureFormula[iCV].textFormula + '" databaseField="0"/>\n'
					}
				}
			}

			cacheDefinition = cacheDefinition + '</cacheFields>\n'
			cacheDefinition = cacheDefinition + '</pivotCacheDefinition>\n'

			//xl - woorksheet - sheet2
			var sheet2 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
				+ '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
				+ '<dimension ref="A1:' + letras[self.columns.length + measures.length - 1] + (dataToShow.length + 1) + '"/>'
				+ '<sheetViews>'
				+ '<sheetView workbookViewId="0"/>'
				+ '</sheetViews>'
				+ '<sheetData>'
			var rowNumber = 1;
			var colNumber = 0;
			//headers
			sheet2 = sheet2 + '<row r="' + rowNumber + '" span="1:3">'
			for (var col = 0; col < self.columns.length; col++) {
				sheet2 = sheet2 + '<c t="inlineStr" r="' + letras[colNumber] + rowNumber + '">'
				sheet2 = sheet2 + '<is><t>' + cleanDistinctValue(self.columns[col].getAttribute("displayName"), self, self.columns[col].getAttribute("name")).trimpivot() + '</t></is>'
				sheet2 = sheet2 + '</c>'
				colNumber++;
			}
			for (var iCV = 0; iCV < measures.length; iCV++) {
				sheet2 = sheet2 + '<c t="inlineStr" r="' + letras[colNumber] + rowNumber + '">'
				sheet2 = sheet2 + '<is><t>' + cleanDistinctValue(getMeasureTitle(measures[iCV].getAttribute("displayName"),iCV), self, measures[iCV].getAttribute("name")).trimpivot() + '</t></is>'
				sheet2 = sheet2 + '</c>'
				colNumber++;
			}
			sheet2 = sheet2 + '</row>'

			sheet2 = sheet2 + '</sheetData>'
			sheet2 = sheet2 + '</worksheet>'


			//unicamente la seccion de las numberFormat
			//conversion a hacer letras P prefijas se cambian por \P la primera por \\P las demas
			//Z se cambia por #
			//, y . quedan por , y .
			//9 se cambia por 0

			var xlstyle = '<numFmts>'
			var addNumberFormat = false
			for (var mPos = 0; mPos < measures.length; mPos++) {
				if (measures[mPos].getAttribute('picture') != "") {
					var pivotFormat = measures[mPos].getAttribute('picture')
					var numFmt = 164 + mPos

					var excelFormat = ""
					for (var charFP = 0; charFP < pivotFormat.length; charFP++) {
						if (pivotFormat[charFP] == 'Z') {
							excelFormat = excelFormat + "#"
						} else if (pivotFormat[charFP] == '9') {
							excelFormat = excelFormat + "0"
						} else if ((pivotFormat[charFP] == '.') || (pivotFormat[charFP] == ',')) {
							excelFormat = excelFormat + pivotFormat[charFP]
						} else /*if ((charFP == 0))*/ {
							excelFormat = excelFormat + "\\" + pivotFormat[charFP]
						} //else {

						//}
					}

					//var excelFormat = "###,###.00"
					//xlstyle = xlstyle + '<numFmt formatCode="' + excelFormat + '" numFmtId="' + numFmt + '"/>'
					xlstyle = xlstyle + '<numFmt formatCode="' + excelFormat + '" numFmtId="' + numFmt + '"/>'
					addNumberFormat = true
				}
			}
			if (addNumberFormat) {
				xlstyle = xlstyle + '</numFmts>'
			} else {
				xlstyle = ''
			}

			sheet = xlsx({
				creator: 'Genexus',
				lastModifiedBy: 'Genexus',
				pivot: true,
				pivotCacheDefinition: cacheDefinition,
				pivotTable1: xlpivotTable1,
				Sheet2: "",//sheet2,
				style: xlstyle,
				worksheets: [{
					data: dataTable,
					name: 'Sheet 1'
				}]
			});




		}

		if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari
			window.location = sheet.href();
		} else if (!gx.util.browser.isIE() || (9 < gx.util.browser.ieVersion())) {
			//window.location = sheet.href();
			var byteCharacters = atob(sheet.base64);
			function charCodeFromCharacter(c) {
				return c.charCodeAt(0);
			}

			var byteNumbers = Array.prototype.map.call(byteCharacters, charCodeFromCharacter);
			var uint8Data = new Uint8Array(byteNumbers);

			var blob = new Blob([uint8Data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
			saveAs(blob, fileName + ".xlsx");
		} else {
			return sheet.base64;
		}



	}

}



/* END OF FILE - ..\oatPivot\jsPDF_output.src.js - */
/* START OF FILE - ..\oatPivot\oat_dialog.src.js - */
//FILE OAT.Dialof

if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {

	OAT.Dialog = function (i, d, c) {
		var e = this, a = {
			width: 0,
			height: 0,
			modal: 0,
			onshow: function () {
			},
			onhide: function () {
			},
			zIndex: 1E3,
			buttons: 1,
			resize: 1,
			close: 1,
			autoEnter: 1,
			imagePath: OAT.Preferences.imagePath
		};
		if (c)
			for (var f in c)
				a[f] = c[f];
		var b = new OAT.Window({
			close: a.close,
			max: 0,
			min: 0,
			width: a.width,
			height: a.height,
			x: 0,
			y: 0,
			title: i,
			resize: a.resize,
			imagePath: a.imagePath
		});
		OAT.Dom.hide(b.div);
		try {
			OAT.$(d).style.margin = "10px"
		} catch (k) {
		}
		i = OAT.Dom.create("table", {
			marginTop: "1em",
			width: "90%",
			textAlign: "center"
		});
		c = OAT.Dom.create("tbody");
		f = OAT.Dom.create("tr");
		var j = OAT.Dom.create("td", {
			border: "none"
		}), g = OAT.Dom.create("input");
		g.setAttribute("type", "button");
		g.value = " OK ";
		j.appendChild(g);
		var h = OAT.Dom.create("input", {
			marginLeft: "2em"
		});
		h.setAttribute("type", "button");
		h.value = "Cancel";
		j.appendChild(h);
		f.appendChild(j);
		c.appendChild(f);
		i.appendChild(c);
		a.buttons && OAT.$(d).appendChild(i);
		document.body.appendChild(b.div);
		b.content.appendChild(OAT.$(d));
		b.div.style.zIndex = a.zIndex;
		a.modal ? (this.show = function () {
			OAT.Dimmer.show(b.div, {});
			b.accomodate();
			OAT.Dom.center(b.div, 1, 1);
			a.onshow()
		}, this.hide = function () {
			OAT.Dimmer.hide();
			a.onhide()
		}) : (this.show = function () {
			OAT.Dom.show(b.div);
			b.accomodate();
			OAT.Dom.center(b.div, 1, 1);
			a.onshow()
		}, this.hide = function () {
			OAT.Dom.hide(b.div);
			a.onhide()
		});
		b.onclose = this.hide;
		this.accomodate = b.accomodate;
		this.ok = function () {
		};
		this.cancel = function () {
		};
		this.okBtn = g;
		this.cancelBtn = h;
		OAT.Dom.attach(g, "click", function () {
			e.ok()
		});
		OAT.Dom.attach(h, "click", function () {
			e.cancel()
		});
		d = function (a) {
			if (e.okBtn.getAttribute("disabled") != "disabled") {
			a.keyCode == 13 && e.ok();
				a.keyCode == 27 && e.cancel()
			}
		};
		a.autoEnter && OAT.Dom.attach(b.div, "keypress", d)
	};
	try {
		OAT.Loader.featureLoaded("dialog");
	} catch (ERROR) {

	}

	OAT.Drag = {
		TYPE_X: 1, TYPE_Y: 2, TYPE_XY: 3, elm: !1, mouse_x: 0, mouse_y: 0,
		move: function (b) {
			function d(a, b) { return Math.abs(a - b) <= o }
			if (OAT.Drag.elm) {
				OAT.Dom.removeSelection();
				var e = OAT.Dom.getViewport(), a = OAT.Dom.position(OAT.Drag.elm);
				OAT.Dom.eventPos(b); OAT.Dom.getWH(OAT.Drag.elm);
				if (!(b.clientX > e[0] || 0 > b.clientX || b.clientY > e[1] || 0 > b.clientY)) {
					for (var e = b.clientX - OAT.Drag.mouse_x, c = b.clientY - OAT.Drag.mouse_y, q = !0, j = OAT.Drag.elm._Drag_movers, h = 0; h < j.length; h++) { var a = j[h][0], i = j[h][1], a = OAT.Dom.getLT(a); i.restrictionFunction(a[0] + e, a[1] + c) && (q = !1) }
					for (var k = !0, o = 10, h = 0; h < j.length; h++) {
						for (var a = j[h][0], i = j[h][1], l = OAT.Dom.getWH(a), m = OAT.Dom.position(a), r = m[0] + e, m = m[1] + c, n = 0; n < i.magnetsH.length; n++) {
							var g = OAT.$(i.magnetsH[n]), f = OAT.Dom.position(g), g = OAT.Dom.getWH(g);
							if (d(r, f[0])) { a.style.left = f[0] + "px"; k = !1; break }
							if (d(r + l[0], f[0])) { a.style.left = f[0] - l[0] + "px"; k = !1; break }
							if (d(r, f[0] + g[0])) { a.style.left = f[0] + g[0] + "px"; k = !1; break }
							if (d(r + l[0], f[0] + g[0])) { a.style.left = f[0] + g[0] - l[0] + "px"; k = !1; break }
						}
						for (n = 0; n < i.magnetsV.length; n++) {
							g = OAT.$(i.magnetsV[n]); f = OAT.Dom.position(g);
							g = OAT.Dom.getWH(g);
							if (d(m, f[1])) { a.style.top = f[1] + "px"; k = !1; break }
							if (d(m + l[1], f[1])) { a.style.top = f[1] - l[1] + "px"; k = !1; break } if (d(m, f[1] + g[1])) { a.style.top = f[1] + g[1] + "px"; k = !1; break }
							if (d(m + l[1], f[1] + g[1])) { a.style.top = f[1] + g[1] - l[1] + "px"; k = !1; break }
						}
					} if (q && k) {
						for (h = 0; h < j.length; h++)if (a = j[h][0], i = j[h][1], i.moveFunction) i.moveFunction(e, c); else switch (i.type) {
							case OAT.Drag.TYPE_X: OAT.Dom.moveBy(a, e, 0); break; case OAT.Drag.TYPE_Y: OAT.Dom.moveBy(a, 0, c); break; case OAT.Drag.TYPE_XY: OAT.Dom.moveBy(a,
								e, c)
						}OAT.Drag.mouse_x = b.clientX; OAT.Drag.mouse_y = b.clientY
					}
				}
			}
		}, up: function () { if (OAT.Drag.elm) { for (var b = OAT.Drag.elm._Drag_movers, d = 0; d < b.length; d++)b[d][1].endFunction(b[d][0]); OAT.Drag.elm = !1 } }, create: function (b, d, e) {
			var a = { type: OAT.Drag.TYPE_XY, restrictionFunction: function () { return !1 }, endFunction: function () { }, moveFunction: !1, magnetsH: [], magnetsV: [], cursor: !0 }; if (e) for (p in e) a[p] = e[p]; var c = OAT.$(b), b = OAT.$(d), d = function (a) { OAT.Drag.initiate(a, c) }; c._Drag_movers || (OAT.Dom.attach(c, "mousedown", d), c._Drag_movers =
				[], c._Drag_cursor = c.style.cursor); a.cursor && (c.style.cursor = "move"); c._Drag_movers.push([b, a])
		}, initiate: function (b, d) { OAT.Drag.elm = d; OAT.Drag.mouse_x = b.clientX; OAT.Drag.mouse_y = b.clientY }, remove: function (b, d) { var e = OAT.$(b); OAT.$(d); if (e._Drag_movers) { for (var a = -1, c = 0; c < e._Drag_movers.length; c++)e._Drag_movers[c][0] == d && (a = c); -1 != a && e._Drag_movers.splice(a, 1) } }, removeAll: function (b) { b = OAT.$(b); b._Drag_movers && (b._Drag_movers = [], b.style.cursor = b._Drag_cursor) }, createDefault: function (b, d) {
			if (OAT.Preferences.allowDefaultDrag) {
				var e =
					OAT.$(b), a = OAT.Dom.create("div", { position: "absolute", width: "21px", height: "21px"}), c = OAT.Dom.getLT(e); a.style.left = c[0] - 21 + "px"; a.style.top = c[1] - 21 + "px"; if (d) {
						e.parentNode.appendChild(a); c = function (a, b) { var c = OAT.Dom.getWH(e), d = OAT.Dom.getWH(e.parentNode), o = a + c[0], c = b + c[1]; return 20 > a || 20 > b || o > d[0] || c > d[1] }; OAT.Drag.create(a, a); OAT.Drag.create(a, e, { restrictionFunction: c }); OAT.Dom.hide(a); var q = function () { a._Drag_pending && OAT.Dom.hide(a) }; OAT.Dom.attach(e,
							"mouseover", function () { OAT.Dom.show(a); a._Drag_pending = 0 }); OAT.Dom.attach(e, "mouseout", function () { a._Drag_pending = 1; setTimeout(q, 3E3) })
					} else c = function (a, b) { var c = OAT.Dom.getWH(e), d = OAT.Dom.getWH(e.parentNode), o = a + c[0], c = b + c[1]; return 0 > a || 0 > b || o > d[0] || c > d[1] }, OAT.Drag.create(e, e, { restrictionFunction: c })
			}
		}
	}; OAT.Dom.attach(document, "mousemove", OAT.Drag.move); OAT.Dom.attach(document, "mouseup", OAT.Drag.up); try {
		OAT.Loader.featureLoaded("drag");
	} catch (ERROR) {

	}


	OAT.GhostDragData = {
		lock: !1,
		up: function (a) {
			if (OAT.GhostDragData.lock) {
				var b = OAT.GhostDragData.lock, c = b.object;
				if (c.pending)
					c.pending = 0, OAT.GhostDragData.lock = !1;
				else {
					OAT.GhostDragData.lock = !1;
					for (var d = OAT.Dom.eventPos(a), a = d[0], d = d[1], e = 0, f = 0; f < c.targets.length; f++) {
						var g = c.targets[f], h = g[1] ? g[1](a, d) : OAT.GhostDragData.pos(g[0], a, d);
						!e && h && (e = 1, c.callback(g[0], a, d))
					}
					e ? (OAT.Dom.unlink(b), OAT.MSG.send(c, OAT.MSG.GD_END, b)) : (OAT.MSG.send(c, OAT.MSG.GD_ABORT, b), c.onFail(), c = OAT.Dom.position(c.originalElement),
						a = c[0], d = c[1], c = new OAT.AnimationPosition(b, { speed: 10, delay: 10, left: a, top: d }), OAT.MSG.attach(c.animation, OAT.MSG.ANIMATION_STOP, function () { OAT.Dom.unlink(b) }), c.start())
				}
			}
		},
		move: function (a) {
			if (OAT.GhostDragData.lock) {/*OAT.Dom.prevent(a);*/var b = OAT.GhostDragData.lock, c = b.object; c.pending && (document.body.appendChild(b), b.style.zIndex = 2E3,
				c.process && c.process(b),
				c.pending = 0, OAT.MSG.send(c, OAT.MSG.GD_START, b)); OAT.Dom.removeSelection(); var d = a.clientX - b.mouse_x, c = a.clientY - b.mouse_y, d = parseInt(OAT.Dom.style(b,
					"left")) + d, c = parseInt(OAT.Dom.style(b, "top")) + c; b.style.left = d + "px"; b.style.top = c + "px"; b.mouse_x = a.clientX; b.mouse_y = a.clientY
			}
		}, pos: function (a, b, c) { if (!a || "none" == a.style.display.toLowerCase()) return 0; var d = OAT.Dom.position(a), e = d[0] - 2, d = d[1] - 2, f = parseInt(a.offsetWidth) + 2, a = parseInt(a.offsetHeight) + 2; return b >= e && b <= e + f && c >= d && c <= d + a }
	};
	OAT.GhostDrag = function () {
		var a = this;
		this.onFail = function () { };
		this.sources = [];
		this.processes = [];
		this.callbacks = [];
		this.targets = [];
		this.pending = 0;
		this.addSource = function (b, c, d) {
			var e = OAT.$(b);
			a.sources.push(e);
			a.processes.push(c);
			a.callbacks.push(d);
			OAT.Dom.attach(e, "mousedown",
				function (b) {
					OAT.Dom.prevent(b);
					var c = a.sources.findIndex(e);
					-1 != c && a.startDrag(a.sources[c], a.processes[c], a.callbacks[c], b.clientX, b.clientY);

				}
			)
		};
		this.delSource = function (b) { b = $(b); b = a.sources.findIndex(b); -1 != b && (a.sources.splice(b, 1), a.processes.splice(b, 1), a.callbacks.splice(b, 1)) };
		this.clearSources = function () { a.sources = []; a.processes = []; a.callbacks = [] };
		this.addTarget = function (b, c, d) { b = [OAT.$(b), c, d]; a.targets.length && a.targets[a.targets.length - 1][2] ? a.targets.splice(a.targets.length - 1, 0, b) : a.targets.push(b) };
		this.delTarget = function (b) { for (var b = OAT.$(b), c = -1, d = 0; d < a.targets.length; d++)a.targets[d][0] == b && (c = d); -1 != c && a.targets.splice(c, 1) };
		this.clearTargets = function () { a.targets = [] };
		this.startDrag = function (b, c, d, e, f) { OAT.GhostDragData.lock || (a.pending = 1, a.originalElement = b, a.callback = d, d = OAT.Dom.create("div", { position: "absolute" }), a.process = c, c = OAT.Dom.position(b), d.style.left = c[0] + "px", d.style.top = c[1] + "px", OAT.Style.opacity(d, 0.5), d.appendChild(b.cloneNode(!0)), d.mouse_x = e, d.mouse_y = f, d.object = a, OAT.GhostDragData.lock = d) }
	};
	OAT.Dom.attach(document, "mousemove", OAT.GhostDragData.move);
	OAT.Dom.attach(document, "mouseup", OAT.GhostDragData.up);
	try {
		OAT.Loader.featureLoaded("ghostdrag");
	} catch (ERROR) {

	}

	OAT.Instant = function (d, c) {
		var a = this;
		this.options = {
			showCallback: !1,
			hideCallback: !1
		};
		for (var e in c)
			a.options[e] = c[e];
		this.state = 1;
		this.elm = OAT.$(d);
		this.handles = [];
		this.hide = function () {
			a.state = 0;
			OAT.Dom.hide(a.elm)
		};
		this.show = function () {
			a.options.showCallback && a.options.showCallback();
			OAT.Dom.show(a.elm);
			a.state = 1
		};
		this.check = function (b) {
			a.state && (b = OAT.Event.source(b), b == a.elm || OAT.Dom.isChild(b, a.elm) || (a.options.hideCallback && a.options.hideCallback(), a.hide()))
		};
		this.createHandle = function (b) {
			var c = OAT.$(b);
			a.handles.push(c);
			OAT.Event.attach(c, "mousedown", function (b) {
			-1 != a.handles.findIndex(c) && !a.state && (OAT.Event.cancel(b), a.show())
			})
		};
		this.removeHandle = function (b) {
			b = OAT.$(b);
			b = a.handles.findIndex(b);
			-1 != b && a.handles.splice(b, 1)
		};
		a.elm._Instant_show = a.show;
		a.elm._Instant_hide = a.hide;
		a.hide();
		OAT.Dom.attach(document, "mousedown", a.check)
	};
	OAT.Instant.assign = function (d, c) {
		new OAT.Instant(d, {
			hideCallback: c
		})
	};
	try {
		OAT.Loader.featureLoaded("instant");
	} catch (ERROR) {

	}

}
/* END OF FILE - ..\oatPivot\oat_dialog.src.js - */
/* START OF FILE - ..\oatPivot\oat_grid.src.js - */

//FILE oat_grid -----------------------------------------------------------------------------------------------------------------------------------------------


if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {

	OAT.GridData = {
		index: 0,        /* column in action */
		LIMIT: 15,       /* minimum width */
		ALIGN_CENTER: 1,
		ALIGN_LEFT: 2,
		ALIGN_RIGHT: 3,
		SORT_NONE: 1,
		SORT_ASC: 2,
		SORT_DESC: 3,
		TYPE_STRING: 1,
		TYPE_NUMERIC: 2,
		TYPE_AUTO: 3
	} /* GridData */

	OAT.Grid = function (element, controlName, query, columnsDataType, colms, QueryViewerCollection,
		pageSize, disableColumnSort, UcId, IdForQueryViewerCollection, rememberLayout, serverPaging, HideDataFilds, OrderFildsHidden, TableDataFilds, relativePath, selection) {
		var self = this;
		self.controlName = controlName;
		self.columnsDataType = columnsDataType;
		self.query = query;
		self.rowsPerPage = "";
		self.columns = colms;
		self.QueryViewerCollection = QueryViewerCollection;
		self.InitPageSize = pageSize;
		self.disableColumnSort = disableColumnSort
		self.UcId = UcId;
		self.IdForQueryViewerCollection = IdForQueryViewerCollection;
		self.rememberLayout = rememberLayout;
		self.serverPaging = serverPaging;
		self.HideDataFilds = HideDataFilds;
		self.OrderFildsHidden = OrderFildsHidden;
		self.TableDataFilds = TableDataFilds;
		self.relativePath = relativePath;
		self.selection = selection;

		self.Debugg = false;
		self.isSD = false;
		var ua = navigator.userAgent.toLowerCase();
		var isAndroid = ua.indexOf("android") > -1;
		if ((gx.util.browser.isIPad() || gx.util.browser.isIPhone() || isAndroid) || (self.Debugg)) {
			self.isSD = true
		}


		self.conditions = new Array(columnsDataType.length);
		for (iC = 0; iC < columnsDataType.length; iC++) {
			self.conditions[iC] = {
				blackList: [],
				sort: 1
			};
		};
		this.options = {
			autoNumber: 0,
			allowHiding: true,
			sortFunc: false,
			imagePath: OAT.Preferences.imagePath
		}
		//self.options.autoNumber = 0




		this.init = function () {

			var topDiv;


			if ((jQuery("#" + self.controlName + "_grid_top_div").length == 0)
				|| (self.QueryViewerCollection[self.IdForQueryViewerCollection]._ControlRenderedTo == undefined)) {
				var divContainer = OAT.$(element);
				self.ContainerName = divContainer.getAttribute("id")
				OAT.Dom.clear(divContainer);

				var divIeContainer = document.createElement("div");
				divIeContainer.setAttribute("class", "divIeContainer");
				divIeContainer.setAttribute("style", "position: relative;opacity: 0");
				divContainer.appendChild(divIeContainer);
				self.div = divIeContainer;


				topDiv = OAT.Dom.create("div");

				if (self.isSD) { //android
					topDiv.setAttribute("class", "oatgrid_top_div oatgrid_top_div_small");
				} else {
					topDiv.setAttribute("class", "oatgrid_top_div");
				}
				topDiv.setAttribute("id", self.controlName + "_grid_top_div");
				var hide = OAT.Dom.create("a");
				hide.href = "#";

				OAT.addTextNode(hide, document.createTextNode("GXPL_QViewerJSVisibleColumns"))

				self.div.appendChild(topDiv);

				OAT.Dom.makePosition(self.div);
				self.html = OAT.Dom.create("table");
				OAT.Dom.addClass(self.html, "oatgrid");
				OAT.Dom.setIdPropertyValue(self.html, self.controlName);
				self.header = new OAT.GridHeader(self);

				self.rows = [];
				self.rowBlock = OAT.Dom.create("tbody");
				OAT.Dom.append([self.div, self.html], [self.html, self.header.html, self.rowBlock]);

			} else {

				var divContainer = OAT.$(element);
				self.ContainerName = divContainer.getAttribute("id")

				self.div = jQuery("#" + self.ContainerName).find(".divIeContainer")[0]

				topDiv = jQuery("#" + self.ContainerName).find(".oatgrid_top_div")[0]
				OAT.Dom.clear(topDiv);

				self.html = jQuery("#" + self.ContainerName).find("table")[0]

				var previousThead = jQuery("#" + self.ContainerName).find("thead")[0]
				OAT.Dom.clear(previousThead);
				self.header = new OAT.GridHeader(self, previousThead);

				self.rows = [];
				self.rowBlock = jQuery("#" + self.ContainerName).find("tbody")[0]
				OAT.Dom.clear(self.rowBlock);
			}



			//draw export image and pop up of export options
			var exportImg = OAT.Dom.create("div");
			exportImg.href = "#";
			if (self.isSD) { //android
				exportImg.setAttribute("class", "exportOptionsAnchor exportOptionsAnchor_small");
			} else {
				exportImg.setAttribute("class", "exportOptionsAnchor");
			}
			self.exportPage = OAT.Dom.create("div", { padding: "0px" });
			
			OAT.addImageNode(exportImg, "menu", "")

			var checkToClose = function (b) {
				source = OAT.Event.source(b);
				var clean = false;
				var closing = false;
				var isInside = false
				for (var i = 0; i < jQuery(".oat_winrect_container").length; i++) {
					var obj = jQuery(".oat_winrect_container")[i];
					if (!(source == obj) && !OAT.Dom.isChild(source, obj)) {
						clean = true;
					} else {
						clean = false; isInside = true; break;
					}
				}
				for (var i = 0; i < jQuery(".oat_winrect_container").length; i++) {
					if (jQuery(".oat_winrect_container")[i].style.display != "none") {
						closing = true;
					}
				}
				if ((self.serverPaging) &&
					((source.getAttribute("class") == "oat_winrect_close_b") || (!OAT.Dom.isChild(source, obj))) &&
					(closing)) {
					self.oat_component.resetAllScrollValue(self.UcId);
				}
				if (clean) {
					jQuery(".oat_winrect_container").css({ display: "none" });
				}
			};

			OAT.Dom.attach(document, "mousedown", checkToClose)

			OAT.Anchor.assign(exportImg, {
				title: " ",
				content: self.exportPage,
				result_control: false,
				activation: "click",
				type: OAT.WinData.TYPE_RECT,
				width: "auto",
				containerQuery: qv.util.GetContainerControlClass(self.QueryViewerCollection[IdForQueryViewerCollection]) + " ExportPopup "
			});

			var generatePair = function (index) {
				
				if (OAT_JS.grid.gridData[self.UcId].rowsMetadata.columns[index].getAttribute("validPositions") != ""){
				
					var state = (self.header.cells[index].html.style.display != "none");
					var pair = OAT.Dom.create("div");
					var check_class = (state) ? "check_item_img" : "uncheck_item_img";
					if (self.isSD) {//android
						check_class = (state) ? "check_item_img_small" : "uncheck_item_img_small";
					}
					OAT.addImageNode(pair, state ? "check_box" : "check_box_outline_blank", "");
					pair.setAttribute("class", check_class);
					var span = OAT.Dom.create("span");

					OAT.addTextNode(span, " " + self.header.cells[index].value.textContent)
					pair.appendChild(span);
					OAT.Event.attach(pair, "click", function () { // this hide or show the columns
						var checkedClass = "check_item_img"
						var unCheckedClass = "uncheck_item_img"
						if (self.isSD) {//android
							checkedClass = "check_item_img_small"
							unCheckedClass = "uncheck_item_img_small"
						}

						var newClass = (this.getAttribute("class") === checkedClass) ? unCheckedClass : checkedClass;
						this.setAttribute("class", newClass);
					
						jQuery(this).find("i")[0].textContent = (this.getAttribute("class") === checkedClass) ? "check_box" : "check_box_outline_blank";

						var newdisp = (self.header.cells[index].html.style.display == "none" ? "" : "none");
						self.header.cells[index].html.style.display = newdisp;
						var numCol = index;//self.columnsDataType.length - 1 - index;

						for (var i = 0; i < self.rows.length; i++) {
							self.rows[i].cells[numCol].html.style.display = newdisp;
						}
						OAT.saveState({ grid: self }, false);

						if (self.serverPaging) {
							OAT_JS.grid.setColumnVisibleValue(self.UcId, numCol, (newdisp == ""))
						}
				

					});
					return pair;
				
				} else {
					return false;
				}
			}

			var clickRef = function (event) {
				var coords = OAT.Event.position(event);
				self.exportPage.style.left = coords[0] + "px";
				self.exportPage.style.top = coords[1] + "px";
				self.exportPage.id = "exportOptionsContainer";
				if (gx.util.browser.isIE()) {
					self.exportPage.id = "exportOptionsContainerGrid";
				}


				var screenWidth = window.innerWidth;
				var initialPopUpWidth = Math.max(jQuery(".ExportPopup")[0].clientWidth, 300)
				var offsetLeft = jQuery(event.currentTarget).offset().left

				var iconExport = event.currentTarget

				jQuery(".ExportPopup").css({ left: -2500 + "px", top: 0 + "px" })

				//title
				jQuery(".oat_winrect_title").find(".winrect_title_label").remove()

				var spantitle = OAT.Dom.create("label");
				if (self.isSD) {
					jQuery(".oat_winrect_container").addClass("oat_winrect_container_small")
					spantitle.setAttribute("class", "winrect_title_label winrect_title_label_small");
				} else {
					spantitle.setAttribute("class", "winrect_title_label");
				}
				OAT.addTextNode(spantitle, gx.getMessage("GXPL_QViewerPopupTitle"));
				jQuery(".oat_winrect_title").append(spantitle)

				OAT.Dom.clear(self.exportPage);
				//botton to allow show all filters in pop up
				var someExport = false;
				var div_upper = document.createElement("div");
				div_upper.setAttribute("class", "upper_container");

				jQuery('#divtoxml').remove();
				jQuery('#divtoxls').remove();
				jQuery('#divtoxlsx').remove();
				jQuery('#divtoexport').remove();
				jQuery('#divtohtml').remove();
				someExport = self.appendExportToXmlOption(div_upper, someExport);
				someExport = self.appendExportToHtmlOption(div_upper, someExport);
				someExport = self.appendExportToPdfOption(div_upper, someExport);
				someExport = self.appendExportToExcelOption(div_upper, someExport);
				someExport = self.appendExportToExcel2010Option(div_upper, someExport);

				self.exportPage.appendChild(div_upper);


				if (self.options.allowHiding) {
					if (someExport) {
						var hr = OAT.Dom.create("hr", {});
						self.exportPage.appendChild(hr);
					}

					var div_down = document.createElement("div");
					div_down.setAttribute("class", "down_container");
					self.exportPage.appendChild(div_down);

					var label = document.createElement("span");
					label.textContent = gx.getMessage("GXPL_QViewerJSVisibleColumns");
					var div_label = document.createElement("div");
					div_label.setAttribute("class", "div_label_win");
					div_label.appendChild(label);
					div_down.appendChild(div_label);

					var start = (self.autoNumber ? 1 : 0);
					for (var i = start; i < self.header.cells.length; i++) {
						var pair = generatePair(i);
						if (pair)
							div_down.appendChild(pair);
					}
				}


				setTimeout(function () {

					var screenWidth = window.innerWidth;
					var initialPopUpWidth = jQuery(".ExportPopup")[0].clientWidth


					if (initialPopUpWidth == 0) {
						var last = jQuery(".ExportPopup").length;
						initialPopUpWidth = jQuery(".ExportPopup")[last - 1].clientWidth
					}

					if (self.isSD) {//android
						if (initialPopUpWidth < 235) {
							initialPopUpWidth = 235
						}

						var padding = (screenWidth - initialPopUpWidth) / 2 + jQuery(window).scrollLeft()

						jQuery(".ExportPopup").css({ left: padding + "px", top: jQuery(iconExport).offset().top + "px", width: initialPopUpWidth + "px" })

					} else {

						var offsetLeft = jQuery(iconExport).offset().left

						if (offsetLeft + initialPopUpWidth + 15 < screenWidth) {
							jQuery(".ExportPopup").css({ left: jQuery(iconExport).offset().left + "px", top: jQuery(iconExport).offset().top + "px" })
						} else {
							jQuery(".ExportPopup").css({ left: (offsetLeft - initialPopUpWidth + 16) + "px", top: jQuery(iconExport).offset().top + "px" })
						}
					}
				}, 50)
			}

			OAT.Event.attach(exportImg, "click", clickRef);
			topDiv.appendChild(exportImg);

		}

		this.appendExportToXmlOption = function (content, someExport) {
			var exportXMLButton;
			var fileName = this.query;
			if (fileName == "") {
				try {
					fileName = self.controlName.substr(4).split("_")[0]
				} catch (error) { }
			}
			if (self.QueryViewerCollection[self.IdForQueryViewerCollection].ExportToXML) {
				if ((!gx.util.browser.isIE()) || 9 < gx.util.browser.ieVersion()) {
					exportXMLButton = OAT.Dom.create("div");
					var exportButtonSub = self.createExportButton(exportXMLButton)

					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXml"))
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXMLButton.appendChild(pvpl);

					OAT.Dom.attach(exportButtonSub, "click", function () {
						if (!self.serverPaging) {
							str = OAT.ExportToXML({ grid: self }, fileName);
						} else {
							OAT_JS.grid.getAllDataRowsForExport(self.UcId, { grid: self }, fileName, "xml")
						}
					}
					);
				} else {
					exportXMLButton = document.createElement("div");
					exportXMLButton.style.marginBottom = "10px"
					exportXMLButtonSub = OAT.Dom.create("div", { paddingLeft: "1px", position: "relative", cssFloat: "left" });
					exportXMLButtonSub.setAttribute('id', 'divtoxml')

					setTimeout(function () {
						jQuery("#divtoxml").downloadify({
							filename: function () {
								return fileName + '.xml';
							},
							data: function () {
								return OAT.ExportToXML({ grid: self });
							},
							onComplete: function () {
							},
							onCancel: function () {
							},
							onError: function () {
							},
							swf: gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/downloadify/media/downloadify.swf'),
							downloadImage: gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/images/download_file.png'),
							width: 21,
							height: 21,
							transparent: true,
							append: false
						});
					}, 100);

					exportXMLButton.appendChild(exportXMLButtonSub);
					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXml"))
					pvpl.style.paddingLeft = "9px";
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXMLButton.appendChild(pvpl);
				}

				content.appendChild(exportXMLButton);
				if (!someExport) someExport = true;
			}
			return someExport;
		}

		this.appendExportToHtmlOption = function (content, someExport) {
			var exportHTMLButton;
			var fileName = this.query;
			if (fileName == "") {
				try {
					fileName = self.controlName.substr(4).split("_")[0]
				} catch (error) { }
			}
			if (self.QueryViewerCollection[self.IdForQueryViewerCollection].ExportToHTML) {
				if (!gx.util.browser.isIE() || (9 < gx.util.browser.ieVersion())) {
					exportHTMLButton = OAT.Dom.create("div");
					var exportButtonSub = self.createExportButton(exportHTMLButton)

					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportHtml"))
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportHTMLButton.appendChild(pvpl);

					OAT.Dom.attach(exportButtonSub, "click", function () {
						if (!self.serverPaging) {
							self.ExportToHtml(self, fileName);
						} else {
							OAT_JS.grid.getAllDataRowsForExport(self.UcId, self, fileName, "html")
						}
					});
				} else {
					exportHTMLButton = document.createElement("div");
					exportHTMLButton.style.marginBottom = "10px"
					exportHTMLButtonSub = OAT.Dom.create("div", { paddingLeft: "1px", position: "relative", cssFloat: "left" });
					exportHTMLButtonSub.setAttribute('id', 'divtohtml')
					setTimeout(function () {
						jQuery("#divtohtml").downloadify({
							filename: function () {
								return fileName + '.html';
							},
							data: function () {
								var dir = gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/css/grid.css')
								var str = "<!DOCTYPE><HTML><BODY>";

								str = str + "<HEAD>";
								str = str + '<META content="text/html; charset=utf-8" http-equiv="Content-Type"/>'
								str = str + '<link id="gxtheme_css_reference" rel="stylesheet" type="text/css" href="' + dir + '" />'
								str = str + "</STYLE>"

								str = str + "</HEAD>"

								str = str + jQuery("#" + self.controlName)[0].outerHTML.replace(/display: none;/g, "")
								str = str + "</BODY></HTML>";
								return str;
							},
							onComplete: function () {
							},
							onCancel: function () {
							},
							onError: function () {
							},
							swf: gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/downloadify/media/downloadify.swf'),
							downloadImage: gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/images/download_file.png'),
							width: 21,
							height: 21,
							transparent: true,
							append: false
						});
					}, 100);

					exportHTMLButton.appendChild(exportHTMLButtonSub);
					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportHtml"))
					pvpl.style.paddingLeft = "9px";
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportHTMLButton.appendChild(pvpl);
				}
				content.appendChild(exportHTMLButton);
				if (!someExport) someExport = true;
			}
			return someExport;
		}

		this.ExportToHtml = function (self, fileName) {
			var dir = gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/css/grid.css')
			var str = "<!DOCTYPE><HTML><BODY>";

			str = str + "<HEAD>";
			str = str + '<META content="text/html; charset=utf-8" http-equiv="Content-Type"/>'

			str = str + '<link id="gxtheme_css_reference" rel="stylesheet" type="text/css" href="' + dir + '" />'
			
			//add other css file
			for(var i = 0; i < jQuery('link').length; i++)
			{
				if ($('link')[i].href.indexOf("QueryViewer.css") < 0) {
					str = str + '<link id="gxtheme_css_reference" rel="stylesheet" type="text/css" href="' + $('link')[i].href + '" />'
				}
			}
			
			str = str + "</STYLE>"
			str = str + "</HEAD>"
			
			str = str + '<div class="gx_usercontrol qv-table QueryViewer-table">'
			
			str = str + '<table class="oatgrid"  style="width: 100%;">'
			
			str = str + OAT.removeIconFont(jQuery("#" + self.controlName)[0].innerHTML.replace(/visibility: collapse;/g, "").replace(/visibility:collapse;/g, ""))
			
			str = str + '</table>'
			
			str = str + '</div>'
			str = str + "</BODY></HTML>";

			if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari
				window.open('data:text/html,' + str);
			} else {
				var blob = new Blob([str], { type: "text/html" });
				saveAs(blob, fileName + ".html");
			}
		}

		this.appendExportToPdfOption = function (content, someExport) {
			var fileName = this.query;
			if (fileName == "") {
				try {
					fileName = self.controlName.substr(4).split("_")[0]
				} catch (error) { }
			}
			var exportPDFButton;
			if (self.QueryViewerCollection[self.IdForQueryViewerCollection].ExportToPDF) {
				if (gx.util.browser.isIE() && (9 >= gx.util.browser.ieVersion())) {
					exportPDFButton = document.createElement("div");
					exportPDFButton.style.marginBottom = "10px"
					exportPDFButtonSub = OAT.Dom.create("div", { paddingLeft: "1px", position: "relative", cssFloat: "left" });

					exportPDFButtonSub.setAttribute('id', 'divtoexport')
					setTimeout(function () {
						jQuery("#divtoexport").downloadify({
							filename: function () {
								return fileName + '.pdf';
							},
							data: function () {
								return btoa(OAT.ExportToPdf({ grid: self }));
							},
							onComplete: function () {
							},
							onCancel: function () {
							},
							onError: function () {
							},
							dataType: 'base64',
							swf: gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/downloadify/media/downloadify.swf'),
							downloadImage: gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/images/download_file.png'),
							width: 21,
							height: 21,
							transparent: true,
							append: false
						});
					}, 100);

					exportPDFButton.appendChild(exportPDFButtonSub);
					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportPdf"))
					pvpl.style.paddingLeft = "9px";
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportPDFButton.appendChild(pvpl);
				} else {
					exportPDFButton = OAT.Dom.create("div");
					var exportButtonSub = self.createExportButton(exportPDFButton)

					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportPdf"))
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportPDFButton.appendChild(pvpl);

					if (!self.serverPaging) {
						OAT.Dom.attach(exportButtonSub, "click", function () {
							OAT.ExportToPdf({ grid: self }, fileName);
						});
					} else {
						OAT.Dom.attach(exportButtonSub, "click", function () {
							OAT_JS.grid.getAllDataRowsForExport(self.UcId, { grid: self }, fileName, "pdf")
						});
					}
				}

				content.appendChild(exportPDFButton);
				if (!someExport) someExport = true;
			}

			return someExport;
		}

		this.appendExportToExcelOption = function (content, someExport) {
			var fileName = this.query;
			if (fileName == "") {
				try {
					fileName = self.controlName.substr(4).split("_")[0]
				} catch (error) { }
			}
			var exportXLSButton
			if (self.QueryViewerCollection[self.IdForQueryViewerCollection].ExportToXLS) {
				if (!gx.util.browser.isIE() || (9 < gx.util.browser.ieVersion())) {
					exportXLSButton = OAT.Dom.create("div");

					var exportButtonSub = self.createExportButton(exportXLSButton)

					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXls2003"))
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXLSButton.appendChild(pvpl);

					OAT.Dom.attach(exportButtonSub, "click", function () {
						if (!self.serverPaging) {
							OAT.ExportToExcel({ grid: self }, fileName);
						} else {
							OAT_JS.grid.getAllDataRowsForExport(self.UcId, { grid: self }, fileName, "xls")
						}
					});
				} else {
					exportXLSButton = document.createElement("div");
					exportXLSButton.style.marginBottom = "10px"
					exportXLSButtonSub = OAT.Dom.create("div", { paddingLeft: "1px", position: "relative", cssFloat: "left" });

					exportXLSButtonSub.setAttribute('id', 'divtoxls');
					setTimeout(function () {
						jQuery("#divtoxls").downloadify({
							filename: function () {
								return fileName + '.xls';
							},
							data: function () {
								return OAT.ExportToExcel({ grid: self });
							},
							onComplete: function () {
							},
							onCancel: function () {
							},
							onError: function () {
							},
							//transparent: false,
							swf: gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/downloadify/media/downloadify.swf'),
							downloadImage: gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/images/download_file.png'),
							width: 21,
							height: 21,
							transparent: true,
							append: false
						});
					}, 100);
					exportXLSButton.appendChild(exportXLSButtonSub);
					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXls2003"))
					pvpl.style.paddingLeft = "9px";
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXLSButton.appendChild(pvpl);
				}

				content.appendChild(exportXLSButton);
				if (!someExport) someExport = true;
			}

			return someExport;
		}

		this.appendExportToExcel2010Option = function (content, someExport) {
			var fileName = this.query;
			if (fileName == "") {
				try {
					fileName = self.controlName.substr(4).split("_")[0]
				} catch (error) { }
			}
			var exportXLSButton
			if (self.QueryViewerCollection[self.IdForQueryViewerCollection].ExportToXLSX) {
				if (!gx.util.browser.isIE() || (9 < gx.util.browser.ieVersion())) {
					exportXLSButton = OAT.Dom.create("div");

					var exportButtonSub = self.createExportButton(exportXLSButton)


					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXlsx"))
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXLSButton.appendChild(pvpl);

					OAT.Dom.attach(exportButtonSub, "click", function () {
						if (!self.serverPaging) {
							OAT.ExportToExcel2010({ grid: self }, fileName);
						} else {
							OAT_JS.grid.getAllDataRowsForExport(self.UcId, { grid: self }, fileName, "xlsx")
						}
					});
				} else {
					exportXLSButton = document.createElement("div");
					exportXLSButton.style.marginBottom = "10px"
					exportXLSButtonSub = OAT.Dom.create("div", { paddingLeft: "1px", position: "relative", cssFloat: "left" });

					exportXLSButtonSub.setAttribute('id', 'divtoxlsx');
					setTimeout(function () {
						jQuery("#divtoxlsx").downloadify({
							filename: function () {
								return fileName + '.xlsx';
							},
							data: function () {
								return OAT.ExportToExcel2010({ grid: self });
							},
							onComplete: function () {
							},
							onCancel: function () {
							},
							onError: function () {
							},
							//transparent: false,
							dataType: 'base64',
							swf: gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/downloadify/media/downloadify.swf'),
							downloadImage: gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/images/download_file.png'),
							width: 21,
							height: 21,
							transparent: true,
							append: false
						});
					}, 100);
					exportXLSButton.appendChild(exportXLSButtonSub);
					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXlsx"))
					pvpl.style.paddingLeft = "9px";
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXLSButton.appendChild(pvpl);
				}

				content.appendChild(exportXLSButton);
				if (!someExport) someExport = true;
			}

			return someExport;
		}

		this.createExportButton = function (divContainer) {

			var exportButtonSub = OAT.Dom.create("div", {});
			exportButtonSub.setAttribute('id', 'divtoxml');
			divContainer.appendChild(exportButtonSub);

			if (self.isSD) {//android				
				exportButtonSub.setAttribute("class", "download_file_img_small");
			} else {
				exportButtonSub.setAttribute("class", "download_file_img");
			}
			
			OAT.addImageNode(exportButtonSub, "save_alt", "");

			divContainer.setAttribute("class", "export_item_div");
			if (self.isSD) { //android		
				divContainer.setAttribute("class", "export_item_div export_item_div_small");
			}
			return divContainer;
		}


		this.clearData = function () {
			self.rows = [];
			OAT.Dom.clear(self.rowBlock);
		}

		this.appendHeader = function (paramsObj, dataField, index) { /* append one header */
			var i = (!index ? self.header.cells.length : index);
			var cell = self.header.addCell(paramsObj, "character", i, dataField);
			for (var i = 0; i < self.header.cells.length; i++) {
				self.header.cells[i].number = i;
			}
			return cell;
		}

		this.ieFix = function () {
			for (var i = 0; i < self.header.cells.length; i++) {
				var html = self.header.cells[i].html;
				OAT.Dom.addClass(html, "hover");
				OAT.Dom.removeClass(html, "hover");
				var value = self.header.cells[i].value;
				var dims = OAT.Dom.getWH(value);
			}
		}

		this.createHeader = function (paramsList, fieldList) { /* add new header */
			self.header.clear();

			for (var i = 0; i < paramsList.length; i++) {
				self.appendHeader(paramsList[i], fieldList[i]);
			}
			if (OAT.Browser.isIE) { self.ieFix(); }
		} /* Grid::createHeader */

		this.getHeaders = function (){
			var actualHeaders = []
			
			for (var i = 0; i < self.header.cells.length; i++) {
				actualHeaders.push(self.header.cells[i].value.textContent);
			}
			
			return actualHeaders
		}

		this.createRow = function (paramsList, columnsDataType, defaultPicture, customPicture, conditionalFormatsColumns, formatValues, customFormat, column, index, columnVisibility) { /* add new row */
			var number = (!index ? self.rows.length : index);
			var row = new OAT.GridRow(self, number);
			if (index == number || number == self.rows.length) {
				self.rowBlock.appendChild(row.html);
			} else {
				self.rowBlock.insertBefore(row.html, self.rowBlock.childNodes[number]);
			}
			OAT.underRecursionStyle = false;
			for (var i = 0; i < paramsList.length; i++) {
				row.addCell(paramsList[i], columnsDataType[i], defaultPicture, customPicture[i], conditionalFormatsColumns, formatValues, customFormat, i, index, columnVisibility[i]);
			}
			self.rows.splice(number, 0, row);
			return row.html;
		} /* Grid::createRow() */

		this.loadDifferentValues = function (columnNumber, values) {
			self.conditions[columnNumber].differentValue = [];
			for (var i = 0; i < values.length; i++) {
				self.conditions[columnNumber].differentValue.push(values[i]);
			}
		}

		this.removeAllRows = function () {
			var totalRows = self.rows.length
			for (var l = 0; l < totalRows; l++) {
				self.removeRow(0)
			}
		}

		this.removeAllHiddenRows = function () {
			var totalRows = self.rows.length
			var rowNumber = self.rows.length - 1;
			while ((rowNumber > 0) && (self.rows[rowNumber].html.style.display == "none")) {
				self.removeRow(rowNumber);
				rowNumber--;
			}
		}

		this.removeAllCollapseRows = function () {
			var totalRows = self.rows.length
			var rowNumber = self.rows.length - 1;
			while ((rowNumber > 0) && (self.rows[rowNumber].html.style.visibility == "collapse")) {
				self.removeRow(rowNumber);
				rowNumber--;
			}
		}

		this.removeRow = function (rowNumber) {
			jQuery(self.rows[rowNumber].html).remove()

			self.rows.splice(rowNumber, 1);
		}

		this.removeColumn = function (index) {
			self.header.removeColumn(index);
			for (var i = 0; i < self.rows.length; i++) { self.rows[i].removeColumn(index); }
		}

		this.hideColumnHeader = function (index) {
			var headerPos = /*self.columnsDataType.length - 1 -*/ index;
			self.header.cells[headerPos].html.style.display = "none";
		}

		this.showColumnHeader = function (index) {
			var headerPos = self.columnsDataType.length - 1 - index;
			self.header.cells[headerPos].html.style.display = "";
		}

		this.sort = function (index, type, numCol) {
			if (self.options.sortFunc) {
				self.options.sortFunc(numCol, type);
				return;
			}
			for (var i = 0; i < self.header.cells.length; i++) {
				/* aca cambio la info de estado sobre las oredenaciones de las columnas */
				self.conditions[i].sort = 1;
				self.header.cells[i].changeSort(OAT.GridData.SORT_NONE);
			}
			self.conditions[index].sort = type;
			self.header.cells[numCol].changeSort(type);
			/* sort elements here */
			var coltype = self.header.cells[numCol].options.type;
			var c1, c2;
			switch (type) {
				case OAT.GridData.SORT_ASC: c1 = 1; c2 = -1; break;
				case OAT.GridData.SORT_DESC: c1 = -1; c2 = 1; break;
			}

			var useCustomOrder = (OAT_JS.grid.gridData[self.UcId].customOrderValues)
				&& (OAT_JS.grid.gridData[self.UcId].customOrderValues[index] != false)
				&& (OAT_JS.grid.gridData[self.UcId].customOrderValues[index].length > 0)


			var numCmp = function (row_a, row_b) {
				var a = row_a.cells[index].options.value;
				var b = row_b.cells[index].options.value;
				if (a == b) { return 0; }
				return (parseFloat(a) > parseFloat(b) ? c1 : c2);
			}
			var strCmp = function (row_a, row_b) {
				var a = row_a.cells[index].options.value;
				var b = row_b.cells[index].options.value;
				if (a == b) { return 0; }
				return (a > b ? c1 : c2);
			}
			var cusCmp = function (row_a, row_b) {
				var a = row_a.cells[index].options.value;
				var b = row_b.cells[index].options.value;
				var indexA = OAT_JS.grid.gridData[self.UcId].customOrderValues[index].indexOf(a)
				var indexB = OAT_JS.grid.gridData[self.UcId].customOrderValues[index].indexOf(b)
				if (indexA == indexB) { return 0; }
				return (indexA > indexB ? c1 : c2);
			}
			var cmp;

			if ((!self.rows.length) || (self.serverPaging)) { return; } /* no work to be done */

			var testValue = self.rows[0].cells[index].options.value;
			switch (coltype) {
				case OAT.GridData.TYPE_STRING: cmp = strCmp; break;
				case OAT.GridData.TYPE_NUMERIC: cmp = numCmp; break;
				case OAT.GridData.TYPE_AUTO: cmp = (testValue == parseFloat(testValue) ? numCmp : strCmp); break;
			}
			if (useCustomOrder) { cmp = cusCmp; }
			self.rows.sort(cmp);

			/* redo dom, odd & even */
			for (var i = 0; i < self.rows.length; i++) {
				self.rowBlock.appendChild(self.rows[i].html);
				var h = self.rows[i].html;
				OAT.Dom.removeClass(h, "WorkWithEven");
				OAT.Dom.removeClass(h, "WorkWithOdd");
				OAT.Dom.addClass(self.rows[i].html, (i % 2 ? "WorkWithEven" : "WorkWithOdd"));
			}
		} /* Grid::sort() */

		this.applySaveState = function (actualPagesize) {
			if ((self.rememberLayout) && (self.rememberLayout != "false")) {
				self = this;
				var exists = OAT.getState(self, actualPagesize);
				if (exists) {
					OAT.filterRows(self);


					for (var jC = 0; jC < self.columnsDataType.length; jC++) {
						if (self.conditions[jC].sort != 1) {
							self.sort(jC, self.conditions[jC].sort, /*self.columnsDataType.length -1 -*/ jC);
						}
					}
				}
			}
		}

		this.applySortOrderType = function (columnNumber, sortOrder) {
			self.sort(columnNumber, sortOrder, /*self.columnsDataType.length -1 -*/ columnNumber)
		}

		this.applyCustomSort = function (columnNumber, sortData, dataRows) {
			var distinctValues = [];
			for (var h = 0; h < sortData.childNodes.length; h++) {
				if ((sortData.childNodes[h] != undefined) &&
					(sortData.childNodes[h].localName != undefined) &&
					(sortData.childNodes[h].localName === "customOrder")) {
					for (var n = 0; n < sortData.childNodes[h].childNodes.length; n++) {
						if (sortData.childNodes[h].childNodes[n].localName == "Value") {
							distinctValues.push(sortData.childNodes[h].childNodes[n].textContent.trimpivot());
						}
					}
				}
			}

			for (var d = 0; d < dataRows.length; d++) {
				if (distinctValues.indexOf(dataRows[d][columnNumber].trimpivot()) == -1) {
					distinctValues.push(dataRows[d][columnNumber])
				}
			}

			var temp = dataRows;
			dataRows = [];
			for (var i = 0; i < distinctValues.length; i++) {
				for (var j = 0; j < temp.length; j++) {
					if (temp[j][columnNumber].trimpivot() === distinctValues[i].trimpivot()) {
						dataRows.push(temp[j]);
					}
				}
			}
			return [dataRows, distinctValues];
		}

		this.applyCustomFilter = function (columnNumber, filterData) {
			try {
				var includeValues = []; //the only values to show
				var applyFilter = false;
				for (var h = 0; h < filterData.childNodes.length; h++) {
					if ((filterData.childNodes[h] != undefined) &&
						(filterData.childNodes[h].localName != undefined) &&
						(filterData.childNodes[h].localName === "include")) {
						applyFilter = true;
						for (var n = 0; n < filterData.childNodes[h].childNodes.length; n++) {
							if ((filterData.childNodes[h].childNodes[n].localName != null) &&
								(filterData.childNodes[h].childNodes[n].localName.toLowerCase() === "value")) {
								includeValues.push(filterData.childNodes[h].childNodes[n].textContent);
							}
						}
					}
				}

				if (applyFilter) {
					self.conditions[columnNumber].blackList = [];

					var dataFieldId = OAT_JS.grid.gridData[self.UcId].columnDataField[columnNumber];
					OAT_JS.grid.gridData[self.UcId].blackLists[dataFieldId].state = ""
					OAT_JS.grid.gridData[self.UcId].blackLists[dataFieldId].defaultAction = "Exclude"
					OAT_JS.grid.gridData[self.UcId].blackLists[dataFieldId].hiddens = []
					for (var i = 0; i < includeValues.length; i++) {
						if (includeValues[i] != "TOTAL")
							OAT_JS.grid.gridData[self.UcId].blackLists[dataFieldId].visibles.push(includeValues[i]);
					}
					for (var i = 0; i < self.rows.length; i++) {
						var col = columnNumber;
						if ((includeValues.findIndex(self.rows[i].cells[col].options.value) === -1)
							&& (includeValues.findIndex(self.rows[i].cells[col].options.value.trimpivot()) === -1)
							&& (self.conditions[col].blackList.findIndex(self.rows[i].cells[col].options.value) === -1)) {
							self.conditions[col].blackList.push(self.rows[i].cells[col].options.value);
							OAT.HideGridRow({ grid: self }, columnNumber, self.rows[i].cells[columnNumber].options.value);
							OAT.actualizeBlackList("push", self, columnNumber, self.rows[i].cells[columnNumber].options.value, false);
						}
					}
				}
			} catch (error) {

			}
		}

		this.moveToNextPage = function () {
			self.oat_component.moveToNextPage(self.UcId);
		}

		this.moveToFirstPage = function () {
			self.oat_component.moveToFirstPage(self.UcId);
		}

		this.moveToLastPage = function () {
			self.oat_component.moveToLastPage(self.UcId);
		}

		this.moveToPreviousPage = function () {
			self.oat_component.moveToPreviousPage(self.UcId);
		}
		
		this.selectValue = function (selection) {
			//clear previous selection
			OAT_JS.grid.gridData[self.UcId].selection.SelectedNode = [];
			OAT.ClearSelectedNodes(jQuery(self.html));
				
			//find column number first condition
			var s = 0;
			var colNumber = OAT_JS.grid.gridData[self.UcId].columnDataField.indexOf(selection[s].DataField);
				
			OAT.SelectNodes({grid: self}, selection[s].Value, false, colNumber, -1, s, selection);
		}
		
		this.deselectValue = function(){
			OAT_JS.grid.gridData[self.UcId].selection.SelectedNode = [];
			OAT.ClearSelectedNodes(jQuery(self.html));
		}
		
		this.refreshPivot = function (metadata, data, sameQuery) {

			if ((metadata != "") && (data != "")) {
				var parser = new DOMParser();
				var xmlData = parser.parseFromString(metadata, 'text/xml');
				var dimensions = xmlData.getElementsByTagName("OLAPDimension");

				if (!self.serverPaging) {
					OAT.RestoreGridRow({
						grid: self
					});
				}

				var dataFieldOrderChanged = "";
				var OrderChanged = "";
				var colPosition = [];
				for (var dim = 0; dim < dimensions.length; dim++) { //for every dimensions of the other querie
					var dimID = dimensions[dim].getElementsByTagName("name")[0].childNodes[0].nodeValue; //get the name - "Identifier" of this dimension

					//now search for this name at this querie
					var dimPos = -1; //the columns number of the dimension in this table
					var dimHeader = -1; //the number of the title (bug!)
					for (var itC = 0; itC < self.columns.length; itC++) {
						if (self.columns[itC].attributes.getNamedItem("name").nodeValue === dimID) {
							var display = self.columns[itC].attributes.getNamedItem("displayName").nodeValue
							//search in the header for "display" name to know the position
							for (var pD = 0; pD < self.header.cells.length; pD++) {
								if (self.header.cells[pD].options.value === display) {
									dimPos = self.header.cells.length - 1 - pD;		//this is the number of the columns of the dimesnion at this table
									dimHeader = pD;
								}
							}
						}
					}

					if (dimPos != -1) { //the dimension exists in this table
						//make the changes
						var position = dimensions[dim].getElementsByTagName("condition")[0].childNodes[0].nodeValue;
						if (position === "none") {
							var newdisp = "none";
							self.header.cells[dimHeader].html.style.display = newdisp;
							for (var i = 0; i < self.rows.length; i++) {
								self.rows[i].cells[dimPos].html.style.display = newdisp;
							}
							if (self.serverPaging) {
								OAT_JS.grid.setColumnVisibleValue(self.UcId, dimHeader, (newdisp == ""))
							}
						} else {
							var newdisp = "";
							self.header.cells[dimHeader].html.style.display = newdisp;
							for (var i = 0; i < self.rows.length; i++) {
								self.rows[i].cells[dimPos].html.style.display = newdisp;
							}
							if (self.serverPaging) {
								OAT_JS.grid.setColumnVisibleValue(self.UcId, dimHeader, (newdisp == ""))
							}
						}

						//set column position
						try {
							if (self.serverPaging) {
								var dataFieldId = OAT_JS.grid.gridData[self.UcId].columnDataField[dimHeader];
								colPosition[parseInt(dimensions[dim].getElementsByTagName("position")[0].childNodes[0].nodeValue)] = dataFieldId
							}
						} catch (error) { }
						//reset blacklists
						if (self.serverPaging) {
							var dataFieldId = OAT_JS.grid.gridData[self.UcId].columnDataField[dimHeader];
							OAT_JS.grid.updateFilterInfo(self.UcId, dataFieldId, { op: "all", values: [] });
						}

						//set order value if changed
						var order = dimensions[dim].getElementsByTagName("order")[0].childNodes[0].nodeValue;
						if ((order == "ascending") && (self.conditions[dimPos].sort == 3)) {
							self.sort(dimPos, OAT.GridData.SORT_ASC, dimHeader);
							OrderChanged = "Ascending"
							dataFieldOrderChanged = dimensions[dim].getElementsByTagName("dataField")[0].childNodes[0].nodeValue

							//OAT.saveState(self, true);
						} else if ((order == "descending") && (self.conditions[dimPos].sort != 3)) {
							self.sort(dimPos, OAT.GridData.SORT_DESC, dimHeader);

							OrderChanged = "Descending"
							dataFieldOrderChanged = dimensions[dim].getElementsByTagName("dataField")[0].childNodes[0].nodeValue

						}

						var hides = dimensions[dim].getElementsByTagName("hide")[0].childNodes;
						for (var sofs = 0; sofs < hides.length; sofs++) {
							if (hides[sofs].tagName === "value") {
								if (self.serverPaging) {
									var dataFieldId = OAT_JS.grid.gridData[self.UcId].columnDataField[dimHeader];
									var distinctValues = OAT_JS.grid.gridData[self.UcId].differentValues[dataFieldId];
									for (var i = 0; i < distinctValues.length; i++) {
										if (distinctValues[i].trimpivot() == hides[sofs].textContent) {
											OAT_JS.grid.updateFilterInfo(self.UcId, dataFieldId, { op: "push", values: distinctValues[i] });
										}
									}
								} else {
									var index = self.conditions[dimPos].blackList.findIndex(hides[sofs].textContent);
									//if not already in the list
									if (index === -1) {
										for (var i = 0; i < self.rows.length; i++) { //search exact value
											var trimValue = self.rows[i].cells[dimPos].options.value.toString().trimpivot();
											if (trimValue == hides[sofs].textContent) {
												self.conditions[dim].blackList.push(self.rows[i].cells[dimPos].options.value);
												break;
											}
										}
									}
								}
							}
						}
					} //else the dimension doesnt exist in this table

				}


				if (self.serverPaging) {
					if (colPosition.length != OAT_JS.grid.gridData[self.UcId].columnDataField.length) {
						colPosition = [];
					}
					var dimensions = xmlData.getElementsByTagName("OLAPDimension");
					OAT_JS.grid.refreshPivotWhenServerPagination(self.UcId, dataFieldOrderChanged, OrderChanged, colPosition);
				} else {
					OAT.filterRows(self);
					OAT.saveState({
						grid: self
					}, true, -1);
				}
			}

		}

		this.getDataXML = function () {
			if (self.serverPaging) {
				spl = self.IdForQueryViewerCollection;
				var temp = self.QueryViewerCollection[spl].getPivottableDataSync();

				dataStr = temp.split("<Recordset")[1];

				dataStr = "<Recordset" + dataStr;

				/*dataStr = '<OLAPData format="adonet">\n <Table>\n'
				
				records = temp.split("<Page")[1];
				
				if (records.indexOf("<Record>") > -1){
					records = records.substr(records.indexOf("<Record>"))
				}
				
				dataStr = dataStr + records.split("</Page>")[0];   			
				
				dataStr = dataStr + '</Table>\n</OLAPData>'*/

				//var dataStr = temp.split("<OLAPData")[1];
				//dataStr = "<OLAPData " + dataStr
				return dataStr;
			} else {
				var dataStr = '<OLAPData format="adonet">\n <Table>\n'
				for (var i = 0; i < self.rows.length; i++) {
					dataStr = dataStr + "  <Record>\n"
					for (var iCV = 0; iCV < self.columns.length; iCV++) {
						dataStr = dataStr + '   <' + self.columns[iCV].getAttribute("dataField") + '>'
						dataStr = dataStr + self.rows[i].cells[iCV].options.value
						dataStr = dataStr + '</' + self.columns[iCV].getAttribute("dataField") + '>\n'
					}
					dataStr = dataStr + "  </Record>\n"
				}
				dataStr = dataStr + " </Table>\n</OLAPData>"
				return dataStr
			}
		}

		this.getFilteredDataXML = function () {
			if (self.serverPaging) {
				return OAT_JS.grid.getTableWhenServerPagination(self.UcId);
			} else {
				var dataStr = '<Table>\n'
				for (var i = 0; i < self.rows.length; i++) {
					if ((self.rows[i].html.style.display != "none") ||
						(self.rows[i].html.getAttribute("visibq") == undefined) || (self.rows[i].html.getAttribute("visibq") == "tt")) {
						//if (self.rows[i].html.style.display != "none"){
						dataStr = dataStr + "  <Record>\n"
						for (var iCV = 0; iCV < self.columns.length; iCV++) {
							dataStr = dataStr + '   <' + self.columns[iCV].getAttribute("dataField") + '>'
							dataStr = dataStr + self.rows[i].cells[iCV].options.value
							dataStr = dataStr + '</' + self.columns[iCV].getAttribute("dataField") + '>\n'
						}
						dataStr = dataStr + "  </Record>\n"
					}
				}
				dataStr = dataStr + "</Table>\n"
				return dataStr
			}
		}


		this.getMetadataXML = function () {


			var xml = '<OLAPCube format="' + "compact" + '" thousandsSeparator="' + "," + '" decimalSeparator="' + "." + '" dateFormat="' + "MDY" + '">';

			for (var iCV = 0; iCV < self.columns.length; iCV++) {
				xml = xml + '<OLAPDimension> ';

				xml = xml + '<name>' + self.columns[iCV].getAttribute("name") + '</name> '
				xml = xml + '<displayName>' + self.columns[iCV].getAttribute("displayName") + '</displayName> ';
				xml = xml + '<description>' + self.columns[iCV].getAttribute("description") + '</description> ';
				xml = xml + '<dataField>' + self.columns[iCV].getAttribute("dataField") + '</dataField> ';
				xml = xml + '<dataType>' + self.columns[iCV].getAttribute("dataType") + '</dataType> ';
				xml = xml + '<defaultPosition>' + self.columns[iCV].getAttribute("defaultPosition") + '</defaultPosition> ';
				xml = xml + '<validPositions>' + self.columns[iCV].getAttribute("validPositions") + '</validPositions> ';
				xml = xml + '<summarize>' + self.columns[iCV].getAttribute("summarize") + '</summarize> ';
				xml = xml + '<align>' + self.columns[iCV].getAttribute("align") + '</align> ';

				if (self.header.cells[iCV].html.style.display == "none") {
					xml = xml + '<hidden>true</hidden>'
				}

				if (self.columns[iCV].getAttribute("picture") === "") {
					xml = xml + '<picture/> '
				} else {
					xml = xml + '<picture>' + self.columns[iCV].getAttribute("picture") + '</picture> ';
				}

				if (self.columns[iCV].getAttribute("format") === "") {
					xml = xml + '<format/> ';
				} else {
					xml = xml + '<format>' + self.columns[iCV].getAttribute("format") + '</format> ';
				}
				//xml = xml + '<order>'+this.columns[iCV].getAttribute("order")+'</order> ';
				if (self.conditions[iCV].sort === 2)
					xml = xml + '<order>ascending</order> '
				else if (self.conditions[iCV].sort === 1)
					xml = xml + '<order>none</order> '
				else
					xml = xml + '<order>descending</order> '

				xml = xml + '<customOrder/> ';
				xml = xml + '<include> ';

				var previusValue = [];
				for (var i = 0; i < self.rows.length; i++) {
					if (self.rows[i].cells[iCV] != undefined) {
						if (previusValue.findIndex(self.rows[i].cells[iCV].options.value) === -1) {
							if (self.conditions[iCV].blackList.findIndex(self.rows[i].cells[iCV].options.value) === -1) {
								xml = xml + '<value>' + self.rows[i].cells[iCV].options.value + '</value> ';
								previusValue.push(self.rows[i].cells[iCV].options.value);
							}
						}
					}
				}

				xml = xml + '<value>TOTAL</value> </include> <collapse/> ';


				xml = xml + ' </OLAPDimension>';
			}

			xml = xml + "</OLAPCube>";

			return xml;
		}

		self.init();




		var itvl = setInterval(function () {
			
			
			if ((jQuery("#" + self.controlName).length > 0) && (jQuery("#" + self.controlName)[0].getAttribute("class") === "oatgrid")) {
				var actual_rowsPerPage = 0;
				if (jQuery("#" + self.controlName + "tablePagination_rowsPerPage").length > 0) {

					if (!OAT_JS.grid.gridData[self.UcId].autoResize){
						var containerWidth = jQuery("#" + self.ContainerName)[0].clientWidth

						jQuery("#" + self.controlName).css({
							width: containerWidth + "px"
						});
					} else {
						containerWidth = jQuery("#" + self.controlName)[0].clientWidth
					}
					

					actual_rowsPerPage = parseInt(jQuery("#" + self.controlName + "tablePagination_rowsPerPage")[0].value);
					if (!isNaN(actual_rowsPerPage)) {
						if (self.rowsPerPage != actual_rowsPerPage) {
							var stateChange = (self.rowsPerPage != "")
							self.rowsPerPage = actual_rowsPerPage;
							var conteiner = {
								grid: self
							};
							if (stateChange) {
								OAT.saveState(conteiner, false);
							}
						} else {
							self.rowsPerPage = actual_rowsPerPage;
						}
					}
					var wd2 = containerWidth;

					jQuery("#" + self.controlName + "_tablePagination").css({
						width: wd2 + "px"
					});
					jQuery("#" + self.controlName + "_grid_top_div").css({
						width: wd2 + "px"
					});

					//ajustar ancho de footer y top div si el contenido sobrepasa al contenedor
					var widthTable = jQuery("#" + self.controlName)[0].clientWidth
					
					if ((widthTable > (containerWidth + 10)) || (jQuery("#" + self.controlName).closest(".gxwebcomponent").length > 0)) {
						jQuery("#" + self.controlName + "_tablePagination").css({
							width: (widthTable+1) + "px"
						});
						jQuery("#" + self.controlName + "_grid_top_div").css({
							width: (widthTable+1) + "px"
						});
					}
					
				} else {

					if (!OAT_JS.grid.gridData[self.UcId].autoResize){
						var containerWidth = jQuery("#" + self.ContainerName)[0].clientWidth
						
						jQuery("#" + self.controlName).css({
							width: containerWidth + "px"
						});
					} else {
						containerWidth = jQuery("#" + self.controlName)[0].clientWidth
					}

					var wid_topBar = containerWidth;

					jQuery("#" + self.controlName + "_grid_top_div").css({
						width: wid_topBar + "px"
					})
					jQuery(".oatgrid").css({ marginBottom: "0px" })

					//ajustar ancho de footer y top div si el contenido sobrepasa al contenedor
					var widthTable = jQuery("#" + self.controlName)[0].clientWidth
					
					if ((widthTable > (containerWidth + 10)) || (jQuery("#" + self.controlName).closest(".gxwebcomponent").length > 0)) { 
						jQuery("#" + self.controlName + "_grid_top_div").css({
							width: (widthTable+1) + "px"
						});
					}
				}

				jQuery(".divIeContainer").css({ opacity: "1" });

				//actualizar colores

				if (jQuery("#" + self.controlName + " tr").length < 500) {
					var nP = 1;
					for (var i = 1; i < jQuery("#" + self.controlName + " tr").length; i++) {
						if (jQuery("#" + self.controlName + " tr")[i].style.display != "none") {
							if (nP % 2 === 1) {
								jQuery("#" + self.controlName + " tr")[i].className = 'odd';
							} else {
								jQuery("#" + self.controlName + " tr")[i].className = 'even';
							}
							nP++;
						}
					}
				}

				if ((jQuery("#" + self.controlName + "tablePagination_rowsPerPage").length > 0) && (self.QueryViewerCollection.length === 0)) {
					jQuery(".pivot_pag_div").css({
						marginBottom: "0px"
					})
				}
			}

		}, 150);




	}  /* Grid */

	OAT.GridHeader = function (grid, previousTHead) {
		var self = this;
		this.cells = [];
		this.grid = grid;
		if (previousTHead) {
			this.html = previousTHead;
		} else {
			this.html = OAT.Dom.create("thead");
		}
		this.container = OAT.Dom.create("tr");
		this.html.appendChild(self.container);

		this.clear = function () {
			OAT.Dom.clear(self.container);
			self.cells = [];
		}

		this.addCell = function (params, columnsDataType, index, dataField) {
			var cell = new OAT.GridHeaderCell(self.grid, params, index, dataField);
			var tds = self.container.childNodes;

			if (tds.length && index < tds.length) {
				self.container.insertBefore(cell.html, tds[index]);
			} else { self.container.appendChild(cell.html); }

			self.cells.splice(index, 0, cell);
			return cell;
		}

		self.removeColumn = function (index) {
			OAT.Dom.unlink(self.cells[index].html);
			self.cells.splice(index, 1);
			for (var i = 0; i < self.cells.length; i++) { self.cells[i].number = i; }
		}
	} /* GridHeader */

	OAT.GridHeaderCell = function (grid, params_, number, dataField) {
		var self = this;
		this.options = {
			value: "",
			sortable: 1,
			//draggable:1,
			//resizable:0,
			align: OAT.GridData.ALIGN_LEFT,
			sort: OAT.GridData.SORT_NONE,
			type: OAT.GridData.TYPE_AUTO
		}

		var params = (typeof (params_) == "object" ? params_ : { value: params_ });
		for (var p in params) { self.options[p] = params[p]; }

		this.changeSort = function (type) {
			self.options.sort = type;
			self.updateSortImage();
		}

		this.updateSortImage = function () {
			if (!self.sorter) { return; }
			var path = "none";
			switch (self.options.sort) {
				case OAT.GridData.SORT_NONE: path = "none"; break;
				case OAT.GridData.SORT_ASC: path = "asc"; break;
				case OAT.GridData.SORT_DESC: path = "desc"; break;
			}
			self.sorter.className = "table-sort-image table-sort-" + path;
			jQuery(self.sorter).find("i")[0].textContent = (path == "none") ? "" : (path == "asc") ? "arrow_drop_up" : "arrow_drop_down";
		}

		this.signal = 0;
		this.number = number;
		this.grid = grid;
		this.dataField = dataField;

		this.html = OAT.Dom.create("td"); /* cell */
		this.container = OAT.Dom.create("div", { position: "relative" }); /* cell interior */
		this.value = OAT.Dom.create("div", { overflow: "hidden" });
		OAT.Dom.addClass(self.value, "header_value");
		OAT.Dom.append([self.html, self.container], [self.container, self.value]);

		OAT.addTextNode(this.value, params.value.replace(/ /g, "\u00A0"))
		this.value.setAttribute("title_v", params.value);
		this.value.setAttribute("dataField", dataField);
		this.html.setAttribute("title_v", params.value);
		this.html.setAttribute("dataField", dataField);

		if (self.options.sortable) {
			self.html.style.cursor = "pointer";
			self.sorter = OAT.Dom.create("div", { });
			OAT.addImageNode(self.sorter, "arrow_drop_up", "");
			
			self.container.appendChild(self.sorter);
			self.updateSortImage();
			var divCont;
			if (gx.util.browser.isIE()) {
				var className = "oatfilterwindowGrid"
				if (grid.isSD) { //android
					divCont = OAT.Dom.create("div", "", "oatfilterwindowGrid oatfilterwindow_small");
				} else {
					divCont = OAT.Dom.create("div", "", "oatfilterwindowGrid");
				}
			} else {
				var className = "oatfilterwindow"
				if (grid.isSD) {//android
					divCont = OAT.Dom.create("div", "", "oatfilterwindow oatfilterwindow_small");
				} else {
					divCont = OAT.Dom.create("div", "", "oatfilterwindow");
				}
			}
			OAT.Anchor.assign(self.container, {
				title: " ",
				content: divCont,
				result_control: false,
				activation: "click",
				type: OAT.WinData.TYPE_RECT,
				width: "auto",
				containerQuery: qv.util.GetContainerControlClass(self.grid.QueryViewerCollection[IdForQueryViewerCollection]) + " FilterPopup "
			});
			var callback = function (event) {
				var type = OAT.GridData.SORT_NONE;
				switch (self.options.sort) {
					case OAT.GridData.SORT_NONE: type = OAT.GridData.SORT_ASC; break;
					case OAT.GridData.SORT_ASC: type = OAT.GridData.SORT_DESC; break;
					case OAT.GridData.SORT_DESC: type = OAT.GridData.SORT_ASC; break;
				}
				OAT.showPopup(event, self, type, divCont);
				//self.grid.sort(self.number,type);
			}
			OAT.Event.attach(self.container, "click", callback);

		}



		switch (self.options.align) {
			case OAT.GridData.ALIGN_LEFT: self.html.style.textAlign = "left"; break;
			case OAT.GridData.ALIGN_CENTER: self.html.style.textAlign = "center"; break;
			case OAT.GridData.ALIGN_RIGHT: self.html.style.textAlign = "right"; break;
		}

		var mouseover = function (event) { OAT.Dom.addClass(self.html, "hover"); }
		var mouseout = function (event) { OAT.Dom.removeClass(self.html, "hover"); }
		OAT.Event.attach(self.html, "mouseover", mouseover);
		OAT.Event.attach(self.html, "mouseout", mouseout);
	} /* GridHeaderCell */

	OAT.GridRow = function (grid, number) {
		var self = this;

		this.clear = function () {
			OAT.Dom.clear(self.html);
			self.cells = [];
		}

		this.removeColumn = function (index) {
			OAT.Dom.unlink(self.cells[index].html);
			self.cells.splice(index, 1);
		}
		this.isDecimal = function (expression, max) {
			var decimal = /^[0-9]+(\.[0-9]+)+$/;
			if (expression.match(decimal)) {
				return true;
			} else {
				return false;
			}
		}
		this.addCell = function (params, columnsDataType, defaultPicture, customPicture, conditionalFormatsColumns, formatValues, customFormat, numCol, index, cellVisible) {
			var i = (!index ? self.cells.length : index);
			if (params == undefined) {
				params = ""
			}

			var cell = new OAT.GridRowCell(params, i, columnsDataType, defaultPicture, customPicture, conditionalFormatsColumns, formatValues, customFormat, numCol, cellVisible);
			var tds = self.html.childNodes;
			if (tds.length && i != tds.length) {
				self.html.insertBefore(cell.html, tds[i]);
				if (!cellVisible) tds[i].style.display = "none"
			} else {
				self.html.appendChild(cell.html);
				if (!cellVisible) cell.html.style.display = "none"
			}

			OAT.setClickEventHandlers(self, tds[tds.length - 1], params, "DIMENSION", numCol, self.grid.rows.length);

			self.cells.splice(i, 0, cell);
			return cell.value;
		}

		this.select = function () {
			self.selected = 1;
			//OAT.Dom.addClass(self.html, "selected");
		}

		this.deselect = function () {
			self.selected = 0;
			OAT.Dom.removeClass(self.html, "selected");
		}

		this.grid = grid; /* parent */
		this.cells = [];
		this.html = OAT.Dom.create("tr");
		this.selected = 0;

		OAT.Dom.addClass(self.html, (number % 2 ? "even" : "odd"));

		var mouseover = function (event) { OAT.Dom.addClass(self.html, "hover"); }
		var mouseout = function (event) { OAT.Dom.removeClass(self.html, "hover"); }
		var click = function (event) {
			if (!event.shiftKey && !event.ctrlKey) {
				/* deselect all */
				for (var i = 0; i < self.grid.rows.length; i++) {
					var r = self.grid.rows[i];
					if (r != self) { r.deselect(); }
				}
			}
			if (event.shiftKey) {
				/* select all above */
				var firstAbove = -1;
				var lastBelow = -1;
				var done = 0;
				for (var i = 0; i < self.grid.rows.length; i++) {
					var r = self.grid.rows[i];
					if (r != self) {
						if (!done && r.selected) { firstAbove = i; } /* first selected above */
						if (!done && firstAbove != -1) { r.select(); }
						if (done && r.selected) { lastBelow = i; } /* last selected below */
					} else {
						done = 1;
					}
				} /* all rows */
				/* if none are above, then try below */
				if (firstAbove == -1 && lastBelow != -1) {
					var done = 0;
					for (var i = 0; i < self.grid.rows.length; i++) {
						var r = self.grid.rows[i];
						if (r == self) { done = 1; }
						if (done && r != self && i < lastBelow) { r.select(); }
					} /* all rows */
				} /* below */
			} /* if shift */

			self.selected ? self.deselect() : self.select();
		}

		OAT.Event.attach(self.html, "mouseover", mouseover);
		OAT.Event.attach(self.html, "mouseout", mouseout);
		OAT.Event.attach(self.html, "click", click);

	}      /* GridRow */

	OAT.GridRowCell = function (params_, number, columnsDataType, defaultPicture, customPicture, conditionalFormatsColumns, formatValues, customFormat, numCol, visible) {
		var self = this;

		this.options = {
			value: "",
			align: OAT.GridData.ALIGN_LEFT
		}

		var params = (typeof (params_) == "object" ? params_ : { value: params_ });
		for (p in params) { self.options[p] = params[p]; }

		this.html = OAT.Dom.create("td");
		this.container = OAT.Dom.create("div");
		this.value = OAT.Dom.create("div", { overflow: "hidden" });
		OAT.Dom.addClass(self.value, "row_value");

		OAT.addTextNode(this.value, OAT.ApplyPictureValue(self.options.value, columnsDataType, defaultPicture, customPicture).trim().replace(/ /g, "\u00A0"))
		this.html = OAT.applyFormatValues(this.html, self.options.value, columnsDataType, numCol, formatValues, conditionalFormatsColumns, customFormat); /* Apply Format */

		this.html.setAttribute("title", OAT.ApplyPictureValue(self.options.value, columnsDataType, defaultPicture, customPicture));//self.options.value);
		OAT.Dom.append([self.html, self.container], [self.container, self.value]);
		this.html.setAttribute("sin_pictureValue", params_);
		//align numbers right
		if ((columnsDataType != "character") && (columnsDataType != "guid")){
			if (!isNaN(self.options.value)) {
				self.options.align = 3; //right
			}
			if (self.options.value) {
				self.options.align = 3; //right
			}
		}
		if (columnsDataType === 'date') {
			self.options.align = OAT.GridData.ALIGN_RIGHT;
		}
		switch (self.options.align) {
			case OAT.GridData.ALIGN_LEFT: self.html.style.textAlign = "left"; break;
			case OAT.GridData.ALIGN_CENTER: self.html.style.textAlign = "center"; break;
			case OAT.GridData.ALIGN_RIGHT: self.html.style.textAlign = "right"; break;
		}

	}         /* GridRowCell */

	OAT.underRecursionStyle = false;
	OAT.applyFormatValues = function (td, value, datatype, columnNumber, formatValues, conditionalFormatsColumns, customFormat) { /* Format for dimensions ("header columns") */
		var measureDataType = datatype;

		//apply default format
		var defaultFormats = customFormat[columnNumber];
		if ((defaultFormats != null) && (defaultFormats != "")) {
			td = OAT.setStyleValues(td, defaultFormats);
		}
		//apply format value
		if (OAT.underRecursionStyle) {
			for (var i = 0; i < formatValues.length; i++) {
				td = OAT.setStyleValues(td, formatValues[i].format);
			}
		}

		for (var i = 0; i < formatValues.length; i++) {
			if (formatValues[i].columnNumber == columnNumber) { //a format for this column
				if (formatValues[i].value === value.trimpivot()) {
					td = OAT.setStyleValues(td, formatValues[i].format);
					if ((self.formatValues[i].recursive != undefined) && (self.formatValues[i].recursive == "yes")) {
						OAT.underRecursionStyle = true
					}
				}
			}
		}
		//apply conditional values
		var equal = [];
		var notequal = [];
		var greaterThan = [];
		var greaterOrEqual = [];
		var lessThan = [];
		var lessOrEqual = [];
		var greaterOrEqual = [];
		var between = [];
		for (var i = 0; i < conditionalFormatsColumns.length; i++) {
			if (conditionalFormatsColumns[i].columnNumber == columnNumber) {
				if (conditionalFormatsColumns[i].operation1 == "equal") {
					if ((measureDataType === "real") || (measureDataType === "integer")) {
						equal[0] = parseFloat(conditionalFormatsColumns[i].value1);
					} else {
						equal[0] = conditionalFormatsColumns[i].value1
					}
					equal[1] = conditionalFormatsColumns[i].format;
				}
				if (conditionalFormatsColumns[i].operation1 == "notequal") {
					if ((measureDataType === "real") || (measureDataType === "integer")) {
						notequal[0] = parseFloat(conditionalFormatsColumns[i].value1);
					} else {
						notequal[0] = conditionalFormatsColumns[i].value1
					}
					notequal[1] = conditionalFormatsColumns[i].format;
				}
				if (conditionalFormatsColumns[i].operation1 == "less") {
					if ((measureDataType === "real") || (measureDataType === "integer")) {
						lessThan[0] = parseFloat(conditionalFormatsColumns[i].value1);
					} else {
						lessThan[0] = conditionalFormatsColumns[i].value1;
					}
					lessThan[1] = conditionalFormatsColumns[i].format;
				}
				if (conditionalFormatsColumns[i].operation1 == "lessequal") {
					if ((measureDataType === "real") || (measureDataType === "integer")) {
						lessOrEqual[0] = parseFloat(conditionalFormatsColumns[i].value1);
					} else {
						lessOrEqual[0] = conditionalFormatsColumns[i].value1
					}
					lessThan[1] = conditionalFormatsColumns[i].format;
				}
				if (conditionalFormatsColumns[i].operation1 == "greater") {
					if ((measureDataType === "real") || (measureDataType === "integer")) {
						greaterThan[0] = parseFloat(conditionalFormatsColumns[i].value1);
					} else {
						greaterThan[0] = conditionalFormatsColumns[i].value1;
					}
					greaterThan[1] = conditionalFormatsColumns[i].format;
				}
				if (conditionalFormatsColumns[i].operation1 == "greaterequal") {
					if ((measureDataType === "real") || (measureDataType === "integer")) {
						greaterOrEqual[0] = parseFloat(conditionalFormatsColumns[i].value1);
					} else {
						greaterOrEqual[0] = conditionalFormatsColumns[i].value1;
					}
					greaterThan[1] = conditionalFormatsColumns[i].format;
				}
				if (conditionalFormatsColumns[i].operation2 && conditionalFormatsColumns[i].operation1 == "greaterequal") {
					greaterOrEqual = []
					if ((measureDataType === "real") || (measureDataType === "integer")) {
						between[0] = parseFloat(conditionalFormatsColumns[i].value1);
					} else {
						between[0] = conditionalFormatsColumns[i].value1;
					}
					if (conditionalFormatsColumns[i].operation2 && conditionalFormatsColumns[i].operation2 == "lessequal") {
						if ((measureDataType === "real") || (measureDataType === "integer")) {
							between[1] = parseFloat(conditionalFormatsColumns[i].value2);
						} else {
							between[1] = conditionalFormatsColumns[i].value2;
						}
						between[2] = conditionalFormatsColumns[i].format;
					}
				}
			}
		}

		var comparisons = new Array(3);

		if (measureDataType === "real") {
			value = parseFloat(value);
			if ((greaterThan[0] != undefined) && (greaterThan[0] != "")) {
				comparisons[0] = parseFloat(greaterThan[0]);
			}
			if ((lessThan[0] != undefined) && (lessThan[0] != "")) {
				comparisons[1] = parseFloat(lessThan[0]);
			}
			if ((between[0] != undefined) && (between[0] != "")) {
				comparisons[2] = parseFloat(between[0]);
			}
		}

		if (measureDataType === "integer") {
			value = parseInt(value);
			if ((greaterThan[0] != undefined) && (greaterThan[0] != "")) {
				comparisons[0] = parseInt(greaterThan[0]);
			}
			if ((lessThan[0] != undefined) && (lessThan[0] != "")) {
				comparisons[1] = parseInt(lessThan[0]);
			}
			if ((between[0] != undefined) && (between[0] != "")) {
				comparisons[2] = parseInt(between[0]);
			}

		}


		if (measureDataType === "date") {
			var dates = value.split("-");

			var dateElements = new Array(3);
			dateElements[0] = parseInt(dates[0]);
			dateElements[1] = parseInt(dates[1]);
			dateElements[2] = parseInt(dates[2]);

			try {
				if ((equal[0] != undefined) || (greaterOrEqual[0] != undefined) || (lessOrEqual[0] != undefined)) {
					var cmpar;
					if (equal[0] != undefined) {
						cmpar = equal[0].split("-");
					} else if (greaterOrEqual[0] != undefined) {
						cmpar = greaterOrEqual[0].split("-");
					} else if (greaterOrEqual[0] != undefined) {
						cmpar = lessOrEqual[0].split("-");
					}
					var cmparElements = new Array(3);
					cmparElements[1] = parseInt(cmpar[1]);
					cmparElements[2] = parseInt(cmpar[2]);
					cmparElements[0] = parseInt(cmpar[0]);

					if ((cmparElements[0] == dateElements[0]) || ((cmparElements[0] == dateElements[0]) && (cmparElements[1] == dateElements[1]))) {
						if (equal[1] != undefined)
							td = OAT.setStyleValues(td, equal[1]);
						else if (greaterThan[1] != undefined)
							td = OAT.setStyleValues(td, greaterThan[1]);
						else if (lessThan[1] != undefined)
							td = OAT.setStyleValues(td, lessThan[1]);
					}

				}

				if ((notequal[0] != undefined)) {
					var cmpar = notequal[0].split("-");
					var cmparElements = new Array(3);
					cmparElements[1] = parseInt(cmpar[1]);
					cmparElements[2] = parseInt(cmpar[2]);
					cmparElements[0] = parseInt(cmpar[0]);

					if ((cmparElements[0] != dateElements[0]) || ((cmparElements[0] != dateElements[0]) && (cmparElements[1] != dateElements[1]))) {
						td = OAT.setStyleValues(td, notequal[1]);
					}

				}


				if ((greaterThan[0] != undefined) || (greaterOrEqual[0] != undefined)) {
					var cmpar;
					if (greaterThan[0].split("-") != undefined) {
						cmpar = greaterThan[0].split("-");
					} else {
						cmpar = greaterOrEqual[0].split("-");
					}
					cmparElements[1] = parseInt(cmpar[1]);
					cmparElements[2] = parseInt(cmpar[2]);
					cmparElements[0] = parseInt(cmpar[0]);

					if ((cmparElements[0] < dateElements[0]) || ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] < dateElements[1]))
						|| ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] <= dateElements[1]) && (cmparElements[2] < dateElements[2]))) {
						td = OAT.setStyleValues(td, greaterThan[1]);
					}

				}


				if ((lessThan[0] != undefined) || (lessOrEqual[0] != undefined)) {
					var cmpar;
					if (lessThan[0].split("-") != undefined) {
						cmpar = lessThan[0].split("-");
					} else {
						cmpar = lessOrEqual[0].split("-");
					}
					cmparElements = new Array(3);
					cmparElements[1] = parseInt(cmpar[1]);
					cmparElements[2] = parseInt(cmpar[2]);
					cmparElements[0] = parseInt(cmpar[0]);

					if ((cmparElements[0] > dateElements[0]) || ((cmparElements[0] >= dateElements[0]) && (cmparElements[1] > dateElements[1]))
						|| ((cmparElements[0] >= dateElements[0]) && (cmparElements[1] >= dateElements[1]) && (cmparElements[2] > dateElements[2]))) {
						td = OAT.setStyleValues(td, lessThan[1]);
					}

				}

				if ((between[0] != undefined) && (between[1] != undefined)) {
					var cmpar = between[0].split("-");
					var cmpar2 = between[1].split("-");
					cmparElements = new Array(3);
					cmparElements2 = new Array(3);
					cmparElements[1] = parseInt(cmpar[1]);
					cmparElements[2] = parseInt(cmpar[2]);
					cmparElements[0] = parseInt(cmpar[0]);

					cmparElements2[1] = parseInt(cmpar2[1]);
					cmparElements2[2] = parseInt(cmpar2[2]);
					cmparElements2[0] = parseInt(cmpar2[0]);

					if (((cmparElements[0] <= dateElements[0]) || ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] < dateElements[1]))
						|| ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] <= dateElements[1]) && (cmparElements[2] < dateElements[2])))
						&&
						((cmparElements2[0] > dateElements[0]) || ((cmparElements2[0] >= dateElements[0]) && (cmparElements2[1] > dateElements[1]))
							|| ((cmparElements2[0] >= dateElements[0]) && (cmparElements2[1] >= dateElements[1]) && (cmparElements2[2] > dateElements[2])))
					) {
						td = OAT.setStyleValues(td, between[2]);
					}

				}

			} catch (ERROR) {

			}

		}

		if (measureDataType != "date") {
			if ((equal[0] != undefined) && (value == equal[0])) {
				td = OAT.setStyleValues(td, equal[1]);
			}
			if ((notequal[0] != undefined) && (value != notequal[0])) {
				td = OAT.setStyleValues(td, notequal[1]);
			}
			if (((greaterThan[0] != undefined) && (value > greaterThan[0])) ||
				((greaterOrEqual[0] != undefined) && (value >= greaterOrEqual[0]))) {
				td = OAT.setStyleValues(td, greaterThan[1]);
			}
			if (((lessThan[0] != undefined) && (value < lessThan[0])) ||
				((lessOrEqual[0] != undefined) && (value <= lessOrEqual[0]))) {
				td = OAT.setStyleValues(td, lessThan[1]);
			}
			if ((between[0] != undefined && between[1] != undefined) && (value >= between[0] && value <= between[1])) {
				td = OAT.setStyleValues(td, between[2]);
			}
		}

		return td;
	}

	OAT.setStyleValues = function (elem, styleValues) {
		if (styleValues == undefined)
			return elem;
		function hexToRgb(hex) {
			// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
			var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
			hex = hex.replace(shorthandRegex, function (m, r, g, b) {
				return r + r + g + g + b + b;
			});

			var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
			return result ? {
				r: parseInt(result[1], 16),
				g: parseInt(result[2], 16),
				b: parseInt(result[3], 16)
			} : null;
		}

		var styleSplit = styleValues.split(";");
		for (var j = 0; j < styleSplit.length; j++) {
			var particularStyleSplit = styleSplit[j].split(":");

			switch (particularStyleSplit[0]) {
				case "color": if ((particularStyleSplit[1][0] != undefined) && (particularStyleSplit[1][0] === '#')) {
					elem.style.color = 'rgb(' + hexToRgb(particularStyleSplit[1]).r + ',' + hexToRgb(particularStyleSplit[1]).g + ',' + hexToRgb(particularStyleSplit[1]).b + ')'
				} else {
					elem.style.color = particularStyleSplit[1];
				}
					break;
				case "fontStyle": elem.style.fontStyle = particularStyleSplit[1];
					break;
				case "backgroundColor": elem.style.backgroundColor = particularStyleSplit[1];
					break;
				case "textDecoration": elem.style.textDecoration = particularStyleSplit[1];
					break;
				case "fontWeight": elem.style.fontWeight = particularStyleSplit[1];
					break;
				case "fontFamily": elem.style.fontFamily = particularStyleSplit[1];
					break;
				case "fontVariant": elem.style.fontVariant = particularStyleSplit[1];
					break;
				case "fontSize": elem.style.fontSize = particularStyleSplit[1].replace("px", "") + "px";
					break;
				case "textAlign": elem.style.textAlign = particularStyleSplit[1];
					break;
				case "lineHeight": elem.style.lineHeight = particularStyleSplit[1];
					break;
				case "textIndent": elem.style.textIndent = particularStyleSplit[1];
					break;
				case "verticalAlign": elem.style.verticalAlign = particularStyleSplit[1];
					break;
				case "wordSpacing": elem.style.wordSpacing = particularStyleSplit[1];
					break;
				case "display": elem.style.display = particularStyleSplit[1];
					break;
				case "borderThickness": elem.style.borderThickness = particularStyleSplit[1];
					elem.style.borderWidth = particularStyleSplit[1] + "px";
					break;
				case "borderColor": elem.style.borderColor = particularStyleSplit[1];
					break;
				case "borderWith": elem.style.borderWith = particularStyleSplit[1];
					break;
				case "borderStyle": elem.style.borderStyle = particularStyleSplit[1];
					break;
				case "padding": elem.style.padding = particularStyleSplit[1];
					break;
				case "paddingBottom": elem.style.paddingBottom = particularStyleSplit[1];
					break;
				case "paddingLeft": elem.style.paddingLeft = particularStyleSplit[1];
					break;
				case "paddingRight": elem.style.paddingRight = particularStyleSplit[1];
					break;
				case "paddingTop": elem.style.paddingTop = particularStyleSplit[1];
					break;
			}
		}
		return elem;
	}

	OAT.GenerateFormatDateForGrid = function (value, picture) {
		var dividepicture = picture.split(" ");
		var valueSplit = value[0].split("-");
		var newValue = ""
		switch (picture) {
			case "99/99/9999":
				newValue = valueSplit[1] + "/" + valueSplit[2] + "/" + valueSplit[0];
				break;
			case "99/99/99":
				if (valueSplit[0].length == 4) {
					valueSplit[0] = valueSplit[0].substr(valueSplit[0].length - 2, 2);
				}
				newValue = valueSplit[1] + "/" + valueSplit[2] + "/" + valueSplit[0];
				break;
			default:
				newValue = valueSplit[2] + "/" + valueSplit[1] + "/" + valueSplit[0];
		}
		return newValue;
	}

	OAT.HideGridRow = function (_self, colNumber, value) {

		for (var i = 0; i < _self.grid.rows.length; i++) {
			if (_self.grid.rows[i].cells[colNumber].options.value.toString().trimpivot() === value.toString().trimpivot()) {
				_self.grid.rows[i].html.style.display = "none";
				_self.grid.rows[i].html.setAttribute('visibQ', 'tf');
			}
		}

	}

	OAT.ShowGridRow = function (_self, colNumber, value) {

		for (var i = 0; i < _self.grid.rows.length; i++) {
			if (_self.grid.rows[i].cells[colNumber].options.value.toString().trimpivot() === value.toString().trimpivot()) {
				_self.grid.rows[i].html.style.display = "";
				_self.grid.rows[i].html.setAttribute('visibQ', 'tt');
			}
		}

	}

	OAT.RestoreGridRow = function (_self) { /* restore GRID  */

		for (var i = 0; i < _self.grid.rows.length; i++) {
			//if (_self.grid.rows[i].html.getAttribute('visib')!='fp'){
			_self.grid.rows[i].html.style.display = "";
			//}
			_self.grid.rows[i].html.setAttribute('visibQ', 'tt');
		}

		for (var colNum = 0; colNum < _self.grid.columnsDataType.length; colNum++) {
			_self.grid.conditions[colNum].blackList = [];
		}
	}

	OAT.RestoreGridOrder = function (_self) {
		//for (var colNum = 0; colNum < _self.grid.columnsDataType.length; colNum++){
		//		if (_self.grid.conditions[colNum].sort != 1){
		//			_self.grid.sort( colNum, 1, _self.grid.columnsDataType.length -1 - colNum);					
		// 	}		
		//}
		_self.grid.sort(0, 2, _self.grid.columnsDataType.length - 1 - 0);
		_self.grid.sort(0, 1, _self.grid.columnsDataType.length - 1 - 0);
	}

	OAT.RestoreGridColumns = function (_self) {
		for (var tC = 0; tC < _self.grid.columnsDataType.length; tC++) {
			_self.grid.header.cells[tC].html.style.display = "";
			var j = 0;
			var numCol = _self.grid.columnsDataType.length - 1 - tC;
			for (j = 0; j < _self.grid.rows.length; j++) {
				_self.grid.rows[j].cells[numCol].html.style.display = "";
			}
		}
	}

	OAT.filterRows = function (grid) {

		var conteiner = {
			grid: grid
		}

		for (var colNum = 0; colNum < grid.columnsDataType.length; colNum++) {

			for (var item = 0; item < grid.conditions[colNum].blackList.length; item++) {
				OAT.HideGridRow(conteiner, colNum, grid.conditions[colNum].blackList[item]);
				OAT.actualizeBlackList("push", grid, colNum, grid.conditions[colNum].blackList[item], false);
			}
		}
	}

	OAT.actualizeBlackList = function (oper, grid, colNumber, value, serverPaging) { //oper = push add value to blackList
		//search all rows
		if (!serverPaging) {
			for (var i = 0; i < grid.rows.length; i++) {
				if (grid.rows[i].cells[colNumber].options.value === value) { //for rows with value "value"
					for (var col = 0; col < grid.rows[0].cells.length; col++) { //for every column disntinc from colNumber
						if (col != colNumber) {
							//search in the table if there's any visible row with this value (not hidden beacause of pagination)
							var colvalue = grid.rows[i].cells[col].options.value;
							var show = 0;
							for (var j = 0; j < grid.rows.length; j++) { //search for other rows with same value
								var nextRowValue = grid.rows[j].cells[col].options.value;
								if (nextRowValue === colvalue) {
									if ((grid.rows[j].html.style.display != "none")
										|| (grid.rows[j].html.getAttribute('visibQ') != "tf")) {
										show = show + 1;
									}
									//a columns for this value is not hide
								}
							}

							var index = grid.conditions[col].blackList.findIndex(colvalue);
							if (show === 0) { //add to black list
								if (oper === "push") {
									if (index === -1) {//if it not already there
										grid.conditions[col].blackList.push(colvalue);
									}
								}
							} else { //remove from black List
								if (oper === "pop") {
									if (index != -1) {
										grid.conditions[col].blackList.splice(index, 1)
									}
								}
							}

						}
					}

				}
			}
		}

		if (oper === "push") {
			if (grid.conditions[colNumber].blackList.findIndex(value) === -1)
				grid.conditions[colNumber].blackList.push(value);
		} else { //pop
			var index = grid.conditions[colNumber].blackList.findIndex(value);
			if (index != -1)
				grid.conditions[colNumber].blackList.splice(index, 1);
		}

	}


	OAT.showPopup = function (pos, _self, _type, div) {

		var toAppend = [];


		var refresh = function () {
			jQuery(".oat_winrect_container").css({ display: "none" });
		}

		var colNumber = _self.number;
		if (OAT_JS.grid.gridData[_self.grid.UcId].redrawHeader){
			var columnCount = 0
			for( var t=0; t<_self.grid.columns.length; t++){
				if (OAT_JS.grid.gridData[_self.grid.UcId].columnVisible[t])
					columnCount = columnCount + 1
				if (_self.grid.columns[t].getAttribute("dataField") == _self.dataField)
					colNumber = columnCount-1
			}		
		}

		var coords = pos;
		var event = pos;

		if (_self.grid.isSD) { //android
			jQuery(".oat_winrect_container").css({ left: "-1500px", top: jQuery(event.currentTarget).offset().top + "px" })
		} else {
			jQuery(".oat_winrect_container").css({ left: jQuery(event.currentTarget).offset().left + "px", top: jQuery(event.currentTarget).offset().top + "px" })
		}

		OAT.Dom.clear(div);
		toAppend.push(div);
		/* contents */

		//add title
		jQuery(".oat_winrect_title").find(".winrect_title_label").remove()

		var spantitle = OAT.Dom.create("label");
		if (_self.grid.isSD) { //android
			jQuery(".oat_winrect_container").addClass("oat_winrect_container_small")
			spantitle.setAttribute("class", "winrect_title_label winrect_title_label_small");
		} else {
			spantitle.setAttribute("class", "winrect_title_label");
		}
		OAT.addTextNode(spantitle, _self.grid.columns[colNumber].getAttribute("displayName"));
		jQuery(".oat_winrect_title").append(spantitle)

		
		var cached = Math.floor(Math.random() * 10000)
		
		if (!_self.grid.disableColumnSort) {
			var div_order = document.createElement("div");
			div_order.setAttribute("class", "first_popup_subdiv");

			var asc = OAT.Dom.radio("order");
			
			var ascForId = "pivot_order_asc" + "_" + _self.grid.ContainerName + "_" + _self.grid.TableDataFilds[_self.number] + cached;
			asc.id = ascForId;
			asc.checked = (_self.grid.conditions[colNumber].sort === 2);  // _self.grid.conditions[colNumber] puede dar undefined
			OAT.Dom.attach(asc, "change", function () { });
			OAT.Dom.attach(asc, "click", function () {
				var previousSortValue = _self.grid.conditions[colNumber].sort;
				_self.grid.sort(colNumber, OAT.GridData.SORT_ASC, _self.number);
				var currentSortValue = _self.grid.conditions[colNumber].sort;
				OAT.saveState(_self, true);
				if (qv.util.isGeneXusPreview()) {
					if (currentSortValue != previousSortValue && previousSortValue != OAT.GridData.SORT_NONE) {		// First ascending sort must not fire event
						try {
							var datastr = "<DATA event=\"OrderChanged\" name=\"" + _self.grid.columns[_self.number].getAttribute("name") + "\" displayName=\"" + _self.grid.columns[_self.number].getAttribute("displayName") + "\"  order=\"ascending\">"
							datastr = datastr + "</DATA>"
							window.external.SendText(qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].ControlName, datastr);
						} catch (error) { }
					}
				}
				if (_self.grid.serverPaging) {
					var dataFieldId = _self.grid.columns[colNumber].getAttribute("dataField"); //OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[_self.number];//_self.grid.columns[colNumber].getAttribute("dataField")
					self.getDataForTable(_self.grid.UcId, 1, _self.grid.rowsPerPage, false, dataFieldId, "Ascending", "", "")
					var idI = "i_" + this.getAttribute("id");
					var inputAsc = document.getElementById(idI);
					inputAsc.textContent = "radio_button_checked";
					var inputDsc = document.getElementById(idI.replace("asc", "desc"));
					inputDsc.textContent = "radio_button_unchecked";
				}
			});
			div_order.appendChild(asc);

			var alabel = OAT.Dom.create("label");
			alabel.htmlFor = ascForId;
			
			var IStyle = gx.util.browser.isIE() ? "top:-10px;" : ""; 
			OAT.addImageNode(alabel, (_self.grid.conditions[colNumber].sort === 2)?"radio_button_checked":"radio_button_unchecked", IStyle, "i_"+ascForId);
			OAT.addTextNode(alabel, gx.getMessage("GXPL_QViewerJSAscending"))
			div_order.appendChild(alabel);
			div_order.appendChild(OAT.Dom.create("br"));
			
			var desc = OAT.Dom.radio("order");
			var dscForId = "pivot_order_desc" + "_" + _self.grid.ContainerName + "_" + _self.grid.TableDataFilds[_self.number] + cached;
			desc.id = dscForId;
			desc.checked = (_self.grid.conditions[colNumber].sort === 3);
			OAT.Dom.attach(desc, "change", function () { });
			OAT.Dom.attach(desc, "click", function () {
				var previousSortValue = _self.grid.conditions[colNumber].sort;
				_self.grid.sort(colNumber, OAT.GridData.SORT_DESC, _self.number);
				var currentSortValue = _self.grid.conditions[colNumber].sort;
				OAT.saveState(_self, true);
				if (qv.util.isGeneXusPreview()) {
					if (currentSortValue != previousSortValue) {
						try {
							var datastr = "<DATA event=\"OrderChanged\" name=\"" + _self.grid.columns[_self.number].getAttribute("name") + "\" displayName=\"" + _self.grid.columns[_self.number].getAttribute("displayName") + "\"  order=\"descending\">"
							datastr = datastr + "</DATA>"
							window.external.SendText(qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].ControlName, datastr);
						} catch (error) { }
					}
				}
				if (_self.grid.serverPaging) {
					var dataFieldId = _self.grid.columns[colNumber].getAttribute("dataField"); //OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[_self.number];//_self.grid.columns[colNumber].getAttribute("dataField") //dataField
					self.getDataForTable(_self.grid.UcId, 1, _self.grid.rowsPerPage, false, dataFieldId, "Descending", "", "");
					var idI = "i_" + this.getAttribute("id");
					var inputDsc = document.getElementById(idI);
					inputDsc.textContent = "radio_button_checked";
					var inputAsc = document.getElementById(idI.replace("desc", "asc"));
					inputAsc.textContent = "radio_button_unchecked";
				}
			});
			var dlabel = OAT.Dom.create("label");
			dlabel.htmlFor = dscForId;
			OAT.addImageNode(dlabel, (_self.grid.conditions[colNumber].sort === 3)?"radio_button_checked":"radio_button_unchecked", IStyle, "i_"+dscForId);
			OAT.addTextNode(dlabel, gx.getMessage("GXPL_QViewerJSDescending"))

			div_order.appendChild(desc);
			div_order.appendChild(dlabel);

			toAppend.push(div_order);

			if (self.header.length > 1) {
				var hr4 = OAT.Dom.create("hr", {});
				//begin drag options
				toAppend.push(hr4);
			}
		}

		var hr3 = OAT.Dom.create("hr", {});

		//to left
		var dragDiv = OAT.Dom.create("div");
		if (_self.grid.disableColumnSort) {
			dragDiv.setAttribute("class", "first_popup_subdiv");
		}
		if ((_self.container.parentNode.cellIndex > 0)) {

			var dragDiv_L_sel_div = document.createElement("div");
			dragDiv_L_sel_div.setAttribute("class", "move_item_img");

			OAT.Dom.attach(dragDiv_L_sel_div, "click", function () {
				var origen = _self.container.parentNode.cellIndex; //the real position of the item click
				var destino = origen - 1;
				var i1 = 0;
				var i2 = 0;

				var strDestino = _self.container.parentNode.parentNode.children[destino].getAttribute('title_v');
				for (var i = 0; i < _self.grid.header.cells.length; i++) {
					if (_self.container.children[0].getAttribute('title_v') === _self.grid.header.cells[i].value.textContent.replace(/\u00A0/g, " ")) {
						i1 = i; //pos on cell array
					}
					if (strDestino === _self.grid.header.cells[i].value.textContent.replace(/\u00A0/g, " ")) {
						i2 = i;
					}
				}

				_self.grid.header.cells[i1].html.parentNode.insertBefore(_self.grid.header.cells[i1].html, _self.grid.header.cells[i2].html);

				if (_self.grid.serverPaging) {
					OAT_JS.grid.gridData[_self.grid.UcId].redrawHeader = true;
					for (var i = 0; i < _self.grid.rows.length; i++) {
						_self.grid.rows[i].cells[i1].html.parentNode.insertBefore(_self.grid.rows[i].cells[i1].html, _self.grid.rows[i].cells[i2].html);
					}
				} else {
					var datRow = jQuery("#" + _self.grid.controlName + " tr")[1];
					for (var i = 0; i < _self.grid.rows[0].cells.length; i++) {
						if ((datRow.children[origen].getAttribute('title') === _self.grid.rows[0].cells[i].value.textContent.replace(/\u00A0/g, " "))
							|| (!isNaN(parseInt(datRow.children[origen].getAttribute('title'))) && (parseInt(datRow.children[origen].getAttribute('title')) === parseInt(_self.grid.rows[0].cells[i].value.textContent.replace(/\u00A0/g, " "))))) {
							i1 = i;
						}
						if ((datRow.children[destino].getAttribute('title') === _self.grid.rows[0].cells[i].value.textContent.replace(/\u00A0/g, " "))
							|| (!isNaN(parseInt(datRow.children[destino].getAttribute('title'))) && (parseInt(datRow.children[destino].getAttribute('title')) === parseInt(_self.grid.rows[0].cells[i].value.textContent.replace(/\u00A0/g, " "))))) {
							i2 = i;
						}
					}

					var newi = (i1 < i2 ? i2 - 1 : i2);

					newi = _self.grid.columnsDataType.length - 1 - newi;
					for (var i = 0; i < _self.grid.rows.length; i++) {
						_self.grid.rows[i].cells[i1].html.parentNode.insertBefore(_self.grid.rows[i].cells[i1].html, _self.grid.rows[i].cells[i2].html);
						var cell = _self.grid.rows[i].cells[i1];
						_self.grid.rows[i].cells.splice(i1, 1);
						_self.grid.rows[i].cells.splice(newi, 0, cell);
					}
				}

				var dataFieldsPos = [];
				for (var idF = 0; idF < jQuery("#" + _self.grid.controlName).find("thead td").length; idF++) {
					dataFieldsPos.push(jQuery("#" + _self.grid.controlName).find("thead td")[idF].getAttribute("dataField"))
				}
				OAT_JS.grid.setDataFieldPosition(_self.grid.UcId, dataFieldsPos);
				refresh();
			});

			var draglabel = OAT.Dom.create("label");
			OAT.addTextNode(draglabel, gx.getMessage("GXPL_QViewerJSMoveColumnToLeft"))
			draglabel.htmlFor = "move_column_to_left" + cached;
			dragDiv_L_sel_div.appendChild(draglabel);

			OAT.Dom.append([dragDiv, dragDiv_L_sel_div]);
			if (_self.container.parentNode.cellIndex >= _self.grid.header.cells.length - 2) { 
				toAppend.push(dragDiv);
			}
		}

		//to right
		if (_self.container.parentNode.cellIndex < _self.grid.header.cells.length - 1) { //si no es la ultima columna

			var dragDiv_R_sel_div = document.createElement("div");
			dragDiv_R_sel_div.setAttribute("class", "move_item_img");

			OAT.Dom.attach(dragDiv_R_sel_div, "click", function () {
				var origen = _self.container.parentNode.cellIndex; //the real position of the item click
				if (origen == -1){
					for (var c = 0; c < _self.grid.html.tHead.rows[0].cells.length; c++){
						if (_self.container.children[0].getAttribute('title_v') == _self.grid.html.tHead.rows[0].cells[c].getAttribute('title_v')){
							origen = c;
						}
					}
				}
				var destino = origen + 1;
				var i1 = 0;
				var i2 = 0;

				//var strDestino = _self.container.parentNode.parentNode.children[destino].textContent;
				var strDestino;
				if (_self.container.parentNode.parentNode != undefined){
					strDestino = _self.container.parentNode.parentNode.children[destino].getAttribute('title_v');
				} else {
					strDestino = _self.grid.html.tHead.rows[0].cells[destino].getAttribute('title_v')
				}
				for (var i = 0; i < _self.grid.header.cells.length; i++) {
					if (_self.container.children[0].getAttribute('title_v') /*textContent*/ === _self.grid.header.cells[i].value.textContent.replace(/\u00A0/g, " ")) {
						i1 = i; //pos on cell array
					}
					if (strDestino === _self.grid.header.cells[i].value.textContent.replace(/\u00A0/g, " ")) {
						i2 = i;
					}
				}

				_self.grid.header.cells[i1].html.parentNode.insertBefore(_self.grid.header.cells[i2].html, _self.grid.header.cells[i1].html);

				if (_self.grid.serverPaging) {
					OAT_JS.grid.gridData[_self.grid.UcId].redrawHeader = true;
					for (var i = 0; i < _self.grid.rows.length; i++) {
						_self.grid.rows[i].cells[i1].html.parentNode.insertBefore(_self.grid.rows[i].cells[i2].html, _self.grid.rows[i].cells[i1].html);
					}
				} else {
					var datRow = jQuery("#" + _self.grid.controlName + " tr")[1];
					for (var i = 0; i < _self.grid.rows[0].cells.length; i++) {
						if ((datRow.children[origen].getAttribute('title') === _self.grid.rows[0].cells[i].value.textContent.replace(/\u00A0/g, " "))
							|| (!isNaN(parseInt(datRow.children[origen].getAttribute('title'))) && (parseInt(datRow.children[origen].getAttribute('title')) === parseInt(_self.grid.rows[0].cells[i].value.textContent.replace(/\u00A0/g, " "))))) {
							i1 = i;
						}
						if ((datRow.children[destino].getAttribute('title') === _self.grid.rows[0].cells[i].value.textContent.replace(/\u00A0/g, " "))
							|| (!isNaN(parseInt(datRow.children[destino].getAttribute('title'))) && (parseInt(datRow.children[destino].getAttribute('title')) === parseInt(_self.grid.rows[0].cells[i].value.textContent.replace(/\u00A0/g, " "))))) {
							i2 = i;
						}
					}

					var newi = (i1 < i2 ? i2 - 1 : i2);

					newi = _self.grid.columnsDataType.length - 1 - newi;
					for (var i = 0; i < _self.grid.rows.length; i++) {
						_self.grid.rows[i].cells[i1].html.parentNode.insertBefore(_self.grid.rows[i].cells[i2].html, _self.grid.rows[i].cells[i1].html);
						var cell = _self.grid.rows[i].cells[i1];
						_self.grid.rows[i].cells.splice(i1, 1);
						_self.grid.rows[i].cells.splice(newi, 0, cell);
					}
				}
				var dataFieldsPos = [];
				for (var idF = 0; idF < jQuery("#" + _self.grid.controlName).find("thead td").length; idF++) {
					dataFieldsPos.push(jQuery("#" + _self.grid.controlName).find("thead td")[idF].getAttribute("dataField"))
				}
				OAT_JS.grid.setDataFieldPosition(_self.grid.UcId, dataFieldsPos);
				refresh();
			});


			var draglabelR = OAT.Dom.create("label");
			OAT.addTextNode(draglabelR, gx.getMessage("GXPL_QViewerJSMoveColumnToRight"))
			draglabelR.htmlFor = "move_column_to_right" + cached;
			dragDiv_R_sel_div.appendChild(draglabelR);
			OAT.Dom.append([dragDiv, dragDiv_R_sel_div]);
			toAppend.push(dragDiv);
		}
		//end drag options

		if (OAT.gridStateChanged(_self)) {

			var restoreview = OAT.Dom.create("div");
			var restoreview_sel_div = document.createElement("div");

			OAT.Dom.attach(restoreview_sel_div, "click", function () {
				if (!_self.grid.serverPaging) {
					OAT.RestoreGridRow(_self);
					OAT.RestoreGridOrder(_self);
					OAT.RestoreGridColumns(_self);
					OAT.saveState(_self, "1");
					refresh()
				} else {
					self.getDataForTable(_self.grid.UcId, 1, _self.grid.rowsPerPage, true, "", "", "", "", true)
					refresh()
				}
			});

			var rl = OAT.Dom.create("label");
			OAT.addTextNode(rl, gx.getMessage("GXPL_QViewerJSRestoreDefaultView"))
			rl.htmlFor = "pivot_checkbox_restoreview";
			restoreview_sel_div.appendChild(rl);
			OAT.Dom.append([restoreview, restoreview_sel_div]);
			toAppend.push(restoreview);
		}

		var distinct = OAT.Dom.create("div");
		distinct.setAttribute("class", "last_div_popup");
		OAT.distinctDivs(_self, distinct);
		toAppend.push(hr3);

		toAppend.push(distinct);


		OAT.Dom.append(toAppend);




		//for smart device center pop-up
		if (_self.grid.isSD) {//android
			setTimeout(function () {

				var screenWidth = window.innerWidth;
				var initialPopUpWidth = jQuery(".oat_winrect_container")[0].clientWidth


				if (initialPopUpWidth == 0) {
					var last = jQuery(".oat_winrect_container").length;
					initialPopUpWidth = jQuery(".oat_winrect_container")[last - 1].clientWidth
				}


				if (initialPopUpWidth < 220) {
					initialPopUpWidth = 220
				}

				var padding = (screenWidth - initialPopUpWidth) / 2 + jQuery(window).scrollLeft()

				jQuery(".oat_winrect_container").css({ left: padding + "px", width: initialPopUpWidth + "px" })


			}, 50)
		}

	}

	OAT.distinctDivs = function (_self, div) { /* set of distinct values checkboxes */
		var colNumber = _self.grid.columns.length - 1 - _self.number;
		var realColNumber = _self.container.parentNode.cellIndex; //the real position of the item click
		if (_self.grid.serverPaging) {
			colNumber = realColNumber
		}
		if (!_self.grid.serverPaging) {
			try {
				var datRow = jQuery("#" + _self.grid.controlName + " tr")[1];
				for (var i = 0; i < _self.grid.columns.length; i++) {
					//var val1 = datRow.children[realColNumber].textContent
					var val1 = datRow.children[realColNumber].getAttribute('title')
					var val2 = _self.grid.rows[0].cells[i].value.textContent.replace(/\u00A0/g, " ")
					if (val1 === val2) {
						colNumber = i;
					}
				}
			} catch (ERROR) { }
		}
		//var colNumber = _self.grid.rows[0].cells.length - 1 - _self.number;
		var getPair = function (text, id) {
			var div = OAT.Dom.create("div");
			var ch = OAT.Dom.create("input");
			//ch.type = "checkbox";
			//ch.id = id;
			var t = OAT.Dom.create("label");

			OAT.addTextNode(t, text)
			t.htmlFor = id;
			//div.appendChild(ch);
			div.appendChild(t);
			return [div, ch];
		}
		
		var getPairWithIcon = function (text, id, checked_value) {
			var div = OAT.Dom.create("div");
			var ch = OAT.Dom.create("input");
			//ch.type = "checkbox";
			//ch.id = id;
			var t = OAT.Dom.create("label");

			OAT.addTextNode(t, text)
			t.htmlFor = id;
			//div.appendChild(ch);
			
			OAT.addImageNode(div, checked_value ? "check_box" : "check_box_outline_blank", "");
			
			div.appendChild(t);
			return [div, ch];
		}

		var getRef = function (ch, value) {
			return function () {
				if (ch.checked) {
					OAT.ShowGridRow(_self, colNumber, value);
					OAT.actualizeBlackList("pop", _self.grid, colNumber, value, _self.grid.serverPaging);
				} else {
					OAT.HideGridRow(_self, colNumber, value);
					OAT.actualizeBlackList("push", _self.grid, colNumber, value, _self.grid.serverPaging);
				}
				OAT.onFilteredChangedEventHandle(_self, colNumber);
				OAT.saveState(_self, true);
			}
		}

		var getRefBool = function (checked, value) {
			var oper = "pop";
			if (checked) {
				if (!_self.grid.serverPaging) {
					OAT.ShowGridRow(_self, colNumber, value);
				}
				OAT.actualizeBlackList("pop", _self.grid, colNumber, value, _self.grid.serverPaging);
			} else {
				if (!_self.grid.serverPaging) {
					OAT.HideGridRow(_self, colNumber, value);
				}
				oper = "push";
				OAT.actualizeBlackList("push", _self.grid, colNumber, value, _self.grid.serverPaging);
			}

			if (_self.grid.serverPaging) {
				var dataFieldId = OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber];//_self.grid.columns[colNumber].getAttribute("dataField")
				self.getDataForTable(_self.grid.UcId, 1, _self.grid.rowsPerPage, true, "", "", dataFieldId, { op: oper, values: value })
			}

			OAT.onFilteredChangedEventHandle(_self, colNumber);
			OAT.saveState(_self, true, colNumber);
		}

		var allRef = function () {
			if (!_self.grid.serverPaging) {
				_self.grid.conditions[colNumber].blackList = [];
				OAT.RestoreGridRow(_self);
				OAT.saveState(_self, true, colNumber)
			} else {
				var dataFieldId = OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber];
				//_self.grid.conditions[colNumber].blackList = [];
				self.getDataForTable(_self.grid.UcId, 1, _self.grid.rowsPerPage, true, "", "", dataFieldId, { op: "all", values: [] })
			}
			OAT.onFilteredChangedEventHandle(_self, colNumber);
			OAT.distinctDivs(_self, div);
		}

		var noneRef = function () {
			if (!_self.grid.serverPaging) {
				_self.grid.conditions[colNumber].blackList = [];
				for (var i = 0; i < _self.grid.rows.length; i++) {
					for (var col = 0; col < _self.grid.columns.length; col++) {
						if (_self.grid.conditions[col].blackList.findIndex(_self.grid.rows[i].cells[col].options.value) === -1)
							_self.grid.conditions[col].blackList.push(_self.grid.rows[i].cells[col].options.value);
					}
					OAT.HideGridRow(_self, colNumber, _self.grid.rows[i].cells[colNumber].options.value);
				}
			} else {
				var dataFieldId = OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber];
				self.getDataForTable(_self.grid.UcId, 1, _self.grid.rowsPerPage, true, "", "", dataFieldId, { op: "none", values: [] })
			}

			OAT.saveState(_self, true, colNumber);
			OAT.onFilteredChangedEventHandle(_self, colNumber);
			OAT.distinctDivs(_self, div);
		}

		var reverseRef = function () {
			if (!_self.grid.serverPaging) {
				var newBL = [];
				for (var i = 0; i < _self.grid.rows.length; i++) {
					var val = _self.grid.rows[i].cells[colNumber].options.value;
					if (_self.grid.conditions[colNumber].blackList.findIndex(val) == -1) { newBL.push(val); }
				}

				for (var col = 0; col < _self.grid.columns.length; col++) {
					_self.grid.conditions[col].blackList = [];
				}

				_self.grid.conditions[colNumber].blackList = newBL;

				for (var i = 0; i < _self.grid.rows.length; i++) {
					_self.grid.rows[i].html.style.display = "";
					_self.grid.rows[i].html.setAttribute('visibQ', 'tt');
				}
				OAT.filterRows(_self.grid);
			} else {
				var dataFieldId = OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber];
				self.getDataForTable(_self.grid.UcId, 1, _self.grid.rowsPerPage, true, "", "", dataFieldId, { op: "reverse", values: [] })
			}

			OAT.saveState(_self, true, colNumber);
			OAT.distinctDivs(_self, div);
			OAT.onFilteredChangedEventHandle(_self, colNumber);
		}

		var searchFilterClick = function () {
			self.getValuesForColumn(_self.grid.UcId, colNumber, this.value)
		}

		OAT.Dom.clear(div);
		var d = OAT.Dom.create("div");
		d.setAttribute("class", "div_buttons_popup");

		var all = document.createElement("button");
		all.textContent = gx.getMessage("GXPL_QViewerJSAll");
		all.setAttribute("class", "btn");
		jQuery(all).click(allRef);

		var none = document.createElement("button");
		none.textContent = gx.getMessage("GXPL_QViewerJSNone");
		none.setAttribute("class", "btn");
		jQuery(none).click(noneRef);

		var reverse = document.createElement("button");
		reverse.textContent = gx.getMessage("GXPL_QViewerJSReverse");
		reverse.setAttribute("class", "btn");
		jQuery(reverse).click(reverseRef);

		OAT.Dom.append([d, all, none, reverse], [div, d]);

		var d2 = OAT.Dom.create("div");
		d2.setAttribute("class", "div_filter_input");

		if (_self.grid.serverPaging) {
			var searchInput = document.createElement("input");
			searchInput.textContent = "none";
			searchInput.setAttribute("class", "search_input");
			searchInput.setAttribute("type", "text");
			searchInput.setAttribute("label", "Search filter...");
			searchInput.setAttribute("title", "Search filter...");
			searchInput.setAttribute("placeholder", "Search filter...");
			searchInput.setAttribute("id", _self.grid.UcId + OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber]);
			jQuery(searchInput).keyup(searchFilterClick);

			OAT.Dom.append([d2, searchInput], [div, d2]);
		}

		var fixHeigthDiv = OAT.Dom.create("div");

		if (!_self.grid.serverPaging) {
			var previusValue = [];
			for (var i = 0; i < _self.grid.rows.length; i++) { /*_self.grid.rows[_self.number].cells.length*/
				if (previusValue.findIndex(_self.grid.rows[i].cells[colNumber].options.value) === -1) {
					var value = _self.grid.rows[i].cells[colNumber].options.value;
					var pict_value = _self.grid.rows[i].cells[colNumber].value.textContent;
					pict_value = pict_value.replace(/\&amp;/g, "&").replace(/\u00A0/g, " ")
					if (pict_value.length > 33) {
						var resto = (pict_value.substring(32, pict_value.length).trimpivot().length > 0) ? '...' : '';
						pict_value = pict_value.substring(0, 32) + resto
					}
					pict_value = pict_value.replace(/ /g, "\u00A0") + '\u00A0\u00A0\u00A0\u00A0\u00A0'
					var pair = getPair(pict_value, "pivot_distinct_" + i);
					pair[0].setAttribute('value', value);
					fixHeigthDiv.appendChild(pair[0]);

					var checked_value = (_self.grid.conditions[colNumber].blackList.findIndex(value) == -1);
					var class_check_div = (checked_value) ? "check_item_img" : "uncheck_item_img";
					if (_self.isSD) {//android
						var class_check_div = (checked_value) ? "check_item_img_small" : "uncheck_item_img_small";
					}

					pair[0].setAttribute("class", class_check_div);
					
					
					
					OAT.Dom.attach(pair[0], "click", function () {
						var checked = !(this.getAttribute("class") === "check_item_img");
						var newClass = (this.getAttribute("class") === "check_item_img") ? "uncheck_item_img" : "check_item_img";
						this.setAttribute("class", newClass);
						getRefBool(checked, this.getAttribute("value"));//this.textContent);          														
					});


					previusValue.push(_self.grid.rows[i].cells[colNumber].options.value);
				}
			}
			if (previusValue.length <= 9) {
				fixHeigthDiv.setAttribute("class", "pivot_popup_auto");
			} else {
				fixHeigthDiv.setAttribute("class", "pivot_popup_fix");
			}
		} else {
			var cantPairs = OAT_JS.grid.getCantDifferentValues(_self.grid.UcId, colNumber);
			for (var i = 0; i < cantPairs; i++) {
				var pairData = OAT_JS.grid.getDifferentValues(_self.grid.UcId, colNumber, i)
				if (pairData) {
					var value = pairData.value;
					var pict_value = pairData.pict_value;
					if ((pairData.value == "#NuN#") || (pict_value.trimpivot() == "")) {
						pict_value = pict_value + "\u00A0"
					}
					pict_value = pict_value.replace(/\&amp;/g, "&").replace(/\u00A0/g, " ")
					if (pict_value.length > 33) {
						var resto = (pict_value.substring(32, pict_value.length).trimpivot().length > 0) ? '...' : '';
						pict_value = pict_value.substring(0, 32) + resto
					}
					pict_value = pict_value.replace(/ /g, "\u00A0") + '\u00A0\u00A0\u00A0\u00A0\u00A0'
					
					var checked_value = pairData.checked;
					
					var pair = getPairWithIcon(pict_value, "pivot_distinct_" + i, checked_value);
					pair[0].setAttribute('value', value);
					fixHeigthDiv.appendChild(pair[0]);

					var class_check_div = (checked_value) ? "check_item_img" : "uncheck_item_img";
					if (_self.grid.isSD) {//android
						var class_check_div = (checked_value) ? "check_item_img_small" : "uncheck_item_img_small";
					}
					pair[0].setAttribute("class", class_check_div);
					
					
					
					OAT.Dom.attach(pair[0], "click", function () {
						var checkedClass = "check_item_img"
						var unCheckedClass = "uncheck_item_img"
						if (_self.grid.isSD) {//android
							checkedClass = "check_item_img_small"
							unCheckedClass = "uncheck_item_img_small"
						}
						var checked = !(this.getAttribute("class") === checkedClass);
						var newClass = (this.getAttribute("class") === checkedClass) ? unCheckedClass : checkedClass;
						this.setAttribute("class", newClass);
						
						jQuery(this).find("i")[0].textContent = checked ? "check_box" : "check_box_outline_blank";
						
						getRefBool(checked, this.getAttribute("value"));
					});
				}
			}
			if (OAT_JS.grid.getCantDifferentValues(_self.grid.UcId, colNumber) <= 9) {
				fixHeigthDiv.setAttribute("class", "pivot_popup_auto");
			} else {
				fixHeigthDiv.setAttribute("class", "pivot_popup_fix");
			}
			fixHeigthDiv.setAttribute("ucid", _self.grid.UcId);
			fixHeigthDiv.setAttribute("columnnumber", colNumber);
			fixHeigthDiv.setAttribute("id", "values_" + _self.grid.UcId + "_" + OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber])//_self.grid.UcId + "_" + colNumber)
		}


		div.appendChild(fixHeigthDiv);
	}


	OAT.appendNewPairToPopUp = function (_self, value, colNumber, checked, pict_value, dataField) {
		var getPair = function (text, id) {
			var div = OAT.Dom.create("div");
			var ch = OAT.Dom.create("input");
			var t = OAT.Dom.create("label");
			OAT.addTextNode(t, text)
			t.htmlFor = id;
			div.appendChild(t);
			return [div, ch];
		}
		
		var getPairWithIcon = function (text, id, checked_value) {
			var div = OAT.Dom.create("div");
			var ch = OAT.Dom.create("input");
			var t = OAT.Dom.create("label");
			OAT.addTextNode(t, text)
			t.htmlFor = id;
			OAT.addImageNode(div, checked_value ? "check_box" : "check_box_outline_blank", "");
			div.appendChild(t);
			return [div, ch];
		}

		var getRefBool = function (checked, value) {
			var oper = "pop";
			if (!checked) {
				oper = "push";
			}
			var filteredValues = _self.grid.conditions[colNumber].blackList
			self.getDataForTable(_self.grid.UcId, 1, _self.grid.rowsPerPage, true, "", "", dataField, { op: oper, values: value })

			OAT.onFilteredChangedEventHandle(_self, colNumber);
			OAT.saveState(_self, true, colNumber);
		}

		var pict_value = pict_value;
		if (value == "#NuN#") {
			pict_value = "\u00A0"
		}
		pict_value = pict_value.replace(/\&amp;/g, "&").replace(/\u00A0/g, " ")
		if (pict_value.length > 33) {
			var resto = (pict_value.substring(32, pict_value.length).trimpivot().length > 0) ? '...' : '';
			pict_value = pict_value.substring(0, 32) + resto
		}
		pict_value = pict_value.replace(/ /g, "\u00A0") + '\u00A0\u00A0\u00A0\u00A0\u00A0'
		var pair = getPairWithIcon(pict_value, "pivot_distinct_" + i, checked);
		pair[0].setAttribute('value', value);
		var fixHeigthDiv = jQuery("#values_" + _self.grid.UcId + "_" + dataField)[0]//colNumber)[0]
		fixHeigthDiv.appendChild(pair[0]);

		var checked_value = checked;
		var class_check_div = (checked_value) ? "check_item_img" : "uncheck_item_img";
		if (_self.grid.isSD) {//android
			var class_check_div = (checked_value) ? "check_item_img_small" : "uncheck_item_img_small";
		}
		pair[0].setAttribute("class", class_check_div);

		OAT.Dom.attach(pair[0], "click", function () {
			var checkedClass = "check_item_img"
			var unCheckedClass = "uncheck_item_img"
			if (_self.grid.isSD) {//android
				checkedClass = "check_item_img_small"
				unCheckedClass = "uncheck_item_img_small"
			}
			var checked = !(this.getAttribute("class") === checkedClass);
			var newClass = (this.getAttribute("class") === checkedClass) ? unCheckedClass : checkedClass;
			
			jQuery(this).find("i")[0].textContent = checked ? "check_box" : "check_box_outline_blank";
			
			this.setAttribute("class", newClass);
			getRefBool(checked, this.getAttribute("value"));
		});

	}

	OAT.removeAllPairsFromPopUp = function (_self, colNumber, withScroll) {
		var checkedClass = "check_item_img"
		var unCheckedClass = "uncheck_item_img"
		if (_self.grid.isSD) { //android
			checkedClass = "check_item_img_small"
			unCheckedClass = "uncheck_item_img_small"
		}

		jQuery("#values_" + _self.grid.UcId + "_" + OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber]).find("." + checkedClass).remove()
		jQuery("#values_" + _self.grid.UcId + "_" + OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber]).find("." + unCheckedClass).remove()

		jQuery(".last_div_popup ." + checkedClass).remove()
		jQuery(".last_div_popup ." + unCheckedClass).remove()

		//set class of pairs container
		if (withScroll) {
			jQuery("#values_" + _self.grid.UcId + "_" + OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber]).removeClass("pivot_popup_auto");
			jQuery("#values_" + _self.grid.UcId + "_" + OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber]).addClass("pivot_popup_fix");
		} else {
			jQuery("#values_" + _self.grid.UcId + "_" + OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber]).removeClass("pivot_popup_fix");
			jQuery("#values_" + _self.grid.UcId + "_" + OAT_JS.grid.gridData[_self.grid.UcId].columnDataField[colNumber]).addClass("pivot_popup_auto");
		}
	}
	/* statefull Rutines */
	OAT.onFilteredChangedEventHandle = function (self, dimensionNumber) {
		if (self.grid.serverPaging) {
			return OAT_JS.grid.setFilterChangedWhenServerPagination(self.grid.UcId, self.grid.columns[dimensionNumber]);
		} else {

			var datastr = "<DATA event=\"FilterChanged\" name=\"" + self.grid.columns[dimensionNumber].getAttribute("name") + "\" displayName=\"" + self.grid.columns[dimensionNumber].getAttribute("displayName") + "\">"

			var previusValue = [];
			for (var i = 0; i < self.grid.rows.length; i++) {
				if (previusValue.findIndex(self.grid.rows[i].cells[dimensionNumber].options.value) === -1) {
					if (self.grid.conditions[dimensionNumber].blackList.findIndex(self.grid.rows[i].cells[dimensionNumber].options.value) === -1) {
						datastr = datastr + '<VALUE>' + self.grid.rows[i].cells[dimensionNumber].options.value + '</VALUE>';
						previusValue.push(self.grid.rows[i].cells[dimensionNumber].options.value);
					}
				}
			}
			datastr = datastr + "</DATA>"
			var spl = self.grid.IdForQueryViewerCollection  //self.grid.controlName.toUpperCase().split("_")[0] + "_" + self.grid.controlName.split("_")[0];

			if (qv.util.isGeneXusPreview())
				window.external.SendText(self.QueryViewerCollection[self.IdForQueryViewerCollection].ControlName, datastr);

			if (self.grid.QueryViewerCollection[spl].FilterChanged) {
				var xml_doc = qv.util.dom.xmlDocument(datastr);
				var Node = qv.util.dom.selectXPathNode(xml_doc, "/DATA");
				self.grid.QueryViewerCollection[spl].FilterChangedData = {}
				self.grid.QueryViewerCollection[spl].FilterChangedData.Name = Node.getAttribute("name");
				self.grid.QueryViewerCollection[spl].FilterChangedData.SelectedValues = [];
				var valueIndex = -1;
				for (var i = 0; i < Node.childNodes.length; i++)
					if (Node.childNodes[i].nodeName == "VALUE") {
						valueIndex++;
						self.grid.QueryViewerCollection[spl].FilterChangedData.SelectedValues[valueIndex] = Node.childNodes[i].firstChild.nodeValue;
					}
				self.grid.QueryViewerCollection[spl].FilterChanged();
			}
		}
	}

	OAT.setClickEventHandlers = function (self, td, itemValue, MeasureOrDimension, dimensionNumber, itemData) {
		var span = jQuery(td).find("#span_txt_pivot")[0];
		if (span) {
			jQuery(td).data('itemValue', itemValue);
			jQuery(td).data('numberMorD', dimensionNumber);
			jQuery(td).data('itemInfo', itemData);
			
			jQuery(span).data('itemValue', itemValue);
			jQuery(span).data('typeMorD', MeasureOrDimension);
			jQuery(span).data('numberMorD', dimensionNumber);
			jQuery(span).data('itemInfo', itemData);
			var qViewer = self.grid.QueryViewerCollection[self.grid.IdForQueryViewerCollection];
			
			if (qViewer.ItemClick && qViewer.Metadata.Axes[dimensionNumber].RaiseItemClick) {
				span.onclick = function () { 
						OAT.onClickEventHandle(self, this); 
						if (OAT_JS.grid.gridData[self.grid.UcId].selection.Allow){ 
							OAT.onClickSelectNode(td, self);
						}
					}
				span.classList.add("gx-qv-clickable-element");
			} else if (OAT_JS.grid.gridData[self.grid.UcId].selection.Allow){ 
				span.onclick = function () { OAT.onClickSelectNode(td, self); }
			}
		}
	}

	var alreadyclicked = false;
	var alreadyclickedTimeout;
	OAT.onClickEventHandle = function (self, elemvalue) {
		if (alreadyclicked) {
			//double click
			alreadyclicked = false;
			clearTimeout(alreadyclickedTimeout);
			var datastr = OAT.ClickHandle(self, elemvalue);
			var spl = self.grid.IdForQueryViewerCollection
			qv.pivot.onItemClickEvent(self.grid.QueryViewerCollection[spl], datastr, true)
		} else {
			var delay = 300
			if (self.grid.QueryViewerCollection[self.grid.IdForQueryViewerCollection].ItemDoubleClick == undefined) {
				delay = 0
			}
			alreadyclicked = true;
			alreadyclickedTimeout = setTimeout(function () {
				alreadyclicked = false;
				//single click
				var datastr = OAT.ClickHandle(self, elemvalue);
				var spl = self.grid.IdForQueryViewerCollection;
				qv.pivot.onItemClickEvent(self.grid.QueryViewerCollection[spl], datastr, false);
			}, delay);
		}
	}

	OAT.onDblClickEventHandle = function (self, elemvalue) {
		var datastr = OAT.ClickHandle(self, elemvalue);
		var spl = self.grid.IdForQueryViewerCollection //self.grid.controlName.toUpperCase().split("_")[0] + "_" + self.grid.controlName.split("_")[0];
		qv.pivot.onItemClickEvent(self.grid.QueryViewerCollection[spl], datastr, true);
	}

	

	OAT.ClickHandle = function (self, elemvalue) {
		if (self.grid.HideDataFilds.length) {
			var spl = self.grid.IdForQueryViewerCollection
			var temp = self.grid.QueryViewerCollection[spl].getPivottableDataSync();

			self.grid.allRowsPivot = []
			self.grid.allFullRowsPivot = []
			var stringRecord = temp.split("<Record>")
			for (var i = 1; i < stringRecord.length; i++) {
				var recordData = [];
				var fullRecordData = [];
				for (var j = 0; j < self.grid.TableDataFilds.length; j++) {
					recordData[j] = "#NuN#"
					var dt = stringRecord[i].split("<" + self.grid.TableDataFilds[j] + ">")
					if (dt.length > 1) {
						var at = dt[1].split("</" + self.grid.TableDataFilds[j] + ">")
						recordData[j] = at[0]
						fullRecordData[j] = recordData[j]
					} else {
						if (stringRecord[i].indexOf("<" + self.grid.TableDataFilds[j] + "/>") >= 0) {
							recordData[j] = ""
							fullRecordData[j] = ""
						} else {
							recordData[j] = "#NuN#"
							fullRecordData[j] = "#NuN#"
						}
					}
				}
				self.grid.allRowsPivot.push(recordData);

				//add hide columns values
				for (var j = 0; j < self.grid.HideDataFilds.length; j++) {
					var dt = stringRecord[i].split("<" + self.grid.HideDataFilds[j] + ">")
					if (dt.length > 1) {
						var at = dt[1].split("</" + self.grid.HideDataFilds[j] + ">")
						fullRecordData[fullRecordData.length + j] = at[0]
					} else {
						if (stringRecord[i].indexOf("<" + self.grid.HideDataFilds[j] + "/>") >= 0) {
							fullRecordData[fullRecordData.length + j] = ""
						} else {
							fullRecordData[fullRecordData.length + j]  = "#NuN#"	
						}
					}
				}
				self.grid.allFullRowsPivot.push(fullRecordData);

			}
		}

		var pseudoRow = []

		var value = jQuery(elemvalue).data('itemValue');
		var type = jQuery(elemvalue).data('typeMorD');
		var number = jQuery(elemvalue).data('numberMorD');
		var columnNumber = jQuery(elemvalue).data('itemInfo');
		var selected = OAT.IsNodeSelected(self.cells[number].html);
		var datastr = "<DATA><ITEM type=\"" + type + "\" ";
		
		datastr = datastr + "name=\"" + self.grid.columns[number].getAttribute("name") + "\" ";
		datastr = datastr + "displayName=\"" + self.grid.columns[number].getAttribute("displayName") + "\" ";
		datastr = datastr + "selected=\"" + selected.toString() + "\" ";
		datastr = datastr + "location=\"rows\">"
		datastr = datastr + value


		datastr = datastr + "</ITEM>";

		datastr = datastr + "<CONTEXT>";
		datastr = datastr + "<RELATED>";
		for (var i = 0; i < self.grid.rows[columnNumber].cells.length; i++) {
			datastr = datastr + "<ITEM name=\"" + self.grid.columns[i].getAttribute("name") + "\">";
			datastr = datastr + "<VALUES";
			var existNullValue = false;
			var stringValues = "";
			
			if (self.grid.rows[columnNumber].cells[i].options.value != "#NuN#"){
				stringValues = stringValues + "<VALUE>" + self.grid.rows[columnNumber].cells[i].options.value + "</VALUE>";
			} else {
				existNullValue = true
			}
			pseudoRow.push(self.grid.rows[columnNumber].cells[i].options.value)
			
			if (existNullValue){
				datastr = datastr + " Null=\"true\""
			}
			datastr = datastr + ">" + stringValues 
			datastr = datastr + "</VALUES>";
			datastr = datastr + "</ITEM>";
		}
		if (self.grid.HideDataFilds.length) {
			var coinc = function (row1, row2) {
				for (var o = 0; o < row1.length; o++) {
					if ((row1[o] != undefined) && (row1[o] != row2[o])) {
						return false;
					}
				}
				return true;
			}
			for (var r = 0; r < self.grid.allFullRowsPivot.length; r++) {
				if (coinc(pseudoRow, self.grid.allFullRowsPivot[r])) {
					for (var h = 0; h < self.grid.HideDataFilds.length; h++) {
						datastr = datastr + "<ITEM name=\"" + self.grid.OrderFildsHidden[h] + "\">";
						datastr = datastr + "<VALUES";
						var existNullValue = false;
						var stringValues = "";
						
						if (self.grid.rows[columnNumber].cells[i].options.value != "#NuN#"){
							stringValues = stringValues + "<VALUE>" + self.grid.allFullRowsPivot[r][h + self.grid.rows[columnNumber].cells.length] + "</VALUE>";
						} else {
							existNullValue = true
						}
						
						if (existNullValue){
							datastr = datastr + " Null=\"true\""
						}
						datastr = datastr + ">" + stringValues 
						datastr = datastr + "</VALUES>";
						datastr = datastr + "</ITEM>";
					}
				}
			}

		}
		datastr = datastr + "</RELATED>";
		datastr = datastr + "<FILTERS>";
		datastr = datastr + "</FILTERS>";
		datastr = datastr + "</CONTEXT>";

		datastr = datastr + "</DATA>"

		return datastr;
	}

	OAT.onClickSelectNode = function (elemvalue, self) {
		 
		var value = jQuery(elemvalue).data('itemValue');
		var number = jQuery(elemvalue).data('numberMorD');
		var rowNumber = jQuery(elemvalue).data('itemInfo');
		
		var colNumber = OAT_JS.grid.gridData[self.grid.UcId].columnDataField.indexOf(self.grid.TableDataFilds[number]);
		
		if (OAT_JS.grid.gridData[self.grid.UcId].selection.Allow){ 
			OAT.SelectNodes(self, value, false, colNumber, rowNumber);
		}
			
	}


	OAT.SelectNodes = function(self, value, isRefresh, colNumber, rowNumber, selectedItemNumber, conditions) {
		if (rowNumber >= 0) {

			var row = jQuery("#" + self.grid.controlName + " tbody").find("tr")[rowNumber];

			if (OAT.IsNodeSelected(jQuery(row).find("td")[colNumber])) {
				OAT.ClearSelectedNodes(jQuery(self.grid.html));
				OAT_JS.grid.gridData[self.grid.UcId].selection.SelectedNode = [];
			} else {

				if (!isRefresh) {
					OAT.SetSelectedNodeBackgroundColor(jQuery(row).find("td")[colNumber], self.grid.selection.Color, jQuery(self.grid.html))

					//save selected node
					OAT_JS.grid.gridData[self.grid.UcId].selection.SelectedNode = []
					OAT_JS.grid.gridData[self.grid.UcId].selection.SelectedNode[0] = {
						value : value,
						dataField : OAT_JS.grid.gridData[self.grid.UcId].columnDataField[colNumber],
						rowData : [OAT_JS.grid.gridData[self.grid.UcId].rowsData[rowNumber]],
						clicked : true
					}
				} else {

					OAT.SetNodeBackgroundColor(jQuery(row).find("td")[colNumber], self.grid.selection.Color);
				}

				if (OAT_JS.grid.gridData[self.grid.UcId].selection.EntireLine) {
					for (var t = 0; t < self.grid.rows[rowNumber].cells.length; t++) {
						if (t != colNumber) {
							OAT.SetNodeBackgroundColor(jQuery(row).find("td")[t], OAT_JS.grid.gridData[self.grid.UcId].selection.Color)
						}
					}
				}
			}
		} else {

			//search for row
			if (!isRefresh)
				OAT_JS.grid.gridData[self.grid.UcId].selection.SelectedNode[selectedItemNumber] = {
					value : value,
					dataField : OAT_JS.grid.gridData[self.grid.UcId].columnDataField[colNumber],
					rowData : [],
					clicked : false,
					conditions : conditions
				}

			for (var i = 0; i < jQuery("#" + self.grid.controlName + " tbody").find("tr").length; i++) {

				var dataType = self.grid.columnsDataType[ self.grid.TableDataFilds.indexOf(OAT_JS.grid.gridData[self.grid.UcId].columnDataField[colNumber])];

				var cellValue = OAT_JS.grid.gridData[self.grid.UcId].rowsData[i][self.grid.TableDataFilds.indexOf(OAT_JS.grid.gridData[self.grid.UcId].columnDataField[colNumber])];
				var sameValue = false;

				if ((dataType == "real") || (dataType == "integer")) {
					sameValue = (parseFloat(value) == cellValue);
				} else {
					sameValue = (cellValue.trim() == value.trim());
				}

				if (sameValue) {
					//check all conditions
					if (OAT.checkConditions(self, OAT_JS.grid.gridData[self.grid.UcId].rowsData[i], conditions)) {
						var row = jQuery("#" + self.grid.controlName + " tbody").find("tr")[i];

						OAT.SetNodeBackgroundColor(jQuery(row).find("td")[colNumber], self.grid.selection.Color, jQuery(self.grid.html))
						//save selected node
						OAT_JS.grid.gridData[self.grid.UcId].selection.SelectedNode[selectedItemNumber].rowData.push(OAT_JS.grid.gridData[self.grid.UcId].rowsData[i]);

						if (OAT_JS.grid.gridData[self.grid.UcId].selection.EntireLine) {
							for (var t = 0; t < self.grid.rows[i].cells.length; t++) {
								if (t != colNumber) {
									OAT.SetNodeBackgroundColor(jQuery(row).find("td")[t], OAT_JS.grid.gridData[self.grid.UcId].selection.Color)
								}
							}
						}
					}
				}
			}
		}
	}
	
	OAT.checkConditions = function(self, rowData, conditions){
		var sameRow = true;
		
		for(var s = 0; s < conditions.length; s++){
			var colNumber = OAT_JS.grid.gridData[self.grid.UcId].columnDataField.indexOf(conditions[s].DataField);
			var dataType = self.grid.columnsDataType[ self.grid.TableDataFilds.indexOf(OAT_JS.grid.gridData[self.grid.UcId].columnDataField[colNumber])];
			var sameValue = true;
			if ((dataType == "real") || (dataType == "integer")) {
				sameValue = (parseFloat(conditions[s].Value) == parseFloat(rowData[colNumber]));
			} else {
				sameValue = (conditions[s].Value.trim() == rowData[colNumber].trim());
			}
			if (!sameValue){
				return false;
			}		
		}
		
		return sameRow;
	}
	
	OAT.RedrawSelectedNode = function(grid){
		if (OAT_JS.grid.gridData[grid.UcId].selection.SelectedNode) {
			OAT.ClearSelectedNodes(jQuery(grid.html));
			
			for (var s = 0; s < OAT_JS.grid.gridData[grid.UcId].selection.SelectedNode.length; s++) {
			
				if (OAT_JS.grid.gridData[grid.UcId].selection.SelectedNode[s].clicked){
					//search for row
					for (var r = 0; r < OAT_JS.grid.gridData[grid.UcId].selection.SelectedNode[s].rowData.length; r++){
						var selectedRow = OAT_JS.grid.gridData[grid.UcId].selection.SelectedNode[s].rowData[r];
						for (var i = 0; i < OAT_JS.grid.gridData[grid.UcId].rowsData.length; i++){
							var sameRow = true;
							for (var j = 0; j < OAT_JS.grid.gridData[grid.UcId].rowsData[i].length; j++)
							{
								if (OAT_JS.grid.gridData[grid.UcId].rowsData[i][j] != selectedRow[j])
									sameRow = false;
							}
				
							if (sameRow)
								OAT.SelectNodes({grid: grid}, OAT_JS.grid.gridData[grid.UcId].selection.SelectedNode[s].value, true, OAT_JS.grid.gridData[self.UcId].columnDataField.indexOf(OAT_JS.grid.gridData[grid.UcId].selection.SelectedNode[s].dataField), i)
							
						}
					}
				} else {
				
					OAT.SelectNodes({grid: grid}, OAT_JS.grid.gridData[grid.UcId].selection.SelectedNode[s].value, true, OAT_JS.grid.gridData[self.UcId].columnDataField.indexOf(OAT_JS.grid.gridData[grid.UcId].selection.SelectedNode[s].dataField), -1, s, OAT_JS.grid.gridData[grid.UcId].selection.SelectedNode[s].conditions);
				}
			}
		}
	}

	OAT.gridStateChanged = function (self) { //true is state changed
		if (!self.grid.serverPaging) {
			var changed = false;
			for (var tC = 0; tC < self.grid.columnsDataType.length; tC++) {
				if ((self.grid.header.cells[tC] != undefined) && (self.grid.header.cells[tC].html.style.display != "")) //some columns is hidden
					changed = true;
			}
			for (var tC = 0; tC < self.grid.conditions.length; tC++) {
				if (self.grid.conditions[tC].sort != 1) //some columns changes order
					changed = true;
				if (self.grid.conditions[tC].blackList.length > 0) //rows are hidden
					changed = true;
			}
			if ((self.grid.InitPageSize != undefined) && (self.grid.rowsPerPage != self.grid.InitPageSize)) return true;
			return changed;
		} else {
			return OAT_JS.grid.getStateChange(self.grid.UcId)
		}
	}


	OAT.createXMLMetadata = function (self, columnNumber, serverPagination) {

		var xml = '<OLAPCube format="' + "compact" + '" thousandsSeparator="' + "," + '" decimalSeparator="' + "." + '" dateFormat="' + "MDY" + '">';

		for (var iC = 0; iC <= self.grid.columns.length - 1; iC++) {
			var iCV = iC;
			/*if ((self.columnDataField != undefined) && (self.columnDataField.length == self.grid.columns.length)){
				for (var i =0; i <= self.grid.columns.length-1; i++){
					if (self.grid.columns[i].getAttribute("dataField") == self.columnDataField[iC]){
						iCV = i;
					}
				}
			} */

			xml = xml + '<OLAPDimension> ';

			xml = xml + '<name>' + self.grid.columns[iCV].getAttribute("name") + '</name> '
			xml = xml + '<displayName>' + self.grid.columns[iCV].getAttribute("displayName") + '</displayName> ';
			xml = xml + '<description>' + self.grid.columns[iCV].getAttribute("description") + '</description> ';
			xml = xml + '<dataField>' + self.grid.columns[iCV].getAttribute("dataField") + '</dataField> ';
			xml = xml + '<dataType>' + self.grid.columns[iCV].getAttribute("dataType") + '</dataType> ';
			if (self.grid.header.cells[iCV].html.style.display != "none") {
				xml = xml + '<defaultPosition>' + self.grid.columns[iCV].getAttribute("defaultPosition") + '</defaultPosition> ';
			} else {
				xml = xml + '<defaultPosition>' + "hidden" + '</defaultPosition> ';
			}
			xml = xml + '<validPositions>' + self.grid.columns[iCV].getAttribute("validPositions") + '</validPositions> ';
			xml = xml + '<summarize>' + self.grid.columns[iCV].getAttribute("summarize") + '</summarize> ';
			xml = xml + '<align>' + self.grid.columns[iCV].getAttribute("align") + '</align> ';

			if (self.grid.header.cells[iCV].html.style.display == "none") {
				xml = xml + '<hidden>true</hidden>'
			}

			if (self.grid.columns[iCV].getAttribute("picture") === "") {
				xml = xml + '<picture/> '
			} else {
				xml = xml + '<picture>' + self.grid.columns[iCV].getAttribute("picture") + '</picture> ';
			}

			if (self.grid.columns[iCV].getAttribute("picture") === "") {
				xml = xml + '<format/> ';
			} else {
				xml = xml + '<format>' + self.grid.columns[iCV].getAttribute("format") + '</format> ';
			}

			if (self.grid.conditions[iCV].sort === 2)
				xml = xml + '<order>ascending</order> '
			else if (self.grid.conditions[iCV].sort === 1)
				xml = xml + '<order>none</order> '
			else
				xml = xml + '<order>descending</order> '

			xml = xml + '<customOrder/> ';
			xml = xml + '<include> ';

			if (!serverPagination) {
				var previusValue = [];
				for (var i = 0; i < self.grid.rows.length; i++) {
					if (self.grid.rows[i].cells[iCV] != undefined) {
						if (previusValue.findIndex(self.grid.rows[i].cells[iCV].options.value) === -1) {
							if (self.grid.conditions[iCV].blackList.findIndex(self.grid.rows[i].cells[iCV].options.value) === -1) {
								xml = xml + '<value>' + self.grid.rows[i].cells[iCV].options.value.toString().trimpivot() + '</value> ';
								previusValue.push(self.grid.rows[i].cells[iCV].options.value);
							}
						}
					}
				}
			} else {
				var dF = self.grid.columns[iCV].getAttribute("dataField");
				if ((self.blackLists[dF].state != "none") && (self.blackLists[dF].state != "all")) {
					for (var i = 0; i < self.blackLists[dF].visibles.length; i++) {
						xml = xml + '<value>' + self.blackLists[dF].visibles[i].trimpivot() + '</value> ';
					}
				} else if (self.blackLists[dF].state != "none") {
					for (var i = 0; i < self.differentValues[dF].length; i++) {
						xml = xml + '<value>' + self.differentValues[dF][i].trimpivot() + '</value> ';
					}
				}
			}
			xml = xml + '<value>TOTAL</value> </include> <collapse/> ';

			xml = xml + '<hide> '
			if (!serverPagination) {
				for (var yu = 0; yu < self.grid.conditions[iCV].blackList.length; yu++) {
					//new code
					var isBlack = (iCV === 0); //this code is necessesary because of diferent representation of black list in pivot and table
					for (var l = 0; l < self.grid.rows.length; l++) {
						if (self.grid.rows[l].cells[iCV].options.value === self.grid.conditions[iCV].blackList[yu]) { //for rows with value "value"
							for (var col = 0; col < iCV; col++) { //for every column previuos to colNumber
								var colvalue = self.grid.rows[l].cells[col].options.value;
								if (self.grid.conditions[col].blackList.findIndex(colvalue) === -1) { //if the value is not in black list
									isBlack = true;
								}
							}
						}
					}
					//end of new code 6/6/2012
					if (isBlack === true) {
						xml = xml + '<value>' + self.grid.conditions[iCV].blackList[yu].toString().trimpivot() + '</value> ';
					}

				}
			} else {
				var dF = self.grid.columns[iCV].getAttribute("dataField");
				if ((self.blackLists[dF].state != "none") && (self.blackLists[dF].state != "all")) {
					for (var i = 0; i < self.blackLists[dF].hiddens.length; i++) {
						xml = xml + '<value>' + self.blackLists[dF].hiddens[i].trimpivot() + '</value> ';
					}
				} else if (self.blackLists[dF].state != "all") {
					for (var i = 0; i < self.differentValues[dF].length; i++) {
						xml = xml + '<value>' + self.differentValues[dF][i].trimpivot() + '</value> ';
					}
				}
			}
			xml = xml + '</hide> '

			var numCol = self.grid.columnsDataType.length - 1 - iCV;
			try {
				if (self.grid.header.cells[numCol] != undefined) {
					if (self.grid.header.cells[numCol].html.style.display === "") {
						xml = xml + '<condition>table</condition> ';
						xml = xml + '<filterbar>no</filterbar> ';
						xml = xml + '<position>' + self.columnDataField.indexOf(self.grid.columns[iCV].getAttribute("dataField")) + '</position>'
					} else {
						xml = xml + '<condition>none</condition> ';
						xml = xml + '<filterbar>yes</filterbar> ';
						xml = xml + '<position>' + self.columnDataField.indexOf(self.grid.columns[iCV].getAttribute("dataField")) + '</position>'
					}
				}
			} catch (ERROR) { }

			try {
				var axisOrder = self.columnDataField.indexOf(self.grid.columns[iCV].getAttribute("dataField")) + 1
				xml = xml + '<axisOrder>' + axisOrder + '</axisOrder>'
			} catch (ERROR) { }

			xml = xml + '<restoreview>no</restoreview> ';
			xml = xml + ' </OLAPDimension>';
		}


		xml = xml + "</OLAPCube>";

		return xml;
	}

	OAT.ExportToPdf = function (_self, fileName) {
		//count hidden columns
		var hiddenColumns = [];
		for (var i = 0; i < 1; i++) {
			var tRow = jQuery("#" + _self.grid.controlName + " tr")[i];
			for (var j = 0; j < tRow.children.length; j++) {
				if (tRow.children[j].style.display == "none") {
					hiddenColumns.push(j);
				}
			}
		}


		//calc max length of paper
		var hgt = 20 + jQuery("#" + _self.grid.controlName + " tr").length * 30 + 5;
		if (hgt < 841) {
			hgt = 841;
		}

		//calc max width of paper
		var wdt = 0;
		var tRow = jQuery("#" + _self.grid.controlName + " tr")[0].children.length - hiddenColumns.length;
		wdt = 20 + tRow * (30 + 65) + 5;
		if (wdt < 595) {
			wdt = 595;
		}

		//calculate columns width
		var columnsWidth = [];

		for (var i = 0; i < jQuery("#" + _self.grid.controlName + " tr").length; i++) {

			var tRow = jQuery("#" + _self.grid.controlName + " tr")[i];
			var columnInPdf = 0;
			for (var j = 0; j < tRow.children.length; j++) {//for every cell in the row
				var childText = tRow.children[j].textContent;
				var hidden = tRow.children[j].getAttribute('hidden');

				if (tRow.children[j].style.display != "none") {

					if (hidden === null) {
						if (columnsWidth[columnInPdf] == undefined) {
							columnsWidth[columnInPdf] = 30;
						}


						//japanese character
						var jChar = 0;
						for (var p = 0; p < childText.length; p++) {
							if (childText.charCodeAt(p) > 1000) {
								jChar++;
							}
						}

						if (jChar === 0) {
							if (childText.length > 14) {
								if (childText.length * 1.68 > columnsWidth[columnInPdf]) {
									columnsWidth[columnInPdf] = childText.length * 1.68;
								}
							}
						} else {
							var w = jChar * 2.8 + (childText.length - jChar) * 1.68;
							if (w > columnsWidth[columnInPdf]) {
								columnsWidth[columnInPdf] = w;
							}
						}

						columnInPdf = columnInPdf + 1;
					}
				}
			}
		}
		//recalculate width
		var nw = 0
		for (var i = 0; i < columnsWidth.length; i++) {
			nw = nw + columnsWidth[i] * 2.5 + 65;
		}
		nw = 20 + nw + 5;
		if (nw > wdt) {
			wdt = nw;
		}

		var getXOffset = function (colNro, columnsWidth) {
			var offset = 0;
			for (var i = 0; i < colNro; i++) {
				offset = offset + columnsWidth[i];
			}
			return offset;
		}

		var getYOffset = function (rowNro, rowsHeight) {
			var offsety = 0;
			for (var j = 0; j < rowNro; j++) {
				offsety = offsety + rowsHeight[j];
			}
			return offsety;
		}

		var doc;
		if (wdt <= hgt) {
			doc = new jsPDF('portrait', 'mm', 'a4', false, wdt, 792); //landscape or portrait
		} else {
			doc = new jsPDF('landscape', 'mm', 'a4', false, wdt, 792); //landscape or portrait
		}
		doc.setFontSize(8);

		doc.line(18, 13, 20 + getXOffset(jQuery("#" + _self.grid.controlName + " tr")[0].children.length - hiddenColumns.length, columnsWidth), 13);

		var y = -1;
		var nroPag = 1
		var verticalHeight = Math.min((jQuery("#" + _self.grid.controlName + " tr").length) - (nroPag - 1) * 26, 26)
		for (var i = 0; i < jQuery("#" + _self.grid.controlName + " tr").length; i++) {
			y++;
			var tRow = jQuery("#" + _self.grid.controlName + " tr")[i];

			var columnInPdf = 0;

			for (var j = 0; j < tRow.children.length; j++) {//for every cell in the row

				if (tRow.children[j].style.display != "none") {
					//vertical line
					doc.line(18 + getXOffset(columnInPdf, columnsWidth), 13, 18 + getXOffset(columnInPdf, columnsWidth), 23 + (verticalHeight - 1) * 10);

					var childText = OAT.removeIconFont(tRow.children[j].textContent);
					var hidden = tRow.children[j].getAttribute('hidden');

					var imgTxtData = []
					if (childText.charCodeAt(0) > 1000) {
						for (var cNo = 0; cNo < childText.length; cNo++) {
							imgTxtData[cNo] = OAT.getCharacterImg(childText.charCodeAt(cNo))
						}
					} else {
						var posI = -1;
						for (var p = 1; p < childText.length; p++) {
							if (childText.charCodeAt(p) > 1000) {
								posI = p;
								break;
							}
						}
						if (posI > 0) {
							var tempchildText = childText.substring(0, posI);
							var posE = 0
							for (var cNo = posI; cNo < childText.length; cNo++) {
								imgTxtData[posE] = OAT.getCharacterImg(childText.charCodeAt(cNo))
								posE++;
							}
							childText = tempchildText;
						}
					}

					//set styles
					var hasBackground = false;
					doc.setTextColor(0, 0, 0);
					doc.setFontStyle('normal');
					var IsTextAlignRight = !isNaN(parseFloat(childText));
					var textWidht = doc.getStringUnitWidth(childText);
					if ((tRow.children[j].getAttribute("style") != undefined) && (tRow.children[j].getAttribute("style") != null)) {
						var attributes = tRow.children[j].getAttribute("style").split(";");
						for (var at = 0; at < attributes.length; at++) {
							var detail = attributes[at].split(":");
							if (detail[0].replace(/^\s+|\s+$/g, '') === "color") {
								var rgb = detail[1].replace(/^\s+|\s+$/g, '');
								rgb = rgb.substring(4, rgb.length);
								rgb = rgb.substring(0, rgb.length - 1);
								doc.setTextColor(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]));

							} else if (detail[0].replace(/^\s+|\s+$/g, '') === "text-align") {
								//var alg = detail[1].replace(/^\s+|\s+$/g, '');
								IsTextAlignRight = (detail[1].replace(/^\s+|\s+$/g, '') == "right")
							} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-style") {
								doc.setFontStyle('italic')
							} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-weight") {
								if (detail[1].replace(/^\s+|\s+$/g, '') === "bold") {
									doc.setFontStyle('bold')
								}
							} else if (detail[0].replace(/^\s+|\s+$/g, '') === "background-color") {
								var rgb = detail[1].replace(/^\s+|\s+$/g, '');
								rgb = rgb.substring(4, rgb.length);
								rgb = rgb.substring(0, rgb.length - 1);
								doc.setFillColor(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]));
								hasBackground = true;
							} else if (detail[0].replace(/^\s+|\s+$/g, '') === "border-color") {
								var rgb = detail[1].replace(/^\s+|\s+$/g, '');
								rgb = rgb.substring(4, rgb.length);
								rgb = rgb.substring(0, rgb.length - 1);
								doc.setDrawColor(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]));
							}

						}
					}

					if ((hasBackground) && (j == (tRow.children.length - 1))) {//for the last column more width
						doc.rect(18 + getXOffset(columnInPdf, columnsWidth), 23 + (y - 1) * 10, 32, 10, 'FD');
					} else if (hasBackground) {
						doc.rect(18 + getXOffset(columnInPdf, columnsWidth), 23 + (y - 1) * 10, 30, 10, 'FD');
					}

					doc.setDrawColor(0, 0, 0);
					doc.setFontSize(8);

					if ((hidden === null) /*&& (tRow.children[j].style.display != "none")*/) {
						var preImage = 0;
						if (childText.charCodeAt(0) < 1000) {
							preImage = childText.length + 2
							if (IsTextAlignRight) {
								doc.text(20 + getXOffset(columnInPdf + 1, columnsWidth) - textWidht * 3 - 4, 20 + y * 10, childText);
							} else {
								doc.text(20 + getXOffset(columnInPdf, columnsWidth), 20 + y * 10, childText);
							}
						}
						if (imgTxtData.length > 0) {
							for (var cNo = 0; cNo < imgTxtData.length; cNo++) {
								doc.addImage(imgTxtData[cNo], 'JPEG', 20 + getXOffset(columnInPdf, columnsWidth) + preImage + cNo * 2.5, 20 + y * 10 - 2.5, 2.5, 2.5);
							}
						}
					}

					columnInPdf = columnInPdf + 1;

				}

			}
			//last vertical line
			doc.line(20 + getXOffset(tRow.children.length - hiddenColumns.length, columnsWidth), 13, 20 + getXOffset(tRow.children.length - hiddenColumns.length, columnsWidth), 23 + (verticalHeight - 1) * 10);

			doc.line(18, 23 + y * 10, 20 + getXOffset(tRow.children.length - hiddenColumns.length, columnsWidth), 23 + y * 10);
			if (y >= 25) {
				doc.setDrawColor(0, 0, 0)
				nroPag++
				verticalHeight = Math.min((jQuery("#" + _self.grid.controlName + " tr").length - 1) - (nroPag - 1) * 26 + 1, 26)
				y = -1
				doc.addPage()
				//top horizontal line
				doc.line(18, 13, 20 + getXOffset(jQuery("#" + _self.grid.controlName + " tr")[0].children.length - hiddenColumns.length, columnsWidth), 13);
			}
		}
		if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari
			doc.output('dataurlnewwindow');
		} else if (!gx.util.browser.isIE() || (9 < gx.util.browser.ieVersion())) {
			doc.save(fileName + '.pdf');
		} else {
			return doc.output();
		}
	}

	OAT.ExportToExcel = function (_self, fileName) {
		
		var table = '<table><tbody>'

		for (var i = 0; i < jQuery("#" + _self.grid.controlName + " tr").length; i++) {//for every row
			table = table + '<tr>';

			var tRow = jQuery("#" + _self.grid.controlName + " tr")[i];
			for (var j = 0; j < tRow.children.length; j++) {//for every cell in the row
				var childText;
				if (i === 0) {
					childText = tRow.children[j].getAttribute("title_v");
					if (childText === undefined) {
						childText = OAT.removeIconFont(tRow.children[j].textContent).trim();
					}
				} else {
					childText = tRow.children[j].getAttribute("title"); 
					//childText = OAT.removeIconFont(tRow.children[j].title/*.textContent*/).trim();
					if (childText === undefined) {
						childText = tRow.children[j].textContent;
					}
				}
				
				
				
				childText = childText.replace(/\u00A0/g, " ")
				var hidden = tRow.children[j].getAttribute('hidden');
				if (tRow.children[j].style.display != "none") {
					if (hidden === null) {
						var rowSpan = tRow.children[j].getAttribute('rowspan');
						var colSpan = tRow.children[j].getAttribute('colspan');

						var styleString = "";
						if ((tRow.children[j].getAttribute("style") != undefined) && (tRow.children[j].getAttribute("style") != null)) {
							styleString = " style=\"" + tRow.children[j].getAttribute("style") + "\" ";
						}
						
						if ((rowSpan === null) && (colSpan === null)) {
							table = table + '<td ' + styleString + '>' + childText + '</td>';
						} else if (colSpan === null) {
							table = table + '<td ' + styleString + ' rowspan="' + rowSpan + '">' + childText + '</td>';
						} else if (rowSpan === null) {
							table = table + '<td ' + styleString + ' colspan="' + colSpan + '">' + childText + '</td>';
						} else {
							table = table + '<td ' + styleString + ' colspan="' + colSpan + '" rowspan="' + rowSpan + '">' + childText + '</td>';
						}
					}
				}
			}

			table = table + '</tr>';
		}


		table = table + '</tbody></table>';
		
		//add header for special characters 
		var header = '<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"></head><body>'
		table = header + table + '</body>'
		
		var dtltbl = table;
		if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) {
			window.open('data:application/vnd.ms-excel,' + encodeURIComponent(dtltbl));
		} else if ((!gx.util.browser.isIE() || (9 < gx.util.browser.ieVersion()))) {
			//window.open('data:application/vnd.ms-excel,' + encodeURIComponent(dtltbl));
			var blob = new Blob([dtltbl], { type: "application/vnd.ms-excel" });
			saveAs(blob, fileName + ".xls");
		} else {
			return dtltbl;
		}


	}


	OAT.ExportToExcel2010 = function (_self, fileName, serverPagination, recordData, UcId) {


		function componentToHex(c) {
			var hex = c.toString(16);
			return hex.length == 1 ? "0" + hex : hex;
		}

		function rgbToHex(r, g, b) {
			return componentToHex(r) + componentToHex(g) + componentToHex(b);
		}



		dataTable = [];

		var rowsToAdd = jQuery("#" + _self.grid.controlName + " tr").length;
		if ((serverPagination != undefined) && (serverPagination)) {
			rowsToAdd = 1;
		}

		var hiddenColumns = []

		for (var i = 0; i < rowsToAdd; i++) {//for every row
			dataRow = [];

			var tRow = jQuery("#" + _self.grid.controlName + " tr")[i];
			for (var j = 0; j < tRow.children.length; j++) {//for every cell in the row
				var childText = tRow.children[j].textContent;
				var hidden = tRow.children[j].getAttribute('hidden');
				if (tRow.children[j].style.display != "none") {
					if (hidden === null) {
						var rowSpan = tRow.children[j].getAttribute('rowspan');
						var colSpan = tRow.children[j].getAttribute('colspan');

						var styleString = "";
						var cellObject = { value: childText };
						if ((tRow.children[j].getAttribute("style") != undefined) && (tRow.children[j].getAttribute("style") != null)) {
							var attributes = tRow.children[j].getAttribute("style").split(";");
							for (var at = 0; at < attributes.length; at++) {
								var detail = attributes[at].split(":");
								if (detail[0].replace(/^\s+|\s+$/g, '') === "color") {
									var rgb = detail[1].replace(/^\s+|\s+$/g, '');
									rgb = rgb.substring(4, rgb.length);
									rgb = rgb.substring(0, rgb.length - 1);
									var hex = rgbToHex(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]))
									cellObject.fontColor = hex;
								} else if (detail[0].replace(/^\s+|\s+$/g, '') === "text-align") {
									var alg = detail[1].replace(/^\s+|\s+$/g, '');
									cellObject.hAlign = alg;
								} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-style") {
									if (detail[1].replace(/^\s+|\s+$/g, '') === "italic") {
										cellObject.italic = 1;
									}
								} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-weight") {
									if (detail[1].replace(/^\s+|\s+$/g, '') === "bold") {
										cellObject.bold = 1;
									}
								} else if (detail[0].replace(/^\s+|\s+$/g, '') === "background-color") {
									var rgb = detail[1].replace(/^\s+|\s+$/g, '');
									rgb = rgb.substring(4, rgb.length);
									rgb = rgb.substring(0, rgb.length - 1);
									var hex = rgbToHex(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]))
									cellObject.fill = hex;
								}

							}
						}

						if ((rowSpan === null) && (colSpan === null)) {
							dataRow.push(cellObject)
						} else if (colSpan === null) {
							cellObject.rowSpan = parseInt(rowSpan);
							dataRow.push(cellObject)
						} else if (rowSpan === null) {
							cellObject.colSpan = parseInt(colSpan);
							dataRow.push(cellObject)
						} else {
							cellObject.colSpan = parseInt(colSpan);
							cellObject.rowSpan = parseInt(rowSpan);
							dataRow.push(cellObject)
						}
					}
				} else {
					hiddenColumns.push(j);
				}
			}

			dataTable.push(dataRow);
		}


		if ((serverPagination != undefined) && (serverPagination)) {
			for (var i = 0; i < recordData.length; i++) {
				dataRow = [];
				for (var j = 0; j < recordData[i].length; j++) {
					if (hiddenColumns.indexOf(j) == -1) {
						var childText = OAT.ApplyPictureValue(recordData[i][j], ""/*_self.grid.columnsDataType[j]*/, OAT_JS.grid.gridData[UcId].rowsMetadata.defaultPicture, OAT_JS.grid.gridData[UcId].rowsMetadata.forPivotCustomPicture[j]) /* Apply Picture */

						var td = OAT.Dom.create("td");

						td.setAttribute("title", childText);
						td = OAT.applyFormatValues(td, recordData[i][j], _self.grid.columnsDataType, j, OAT_JS.grid.gridData[UcId].rowsMetadata.formatValues, OAT_JS.grid.gridData[UcId].rowsMetadata.conditionalFormatsColumns, OAT_JS.grid.gridData[UcId].rowsMetadata.forPivotCustomFormat);

						//align numbers right
						if ((_self.grid.columnsDataType[j] != "character") || (_self.grid.columnsDataType[j] === 'date')) {
							td.style.textAlign = "right";
						} else {
							//td.style.textAlign = "left";
						}
						
						
						
						
						var cellObject = { value: childText };
						
						if ( !isNaN(parseFloat(childText)) && (_self.grid.columnsDataType[j] != "character")
							 && (_self.grid.columnsDataType[j] != "date") && (_self.grid.columnsDataType[j] != "datetime") ) 
						{
							cellObject = { value: parseFloat(childText) + "" };	
						}
						
						if ((td.getAttribute("style") != undefined) && (td.getAttribute("style") != null)) {
							var attributes = td.getAttribute("style").split(";");
							for (var at = 0; at < attributes.length; at++) {
								var detail = attributes[at].split(":");
								if (detail[0].replace(/^\s+|\s+$/g, '') === "color") {
									var rgb = detail[1].replace(/^\s+|\s+$/g, '');
									rgb = rgb.substring(4, rgb.length);
									rgb = rgb.substring(0, rgb.length - 1);
									var hex = rgbToHex(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]))
									cellObject.fontColor = hex;
								} else if (detail[0].replace(/^\s+|\s+$/g, '') === "text-align") {
									var alg = detail[1].replace(/^\s+|\s+$/g, '');
									cellObject.hAlign = alg;
								} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-style") {
									if (detail[1].replace(/^\s+|\s+$/g, '') === "italic") {
										cellObject.italic = 1;
									}
								} else if (detail[0].replace(/^\s+|\s+$/g, '') === "font-weight") {
									if (detail[1].replace(/^\s+|\s+$/g, '') === "bold") {
										cellObject.bold = 1;
									}
								} else if (detail[0].replace(/^\s+|\s+$/g, '') === "background-color") {
									var rgb = detail[1].replace(/^\s+|\s+$/g, '');
									rgb = rgb.substring(4, rgb.length);
									rgb = rgb.substring(0, rgb.length - 1);
									var hex = rgbToHex(parseInt(rgb.split(",")[0]), parseInt(rgb.split(",")[1]), parseInt(rgb.split(",")[2]))
									cellObject.fill = hex;
								}

							}
						}

						if ((_self.grid.columnsDataType[j] == "real") || (_self.grid.columnsDataType[j] == "integer")){
							cellObject.formatCode = OAT_JS.grid.gridData[UcId].rowsMetadata.forPivotCustomPicture[j].replace(/Z/g,"#").replace(/9/g, "0")
						}
						if (_self.grid.columnsDataType[j] == "date"){
							if (OAT_JS.grid.gridData[UcId].rowsMetadata.forPivotCustomPicture[j] != undefined){ 
								 var datePicture = OAT_JS.grid.gridData[UcId].rowsMetadata.forPivotCustomPicture[j].trim()
								 if (datePicture == "99/99/99")
								 {
								 	cellObject.formatCode = "mm/dd/yy"
								 }
								 if (datePicture == "99/99/9999"){
									cellObject.formatCode = "mm/dd/yyyy"
								 }
								 if (datePicture == "9999/99/99"){
									cellObject.formatCode = "yyyy/mm/dd"
								 }
							}
						}
						if (_self.grid.columnsDataType[j] == "datetime"){
							if (OAT_JS.grid.gridData[UcId].rowsMetadata.forPivotCustomPicture[j] != undefined){ 
								var datePicture = OAT_JS.grid.gridData[UcId].rowsMetadata.forPivotCustomPicture[j].trim().split(" ")
								var formatDatePicture = ""
								if (datePicture[0] == "99/99/99")
								{
								 	formatDatePicture = "mm/dd/yy"
								}
								if (datePicture[0] == "99/99/9999"){
									formatDatePicture = "mm/dd/yyyy"
								}
								if (datePicture[0] == "9999/99/99"){
									formatDatePicture = "yyyy/mm/dd"
								}
								
								if (datePicture[1] == "99")
								{
									cellObject.formatCode = formatDatePicture + " hh"
								}
								if (datePicture[1] == "99:99")
								{
									cellObject.formatCode = formatDatePicture + " hh:mm"									
								}
								if (datePicture[1] == "99:99:99")
								{
									cellObject.formatCode = formatDatePicture + " hh:mm:ss"		
								}								
								if (datePicture[1] == "99:99:99.999")
								{
									cellObject.formatCode = formatDatePicture + " hh:mm:ss"
								}								
							}
						}

						cellObject.genexusType = _self.grid.columnsDataType[j];
						cellObject.genexusPicture = OAT_JS.grid.gridData[UcId].rowsMetadata.forPivotCustomPicture[j];

						dataRow.push(cellObject)
					}
				}
				dataTable.push(dataRow);
			}
		}

		var sheet = xlsx({
			creator: 'Genexus',
			lastModifiedBy: 'Genexus',
			pivot: false,
			worksheets: [{
				data: dataTable,
				name: 'Sheet 1'
			}]
		});
		if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari
			window.location = sheet.href();
		} else if (!gx.util.browser.isIE() || (9 < gx.util.browser.ieVersion())) {
			//window.location = sheet.href();
			var byteCharacters = atob(sheet.base64);
			function charCodeFromCharacter(c) {
				return c.charCodeAt(0);
			}

			var byteNumbers = Array.prototype.map.call(byteCharacters, charCodeFromCharacter);
			var uint8Data = new Uint8Array(byteNumbers);

			var blob = new Blob([uint8Data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
			saveAs(blob, fileName + ".xlsx");
		} else {
			return sheet.base64;
		}
	}

	OAT.ExportToXML = function (self, fileName) {
		var hiddenColumns = [];
		for (var i = 0; i < 1; i++) {
			var tRow = jQuery("#" + self.grid.controlName + " tr")[i];
			for (var j = 0; j < tRow.children.length; j++) {
				if (tRow.children[j].style.display == "none") {
					hiddenColumns.push(j);
				}
			}
		}

		var xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><EXPORT format="XML" type="flat">';
		xml = xml + '<METADATA>';
		for (var iCV = 0; iCV < self.grid.columns.length; iCV++) {
			if (hiddenColumns.indexOf(iCV) == -1) {
				var position = 'row';

				xml = xml + '<OLAPDimension ';
				xml = xml + 'name="' + self.grid.columns[iCV].getAttribute("dataField") + '" ';
				xml = xml + 'label="' + self.grid.columns[iCV].getAttribute("displayName") + '" ';
				xml = xml + 'picture="' + self.grid.columns[iCV].getAttribute("picture") + '" ';
				xml = xml + 'datatype="' + self.grid.columns[iCV].getAttribute("dataType") + '" ';
				xml = xml + 'showAll="false" ';
				xml = xml + 'position="' + position + '">';


				var previusValue = [];
				for (var i = 0; i < self.grid.rows.length; i++) {
					if (previusValue.findIndex(self.grid.rows[i].cells[iCV].options.value) === -1) {
						xml = xml + '<VALUE CHECKED=';
						if (self.grid.conditions[iCV].blackList.findIndex(self.grid.rows[i].cells[iCV].options.value) === -1) {
							previusValue.push(self.grid.rows[i].cells[iCV].options.value);
							xml = xml + '"true"';
						} else {
							xml = xml + '"false"';
						}
						xml = xml + ' COLLAPSED="false">'

						/*Set the value with the original format, for numeric values*/
						var valuetoString = self.grid.rows[i].cells[iCV].options.value;
						if (!isNaN(parseFloat(self.grid.rows[i].cells[iCV].options.value))) {
							var numRecord = parseFloat(self.grid.rows[i].cells[iCV].options.value);
							if (data != undefined) {
								for (var di = 0; di < data.length; di++) {
									if (data[di] != undefined) {
										for (var dj = 0; dj < data[di].length; dj++) {
											if ((parseFloat(data[di][dj]) != undefined) && (!isNaN(data[di][dj]))) {
												if (parseFloat(data[di][dj]) === parseFloat(self.grid.rows[i].cells[iCV].options.value)) {
													valuetoString = data[di][dj];
												}
											}
										}
									}
								}
							}
						}

						xml = xml + valuetoString + '</VALUE>';
					}
				}

				xml = xml + '</OLAPDimension>';
			}
		}

		for (var iCV = 0; iCV < measures.length; iCV++) {
			xml = xml + '<OLAPMeasure ';
			xml = xml + 'name="' + measures[iCV].getAttribute("dataField") + '" ';
			xml = xml + 'label="' + measures[iCV].getAttribute("displayName") + '" ';
			xml = xml + 'picture="' + measures[iCV].getAttribute("picture") + '" ';
			xml = xml + 'datatype="' + measures[iCV].getAttribute("dataType") + '" ';
			xml = xml + 'showAll="true" ';
			xml = xml + 'aggregator="sum"/>';
		}

		xml = xml + '</METADATA>';

		xml = xml + '<FLATDATA>';
		if (data != undefined) {
			for (var i = 0; i < data.length; i++) {
				xml = xml + '<ROW ';
				for (var iCV = 0; iCV < data[0].length; iCV++) {
					if (hiddenColumns.indexOf(iCV) == -1) {
						var valuetoString = data[i][iCV];
						xml = xml + self.grid.columns[iCV].getAttribute("dataField") + '="' + valuetoString + '" ';
					}
				}
				xml = xml + '/>';
			}
		} else {
			for (var i = 0; i < self.grid.rows.length; i++) {
				xml = xml + '<ROW ';


				for (var iCV = 0; iCV < self.grid.rows[0].cells.length; iCV++) {
					/*Set the value with the original format, for numeric values*/
					var valuetoString = "";
					valuetoString = self.grid.rows[i].cells[iCV].options.value;
					if (!isNaN(parseFloat(self.grid.rows[i].cells[iCV].options.value))) {
						var numRecord = parseFloat(self.grid.rows[i].cells[iCV].options.value);
						if (data != undefined) {
							for (var di = 0; di < data.length; di++) {
								if (data[di] != undefined) {
									for (var dj = 0; dj < data[di].length; dj++) {
										if ((parseFloat(data[di][dj]) != undefined) && (!isNaN(data[di][dj]))) {
											if (parseFloat(data[di][dj]) === parseFloat(self.grid.rows[i].cells[iCV].options.value)) {
												valuetoString = data[di][dj];
											}
										}
									}
								}
							}
						}
					}
					xml = xml + self.grid.columns[iCV].getAttribute("dataField") + '="' + valuetoString + '" ';
				}

				xml = xml + '/>'
			}
		}
		xml = xml + '</FLATDATA>';


		xml = xml + '<HTML>';

		xml = xml + '<HEAD>';
		xml = xml + '<META content="text/html; charset=utf-8" http-equiv="Content-Type"/>';

		xml = xml + '<STYLE>';

		xml = xml + '.odd {background-color: #FEFEFE; font-family: Verdana; font-size: 10pt;}\n';
		xml = xml + '.event {background-color: #EBEBEB; font-family: Verdana; font-size: 10pt;}\n';
		xml = xml + '.even {background-color: #FEFEFE;	font-weight: normal; font-family: Verdana; font-size: 10pt;	padding: 5px; }\n';
		xml = xml + 'tr {border-left: 1px solid #BBBBBB; border-right: 1px solid #BBBBBB; line-height: 22px;}\n';
		xml = xml + 'table {border-collapse: collapse;}\n'

		xml = xml + '</STYLE>';
		xml = xml + '</HEAD>';
		xml = xml + '<BODY>';

		for (var i = 0; i < jQuery("#" + self.grid.controlName + " tr").length; i++) {//for every row
			xml = xml + '<TR>';

			var tRow = jQuery("#" + self.grid.controlName + " tr")[i];
			for (var j = 0; j < tRow.children.length; j++) {//for every cell in the row
				var childText = OAT.removeIconFont(tRow.children[j].textContent).trim();
				var hidden = tRow.children[j].getAttribute('hidden');
				if (tRow.children[j].style.display != "none") {
					if (hidden === null) {
						var rowSpan = tRow.children[j].getAttribute('rowspan');
						var colSpan = tRow.children[j].getAttribute('colspan');

						var styleString = "";
						if ((tRow.children[j].getAttribute("style") != undefined) && (tRow.children[j].getAttribute("style") != null)) {
							styleString = " style=\"" + tRow.children[j].getAttribute("style") + "\" ";
						}

						var classString = "";
						if ((tRow.getAttribute("class") != undefined) && (tRow.getAttribute("class") != null)) {
							classString = " class=\"" + tRow.getAttribute("class") + "\" ";
						}

						if ((rowSpan === null) && (colSpan === null)) {
							xml = xml + '<TD ' + classString + ' ' + styleString + ' >' + childText + '</TD>';
						} else if (colSpan === null) {
							xml = xml + '<TD ' + classString + ' ' + styleString + ' rowspan="' + rowSpan + '">' + childText + '</TD>';
						} else if (rowSpan === null) {
							xml = xml + '<TD ' + classString + ' ' + styleString + ' colspan="' + colSpan + '">' + childText + '</TD>';
						} else {
							xml = xml + '<TD ' + classString + ' ' + styleString + ' colspan="' + colSpan + '" rowspan="' + rowSpan + '">' + childText + '</TD>';
						}
					}
				}
			}

			xml = xml + '</TR>';
		}


		xml = xml + '</BODY>';
		xml = xml + '</HTML>';


		xml = xml + "</EXPORT>";

		if ((!gx.util.browser.isIE()) || 9 < gx.util.browser.ieVersion()) {
			xml = xml.replace(/\&/g, "&amp;");
			if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari			
				window.open('data:text/xml,' + encodeURIComponent(xml));
			} else {
				var blob = new Blob([xml], { type: "text/xml" });
				saveAs(blob, fileName + ".xml");
			}
		} else {
			return xml.replace(/\&/g, "&amp;");
		}
	}

	OAT.SaveStateWhenServerPaging = function (self, UcId, pageSize, dataFieldOrder, orderType, filters, blackLists, columnVisible) {
		var state = {
			pageSize: pageSize,
			dataFieldOrder: dataFieldOrder,
			orderType: orderType,
			filters: filters,
			blackLists: blackLists,
			columnVisible: columnVisible
		}

		var columnDisplay = new Array(self.columnsDataType);
		for (var tC = 0; tC < self.columnsDataType.length; tC++) {
			if (self.header.cells[tC] != undefined) {
				columnDisplay[tC] = self.header.cells[tC].html.style.display;
			}
		}

		localStorage.setItem(OAT.getURL() + self.controlName + self.query, JSON.stringify(state));
	}

	OAT.saveState = function (self, repage, columnChange, serverInfo) {

		if (self.grid.serverPaging) {
			return;
		}

		if (typeof JSON.decycle !== 'function') {
			JSON.decycle = function decycle(object) {
				'use strict';

				var objects = [], // Keep a reference to each unique object or array
					paths = [];
				return (function derez(value, path) {

					var i, // The loop counter
						name, // Property name
						nu;
					switch (typeof value) {
						case 'object':
							if (!value) {
								return null;
							}
							for (i = 0; i < objects.length; i += 1) {
								if (objects[i] === value) {
									return {
										$ref: paths[i]
									};
								}
							}
							objects.push(value);
							paths.push(path);
							if (Object.prototype.toString.apply(value) === '[object Array]') {
								nu = [];
								for (i = 0; i < value.length; i += 1) {
									nu[i] = derez(value[i], path + '[' + i + ']');
								}
							} else {
								nu = {};
								for (name in value) {
									if (Object.prototype.hasOwnProperty.call(value, name)) {
										nu[name] = derez(value[name], path + '[' + JSON.stringify(name) + ']');
									}
								}
							}
							return nu;
						case 'number':
						case 'string':
						case 'boolean':
							return value;
					}
				}(object, '$'));
			};
		}

		var columnDisplay = new Array(self.grid.columnsDataType);
		for (var tC = 0; tC < self.grid.columnsDataType.length; tC++) {
			if (self.grid.header.cells[tC] != undefined) {
				columnDisplay[tC] = self.grid.header.cells[tC].html.style.display;
			}
		}

		if (repage === "1") self.grid.rowsPerPage = self.grid.InitPageSize;

		var state = {
			conditions: self.grid.conditions,
			columnDisplay: columnDisplay,
			rowsPerPage: self.grid.rowsPerPage
		}

		localStorage.setItem(OAT.getURL() + self.grid.controlName + self.grid.query, JSON.stringify(JSON.decycle(state)));

		var rowNum;
		if (!isNaN(self.grid.rowsPerPage) && (self.grid.rowsPerPage != "")) {
			rowNum = self.grid.rowsPerPage;
		} else {
			rowNum = self.grid.InitPageSize;
		}
		if (repage === "1") rowNum = self.grid.InitPageSize
		/* re - pagination */
		var options = {
			currPage: 1,
			ignoreRows: jQuery('tbody tr[visibQ=tf]', jQuery("#" + self.grid.controlName)),
			optionsForRows: [10, 15, 20],
			rowsPerPage: rowNum != 'undefined' ? rowNum : 50,
			

			jstype: "table",
			topNav: false,
			controlName: self.grid.controlName
		}
		if ((self.grid.InitPageSize) && (repage)) {
			OAT.tablePagination(jQuery("#" + self.grid.controlName), options);
			setTimeout(function () {
				var wd2 = jQuery("#" + self.grid.controlName)[0].offsetWidth - 1;
				jQuery("#" + self.grid.controlName + "_tablePagination").css({ width: wd2 + "px" })
				jQuery("#" + self.grid.controlName).css("margin-bottom", "0px");
			}, 500);
		}
		/* end of re pagination*/

		/* Begin of autorefresh */
		if ((columnChange != undefined) && (columnChange > -1)) {
			var meta = OAT.createXMLMetadata(self, columnChange);
			var spl = self.grid.IdForQueryViewerCollection;
			var listennings = self.grid.QueryViewerCollection[spl];
			if ((listennings != "") && (listennings != null) && (listennings != undefined)) {
				qv.util.autorefresh.UpdateLayoutSameGroup(listennings, meta);
			}
		}

		/* -------------------- */
	}

	OAT.getStateWhenServingPaging = function (controlName, queryName) {
		var retrievedObject = localStorage.getItem(OAT.getURL() + controlName + queryName);
		var oldState = JSON.parse(retrievedObject);
		return oldState;
	}

	OAT.getState = function (grid, actualPageSize) {
		if (typeof JSON.retrocycle !== 'function') {
			JSON.retrocycle = function retrocycle($) {
				'use strict';

				var px =
					/^\$(?:\[(?:\d+|\"(?:[^\\\"\u0000-\u001f]|\\([\\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*\")\])*$/;

				(function rez(value) {

					var i, item, name, path;

					if (value && typeof value === 'object') {
						if (Object.prototype.toString.apply(value) === '[object Array]') {
							for (i = 0; i < value.length; i += 1) {
								item = value[i];
								if (item && typeof item === 'object') {
									path = item.$ref;
									if (typeof path === 'string' && px.test(path)) {
										value[i] = eval(path);
									} else {
										rez(item);
									}
								}
							}
						} else {
							for (name in value) {
								if (typeof value[name] === 'object') {
									item = value[name];
									if (item) {
										path = item.$ref;
										if (typeof path === 'string' && px.test(path)) {
											value[name] = eval(path);
										} else {
											rez(item);
										}
									}
								}
							}
						}
					}
				}($));
				return $;
			};
		}
		var retrievedObject = localStorage.getItem(OAT.getURL() + grid.controlName + grid.query);
		var oldState = JSON.retrocycle(JSON.parse(retrievedObject));

		if ((oldState != null) && ((oldState.rowsPerPage + " ") == (actualPageSize + " "))) {

			for (var tC = 0; tC < grid.columnsDataType.length; tC++) {
				grid.header.cells[tC].html.style.display = oldState.columnDisplay[tC];
				var numCol = grid.columnsDataType.length - 1 - tC;
				var j = 0;
				for (j = 0; j < grid.rows.length; j++) {
					grid.rows[j].cells[numCol].html.style.display = oldState.columnDisplay[tC];
				}
			}

			grid.conditions = oldState.conditions;
			grid.rowsPerPage = oldState.rowsPerPage;
			return true;
		} else
			return false;

	}

	OAT.SaveMetadata = function (metaDataString, key) {
		try {
			if (!!window.localStorage) {
				localStorage.removeItem(OAT.getURL() + key);
				localStorage.setItem(OAT.getURL() + key, metaDataString);
			}
		} catch (error) {

		}
	}

	OAT.GetSavedMetadata = function (key) {
		try {
			if (localStorage.getItem(OAT.getURL() + key) != null) {
				var mdata = localStorage.getItem(OAT.getURL() + key);
				if ((mdata != undefined) && (mdata != null)) {
					return mdata;
				}
			}
		} catch (error) {
			return "";
		}
		return ""
	}


	try {
		OAT.Loader.featureLoaded("grid");
	} catch (ERROR) {

	}


}





/* END OF FILE - ..\oatPivot\oat_grid.src.js - */
/* START OF FILE - ..\oatPivot\oat_impl.src.js - */
//OAT_IMPL file
if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {

	this.contains = function (a, obj) {
		for (var i = 0; i < a.length; i++) {
			if (a[i] === obj) {
				return i;
			}
		}
		return -1;
	}

	renderJSPivot = function (pivotParams, QueryViewerCollection, queryself) {
		if (pivotParams.RealType != "Table") {
			pivotParams.ServerPaging = false;
		}
		if (pivotParams.RealType == "Table") {
			pivotParams.ServerPagingPivot = false;
			if (qv.collection[pivotParams.UcId].AutoRefreshGroup == "") {
				jQuery(".oat_winrect_container").remove()
			}
		}
		if ((pivotParams.RememberLayout) && (pivotParams.ServerPaging) && (pivotParams.RealType != "PivotTable")) {
			var state = OAT.getStateWhenServingPaging(pivotParams.UcId + '_' + pivotParams.ObjectName, pivotParams.ObjectName)
			if (!state) {
				renderJSPivotInter(pivotParams, QueryViewerCollection, null, queryself)
			} else {
				var pageValue = 1;
				if (state.pageSize == "") { state.pageSize = undefined; pageValue = 0; }

				QueryViewerCollection[pivotParams.UcId].getPageDataForTable((function (resXML) {
					pivotParams.data = resXML;

					pivotParams.previousDataFieldOrder = state.dataFieldOrder;
					pivotParams.orderType = state.orderType;
					renderJSPivotInter(pivotParams, QueryViewerCollection, state, queryself)
				}).closure(this), [pageValue, state.pageSize, true, state.dataFieldOrder, state.orderType, state.filters]);

			}
		} else {
			if (pivotParams.RealType != "Table") {
				renderJSPivotInter(pivotParams, QueryViewerCollection, null, queryself)
			} else {

				pivotParams.customFilterInfo = "";
				var xmlDoc = jQuery.parseXML(pivotParams.metadata);
				var columns = xmlDoc.getElementsByTagName("OLAPDimension");

				var withOrderCustom = false
				var dataFieldOrder = ""
				var orderType = ""

				for (var u = 0; u < columns.length; u++) {
					var dataField = columns[u].getAttribute("dataField")

					var includeValues = []; //the only values to show
					var applyFilter = false;
					for (var h = 0; h < columns[u].childNodes.length; h++) {
						if ((columns[u].childNodes[h] != undefined) &&
							(columns[u].childNodes[h].localName != undefined) &&
							(columns[u].childNodes[h].localName === "include")) {
							applyFilter = true;
							for (var n = 0; n < columns[u].childNodes[h].childNodes.length; n++) {
								if ((columns[u].childNodes[h].childNodes[n].localName != null) &&
									(columns[u].childNodes[h].childNodes[n].localName.toLowerCase() === "value")) {
									includeValues.push(columns[u].childNodes[h].childNodes[n].textContent);
								}
							}
						}
					}


					if (!withOrderCustom) {
						if ((columns[u].getAttribute("order") != undefined) && (columns[u].getAttribute("order") != "")) {
							dataFieldOrder = columns[u].getAttribute("dataField")
							orderType = (columns[u].getAttribute("order") == "descending") ? "Descending" : "Ascending";
							withOrderCustom = true//(columns[u].getAttribute("order") == "custom")  
						}
					}


					if (applyFilter) {

						var res = QueryViewerCollection[pivotParams.UcId].getAttributeValuesSync([columns[u].getAttribute("dataField"), 1, 0, ""]);
						var res = JSON.parse(res);
						var realValues = res.NotNullValues;
						var realIncludeValues = [];
						for (var j = 0; j < includeValues.length; j++) {
							for (var h = 0; h < realValues.length; h++) {
								if (realValues[h].trimpivot() == includeValues[j].trimpivot()) {
									realIncludeValues.push(realValues[h])
									break;
								}
							}
						}


						if (pivotParams.customFilterInfo == "") {
							pivotParams.customFilterInfo = [];
						}
						var obj = {
							DataField: columns[u].getAttribute("dataField"),
							NotNullValues: {
								DefaultAction: "Exclude",
								Excluded: "",
								Included: realIncludeValues
							},
							NullIncluded: true
						}
						pivotParams.customFilterInfo.push(obj)


					}
				}

				if (pivotParams.ServerPaging && (pivotParams.customFilterInfo != "" || dataFieldOrder != "")) {
					QueryViewerCollection[pivotParams.UcId].getPageDataForTable((function (resXML) {
						pivotParams.data = resXML;
						renderJSPivotInter(pivotParams, QueryViewerCollection, null, queryself)
					}).closure(this), [1, pivotParams.PageSize, true, dataFieldOrder, orderType, pivotParams.customFilterInfo]);
				} else {
					renderJSPivotInter(pivotParams, QueryViewerCollection, null, queryself)
				}

			}
		}
	}

	renderJSPivotInter = function (pivotParams, QueryViewerCollection, state, queryself) {
		var type = pivotParams.RealType
		var container = pivotParams.container
		var page = pivotParams.page
		var content = pivotParams.content
		var metadata = pivotParams.metadata
		this.dataString = pivotParams.data
		var queryName = pivotParams.ObjectName
		var controlName = pivotParams.ControlName
		var pageSize = pivotParams.PageSize
		var autoResize = pivotParams.AutoResize
		var DisableColumnSort = pivotParams.DisableColumnSort
		var UcId = pivotParams.UcId
		var rememberLayout = pivotParams.RememberLayout
		this.pivotParams = pivotParams
		this.serverPaging = pivotParams.ServerPaging
		this.previousDataFieldOrder = pivotParams.previousDataFieldOrder;
		this.previousOrderType = pivotParams.orderType;
		this.previousFilters = (state) ? state.filters : undefined;
		this.previousColumnVisible = (state) ? state.columnVisible : undefined; this.initialColumnVisible = []
		this.previousState = state
		this.customFilterInfo = pivotParams.customFilterInfo
		this.gridCacheSize = pivotParams.ServerPagingCacheSize;

		var ShowMeasuresAsRows = (pivotParams.ShowDataLabelsIn == "Rows")
		if ((rememberLayout == undefined) || (rememberLayout == "false")) {
			rememberLayout = false
		}
		//recover metadata when metadata error, is there no metadata save it
		try {
			if (rememberLayout) {
				var savedMd = OAT.GetSavedMetadata(container.id + queryName + UcId + controlName + type + "metadata")
				if (savedMd === "") {
					OAT.SaveMetadata(metadata, container.id + queryName + UcId + controlName + type + "metadata")
				} else {
					var t1 = savedMd.split('OLAPDimension').length === metadata.split('OLAPDimension').length;
					var t2 = savedMd.split('OLAPMeasure').length === metadata.split('OLAPMeasure').length;
					var t3 = savedMd.split('name').length === metadata.split('name').length;
					var t4 = true
					if (t1 && t2 && t3) {
						for (var i = 1; i < savedMd.split('name').length; i++) {
							var name1 = savedMd.split('name')[i].substring(2, savedMd.split('name')[i].length).split("\"")[0];
							var name2 = metadata.split('name')[i].substring(2, metadata.split('name')[i].length).split("\"")[0];
							if (name1 != name2) {
								t4 = false;
							}
						}
					}
					if (!(t1 && t2 && t3 && t4)) {
						if (!gx.util.browser.isIE()) {
							rememberLayout = false
						} else {
							try {
								if (!!window.localStorage) {
									localStorage.removeItem(OAT.getURL() + container.id + queryName + UcId + controlName + type + "metadata");
									localStorage.removeItem(OAT.getURL() + queryName + UcId);
								}
							} catch (ERROR) {

							}
						}
					}
				}
			}
		} catch (ERROR) {

		}

		var fullXmlData = jQuery.parseXML(metadata); //metada for formulas and hide columns
		this.InitMetadata = {};
		this.InitMetadata.Metadata = metadata
		this.InitMetadata.DataString = dataString;
		this.InitMetadata.Dimensions = []
		this.InitMetadata.Conditions = []
		this.InitMetadata.DataFields = []
		var initColumns = fullXmlData.getElementsByTagName("OLAPDimension");
		for (var i = 0; i < initColumns.length; i++) {
			var objectColumn = {}
			objectColumn.name = initColumns[i].getAttribute("name")
			objectColumn.displayName = initColumns[i].getAttribute("displayName")
			objectColumn.description = initColumns[i].getAttribute("description")
			objectColumn.dataField = initColumns[i].getAttribute("dataField")
			objectColumn.defaultPosition = initColumns[i].getAttribute("defaultPosition")
			objectColumn.validPosition = initColumns[i].getAttribute("validPositions")
			if (objectColumn.validPosition == ""){
				objectColumn.defaultPosition = "hidden"
				objectColumn.Visible = false
			} else {
				objectColumn.Visible = (objectColumn.defaultPosition != "hidden")
			} 
			this.InitMetadata.Dimensions.push(objectColumn)
			this.InitMetadata.Conditions.push("")
			this.InitMetadata.DataFields.push(objectColumn.dataField)
		}
		this.InitMetadata.Measures = []
		var initMeasures = fullXmlData.getElementsByTagName("OLAPMeasure");
		for (var i = 0; i < initMeasures.length; i++) {
			var measureObject = {}
			measureObject.name = initMeasures[i].attributes.getNamedItem("name").nodeValue;
			measureObject.displayName = initMeasures[i].attributes.getNamedItem("displayName").nodeValue;
			measureObject.dataField = initMeasures[i].attributes.getNamedItem("dataField").nodeValue;
			measureObject.dataType = initMeasures[i].attributes.getNamedItem("dataType").nodeValue;

			measureObject.defaultPosition = (initMeasures[i].attributes.getNamedItem("defaultPosition")) ? initMeasures[i].attributes.getNamedItem("defaultPosition") : "data"
			measureObject.validPosition = (initMeasures[i].attributes.getNamedItem("validPositions")) ? initMeasures[i].attributes.getNamedItem("validPositions") : "data;hidden"

			measureObject.Visible = measureObject.defaultPosition != "hidden"//true
			this.InitMetadata.Measures.push(measureObject)
		}
		this.InitMetadata.DimensionPosition = []

		//parse metadata
		this.HideDataFilds = []

		var result;
		var previousState = OATgetState(queryName, UcId.replace(/,/g, "").replace(/\./g, ""))
		if ((rememberLayout) && (previousState != undefined)) {
			var hideDimension = [];
			for (var i = 0; i < previousState.Dimensions.length; i++) {
				if (!previousState.Dimensions[i].Visible) {
					hideDimension.push(previousState.Dimensions[i].dataField)
				}
			}
			var hideMeasures = [];
			for (var i = 0; i < previousState.Measures.length; i++) {
				if (!previousState.Measures[i].Visible) {
					hideMeasures.push(previousState.Measures[i].dataField)
				}
			}

			this.InitMetadata.Measures = previousState.Measures
			this.InitMetadata.Dimensions = previousState.Dimensions
			this.InitMetadata.DataFields = previousState.DataFields
			this.InitMetadata.DimensionPosition = previousState.DimensionPosition

			if (pivotParams.ServerPagingPivot) {
				this.InitMetadata.Conditions = previousState.Conditions
			}

			result = OATParseMetadata(metadata, hideDimension, hideMeasures, pivotParams.ServerPagingPivot)
		} else {
			var hideDimension = [];
			for (var i = 0; i < this.InitMetadata.Dimensions.length; i++) {
				if (!this.InitMetadata.Dimensions[i].Visible) {
					hideDimension.push(this.InitMetadata.Dimensions[i].dataField)
				}
			}

			var hideMeasures = [];
			for (var i = 0; i < this.InitMetadata.Measures.length; i++) {
				if (!this.InitMetadata.Measures[i].Visible) {
					hideMeasures.push(this.InitMetadata.Measures[i].dataField)
				}
			}
			if ((pivotParams.RealType == "Table")) {
				result = OATParseMetadata(metadata, [], hideMeasures, pivotParams.ServerPagingPivot)
			} else {
				result = OATParseMetadata(metadata, hideDimension, hideMeasures, pivotParams.ServerPagingPivot)
			}
		}

		metadata = result[0]; var orderFildsHidden = result[1]; var nameFildsHidden = result[3]; this.HideDataFilds = result[2];


		var xmlDoc = jQuery.parseXML(metadata);

		var defaultPicture = xmlDoc.childNodes[0];

		this.IdForQueryViewerCollection = UcId;
		UcId = UcId.replace(/,/g, "").replace(/\./g, "")
		this.UcId = UcId;
		this.pivotDiv = container.id;
		this.query = queryName;
		this.control = controlName;
		this.pageSize = pageSize;
		this.autoResize = autoResize;
		this.disableColumnSort = DisableColumnSort;
		this.header = [];
		this.data = [];
		this.columnNumbers = [];
		this.rowNumbers = [];
		this.filterNumbers = [];
		this.cols = 0;
		this.conditionalFormats = [];
		this.conditionalFormatsColumns = []; //conditional format for columns - needed?
		this.formatValues = [];
		this.formatValuesMeasures = [];

		this.forPivotFormatValues = [];
		this.forPivotFormats = [];
		this.forPivotCustomPicture = [];
		this.forPivotCustomFormat = [];


		//Columns and measures names
		var columns = xmlDoc.getElementsByTagName("OLAPDimension");
		var columnNames = [];
		var rowNames = [];
		var filterNames = [];
		this.measures = xmlDoc.getElementsByTagName("OLAPMeasure");
		var columnsDataType = [];
		var measureNames = []; var measuresNamesWidthHidden = [];
		var j = 0;
		var k = 0;
		var preHeader = [];
		var formulaInfo = { measureFormula: [], itemPosition: [] }
		//handle pictures
		var orderFilds = [];
		var datePictures = [];
		var intPictures = [];
		var dateFields = [];
		var intFields = [];

		if ((pivotParams.RealType == "Table")) {
			for (var i = 0; i < columns.length; i++) {
				this.initialColumnVisible[i] = true
				if ((columns[i].attributes.getNamedItem("defaultPosition").nodeValue == "hidden") || (columns[i].attributes.getNamedItem("validPositions").nodeValue == "")) {
					this.initialColumnVisible[i] = false
				}
			}
		}

		//get columns
		for (var i = 0; i < columns.length; i++) {

			if ((columns[i].attributes.getNamedItem("defaultPosition").nodeValue == "rows")
				|| (pivotParams.RealType == "Table") || (columns[i].attributes.getNamedItem("validPositions").nodeValue == "")) {
				columnNames[j] = columns[i].attributes.getNamedItem("displayName").nodeValue;
				preHeader[i] = columnNames[j];
				j++;
			}
			if (columns[i].attributes.getNamedItem("defaultPosition").nodeValue == "columns") {
				rowNames[k] = columns[i].attributes.getNamedItem("displayName").nodeValue;
				preHeader[i] = rowNames[k];
				k++;
			}
			if (columns[i].attributes.getNamedItem("defaultPosition").nodeValue == "filters") {
				filterNames[k] = columns[i].attributes.getNamedItem("displayName").nodeValue;
				preHeader[i] = filterNames[k];
				k++;
			}
			if (pivotParams.ServerPagingPivot && (columns[i].attributes.getNamedItem("defaultPosition").nodeValue == "hidden")) {
				for (var t = 0; t < this.InitMetadata.Dimensions.length; t++) {
					if (this.InitMetadata.Dimensions[t].dataField == columns[i].attributes.getNamedItem("dataField").nodeValue) {
						if (this.InitMetadata.Dimensions[t].Visible) {
							columnNames[j] = columns[i].attributes.getNamedItem("displayName").nodeValue;
							j++;
							preHeader[i] = columns[i].attributes.getNamedItem("displayName").nodeValue;
						}
					}
				}
			}
			columnsDataType[i] = columns[i].attributes.getNamedItem("dataType").nodeValue;
			//handle formats values
			if (columns[i].childNodes.length > 0) {
				if (columns[i].childNodes != null) {
					for (var m = 0; m < columns[i].childNodes.length; m++) {
						if (columns[i].childNodes[m].localName == "formatValues") {
							for (var n = 0; n < columns[i].childNodes[m].childNodes.length; n++) {
								if (columns[i].childNodes[m].childNodes[n].localName == "value") {
									var value = {};
									value.format = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("format").nodeValue;
									value.recursive = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("recursive").nodeValue;
									var crude = columns[i].childNodes[m].childNodes[n].textContent;
									value.value = crude.replace(/^\s+|\s+$/g, '');
									value.columnNumber = i;
									this.formatValues.push(value);
								}
							}
						}
					}
				}
			}//handle conditional formats
			if (columns[i].childNodes.length > 0) {
				if (columns[i].childNodes != null) {
					for (var m = 0; m < columns[i].childNodes.length; m++) {
						if (columns[i].childNodes[m].localName == "conditionalFormats") {
							for (var n = 0; n < columns[i].childNodes[m].childNodes.length; n++) {
								if (columns[i].childNodes[m].childNodes[n].localName == "rule") {
									var format = {};
									format.format = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("format").nodeValue;
									format.operation1 = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("op1").nodeValue;
									format.value1 = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("value1").nodeValue;
									if (columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("op2") != null) {
										format.operation2 = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("op2").nodeValue;
										format.value2 = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("value2").nodeValue;
									}
									format.columnNumber = i;
									this.conditionalFormatsColumns.push(format);
								}
							}
						}

					}
				}
			}

			//manage pictures
			if (columns[i].attributes.getNamedItem("picture").nodeValue != "") {
				if (columns[i].attributes.getNamedItem("dataType").nodeValue == "date") {
					datePictures.push(columns[i].attributes.getNamedItem("picture").nodeValue);
					dateFields.push(columns[i].attributes.getNamedItem("dataField").nodeValue);
				}
				//if (columns[i].attributes.getNamedItem("dataType").nodeValue == "integer" || measures[i].attributes.getNamedItem("dataType").nodeValue == "real") {
				if (columns[i].attributes.getNamedItem("dataType").nodeValue == "integer") {
					intPictures.push(columns[i].attributes.getNamedItem("picture").nodeValue);
					intFields.push(columns[i].attributes.getNamedItem("dataField").nodeValue);
				}

			}
			this.forPivotCustomPicture.push(columns[i].attributes.getNamedItem("picture").nodeValue);
			this.forPivotCustomFormat.push(columns[i].attributes.getNamedItem("format").nodeValue);
			orderFilds.push(columns[i].attributes.getNamedItem("dataField").nodeValue);

		}

		//var measures;
		for (var i = 0; i < this.measures.length; i++) {

			measureNames[i] = this.measures[i].attributes.getNamedItem("displayName").nodeValue;
			//manage format values
			if (measures[i].childNodes.length > 0) {
				if (measures[i].childNodes != null) {
					for (var m = 0; m < measures[i].childNodes.length; m++) {
						if (measures[i].childNodes[m].localName == "formatValues") {
							for (var n = 0; n < measures[i].childNodes[m].childNodes.length; n++) {
								if (measures[i].childNodes[m].childNodes[n].localName == "value") {
									var value = {};
									value.format = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("format").nodeValue;
									value.recursive = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("recursive").nodeValue;
									var crude = measures[i].childNodes[m].childNodes[n].textContent;
									value.value = crude.replace(/^\s+|\s+$/g, '');
									value.columnNumber = i;
									this.formatValuesMeasures.push(value);
								}
							}
						}

					}
				}
			}
			//manage conditional formats
			if (measures[i].childNodes.length > 0) {
				if (measures[i].childNodes != null) {
					for (var m = 0; m < measures[i].childNodes.length; m++) {
						if (measures[i].childNodes[m].localName == "conditionalFormats") {
							for (var n = 0; n < measures[i].childNodes[m].childNodes.length; n++) {
								if (measures[i].childNodes[m].childNodes[n].localName == "rule") {
									var format = {};
									format.format = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("format").nodeValue;
									format.operation1 = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("op1").nodeValue;
									format.value1 = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("value1").nodeValue;
									if (measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("op2") != null) {
										format.operation2 = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("op2").nodeValue;
										format.value2 = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("value2").nodeValue;
									}
									format.columnNumber = i; //+ columns.length; Only the measure number
									this.conditionalFormats.push(format);
								}
							}
						}
					}
				}
			}

			//manage pictures
			if (measures[i].attributes.getNamedItem("picture").nodeValue != "") {
				if (measures[i].attributes.getNamedItem("dataType").nodeValue == "date") {
					datePictures.push(measures[i].attributes.getNamedItem("picture").nodeValue);
					dateFields.push(measures[i].attributes.getNamedItem("dataField").nodeValue);
				}
				if (measures[i].attributes.getNamedItem("dataType").nodeValue == "integer" || measures[i].attributes.getNamedItem("dataType").nodeValue == "real") {
					intPictures.push(measures[i].attributes.getNamedItem("picture").nodeValue);
					intFields.push(measures[i].attributes.getNamedItem("dataField").nodeValue);/* */
				}
			}

			//manage formula
			if ((measures[i].attributes.getNamedItem("formula") != undefined) && (measures[i].attributes.getNamedItem("formula").nodeValue != "")) {
				formulaInfo.measureFormula.push({ hasFormula: true, textFormula: measures[i].attributes.getNamedItem("formula").nodeValue })
			} else {
				formulaInfo.measureFormula.push({ hasFormula: false })
			}

			this.forPivotCustomPicture.push(measures[i].attributes.getNamedItem("picture").nodeValue);
			orderFilds.push(measures[i].attributes.getNamedItem("dataField").nodeValue);
		}


		this.header = preHeader.concat(measureNames);

		this.getDataFromXML = function (dataString, tableOrderField){
			var stringRecord = dataString.split("<Record>")

			//get server pagination info
			if (this.serverPaging) {
				this.ServerRecordCount = parseToIntRegisterValue(stringRecord[0], "RecordCount")
				this.ServerPageCount = parseToIntRegisterValue(stringRecord[0], "PageCount")
				this.ServerPageNumber = parseToIntRegisterValue(stringRecord[0], "PageNumber")
			}
			//get records of the table
			/*var filds = orderFilds;
			if (this.TableOrderFilds != undefined) {
				filds = this.TableOrderFilds;
			}*/
			filds = tableOrderField;
			
			for (var i = 1; i < stringRecord.length; i++) {
				var recordData = [];
				var fullRecordData = [];
				for (var j = 0; j < filds.length; j++) {
					recordData[j] = "#NuN#"
					var dt = stringRecord[i].split("<" + filds[j] + ">")
					if (dt.length > 1) {
						var at = dt[1].split("</" + filds[j] + ">")
						/*var rp = at[0].replace(/^\s+|\s+$/g, '')
						recordData[j] = (rp != "") ? rp : undefined*/
						recordData[j] = at[0]
						fullRecordData[j] = recordData[j]
					} else {
						if (stringRecord[i].indexOf("<" + filds[j] + "/>") >= 0) {
							recordData[j] = ""
							fullRecordData[j] = ""
						}

					}
				}
				this.data.push(recordData);

				/*var pos_init = orderFilds.length;
				for (var j = 0; j < orderFildsHidden.length; j++) {
					fullRecordData[pos_init + j] = undefined
					var dt = stringRecord[i].split("<" + orderFildsHidden[j] + ">")
					if (dt.length > 1){
						var at = dt[1].split("</" + orderFildsHidden[j] + ">")
						fullRecordData[pos_init + j] = at[0]
					}
				}*/
				var pos_init = filds.length;
				for (var j = 0; j < this.HideDataFilds.length; j++) {
					fullRecordData[pos_init + j] = undefined
					var dt = stringRecord[i].split("<" + this.HideDataFilds[j] + ">")
					if (dt.length > 1) {
						var at = dt[1].split("</" + this.HideDataFilds[j] + ">")
						fullRecordData[pos_init + j] = at[0]
					}
				}
				this.fullRecord.push(fullRecordData);
				if (fullRecordData.length > this.maxLengthRecord) this.maxLengthRecord = fullRecordData.length;
			}
		}

		this.maxLengthRecord = 0;
		this.data = []
		this.fullRecord = []  //array to store extra data for formulas
		this.orderFildsHidden = orderFildsHidden
		this.TableOrderFilds = orderFilds;
		if (!pivotParams.ServerPagingPivot) {
			this.getDataFromXML(pivotParams.data, this.TableOrderFilds);
		} else {
			ShowMeasuresAsRows = ((ShowMeasuresAsRows) && (measures.length > 1))
			this.pagingData = {}//OATGetDataFromXMLForPivot(this.dataString, ShowMeasuresAsRows);
			this.pagingData.dataFields = orderFilds;
		}

		var furmulaIndex = {}
		for (var j = 0; j < orderFildsHidden.length; j++) {
			furmulaIndex[orderFildsHidden[j]] = orderFilds.length + j
		}
		this.orderFildsHidden = nameFildsHidden
		formulaInfo.itemPosition = furmulaIndex
		formulaInfo.recordDataLength = this.maxLengthRecord;
		formulaInfo.cantFormulaMeasures = 0;

		for (var n = 0; n < formulaInfo.measureFormula.length; n++) {
			if (formulaInfo.measureFormula[n].hasFormula) {
				formulaInfo.cantFormulaMeasures++;

				var inlineFormula = formulaInfo.measureFormula[n].textFormula

				var inline = inlineFormula
				var opers = ['*', '-', '+', '/', '(', ')']
				for (var j = 0; j < opers.length; j++) {
					var inline2 = inline.split(opers[j])
					if (inline2.length > 1) {
						inline = ""
						for (var i = 0; i < inline2.length - 1; i++) {
							inline = inline + inline2[i] + " " + opers[j] + " "
						}
						inline = inline + inline2[inline2.length - 1]
					}
				}

				var polishNot = InfixToPostfix(inline)
				formulaInfo.measureFormula[n].polishNotationText = polishNot
				var items = polishNot.split(" ")
				while (items.indexOf("") != -1) {
					items.splice(items.indexOf(""), 1)
				}
				var relatedMeasure = []
				for (var k = 0; k < items.length; k++) {
					if ((opers.indexOf(items[k]) == -1) && (isNaN(parseInt(items[k])))) {
						//add item
						var operPositionInDataRow = formulaInfo.itemPosition[items[k]]
						if (relatedMeasure.indexOf(operPositionInDataRow) == -1)
							relatedMeasure.push(operPositionInDataRow)
					}
				}

				formulaInfo.measureFormula[n].relatedMeasures = relatedMeasure

				var arrayNot = polishNot.split(" ")
				while (arrayNot.indexOf("") != -1) {
					arrayNot.splice(arrayNot.indexOf(""), 1)
				}
				formulaInfo.measureFormula[n].PolishNotation = arrayNot
			}
		}

		var l = 0;
		var m = 0;
		var d = 0;
		for (var i = 0; i < preHeader.length; i++) {
			if (this.contains(columnNames, preHeader[i]) != -1) {
				this.columnNumbers[l] = i;
				l++;
			}
			if (this.contains(rowNames, preHeader[i]) != -1) {
				this.rowNumbers[m] = i;
				m++;
			}
			if (this.contains(filterNames, preHeader[i]) != -1) {
				this.filterNumbers[d] = i;
				d++;
			}
		}

		//crear arreglo de columnas
		var colms = new Array();
		for (var t = 0; t < columns.length; t++) {
			colms[t] = columns[t];
		}

		var urlRelative = ""

		for (var i = 0; i < jQuery('script').length; i++) {
			var js_url = jQuery('script')[i].src
			if (js_url.indexOf("gxpivotjs") > 0) {
				urlRelative = js_url
				break;
			}
		}

		var relativePath = urlRelative.substring(0, urlRelative.indexOf("QueryViewer/oatPivot"));
		this.relativePath = relativePath

		var pivot;

		queryName = queryName.replace(/\./g, "")
		this.query = queryName
		OAT.Style.include("winrect.css", this.relativePath);
		OAT.Style.include("common.css", this.relativePath);
		if (type == "PivotTable") {
			OAT.Style.include("pivot.css", this.relativePath);
			pivot = OAT_JS.pivot.cb(this.pivotDiv, page, content, defaultPicture, QueryViewerCollection, colms,
				this.formatValues, this.conditionalFormatsColumns, this.formatValuesMeasures, this.autoResize, this.disableColumnSort, this.UcId, this.IdForQueryViewerCollection,
				rememberLayout, ShowMeasuresAsRows, formulaInfo, this.fullRecord,
				pivotParams.ServerPagingPivot, this.pagingData, this.HideDataFilds, this.orderFildsHidden, this.InitMetadata, this.relativePath,
			    this.pivotParams );
			if (pivot == 'error') {
				return;
			}
		} else {
			if (type == "Table") {
				OAT.Style.include("grid.css", this.relativePath);
				pivot = OAT_JS.grid.cb(this.pivotDiv, this.UcId + '_' + queryName, columnsDataType, defaultPicture, this.forPivotCustomPicture, this.conditionalFormatsColumns,
					this.formatValues, this.forPivotCustomFormat, colms, columns, QueryViewerCollection, this.pageSize, this.disableColumnSort, this.UcId, this.IdForQueryViewerCollection,
					rememberLayout, this);
			}
		}
		//add pagination functionality
		if (type == "Table") {
			this.pageSize = (this.previousState) ? this.previousState.pageSize : pageSize;

			var rowNum = this.pageSize;
			if ((pivot.rowsPerPage != undefined) && (pivot.rowsPerPage != "")) {
				rowNum = pivot.rowsPerPage;
			}

			if (QueryViewerCollection[this.UcId]._ControlRenderedTo) {
				jQuery("#"+this.UcId + "_" + this.query + "_tablePagination").remove(); //jQuery(".pivot_pag_div").remove()
			}

			if (this.pageSize) {
				if (!self.serverPaging) {
					setTimeout(function () {
						var options = {
							currPage: this.ServerPageNumber,
							ignoreRows: jQuery('tbody tr[visibQ=tf]', jQuery("#" + this.UcId + "_" + this.query)),
							optionsForRows: [10, 15, 20],
							rowsPerPage: rowNum != 'undefined' ? rowNum : 10,
							jstype: "table",
							topNav: false,
							controlName: this.UcId + "_" + this.query,
							cantPages: this.ServerPageCount,
							controlUcId: this.UcId,
							control: this
						}
						OAT.tablePagination(jQuery("#" + this.UcId + "_" + this.query), options);
						var wd2 = jQuery("#" + this.UcId + "_" + this.query)[0].clientWidth - 1;
						jQuery("#" + this.UcId + "_" + this.query + "_tablePagination").css({ width: wd2 + "px" });
						if (jQuery("#" + this.UcId + "_" + this.query + "_tablePagination").css('display') === 'none') {
							jQuery("#" + this.UcId + "_" + this.query).css({ marginBottom: "0px" });
						} else {
							jQuery("#" + this.UcId + "_" + this.query).css("margin-bottom", "0px");
						}

						if ((jQuery("#" + this.UcId + "_" + this.query + "_tablePagination_paginater").length > 0) && (jQuery("#" + this.UcId + "_" + this.query + "_tablePagination")[0].getBoundingClientRect().bottom < jQuery("#" + this.UcId + "_" + this.query + "_tablePagination_paginater")[0].getBoundingClientRect().bottom)) {
							jQuery("#" + this.UcId + "_" + this.query + "_tablePagination").css({ marginBottom: "0px" })
						}
						var wd = jQuery("#" + this.UcId + "_" + this.query)[0].offsetWidth - 4;
						jQuery("#" + this.UcId + "_" + this.query + "_grid_top_div").css({ width: wd + "px" });

						if ((this.serverPaging) && (this.pageSize == 10)) {
							if (this.ServerPageCount <= 1) { //hide pagiantion
								jQuery("#" + this.UcId + "_" + this.query + "_tablePagination").css({ display: "none" });
							}
						}

					}, 50)

				} else {
					var options = {
						currPage: this.ServerPageNumber,
						ignoreRows: jQuery('tbody tr[visibQ=tf]', jQuery("#" + this.UcId + "_" + this.query)),
						optionsForRows: [10, 15, 20],
						rowsPerPage: rowNum != 'undefined' ? rowNum : 10,
						jstype: "table",
						topNav: false,
						controlName: this.UcId + "_" + this.query,
						cantPages: this.ServerPageCount,
						controlUcId: this.UcId,
						control: this
					}
					OAT.partialTablePagination(jQuery("#" + this.UcId + "_" + this.query),options);
					var wd2 = jQuery("#" + this.UcId + "_" + this.query)[0].clientWidth - 1;
					jQuery("#" + this.UcId + "_" + this.query + "_tablePagination").css({ width: wd2 + "px" });
					if (jQuery("#" + this.UcId + "_" + this.query + "_tablePagination").css('display') === 'none') {
						jQuery("#" + this.UcId + "_" + this.query).css({ marginBottom: "0px" });
					} else {
						jQuery("#" + this.UcId + "_" + this.query).css("margin-bottom", "0px");
					}

					if ((jQuery("#" + this.UcId + "_" + this.query + "_tablePagination_paginater").length > 0) && (jQuery("#" + this.UcId + "_" + this.query + "_tablePagination")[0].getBoundingClientRect().bottom < jQuery("#" + this.UcId + "_" + this.query + "_tablePagination_paginater")[0].getBoundingClientRect().bottom)) {
						jQuery("#" + this.UcId + "_" + this.query + "_tablePagination").css({ marginBottom: "0px" })
					}
					var wd = jQuery("#" + this.UcId + "_" + this.query)[0].offsetWidth - 4;
					jQuery("#" + this.UcId + "_" + this.query + "_grid_top_div").css({ width: wd + "px" });

					if ((this.serverPaging) && ((this.pageSize == 10) || (this.ServerRecordCount < 10))) {
						if (this.ServerPageCount <= 1) { //hide pagiantion
							jQuery("#" + this.UcId + "_" + this.query + "_tablePagination").css({ display: "none" });
						}
					}
				}

			}
			var wd = jQuery("#" + this.UcId + "_" + this.query)[0].offsetWidth - 4;
			try {
				if ($("#MAINFORM")[0].className.indexOf("form-horizontal") > -1) {
					wd = wd + 4;
				}
			} catch (Error) {
			}
			jQuery("#" + this.UcId + "_" + this.query + "_grid_top_div").css({ width: wd + "px" });

			//set interval for handler values infinite scroll
			if (self.serverPaging) {
				setInterval(function () {
					for (var t = 0; t < jQuery(".oat_winrect_container .pivot_popup_fix").length; t++) {
						if ((!jQuery(".oat_winrect_container .pivot_popup_fix").closest(".oat_winrect_container")[t].style.display) ||
							(jQuery(".oat_winrect_container .pivot_popup_fix").closest(".oat_winrect_container")[t].style.display != "none")) {

							if (jQuery(".oat_winrect_container .pivot_popup_fix").length > 0) {
								var element = jQuery(".oat_winrect_container .pivot_popup_fix")[t];
								var scrollBottom = element.scrollHeight - element.clientHeight - element.scrollTop
								if (scrollBottom < 25) {
									var UcId = element.getAttribute("ucid")
									var columnNumber = parseInt(element.getAttribute("columnNumber"))
									OAT_JS.grid.readScrollValue(UcId, columnNumber)
								}
							}
						}
					}
				},
					250)
			}

		}

		if (!pivotParams.ServerPagingPivot) {
			if (this.autoResize) {
				jQuery("#" + this.UcId + "_" + this.query).css({ minWidth: "10px" });
			}
		}

		this.getDataForTable = function (UcId, pageNumber, rowsPerPage, recalculateCantPages, DataFieldOrder, OrderType, DataFieldFilter, DataFieldBlackList, restoreDefaultView, fromExternalRefresh) {
			if ((recalculateCantPages) || (DataFieldOrder != "") || (DataFieldFilter != "")) {
				OAT_JS.grid.cleanCache(this, UcId);
			}
			if (DataFieldOrder != "") OAT_JS.grid.gridData[UcId].dataFieldOrder = DataFieldOrder;
			if (OrderType != "") OAT_JS.grid.gridData[UcId].orderType = OrderType;
			if (DataFieldFilter != "") OAT_JS.grid.updateFilterInfo(UcId, DataFieldFilter, DataFieldBlackList);
			if (restoreDefaultView) { OAT_JS.grid.restoreDefaultView(UcId); rowsPerPage = OAT_JS.grid.gridData[UcId].rowsPerPage }

			if ((recalculateCantPages) || (DataFieldOrder != "") || (DataFieldFilter != "")) {//save state
				OAT.SaveStateWhenServerPaging(OAT_JS.grid.gridData[UcId].grid, UcId, rowsPerPage, OAT_JS.grid.gridData[UcId].dataFieldOrder, OAT_JS.grid.gridData[UcId].orderType, OAT_JS.grid.gridData[UcId].filterInfo, OAT_JS.grid.gridData[UcId].blackLists, OAT_JS.grid.gridData[UcId].columnVisible)
			}

			//OAT_JS.grid.gridData[UcId].actualPageNumber = pageNumber
			OAT_JS.grid.gridData[UcId].rowsPerPage = rowsPerPage
			if (rowsPerPage == "") { rowsPerPage = undefined; pageNumber = 0; }

			if (!OAT_JS.grid.pageInCache(UcId, pageNumber)) {
				qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].getPageDataForTable((function (resXML) {
					if (pageNumber == 0) { pageNumber = 1, recalculateCantPages = false; }
					OAT_JS.grid.redraw(this, UcId, resXML, recalculateCantPages, DataFieldOrder != "", pageNumber, fromExternalRefresh)
				}).closure(this), [pageNumber, rowsPerPage, recalculateCantPages, OAT_JS.grid.gridData[UcId].dataFieldOrder, OAT_JS.grid.gridData[UcId].orderType, OAT_JS.grid.gridData[UcId].filterInfo]);
			} else {
				OAT_JS.grid.redraw(this, UcId, OAT_JS.grid.pageInCache(UcId, pageNumber), false, false, pageNumber, true)
			}
		}

		this.getValuesForColumn = function (UcId, columnNumber, filterValue) {
			var dataField = OAT_JS.grid.gridData[UcId].columnDataField[columnNumber]
			if (filterValue != "") {
				var page = 1
				qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
					var res = JSON.parse(resJSON);
					OAT_JS.grid.changeValues(UcId, dataField, columnNumber, res, filterValue);
				}).closure(this), [dataField, page, 10, filterValue]);
			} else {
				OAT_JS.grid.resetScrollValue(UcId, dataField, columnNumber)
			}
		}

		queryself.oat_element = pivot;

		//setTimeout( function(){

		//	if ((OAT_JS.grid.gridData[UcId].mustRedraw) && (this.pageSize)){
		//		this.getDataForTable(this.UcId, 1, OAT_JS.grid.gridData[this.UcId].rowsPerPage, false, OAT_JS.grid.gridData[this.UcId].dataFieldOrder, OAT_JS.grid.gridData[this.UcId].orderType, "", "","", true)
		//	}
		//}, 500)*/

		//redraw if table and initial ascending or descending
		//if ( (self.serverPaging) && (type == "Table") && (OAT_JS.grid.gridData[this.UcId].dataFieldOrder != "")){
		//self.getDataForTable(self.UcId, 1, OAT_JS.grid.gridData[self.UcId].rowsPerPage, false, OAT_JS.grid.gridData[self.UcId].dataFieldOrder, OAT_JS.grid.gridData[self.UcId].orderType, "", "")
		//this.getDataForTable(this.UcId, 1, OAT_JS.grid.gridData[this.UcId].rowsPerPage, false, OAT_JS.grid.gridData[this.UcId].dataFieldOrder, OAT_JS.grid.gridData[this.UcId].orderType, "", "")		
		//}
		//return pivot;
	}

	var OAT_JS = {};

	OAT_JS.grid = {
		panel: 1,
		tab: 4,
		div: "",
		needs: ["grid"],
		gridData: [],
		cb: function (content, controlName, columnsDataType, defaultPicture, forPivotCustomPicture, conditionalFormatsColumns, formatValues, forPivotCustomFormar, colms, columns,
			QueryViewerCollection, pageSize, disableColumnSort, UcId, IdForQueryViewerCollection, rememberLayout, _mthis) {
			this.gridData[UcId] = {};
			this.gridData[UcId].div = content;
			this.gridData[UcId].controlName = controlName;

			this.gridData[UcId].actualPageNumber = 1;
			this.gridData[UcId].rowsPerPage = (_mthis.previousState) ? _mthis.previousState.pageSize : pageSize;
			this.gridData[UcId].actualCantPages = _mthis.ServerPageCount;
			
			this.gridData[UcId].autoResize = _mthis.autoResize;
			this.gridData[UcId].selection = {Allow: _mthis.pivotParams.AllowSelection, EntireLine: _mthis.pivotParams.SelectLine, SelectedNode: []};
			
			this.gridData[UcId].grid = new OAT.Grid(content, controlName, query, columnsDataType, colms, QueryViewerCollection, this.gridData[UcId].rowsPerPage,
				disableColumnSort, UcId, IdForQueryViewerCollection, rememberLayout, _mthis.serverPaging, _mthis.HideDataFilds, _mthis.orderFildsHidden, _mthis.TableOrderFilds, _mthis.relativePath,
				this.gridData[UcId].selection );
			this.gridData[UcId].grid.oat_component = this;
			

			//initialize 
			this.gridData[UcId].columnDataField = []
			for (var id = 0; id < columns.length; id++) {
				this.gridData[UcId].columnDataField[id] = columns[id].getAttribute("dataField");
			}

			this.gridData[UcId].grid.createHeader(header, this.gridData[UcId].columnDataField);
			this.gridData[UcId].redrawHeader = false
			
			//initialize default data
			this.gridData[UcId].defaultValues = {}
			this.gridData[UcId].defaultValues.rowsPerPage = pageSize;
			this.gridData[UcId].defaultValues.dataFieldOrder = "";
			this.gridData[UcId].defaultValues.orderType = ""
			this.gridData[UcId].defaultValues.filterInfo = [];


			this.gridData[UcId].IdForQueryViewerCollection = IdForQueryViewerCollection;
			
			this.gridData[UcId].TableOrderFields = _mthis.TableOrderFilds;

			//initialize cache
			this.gridData[UcId].cacheSize = (_mthis.gridCacheSize == 0) ? (_mthis.ServerPageCount * ((this.gridData[UcId].rowsPerPage > 0) ? this.gridData[UcId].rowsPerPage : 1)) : _mthis.gridCacheSize;
			this.gridData[UcId].gridCache = [];
			this.gridData[UcId].gridCache[0] = { page: 1, pageData: _mthis.dataString };
			this.gridData[UcId].nextCachePos = 1;
			//end initialize cache

			//initialize column visibility
			this.gridData[UcId].columnVisible = [];
			for (var id = 0; id < columns.length; id++) {
				this.gridData[UcId].columnVisible[id] = true
				if (_mthis.previousColumnVisible) {
					this.gridData[UcId].columnVisible[id] = _mthis.previousColumnVisible[id]
					if (!this.gridData[UcId].columnVisible[id])
						this.gridData[UcId].grid.hideColumnHeader(id);
				} else if (_mthis.initialColumnVisible) {
					this.gridData[UcId].columnVisible[id] = _mthis.initialColumnVisible[id]
					if (!this.gridData[UcId].columnVisible[id])
						this.gridData[UcId].grid.hideColumnHeader(id);
				}
			}
			//initialize  dataFields
			this.gridData[UcId].columnDataField = []
			this.gridData[UcId].originalColumnDataField = []
			for (var id = 0; id < columns.length; id++) {
				this.gridData[UcId].columnDataField[id] = columns[id].getAttribute("dataField");
				this.gridData[UcId].originalColumnDataField[id] = columns[id].getAttribute("dataField");
			}

			//initialize filter info
			this.gridData[UcId].filterInfo = [];
			this.gridData[UcId].differentValues = [];
			this.gridData[UcId].blackLists = [];
			this.gridData[UcId].differentValuesPaginationInfo = [];
			this.gridData[UcId].filteredValuesPaginationInfo = [];
			for (var id = 0; id < columns.length; id++) {
				this.gridData[UcId].differentValues[columns[id].getAttribute("dataField")] = [];
				this.gridData[UcId].blackLists[columns[id].getAttribute("dataField")] = { state: "all", visibles: [], hiddens: [], defaultAction: "Include", hasNull: true };
				this.gridData[UcId].differentValuesPaginationInfo[columns[id].getAttribute("dataField")] = {
					blocked: false, previousPage: 0,
					totalPages: true, filtered: false
				}
				this.gridData[UcId].filteredValuesPaginationInfo[columns[id].getAttribute("dataField")] = { previousPage: 0, totalPages: 0, filteredText: "", values: [] }
			}

			this.gridData[UcId].defaultNullText = defaultPicture.getAttribute("textForNullValues");

			if (_mthis.previousFilters != undefined) {//load previus state filter info
				this.gridData[UcId].filterInfo = _mthis.previousFilters;
				for (var u = 0; u < this.gridData[UcId].filterInfo.length; u++) {
					for (var t = 0; t < this.gridData[UcId].filterInfo[u].NotNullValues.Included.length; t++) {
						var val = this.gridData[UcId].filterInfo[u].NotNullValues.Included[t];
						if (this.gridData[UcId].blackLists[this.gridData[UcId].filterInfo[u].DataField].visibles.indexOf(val) == -1) {
							this.gridData[UcId].blackLists[this.gridData[UcId].filterInfo[u].DataField].visibles.push(val);
						}
					}

					for (var t = 0; t < this.gridData[UcId].filterInfo[u].NotNullValues.Excluded.length; t++) {
						var val = this.gridData[UcId].filterInfo[u].NotNullValues.Excluded[t];
						if (this.gridData[UcId].blackLists[this.gridData[UcId].filterInfo[u].DataField].hiddens.indexOf(val) == -1) {
							this.gridData[UcId].blackLists[this.gridData[UcId].filterInfo[u].DataField].hiddens.push(val);
						}
					}

					if (this.gridData[UcId].filterInfo[u].NotNullValues.Included.length > 0) {
						this.gridData[UcId].blackLists[this.gridData[UcId].filterInfo[u].DataField].state = "";
					} else {
						this.gridData[UcId].blackLists[this.gridData[UcId].filterInfo[u].DataField].state = "none";
					}

					this.gridData[UcId].blackLists[this.gridData[UcId].filterInfo[u].DataField].defaultAction = this.gridData[UcId].filterInfo[u].NotNullValues.DefaultAction;

				}
			} else {
				if ((_mthis.customFilterInfo != undefined) & (_mthis.customFilterInfo != "")) {
					this.gridData[UcId].filterInfo = _mthis.customFilterInfo;
				}
			}
			//end initialize filter info
			//initialize order info
			this.gridData[UcId].dataFieldOrder = (_mthis.previousDataFieldOrder != undefined) ? _mthis.previousDataFieldOrder : ""
			this.gridData[UcId].orderType = (_mthis.previousOrderType != undefined) ? _mthis.previousOrderType : ""
			//end initialize order info
			//for custom order
			this.gridData[UcId].customOrderValues = [];
			for (var index = 0; index < columns.length; index++) {
				if ((columns[index].getAttribute("order") != undefined) && (columns[index].getAttribute("order") === "custom")) {
					result = this.gridData[UcId].grid.applyCustomSort(index, columns[index], data);
					data = result[0]
					this.gridData[UcId].customOrderValues[index] = result[1]
				} else {
					this.gridData[UcId].customOrderValues[index] = false
				}
			}

			this.gridData[UcId].rowsMetadata = {
				columnsDataType: columnsDataType, defaultPicture: defaultPicture, forPivotCustomPicture: forPivotCustomPicture,
				conditionalFormatsColumns: conditionalFormatsColumns, formatValues: formatValues, forPivotCustomFormat: forPivotCustomFormat, columns: columns
			}
			this.gridData[UcId].rowsData = data;
			for (var i = 0; i < data.length; i++) {
				this.gridData[UcId].grid.createRow(data[i], columnsDataType, defaultPicture, forPivotCustomPicture, conditionalFormatsColumns, formatValues, forPivotCustomFormat, columns, null, this.gridData[UcId].columnVisible);
			}

			//for ascending or descending order
			if (!_mthis.serverPaging) {
				for (var index = 0; index < columns.length; index++) {
					if ((columns[index].getAttribute("order") != undefined) && (columns[index].getAttribute("order") === "ascending")) {
						this.gridData[UcId].grid.applySortOrderType(index, 2);
					}
					if ((columns[index].getAttribute("order") != undefined) && (columns[index].getAttribute("order") === "descending")) {
						this.gridData[UcId].grid.applySortOrderType(index, 3);
					}
					if (columns[index].getAttribute("order") != undefined) {
						break;
					}
				}
			} else {
				var withOrderCustom = false
				for (var index = 0; index < columns.length; index++) {
					if ((columns[index].getAttribute("order") != undefined) && (columns[index].getAttribute("order") != "")) {
						this.gridData[UcId].dataFieldOrder = columns[index].getAttribute("dataField")
						this.gridData[UcId].orderType = (columns[index].getAttribute("order") == "descending") ? "Descending" : "Ascending";
						withOrderCustom = (columns[index].getAttribute("order") == "custom")
						break;
					}
				}

				if ((this.gridData[UcId].dataFieldOrder != "") && (!withOrderCustom)) {
					var columnOrderNumber = 0;
					for (var t = 0; t < this.gridData[UcId].grid.columns.length; t++) {
						if (this.gridData[UcId].dataFieldOrder == this.gridData[UcId].columnDataField[t]) { //this.gridData[UcId].grid.columns[t].getAttribute("dataField")){
							columnOrderNumber = t;
							break;
						}
					}
					//var colNumber = columns.length - 1 - columnOrderNumber;
					this.gridData[UcId].grid.applySortOrderType(columnOrderNumber, (this.gridData[UcId].orderType.toLowerCase() == "ascending") ? 2 : 3);
				}
			}

			//apply custom filters
			//this.gridData[UcId].mustRedraw = false; 
			for (var index = 0; index < columns.length; index++) {
				this.gridData[UcId].grid.applyCustomFilter(index, columns[index]);
				//var toRedraw = this.gridData[UcId].grid.applyCustomFilter(index, columns[index]);
				//if (toRedraw) { this.gridData[UcId].mustRedraw = true; }
			}

			//load different values
			if (_mthis.serverPaging) {
				OAT_JS.grid.initValueRead(UcId, 0)

				//call OnFirstPage on load
				qv.collection[this.gridData[UcId].IdForQueryViewerCollection].CurrentPage = 1;
				if (typeof (qv.collection[this.gridData[UcId].IdForQueryViewerCollection].OnFirstPage) == 'function') qv.collection[this.gridData[UcId].IdForQueryViewerCollection].OnFirstPage()
			}

			if (!_mthis.serverPaging) {
				this.gridData[UcId].grid.applySaveState(this.gridData[UcId].rowsPerPage);
			}

			return this.gridData[UcId].grid;
		},
		redraw: function (_mthis, UcId, xmlData, recalculateCantPages, moveToFirstPage, pageNumber, fromExternalRefresh) {
			//add data to cache
			if (!this.pageInCache(UcId, pageNumber)) {
				this.gridData[UcId].gridCache.push({ page: pageNumber, pageData: xmlData })
				if (this.gridData[UcId].gridCache.length > this.gridData[UcId].cacheSize) {
					this.gridData[UcId].gridCache.splice(0, 1)
				}
			} else {
				var indCache = -1;
				for (var cP = 0; cP < this.gridData[UcId].gridCache.length; cP++) {
					if (this.gridData[UcId].gridCache[cP].page == pageNumber) {
						indCache = cP;
					}
				}
				this.gridData[UcId].gridCache.splice(indCache, 1)
				this.gridData[UcId].gridCache.push({ page: pageNumber, pageData: xmlData })
			}
			//end add data to cache
			_mthis.data = []
			_mthis.getDataFromXML(xmlData, this.gridData[UcId].TableOrderFields);
			if (_mthis.ServerPageCount >= 0) {
				this.gridData[UcId].actualCantPages = _mthis.ServerPageCount;
			}
			
			//redraw header when neded
			if (this.gridData[UcId].redrawHeader){
				var actualheader = [];
			
				for(var i = 0; i < this.gridData[UcId].columnDataField.length; i++){
					var dtF = this.gridData[UcId].columnDataField[i]
					for(var j = 0 ; j < this.gridData[UcId].rowsMetadata.columns.length; j++){
						if (dtF == this.gridData[UcId].rowsMetadata.columns[j].getAttribute("dataField"))
						{
							actualheader.push(this.gridData[UcId].rowsMetadata.columns[j].getAttribute("displayName"));
						}
					}
				}
			
				this.gridData[UcId].grid.createHeader(actualheader, this.gridData[UcId].columnDataField);
			
				if ((this.gridData[UcId].dataFieldOrder != "")){ //&& (!withOrderCustom)) {
					var columnOrderNumber = 0;
					for (var t = 0; t < this.gridData[UcId].grid.columns.length; t++) {
						if (this.gridData[UcId].dataFieldOrder == this.gridData[UcId].columnDataField[t]) { //this.gridData[UcId].grid.columns[t].getAttribute("dataField")){
							columnOrderNumber = t;
							break;
						}
					}
					this.gridData[UcId].grid.applySortOrderType(columnOrderNumber, (this.gridData[UcId].orderType.toLowerCase() == "ascending") ? 2 : 3);
				}
				
				//hide hidden columns
				for(var i = 0; i < this.gridData[UcId].columnVisible.length; i++){
					if (!this.gridData[UcId].columnVisible[i]){
						var dtF = this.gridData[UcId].originalColumnDataField[i]
						this.gridData[UcId].grid.hideColumnHeader(this.gridData[UcId].columnDataField.indexOf(dtF));
					}
				}				
				
			}			
			//end redraw header
			
			this.gridData[UcId].grid.removeAllRows();
			if (recalculateCantPages) {
				if (jQuery("#" + this.gridData[UcId].controlName + "_tablePagination " + "#tablePagination_totalPages").length > 0) {
					OAT.replaceTextNode(jQuery("#" + this.gridData[UcId].controlName + "_tablePagination " + "#tablePagination_totalPages")[0], " " + _mthis.ServerPageCount)
					if ((_mthis.ServerPageCount <= 1) && (this.gridData[UcId].rowsPerPage == 10)) { //hide pagiantion
						jQuery("#" + this.gridData[UcId].controlName + "_tablePagination ").css({ display: "none" });
					} else {
						jQuery("#" + this.gridData[UcId].controlName + "_tablePagination ").css({ display: "" });
						if (_mthis.ServerPageCount == 1) {
							$('#' + this.gridData[UcId].controlName + '_tablePagination_paginater').css('display', 'none');
						} else {
							$('#' + this.gridData[UcId].controlName + '_tablePagination_paginater').css('display', '');
						}
					}
				}
			}

			//call navigational events
			if (OAT_JS.grid.gridData[UcId].actualPageNumber != pageNumber) {
				qv.collection[this.gridData[UcId].IdForQueryViewerCollection].CurrentPage = pageNumber;
				if (pageNumber == 1) {
					if (typeof (qv.collection[this.gridData[UcId].IdForQueryViewerCollection].OnFirstPage) == 'function') qv.collection[this.gridData[UcId].IdForQueryViewerCollection].OnFirstPage()
				} else if (pageNumber == this.gridData[UcId].actualCantPages) {
					if (typeof (qv.collection[this.gridData[UcId].IdForQueryViewerCollection].OnLastPage) == 'function') qv.collection[this.gridData[UcId].IdForQueryViewerCollection].OnLastPage()
				} else if (pageNumber < OAT_JS.grid.gridData[UcId].actualPageNumber) {
					if (typeof (qv.collection[this.gridData[UcId].IdForQueryViewerCollection].OnPreviousPage) == 'function') qv.collection[this.gridData[UcId].IdForQueryViewerCollection].OnPreviousPage()
				} else {
					if (typeof (qv.collection[this.gridData[UcId].IdForQueryViewerCollection].OnNextPage) == 'function') qv.collection[this.gridData[UcId].IdForQueryViewerCollection].OnNextPage()
				}

			}

			//call autorefresh
			if ((!fromExternalRefresh) && (qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].AutoRefreshGroup != "")) {
				var meta = OAT.createXMLMetadata(OAT_JS.grid.gridData[UcId], null, true);
				var spl = OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection;
				var listennings = qv.collection[spl];
				if ((listennings != "") && (listennings != null) && (listennings != undefined)) {
					qv.util.autorefresh.UpdateLayoutSameGroup(listennings, meta);
				}
			}

			//set new current page
			OAT_JS.grid.gridData[UcId].actualPageNumber = pageNumber
			currPageNumber[this.gridData[UcId].controlName] = pageNumber
			jQuery("#" + this.gridData[UcId].controlName + "_tablePagination " + "#tablePagination_currPage").val(pageNumber)
			
			this.gridData[UcId].rowsData = _mthis.data;
			for (var i = 0; i < _mthis.data.length; i++) {
				var dataByField = []
				var tempcolumnsDataType = []; var tempforPivotCustomPicture = []; var tempforPivotCustomFormat = []; var tempcolumnVisible = [];
				for (var p = 0; p < this.gridData[UcId].columnDataField.length; p++) {
					var pos = this.gridData[UcId].originalColumnDataField.indexOf(this.gridData[UcId].columnDataField[p])
					dataByField[p] = _mthis.data[i][pos];
					tempcolumnsDataType[p] = this.gridData[UcId].rowsMetadata.columnsDataType[pos];
					tempforPivotCustomPicture[p] = this.gridData[UcId].rowsMetadata.forPivotCustomPicture[pos]
					tempforPivotCustomFormat[p] = this.gridData[UcId].rowsMetadata.forPivotCustomFormat[pos]
					tempcolumnVisible[p] = this.gridData[UcId].columnVisible[pos]
				}
				this.gridData[UcId].grid.createRow(dataByField, tempcolumnsDataType, this.gridData[UcId].rowsMetadata.defaultPicture,
					tempforPivotCustomPicture, this.gridData[UcId].rowsMetadata.conditionalFormatsColumns,
					this.gridData[UcId].rowsMetadata.formatValues, tempforPivotCustomFormat, this.gridData[UcId].rowsMetadata.columns,
					null, tempcolumnVisible);
			}
			
			//redraw selection
			OAT.RedrawSelectedNode(this.gridData[UcId].grid)
		},
		getDifferentValues: function (UcId, columnNumber, iter) { //return the list of distint values of a column, and if it checked or not
			var dataField = this.gridData[UcId].columnDataField[columnNumber];//this.gridData[UcId].grid.columns[columnNumber].getAttribute("dataField")
			var value = this.gridData[UcId].differentValues[dataField][iter]
			var pos = this.gridData[UcId].originalColumnDataField.indexOf(this.gridData[UcId].columnDataField[columnNumber])
			var pict_value = OAT.ApplyPictureValue(value.trimpivot(), this.gridData[UcId].rowsMetadata.columnsDataType[pos],
				this.gridData[UcId].rowsMetadata.defaultPicture, this.gridData[UcId].rowsMetadata.forPivotCustomPicture[pos]).replace(/ /g, "\u00A0");

			if ((this.gridData[UcId].blackLists[dataField].hasNull) && (value.trimpivot() == this.gridData[UcId].defaultNullText)) {
				value = "#NuN#" //tomo este valor como el null
				return false;//{value: "", checked: true, pict_value: ""} 
			}
			var checked = true;
			if (this.gridData[UcId].blackLists[dataField].state != "all") {
				if (this.gridData[UcId].blackLists[dataField].visibles.findIndex(value) < 0) {
					checked = false;
				}
			}

			return { value: value, checked: checked, pict_value: pict_value };
		},
		getCantDifferentValues: function (UcId, columnNumber) {
			var dataField = this.gridData[UcId].columnDataField[columnNumber];//this.gridData[UcId].grid.columns[columnNumber].getAttribute("dataField")
			return this.gridData[UcId].differentValues[dataField].length
		},
		cleanCache: function (_mthis, UcId) {
			for (var cP = 0; cP < this.gridData[UcId].gridCache.length; cP++) {
				this.gridData[UcId].gridCache[cP] = { page: -1, pageData: "" };
			}
			this.gridData[UcId].nextCachePos = 0;
		},
		pageInCache: function (UcId, pageNumber) {
			for (var cP = 0; cP < this.gridData[UcId].gridCache.length; cP++) {
				if (this.gridData[UcId].gridCache[cP].page == pageNumber) {
					return this.gridData[UcId].gridCache[cP].pageData;
				}
			}
			return false;
		},
		updateFilterInfo: function (UcId, DataFieldFilter, NewFilter) {
			if (NewFilter.op == "all") {
				//remove filter from filterInof
				var pos = -1;
				for (var p = 0; p < this.gridData[UcId].filterInfo.length; p++) {
					if (DataFieldFilter == this.gridData[UcId].filterInfo[p].DataField) { pos = p; break; }
				}
				if (pos > -1) this.gridData[UcId].filterInfo.splice(pos, 1)
				this.gridData[UcId].blackLists[DataFieldFilter].state = "all"
				this.gridData[UcId].blackLists[DataFieldFilter].visibles = []
				this.gridData[UcId].blackLists[DataFieldFilter].hiddens = []
				this.gridData[UcId].blackLists[DataFieldFilter].defaultAction = "Include"
				return;
			}

			if (this.gridData[UcId].blackLists[DataFieldFilter].state == "none") {
				this.gridData[UcId].blackLists[DataFieldFilter].visibles = []
				for (var u = 0; u < this.gridData[UcId].differentValues[DataFieldFilter].length; u++) {
					if (this.gridData[UcId].blackLists[DataFieldFilter].hiddens.indexOf(this.gridData[UcId].differentValues[DataFieldFilter][u]) == -1) {
						this.gridData[UcId].blackLists[DataFieldFilter].hiddens.push(this.gridData[UcId].differentValues[DataFieldFilter][u])
					}
				}
			} else if (this.gridData[UcId].blackLists[DataFieldFilter].state == "all") {
				this.gridData[UcId].blackLists[DataFieldFilter].hiddens = []
				for (var u = 0; u < this.gridData[UcId].differentValues[DataFieldFilter].length; u++) {
					if (this.gridData[UcId].blackLists[DataFieldFilter].visibles.indexOf(this.gridData[UcId].differentValues[DataFieldFilter][u]) == -1) {
						this.gridData[UcId].blackLists[DataFieldFilter].visibles.push(this.gridData[UcId].differentValues[DataFieldFilter][u])
					}
				}
			}

			var notNullValue = [];
			if (NewFilter.op == "none") {
				notNullValue = [];
				this.gridData[UcId].blackLists[DataFieldFilter].state = "none"
				this.gridData[UcId].blackLists[DataFieldFilter].visibles = []
				this.gridData[UcId].blackLists[DataFieldFilter].hiddens = []
				this.gridData[UcId].blackLists[DataFieldFilter].defaultAction = "Exclude"
			} else {

				if (NewFilter.op == "push") {
					this.gridData[UcId].blackLists[DataFieldFilter].state = ""
					var pos = this.gridData[UcId].blackLists[DataFieldFilter].visibles.indexOf(NewFilter.values)
					if (pos > -1) this.gridData[UcId].blackLists[DataFieldFilter].visibles.splice(pos, 1);
					if (this.gridData[UcId].blackLists[DataFieldFilter].hiddens.indexOf(NewFilter.values) == -1)
						this.gridData[UcId].blackLists[DataFieldFilter].hiddens.push(NewFilter.values)
				} else if (NewFilter.op == "pop") {
					this.gridData[UcId].blackLists[DataFieldFilter].state = ""
					if (this.gridData[UcId].blackLists[DataFieldFilter].visibles.indexOf(NewFilter.values) == -1)
						this.gridData[UcId].blackLists[DataFieldFilter].visibles.push(NewFilter.values)
					var pos = this.gridData[UcId].blackLists[DataFieldFilter].hiddens.indexOf(NewFilter.values)
					if (pos > -1) this.gridData[UcId].blackLists[DataFieldFilter].hiddens.splice(pos, 1);
				} else if (NewFilter.op == "reverse") {
					if (this.gridData[UcId].blackLists[DataFieldFilter].defaultAction == "Include") {
						this.gridData[UcId].blackLists[DataFieldFilter].defaultAction = "Exclude"
					} else {
						this.gridData[UcId].blackLists[DataFieldFilter].defaultAction = "Include"
					}
					if (this.gridData[UcId].blackLists[DataFieldFilter].state == "none") {//si el estado anterior es none pasa a all
						var pos = -1;
						for (var p = 0; p < this.gridData[UcId].filterInfo.length; p++) {
							if (DataFieldFilter == this.gridData[UcId].filterInfo[p].DataField) { pos = p; break; }
						}
						if (pos > -1) this.gridData[UcId].filterInfo.splice(pos, 1)
						this.gridData[UcId].blackLists[DataFieldFilter].state = "all"
						this.gridData[UcId].blackLists[DataFieldFilter].visibles = []
						this.gridData[UcId].blackLists[DataFieldFilter].hiddens = []
						return;
					} else if (this.gridData[UcId].blackLists[DataFieldFilter].state == "all") {//si el estado anterior es all pasa a none
						notNullValue = [];
						this.gridData[UcId].blackLists[DataFieldFilter].state = "none"
						this.gridData[UcId].blackLists[DataFieldFilter].visibles = []
						this.gridData[UcId].blackLists[DataFieldFilter].hiddens = []
					} else {

						var tempArrayVisibles = []; for (var tit = 0; tit < this.gridData[UcId].blackLists[DataFieldFilter].visibles.length; tit++) { tempArrayVisibles.push(this.gridData[UcId].blackLists[DataFieldFilter].visibles[tit]) }
						var tempArrayHiddens = []; for (var tit = 0; tit < this.gridData[UcId].blackLists[DataFieldFilter].hiddens.length; tit++) { tempArrayHiddens.push(this.gridData[UcId].blackLists[DataFieldFilter].hiddens[tit]) }

						this.gridData[UcId].blackLists[DataFieldFilter].visibles = []
						this.gridData[UcId].blackLists[DataFieldFilter].hiddens = []

						for (var u = 0; u < this.gridData[UcId].differentValues[DataFieldFilter].length; u++) {
							var val = this.gridData[UcId].differentValues[DataFieldFilter][u];
							if (tempArrayVisibles.indexOf(val) == -1) {
								this.gridData[UcId].blackLists[DataFieldFilter].visibles.push(val)
							} else {
								this.gridData[UcId].blackLists[DataFieldFilter].hiddens.push(val)
							}
						}
						for (var u = 0; u < tempArrayHiddens.length; u++) {
							if (this.gridData[UcId].blackLists[DataFieldFilter].visibles.indexOf(tempArrayHiddens[u]) == -1) {
								this.gridData[UcId].blackLists[DataFieldFilter].visibles.push(tempArrayHiddens[u])
							}
						}
						for (var u = 0; u < tempArrayVisibles.length; u++) {
							if (this.gridData[UcId].blackLists[DataFieldFilter].hiddens.indexOf(tempArrayVisibles[u]) == -1) {
								this.gridData[UcId].blackLists[DataFieldFilter].hiddens.push(tempArrayVisibles[u])
							}
						}
					}
				}
			}

			var filterExist = false; var nullIncluded = true;
			var included = [];
			for (var t = 0; t < this.gridData[UcId].blackLists[DataFieldFilter].visibles.length; t++) {
				if (this.gridData[UcId].blackLists[DataFieldFilter].visibles[t] != "#NuN#") {
					included.push(this.gridData[UcId].blackLists[DataFieldFilter].visibles[t])
				}
			}
			var excluded = [];
			if (this.gridData[UcId].blackLists[DataFieldFilter].state != "none") {
				for (var t = 0; t < this.gridData[UcId].differentValues[DataFieldFilter].length; t++) {
					var val = this.gridData[UcId].differentValues[DataFieldFilter][t]
					if ((val != "#NuN#") && (included.indexOf(val) == -1)) {
						excluded.push(val)
					}
				}
				for (var t = 0; t < this.gridData[UcId].blackLists[DataFieldFilter].hiddens.length; t++) {
					if ((this.gridData[UcId].blackLists[DataFieldFilter].hiddens[t] != "#NuN#")
						&& (excluded.indexOf(this.gridData[UcId].blackLists[DataFieldFilter].hiddens[t]) == -1)) {
						excluded.push(this.gridData[UcId].blackLists[DataFieldFilter].hiddens[t])
					}
				}
				if ((included.length == 0) && ((this.gridData[UcId].blackLists[DataFieldFilter].defaultAction == "Exclude"))) {
					excluded = [];
				}
			}

			if (NewFilter.op == "none") {
				nullIncluded = false;
				included = []; excluded = [];
			} else {
				if ((this.gridData[UcId].differentValues[DataFieldFilter].indexOf("#NuN#") > -1) ||
					(excluded.indexOf(this.gridData[UcId].blackLists[DataFieldFilter].hiddens[t]) != -1)) {
					if (this.gridData[UcId].blackLists[DataFieldFilter].visibles.indexOf("#NuN#") == -1) {
						nullIncluded = false;
					}
				} else {
					if (this.gridData[UcId].blackLists[DataFieldFilter].defaultAction == "Exclude") {
						nullIncluded = false;
					}
				}
			}


			if ((this.gridData[UcId].blackLists[DataFieldFilter].hasNull) && (!(NewFilter.op == "none"))) {
				//asociated psuedo-Null
				var reallyPseudoNull = this.gridData[UcId].defaultNullText
				var finded = false
				var data_length = 0;
				for (var u = 0; u < this.gridData[UcId].differentValues[DataFieldFilter].length; u++) {
					data_length = this.gridData[UcId].differentValues[DataFieldFilter][u].length;
				}
				for (var u = 0; u < this.gridData[UcId].differentValues[DataFieldFilter].length; u++) {
					if (this.gridData[UcId].differentValues[DataFieldFilter][u].trimpivot() == this.gridData[UcId].defaultNullText) {
						reallyPseudoNull = this.gridData[UcId].differentValues[DataFieldFilter][u];
						finded = true;
						break;
					}
				}
				if (!finded) {
					for (var t = 0; t < data_length - this.gridData[UcId].defaultNullText.length; t++) {
						reallyPseudoNull = reallyPseudoNull + " ";
					}
				}

				if (!nullIncluded) {
					if (excluded.indexOf(reallyPseudoNull) == -1) {
						excluded.push(reallyPseudoNull)
						if (this.gridData[UcId].blackLists[DataFieldFilter].hiddens.indexOf(reallyPseudoNull) == -1) {
							this.gridData[UcId].blackLists[DataFieldFilter].hiddens.push(reallyPseudoNull)
						}
					}
					if (included.indexOf(reallyPseudoNull) != -1) {
						included.splice(included.indexOf(reallyPseudoNull), 1)
					}
					if (this.gridData[UcId].blackLists[DataFieldFilter].visibles.indexOf(reallyPseudoNull) != -1) {
						this.gridData[UcId].blackLists[DataFieldFilter].visibles.splice(this.gridData[UcId].blackLists[DataFieldFilter].visibles.indexOf(reallyPseudoNull), 1)
					}
				} else {
					if (included.indexOf(reallyPseudoNull) == -1) {
						if (excluded.indexOf(reallyPseudoNull) != -1) {
							excluded.splice(excluded.indexOf(reallyPseudoNull), 1)
							included.push(reallyPseudoNull)
						} else {
							if (this.gridData[UcId].blackLists[DataFieldFilter].defaultAction == "Exclude") {
								included.push(reallyPseudoNull)
							}
						}
						if (this.gridData[UcId].blackLists[DataFieldFilter].hiddens.indexOf(reallyPseudoNull) != -1) {
							this.gridData[UcId].blackLists[DataFieldFilter].hiddens.splice(this.gridData[UcId].blackLists[DataFieldFilter].hiddens.indexOf(reallyPseudoNull), 1)
							if (this.gridData[UcId].blackLists[DataFieldFilter].visibles.indexOf(reallyPseudoNull) == -1) {
								this.gridData[UcId].blackLists[DataFieldFilter].visibles.push(reallyPseudoNull)
							}
						}
					}
				}
			}

			var allValuesLoaded = false;
			if (this.gridData[UcId].differentValuesPaginationInfo[DataFieldFilter] != null) {
				allValuesLoaded = (this.gridData[UcId].differentValuesPaginationInfo[DataFieldFilter].previousPage == this.gridData[UcId].differentValuesPaginationInfo[DataFieldFilter].totalPages)
			}
			var noFilterNeeded = (((nullIncluded) || (!this.gridData[UcId].blackLists[DataFieldFilter].hasNull))
				&& (excluded.length == 0) && (NewFilter.op != "none") && (NewFilter.op != "push")
				&& ((this.gridData[UcId].blackLists[DataFieldFilter].defaultAction == "Include") || (allValuesLoaded))
				&& (!(NewFilter.op == "reverse"))
			);

			var pos = 0;
			for (var t = 0; t < this.gridData[UcId].filterInfo.length; t++) {
				if (this.gridData[UcId].filterInfo[t].DataField == DataFieldFilter) {
					filterExist = true;
					this.gridData[UcId].filterInfo[t].NullIncluded = nullIncluded
					this.gridData[UcId].filterInfo[t].NotNullValues.Included = included
					this.gridData[UcId].filterInfo[t].NotNullValues.Excluded = excluded
					this.gridData[UcId].filterInfo[t].NotNullValues.DefaultAction = this.gridData[UcId].blackLists[DataFieldFilter].defaultAction
					pos = t;
				}
			}
			if (noFilterNeeded) {
				this.gridData[UcId].filterInfo.splice(pos, 1)
			}
			if ((!filterExist) && (!noFilterNeeded)) {
				var notNullValues = { Included: included, Excluded: excluded, DefaultAction: this.gridData[UcId].blackLists[DataFieldFilter].defaultAction }
				filter = { DataField: DataFieldFilter, NullIncluded: nullIncluded, NotNullValues: notNullValues }
				this.gridData[UcId].filterInfo.push(filter);
			}
		},

		readScrollValue: function (UcId, columnNumber) {
			var dataField = this.gridData[UcId].columnDataField[columnNumber];
			var posColumnNumber = this.gridData[UcId].originalColumnDataField.indexOf(this.gridData[UcId].columnDataField[columnNumber])
			if (!this.gridData[UcId].differentValuesPaginationInfo[dataField].blocked) {
				this.gridData[UcId].differentValuesPaginationInfo[dataField].blocked = true;
				if (!this.gridData[UcId].differentValuesPaginationInfo[dataField].filtered) {
					var ValuePageInfo = this.gridData[UcId].differentValuesPaginationInfo[dataField]
					var page = ValuePageInfo.previousPage + 1;
					this.gridData[UcId].lastRequestValue = dataField;
					qv.collection[this.gridData[UcId].IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
						var res = JSON.parse(resJSON);
						OAT_JS.grid.appendNewValueData(UcId, res)
					}).closure(this), [dataField, page, 10, ""]);
				} else {
					var ValuePageInfo = this.gridData[UcId].filteredValuesPaginationInfo[dataField]
					var page = ValuePageInfo.previousPage + 1;
					this.gridData[UcId].lastRequestValue = dataField;
					var filterText = ValuePageInfo.filteredText
					qv.collection[this.gridData[UcId].IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
						var res = JSON.parse(resJSON);
						OAT_JS.grid.appendNewFilteredValueData(UcId, res, posColumnNumber, filterText)
					}).closure(this), [dataField, page, 10, ValuePageInfo.filteredText]);
				}
			}
			var j = 0;
		},
		appendNewValueData: function (UcId, data, whenFilter) {
			var dataField = this.gridData[UcId].lastRequestValue
			var ValuePageInfo = this.gridData[UcId].differentValuesPaginationInfo[dataField]
			if ((data.PageNumber > ValuePageInfo.previousPage) || (whenFilter)) {
				this.gridData[UcId].differentValuesPaginationInfo[dataField].previousPage = data.PageNumber
				this.gridData[UcId].differentValuesPaginationInfo[dataField].totalPages = data.PagesCount
				var newValues = [];

				if (data.Null) {
					if (this.gridData[UcId].differentValues[dataField].indexOf("#NuN#") == -1) {
						this.gridData[UcId].differentValues[dataField].push("#NuN#")
					}
				}

				//add to differentValues
				for (var i = 0; i < data.NotNullValues.length; i++) {
					var val = data.NotNullValues[i];
					if (this.gridData[UcId].differentValues[dataField].indexOf(val) == -1) {
						this.gridData[UcId].differentValues[dataField].push(val)
						newValues.push(val)
					}//lo mismo
					if (this.gridData[UcId].blackLists[dataField].defaultAction == "Include") {
						if ((this.gridData[UcId].blackLists[dataField].visibles.indexOf(val) == -1)
							&& (this.gridData[UcId].blackLists[dataField].hiddens.indexOf(val) == -1)) {
							this.gridData[UcId].blackLists[dataField].visibles.push(val)
						}
					} else {
						if ((this.gridData[UcId].blackLists[dataField].visibles.indexOf(val) == -1)
							&& (this.gridData[UcId].blackLists[dataField].hiddens.indexOf(val) == -1)) {
							this.gridData[UcId].blackLists[dataField].hiddens.push(val)
						}
					}
				}

				var columnNumber = this.gridData[UcId].columnDataField.indexOf(dataField);
				var originalColumn = this.gridData[UcId].originalColumnDataField.indexOf(dataField)

				this.gridData[UcId].grid.loadDifferentValues(columnNumber, this.gridData[UcId].differentValues[dataField])

				for (var nI = 0; nI < newValues.length; nI++) {
					var checked = true;
					if (this.gridData[UcId].blackLists[dataField].state != "all") {
						if (this.gridData[UcId].blackLists[dataField].visibles.findIndex(newValues[nI]) < 0) {
							checked = false;
						}
					}

					if (!((this.gridData[UcId].blackLists[dataField].hasNull) && (newValues[nI].trimpivot() == this.gridData[UcId].defaultNullText))) {
						var pict_value = OAT.ApplyPictureValue(newValues[nI].trimpivot(), this.gridData[UcId].rowsMetadata.columnsDataType[originalColumn],
							this.gridData[UcId].rowsMetadata.defaultPicture, this.gridData[UcId].rowsMetadata.forPivotCustomPicture[originalColumn]).replace(/ /g, "\u00A0");
						OAT.appendNewPairToPopUp(this.gridData[UcId], newValues[nI], columnNumber, checked, pict_value, dataField)
					}
				}
			}
			if (this.gridData[UcId].differentValuesPaginationInfo[dataField].previousPage < data.PagesCount)
				this.gridData[UcId].differentValuesPaginationInfo[dataField].blocked = false;
		},
		resetScrollValue: function (UcId, dataField, columnNumber) { //after filtered when input serach is clean, restor values without filter
			this.gridData[UcId].differentValuesPaginationInfo[dataField].filtered = false;
			this.gridData[UcId].differentValuesPaginationInfo[dataField].blocked = true;

			var columnNumber = this.gridData[UcId].columnDataField.indexOf(dataField);
			var originalColumn = this.gridData[UcId].originalColumnDataField.indexOf(dataField)

			OAT.removeAllPairsFromPopUp(this.gridData[UcId], columnNumber, OAT_JS.grid.cantPages(UcId, dataField) > 1);

			for (var u = 0; u < this.gridData[UcId].differentValues[dataField].length; u++) {
				var checked = true;
				var value = this.gridData[UcId].differentValues[dataField][u];
				if (this.gridData[UcId].blackLists[dataField].state != "all") {
					if (this.gridData[UcId].blackLists[dataField].visibles.findIndex(value) < 0) {
						checked = false;
					}
				}
				var pict_value = OAT.ApplyPictureValue(value.trimpivot(), this.gridData[UcId].rowsMetadata.columnsDataType[originalColumn],
					this.gridData[UcId].rowsMetadata.defaultPicture, this.gridData[UcId].rowsMetadata.forPivotCustomPicture[originalColumn]).replace(/ /g, "\u00A0");

				if (!((this.gridData[UcId].blackLists[dataField].hasNull) && (value.trimpivot() == this.gridData[UcId].defaultNullText))) {
					OAT.appendNewPairToPopUp(this.gridData[UcId], value, columnNumber, checked, pict_value, dataField)
				}
			}

			if (this.gridData[UcId].differentValuesPaginationInfo[dataField].previousPage < OAT_JS.grid.cantPages(UcId, dataField))
				this.gridData[UcId].differentValuesPaginationInfo[dataField].blocked = false;
		},
		resetAllScrollValue: function (UcId) { //when closing the filter popup
			for (var id = 0; id < this.gridData[UcId].grid.columns.length; id++) {
				var field = this.gridData[UcId].grid.columns[id].getAttribute("dataField");
				this.gridData[UcId].differentValuesPaginationInfo[field].filtered = false;
				this.gridData[UcId].differentValuesPaginationInfo[field].blocked = true;
				if (this.gridData[UcId].differentValuesPaginationInfo[field].previousPage < this.gridData[UcId].differentValuesPaginationInfo[field].totalPages)
					this.gridData[UcId].differentValuesPaginationInfo[field].blocked = false;
			}
		},
		appendNewFilteredValueData: function (UcId, data, columnNumber, filterValue) { //add pairs when filtering by filter input
			var dataField = this.gridData[UcId].lastRequestValue
			var columnNumber = this.gridData[UcId].columnDataField.indexOf(dataField);
			var originalColumn = this.gridData[UcId].originalColumnDataField.indexOf(dataField)

			var ValuePageInfo = this.gridData[UcId].filteredValuesPaginationInfo[dataField]
			if (((filterValue) || (filterValue == "")) && (ValuePageInfo.filteredText != filterValue)) {
				return;
			}
			if (data.PageNumber > ValuePageInfo.previousPage) {
				this.gridData[UcId].filteredValuesPaginationInfo[dataField].previousPage = data.PageNumber
				this.gridData[UcId].filteredValuesPaginationInfo[dataField].totalPages = data.PagesCount

				if (data.Null) {
					if (this.gridData[UcId].differentValues[dataField].indexOf("#NuN#") == -1) {
						this.gridData[UcId].differentValues[dataField].push("#NuN#")
					}
				}

				for (var i = 0; i < data.NotNullValues.length; i++) {
					var alreadyInValues = (this.gridData[UcId].differentValues[dataField].indexOf(data.NotNullValues[i]) != -1)
					//append to different values
					if (this.gridData[UcId].differentValues[dataField].indexOf(data.NotNullValues[i]) == -1) {
						this.gridData[UcId].differentValues[dataField].push(data.NotNullValues[i])
					}
					if ((this.gridData[UcId].blackLists[dataField].defaultAction == "Include") && (!alreadyInValues)) {
						if ((this.gridData[UcId].blackLists[dataField].visibles.indexOf(data.NotNullValues[i]) == -1)
							&& (this.gridData[UcId].blackLists[dataField].hiddens.indexOf(data.NotNullValues[i]) == -1)) {
							this.gridData[UcId].blackLists[dataField].visibles.push(data.NotNullValues[i])
						}
					} else {
						if ((this.gridData[UcId].blackLists[dataField].visibles.indexOf(data.NotNullValues[i]) == -1)
							&& (this.gridData[UcId].blackLists[dataField].hiddens.indexOf(data.NotNullValues[i]) == -1)) {
							this.gridData[UcId].blackLists[dataField].hiddens.push(data.NotNullValues[i])
						}
					}

					var checked = true;
					if (this.gridData[UcId].blackLists[dataField].state != "all") {
						if (this.gridData[UcId].blackLists[dataField].visibles.findIndex(data.NotNullValues[i]) < 0) {
							checked = false;
						}
					}
					var pict_value = OAT.ApplyPictureValue(data.NotNullValues[i].trimpivot(), this.gridData[UcId].rowsMetadata.columnsDataType[originalColumn],
						this.gridData[UcId].rowsMetadata.defaultPicture, this.gridData[UcId].rowsMetadata.forPivotCustomPicture[originalColumn]).replace(/ /g, "\u00A0");
					if (!((this.gridData[UcId].blackLists[dataField].hasNull) && (data.NotNullValues[i].trimpivot() == this.gridData[UcId].defaultNullText))) {
						OAT.appendNewPairToPopUp(this.gridData[UcId], data.NotNullValues[i], columnNumber, checked, pict_value, dataField)
					}
				}
				if (this.gridData[UcId].filteredValuesPaginationInfo[dataField].previousPage < data.PagesCount)
					this.gridData[UcId].differentValuesPaginationInfo[dataField].blocked = false;
			}
		},
		initValueRead: function (UcId, columnNumber) {
			if (columnNumber >= this.gridData[UcId].grid.columns.length) {
				return;
			} else {
			  if (this.gridData[UcId].grid.columns[columnNumber].getAttribute("validPositions") != ""){
				this.gridData[UcId].grid.lastRequestValue = this.gridData[UcId].grid.columns[columnNumber].getAttribute("dataField")
				var cantItems = 10;
				if ((qv.collection[this.gridData[UcId].IdForQueryViewerCollection].AutoRefreshGroup != "")
			/*  || (typeof(qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].FilterChanged) == 'function')*/) {
					cantItems = 0;
				}
				qv.collection[this.gridData[UcId].IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
					var data = JSON.parse(resJSON);
					//load data
					dataField = this.gridData[UcId].grid.lastRequestValue
					this.gridData[UcId].differentValuesPaginationInfo[dataField].previousPage = data.PageNumber
					this.gridData[UcId].differentValuesPaginationInfo[dataField].totalPages = data.PagesCount

					//end load data
					var columnNumber = 0;
					for (var t = 0; t < this.gridData[UcId].grid.columns.length; t++) {
						if (this.gridData[UcId].grid.lastRequestValue == this.gridData[UcId].grid.columns[t].getAttribute("dataField")) {
							columnNumber = t;
							break;
						}
					}


					//null value?
					if (data.Null) {
						this.gridData[UcId].blackLists[dataField].hasNull = true;
						if (this.gridData[UcId].differentValues[dataField].indexOf("#NuN#") == -1) {
							this.gridData[UcId].differentValues[dataField].push("#NuN#")
						}
						var nullIncluded = true;
						for (var i = 0; i < this.gridData[UcId].filterInfo.length; i++) {
							if (this.gridData[UcId].filterInfo[i].DataField == dataField) {
								if (!this.gridData[UcId].filterInfo[i].NullIncluded) {
									nullIncluded = false;
								}
							}
						}
						if ((nullIncluded) && (this.gridData[UcId].blackLists[dataField].visibles.indexOf("#NuN#") == -1)) {
							this.gridData[UcId].blackLists[dataField].visibles.push("#NuN#");
						}
					} else {
						this.gridData[UcId].blackLists[dataField].hasNull = false;
					}


					for (var i = 0; i < data.NotNullValues.length; i++) {
						if (this.gridData[UcId].differentValues[dataField].indexOf(data.NotNullValues[i]) == -1) {
							this.gridData[UcId].differentValues[dataField].push(data.NotNullValues[i])
						}
						if ((this.gridData[UcId].blackLists[dataField].state == "all")
							&& (this.gridData[UcId].blackLists[dataField].visibles.indexOf(data.NotNullValues[i]) == -1)) {
							this.gridData[UcId].blackLists[dataField].visibles.push(data.NotNullValues[i])
						}
						if ((this.gridData[UcId].blackLists[dataField].state == "none")
							&& (this.gridData[UcId].blackLists[dataField].hiddens.indexOf(data.NotNullValues[i]) == -1)) {
							this.gridData[UcId].blackLists[dataField].hiddens.push(data.NotNullValues[i])
						}
						if ((this.gridData[UcId].blackLists[dataField].defaultAction == "Exclude")
							&& (this.gridData[UcId].blackLists[dataField].state == "") && (data.NotNullValues[i].trimpivot() != "")
							&& (this.gridData[UcId].blackLists[dataField].visibles.length > 0)) { //correct blanck spaces when initial user filter
							for (var j = 0; j < this.gridData[UcId].blackLists[dataField].visibles.length; j++) {
								if (this.gridData[UcId].blackLists[dataField].visibles[j] == data.NotNullValues[i].trimpivot()) {
									this.gridData[UcId].blackLists[dataField].visibles[j] = data.NotNullValues[i]
								}
							}
						}
					}



					this.gridData[UcId].grid.loadDifferentValues(columnNumber, this.gridData[UcId].differentValues[dataField]);

					columnNumber++;
					OAT_JS.grid.initValueRead(UcId, columnNumber)

				}).closure(this), [this.gridData[UcId].grid.lastRequestValue, 1, cantItems, ""]);
			  } else {
			  		columnNumber++;
					OAT_JS.grid.initValueRead(UcId, columnNumber)
			  }
			}
		},
		changeValues: function (UcId, dataField, columnNumber, data, filterText) { //when filter by search filter, delete pairs and show new ones
			var searchInput = jQuery("#" + UcId + dataField)[0];

			if (((searchInput.value) || (searchInput.value == "")) && (searchInput.value != filterText)) {
				return;
			}

			var columnNumber = this.gridData[UcId].columnDataField.indexOf(dataField);
			var originalColumn = this.gridData[UcId].originalColumnDataField.indexOf(dataField)

			this.gridData[UcId].differentValuesPaginationInfo[dataField].filtered = true;
			this.gridData[UcId].differentValuesPaginationInfo[dataField].blocked = true;
			OAT.removeAllPairsFromPopUp(this.gridData[UcId], columnNumber, data.PagesCount > 1);

			//set filtered pagination info
			this.gridData[UcId].filteredValuesPaginationInfo[dataField].previousPage = 1
			this.gridData[UcId].filteredValuesPaginationInfo[dataField].totalPages = data.PagesCount
			this.gridData[UcId].filteredValuesPaginationInfo[dataField].filteredText = filterText

			for (var i = 0; i < data.NotNullValues.length; i++) {
				var alreadyInValues = (this.gridData[UcId].differentValues[dataField].indexOf(data.NotNullValues[i]) != -1)
				//append to different values
				if (this.gridData[UcId].differentValues[dataField].indexOf(data.NotNullValues[i]) == -1) {
					this.gridData[UcId].differentValues[dataField].push(data.NotNullValues[i])
				}
				if ((this.gridData[UcId].blackLists[dataField].state == "all") ||
					((this.gridData[UcId].blackLists[dataField].defaultAction == "Include") && (!alreadyInValues))) {
					//if Include new values and is a new value
					if ((this.gridData[UcId].blackLists[dataField].visibles.indexOf(data.NotNullValues[i]) == -1)
						&& (this.gridData[UcId].blackLists[dataField].hiddens.indexOf(data.NotNullValues[i]) == -1)) {
						this.gridData[UcId].blackLists[dataField].visibles.push(data.NotNullValues[i])
					}
				}
				//


				var checked = true;
				if (this.gridData[UcId].blackLists[dataField].state != "all") {
					if (this.gridData[UcId].blackLists[dataField].visibles.findIndex(data.NotNullValues[i]) < 0) {
						checked = false;
					}
				}
				this.gridData[UcId].filteredValuesPaginationInfo[dataField].values.push(data.NotNullValues[i]);
				var pict_value = OAT.ApplyPictureValue(data.NotNullValues[i].trimpivot(), this.gridData[UcId].rowsMetadata.columnsDataType[originalColumn],
					this.gridData[UcId].rowsMetadata.defaultPicture, this.gridData[UcId].rowsMetadata.forPivotCustomPicture[originalColumn]).replace(/ /g, "\u00A0");
				if (!((this.gridData[UcId].blackLists[dataField].hasNull) && (data.NotNullValues[i].trimpivot() == this.gridData[UcId].defaultNullText))) {
					OAT.appendNewPairToPopUp(this.gridData[UcId], data.NotNullValues[i], columnNumber, checked, pict_value, dataField);
				}
			}

			if (data.PagesCount > 0)
				this.gridData[UcId].differentValuesPaginationInfo[dataField].blocked = false;
		},
		setColumnVisibleValue: function (UcId, column, visible) {
			var origColumnNumber = this.gridData[UcId].originalColumnDataField.indexOf(this.gridData[UcId].columnDataField[column])
			this.gridData[UcId].columnVisible[origColumnNumber] = visible
			OAT.SaveStateWhenServerPaging(OAT_JS.grid.gridData[UcId].grid, UcId, OAT_JS.grid.gridData[UcId].rowsPerPage, OAT_JS.grid.gridData[UcId].dataFieldOrder,
				OAT_JS.grid.gridData[UcId].orderType, OAT_JS.grid.gridData[UcId].filterInfo, OAT_JS.grid.gridData[UcId].blackLists, OAT_JS.grid.gridData[UcId].columnVisible)

			//call autorefresh
			if (qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].AutoRefreshGroup != "") {
				var meta = OAT.createXMLMetadata(OAT_JS.grid.gridData[UcId], null, true);

				var spl = OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection;
				var listennings = qv.collection[spl];
				if ((listennings != "") && (listennings != null) && (listennings != undefined)) {
					qv.util.autorefresh.UpdateLayoutSameGroup(listennings, meta);
				}
			}

		},
		getTableWhenServerPagination: function (UcId) {
			var res = qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].getPageDataForTableSync([1, 0, true, "", "", OAT_JS.grid.gridData[UcId].filterInfo]);
			var t = 0;
			var records = res.split("<Recordset");//res.split("<Page PageNumber=\"1\">")
			var rec = "<Recordset" + records[1]
			var last = rec.split("</Page>");
			var finalRes = last[0] + '</Page>\n</Recordset>';//"</Table>";
			return finalRes;
		},
		setFilterChangedWhenServerPagination: function (UcId, oatDimension) {
			if ((qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].FilterChanged) || (qv.util.isGeneXusPreview())) {
				var df = oatDimension.getAttribute("dataField")

				var difValues = OAT_JS.grid.gridData[UcId].differentValues[df];
				var diffValuesPagInfo = OAT_JS.grid.gridData[UcId].differentValuesPaginationInfo[df];

				if (OAT_JS.grid.gridData[UcId].differentValuesPaginationInfo[df].previousPage == OAT_JS.grid.gridData[UcId].differentValuesPaginationInfo[df].totalPages) {

					var blacInfo = OAT_JS.grid.gridData[UcId].blackLists[df]

					var datastr = "<DATA event=\"FilterChanged\" name=\"" + oatDimension.getAttribute("name") + "\" displayName=\"" + oatDimension.getAttribute("displayName") + "\">"

					for (var dvi = 0; dvi < difValues.length; dvi++) {
						var checked = true;
						if (OAT_JS.grid.gridData[UcId].blackLists[df].state != "all") {
							if (OAT_JS.grid.gridData[UcId].blackLists[df].visibles.findIndex(difValues[dvi]) < 0) {
								checked = false;
							}
						}
						if (checked) {
							datastr = datastr + '<VALUE>' + difValues[dvi] + '</VALUE>';
						}
					}

					datastr = datastr + "</DATA>"


					if (qv.util.isGeneXusPreview())
						window.external.SendText(qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].ControlName, datastr);

					var xml_doc = qv.util.dom.xmlDocument(datastr);
					var Node = qv.util.dom.selectXPathNode(xml_doc, "/DATA");
					qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].FilterChangedData = {};
					qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].FilterChangedData.Name = Node.getAttribute("name");
					qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].FilterChangedData.SelectedValues = [];
					var valueIndex = -1;
					for (var i = 0; i < Node.childNodes.length; i++)
						if (Node.childNodes[i].nodeName == "VALUE") {
							valueIndex++;
							qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].FilterChangedData.SelectedValues[valueIndex] = Node.childNodes[i].firstChild.nodeValue;
						}
					if (qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].FilterChanged) {
						qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].FilterChanged();
					}
				} else {
					OAT_JS.grid.gridData[UcId].differentValuesPaginationInfo[df].blocked = true;
					var ValuePageInfo = OAT_JS.grid.gridData[UcId].differentValuesPaginationInfo[df]
					var page = ValuePageInfo.previousPage + 1;
					OAT_JS.grid.gridData[UcId].lastRequestValue = df;
					qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
						var res = JSON.parse(resJSON);
						OAT_JS.grid.appendNewValueData(UcId, res, true)
						OAT_JS.grid.setFilterChangedWhenServerPagination(UcId, oatDimension)
					}).closure(this), [df, page, 0, ""]);
				}
			}

		},
		getAllDataRowsForExport: function (UcId, _selfgrid, fileName, format) {
			qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].getPageDataForTable((function (resXML) {
				var dataString = resXML;
				var stringRecord = dataString.split("<Record>");
				var data = []
				for (var i = 1; i < stringRecord.length; i++) {
					var recordData = [];
					for (var j = 0; j < OAT_JS.grid.gridData[UcId].grid.columns.length; j++) {
						recordData[j] = "#NuN#"
						var dt = stringRecord[i].split("<" + OAT_JS.grid.gridData[UcId].grid.columns[j].getAttribute("dataField") + ">")
						if (dt.length > 1) {
							var at = dt[1].split("</" + OAT_JS.grid.gridData[UcId].grid.columns[j].getAttribute("dataField") + ">")
							recordData[j] = at[0]
						}
					}
					data.push(recordData)

					if (format != "xlsx") {
						if ((i > OAT_JS.grid.gridData[UcId].rowsPerPage) && !(OAT_JS.grid.gridData[UcId].rowsPerPage == "")) { //createRow
							var row = OAT_JS.grid.gridData[UcId].grid.createRow(recordData, OAT_JS.grid.gridData[UcId].rowsMetadata.columnsDataType, OAT_JS.grid.gridData[UcId].rowsMetadata.defaultPicture,
								OAT_JS.grid.gridData[UcId].rowsMetadata.forPivotCustomPicture, OAT_JS.grid.gridData[UcId].rowsMetadata.conditionalFormatsColumns,
								OAT_JS.grid.gridData[UcId].rowsMetadata.formatValues, OAT_JS.grid.gridData[UcId].rowsMetadata.forPivotCustomFormat, OAT_JS.grid.gridData[UcId].rowsMetadata.columns,
								null, OAT_JS.grid.gridData[UcId].columnVisible);
							//row.style.display = "none";
							row.style.visibility = "collapse";
						}
					}
				}

				switch (format) {
					case "pdf": OAT.ExportToPdf(_selfgrid, fileName); break;
					case "xml": OAT.ExportToXML(_selfgrid, fileName); break;
					case "html": OAT_JS.grid.gridData[UcId].grid.ExportToHtml(_selfgrid, fileName); break;
					case "xls": OAT.ExportToExcel(_selfgrid, fileName); break;
					case "xlsx": OAT.ExportToExcel2010(_selfgrid, fileName, true, data, UcId); break;
				}

				OAT_JS.grid.gridData[UcId].grid.removeAllCollapseRows()

			}).closure(this), [1, 0, false, OAT_JS.grid.gridData[UcId].dataFieldOrder, OAT_JS.grid.gridData[UcId].orderType, OAT_JS.grid.gridData[UcId].filterInfo]);

			
		},
		restoreDefaultView: function (UcId) {
			//reset order
			OAT_JS.grid.gridData[UcId].dataFieldOrder = ""
			OAT_JS.grid.gridData[UcId].orderType = ""
			//reset filter info
			this.gridData[UcId].filterInfo = [];
			var tempInfo = [];
			for (var id = 0; id < OAT_JS.grid.gridData[UcId].grid.columns.length; id++) {
				tempInfo[OAT_JS.grid.gridData[UcId].grid.columns[id].getAttribute("dataField")] = this.gridData[UcId].blackLists[OAT_JS.grid.gridData[UcId].grid.columns[id].getAttribute("dataField")].hasNull;
			}
			for (var id = 0; id < OAT_JS.grid.gridData[UcId].grid.columns.length; id++) {
				this.gridData[UcId].blackLists[OAT_JS.grid.gridData[UcId].grid.columns[id].getAttribute("dataField")] = {
					state: "all", visibles: [], defaultAction: "Include", hiddens: [],
					hasNull: tempInfo[OAT_JS.grid.gridData[UcId].grid.columns[id].getAttribute("dataField")]
				};
			}

			for (var c = 0; c < this.gridData[UcId].columnVisible.length; c++) {
				this.gridData[UcId].grid.applySortOrderType(c, 1);
				this.gridData[UcId].columnVisible[c] = true;
				this.gridData[UcId].grid.showColumnHeader(c);
			}

			this.gridData[UcId].rowsPerPage = this.gridData[UcId].defaultValues.rowsPerPage
			if (jQuery("#" + this.gridData[UcId].grid.controlName + "tablePagination_rowsPerPage").length > 0) {
				jQuery("#" + this.gridData[UcId].grid.controlName + "tablePagination_rowsPerPage")[0].value = this.gridData[UcId].defaultValues.rowsPerPage
			}

		},
		getStateChange: function (UcId) {
			if (this.gridData[UcId].rowsPerPage != this.gridData[UcId].defaultValues.rowsPerPage) {
				return true;
			}
			if ((this.gridData[UcId].defaultValues.dataFieldOrder != OAT_JS.grid.gridData[UcId].dataFieldOrder) || (this.gridData[UcId].defaultValues.orderType != OAT_JS.grid.gridData[UcId].orderType)) {
				return true;
			}
			if ((this.gridData[UcId].filterInfo != undefined) && (this.gridData[UcId].filterInfo.length > 0)) {//TODO: change if can be filter initial values
				return true
			}
			for (var t = 0; t < this.gridData[UcId].columnVisible.length; t++) {
				if (!this.gridData[UcId].columnVisible[t]) {
					return true
				}
			}
			//for (var t = 0; t < this.gridData[UcId].columnDataField.length; t++){
			//	if (this.gridData[UcId].columnDataField[t] != this.gridData[UcId].originalColumnDataField[t]){
			//		return true;
			//	}
			//}
			return false
		},
		refreshPivotWhenServerPagination: function (UcId, dataFieldOrderChanged, OrderChanged, dataFieldPositions) {
			/*if (dataFieldPositions.length > 0){
				this.gridData[UcId].columnDataField = []
				this.gridData[UcId].columnDataField = dataFieldPositions
			} */
			self.getDataForTable(UcId, 1, this.gridData[UcId].rowsPerPage, true, dataFieldOrderChanged, OrderChanged, "", "", "", true);
		},
		moveToFirstPage: function (UcId) {
			if (this.gridData[UcId].actualPageNumber > 1) {
				self.getDataForTable(UcId, 1, this.gridData[UcId].rowsPerPage, false, "", "", "", "", false);
			}
		},
		moveToNextPage: function (UcId) {
			if (this.gridData[UcId].actualPageNumber < this.gridData[UcId].actualCantPages) {
				self.getDataForTable(UcId, this.gridData[UcId].actualPageNumber + 1, this.gridData[UcId].rowsPerPage, false, "", "", "", "", false);
			}
		},
		moveToLastPage: function (UcId) {
			if (this.gridData[UcId].actualPageNumber < this.gridData[UcId].actualCantPages) {
				self.getDataForTable(UcId, this.gridData[UcId].actualCantPages, this.gridData[UcId].rowsPerPage, false, "", "", "", "", false);
			}
		},
		moveToPreviousPage: function (UcId) {
			if (this.gridData[UcId].actualPageNumber > 1) {
				self.getDataForTable(UcId, this.gridData[UcId].actualPageNumber - 1, this.gridData[UcId].rowsPerPage, false, "", "", "", "", false);
			}
		},
		cantPages: function (UcId, dataField) {
			return this.gridData[UcId].differentValuesPaginationInfo[dataField].totalPages
		},
		setDataFieldPosition: function (UcId, dataFieldPositions) {
			this.gridData[UcId].columnDataField = []
			this.gridData[UcId].columnDataField = dataFieldPositions
			//call autorefresh
			if (qv.collection[OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection].AutoRefreshGroup != "") {
				var meta = OAT.createXMLMetadata(OAT_JS.grid.gridData[UcId], null, true);

				var spl = OAT_JS.grid.gridData[UcId].IdForQueryViewerCollection;
				var listennings = qv.collection[spl];
				if ((listennings != "") && (listennings != null) && (listennings != undefined)) {
					qv.util.autorefresh.UpdateLayoutSameGroup(listennings, meta);
				}
			}
		},
		addValueToDifferentValues: function (UcId, dataField, val) {
			var originalColumn = this.gridData[UcId].originalColumnDataField.indexOf(dataField);
			var dataType = this.gridData[UcId].grid.columnsDataType[originalColumn];
			var sortInt = false;
			if ((dataType == "integer") || (dataType == "real")) {
				sortInt = true;
			}



			var tempData = [];
			var added = false;

			if (val == "#NuN#") {
				tempData.push(val);
				added = true;
			}

			for (var l = 0; l < this.gridData[UcId].differentValues[dataField].length; l++) {
				if (!sortInt) {
					if ((val < this.gridData[UcId].differentValues[dataField][l]) && (!added)) {
						tempData.push(val);
						added = true;
					}
					tempData.push(this.gridData[UcId].differentValues[dataField][l])
				} else {
					if ((parseFloat(val) < parseFloat(this.gridData[UcId].differentValues[dataField][l])) && (!added)) {
						tempData.push(val);
						added = true;
					}
					tempData.push(this.gridData[UcId].differentValues[dataField][l])
				}
			}

			if (!added) {
				tempData.push(val)
			}

			this.gridData[UcId].differentValues[dataField] = tempData;

		}
	}

	OAT_JS.pivot = {
		panel: 1,
		tab: 5,
		div: "",
		needs: ["pivot", "statistics"],
		cb: function (pivotdiv, page, content, defaultPicture, QueryViewerCollection, colms, formatValue, conditionalFormatsColumns,
			formatValueMeasures, autoResize, disableColumnSort, UcId, IdForQueryViewerCollection, rememberLayout, ShowMeasuresAsRows,
			formulaInfo, fullRecord, serverPagination, pagingData, HideDataFilds, OrderFildsHidden, initMetadata, relativePath, pivotParams) {
			this.div = pivotdiv;
			var cols = columnNumbers.length + rowNumbers.length + filterNumbers.length;
			if (measures.length > 1) {
				var prevCol = cols;
				cols = cols + measures.length - 1;
				for (var i = prevCol; i < cols; i++) {
					columnNumbers.push(i);
				}
			} else {
				for (var i = 0; i < data.length; i++) {
					data[i].push("0");
				}
			}
			var pivot;
			try {
				pivot = new OAT.Pivot(content, page, header, data, columnNumbers, rowNumbers, filterNumbers, cols, query, conditionalFormats, UcId, pageSize, defaultPicture, QueryViewerCollection, colms, pivotdiv,
					formatValue, conditionalFormatsColumns, formatValueMeasures, measures, autoResize, disableColumnSort, UcId, IdForQueryViewerCollection, rememberLayout,
					ShowMeasuresAsRows, formulaInfo, fullRecord, serverPagination, pagingData, HideDataFilds, OrderFildsHidden, initMetadata, relativePath,
					{ Allow: pivotParams.AllowSelection, EntireLine: pivotParams.SelectLine});
			} catch (Error) {
				//alert(Error)
			}
			return pivot;
		}
	}

	function parseToIntRegisterValue(string, registerValue) {
		if (string.indexOf(registerValue) > 0) {
			var tmpstr = string.split(registerValue + '="');
			if (tmpstr.length == 1) {
				tmpstr = string.split(registerValue + "='");
				return (tmpstr[1]) ? parseInt(tmpstr[1].split("'")[0]) : -1;
			}
			return (tmpstr[1]) ? parseInt(tmpstr[1].split('"')[0]) : -1;
		}
		return -1;
	}

	function parseToStringRegisterValue(string, registerValue) {
		if (string.indexOf(registerValue) > 0) {
			var tmpstr = string.split(registerValue + '="');
			if (tmpstr.length == 1) {
				tmpstr = string.split(registerValue + "='");
				return (tmpstr[1]) ? (tmpstr[1].split("'")[0]) : -1;
			}
			return (tmpstr[1]) ? (tmpstr[1].split('"')[0]) : -1;
		}
		return -1;
	}

	function EvaluateExpressionPivotJs(expression, data, formulaInfo) {
		var tokens = []
		for (var i = 0; i < expression.length; i++) {
			tokens[i] = expression[i]
		}
		var evalStack = [];

		while (tokens.length != 0) {
			var currentToken = tokens.shift();
			if (isOperator(currentToken)) {
				var operand1 = evalStack.pop();
				var operand2 = evalStack.pop();

				var result = PerformOperation(parseFloat(operand1), parseFloat(operand2), currentToken);
				evalStack.push(result);
			} else {
				if (isNaN(parseInt(currentToken))) {
					if (data[formulaInfo.itemPosition[currentToken]] == "#NuN#") return "#NuN#";
					evalStack.push(data[formulaInfo.itemPosition[currentToken]]);
				} else {
					evalStack.push(currentToken);
				}
			}
		}
		return evalStack.pop();
	}

	function PerformOperation(operand1, operand2, operator) {
		switch (operator) {
			case '+':
				return operand1 + operand2;
			case '-':
				return operand2 - operand1;
			case '*':
				return operand1 * operand2;
			case '/':
				return operand2 / operand1;
			default:
				return;
		}

	}

	function InfixToPostfix(expression) {
		//var tokens = expression.split(/([0-9]+|[*+-\/()])/);
		var tokens = expression.split(" ");
		var outputQueue = [];
		var operatorStack = [];

		while (tokens.length != 0) {
			var currentToken = tokens.shift();

			if (isOperator(currentToken)) {
				while ((getAssociativity(currentToken) == 'left' &&
					getPrecedence(currentToken) <= getPrecedence(operatorStack[operatorStack.length - 1])) ||
					(getAssociativity(currentToken) == 'right' &&
						getPrecedence(currentToken) < getPrecedence(operatorStack[operatorStack.length - 1]))) {
					outputQueue.push(operatorStack.pop())
				}

				operatorStack.push(currentToken);

			}
			else if (currentToken == '(') {
				operatorStack.push(currentToken);
			}
			else if (currentToken == ')') {
				while (operatorStack[operatorStack.length - 1] != '(') {
					if (operatorStack.length == 0)
						throw ("");

					outputQueue.push(operatorStack.pop());
				}
				operatorStack.pop();
			} else {
				outputQueue.push(currentToken);
			}
		}

		while (operatorStack.length != 0) {
			if (!operatorStack[operatorStack.length - 1].match(/([()])/))
				outputQueue.push(operatorStack.pop());
			else
				throw ("Parenthesis balancing error! Shame on you!");
		}

		return outputQueue.join(" ");
	}


	function isOperator(token) {
		if (!token.match(/([*+-\/])/))
			return false;
		else
			return true;
	}


	function isNumber(token) {
		if (!token.match(/([0-9]+)/))
			return false;
		else
			return true;
	}


	function getPrecedence(token) {
		switch (token) {
			case '^':
				return 9;
			case '*':
			case '/':
			case '%':
				return 8;
			case '+':
			case '-':
				return 6;
			default:
				return -1;
		}
	}

	function getAssociativity(token) {
		switch (token) {
			case '+':
			case '-':
			case '*':
			case '/':
				return 'left';
			case '^':
				return 'right';
		}
	}


	function OATSetCookie(name, value, expires, path, domain, secure) {
		document.cookie = name + "=" + escape(value) +
			((expires == null) ? "" : "; expires=" + expires.toGMTString()) +
			((path == null) ? "" : "; path=" + path) +
			((domain == null) ? "" : "; domain=" + domain) +
			((secure == null) ? "" : "; secure");
	}
	function OATGetCookie(name) {
		var cname = name + "=";
		var dc = document.cookie;
		if (dc.length > 0) {
			begin = dc.indexOf(cname);
			if (begin != -1) {
				begin += cname.length;
				end = dc.indexOf(";", begin);
				if (end == -1) end = dc.length;
				return unescape(dc.substring(begin, end));
			}
		}
		return null;
	}

	function OATIsNotEmptyValue(value) {
		return (value != "#NaV#") && (value != "#NuN#")
	}

	function OATGetRowsFromXML(data, obj, ShowMeasuresAsRows) {
		var rows = [];

		var rowsString = data.split("<Rows>")
		if (rowsString.length) {
			rowsString = rowsString[1].split("</Rows>")
			rowsString = rowsString[0].split("<Row>")
			var isTitle = 0;
			for (var l = 1; l < rowsString.length; l++) {
				var row = { headers: [], cells: [], subTotal: false, dataField: -1, rowSpan: 0 }

				var subTotal = parseToStringRegisterValue(rowsString[l], "Subtotal")
				if (subTotal == "true") {
					row.subTotal = true
				}
				var headerString
				if (rowsString[l].indexOf("</Header>") > 0) {
					headerString = rowsString[l].split("</Header>")[0].replace("<Header>", "")
				} else {
					headerString = rowsString[l].split("/>")[0].replace("<Header", "")
				}

				row.dataField = parseToStringRegisterValue(headerString, "DataField"); //for columns in rows only

				//get dataFields of headers
				var headerrep = headerString.replace(/<\//g, "-*-5").replace(/\/>/g, "-*-5")
				var headersItems = headerrep.split("-*-5");

				for (var df = 1; df < headersItems.length; df++) {
					var value;
					var datafield = headersItems[df].split(">")[0]
					if (datafield == "") {
						datafield = headersItems[df - 1].split("<")[1].split(" ")[0]
						value = "#NuN#";
					} else {
						try {
							value = headersItems[df - 1].split(datafield + ">")[1].split("<")[0]
						} catch (ERROR) {
							value = "#NuN#";
						}
					}

					var h = { dataField: datafield, value: value, rowSpan: 1 }


					var totalizedItems = headersItems.length - 1
					if (ShowMeasuresAsRows) {
						totalizedItems = headersItems.length
						if (row.subTotal) {
							totalizedItems--;
						}
					}
					var sumarized = (df - totalizedItems >= 0)

					if ((rows.length > 0) && (!sumarized)) { //set rowspan
						if ((df - 1 == 0) || (row.headers[df - 2].rowSpan == 0)) { //no es la 1er columna, pero la anterior tiene span
							if (value == rows[l - 2].headers[df - 1].value) {
								h.rowSpan = 0
								var ant = l - 2
								while (ant >= 0) {
									if (rows[ant].headers[df - 1].rowSpan > 0) {
										rows[ant].headers[df - 1].rowSpan++
										break;
									}
									ant--;
								}
							}
						}
					}


					row.headers.push(h);
				}

				if ((ShowMeasuresAsRows) && (row.subTotal)) {
					if ((l == 1) || (!rows[l - 2].subTotal) || (row.headers.length != rows[l - 2].headers.length)) {
						row.rowSpan = 1
					} else {
						var ant = l - 2;
						while (ant >= 0) {
							if (rows[ant].rowSpan > 0) {
								rows[ant].rowSpan++
								break;
							}
							ant--
						}
					}
				}
				//get cells values
				var cellsString = rowsString[l].split("<Cells>")[1].split("</Cell>")
				for (var ci = 0; ci < cellsString.length - 1; ci++) {

					var dField = (row.dataField != -1) ? row.dataField : obj.columnsHeaders[ci].dataField;
					//add empty cells
					for (var ec = 1; ec < cellsString[ci].split("<Cell />").length; ec++) {
						var c = { value: "#NuN#", dataField: dField }
						row.cells.push(c);
					}

					var value = cellsString[ci].split("<Cell>")[1]
					var c = { value: value, dataField: dField }
					row.cells.push(c);
				}

				rows.push(row);
			}

		}
		return rows;
	}

	function OATGetColumnsHeadersFromXML(dataString) {
		var columnsString = dataString.split("<Columns>")
		var columnsHeaders = [];
		if (columnsString.length > 1) {

			columnsString = columnsString[1].split("</Columns>")[0]
			var headerString = columnsString.split("<Header")

			for (var t = 1; t < headerString.length; t++) {
				var o = parseToStringRegisterValue(headerString[t], "DataField")
				var subTotal = parseToStringRegisterValue(headerString[t], "Subtotal")

				var subHeaders = [];
				var subHeadersString = headerString[t].replace("DataField=\"" + o + "\">", "").replace("DataField='" + o + "'>", "").replace("</Header>", "").replace(/IsNull="true" \/>/g, ">#NuN#<F>").replace(/IsNull='true' \/>/g, ">#NuN#<F>").replace(/IsNull="true"\/>/g, ">#NuN#<F>").split("<")
				if (subHeadersString.length > 1) { //hay dimensiones en las columnas
					for (var sh = 1; sh < subHeadersString.length - 1; sh++) {
						if (sh % 2 == 1) {
							var datafield = subHeadersString[sh].split(">")[0]
							var value = subHeadersString[sh].split(datafield + ">")[1]
							var h = { dataField: datafield, value: value, colSpan: 1 }
							subHeaders.push(h)
						}
					}
				}

				columnsHeaders.push({ dataField: o, subTotal: (subTotal == "true"), subHeaders: subHeaders })

			}

			//obj.columnsHeaders = columnsHeaders;
		}
		return columnsHeaders
	}

	function OATGetDataFromXMLForPivot(data, ShowMeasuresAsRows) {
		var stringRecord = dataString.split("<Record>")

		var obj = {};
		obj.ServerRecordCount = parseToIntRegisterValue(data, "RecordCount")
		obj.ServerPageCount = parseToIntRegisterValue(data, "PageCount")
		obj.ServerPageNumber = parseToIntRegisterValue(data, "PageNumber")

		obj.columnsHeaders = OATGetColumnsHeadersFromXML(data);
		obj.rows = OATGetRowsFromXML(data, obj, ShowMeasuresAsRows);


		return obj;
	}

	function OATGetNewDataFromXMLForPivot(data, obj, ShowMeasuresAsRows, exportTo) {
		data = data.replace(/<Cell\/>/g, "<Cell \/>")
		if ((exportTo == undefined) || (exportTo == "")) {
			if (parseToIntRegisterValue(data, "RecordCount") != -1) {
				obj.ServerRecordCount = parseToIntRegisterValue(data, "RecordCount")
			}
			if (parseToIntRegisterValue(data, "PageCount") != -1) {
				obj.ServerPageCount = parseToIntRegisterValue(data, "PageCount")
			}
		}
		obj.ServerPageNumber = parseToIntRegisterValue(data, "PageNumber")

		if (data.split("<Columns>").length > 1) {
			obj.columnsHeaders = OATGetColumnsHeadersFromXML(data);
		}

		obj.rows = OATGetRowsFromXML(data, obj, ShowMeasuresAsRows);

		return obj;
	}

	function OATgetDataFromXMLOldFormat(dataString, orderFilds, orderFildsHidden) {
		var stringRecord = dataString.split("<Record>")

		var data = [];
		var fullData = [];
		for (var i = 1; i < stringRecord.length; i++) {
			var recordData = [];
			var fullRecordData = [];
			for (var j = 0; j < orderFilds.length; j++) {
				recordData[j] = "#NuN#"
				var dt = stringRecord[i].split("<" + orderFilds[j] + ">")
				if (dt.length > 1) {
					var at = dt[1].split("</" + orderFilds[j] + ">")
					/*var rp = at[0].replace(/^\s+|\s+$/g, '')
					recordData[j] = (rp != "") ? rp : undefined*/
					recordData[j] = at[0]
					fullRecordData[j] = recordData[j]
				}
			}
			data.push(recordData);

			if (orderFildsHidden != undefined) {
				var pos_init = orderFilds.length;
				for (var j = 0; j < orderFildsHidden.length; j++) {
					fullRecordData[pos_init + j] = undefined
					var dt = stringRecord[i].split("<" + orderFildsHidden[j] + ">")
					if (dt.length > 1) {
						var at = dt[1].split("</" + orderFildsHidden[j] + ">")
						fullRecordData[pos_init + j] = at[0]
					}
				}
				fullData.push(fullRecordData);
			}
			/*	if (fullRecordData.length > this.maxLengthRecord) this.maxLengthRecord = fullRecordData.length;*/
		}

		if (orderFildsHidden != undefined) {
			return [data, fullData];
		} else {
			return data;
		}
	}

	function OATgetAllDataFromXMLOldFormat(dataString, orderFilds, orderFildsHidden) {
		var stringRecord = dataString.split("<Record>")

		var data = [];
		var fullData = [];
		for (var i = 1; i < stringRecord.length; i++) {
			var recordData = [];
			var fullRecordData = [];
			for (var j = 0; j < orderFilds.length; j++) {
				recordData[j] = "#NuN#"
				var dt = stringRecord[i].split("<" + orderFilds[j] + ">")
				if (dt.length > 1) {
					var at = dt[1].split("</" + orderFilds[j] + ">")
					/*var rp = at[0].replace(/^\s+|\s+$/g, '')
					recordData[j] = (rp != "") ? rp : undefined*/
					recordData[j] = at[0]
					fullRecordData[j] = recordData[j]
				}
			}
			data.push(recordData);

			var pos_init = orderFilds.length;
			for (var j = 0; j < orderFildsHidden.length; j++) {
				fullRecordData[pos_init + j] = undefined
				var dt = stringRecord[i].split("<" + orderFildsHidden[j] + ">")
				if (dt.length > 1) {
					var at = dt[1].split("</" + orderFildsHidden[j] + ">")
					fullRecordData[pos_init + j] = at[0]
				}
			}
			fullData.push(fullRecordData);
			//if (fullRecordData.length > this.maxLengthRecord) this.maxLengthRecord = fullRecordData.length; 
		}

		return [data, fullData];
	}

	OATParseMetadata = function (metadata, hideDimension, hideMeasures, serverPaging) {
		//Parsear string metadata para remover measures ocultas
		var orderFildsHidden = []; var hideDataFilds = []; var nameFildsHidden = [];

		var removeMeasures = []; //number of remove measures
		var headMetadata;
		if (metadata.indexOf('<OLAPDimension') != -1) {
			headMetadata = metadata.substring(0, metadata.indexOf('<OLAPDimension'));
		} else {
			headMetadata = metadata.substring(0, metadata.indexOf('<OLAPMeasure'));
		}
		var restMetadata = metadata.substring(metadata.indexOf('<OLAPDimension'), metadata.length);

		var dimensionString = restMetadata.split("<OLAPDimension");
		for (var i = 1; i < dimensionString.length; i++) {
			if (dimensionString[i].length > 0) {
				if (dimensionString[i].indexOf('</OLAPDimension>') != -1) {
					dimensionString[i] = dimensionString[i].substring(0, dimensionString[i].indexOf('</OLAPDimension>'));
				} else {
					dimensionString[i] = dimensionString[i].substring(0, dimensionString[i].indexOf('/>')) + ">";
				}

				var hide = false
				if ((hideDimension != undefined) && (hideDimension.length > 0)) {
					var dataField = dimensionString[i].split("dataField=\"")[1].split("\"")[0]
					hide = (hideDimension.indexOf(dataField) != -1)
				}
				//if (serverPaging) hide = false;

				if (((dimensionString[i].indexOf("defaultPosition=\"hidden\"") != -1) && (hideDimension == undefined)) ||
					(hide && (hideDimension != undefined))) {//hide dimension
					try {
						if (dimensionString[i].indexOf("displayName=") != -1) {
							var infoDisplayName = dimensionString[i].substring(dimensionString[i].indexOf("displayName=") + 13)
							orderFildsHidden.push(infoDisplayName.split('"')[0])
							hideDataFilds.push(dimensionString[i].substring(dimensionString[i].indexOf("dataField=") + 11).split('"')[0])
							try {
								nameFildsHidden.push(dimensionString[i].substring(dimensionString[i].indexOf("name=") + 6).split('"')[0])
							} catch (ERROR) {
							}
						}
					} catch (ERROR) { }
					dimensionString[i] = "";
				} else {
					dimensionString[i] = "<OLAPDimension " + dimensionString[i] + "</OLAPDimension>"
				}
			} else {
				dimensionString[i] = "";
			}
		}

		var measuresString = restMetadata.split("<OLAPMeasure");
		var allHide = true;
		for (var i = 1; i < measuresString.length; i++) {

			var hide = false
			if ((hideMeasures != undefined) && (hideMeasures.length > 0)) {
				var dataField = measuresString[i].split("dataField=\"")[1].split("\"")[0]
				hide = (hideMeasures.indexOf(dataField) != -1)
			}
			//if (serverPaging) hide = false;

			if (!hide) {
				if (measuresString[i].indexOf("</OLAPMeasure") != -1) {
					measuresString[i] = "<OLAPMeasure " + measuresString[i].substring(0, measuresString[i].indexOf('</OLAPMeasure>')) + "</OLAPMeasure>"
				} else if (measuresString[i].indexOf("/>") != -1) {
					measuresString[i] = "<OLAPMeasure " + measuresString[i].substring(0, measuresString[i].indexOf('/>')) + "/>";
				} else {
					measuresString[i] = "";
				}
				allHide = false;
			} else {
				measuresString[i] = "";
			}
		}
		if ((serverPaging) && (allHide)) {
			measuresString.push('<OLAPMeasure name="Quantity" displayName="' + gx.getMessage("GXPL_QViewerQuantity") + '" description="' + gx.getMessage("GXPL_QViewerQuantity") + '" dataField="F0" aggregation="count" summarize="yes" align="right" picture="" targetValue="0" defaultPosition="data" validPositions="data" dataType="integer" format="borderThickness:1"> </OLAPMeasure>');
		}

		var taileMetadata = "</OLAPCube>";

		metadata = "";
		metadata = headMetadata;
		for (var i = 1; i < dimensionString.length; i++) {
			if (dimensionString[i].length > 0) {
				metadata = metadata + dimensionString[i];
			}
		}
		for (var i = 1; i < measuresString.length; i++) {
			if (measuresString[i].length > 0) {
				metadata = metadata + measuresString[i]
			}
		}
		metadata = metadata + taileMetadata;
		//end parsing metadata
		return [metadata, orderFildsHidden, hideDataFilds, nameFildsHidden]
	}


	OATGetColumnsAndMeasureMeatadata = function (columns, measures, formulaInfo, OrderFildsHidden) {
		var preHeader = []; var columnNames = []; var rowNames = []; var filterNames = [];
		var formatValues = []; var conditionalFormatsColumns = []; var formatValuesMeasures = []; var conditionalFormats = [];
		var orderFilds = []; var j = 0; var k = 0; var columnsDataType = []; var measureNames = [];
		var forPivotCustomPicture = []; var forPivotCustomFormat = [];
		//get columns
		for (var i = 0; i < columns.length; i++) {

			if ((columns[i].attributes.getNamedItem("defaultPosition").nodeValue == "rows") ||
				(columns[i].attributes.getNamedItem("defaultPosition").nodeValue == "hidden")) {
				columnNames[j] = columns[i].attributes.getNamedItem("displayName").nodeValue;
				preHeader[i] = columnNames[j];
				j++;
			}
			if (columns[i].attributes.getNamedItem("defaultPosition").nodeValue == "columns") {
				rowNames[k] = columns[i].attributes.getNamedItem("displayName").nodeValue;
				preHeader[i] = rowNames[k];
				k++;
			}
			if (columns[i].attributes.getNamedItem("defaultPosition").nodeValue == "filters") {
				filterNames[k] = columns[i].attributes.getNamedItem("displayName").nodeValue;
				preHeader[i] = filterNames[k];
				k++;
			}

			columnsDataType[i] = columns[i].attributes.getNamedItem("dataType").nodeValue;
			//handle formats values
			if (columns[i].childNodes.length > 0) {
				if (columns[i].childNodes != null) {
					for (var m = 0; m < columns[i].childNodes.length; m++) {
						if (columns[i].childNodes[m].localName == "formatValues") {
							for (var n = 0; n < columns[i].childNodes[m].childNodes.length; n++) {
								if (columns[i].childNodes[m].childNodes[n].localName == "value") {
									var value = {};
									value.format = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("format").nodeValue;
									value.recursive = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("recursive").nodeValue;
									var crude = columns[i].childNodes[m].childNodes[n].textContent;
									value.value = crude.replace(/^\s+|\s+$/g, '');
									value.columnNumber = i;
									formatValues.push(value);
								}
							}
						}
					}
				}
			}//handle conditional formats
			if (columns[i].childNodes.length > 0) {
				if (columns[i].childNodes != null) {
					for (var m = 0; m < columns[i].childNodes.length; m++) {
						if (columns[i].childNodes[m].localName == "conditionalFormats") {
							for (var n = 0; n < columns[i].childNodes[m].childNodes.length; n++) {
								if (columns[i].childNodes[m].childNodes[n].localName == "rule") {
									var format = {};
									format.format = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("format").nodeValue;
									format.operation1 = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("op1").nodeValue;
									format.value1 = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("value1").nodeValue;
									if (columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("op2") != null) {
										format.operation2 = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("op2").nodeValue;
										format.value2 = columns[i].childNodes[m].childNodes[n].attributes.getNamedItem("value2").nodeValue;
									}
									format.columnNumber = i;
									conditionalFormatsColumns.push(format);
								}
							}
						}

					}
				}
			}

			//manage pictures
			/*if (columns[i].attributes.getNamedItem("picture").nodeValue != "") {
				if (columns[i].attributes.getNamedItem("dataType").nodeValue == "date") {
					datePictures.push(columns[i].attributes.getNamedItem("picture").nodeValue);
					dateFields.push(columns[i].attributes.getNamedItem("dataField").nodeValue);
				}
				//if (columns[i].attributes.getNamedItem("dataType").nodeValue == "integer" || measures[i].attributes.getNamedItem("dataType").nodeValue == "real") {
				if (columns[i].attributes.getNamedItem("dataType").nodeValue == "integer") {
					intPictures.push(columns[i].attributes.getNamedItem("picture").nodeValue);
					intFields.push(columns[i].attributes.getNamedItem("dataField").nodeValue);
				}
				
			}*/
			forPivotCustomPicture.push(columns[i].attributes.getNamedItem("picture").nodeValue);
			forPivotCustomFormat.push(columns[i].attributes.getNamedItem("format").nodeValue);
			orderFilds.push(columns[i].attributes.getNamedItem("dataField").nodeValue);

		}

		//var measures;
		var measureFormula = [];
		for (var i = 0; i < measures.length; i++) {

			measureNames[i] = measures[i].attributes.getNamedItem("displayName").nodeValue;
			//manage format values
			if (measures[i].childNodes.length > 0) {
				if (measures[i].childNodes != null) {
					for (var m = 0; m < measures[i].childNodes.length; m++) {
						if (measures[i].childNodes[m].localName == "formatValues") {
							for (var n = 0; n < measures[i].childNodes[m].childNodes.length; n++) {
								if (measures[i].childNodes[m].childNodes[n].localName == "value") {
									var value = {};
									value.format = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("format").nodeValue;
									value.recursive = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("recursive").nodeValue;
									var crude = measures[i].childNodes[m].childNodes[n].textContent;
									value.value = crude.replace(/^\s+|\s+$/g, '');
									value.columnNumber = i;
									formatValuesMeasures.push(value);
								}
							}
						}

					}
				}
			}
			//manage conditional formats
			if (measures[i].childNodes.length > 0) {
				if (measures[i].childNodes != null) {
					for (var m = 0; m < measures[i].childNodes.length; m++) {
						if (measures[i].childNodes[m].localName == "conditionalFormats") {
							for (var n = 0; n < measures[i].childNodes[m].childNodes.length; n++) {
								if (measures[i].childNodes[m].childNodes[n].localName == "rule") {
									var format = {};
									format.format = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("format").nodeValue;
									format.operation1 = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("op1").nodeValue;
									format.value1 = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("value1").nodeValue;
									if (measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("op2") != null) {
										format.operation2 = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("op2").nodeValue;
										format.value2 = measures[i].childNodes[m].childNodes[n].attributes.getNamedItem("value2").nodeValue;
									}
									format.columnNumber = i; //+ columns.length; Only the measure number
									conditionalFormats.push(format);
								}
							}
						}
					}
				}
			}

			//manage pictures
			/*if (measures[i].attributes.getNamedItem("picture").nodeValue != "") {
				if (measures[i].attributes.getNamedItem("dataType").nodeValue == "date") {
					datePictures.push(measures[i].attributes.getNamedItem("picture").nodeValue);
					dateFields.push(measures[i].attributes.getNamedItem("dataField").nodeValue);
				}
				if (measures[i].attributes.getNamedItem("dataType").nodeValue == "integer" || measures[i].attributes.getNamedItem("dataType").nodeValue == "real") {
					intPictures.push(measures[i].attributes.getNamedItem("picture").nodeValue);
					intFields.push(measures[i].attributes.getNamedItem("dataField").nodeValue);
				}
			}*/

			//manage formula
			if ((measures[i].attributes.getNamedItem("formula") != undefined) && (measures[i].attributes.getNamedItem("formula").nodeValue != "")) {
				measureFormula.push({ hasFormula: true, textFormula: measures[i].attributes.getNamedItem("formula").nodeValue })
			} else {
				measureFormula.push({ hasFormula: false })
			}

			forPivotCustomPicture.push(measures[i].attributes.getNamedItem("picture").nodeValue);
			orderFilds.push(measures[i].attributes.getNamedItem("dataField").nodeValue);
		}


		var furmulaIndex = {}
		for (var j = 0; j < OrderFildsHidden.length; j++) {
			furmulaIndex[OrderFildsHidden[j]] = orderFilds.length + j
		}
		formulaInfo.itemPosition = furmulaIndex
		//formulaInfo.recordDataLength = this.maxLengthRecord;
		formulaInfo.measureFormula = measureFormula
		formulaInfo.cantFormulaMeasures = 0;

		for (var n = 0; n < formulaInfo.measureFormula.length; n++) {
			if (formulaInfo.measureFormula[n].hasFormula) {
				formulaInfo.cantFormulaMeasures++;

				var inlineFormula = formulaInfo.measureFormula[n].textFormula

				var inline = inlineFormula
				var opers = ['*', '-', '+', '/', '(', ')']
				for (var j = 0; j < opers.length; j++) {
					var inline2 = inline.split(opers[j])
					if (inline2.length > 1) {
						inline = ""
						for (var i = 0; i < inline2.length - 1; i++) {
							inline = inline + inline2[i] + " " + opers[j] + " "
						}
						inline = inline + inline2[inline2.length - 1]
					}
				}

				var polishNot = InfixToPostfix(inline)
				formulaInfo.measureFormula[n].polishNotationText = polishNot
				var items = polishNot.split(" ")
				while (items.indexOf("") != -1) {
					items.splice(items.indexOf(""), 1)
				}
				var relatedMeasure = []
				for (var k = 0; k < items.length; k++) {
					if ((opers.indexOf(items[k]) == -1) && (isNaN(parseInt(items[k])))) {
						//add item
						var operPositionInDataRow = formulaInfo.itemPosition[items[k]]
						if (relatedMeasure.indexOf(operPositionInDataRow) == -1)
							relatedMeasure.push(operPositionInDataRow)
					}
				}

				formulaInfo.measureFormula[n].relatedMeasures = relatedMeasure

				var arrayNot = polishNot.split(" ")
				while (arrayNot.indexOf("") != -1) {
					arrayNot.splice(arrayNot.indexOf(""), 1)
				}
				formulaInfo.measureFormula[n].PolishNotation = arrayNot
			}
		}

		return [preHeader.concat(measureNames), orderFilds, measureFormula, conditionalFormats, conditionalFormatsColumns, forPivotCustomPicture, forPivotCustomFormat];
	}


	OATgetState = function (query, controlName) {
		if (typeof JSON.retrocycle !== 'function') {
			JSON.retrocycle = function retrocycle($) {
				'use strict';

				var px =
					/^\$(?:\[(?:\d+|\"(?:[^\\\"\u0000-\u001f]|\\([\\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*\")\])*$/;
				(function rez(value) {
					var i, item, name, path;
					if (value && typeof value === 'object') {
						if (Object.prototype.toString.apply(value) === '[object Array]') {
							for (i = 0; i < value.length; i += 1) {
								item = value[i];
								if (item && typeof item === 'object') {
									path = item.$ref;
									if (typeof path === 'string' && px.test(path)) {
										value[i] = eval(path);
									} else {
										rez(item);
									}
								}
							}
						} else {
							for (name in value) {
								if (typeof value[name] === 'object') {
									item = value[name];
									if (item) {
										path = item.$ref;
										if (typeof path === 'string' && px.test(path)) {
											value[name] = eval(path);
										} else {
											rez(item);
										}
									}
								}
							}
						}
					}
				}($));
				return $;
			};
		}
		try {
			var i;
			if (localStorage.getItem(OAT.getURL() + query + controlName + "HiddenState") != null) {
				var retrievedObject = localStorage.getItem(OAT.getURL() + query + controlName + "HiddenState");
				i = JSON.retrocycle(JSON.parse(retrievedObject));
			}

			if (i == null) {
				var cookieValue = OATGetCookie('"' + OAT.getURL() + query + controlName + "HiddenState" + 'cookie' + '"')
				if (cookieValue != null) {
					i = JSON.parse(cookieValue)
				}
			}

			return i;
		} catch (error) {
			try {
				var cookieValue = OATGetCookie('"' + OAT.getURL() + query + controlName + "HiddenState" + 'cookie' + '"')
				var i = JSON.parse(cookieValue)
				return i
			} catch (error) {
				return null;
			}
		}
	}


	function init() {

	}

}
/* END OF FILE - ..\oatPivot\oat_impl.src.js - */
/* START OF FILE - ..\oatPivot\oat_layers.src.js - */
if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {
	//FILE OAT.Layers
	OAT.Layers = function (f) {
		var a = this;
		this.baseOffset = f;
		this.layers = [];
		this.currentIndex = 0;
		this.raise = function (b) {
			if (-1 != a.layers.findIndex(b)) {
				for (var d = b.style.zIndex, c = 0; c < a.layers.length; c++) {
					var e = a.layers[c];
					e.style.zIndex > d && e.style.zIndex--
				}
				b.style.zIndex = a.currentIndex
			}
		};
		this.addLayer = function (b, d) {
			var c = OAT.$(b);
			c && (a.currentIndex++ , c.style.zIndex = a.currentIndex, a.layers.push(c), OAT.Dom.attach(c, d ? d : "mousedown", function () {
				a.raise(c)
			}))
		};
		this.removeLayer = function (b) {
			b = OAT.$(b);
			b = a.layers.findIndex(b);
			-1 != b && a.layers.splice(b, 1)
		};
		a.currentIndex = a.baseOffset
	};




	/*!
	 * jQuery blockUI plugin
	 * Version 2.70.0-2014.11.23
	 * Requires jQuery v1.7 or later
	 *
	 * Examples at: http://malsup.com/jquery/block/
	 * Copyright (c) 2007-2013 M. Alsup
	 * Dual licensed under the MIT and GPL licenses:
	 * http://www.opensource.org/licenses/mit-license.php
	 * http://www.gnu.org/licenses/gpl.html
	 *
	 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
	 */

	; (function () {
		/*jshint eqeqeq:false curly:false latedef:false */
		"use strict";

		function setup($) {
			$.fn._fadeIn = $.fn.fadeIn;

			var noOp = $.noop || function () { };

			// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
			// confusing userAgent strings on Vista)
			var msie = /MSIE/.test(navigator.userAgent);
			var ie6 = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);
			var mode = document.documentMode || 0;
			var setExpr = $.isFunction(document.createElement('div').style.setExpression);

			// global $ methods for blocking/unblocking the entire page
			$.blockUI = function (opts) { install(window, opts); };
			$.unblockUI = function (opts) { remove(window, opts); };

			// convenience method for quick growl-like notifications  (http://www.google.com/search?q=growl)
			$.growlUI = function (title, message, timeout, onClose) {
				var $m = $('<div class="growlUI"></div>');
				if (title) $m.append('<h1>' + title + '</h1>');
				if (message) $m.append('<h2>' + message + '</h2>');
				if (timeout === undefined) timeout = 3000;

				// Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications
				var callBlock = function (opts) {
					opts = opts || {};

					$.blockUI({
						message: $m,
						fadeIn: typeof opts.fadeIn !== 'undefined' ? opts.fadeIn : 700,
						fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000,
						timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout,
						centerY: false,
						showOverlay: false,
						onUnblock: onClose,
						css: $.blockUI.defaults.growlCSS
					});
				};

				callBlock();
				var nonmousedOpacity = $m.css('opacity');
				$m.mouseover(function () {
					callBlock({
						fadeIn: 0,
						timeout: 30000
					});

					var displayBlock = $('.blockMsg');
					displayBlock.stop(); // cancel fadeout if it has started
					displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency
				}).mouseout(function () {
					$('.blockMsg').fadeOut(1000);
				});
				// End konapun additions
			};

			// plugin method for blocking element content
			$.fn.block = function (opts) {
				if (this[0] === window) {
					$.blockUI(opts);
					return this;
				}
				var fullOpts = $.extend({}, $.blockUI.defaults, opts || {});
				this.each(function () {
					var $el = $(this);
					if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))
						return;
					$el.unblock({ fadeOut: 0 });
				});

				return this.each(function () {
					if ($.css(this, 'position') == 'static') {
						this.style.position = 'relative';
						$(this).data('blockUI.static', true);
					}
					this.style.zoom = 1; // force 'hasLayout' in ie
					install(this, opts);
				});
			};

			// plugin method for unblocking element content
			$.fn.unblock = function (opts) {
				if (this[0] === window) {
					$.unblockUI(opts);
					return this;
				}
				return this.each(function () {
					remove(this, opts);
				});
			};

			$.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!

			// override these in your code to change the default behavior and style
			$.blockUI.defaults = {
				// message displayed when blocking (use null for no message)
				message: '<h1>Please wait...</h1>',

				title: null,		// title string; only used when theme == true
				draggable: true,	// only used when theme == true (requires jquery-ui.js to be loaded)

				theme: false, // set to true to use with jQuery UI themes

				// styles for the message when blocking; if you wish to disable
				// these and use an external stylesheet then do this in your code:
				// $.blockUI.defaults.css = {};
				css: {
					padding: 0,
					margin: 0,
					width: '30%',
					top: '40%',
					left: '35%',
					textAlign: 'center',
					color: '#000',
					border: '3px solid #aaa',
					backgroundColor: '#fff',
					cursor: 'wait'
				},

				// minimal style set used when themes are used
				themedCSS: {
					width: '30%',
					top: '40%',
					left: '35%'
				},

				// styles for the overlay
				overlayCSS: {
					backgroundColor: '#000',
					opacity: 0.1,
					cursor: 'wait'
				},

				// style to replace wait cursor before unblocking to correct issue
				// of lingering wait cursor
				cursorReset: 'default',

				// styles applied when using $.growlUI
				growlCSS: {
					width: '350px',
					top: '10px',
					left: '',
					right: '10px',
					border: 'none',
					padding: '5px',
					opacity: 0.6,
					cursor: 'default',
					color: '#fff',
					backgroundColor: '#000',
					'-webkit-border-radius': '10px',
					'-moz-border-radius': '10px',
					'border-radius': '10px'
				},

				// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
				// (hat tip to Jorge H. N. de Vasconcelos)
				/*jshint scripturl:true */
				iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',

				// force usage of iframe in non-IE browsers (handy for blocking applets)
				forceIframe: false,

				// z-index for the blocking overlay
				baseZ: 1000,

				// set these to true to have the message automatically centered
				centerX: true, // <-- only effects element blocking (page block controlled via css above)
				centerY: true,

				// allow body element to be stetched in ie6; this makes blocking look better
				// on "short" pages.  disable if you wish to prevent changes to the body height
				allowBodyStretch: true,

				// enable if you want key and mouse events to be disabled for content that is blocked
				bindEvents: true,

				// be default blockUI will supress tab navigation from leaving blocking content
				// (if bindEvents is true)
				constrainTabKey: true,

				// fadeIn time in millis; set to 0 to disable fadeIn on block
				fadeIn: 200,

				// fadeOut time in millis; set to 0 to disable fadeOut on unblock
				fadeOut: 400,

				// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
				timeout: 0,

				// disable if you don't want to show the overlay
				showOverlay: true,

				// if true, focus will be placed in the first available input field when
				// page blocking
				focusInput: true,

				// elements that can receive focus
				focusableElements: ':input:enabled:visible',

				// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
				// no longer needed in 2012
				// applyPlatformOpacityRules: true,

				// callback method invoked when fadeIn has completed and blocking message is visible
				onBlock: null,

				// callback method invoked when unblocking has completed; the callback is
				// passed the element that has been unblocked (which is the window object for page
				// blocks) and the options that were passed to the unblock call:
				//	onUnblock(element, options)
				onUnblock: null,

				// callback method invoked when the overlay area is clicked.
				// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
				onOverlayClick: null,

				// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
				quirksmodeOffsetHack: 4,

				// class name of the message block
				blockMsgClass: 'blockMsg',

				// if it is already blocked, then ignore it (don't unblock and reblock)
				ignoreIfBlocked: false
			};

			// private data and functions follow...

			var pageBlock = null;
			var pageBlockEls = [];

			function install(el, opts) {
				var css, themedCSS;
				var full = (el == window);
				var msg = (opts && opts.message !== undefined ? opts.message : undefined);
				opts = $.extend({}, $.blockUI.defaults, opts || {});

				if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))
					return;

				opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
				css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
				if (opts.onOverlayClick)
					opts.overlayCSS.cursor = 'pointer';

				themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
				msg = msg === undefined ? opts.message : msg;

				// remove the current block (if there is one)
				if (full && pageBlock)
					remove(window, { fadeOut: 0 });

				// if an existing element is being used as the blocking content then we capture
				// its current place in the DOM (and current display style) so we can restore
				// it when we unblock
				if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
					var node = msg.jquery ? msg[0] : msg;
					var data = {};
					$(el).data('blockUI.history', data);
					data.el = node;
					data.parent = node.parentNode;
					data.display = node.style.display;
					data.position = node.style.position;
					if (data.parent)
						data.parent.removeChild(node);
				}

				$(el).data('blockUI.onUnblock', opts.onUnblock);
				var z = opts.baseZ;

				// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
				// layer1 is the iframe layer which is used to supress bleed through of underlying content
				// layer2 is the overlay layer which has opacity and a wait cursor (by default)
				// layer3 is the message content that is displayed while blocking
				var lyr1, lyr2, lyr3, s;
				if (msie || opts.forceIframe)
					lyr1 = $('<iframe class="blockUI" style="z-index:' + (z++) + ';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="' + opts.iframeSrc + '"></iframe>');
				else
					lyr1 = $('<div class="blockUI" style="display:none"></div>');

				if (opts.theme)
					lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:' + (z++) + ';display:none"></div>');
				else
					lyr2 = $('<div class="blockUI blockOverlay" style="z-index:' + (z++) + ';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');

				if (opts.theme && full) {
					s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:' + (z + 10) + ';display:none;position:fixed">';
					if (opts.title) {
						s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">' + (opts.title || '&nbsp;') + '</div>';
					}
					s += '<div class="ui-widget-content ui-dialog-content"></div>';
					s += '</div>';
				}
				else if (opts.theme) {
					s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:' + (z + 10) + ';display:none;position:absolute">';
					if (opts.title) {
						s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">' + (opts.title || '&nbsp;') + '</div>';
					}
					s += '<div class="ui-widget-content ui-dialog-content"></div>';
					s += '</div>';
				}
				else if (full) {
					s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:' + (z + 10) + ';display:none;position:fixed"></div>';
				}
				else {
					s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:' + (z + 10) + ';display:none;position:absolute"></div>';
				}
				lyr3 = $(s);

				// if we have a message, style it
				if (msg) {
					if (opts.theme) {
						lyr3.css(themedCSS);
						lyr3.addClass('ui-widget-content');
					}
					else
						lyr3.css(css);
				}

				// style the overlay
				if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)
					lyr2.css(opts.overlayCSS);
				lyr2.css('position', full ? 'fixed' : 'absolute');

				// make iframe layer transparent in IE
				if (msie || opts.forceIframe)
					lyr1.css('opacity', 0.0);

				//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
				var layers = [lyr1, lyr2, lyr3], $par = full ? $('body') : $(el);
				$.each(layers, function () {
					this.appendTo($par);
				});

				if (opts.theme && opts.draggable && $.fn.draggable) {
					lyr3.draggable({
						handle: '.ui-dialog-titlebar',
						cancel: 'li'
					});
				}

				// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
				var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);
				if (ie6 || expr) {
					// give body 100% height
					if (full && opts.allowBodyStretch && $.support.boxModel)
						$('html,body').css('height', '100%');

					// fix ie6 issue when blocked element has a border width
					if ((ie6 || !$.support.boxModel) && !full) {
						var t = sz(el, 'borderTopWidth'), l = sz(el, 'borderLeftWidth');
						var fixT = t ? '(0 - ' + t + ')' : 0;
						var fixL = l ? '(0 - ' + l + ')' : 0;
					}

					// simulate fixed position
					$.each(layers, function (i, o) {
						var s = o[0].style;
						s.position = 'absolute';
						if (i < 2) {
							if (full)
								s.setExpression('height', 'Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:' + opts.quirksmodeOffsetHack + ') + "px"');
							else
								s.setExpression('height', 'this.parentNode.offsetHeight + "px"');
							if (full)
								s.setExpression('width', 'jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
							else
								s.setExpression('width', 'this.parentNode.offsetWidth + "px"');
							if (fixL) s.setExpression('left', fixL);
							if (fixT) s.setExpression('top', fixT);
						}
						else if (opts.centerY) {
							if (full) s.setExpression('top', '(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
							s.marginTop = 0;
						}
						else if (!opts.centerY && full) {
							var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;
							var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + ' + top + ') + "px"';
							s.setExpression('top', expression);
						}
					});
				}

				// show the message
				if (msg) {
					if (opts.theme)
						lyr3.find('.ui-widget-content').append(msg);
					else
						lyr3.append(msg);
					if (msg.jquery || msg.nodeType)
						$(msg).show();
				}

				if ((msie || opts.forceIframe) && opts.showOverlay)
					lyr1.show(); // opacity is zero
				if (opts.fadeIn) {
					var cb = opts.onBlock ? opts.onBlock : noOp;
					var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
					var cb2 = msg ? cb : noOp;
					if (opts.showOverlay)
						lyr2._fadeIn(opts.fadeIn, cb1);
					if (msg)
						lyr3._fadeIn(opts.fadeIn, cb2);
				}
				else {
					if (opts.showOverlay)
						lyr2.show();
					if (msg)
						lyr3.show();
					if (opts.onBlock)
						opts.onBlock.bind(lyr3)();
				}

				// bind key and mouse events
				bind(1, el, opts);

				if (full) {
					pageBlock = lyr3[0];
					pageBlockEls = $(opts.focusableElements, pageBlock);
					if (opts.focusInput)
						setTimeout(focus, 20);
				}
				else
					center(lyr3[0], opts.centerX, opts.centerY);

				if (opts.timeout) {
					// auto-unblock
					var to = setTimeout(function () {
						if (full)
							$.unblockUI(opts);
						else
							$(el).unblock(opts);
					}, opts.timeout);
					$(el).data('blockUI.timeout', to);
				}
			}

			// remove the block
			function remove(el, opts) {
				var count;
				var full = (el == window);
				var $el = $(el);
				var data = $el.data('blockUI.history');
				var to = $el.data('blockUI.timeout');
				if (to) {
					clearTimeout(to);
					$el.removeData('blockUI.timeout');
				}
				opts = $.extend({}, $.blockUI.defaults, opts || {});
				bind(0, el, opts); // unbind events

				if (opts.onUnblock === null) {
					opts.onUnblock = $el.data('blockUI.onUnblock');
					$el.removeData('blockUI.onUnblock');
				}

				var els;
				if (full) // crazy selector to handle odd field errors in ie6/7
					els = $('body').children().filter('.blockUI').add('body > .blockUI');
				else
					els = $el.find('>.blockUI');

				// fix cursor issue
				if (opts.cursorReset) {
					if (els.length > 1)
						els[1].style.cursor = opts.cursorReset;
					if (els.length > 2)
						els[2].style.cursor = opts.cursorReset;
				}

				if (full)
					pageBlock = pageBlockEls = null;

				if (opts.fadeOut) {
					count = els.length;
					els.stop().fadeOut(opts.fadeOut, function () {
						if (--count === 0)
							reset(els, data, opts, el);
					});
				}
				else
					reset(els, data, opts, el);
			}

			// move blocking element back into the DOM where it started
			function reset(els, data, opts, el) {
				var $el = $(el);
				if ($el.data('blockUI.isBlocked'))
					return;

				els.each(function (i, o) {
					// remove via DOM calls so we don't lose event handlers
					if (this.parentNode)
						this.parentNode.removeChild(this);
				});

				if (data && data.el) {
					data.el.style.display = data.display;
					data.el.style.position = data.position;
					data.el.style.cursor = 'default'; // #59
					if (data.parent)
						data.parent.appendChild(data.el);
					$el.removeData('blockUI.history');
				}

				if ($el.data('blockUI.static')) {
					$el.css('position', 'static'); // #22
				}

				if (typeof opts.onUnblock == 'function')
					opts.onUnblock(el, opts);

				// fix issue in Safari 6 where block artifacts remain until reflow
				var body = $(document.body), w = body.width(), cssW = body[0].style.width;
				body.width(w - 1).width(w);
				body[0].style.width = cssW;
			}

			// bind/unbind the handler
			function bind(b, el, opts) {
				var full = el == window, $el = $(el);

				// don't bother unbinding if there is nothing to unbind
				if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
					return;

				$el.data('blockUI.isBlocked', b);

				// don't bind events when overlay is not in use or if bindEvents is false
				if (!full || !opts.bindEvents || (b && !opts.showOverlay))
					return;

				// bind anchors and inputs for mouse and key events
				var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
				if (b)
					$(document).bind(events, opts, handler);
				else
					$(document).unbind(events, handler);

				// former impl...
				//		var $e = $('a,:input');
				//		b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
			}

			// event handler to suppress keyboard/mouse events when blocking
			function handler(e) {
				// allow tab navigation (conditionally)
				if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) {
					if (pageBlock && e.data.constrainTabKey) {
						var els = pageBlockEls;
						var fwd = !e.shiftKey && e.target === els[els.length - 1];
						var back = e.shiftKey && e.target === els[0];
						if (fwd || back) {
							setTimeout(function () { focus(back); }, 10);
							return false;
						}
					}
				}
				var opts = e.data;
				var target = $(e.target);
				if (target.hasClass('blockOverlay') && opts.onOverlayClick)
					opts.onOverlayClick(e);

				// allow events within the message content
				if (target.parents('div.' + opts.blockMsgClass).length > 0)
					return true;

				// allow events for content that is not being blocked
				return target.parents().children().filter('div.blockUI').length === 0;
			}

			function focus(back) {
				if (!pageBlockEls)
					return;
				var e = pageBlockEls[back === true ? pageBlockEls.length - 1 : 0];
				if (e)
					e.focus();
			}

			function center(el, x, y) {
				var p = el.parentNode, s = el.style;
				var l = ((p.offsetWidth - el.offsetWidth) / 2) - sz(p, 'borderLeftWidth');
				var t = ((p.offsetHeight - el.offsetHeight) / 2) - sz(p, 'borderTopWidth');
				if (x) s.left = l > 0 ? (l + 'px') : '0';
				if (y) s.top = t > 0 ? (t + 'px') : '0';
			}

			function sz(el, p) {
				return parseInt($.css(el, p), 10) || 0;
			}

		}


		/*global define:true */
		if (typeof define === 'function' && define.amd && define.amd.jQuery) {
			define(['jquery'], setup);
		} else {
			setup(jQuery);
		}

	})();








	try {
		OAT.Loader.featureLoaded("layers");
	} catch (ERROR) {

	}

}
/* END OF FILE - ..\oatPivot\oat_layers.src.js - */
/* START OF FILE - ..\oatPivot\oat_pivot.src.js - */
//FILE oat_pivot -----------------------------------------------------------------------------------------------------------------------------------------------

if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {

	if (GlobalPivotInterval == undefined) {
		var GlobalPivotInterval = [];
	}

	OAT.Pivot = function (div, filterDiv, headerRow, dataRows, headerRowIndexes,
		headerColIndexes, filterIndexes, dataColumnIndex, query,
		condFormats, control, pageSize, defaultPicture, QueryViewerCollection,
		columns, containerName, formatValue, conditionalFormatsColumns, formatValueMeasures,
		measures, autoResize, disableColumnSort, UcId, IdForQueryViewerCollection, rememberLayout,
		ShowMeasuresAsRows, formulaInfo, fullRecord, serverPagination, pageData, hideDataFilds,
		orderFildsHidden, initMetadata, relativePath, selection) {
		var self = this;
		this.autoPaging = false;
		this.nextRowWhenAutopaging = 0;
		this.prevRowWhenAutopaging = 0;
		this.paginationInfo = false;
		this.TempDataStructForAggStepOptimization = [];
		this.actualPaginationPage = 1;
		this.allDataWithoutSort = jQuery.extend(true, [], dataRows);
		this.IdForQueryViewerCollection = IdForQueryViewerCollection;
		this.UcId = UcId;
		this.ShowMeasuresAsRows = ShowMeasuresAsRows;
		this.rememberLayoutStateVersion = (serverPagination) ? "4.3.8SP" : "4.3.8";
		if (measures.length < 2) { //si solo tiene una medida no aplica esta propiedad
			this.ShowMeasuresAsRows = false
		}
		this.swfPath = gx.util.resourceUrl(relativePath + 'QueryViewer/oatPivot/downloadify/media/downloadify.swf')
		this.downloadImagePath = gx.util.resourceUrl(relativePath + 'QueryViewer/oatPivot/images/download_file.png'),
		this.allRowsPivot = "vacio";
		this.HideDataFilds = hideDataFilds;
		this.OrderFildsHidden = orderFildsHidden;
		this.initMetadata = initMetadata;
		this.relativePath = relativePath;
		this.selection = selection;

		this.Debugg = false;
		this.isSD = false;
		var ua = navigator.userAgent.toLowerCase();
		var isAndroid = ua.indexOf("android") > -1;
		if ((gx.util.browser.isIPad() || gx.util.browser.isIPhone() || isAndroid) || (this.Debugg)) {
			this.isSD = true
		}

		fromUndefinedToBlanck(dataRows);

		if (dataRows[0] != undefined) {

			//agregar indice de fila
			if (formulaInfo.cantFormulaMeasures > 0) {
				for (var i = 0; i < dataRows.length; i++) {
					dataRows[i][headerRow.length] = i;
				}
			}
			//end agregar indice a filas
			var sortIntMemory = [];

			//get sort value
			for (var index = headerRow.length - 1; index > -1; index--) { //*dataRows[0].length*/
				var sortInt = true;
				for (var ival = 0; ival < dataRows.length; ival++) {
					if ((sortInt) && (dataRows[ival][index] != parseInt(dataRows[ival][index]))) {
						sortInt = false;
						break;
					}
				}
				sortIntMemory[index] = sortInt;
			}
			var index = 0;
			if (sortIntMemory[index]) {
				dataRows = dataRows.sort((function (index) {
					return function (a, b) {
						return (parseInt(a[index]) === parseInt(b[index]) ? 0 : (parseInt(a[index]) < parseInt(b[index]) ? -1 : 1));
					};
				})(index));
			} else {
				dataRows = dataRows.sort((function (index) {
					return function (a, b) {
						return (a[index] === b[index] ? 0 : (a[index] < b[index] ? -1 : 1));
					};
				})(index));
			}

			var actualVal = dataRows[0][index];
			var initPos = 0;
			for (var i = 0; i < dataRows.length; i++) {
				if ((actualVal != dataRows[i][index])) {
					actualVal = dataRows[i][index]
					dataRows = OAT.PartialSort(dataRows, initPos, i - 1, index + 1, headerRow.length, sortIntMemory)
					initPos = i;
				} else if ((i == dataRows.length - 1)) {
					dataRows = OAT.PartialSort(dataRows, initPos, i, index + 1, headerRow.length, sortIntMemory)
				}
			}

		}
		//collapse repeate rows
		var tempDataRows = dataRows;
		dataRows = [];
		if (tempDataRows.length > 0) {
			dataRows[0] = tempDataRows[0]
		}
		var act_pos = 0;
		for (var i = 1; i < tempDataRows.length; i++) {
			var repeated = true;
			for (var j = 0; j < columns.length; j++) {
				if (tempDataRows[i][j] != tempDataRows[i - 1][j]) { repeated = false; break; }
			}
			if (repeated) {
				for (var j = columns.length; j < columns.length + measures.length; j++) {
					var tot = parseFloat(dataRows[act_pos][j]) + parseFloat(tempDataRows[i][j])
					if ((dataRows[act_pos][j] == "#NuN#") && (tempDataRows[i][j] == "#NuN#")) {
						tot = "#NuN#"
					} else if (dataRows[act_pos][j] == "#NuN#") {
						tot = tempDataRows[i][j] + ""
					} else if (tempDataRows[i][j] == "#NuN#") {
						tot = dataRows[act_pos][j] + ""
					}
					dataRows[act_pos][j] = tot + "";
				}
				//colapsar filas de formula
				if (formulaInfo.cantFormulaMeasures > 0) {
					var filaSumar = dataRows[act_pos][headerRow.length];
					var filaRepetida = tempDataRows[i][headerRow.length];
					for (var formulasI = 0; formulasI < formulaInfo.measureFormula.length; formulasI++) { //campos formulas
						if (formulaInfo.measureFormula[formulasI].hasFormula) {
							for (var formulasJ = 0; formulasJ < formulaInfo.measureFormula[formulasI].relatedMeasures.length; formulasJ++) {
								var pos = formulaInfo.measureFormula[formulasI].relatedMeasures[formulasJ];
								var tot = parseFloat(fullRecord[filaSumar][pos]) + parseFloat(fullRecord[filaRepetida][pos])
								fullRecord[filaSumar][pos] = tot + "";
							}
						}
					}
					for (var j = columns.length; j < columns.length + measures.length; j++) { //restantes medidas para mantener coherencia
						var tot = parseFloat(fullRecord[filaSumar][j]) + parseFloat(fullRecord[filaRepetida][j])
						fullRecord[filaSumar][j] = tot + "";
					}
					for (var posB = 0; posB < headerRow.length; posB++) { //anular fila ya sumada
						fullRecord[filaRepetida][posB] = "";
					}
				}
				//end colapsar formula info
			} else {
				act_pos++
				dataRows[act_pos] = tempDataRows[i];
			}
		}

		//eliminar indice de fila
		if (formulaInfo.cantFormulaMeasures > 0) {
			if (dataRows[0] != undefined) {
				for (var it = 0; it < dataRows.length; it++) {
					dataRows[it].splice(headerRow.length, 1)
				}
			}
		}
		//end borrar incide a filas
		this.serverPagination = serverPagination;
		this.pageData = pageData;
		if (this.serverPagination) {
			this.pageData.PreviousPageNumber = -1;
			this.pageData.AxisInfo = [];
			this.pageData.FilterInfo = [];
		}
		//determine where to use or not use auto-pagination
		if ((!this.serverPagination) && (pageSize != undefined) && ((columns.length > 1) || (measures.length > 0))) {
			if ((dataRows[0] != undefined) && ((dataRows[0].length - filterIndexes.length) < 4) && (dataRows.length > 4004)) {
				this.autoPaging = true;
			}
			if ((dataRows[0] != undefined) && ((dataRows[0].length - filterIndexes.length) == 4) && (dataRows.length > 2701)) {
				this.autoPaging = true;
			}
			if ((dataRows[0] != undefined) && ((dataRows[0].length - filterIndexes.length) == 5) && (dataRows.length > 2501)) {
				this.autoPaging = true;
			}
			if ((dataRows[0] != undefined) && ((dataRows[0].length - filterIndexes.length) == 6) && (dataRows.length > 1301)) {
				this.autoPaging = true;
			}
			if ((dataRows[0] != undefined) && ((dataRows[0].length - filterIndexes.length) == 7) && (dataRows.length > 601)) {
				this.autoPaging = true;
			}
			if ((dataRows[0] != undefined) && ((dataRows[0].length - filterIndexes.length) >= 8) && (dataRows.length >= 301)) {
				this.autoPaging = true;
			}
		}
		if ((filterIndexes.length > 1) && (columns.length - filterIndexes.length <= 2) && (headerColIndexes.length == 0)) {
			this.autoPaging = true;
		}
		if ((this.ShowMeasuresAsRows) || (this.serverPagination)) {
			this.autoPaging = false;
		}

		this.recordForFormula = fullRecord;
		this.formulaInfo = formulaInfo;
		this.filterIndexes = filterIndexes; /* indexes of column conditions */
		this.initFilterIndexes = [];
		for (var i = 0; i < this.filterIndexes.length; i++) {
			this.initFilterIndexes[i] = this.filterIndexes[i];
		}
		this.getFormulaRowByDataRow = function (row, measureNumber, caseId) {
			var value = ""
			var hallado = false
			var numRow = 0
			var searchIn = self.recordForFormula
			//if (self.filterIndexes.length > 0){ searchIn = self.filteredData }
			var addedValues = []; for (var o = 0; o < self.formulaInfo.recordDataLength; o++) { addedValues[o] = 0 }
			for (var i = 0; i < searchIn.length; i++) {
				var coincide = false
				for (var j = 0; j < row.length; j++) {
					if (self.filterIndexes.indexOf(j) != -1) { //case filter to top bar
						var pos = self.filterIndexes.indexOf(j)
						if (self.filterDiv != undefined) {
							var s = self.filterDiv.selects[pos]; /* select node */
							var val = OAT.$v(s)
							if (val == "[all]") { coincide = true } //case [all]
							else {
								coincide = (val == searchIn[i][j])
								if (!coincide) break;
							}
						} else {
							coincide = true;
						}
					} else if ((self.filterIndexes.length > 0) && (j >= row.length - measures.length)) { //case filter to top bar y measure item
						coincide = true;
					} else if ((searchIn[i][j] == row[j]) || ((row[j] == "#FoE#") && (searchIn[i][j] == 0))) {
						coincide = true;
					} else if ((headerRowIndexes != undefined) && (headerRowIndexes.indexOf(j) != -1)
						&& (headerRowIndexes.indexOf(j) > headerRowIndexes.length - measures.length)) { //if a measure, when rowConditions is not defined yet
						coincide = true;
					} else if ((dataColumnIndex > 0) && (dataColumnIndex == j)) {
						coincide = true;
					} else {
						if ((row[j] == undefined) && (self.filterIndexes.length > 0)) {
							coincide = true;
						} else {
							coincide = false;
							break;
						}
					}
				}
				if (coincide) {
					for (var t = 0; t < self.formulaInfo.measureFormula[measureNumber].relatedMeasures.length; t++) {
						var pos = self.formulaInfo.measureFormula[measureNumber].relatedMeasures[t]
						addedValues[pos] = addedValues[pos] + parseFloat(searchIn[i][pos]);
					}
					hallado = true

				}
			}
			if (hallado)
				return addedValues;
			else
				return "#NuN#"//self.EmptyValue; //"#NuN#"
		}


		//calculate single measure formula value
		for (var mforF = 0; mforF < measures.length; mforF++) {
			if (formulaInfo.measureFormula[mforF].hasFormula) {
				for (var rforF = 0; rforF < dataRows.length; rforF++) {
					if (dataRows[rforF][dataRows[rforF].length - measures.length + mforF] == 0) {
						var formula = this.getFormulaRowByDataRow(dataRows[rforF], mforF, "");
						var result = EvaluateExpressionPivotJs(formulaInfo.measureFormula[mforF].PolishNotation, formula, formulaInfo)
						if ((result == Infinity) || isNaN(result)) {
							dataRows[rforF][dataRows[rforF].length - measures.length + mforF] = "#FoE#";
						}
					}
				}
			}
		}

		this.GeneralDataRows = dataRows;
		this.autoPagingRowsPerPage = (pageSize != undefined) ? parseInt(pageSize) : 10;
		this.TotalPagesPaging = parseInt(dataRows.length / this.autoPagingRowsPerPage);
		if ((dataRows.length % this.autoPagingRowsPerPage) != 0) {
			this.TotalPagesPaging++;
		}
		this.GeneralDistinctValues = [];
		this.GrandTotalsPaging = [];
		this.columns = columns;
		if (dataRows.length > 0) {
			fillGeneralDistinctValues(headerRow.length - measures.length, self, dataRows);
		}
		if (this.autoPaging) {
			var tempDataRows = dataRows;
			dataRows = [];
			for (var i = 0; i < Math.min(tempDataRows.length, this.autoPagingRowsPerPage); i++) {
				dataRows.push([tempDataRows[i]]);
			}
		}
		this.RowsWhenMoveToFilter = []
		this.FilterByTopFilter = false
		this.options = {
			headingBefore: 1,
			headingAfter: 0,
			agg: 1, /* index of default statistic function, SUM */
			aggTotals: 1, /* dtto for subtotals & totals */
			customType: function (data) {
				return data;
			},
			//currencySymbol: "$",
			showEmpty: 0,
			subtotals: 1,
			totals: 1
		}


		this.firstTime = true;
		this.readState = false;
		this.deleteState = false;
		this.defaultPicture = defaultPicture;
		this.gd = new OAT.GhostDrag();
		this.div = OAT.$(div);
		this.filterDiv = OAT.$(filterDiv);
		this.defCArray = ["rgb(153,153,255)", "rgb(153,51,205)", "rgb(255,255,204)", "rgb(204,255,255)", "rgb(102,0,102)",
			"rgb(255,128,128)", "rgb(0,102,204)", "rgb(204,204,255)", "rgb(0,0,128)", "rgb(255,0,255)",
			"rgb(0,255,255)", "rgb(255,255,0)"];
		this.QueryViewerCollection = QueryViewerCollection;
		this.containerName = containerName;
		this.formatValues = formatValue;
		this.formatValuesMeasures = formatValueMeasures;
		this.tempBlackLists = []; this.tempCollapsedValues = []; this.oldSortValues = [];
		this.stateChanged = false;
		this.rowsPerPage = pageSize;



		this.headerRow = headerRow; /* store data */
		this.allData = dataRows; /* store data */
		this.filteredData = [];
		this.tabularData = []; /* result */

		this.dataColumnIndex = dataColumnIndex; /* store data */
		this.rowConditions = headerRowIndexes; /* indexes of row conditions */
		this.colConditions = headerColIndexes; /* indexes of column conditions */

		this.initRowConditions = [];
		for (var i = 0; i < this.rowConditions.length; i++) {
			this.initRowConditions[i] = this.rowConditions[i];
		}
		this.initColConditions = []
		for (var i = 0; i < this.colConditions.length; i++) {
			this.initColConditions[i] = this.colConditions[i];
		}

		if ((columns.length == 1) && (measures.length == 0)) {
			this.rowConditions = [0];
		}

		this.conditions = [];
		this.filterDiv.selects = [];
		this.rowStructure = {};
		this.colStructure = {};
		this.colPointers = [];
		this.rowPointers = [];
		this.rowTotals = [[], []];
		this.colTotals = [[], []];
		this.gTotal = [];

		this.query = query;
		this.controlName = control;
		this.conditionalFormats = condFormats;
		this.conditionalFormatsColumns = conditionalFormatsColumns;
		this.GreyList = [];
		this.EmptyValue = "#NaV#"
		this.NullValue = "#NuN#"

		this.initState = {};

		/* supplemental routines */
		if (typeof JSON.decycle !== 'function') {
			JSON.decycle = function decycle(object) {
				'use strict';
				var objects = [], // Keep a reference to each unique object or array
					paths = [];
				return (function derez(value, path) {
					var i, // The loop counter
						name, // Property name
						nu;
					switch (typeof value) {
						case 'object':
							if (!value) {
								return null;
							}
							for (i = 0; i < objects.length; i += 1) {
								if (objects[i] === value) {
									return {
										$ref: paths[i]
									};
								}
							}
							objects.push(value);
							paths.push(path);
							if (Object.prototype.toString.apply(value) === '[object Array]') {
								nu = [];
								for (i = 0; i < value.length; i += 1) {
									nu[i] = derez(value[i], path + '[' + i + ']');
								}
							} else {
								nu = {};
								for (name in value) {
									if (Object.prototype.hasOwnProperty.call(value, name)) {
										nu[name] = derez(value[name], path + '[' + JSON.stringify(name) + ']');
									}
								}
							}
							return nu;
						case 'number':
						case 'string':
						case 'boolean':
							return value;
					}
				}(object, '$'));
			};
		}


		this.saveState = function (state) {
			try {
				if (!!window.localStorage) {
					localStorage.removeItem(OAT.getURL() + self.query + self.controlName);
					localStorage.setItem(OAT.getURL() + self.query + self.controlName, JSON.stringify(JSON.decycle(state)));
				} else {
					OATSetCookie('"' + OAT.getURL() + self.query + self.controlName + 'cookie' + '"', JSON.stringify(state), null, "/");
				}
			} catch (error) {
				try {
					OATSetCookie('"' + OAT.getURL() + self.query + self.controlName + 'cookie' + '"', JSON.stringify(state), null, "/");
				} catch (error) { }
			}
		}

		this.saveHiddenState = function (state) {
			try {
				if (!!window.localStorage) {
					localStorage.removeItem(OAT.getURL() + self.query + self.controlName + "HiddenState");
					localStorage.setItem(OAT.getURL() + self.query + self.controlName + "HiddenState", JSON.stringify(JSON.decycle(state)));
				} else {
					OATSetCookie('"' + OAT.getURL() + self.query + self.controlName + "HiddenState" + 'cookie' + '"', JSON.stringify(state), null, "/");
				}
			} catch (error) {
				try {
					OATSetCookie('"' + OAT.getURL() + self.query + self.controlName + "HiddenState" + 'cookie' + '"', JSON.stringify(state), null, "/");
				} catch (error) { }
			}
		}

		this.getState = function () {
			if (typeof JSON.retrocycle !== 'function') {
				JSON.retrocycle = function retrocycle($) {
					'use strict';

					var px =
						/^\$(?:\[(?:\d+|\"(?:[^\\\"\u0000-\u001f]|\\([\\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*\")\])*$/;

					(function rez(value) {

						var i, item, name, path;

						if (value && typeof value === 'object') {
							if (Object.prototype.toString.apply(value) === '[object Array]') {
								for (i = 0; i < value.length; i += 1) {
									item = value[i];
									if (item && typeof item === 'object') {
										path = item.$ref;
										if (typeof path === 'string' && px.test(path)) {
											value[i] = eval(path);
										} else {
											rez(item);
										}
									}
								}
							} else {
								for (name in value) {
									if (typeof value[name] === 'object') {
										item = value[name];
										if (item) {
											path = item.$ref;
											if (typeof path === 'string' && px.test(path)) {
												value[name] = eval(path);
											} else {
												rez(item);
											}
										}
									}
								}
							}
						}
					}($));
					return $;
				};
			}
			try {
				var i;
				if (localStorage.getItem(OAT.getURL() + self.query + self.controlName) != null) {
					var retrievedObject = localStorage.getItem(OAT.getURL() + self.query + self.controlName);
					i = JSON.retrocycle(JSON.parse(retrievedObject));
				}

				if (i == null) {
					var cookieValue = OATGetCookie('"' + OAT.getURL() + self.query + self.controlName + 'cookie' + '"')
					if (cookieValue != null) {
						i = JSON.parse(cookieValue)
					}
				}

				return i;
			} catch (error) {
				try {
					var cookieValue = OATGetCookie('"' + OAT.getURL() + self.query + self.controlName + 'cookie' + '"')
					var i = JSON.parse(cookieValue)
					return i
				} catch (error) {
					return null;
				}
			}

		}

		this.cleanState = function () {

			for (var il = 0; il < self.filterDiv.selects.length; il++) {
				self.filterDiv.selects[il].value = "[all]"
			}
			for (var ci = 0; ci <= self.conditions.length - 1; ci++) {
				self.conditions[ci].blackList = [];
				self.conditions[ci].whiteList = [];
				self.conditions[ci].greyList = [];
			}
			localStorage.removeItem(OAT.getURL() + self.query + self.controlName);
			self.deleteState = false;

			var viejcolCond = new Array()
			for (var i = 0; i < self.initState.colConditions.length; i++) {
				viejcolCond[i] = self.initState.colConditions[i];
			}
			var viejcolRow = new Array();
			for (var i = 0; i < self.initState.rowConditions.length; i++) {
				viejcolRow[i] = self.initState.rowConditions[i];
			}
			var viejcolFilt = new Array();
			for (var i = 0; i < self.initState.filterIndexes.length; i++) {
				viejcolFilt[i] = self.initState.filterIndexes[i];
			}
			this.conditions = jQuery.extend(true, [], self.initState.conditions);
			this.rowConditions = viejcolRow;
			this.colConditions = viejcolCond;
			this.filterIndexes = viejcolFilt;
			this.stateChanged = self.initState.stateChanged;
			this.rowsPerPage = self.initState.rowsPerPage;

			var state = {
				query: self.query,
				conditions: self.conditions,
				colConditions: self.colConditions,
				rowConditions: self.rowConditions,
				filterIndexes: self.filterIndexes,
				filterDivSelects: [],
				rowsPerPage: self.rowsPerPage,
				version: self.rememberLayoutStateVersion
			};


			self.saveState(state);


		}

		this.cleanStateWhenServerPagination = function () {

			for (var il = 0; il < self.filterDiv.selects.length; il++) {
				self.filterDiv.selects[il].value = "[all]"
			}
			for (var ci = 0; ci <= self.conditions.length - 1; ci++) {
				self.conditions[ci].blackList = [];
			}
			//localStorage.removeItem(OAT.getURL()+self.query+self.controlName);
			//self.deleteState = false;

			var viejcolCond = new Array()
			for (var i = 0; i < self.initState.colConditions.length; i++) {
				viejcolCond[i] = self.initState.colConditions[i];
			}
			var viejcolRow = new Array();
			for (var i = 0; i < self.initState.rowConditions.length; i++) {
				viejcolRow[i] = self.initState.rowConditions[i];
			}
			var viejcolFilt = new Array();
			for (var i = 0; i < self.initState.filterIndexes.length; i++) {
				viejcolFilt[i] = self.initState.filterIndexes[i];
			}

			for (var i = 0; i < self.conditions.length; i++) {
				if ((self.conditions[i]) && (self.conditions[i].distinctValues) && (self.conditions[i].dataField)) {
					var initValuePos = -1;
					for (var t = 0; t < self.initState.conditions.length; t++) {
						if (self.initState.conditions[t]) {
							if (self.initState.conditions[t].dataField == self.conditions[i].dataField) {
								initValuePos = t;
							}
						}
					}

					if (initValuePos > -1) {
						self.initState.conditions[initValuePos].distinctValues = []
						for (var j = 0; j < self.conditions[i].distinctValues.length; j++) {
							if ((self.initState.conditions[initValuePos]) && (self.initState.conditions[initValuePos].distinctValues.indexOf(self.conditions[i].distinctValues[j]) == -1)) {
								self.initState.conditions[initValuePos].distinctValues.push(self.conditions[i].distinctValues[j])
							}
						}
						self.initState.conditions[initValuePos].previousPage = self.conditions[i].previousPage
						self.initState.conditions[initValuePos].totalPages = self.conditions[i].totalPages
					}
				}
			}

			self.conditions = jQuery.extend(true, [], self.initState.conditions);

			self.pageData.AxisInfo = jQuery.extend(true, [], self.initState.AxisInfo);
			self.pageData.DataInfo = jQuery.extend(true, [], self.initState.DataInfo);
			self.pageData.FilterInfo = jQuery.extend(true, [], self.initState.FilterInfo);
			self.pageData.CollapseInfo = jQuery.extend(true, [], self.initState.CollapseInfo);

			self.rowConditions = viejcolRow;
			self.colConditions = viejcolCond;
			self.filterIndexes = viejcolFilt;
			self.stateChanged = self.initState.stateChanged;
			self.rowsPerPage = self.initState.rowsPerPage;
			self.DefaultAction = self.initState.DefaultAction;

			self.initMetadata = jQuery.extend(true, {}, self.initState.InitMetadata);

			self.initMetadata.Conditions = []
			//self.initMetadata.Conditions = jQuery.extend(true, [] ,self.initState.conditions);
			for (var ip = 0; ip < self.initState.conditions.length; ip++) {
				var dF = self.initState.conditions[ip].dataField;
				var ix = self.initMetadata.DataFields.indexOf(dF);
				self.initMetadata.Conditions[ix] = self.conditions[ip];
			}

			if (!gx.util.browser.isIE()){
				self.goWhenHide(true);
			}
		}

		this.getDataXML = function () {
			var dataStr;
			if (self.serverPagination) {
				var temp = self.QueryViewerCollection[self.IdForQueryViewerCollection].getPivottableDataSync();

				dataStr = temp.split("<Recordset")[1];

				dataStr = "<Recordset" + dataStr;
				/*dataStr = '<OLAPData format="adonet">\n <Table>\n'
				
				
				records = temp.split("<Page")[1];
				
				if (records.indexOf("<Record>") > -1){
					records = records.substr(records.indexOf("<Record>"))
				}
				
				dataStr = dataStr + records.split("</Page>")[0];   			
				
				dataStr = dataStr + '</Table>\n</OLAPData>'*/
			} else {
				dataStr = '<OLAPData format="adonet">\n <Table>\n'

				for (var i = 0; i < self.GeneralDataRows.length; i++) {
					dataStr = dataStr + '  <Record>\n'

					for (var iCV = 0; iCV < this.columns.length; iCV++) {
						dataStr = dataStr + '    <' + this.columns[iCV].getAttribute("dataField") + '>'
						dataStr = dataStr + self.GeneralDataRows[i][iCV]
						dataStr = dataStr + '</' + this.columns[iCV].getAttribute("dataField") + '>\n'
					}

					for (var iCV = 0; iCV < measures.length; iCV++) {
						dataStr = dataStr + '    <' + measures[iCV].getAttribute("dataField") + '>'
						dataStr = dataStr + self.GeneralDataRows[i][iCV + this.columns.length]
						dataStr = dataStr + '</' + measures[iCV].getAttribute("dataField") + '>\n'
					}

					dataStr = dataStr + '  </Record>\n'
				}
				dataStr = dataStr + '</Table>\n</OLAPData>'
			}
			return dataStr
		}

		this.getFilteredDataXML = function () {
			if (self.serverPagination) {
				var temp = self.QueryViewerCollection[self.IdForQueryViewerCollection].getPivottableDataSync();
				var stringRecord = temp.split("<Record>")

				var tempData = [];
				for (var i = 1; i < stringRecord.length; i++) {
					var recordData = [];
					var fullRecordData = [];
					for (var j = 0; j < self.pageData.dataFields.length; j++) {
						recordData[j] = "#NuN#"
						var dt = stringRecord[i].split("<" + self.pageData.dataFields[j] + ">")
						if (dt.length > 1) {
							var at = dt[1].split("</" + self.pageData.dataFields[j] + ">")
							/*var rp = at[0].replace(/^\s+|\s+$/g, '')
							recordData[j] = (rp != "") ? rp : undefined*/
							recordData[j] = at[0]
							fullRecordData[j] = recordData[j]
						} else {
							if (stringRecord[i].indexOf("<" + self.pageData.dataFields[j] + "/>") >= 0) {
								recordData[j] = ""
								fullRecordData[j] = ""
							}

						}
					}
					if (self.filterOK(recordData)) {
						tempData.push(recordData);
					}

				}

				//var dataStr = '<Table>\n'
				var dataStr = '<Recordset RecordCount=\"' + tempData.length + '\" PageCount=\"1\">\n';
				dataStr = dataStr + '<Page PageNumber=\"1\">\n';

				for (var i = 0; i < tempData.length; i++) {
					dataStr = dataStr + '  <Record>\n'

					for (var iCV = 0; iCV < this.columns.length; iCV++) {
						dataStr = dataStr + '    <' + this.columns[iCV].getAttribute("dataField") + '>'
						dataStr = dataStr + tempData[i][iCV]
						dataStr = dataStr + '</' + this.columns[iCV].getAttribute("dataField") + '>\n'
					}

					for (var iCV = 0; iCV < measures.length; iCV++) {
						dataStr = dataStr + '    <' + measures[iCV].getAttribute("dataField") + '>'
						dataStr = dataStr + tempData[i][iCV + this.columns.length]
						dataStr = dataStr + '</' + measures[iCV].getAttribute("dataField") + '>\n'
					}

					dataStr = dataStr + '  </Record>\n'
				}

				dataStr = dataStr + '</Page>\n</Recordset>';//'</Table>'
				return dataStr
			} else {
				var dataStr = '<Table>\n'

				for (var i = 0; i < self.filteredData.length; i++) {
					dataStr = dataStr + '  <Record>\n'

					for (var iCV = 0; iCV < this.columns.length; iCV++) {
						dataStr = dataStr + '    <' + this.columns[iCV].getAttribute("dataField") + '>'
						dataStr = dataStr + self.filteredData[i][iCV]
						dataStr = dataStr + '</' + this.columns[iCV].getAttribute("dataField") + '>\n'
					}

					for (var iCV = 0; iCV < measures.length; iCV++) {
						dataStr = dataStr + '    <' + measures[iCV].getAttribute("dataField") + '>'
						dataStr = dataStr + self.filteredData[i][iCV + this.columns.length]
						dataStr = dataStr + '</' + measures[iCV].getAttribute("dataField") + '>\n'
					}

					dataStr = dataStr + '  </Record>\n'
				}

				dataStr = dataStr + '</Table>'
				return dataStr
			}
		}

		this.getMetadataXML = function () {
			xml = '<OLAPCube format="' + this.defaultPicture.getAttribute("format") + '" thousandsSeparator="' + this.defaultPicture.getAttribute("thousandsSeparator") + '" decimalSeparator="' + this.defaultPicture.getAttribute("decimalSeparator") + '" dateFormat="' + this.defaultPicture.getAttribute("dateFormat") + '">'

			var forMetadatacolumns = this.columns;
			if (self.initMetadata.Metadata) {
				var xmlDoc = jQuery.parseXML(self.initMetadata.Metadata);
				forMetadatacolumns = []
				forMetadatacolumns = xmlDoc.getElementsByTagName("OLAPDimension");
			}

			var hiddenPos = 1
			for (var iCV = 0; iCV < forMetadatacolumns.length; iCV++) {
				var conPos = iCV;
				if (self.initMetadata.Metadata) {
					conPos = -1;
					for (var c = 0; c < self.conditions.length; c++) {
						if (self.conditions[c].dataField == self.initMetadata.Dimensions[iCV].dataField) {
							conPos = c;
						}
					}
				}

				xml = xml + '<OLAPDimension>'

				xml = xml + '<name>' + forMetadatacolumns[iCV].getAttribute("name") + '</name> '
				xml = xml + '<displayName>' + forMetadatacolumns[iCV].getAttribute("displayName") + '</displayName> ';
				xml = xml + '<description>' + forMetadatacolumns[iCV].getAttribute("description") + '</description> ';
				xml = xml + '<dataField>' + forMetadatacolumns[iCV].getAttribute("dataField") + '</dataField> ';
				xml = xml + '<dataType>' + forMetadatacolumns[iCV].getAttribute("dataType") + '</dataType> ';
				//xml = xml + '<defaultPosition>'+this.columns[iCV].getAttribute("defaultPosition")+'</defaultPosition> ';
				if ((self.initMetadata.Dimensions) && (!self.initMetadata.Dimensions[iCV].Visible)) {
					xml = xml + '<hidden>true</hidden>'
				}

				xml = xml + '<defaultPosition>'
				var pos = 0;
				if (/*(forMetadatacolumns[iCV].getAttribute("defaultPosition") == "Hidden") ||*/ (forMetadatacolumns[iCV].getAttribute("defaultPosition") == "Data")) {
					xml = xml + forMetadatacolumns[iCV].getAttribute("defaultPosition")
				} else {
					if (conPos == -1) {
						xml = xml + 'hidden'
						pos = hiddenPos
						hiddenPos = hiddenPos + 1
					} else if (self.rowConditions.findIndex(conPos) != -1) {
						xml = xml + 'rows';
						pos = self.rowConditions.indexOf(conPos) + 1
					} else if (self.colConditions.findIndex(conPos) != -1) {
						xml = xml + 'columns';
						pos = self.colConditions.indexOf(conPos) + 1
					} else {
						xml = xml + 'pages';
						pos = self.filterIndexes.indexOf(conPos) + 1
					}
				}
				xml = xml + '</defaultPosition> ';

				xml = xml + '<axisOrder>' + pos + '</axisOrder>';


				xml = xml + '<validPositions>' + forMetadatacolumns[iCV].getAttribute("validPositions") + '</validPositions> ';


				var summarize = forMetadatacolumns[iCV].getAttribute("summarize");
				if (conPos >= 0) {
					summarize = (self.conditions[conPos].subtotals) ? "yes" : "no";
				}

				xml = xml + '<summarize>' + summarize + '</summarize> ';
				xml = xml + '<align>' + forMetadatacolumns[iCV].getAttribute("align") + '</align> ';

				if (forMetadatacolumns[iCV].getAttribute("picture") === "") {
					xml = xml + '<picture/> '
				} else {
					xml = xml + '<picture>' + forMetadatacolumns[iCV].getAttribute("picture") + '</picture> ';
				}

				if (forMetadatacolumns[iCV].getAttribute("picture") === "") {
					xml = xml + '<format/> ';
				} else {
					xml = xml + '<format>' + forMetadatacolumns[iCV].getAttribute("format") + '</format> ';
				}

				var prevConPos = -1;
				if (self.initMetadata.Metadata) {
					prevConPos = -1;
					for (var c = 0; c < self.initMetadata.Conditions.length; c++) {
						if (self.initMetadata.Conditions[c].dataField == self.initMetadata.Dimensions[iCV].dataField) {
							prevConPos = c;
						}
					}
				}

				var sortValue = (conPos > -1) ? self.conditions[conPos].sort : (prevConPos > - 1) ? self.initMetadata.Conditions[prevConPos].sort : "metadata";

				if (sortValue == "metadata") {
					xml = xml + '<order>' + ((forMetadatacolumns[iCV].getAttribute("order") != "") ? forMetadatacolumns[iCV].getAttribute("order") : 'Ascending') + '</order> '
				} else {
					if (sortValue == 1)
						xml = xml + '<order>Ascending</order> '
					else if (sortValue == -1)
						xml = xml + '<order>Descending</order> '
					else
						xml = xml + '<order>Custom</order> '
				}
				xml = xml + '<customOrder/> ';

				xml = xml + '<filterType>'

				var blackList = (conPos > -1) ? self.conditions[conPos].blackList : (prevConPos > - 1) ? self.initMetadata.Conditions[prevConPos].blackList : [];
				
				if (blackList.length == 0) {
					if ((conPos > -1) && (self.conditions[conPos].defaultAction == "Exclude")) {
						if (self.conditions[conPos].visibles.length == 0)   
							xml = xml + 'HideAllValues';
						else
							xml = xml + 'ShowAllValues'
					} else {
						xml = xml + 'ShowAllValues';
					}
				} else {
					xml = xml + 'ShowSomeValues';
				}

				xml = xml + '</filterType>'

				xml = xml + '<include> ';

				var findex = (conPos > -1) ? self.filterIndexes.findIndex(conPos) : -1;
				if ((findex != -1) && (self.filterDiv.selects[findex].value != "[all]")) {
					if (blackList.findIndex(self.filterDiv.selects[findex].value) === -1) {
						xml = xml + '<value>' + self.filterDiv.selects[findex].value + '</value> ';
					}
				} else {
					var distinctValues = (conPos > -1) ? self.conditions[conPos].distinctValues : (prevConPos > - 1) ? self.initMetadata.Conditions[prevConPos].distinctValues : [];
					if (!(((conPos > -1) && (self.conditions[conPos].defaultAction == "Exclude")) && (blackList.length == 0))) {
						for (var val = 0; val < distinctValues.length; val++) {
							if (blackList.findIndex(distinctValues[val]) === -1) {
								xml = xml + '<value>' + distinctValues[val] + '</value> ';
							}
						}
					}
				}
				xml = xml + '<value>TOTAL</value> </include>'

				xml = xml + '<collapseType>'

				var collapsedValues = (conPos > -1) ? self.conditions[conPos].collapsedValues : (prevConPos > - 1) ? self.initMetadata.Conditions[prevConPos].collapsedValues : [];
				if ((collapsedValues == undefined) || (collapsedValues.length == 0)) {
					xml = xml + 'ExpandAllValues'
					xml = xml + '</collapseType>'
				} else {
					xml = xml + 'ExpandSomeValues'
					xml = xml + '</collapseType>'
					var distinctValues = [];
					if (self.serverPagination) {
						distinctValues = (conPos > -1) ? self.conditions[conPos].distinctValues : (prevConPos > - 1) ? self.initMetadata.Conditions[prevConPos].distinctValues : [];
					} else {
						distinctValues = self.GeneralDistinctValues[iCV];
					}
					xml = xml + '<includeExpand> ';

					for (var val = 0; val < distinctValues.length; val++) {
						if ((distinctValues[val] != undefined) && (collapsedValues.indexOf(distinctValues[val]) == -1)) {
							xml = xml + '<value>' + distinctValues[val] + '</value>'
						}
					}

					xml = xml + '</includeExpand> ';
				}

				xml = xml + '</OLAPDimension>'
			}

			var forMetadatameasures = measures;
			if (self.initMetadata.Metadata) {
				var xmlDoc = jQuery.parseXML(self.initMetadata.Metadata);
				forMetadatameasures = []
				forMetadatameasures = xmlDoc.getElementsByTagName("OLAPMeasure");
			}

			for (var iCV = 0; iCV < forMetadatameasures.length; iCV++) {
				xml = xml + '<OLAPMeasure> ';

				xml = xml + '<name>' + forMetadatameasures[iCV].getAttribute("name") + '</name> '
				xml = xml + '<displayName>' + forMetadatameasures[iCV].getAttribute("displayName") + '</displayName> ';
				xml = xml + '<description>' + forMetadatameasures[iCV].getAttribute("description") + '</description> ';
				xml = xml + '<dataField>' + forMetadatameasures[iCV].getAttribute("dataField") + '</dataField> ';
				xml = xml + '<dataType>' + forMetadatameasures[iCV].getAttribute("dataType") + '</dataType> ';
				xml = xml + '<defaultAggregator>' + forMetadatameasures[iCV].getAttribute("defaultAggregator") + '</defaultAggregator> ';
				xml = xml + '<validAggregators>' + forMetadatameasures[iCV].getAttribute("validAggregators") + '</validAggregators> ';
				xml = xml + '<summarize>' + forMetadatameasures[iCV].getAttribute("summarize") + '</summarize> ';

				if (forMetadatameasures[iCV].getAttribute("format") === "") {
					xml = xml + '<format/> ';
				} else {
					xml = xml + '<format>' + forMetadatameasures[iCV].getAttribute("format") + '</format> ';
				}

				xml = xml + '<align>' + forMetadatameasures[iCV].getAttribute("align") + '</align> ';

				if (forMetadatameasures[iCV].getAttribute("picture") === "") {
					xml = xml + '<picture/> '
				} else {
					xml = xml + '<picture>' + forMetadatameasures[iCV].getAttribute("picture") + '</picture> ';
				}

				if ((self.initMetadata.Measures) && (!self.initMetadata.Measures[iCV].Visible)) {
					xml = xml + '<hidden>true</hidden>'
				}

				xml = xml + '</OLAPMeasure>';
			}

			xml = xml + '</OLAPCube>'
			xml = xml.replace(/\&/g, "&amp;");
			return xml
		}

		this.createXMLMetadata = function () {
			var xml = '<OLAPCube format="' + this.defaultPicture.getAttribute("format") + '" thousandsSeparator="' + this.defaultPicture.getAttribute("thousandsSeparator") + '" decimalSeparator="' + this.defaultPicture.getAttribute("decimalSeparator") + '" dateFormat="' + this.defaultPicture.getAttribute("dateFormat") + '">';

			for (var iCV = 0; iCV < this.columns.length; iCV++) {
				if ((this.conditions[iCV] != false) && (this.conditions[iCV] != undefined)) {
					xml = xml + '<OLAPDimension> ';

					xml = xml + '<name>' + this.columns[iCV].getAttribute("name") + '</name> '
					xml = xml + '<displayName>' + this.columns[iCV].getAttribute("displayName") + '</displayName> ';
					xml = xml + '<description>' + this.columns[iCV].getAttribute("description") + '</description> ';
					xml = xml + '<dataField>' + this.columns[iCV].getAttribute("dataField") + '</dataField> ';
					xml = xml + '<dataType>' + this.columns[iCV].getAttribute("dataType") + '</dataType> ';
					xml = xml + '<defaultPosition>' + this.columns[iCV].getAttribute("defaultPosition") + '</defaultPosition> ';
					xml = xml + '<validPositions>' + this.columns[iCV].getAttribute("validPositions") + '</validPositions> ';
					xml = xml + '<summarize>' + this.columns[iCV].getAttribute("summarize") + '</summarize> ';
					xml = xml + '<align>' + this.columns[iCV].getAttribute("align") + '</align> ';

					if (this.columns[iCV].getAttribute("picture") === "") {
						xml = xml + '<picture/> '
					} else {
						xml = xml + '<picture>' + this.columns[iCV].getAttribute("picture") + '</picture> ';
					}

					if (this.columns[iCV].getAttribute("picture") === "") {
						xml = xml + '<format/> ';
					} else {
						xml = xml + '<format>' + this.columns[iCV].getAttribute("format") + '</format> ';
					}

					if (this.conditions[iCV].sort === 1)
						xml = xml + '<order>ascending</order> '
					else
						xml = xml + '<order>descending</order> '
					xml = xml + '<customOrder/> ';
					xml = xml + '<include> ';

					var findex = self.filterIndexes.findIndex(iCV);
					if ((findex != -1) && (self.filterDiv.selects[findex].value != "[all]")) {
						if (this.conditions[iCV].blackList.findIndex(self.filterDiv.selects[findex].value) === -1) {
							xml = xml + '<value>' + self.filterDiv.selects[findex].value.toString().trimpivot() + '</value> ';
						}
					} else {
						if (!self.serverPagination) {
							for (var val = 0; val < this.conditions[iCV].distinctValues.length; val++) {
								if (this.conditions[iCV].blackList.findIndex(this.conditions[iCV].distinctValues[val]) === -1) {
									xml = xml + '<value>' + this.conditions[iCV].distinctValues[val].toString().trimpivot() + '</value> ';
								}
							}
						} else {
							if (self.conditions[iCV].state != "none") {
								for (var val = 0; val < this.conditions[iCV].distinctValues.length; val++) {
									if (this.conditions[iCV].blackList.findIndex(this.conditions[iCV].distinctValues[val]) === -1) {
										xml = xml + '<value>' + this.conditions[iCV].distinctValues[val].toString().trimpivot() + '</value> ';
									}
								}
							}
						}
					}
					xml = xml + '<value>TOTAL</value> </include> <collapse/> ';

					xml = xml + '<hide> '
					if (self.serverPagination) {
						if (self.conditions[iCV].state == "none") {
							for (var val = 0; val < this.conditions[iCV].distinctValues.length; val++) {
								xml = xml + '<value>' + this.conditions[iCV].distinctValues[val].toString().trimpivot() + '</value> ';
							}
						} else if (self.conditions[iCV].state != "all") {
							for (var yu = 0; yu < this.conditions[iCV].blackList.length; yu++) {
								xml = xml + '<value>' + this.conditions[iCV].blackList[yu].toString().trimpivot() + '</value> ';
							}
						}
					} else {
						for (var yu = 0; yu < this.conditions[iCV].blackList.length; yu++) {
							xml = xml + '<value>' + this.conditions[iCV].blackList[yu].toString().trimpivot() + '</value> ';
						}
					}
					xml = xml + '</hide> '

					if (self.rowConditions.findIndex(iCV) != -1) {
						xml = xml + '<condition>row</condition> ';
						xml = xml + '<filterbar>no</filterbar> ';
						xml = xml + '<position>' + self.rowConditions.findIndex(iCV) + '</position>'
					} else if (self.colConditions.findIndex(iCV) != -1) {
						xml = xml + '<condition>col</condition> ';
						xml = xml + '<filterbar>no</filterbar> ';
						xml = xml + '<position>' + self.colConditions.findIndex(iCV) + '</position>'
					} else {
						xml = xml + '<condition>none</condition> ';
						xml = xml + '<filterbar>yes</filterbar> ';
					}

					xml = xml + '<filterdivs> ';
					if (findex != -1) {
						xml = xml + '<value>' + self.filterDiv.selects[findex].value.toString().trimpivot() + '</value> ';
					}
					xml = xml + '</filterdivs> ';

					xml = xml + '<restoreview>no</restoreview> ';
					xml = xml + ' </OLAPDimension>';
				}
			}

			for (var iCV = 0; iCV < measures.length; iCV++) {
				xml = xml + '<OLAPMeasure> ';

				xml = xml + '<name>' + measures[iCV].getAttribute("name") + '</name> '
				xml = xml + '<displayName>' + measures[iCV].getAttribute("displayName") + '</displayName> ';
				xml = xml + '<description>' + measures[iCV].getAttribute("description") + '</description> ';
				xml = xml + '<dataField>' + measures[iCV].getAttribute("dataField") + '</dataField> ';
				xml = xml + '<dataType>' + measures[iCV].getAttribute("dataType") + '</dataType> ';
				xml = xml + '<defaultAggregator>' + measures[iCV].getAttribute("defaultAggregator") + '</defaultAggregator> ';
				xml = xml + '<validAggregators>' + measures[iCV].getAttribute("validAggregators") + '</validAggregators> ';
				xml = xml + '<summarize>' + measures[iCV].getAttribute("summarize") + '</summarize> ';

				if (measures[iCV].getAttribute("format") === "") {
					xml = xml + '<format/> ';
				} else {
					xml = xml + '<format>' + measures[iCV].getAttribute("format") + '</format> ';
				}

				xml = xml + '<align>' + measures[iCV].getAttribute("align") + '</align> ';

				if (measures[iCV].getAttribute("picture") === "") {
					xml = xml + '<picture/> '
				} else {
					xml = xml + '<picture>' + measures[iCV].getAttribute("picture") + '</picture> ';
				}

				xml = xml + ' </OLAPMeasure>';

			}
			xml = xml + "</OLAPCube>";

			return xml;
		}

		this.ExportToXML = function () {
			var xml = '<EXPORT format="XML" type="pivot">';
			xml = xml + '<METADATA>';
			for (var iCV = 0; iCV < this.columns.length; iCV++) {

				var position = 'row';
				if (self.rowConditions.findIndex(iCV) != -1) {
					position = 'row';
				} else if (self.colConditions.findIndex(iCV) != -1) {
					position = 'column';
				} else {
					position = 'filter';
				}

				xml = xml + '<OLAPDimension ';
				xml = xml + 'name="' + this.columns[iCV].getAttribute("dataField") + '" ';
				xml = xml + 'label="' + this.columns[iCV].getAttribute("displayName") + '" ';
				xml = xml + 'picture="' + this.columns[iCV].getAttribute("picture") + '" ';
				xml = xml + 'datatype="' + this.columns[iCV].getAttribute("dataType") + '" ';
				xml = xml + 'showAll="true" ';
				xml = xml + 'position="' + position + '">';

				if ((this.conditions[iCV] != undefined) && (this.conditions[iCV].distinctValues != undefined)) {
					for (var val = 0; val < this.conditions[iCV].distinctValues.length; val++) {
						xml = xml + '<VALUE CHECKED=';
						if (this.conditions[iCV].blackList.findIndex(this.conditions[iCV].distinctValues[val]) === -1) {
							xml = xml + '"true"';
						} else {
							xml = xml + '"false"';
						}
						if (this.conditions[iCV].collapsedValues.indexOf(this.conditions[iCV].distinctValues[val]) == -1) {
							xml = xml + ' COLLAPSED="false">'
						} else {
							xml = xml + ' COLLAPSED="true">'
						}
						xml = xml + this.conditions[iCV].distinctValues[val] + '</VALUE>';
					}
				}

				xml = xml + '</OLAPDimension>';
			}

			for (var iCV = 0; iCV < measures.length; iCV++) {
				xml = xml + '<OLAPMeasure ';
				xml = xml + 'name="' + measures[iCV].getAttribute("dataField") + '" ';
				xml = xml + 'label="' + measures[iCV].getAttribute("displayName") + '" ';
				xml = xml + 'picture="' + measures[iCV].getAttribute("picture") + '" ';
				xml = xml + 'datatype="' + measures[iCV].getAttribute("dataType") + '" ';
				xml = xml + 'showAll="true" ';
				xml = xml + 'aggregator="sum"/>';
			}

			xml = xml + '</METADATA>';

			xml = xml + '<FLATDATA>';
			for (var i = 0; i < this.allDataWithoutSort.length; i++) {
				xml = xml + '<ROW ';
				for (var iCV = 0; iCV < this.columns.length; iCV++) {
					xml = xml + this.columns[iCV].getAttribute("dataField") + '="' + this.allDataWithoutSort[i][iCV] + '" ';
				}
				for (var iCV = 0; iCV < measures.length; iCV++) {
					xml = xml + measures[iCV].getAttribute("dataField") + '="' + this.allDataWithoutSort[i][iCV + this.columns.length] + '" ';
				}
				xml = xml + '/>'
			}
			xml = xml + '</FLATDATA>';

			xml = xml + '<COLITEMS>' //include measures & dimensions move to columns
			var previuosXml = xml;
			try {
				var level = 0;
				var maxlevel = this.colConditions.length;
				if (level === maxlevel) {
					for (var iCV = 0; iCV < measures.length; iCV++) {
						xml = xml + '<COLITEM measure="' + measures[iCV].getAttribute("displayName") + '" type=""'
						xml = xml + '/>';
					}
				} else {
					level++;
					for (var iCV = 0; iCV < this.colStructure.items.length; iCV++) {
						xml = xml + this.createXMLCOLITEMS(this.colStructure.items[iCV], level, maxlevel);
					}
				}
			} catch (ERROR) {
				xml = previuosXml;
			}
			xml = xml + '</COLITEMS>'

			xml = xml + '<ROWITEMS>'
			previuosXml = xml;
			try {
				for (var iCV = 0; iCV < this.rowStructure.items.length; iCV++) {
					var level = 0;
					var maxlevel = this.columns.length - this.colConditions.length - this.filterIndexes.length - 1;
					if (maxlevel >= level) {
						xml = xml + this.createXMLROWITEMS(this.rowStructure.items[iCV], level, maxlevel);
					}
				}
			} catch (ERROR) {
				xml = previuosXml;
			}
			xml = xml + '</ROWITEMS>'


			//add Html info
			xml = xml + '<HTML>';

			xml = xml + '<HEAD>';
			xml = xml + '<META content="text/html; charset=utf-8" http-equiv="Content-Type"/>';

			xml = xml + '<STYLE>';

			xml = xml + '.h2title {background-color: #5C5D5F; border-color: #666666; font-family: Verdana; font-weight: normal; font-size: 10pt; height: 44px; color: #E0E0E0;}\n';
			xml = xml + '.h2titlewhite {background-color: #ffffff; font-family: Verdana; font-size: 10pt; font-weight: normal; height: 25px; color: black;}\n';
			xml = xml + '.even {background-color: #FEFEFE;	font-weight: normal; font-family: Verdana; font-size: 10pt;	padding: 5px; }\n';
			xml = xml + '.h2subtitle {background-color: #5C5D5F; border-color: #666666; font-family: Verdana; font-weight: normal; font-size: 10pt;	height: 22px; color: #E0E0E0;}\n';
			xml = xml + '.gtotal {background-color: #EBEBEB; font-weight: normal; font-family: Verdana; font-size: 10pt;}\n';
			xml = xml + '.pivot_table td.total {background-color: #EBEBEB; font-weight: normal;	font-family: Verdana; font-size: 10pt;}\n';
			xml = xml + '.pivot_table td.subtotal {background-color: #EBEBEB; font-weight: normal;	font-family: Verdana; font-size: 10pt;}\n';

			xml = xml + '</STYLE>';
			xml = xml + '</HEAD>';

			xml = xml + '<BODY>';
			xml = xml + '<TABLE border="2">'

			for (var i = 0; i < jQuery("#" + self.controlName + "_" + self.query + " tr").length; i++) {//for every row
				xml = xml + '<TR>';

				var tRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[i];
				for (var j = 0; j < tRow.children.length; j++) {
					var childText = OAT.removeIconFont(tRow.children[j].textContent).trim();
					var hidden = tRow.children[j].getAttribute('hidden');

					var styleString = "";
					if ((tRow.children[j].getAttribute("style") != undefined) && (tRow.children[j].getAttribute("style") != null)) {
						styleString = " style=\"" + tRow.children[j].getAttribute("style") + "\" ";
					}

					var classString = "";
					if ((tRow.children[j].getAttribute("class") != undefined) && (tRow.children[j].getAttribute("class") != null)) {
						classString = " class=\"" + tRow.children[j].getAttribute("class") + "\" ";
					}

					if (hidden === null) {
						var rowSpan = tRow.children[j].getAttribute('rowspan');
						var colSpan = tRow.children[j].getAttribute('colspan');
						if (((rowSpan === null) && (colSpan === null)) || (j === tRow.children.length - 1)) {
							xml = xml + '<TD ' + classString + ' ' + styleString + '>' + childText + '</TD>';
						} else if (colSpan === null) {
							xml = xml + '<TD ' + classString + " " + 'rowspan="' + rowSpan + '" ' + styleString + ' >' + childText + '</TD>';
						} else if (rowSpan === null) {
							xml = xml + '<TD ' + classString + " " + 'colspan="' + colSpan + '" ' + styleString + ' >' + childText + '</TD>';
						} else {
							xml = xml + '<TD ' + classString + " " + 'colspan="' + colSpan + '" rowspan="' + rowSpan + '" ' + styleString + ' >' + childText + '</TD>';
						}
					}
				}

				xml = xml + '</TR>';
			}


			xml = xml + '</TABLE>';

			xml = xml + '</BODY>';

			xml = xml + '</HTML>';
			//
			xml = xml + "</EXPORT>";

			return xml.replace(/\&/g, "&amp;");

		}

		this.createXMLROWITEMS = function (item, level, maxlevel) {
			var parentCollapse = ((item.parent == undefined) || (item.parent.collapsed == undefined)) ? false : item.parent.collapsed;
			var str = '<ROWITEM dimension="' + columns[level].getAttribute('dataField') + '" collapsed="' + item.collapsed + '" parentCollapsed="' + parentCollapse + '" value="' + item.value + '" level="' + level + '"'
			if (level === maxlevel) {
				return str + "/>";
			} else {
				level++;
				str = str + ">";
				for (var i = 0; i < item.items.length; i++) {
					str = str + this.createXMLROWITEMS(item.items[i], level, maxlevel);
				}
				str = str + '</ROWITEM>'
				return str;
			}
		}

		this.createXMLCOLITEMS = function (item, level, maxlevel) {
			var str = ""
			if (level === maxlevel) {
				for (var iCV = 0; iCV < measures.length; iCV++) {
					str = str + '<COLITEM measure="' + measures[iCV].getAttribute("displayName") + '" type="">'
					var inRow = self.rowConditions.length - measures.length + 1;
					str = str + '<VALITEM dimension="' + columns[level - 1 + inRow].getAttribute('dataField') + '" value="' + item.value + '"/>' //level + cantidad de dimensiones que no estan movidas a las columnas
					var superItem = item;
					while (superItem.parent.depth != -1) {
						superItem = superItem.parent;
						str = str + '<VALITEM dimension="' + columns[level - 1 + inRow].getAttribute('dataField') + '" value="' + superItem.value + '"/>'
					}
					str = str + '</COLITEM>';
				}
				return str;
			} else {
				level++;
				for (var i = 0; i < item.items.length; i++) {
					str = str + this.createXMLCOLITEMS(item.items[i], level, maxlevel);
				}
				return str;
			}
		}

		this.ExportToExcel = function (fileName) {
			var table = '<table border="2">'

			for (var i = 0; i < jQuery("#" + self.controlName + "_" + self.query + " tr").length; i++) {//for every row
				table = table + '<tr>';

				var tRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[i];
				for (var j = 0; j < tRow.children.length; j++) {
					var childText = OAT.removeIconFont(tRow.children[j].textContent.replace(/^\s+|\s+$/g, '')).trim();
					var hidden = tRow.children[j].getAttribute('hidden');

					var styleString = "";
					if ((tRow.children[j].getAttribute("style") != undefined) && (tRow.children[j].getAttribute("style") != null)) {
						styleString = " style=\"" + tRow.children[j].getAttribute("style") + "\" ";
					}

					var parseText = ""
					var previusJap = false;
					
					for (var c = 0; c < childText.length; c++) {
						if (childText.charCodeAt(c) < 1000) {
							if (previusJap) {
								parseText = parseText + " " + childText[c];
							} else {
								parseText = parseText + childText[c];
							}
							previusJap = false;
						} else {
							var Hex = childText.charCodeAt(c).toString(16);
							parseText = parseText + "&#x" + Hex;
							previusJap = true;
						}
					}

					if (hidden === null) {
						var rowSpan = tRow.children[j].getAttribute('rowspan');
						var colSpan = tRow.children[j].getAttribute('colspan');
						if (((rowSpan === null) && (colSpan === null)) || (j === tRow.children.length - 1)) {
							table = table + '<td ' + styleString + '>' + parseText + '</td>';
						} else if (colSpan === null) {
							table = table + '<td rowspan="' + rowSpan + '" ' + styleString + ' >' + parseText + '</td>';
						} else if (rowSpan === null) {
							table = table + '<td colspan="' + colSpan + '" ' + styleString + ' >' + parseText + '</td>';
						} else {
							table = table + '<td colspan="' + colSpan + '" rowspan="' + rowSpan + '" ' + styleString + ' >' + parseText + '</td>';
						}
					}
				}

				table = table + '</tr>';
			}

			table = table + '</table>'; //</tbody>
			
			//add header for special characters 
			var header = '<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"></head><body>'
			table = header + table + '</body>'
			
			var dtltbl = table;

			if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) {
				window.open('data:application/vnd.ms-excel,' + encodeURIComponent(dtltbl));
			} else if ((!gx.util.browser.isIE()) || (9 < gx.util.browser.ieVersion())) {
				var blob = new Blob([dtltbl], { type: "application/vnd.ms-excel" });
				saveAs(blob, fileName + ".xls");
			} else {
				return dtltbl;
			}

		}


		this.lightOn = function () {
			for (var i = 0; i < self.gd.targets.length; i++) {
				var elm = self.gd.targets[i][0];
				if (gx.util.browser.isIE()) {
					elm.className += " drag-drop";
				} else {
					elm.classList.add("drag-drop");
				}
			}
		}

		this.lightOff = function () {
			for (var i = 0; i < self.gd.targets.length; i++) {
				var elm = self.gd.targets[i][0];
				try {
					if (gx.util.browser.isIE() && 11 > gx.util.browser.ieVersion()) {
						elm.className.replace("drag-drop");
					} else {
						elm.classList.remove("drag-drop");
					}
				} catch (error) {

				}
			}
		}
		self.gd.onFail = self.lightOff;

		this.process = function (elm) {
			self.lightOn();
			elm.style.backgroundColor = "#888";
			elm.style.padding = "2px";
			elm.style.cursor = "pointer";
			//OAT.Dom.attach(elm, "mouseup", function(e) { self.lightOff(); });
		}

		this.filterOK = function (row) { /* does row pass filters? */
			for (var i = 0; i < self.filterIndexes.length; i++) { /* for all filters */
				var fi = self.filterIndexes[i]; /* this column is important */
				var s = self.filterDiv.selects[i]; /* select node */
				if (s.selectedIndex && OAT.$v(s) != row[fi]) { return false; }
			}

			//var notInBlackList = true;
			for (var i = 0; i < self.rowConditions.length; i++) { /* row blacklist */
				var value = row[self.rowConditions[i]];
				var cond = self.conditions[self.rowConditions[i]];
				if (cond.blackList.findIndex(value) != -1) { /*notInBlackList = false; */return false; }

			}


			for (var i = 0; i < self.colConditions.length; i++) { /* column blacklist */
				var value = row[self.colConditions[i]];
				var cond = self.conditions[self.colConditions[i]];
				if (cond.blackList.findIndex(value) != -1) { return false; }
			}
			return true;
		}

		this.sort = function (cond, index) { /* sort distinct values of a condition */
			var sortFunc;
			var coef = cond.sort; if (cond.sort == 0) { coef = 1 } if (cond.sort == 2) { coef = -1 }
			var numSort = function (a, b) {
				if (a == b) { return 0; }
				return coef * (parseInt(a) > parseInt(b) ? 1 : -1);
			}
			var dictSort = function (a, b) {
				if (a == b) { return 0; }
				return coef * (a > b ? 1 : -1);
			}

			if (cond.distinctValues == undefined) return;

			//new code
			var sortInt = true;
			for (var ival = 0; ival < cond.distinctValues.length; ival++) {
				if ((sortInt) && (cond.distinctValues[ival] != parseInt(cond.distinctValues[ival]))) {
					sortInt = false;
				}
			}
			if (sortInt) { sortFunc = numSort; } else { sortFunc = dictSort; } //decides the type of sorting
			//end new code
			var testValue = cond.distinctValues[0];

			if ((cond.sort != 0) && (cond.sort != 2)) {
				cond.distinctValues.sort(sortFunc);
			} else {
				if ((index != undefined) && (self.columns[index] != undefined)) {
					cond.distinctValues.sort(sortFunc);

					var prevValues = [];
					for (var h = 0; h < cond.distinctValues.length; h++) {
						prevValues[h] = cond.distinctValues[h];
					}

					cond.distinctValues = [];
					if (cond.sort == 0) {
						for (var h = 0; h < self.columns[index].childNodes.length; h++) {
							if ((self.columns[index].childNodes[h] != undefined) &&
								(self.columns[index].childNodes[h].localName != undefined) &&
								(self.columns[index].childNodes[h].localName === "customOrder")) {
								for (var n = 0; n < self.columns[index].childNodes[h].childNodes.length; n++) {
									if (self.columns[index].childNodes[h].childNodes[n].localName == "Value") {
										//cond.distinctValues.push(self.columns[index].childNodes[h].childNodes[n].textContent);
										var notTrimValue = self.columns[index].childNodes[h].childNodes[n].textContent
										for (var m = 0; m < prevValues.length; m++) {
											if (prevValues[m].trimpivot() == notTrimValue.trimpivot()) {
												cond.distinctValues.push(prevValues[m]);
											}
										}
									}
								}
							}
						}
					} else {
						for (var h = 0; h < self.columns[index].childNodes.length; h++) {
							if ((self.columns[index].childNodes[h] != undefined) &&
								(self.columns[index].childNodes[h].localName != undefined) &&
								(self.columns[index].childNodes[h].localName === "customOrder")) {
								for (var n = self.columns[index].childNodes[h].childNodes.length - 1; n >= 0; n--) {
									if (self.columns[index].childNodes[h].childNodes[n].localName == "Value") {
										//cond.distinctValues.push(self.columns[index].childNodes[h].childNodes[n].textContent);
										var notTrimValue = self.columns[index].childNodes[h].childNodes[n].textContent
										for (var m = 0; m < prevValues.length; m++) {
											if (prevValues[m].trimpivot() == notTrimValue.trimpivot()) {
												cond.distinctValues.push(prevValues[m]);
											}
										}
									}
								}
							}
						}
					}
					if (cond.distinctValues.length < prevValues.length) {
						for (var h = 0; h < prevValues.length; h++) {
							if (cond.distinctValues.indexOf(prevValues[h]) == -1) {
								cond.distinctValues.push(prevValues[h])
							}
						}
					}
				}
			}
			if ((columns.length == 1) || (measures.length = 0)) {
				if (cond.sort == 1) {
					self.allData.sort((function (index) {
						return function (a, b) {
							return (a[index] === b[index] ? 0 : (a[index] < b[index] ? -1 : 1));
						};
					})(0));
				} else if (cond.sort == -1) {
					self.allData.sort((function (index) {
						return function (a, b) {
							return (a[index] === b[index] ? 0 : (a[index] > b[index] ? -1 : 1));
						};
					})(0));
				}
			}
		} /* sort */

		/* init routines */
		this.initCondition = function (index) {
			if ((index == self.dataColumnIndex) && (((columns.length > 1) || (measures.length > 0)))) { /* dummy condition */
				self.conditions.push(false);
				return;
			}
			var sortValue = 1;
			//if (self.serverPagination){
			//	sortValue = 0
			//}
			var showSubtotals = 1;
			var hideSubtotalsOption = false;
			var validPosition = "filters;rows;columns;hidden";
			var isDimension = false;
			if (self.columns[index] != undefined) {
				isDimension = true;
				if (self.serverPagination) {
					if ((self.columns[index].getAttribute("order") != undefined) && (self.columns[index].getAttribute("order") === "ascending")) {
						sortValue = 1;
					}
				}
				if ((self.columns[index].getAttribute("order") != undefined) && (self.columns[index].getAttribute("order") === "descending")) {
					sortValue = -1;
				}
				if ((self.columns[index].getAttribute("order") != undefined) && (self.columns[index].getAttribute("order") === "custom")) {
					sortValue = 0;
					if (self.serverPagination) {
						sortValue = 1;
					}
				}
				if ((self.columns[index].getAttribute("summarize") != undefined) && (self.columns[index].getAttribute("summarize") === "yes")) {
					showSubtotals = 1;

					for (var h = 0; h < self.columns[index].childNodes.length; h++) {
						if ((self.columns[index].childNodes[h] != undefined) &&
							(self.columns[index].childNodes[h].localName != undefined) &&
							(self.columns[index].childNodes[h].localName === "include")) {
							showSubtotals = false;
							for (var n = 0; n < self.columns[index].childNodes[h].childNodes.length; n++) {
								if ((self.columns[index].childNodes[h].childNodes[n].localName != null) &&
									(self.columns[index].childNodes[h].childNodes[n].localName.toLowerCase() === "value")) {
									if (self.columns[index].childNodes[h].childNodes[n].textContent == "TOTAL") {
										showSubtotals = true;
									}
								}
							}
						} else if ((self.columns[index].childNodes[h] != undefined) &&
							(self.columns[index].childNodes[h].localName != undefined) &&
							(self.columns[index].childNodes[h].localName === "exclude")) {
							showSubtotals = false;
						}
					}

					/*if ((self.columns[index].firstElementChild != undefined) && (self.columns[index].firstElementChild.localName == "exclude")){
						showSubtotals = false;
					} else if ((self.columns[index].firstElementChild != undefined) && (self.columns[index].firstElementChild.localName == "include")) {
						showSubtotals = false;
						for (var n = 0; n < self.columns[index].firstElementChild.childNodes.length; n++) {
								if ((self.columns[index].firstElementChild.childNodes[n].localName != null) && 
								(self.columns[index].firstElementChild.childNodes[n].localName.toLowerCase() === "value")) {
									if (self.columns[index].firstElementChild.childNodes[n].textContent == "TOTAL"){
										showSubtotals = true;
									}
							}
						}
					}*/
				}
				if ((self.columns[index].getAttribute("summarize") != undefined) && (self.columns[index].getAttribute("summarize") === "no")) {
					showSubtotals = false;
					hideSubtotalsOption = true;
				}
				if ((self.columns[index].getAttribute("validPositions") != undefined)) {
					validPosition = self.columns[index].getAttribute("validPositions");
				}

			}

			var cond = {
				distinctValues: [], blackList: [], whiteList: [], greyList: [], collapsedValues: [],
				sort: sortValue, subtotals: showSubtotals, hideSubtotalOption: hideSubtotalsOption, validPosition: validPosition,
				dataRowPosition: index, isDimension: isDimension, topFilterValue: gx.getMessage("GXPL_QViewerJSAllOption")/*"[all]"*/
			}
			if (self.serverPagination) {
				cond.topFilterValue = "[all]"
				cond.topFilterString = gx.getMessage("GXPL_QViewerJSAllOption")
			}

			self.conditions.push(cond);
			if (!self.serverPagination) {
				for (var i = 0; i < self.allData.length; i++) {
					var value = self.allData[i][index];
					if (value == undefined) {
						value = " ";
						self.allData[i][index] = " ";
					}
					if (cond.distinctValues.findIndex(value) == -1) { /* not yet present */
						cond.distinctValues.push(value);
					} /* if new value */
				} /* for all rows */
				if ((sortValue != 0) && (sortValue != 2)) {
					self.sort(cond);
				} else { //sort with order custom
					if (self.columns[index] != undefined) {
						var tempCondSort = cond.sort;
						if (cond.sort != 2) {
							cond.sort = 1;
						} else {
							cond.sort = -1;
						}
						self.sort(cond)
						cond.sort = tempCondSort;

						var prevValues = [];
						for (var h = 0; h < cond.distinctValues.length; h++) {
							prevValues[h] = cond.distinctValues[h];
						}

						cond.distinctValues = [];
						for (var h = 0; h < self.columns[index].childNodes.length; h++) {
							if ((self.columns[index].childNodes[h] != undefined) &&
								(self.columns[index].childNodes[h].localName != undefined) &&
								(self.columns[index].childNodes[h].localName === "customOrder")) {
								if (sortValue == 0) {
									for (var n = 0; n < self.columns[index].childNodes[h].childNodes.length; n++) {
										if (self.columns[index].childNodes[h].childNodes[n].localName == "Value") {
											//cond.distinctValues.push(self.columns[index].childNodes[h].childNodes[n].textContent);
											var notTrimValue = self.columns[index].childNodes[h].childNodes[n].textContent
											for (var m = 0; m < prevValues.length; m++) {
												if (prevValues[m].trimpivot() == notTrimValue.trimpivot()) {
													cond.distinctValues.push(prevValues[m]);
												}
											}
										}
									}
								} else {
									for (var n = self.columns[index].childNodes[h].childNodes.length - 1; n >= 0; n--) {
										if (self.columns[index].childNodes[h].childNodes[n].localName == "Value") {
											//cond.distinctValues.push(self.columns[index].childNodes[h].childNodes[n].textContent);
											var notTrimValue = self.columns[index].childNodes[h].childNodes[n].textContent
											for (var m = 0; m < prevValues.length; m++) {
												if (prevValues[m].trimpivot() == notTrimValue.trimpivot()) {
													cond.distinctValues.push(prevValues[m]);
												}
											}
										}
									}
								}
								if (cond.distinctValues.length < prevValues.length) {
									for (var h = 0; h < prevValues.length; h++) {
										if (cond.distinctValues.indexOf(prevValues[h]) == -1) {
											cond.distinctValues.push(prevValues[h]);
										}
									}
								}
							}
						}
					}
				}
			}
			if (self.columns[index] != undefined) {
				for (var h = 0; h < self.columns[index].childNodes.length; h++) {
					if ((self.columns[index].childNodes[h] != undefined) &&
						(self.columns[index].childNodes[h].localName != undefined) &&
						(self.columns[index].childNodes[h].localName === "include")) {
						for (var n = 0; n < self.columns[index].childNodes[h].childNodes.length; n++) {
							if ((self.columns[index].childNodes[h].childNodes[n].localName != null) &&
								(self.columns[index].childNodes[h].childNodes[n].localName.toLowerCase() === "value")) {
								if (self.columns[index].childNodes[h].childNodes[n].textContent != "TOTAL") {
									self.conditions[index].topFilterValue = self.columns[index].childNodes[h].childNodes[n].textContent;
								}
							}
						}
					}
				}
			}

		}

		this.restoreSubtotalsAndSortLayout = function (index) {
			//restore save conditions
			try {
				if (rememberLayout) {
					mState = self.getState();
					if ((mState != undefined) && (mState.version != undefined) && (mState.version === self.rememberLayoutStateVersion)) { //check version
						if ((mState.query == self.query) && (self.conditions.length == mState.conditions.length)) {
							self.conditions[index].subtotals = mState.conditions[index].subtotals;
							self.conditions[index].sort = mState.conditions[index].sort;
							self.conditions[index].collapsedValues = mState.conditions[index].collapsedValues;
							//if (!self.autoPaging){
							//self.conditions[index].distinctValues  =  mState.conditions[index].distinctValues;
							//}
						}
					}
				}
			} catch (Error) { }
		}

		this.applyCustomFilters = function (index) {
			try {
				if (index == self.dataColumnIndex) { /* dummy condition */
					return;
				}
				if (self.columns[index] != undefined) {
					for (var h = 0; h < self.columns[index].childNodes.length; h++) {
						if ((self.columns[index].childNodes[h] != undefined) &&
							(self.columns[index].childNodes[h].localName != undefined) &&
							(self.columns[index].childNodes[h].localName === "include")) {
							if (!self.serverPagination) {
								//push all in blacklist 
								self.conditions[index].blackList = [];
								for (var i = 0; i < self.GeneralDistinctValues[index].length; i++) {
									self.conditions[index].blackList.push(self.GeneralDistinctValues[index][i])
								}

								for (var n = 0; n < self.columns[index].childNodes[h].childNodes.length; n++) {
									if ((self.columns[index].childNodes[h].childNodes[n].localName != null) &&
										(self.columns[index].childNodes[h].childNodes[n].localName.toLowerCase() === "value")) {
										var ind = self.conditions[index].blackList.indexOf(self.columns[index].childNodes[h].childNodes[n].textContent);
										if (ind != -1) {
											self.conditions[index].topFilterValue = self.columns[index].childNodes[h].childNodes[n].textContent;
											self.conditions[index].blackList.splice(ind, 1);
										}
									}
								}
								if (self.filterIndexes.indexOf(index) != -1) {
									self.conditions[index].blackList = [];
								}
							} else {
								//push all in blacklist
								self.createFilterInfo({ op: "none", values: "", dim: index });
								for (var n = 0; n < self.columns[index].childNodes[h].childNodes.length; n++) {
									if ((self.columns[index].childNodes[h].childNodes[n].localName != null) &&
										(self.columns[index].childNodes[h].childNodes[n].localName.toLowerCase() === "value")) {
										if (self.columns[index].childNodes[h].childNodes[n].textContent != "TOTAL") {
											if (self.UserFilterValues[index] == undefined) self.UserFilterValues[index] = [];
											self.UserFilterValues[index].push(self.columns[index].childNodes[h].childNodes[n].textContent.trimpivot());
										}
									}
								}
							}
						}
						//add expand collapse info
						var rowPos = self.rowConditions.indexOf(index);
						var colPos = self.colConditions.indexOf(index);
						if (((colPos < self.colConditions.length - 1) && (colPos != -1)) || ((rowPos < self.rowConditions.length - measures.length) && (rowPos != -1))) {
							if ((self.columns[index].childNodes[h] != undefined) &&
								(self.columns[index].childNodes[h].localName != undefined) &&
								(self.columns[index].childNodes[h].localName === "expand")) {
								if (!self.serverPagination) {
									self.conditions[index].collapsedValues = [];
									for (var i = 0; i < self.GeneralDistinctValues[index].length; i++) {
										self.conditions[index].collapsedValues.push(self.GeneralDistinctValues[index][i])
									}

									for (var n = 0; n < self.columns[index].childNodes[h].childNodes.length; n++) {
										if ((self.columns[index].childNodes[h].childNodes[n].localName != null) &&
											(self.columns[index].childNodes[h].childNodes[n].localName.toLowerCase() === "value")) {
											var ind = self.conditions[index].collapsedValues.indexOf(self.columns[index].childNodes[h].childNodes[n].textContent);
											if (ind != -1) {
												self.conditions[index].collapsedValues.splice(ind, 1);
											}
										}
									}
								} else {


									for (var n = 0; n < self.columns[index].childNodes[h].childNodes.length; n++) {
										if ((self.columns[index].childNodes[h].childNodes[n].localName != null) &&
											(self.columns[index].childNodes[h].childNodes[n].localName.toLowerCase() === "value")) {
											if (self.UserExpandValues[index] == undefined) self.UserExpandValues[index] = [];
											self.UserExpandValues[index].push(self.columns[index].childNodes[h].childNodes[n].textContent.trimpivot());
										}
									}
									if (self.UserExpandValues[index] == undefined) {
										self.UserExpandValues[index] = ["#ALLCOLLAPSE#"];
									}
								}
							}
						}
					}
				}
			} catch (error) {

			}
		}

		/* pseudo-init routines */
		this.pseudoInitCondition = function (index, prevCondition) {
			if (index == self.dataColumnIndex) { /* dummy condition */
				self.conditions.push(false);
				return;
			}
			var sortValue = 1;
			var showSubtotals = 1;
			var hideSubtotalsOption = false;
			var validPosition = "filters;rows;columns;hidden";
			var isDimension = false;
			if (self.columns[index] != undefined) {
				var isDimension = true;
				if ((self.columns[index].getAttribute("order") != undefined) && (self.columns[index].getAttribute("order") === "descending")) {
					sortValue = -1;
				}
				if ((self.columns[index].getAttribute("order") != undefined) && (self.columns[index].getAttribute("order") === "custom")) {
					sortValue = 0;
				}
				if ((self.columns[index].getAttribute("summarize") != undefined) && (self.columns[index].getAttribute("summarize") === "yes")) {
					showSubtotals = 1;
					if ((self.columns[index].firstElementChild != undefined) && (self.columns[index].firstElementChild.localName == "exclude")) {
						showSubtotals = false;
					}
				}
				if (prevCondition[index].sort != undefined) {
					sortValue = prevCondition[index].sort;
				}
				if (prevCondition[index].subtotals != undefined) {
					showSubtotals = prevCondition[index].subtotals;
				}
				if ((self.columns[index].getAttribute("summarize") != undefined) && (self.columns[index].getAttribute("summarize") === "no")) {
					showSubtotals = false;
					hideSubtotalsOption = true;
				}
				if ((self.columns[index].getAttribute("validPositions") != undefined)) {
					validPosition = self.columns[index].getAttribute("validPositions");
				}
			}

			var cond = {
				distinctValues: [], blackList: [], whiteList: [], greyList: [], collapsedValues: [],
				sort: sortValue, subtotals: showSubtotals, hideSubtotalOption: hideSubtotalsOption, validPosition: validPosition,
				dataRowPosition: index, isDimension: isDimension, topFilterValue: gx.getMessage("GXPL_QViewerJSAllOption")/*"[all]"*/
			}

			self.conditions.push(cond);
			for (var i = 0; i < self.allData.length; i++) {
				var value = self.allData[i][index];
				if (value == undefined) {
					value = " ";
					self.allData[i][index] = " ";
				}
				if (cond.distinctValues.findIndex(value) == -1) { /* not yet present */
					cond.distinctValues.push(value);
				} /* if new value */
			} /* for all rows */

			/*set previus black & collapsed values list*/
			cond.blackList = prevCondition[index].blackList;
			cond.collapsedValues = prevCondition[index].collapsedValues;

			if (self.allData.length > 0) {
				self.sort(cond, index);
			}
		}

		this.init = function () {
			self.propPage = OAT.Dom.create("div", {});

			if (dataRows[0] != undefined) { //if data available


				for (var i = 0; i < self.headerRow.length; i++) {
					self.initCondition(i);
					self.applyCustomFilters(i);
				}

				//save default view values
				var oldConditions = jQuery.extend(true, [], self.conditions);

				var defcolCond = new Array()
				for (var i = 0; i < self.initRowConditions.length; i++) {
					defcolCond[i] = self.initRowConditions[i];
				}
				var defcolRow = new Array();
				for (var i = 0; i < self.initColConditions.length; i++) {
					defcolRow[i] = self.initColConditions[i];
				}
				var defStIndex = new Array();
				for (var i = 0; i < self.initFilterIndexes.length; i++) {
					defStIndex[i] = self.initFilterIndexes[i];
				}

				self.initState = {
					query: self.query,
					conditions: oldConditions,
					colConditions: defcolRow,
					rowConditions: defcolCond,
					filterDivSelects: [],
					filterIndexes: defStIndex,
					stateChanged: false,
					rowsPerPage: pageSize
				};
				//end save default view values

				for (var i = 0; i < self.headerRow.length; i++) {
					self.restoreSubtotalsAndSortLayout(i)
				}

				//get previuos state
				var mState;
				//get previus state
				if ((rememberLayout) /*&& (!self.autoPaging)*/) {
					mState = self.getState();
				} else {
					mState = null;
				}

				var oldFilterDivValues = [];

				if (mState != null) {
					if ((mState.version != undefined) && (mState.version === self.rememberLayoutStateVersion)) { //check version
						if ((mState.query == self.query) && (self.conditions.length == mState.conditions.length)
							//&& ((!self.autoPaging) || (mState.filterIndexes.length == 0)) 
						) {
							//load blacklist
							for (var ci = 0; ci <= mState.conditions.length - 1; ci++) {
								if ((mState.conditions[ci] != false) && (self.conditions[ci] != false)) {
									for (var p = 0; p < mState.conditions[ci].blackList.length; p++) {
										if ((self.conditions[ci].blackList.indexOf(mState.conditions[ci].blackList[p]) == -1) &&
											(self.GeneralDistinctValues[ci].indexOf(mState.conditions[ci].blackList[p]) != -1)) {//self.conditions[ci]
											self.conditions[ci].blackList.push(mState.conditions[ci].blackList[p])
										}
									}
									for (var p = 0; p < mState.conditions[ci].collapsedValues.length; p++) {
										if ((self.conditions[ci].collapsedValues.indexOf(mState.conditions[ci].collapsedValues[p]) == -1) &&
											(self.GeneralDistinctValues[ci].indexOf(mState.conditions[ci].collapsedValues[p]) != -1)) {
											self.conditions[ci].collapsedValues.push(mState.conditions[ci].collapsedValues[p])
										}
									}
									try {
										self.conditions[ci].sort = mState.conditions[ci].sort;
										self.sort(self.conditions[ci], ci);
										self.oldSortValues[ci] = mState.conditions[ci].sort;
										self.conditions[ci].subtotals = mState.conditions[ci].subtotals;
									} catch (Error) { }
								}
							}

							self.rowConditions = mState.rowConditions;
							self.colConditions = mState.colConditions;
							self.rowsPerPage = mState.rowsPerPage;

							self.filterIndexes = mState.filterIndexes;
							if (mState.filterDivSelects != undefined) {
								for (var fiv = 0; fiv < mState.filterDivSelects.length; fiv++) {
									oldFilterDivValues[fiv] = mState.filterDivSelects[fiv];
								}
							}

							self.stateChanged = true
						}
					}
				}

				try {
					if ((mState != null) && (mState.version === self.rememberLayoutStateVersion) && (mState.filterIndexes.length > 0)) {
						var existElm = false;
						for (var i = 0; i < self.conditions.length; i++) {//save the black list create from older state
							var tmp = []
							if ((self.conditions[i]) && (self.conditions[i].blackList)) {
								for (var j = 0; j < self.conditions[i].blackList.length; j++) {
									tmp.push(self.conditions[i].blackList[j])
									existElm = true;
								}
							}
							self.tempBlackLists.push([tmp])
							var tmp2 = []
							if ((self.conditions[i]) && (self.conditions[i].collapsedValues)) {
								for (var j = 0; j < self.conditions[i].collapsedValues.length; j++) {
									tmp2.push(self.conditions[i].collapsedValues[j])
									existElm = true;
								}
							}
							self.tempCollapsedValues.push([tmp2])
						}
						if (!existElm) {
							self.tempBlackLists = false
						}
					} else {
						self.tempBlackLists = false
					}
				} catch (error) {
					self.tempBlackLists = false
				}


				self.gd.clearSources();
				self.gd.clearTargets();
				//draw filter bar


				if ((self.autoPaging) || (self.rowConditions.length <= 16) || (self.GeneralDataRows.length <= 1200)) {
					self.drawFilters();
				}

				//first draw filter then write old valueF
				if (oldFilterDivValues.length > 0) {
					for (var fiv = 0; fiv < oldFilterDivValues.length; fiv++) {
						self.filterDiv.selects[fiv].value = oldFilterDivValues[fiv];
					}
					self.preGoWhenFilterByTopFilter(true)
				}

				try {
					if (self.filterIndexes.length == 0) {
						self.applyFilters();
						self.createAggStructure();
						self.fillAggStructure();

						self.checkAggStructure();

						self.count();
					}
				} catch (Error) {
					//alert(Error)
				}



				if (GlobalPivotInterval[UcId] != undefined) {
					clearInterval(GlobalPivotInterval[UcId]);
				}
				var previousValuePivotWidth = 0
				var antepreviusValuePivotWidth = 0
				GlobalPivotInterval[UcId] = setInterval(function () {
					if ((self.autoPaging) /*&& (!self.FilterByTopFilter)*/) {


						if ((jQuery("#" + self.containerName + " #tablePagination_currPage")[0] != undefined) ||
							(jQuery("#" + self.controlName + "_" + self.query + "_tablePagination " + "#tablePagination_currPage")[0] != undefined)) {
							var actualPage;
							if (jQuery("#" + self.containerName + " #tablePagination_currPage")[0] != undefined) {
								actualPage = parseInt(jQuery("#" + self.containerName + " #tablePagination_currPage")[0].value);
							} else {
								actualPage = parseInt(jQuery("#" + self.controlName + "_" + self.query + "_tablePagination " + "#tablePagination_currPage")[0].value)
							}
							var t = 0;
							if (self.actualPaginationPage != actualPage) { //change of page
								var gonext = (self.actualPaginationPage < actualPage)
								var lastPage = (actualPage == parseInt(jQuery("#" + self.containerName + " #tablePagination_totalPages")[0].textContent))
								self.actualPaginationPage = actualPage
								self.changePaginationRows(actualPage, gonext, lastPage);
								var _pagetot;
								if (jQuery("#" + self.containerName + " #tablePagination_totalPages")[0] != undefined) {
									_pagetot = parseInt(jQuery("#" + self.containerName + " #tablePagination_totalPages")[0].value);
								} else {
									_pagetot = parseInt(jQuery("#" + self.controlName + "_" + self.query + "_tablePagination " + " #tablePagination_totalPages")[0].value);
								}
								if (!isNaN(_pagetot)) self.TotalPagesPaging = _pagetot
								self.go(false);
							}
							//if ((!gx.util.browser.isFirefox()) || ((document.activeElement.type != undefined) && (document.activeElement != jQuery("#" + self.controlName + "_" + self.query + "tablePagination_rowsPerPage")[0])) ){
							actual_rowsPerPage = parseInt(jQuery("#" + self.controlName + "_" + self.query + "tablePagination_rowsPerPage")[0].value);
							if (self.autoPagingRowsPerPage != actual_rowsPerPage) {
								self.autoPagingRowsPerPage = actual_rowsPerPage
								//self.changePaginationPagesSize(actualPage);
								self.actualPaginationPage = 1
								setTimeout(function () {
									createPaginationInfo(self, self.RowsWhenMoveToFilter);
									self.changePaginationRows(1);
									self.go(false);
								},
									500)
							}
						}
					}
					var actual_rowsPerPage = 0;
					if (jQuery("#" + self.controlName + "_" + self.query + "tablePagination_rowsPerPage").length > 0) {
						actual_rowsPerPage = parseInt(jQuery("#" + self.controlName + "_" + self.query + "tablePagination_rowsPerPage")[0].value);
						if (!isNaN(actual_rowsPerPage)) {
							if (self.rowsPerPage != actual_rowsPerPage) {
								self.rowsPerPage = actual_rowsPerPage;
								self.stateChanged = true;
								/* must save state change*/

								var filterDivSelects = new Array();
								for (var fiv = 0; fiv < self.filterDiv.selects.length; fiv++) {
									filterDivSelects[fiv] = self.filterDiv.selects[fiv].value;
								}

								var state = {
									query: self.query,
									conditions: self.conditions,
									colConditions: self.colConditions,
									rowConditions: self.rowConditions,
									filterIndexes: self.filterIndexes,
									filterDivSelects: filterDivSelects,
									rowsPerPage: self.rowsPerPage,
									version: self.rememberLayoutStateVersion
								};

								self.saveState(state);

							} else {
								self.rowsPerPage = actual_rowsPerPage;
							}

							if (jQuery("#" + self.controlName + "_" + self.query)[0].getAttribute("class") === "pivot_table") {
								if ((!autoResize)) {
									var clientWdt = jQuery("#" + self.containerName)[0].clientWidth
									jQuery("#" + self.controlName + "_" + self.query).css({ width: (clientWdt) + "px" })
								}
								
								var wd = jQuery("#" + self.controlName + "_" + self.query)[0].offsetWidth - 4;
								try {
									if (jQuery("#MAINFORM")[0].className.indexOf("form-horizontal") > -1) {
										wd = wd + 4;
									}
								} catch (Error) {
								}
								var wd2 = jQuery("#" + self.controlName + "_" + self.query)[0].offsetWidth - 1;
								try {
									var borderWidth = jQuery("#" + self.controlName + "_" + self.query + "_tablePagination").css("border-right-width");
									if ((borderWidth != undefined) && (borderWidth[0] != '0')) {
										wd2 = wd2 - 1;
									}
								} catch (ERROR) { }

								var actualWidth = jQuery("#" + self.controlName + "_" + self.query + "_tablePagination")[0].clientWidth

								if ((actualWidth > wd + 1) || (actualWidth < wd - 1)) {
									jQuery("#" + UcId + "_" + self.query + "_pivot_page").css({ width: wd + "px" });

									jQuery("#" + self.controlName + "_" + self.query + "_tablePagination").css({ width: wd2 + "px" });

									antepreviusValuePivotWidth = previousValuePivotWidth
									previousValuePivotWidth = wd
								}
								if ((jQuery("#" + this.controlName + "_" + self.query + "_tablePagination_paginater").length > 0) && (jQuery("#" + this.controlName + "_" + self.query + "_tablePagination")[0].getBoundingClientRect().bottom < jQuery("#" + this.controlName + "_" + self.query + "_tablePagination_paginater")[0].getBoundingClientRect().bottom)) {

									jQuery("#" + this.controlName + "_" + self.query + "_tablePagination")

								}
							}
							if ((jQuery("#" + self.controlName + "_" + self.query + "_tablePagination_paginater").length > 0) && (jQuery("#" + self.controlName + "_" + self.query + "_tablePagination")[0].getBoundingClientRect().bottom < jQuery("#" + self.controlName + "_" + self.query + "_tablePagination_paginater")[0].getBoundingClientRect().bottom)) {
								jQuery("#" + self.controlName + "_" + self.query + "_tablePagination")
							}
						}
					} else {
						if (jQuery("#" + self.controlName + "_" + self.query)[0] != undefined) {
							if (jQuery("#" + self.controlName + "_" + self.query)[0].getAttribute("class") === "pivot_table") {

								if (!autoResize) {
									var clientWdt = jQuery("#" + self.containerName)[0].clientWidth
									jQuery("#" + self.controlName + "_" + self.query).css({ width: (clientWdt) + "px" })
								}
								
								var wd = jQuery("#" + self.controlName + "_" + self.query)[0].offsetWidth;
								
								if ((antepreviusValuePivotWidth == 0) || (antepreviusValuePivotWidth == previousValuePivotWidth) ||
									((previousValuePivotWidth > wd + 6) || (previousValuePivotWidth < wd - 6)
										|| (antepreviusValuePivotWidth > previousValuePivotWidth + 6) || (antepreviusValuePivotWidth < previousValuePivotWidth - 6))) {
									jQuery("#" + UcId + "_" + self.query + "_pivot_page").css({ width: wd + "px" });
									antepreviusValuePivotWidth = previousValuePivotWidth
									previousValuePivotWidth = wd
								}
							}
						}
					}
				}, 250);
			} else { //there's no data

				OAT.Dom.clear(self.div);
				self.div.setAttribute("class", "conteiner_table_div");
				//draw filter bar
				//myTable.id = self.controlName + "_" + self.query + "_toolbar";
				self.drawFilters();

				var table = OAT.Dom.create("table", {}, "pivot_table");
				table.id = this.controlName + "_" + this.query; //add control name and query name as the id of main table
				var tbody = OAT.Dom.create("tbody");

				OAT.Dom.append([table, tbody], [self.div, table]);

				if (self.colConditions.length > 0) {

					var i = 0;
					var tr = OAT.Dom.create("tr");
					self._drawRowConditionsHeadingsCustom(tr);

					for (var ni = 0; ni < self.colConditions.length; ni++) {
						tr = self._drawColConditionsHeadingsCustom(tr, ni, (ni === self.colConditions.length - 1));
					}

					self.appendRowToTable(tbody, tr, true);
					firstRow = tr;


					if (self.colConditions.length > 0) {
						var tr = OAT.Dom.create("tr");

						for (var m = 0; m < measures.length; m++) {
							var th = OAT.Dom.create("th", {}, "h2titlewhite");
							th.colSpan = 1;
							OAT.addTextNode(th, measures[m].attributes.getNamedItem("displayName").nodeValue)
							self.setTitleTexrtAlign(th, th.textContent);
							tr.appendChild(th);
						}

						self.appendRowToTable(tbody, tr, true);
					}

					var _mtotalSpan = measures.length - self.colConditions.length
					if (_mtotalSpan > 0) {
						var th = OAT.Dom.create("th", {}, "h2subtitle ");
						OAT.addTextNode(th, "")
						th.colSpan = _mtotalSpan;
						th.style.borderLeftColor = "transparent";
						firstRow.appendChild(th);
					}

				} else {

					var tr = OAT.Dom.create("tr");

					for (var i = 0; i < self.rowConditions.length - (measures.length - 1); i++) {
						var th = OAT.Dom.create("th", { cursor: "pointer" }, "h2title");
						var div = OAT.Dom.create("div");
						OAT.addTextNode(div, self.headerRow[self.rowConditions[i]] + "\u00A0\u00A0\u00A0")
						th.appendChild(div);
						tr.appendChild(th);
					}

					if (self.colConditions.length > 0) {
						for (var i = 0; i < self.colConditions.length; i++) {
							var th = OAT.Dom.create("th", { cursor: "pointer" }, "h2title");
							var div = OAT.Dom.create("div");
							OAT.addTextNode(div, self.headerRow[self.colConditions[i]] + "\u00A0\u00A0\u00A0")
							th.appendChild(div);
							tr.appendChild(th);
						}
					}

					for (var j = 0; j < self.rowConditions.length; j++) {
						var cond = self.conditions[self.rowConditions[j]];
						if (self.isMeasureByName(self.headerRow[self.rowConditions[j]])) {
							var th = OAT.Dom.create("th", {}, "h2titlewhite");
							var div = OAT.Dom.create("div");
							OAT.addTextNode(div, self.headerRow[self.rowConditions[j]])
							self.setTitleTexrtAlign(div, self.headerRow[self.rowConditions[j]]);
							self.setClickEventHandlers(th, self.headerRow[self.rowConditions[j]], "MEASURE", self.rowConditions[j] - columns.length, 'GrandTotal');
							OAT.Dom.append([th, div], [tr, th]);
						}
					}


					if (!self.colConditions.length) {
						var th = OAT.Dom.create("th");
						self._drawCorner(th, true);
						th.conditionIndex = -1;
						tr.appendChild(th);
					} else { th.style.border = "none"; }
					tbody.appendChild(tr);
				}


				if (gx.util.browser.isIE()) {
					jQuery("#" + UcId + "_" + self.query + "_pivot_page").css({ boxShadow: '0px 0px 0px' })
				}

				if (GlobalPivotInterval[UcId] != undefined) {
					clearInterval(GlobalPivotInterval[UcId]);
				}
				var previousValuePivotWidth = 0
				var antepreviusValuePivotWidth = 0

				setTimeout(function () {
					if (jQuery("#" + self.controlName + "_" + self.query)[0] != undefined) {
						if (jQuery("#" + self.controlName + "_" + self.query)[0].getAttribute("class") === "pivot_table") {
							if ((!autoResize)) {
								var clientWdt = jQuery("#" + this.containerName)[0].clientWidth
								jQuery("#" + self.controlName + "_" + self.query).css({ width: (clientWdt - 4) + "px" })
							}

							var wd = jQuery("#" + self.controlName + "_" + self.query)[0].offsetWidth - 4;
							try {
								if (jQuery("#MAINFORM")[0].className.indexOf("form-horizontal") > -1) {
									wd = wd + 4;
								}
							} catch (Error) {
							}
							jQuery("#" + UcId + "_" + self.query + "_pivot_page").css({ width: wd + "px" });
						}
					}
				}, 250)




			}
		} /* init */


		this.initWhenServerPagination = function () {
			self.propPage = OAT.Dom.create("div", {});
			if ((self.QueryViewerCollection[self.IdForQueryViewerCollection].AutoRefreshGroup == "")) {
				jQuery(".oat_winrect_container").remove();//delete previous pop-ups
			}
			self.UserFilterValues = []; self.UserExpandValues = [];
			for (var i = 0; i < self.headerRow.length; i++) {
				self.initCondition(i);
				//add info for server paging porpouse
				if (self.conditions[i] && self.columns[i]) {
					self.conditions[i].dataField = self.columns[i].getAttribute("dataField")
					self.conditions[i].state = "all"
					self.conditions[i].defaultAction = "Include"
					self.conditions[i].visibles = []
					self.conditions[i].searchInfo = { previousPage: 0, totalPages: 0, filteredText: "", values: [] }
				}
				self.applyCustomFilters(i);
			}

			//save default view values
			var oldConditions = jQuery.extend(true, [], self.conditions);

			var defcolCond = new Array()
			for (var i = 0; i < self.initRowConditions.length; i++) {
				defcolCond[i] = self.initRowConditions[i];
			}
			var defcolRow = new Array();
			for (var i = 0; i < self.initColConditions.length; i++) {
				defcolRow[i] = self.initColConditions[i];
			}
			var defStIndex = new Array();
			for (var i = 0; i < self.initFilterIndexes.length; i++) {
				defStIndex[i] = self.initFilterIndexes[i];
			}

			var oldInitMetadata = jQuery.extend(true, {}, self.initMetadata)

			self.initState = {
				query: self.query,
				conditions: oldConditions,
				colConditions: defcolRow,
				rowConditions: defcolCond,
				filterDivSelects: [],
				filterIndexes: defStIndex,
				stateChanged: false,
				rowsPerPage: pageSize,
				AxisInfo: self.createAxisInfo(""),
				DataInfo: self.createDataInfo(),
				CollapseInfo: [],
				FilterInfo: [],
				InitMetadata: oldInitMetadata
			};
			//end save default view values

			for (var i = 0; i < self.headerRow.length; i++) {
				self.restoreSubtotalsAndSortLayout(i)
			}

			//get previuos state
			var mState;
			if (rememberLayout) {
				mState = self.getState();
			} else {
				mState = null;
			}

			var oldFilterDivValues = [];
			var stateLoad = false;
			if (mState != null) {
				if ((mState.version != undefined) && (mState.version === self.rememberLayoutStateVersion)) {
					if ((mState.query == self.query) && (self.conditions.length == mState.conditions.length)) {
						stateLoad = true;
						self.UserFilterValues = []
						for (var ci = 0; ci <= mState.conditions.length - 1; ci++) {
							if ((mState.conditions[ci] != false) && (self.conditions[ci] != false)) {
								for (var p = 0; p < mState.conditions[ci].distinctValues.length; p++) {
									if ((self.conditions[ci].distinctValues.indexOf(mState.conditions[ci].distinctValues[p]) == -1)) {
										self.conditions[ci].distinctValues.push(mState.conditions[ci].distinctValues[p])
									}
								}
								for (var p = 0; p < mState.conditions[ci].blackList.length; p++) {
									if ((self.conditions[ci].blackList.indexOf(mState.conditions[ci].blackList[p]) == -1)) {
										self.conditions[ci].blackList.push(mState.conditions[ci].blackList[p])
									}
								}
								if (mState.conditions[ci].visibles) {
									for (var p = 0; p < mState.conditions[ci].visibles.length; p++) {
										if ((self.conditions[ci].visibles.indexOf(mState.conditions[ci].visibles[p]) == -1)) {
											self.conditions[ci].visibles.push(mState.conditions[ci].visibles[p])
										}
									}
								}
								for (var p = 0; p < mState.conditions[ci].collapsedValues.length; p++) {
									if ((self.conditions[ci].collapsedValues.indexOf(mState.conditions[ci].collapsedValues[p]) == -1)) {
										self.conditions[ci].collapsedValues.push(mState.conditions[ci].collapsedValues[p])
									}
								}
								try {
									self.conditions[ci].sort = mState.conditions[ci].sort;

									self.oldSortValues[ci] = mState.conditions[ci].sort;
									self.conditions[ci].subtotals = mState.conditions[ci].subtotals;
									self.conditions[ci].defaultAction = mState.conditions[ci].defaultAction;
									self.conditions[ci].state = mState.conditions[ci].state;
									self.conditions[ci].topFilterValue = mState.conditions[ci].topFilterValue

									self.conditions[ci].totalPages = mState.conditions[ci].totalPages
									self.conditions[ci].previousPage = mState.conditions[ci].previousPage
									self.conditions[ci].blocked = mState.conditions[ci].blocked

								} catch (Error) { }
							}
						}

						self.rowConditions = mState.rowConditions;
						self.colConditions = mState.colConditions;
						self.rowsPerPage = mState.rowsPerPage;

						self.filterIndexes = mState.filterIndexes;
						if (mState.filterDivSelects != undefined) {
							for (var fiv = 0; fiv < mState.filterDivSelects.length; fiv++) {
								oldFilterDivValues[fiv] = mState.filterDivSelects[fiv];
							}
						}

						self.stateChanged = true
					}
				}
			}

			try {
				if ((mState != null) && (mState.version === self.rememberLayoutStateVersion) && (mState.filterIndexes.length > 0)) {
					var existElm = false;
					for (var i = 0; i < self.conditions.length; i++) {//save the black list create from older state
						var tmp = []
						if ((self.conditions[i]) && (self.conditions[i].blackList)) {
							for (var j = 0; j < self.conditions[i].blackList.length; j++) {
								tmp.push(self.conditions[i].blackList[j])
								existElm = true;
							}
						}
						self.tempBlackLists.push([tmp])
						var tmp2 = []
						if ((self.conditions[i]) && (self.conditions[i].collapsedValues)) {
							for (var j = 0; j < self.conditions[i].collapsedValues.length; j++) {
								tmp2.push(self.conditions[i].collapsedValues[j])
								existElm = true;
							}
						}
						self.tempCollapsedValues.push([tmp2])
					}
					if (!existElm) {
						self.tempBlackLists = false
					}
				} else {
					self.tempBlackLists = false
				}
			} catch (error) {
				self.tempBlackLists = false
			}


			self.gd.clearSources();
			self.gd.clearTargets();



			if (GlobalPivotInterval[UcId] != undefined) {
				clearInterval(GlobalPivotInterval[UcId]);
			}
			var previousValuePivotWidth = 0
			var antepreviusValuePivotWidth = 0
			GlobalPivotInterval[UcId] = setInterval(function () {
				var actual_rowsPerPage = 0;
				
				//find max with of inner_filter_div
				var pageFilter = jQuery("#" + UcId + "_" + self.query + "_pivot_page").find(".inner_filter_div")
				var MaxWidthFilters = 0;
				for (var pFIndx = 0; pFIndx < pageFilter.length; pFIndx++){
					if (MaxWidthFilters < pageFilter[pFIndx].offsetWidth){
						MaxWidthFilters = pageFilter[pFIndx].offsetWidth
					}
				}
				MaxWidthFilters = (MaxWidthFilters > 0) ? MaxWidthFilters + 8 : MaxWidthFilters; 
				
				if (jQuery("#" + self.controlName + "_" + self.query + "tablePagination_rowsPerPage").length > 0) {
					actual_rowsPerPage = parseInt(jQuery("#" + self.controlName + "_" + self.query + "tablePagination_rowsPerPage")[0].value);
					if (!isNaN(actual_rowsPerPage)) {
						if (jQuery("#" + self.controlName + "_" + self.query)[0].getAttribute("class") === "pivot_table") {
							if ((!autoResize)) {
								var clientWdt = jQuery("#" + self.containerName)[0].clientWidth
								if (clientWdt < MaxWidthFilters) {
									jQuery("#" + self.controlName + "_" + self.query).css({ width: MaxWidthFilters + "px" });
								} else {
									jQuery("#" + self.controlName + "_" + self.query).css({ width: (clientWdt) + "px" });
								}
							}
							var wd = jQuery("#" + self.controlName + "_" + self.query)[0].offsetWidth;
							
							
							if (wd >= MaxWidthFilters){
								
								var actualWidth = jQuery("#" + self.controlName + "_" + self.query + "_tablePagination")[0].clientWidth
								if ((actualWidth > MaxWidthFilters + 1) || (actualWidth < MaxWidthFilters - 1)) {
									jQuery("#" + UcId + "_" + self.query + "_pivot_page").css({ width: wd + "px" });
	
									jQuery("#" + self.controlName + "_" + self.query + "_tablePagination").css({ width: wd + "px" });

									antepreviusValuePivotWidth = previousValuePivotWidth
									previousValuePivotWidth = wd
								}
								
								
							} else {
								//
								//var actualWidth = jQuery("#" + self.controlName + "_" + self.query + "_tablePagination")[0].clientWidth
								//if ((actualWidth > wd + 1) || (actualWidth < wd - 1)) {
								jQuery("#" + UcId + "_" + self.query + "_pivot_page").css({ width: MaxWidthFilters + "px" });
	
								jQuery("#" + self.controlName + "_" + self.query + "_tablePagination").css({ width: MaxWidthFilters + "px" });
								
								jQuery("#" + self.controlName + "_" + self.query).css({ width: MaxWidthFilters + "px" });
								
								antepreviusValuePivotWidth = previousValuePivotWidth
								previousValuePivotWidth = MaxWidthFilters
								//}
							}
							/*if ((jQuery("#" + this.controlName + "_" + self.query + "_tablePagination_paginater").length > 0) && (jQuery("#" + this.controlName + "_" + self.query + "_tablePagination")[0].getBoundingClientRect().bottom < jQuery("#" + this.controlName + "_" + self.query + "_tablePagination_paginater")[0].getBoundingClientRect().bottom)) {
								jQuery("#" + this.controlName + "_" + self.query + "_tablePagination")
							}*/
						}
						/*if ((jQuery("#" + self.controlName + "_" + self.query + "_tablePagination_paginater").length > 0) && (jQuery("#" + self.controlName + "_" + self.query + "_tablePagination")[0].getBoundingClientRect().bottom < jQuery("#" + self.controlName + "_" + self.query + "_tablePagination_paginater")[0].getBoundingClientRect().bottom)) {
							jQuery("#" + self.controlName + "_" + self.query + "_tablePagination")
						}*/
					}
				} else {
					if (jQuery("#" + self.controlName + "_" + self.query)[0] != undefined) {
						if (jQuery("#" + self.controlName + "_" + self.query)[0].getAttribute("class") === "pivot_table") {
							
							
							
							if (!autoResize) {
								var clientWdt = jQuery("#" + self.containerName)[0].clientWidth
								if (clientWdt < MaxWidthFilters) {
									jQuery("#" + self.controlName + "_" + self.query).css({ width: MaxWidthFilters + "px" });
								} else {
									jQuery("#" + self.controlName + "_" + self.query).css({ width: (clientWdt) + "px" });
								}
							}

							var wd = jQuery("#" + self.controlName + "_" + self.query)[0].offsetWidth
							
							if (wd < MaxWidthFilters){
								
								if ((antepreviusValuePivotWidth == 0) || (antepreviusValuePivotWidth == previousValuePivotWidth) ||
									((previousValuePivotWidth > MaxWidthFilters + 6) || (previousValuePivotWidth < MaxWidthFilters - 6)
										|| (antepreviusValuePivotWidth > previousValuePivotWidth + 6) || (antepreviusValuePivotWidth < previousValuePivotWidth - 6))) {
								
									jQuery("#" + UcId + "_" + self.query + "_pivot_page").css({ width: MaxWidthFilters + "px" });
									antepreviusValuePivotWidth = previousValuePivotWidth
									previousValuePivotWidth = MaxWidthFilters
									
									
									jQuery("#" + self.controlName + "_" + self.query).css({ width: MaxWidthFilters + "px" });
								}
								
							} else {
							
								if ((antepreviusValuePivotWidth == 0) || (antepreviusValuePivotWidth == previousValuePivotWidth) ||
									((previousValuePivotWidth > wd + 6) || (previousValuePivotWidth < wd - 6)
										|| (antepreviusValuePivotWidth > previousValuePivotWidth + 6) || (antepreviusValuePivotWidth < previousValuePivotWidth - 6))) {
								
									jQuery("#" + UcId + "_" + self.query + "_pivot_page").css({ width: wd + "px" });
									antepreviusValuePivotWidth = previousValuePivotWidth
									previousValuePivotWidth = wd
								}
							}
							
						}
					}
				}
			}, 20);




			if ((mState != null) && (mState.AxisInfo != null)) {
				self.pageData.AxisInfo = mState.AxisInfo;
			} else {
				self.pageData.AxisInfo = self.createAxisInfo("");
			}

			if ((mState != null) && (mState.DataInfo != null)) {
				self.pageData.DataInfo = mState.DataInfo;
			} else {
				self.pageData.DataInfo = self.createDataInfo();
			}

			if ((mState != null) && (mState.FilterInfo != null)) {
				self.pageData.FilterInfo = mState.FilterInfo;
			}

			if ((self.UserFilterValues.length == 0) && (self.UserExpandValues.length == 0)) {

				self.pageData.CollapseInfo = self.CreateExpandCollapseInfo("");

				self.QueryViewerCollection[self.IdForQueryViewerCollection].getPageDataForPivotTable((function (resXML) {
					if (!qv.util.anyError(resXML) || self.QueryViewerCollection[self.IdForQueryViewerCollection].debugServices) {

						self.pageData = OATGetNewDataFromXMLForPivot(resXML, self.pageData, self.ShowMeasuresAsRows);
						self.preGoWhenServerPagination(true);
						//if (!stateLoad) {
							self.initValueRead(self, 0, stateLoad);
						//}
						qv.util.hideActivityIndicator(self.QueryViewerCollection[self.IdForQueryViewerCollection]);

					} else {
						var errMsg = qv.util.getErrorFromText(resXML);
						qv.util.renderError(self.QueryViewerCollection[self.IdForQueryViewerCollection], errMsg);
					}
				}).closure(this), [1, self.rowsPerPage, true, self.pageData.AxisInfo, self.pageData.DataInfo, self.pageData.FilterInfo, self.pageData.CollapseInfo, true]);

				//}


			} else {
				//when user customize filters or expand-collapsed
				/*if (self.QueryViewerCollection[self.IdForQueryViewerCollection].UseRecordsetCache && self.QueryViewerCollection[self.IdForQueryViewerCollection].RecordsetChanged())
				{
					self.QueryViewerCollection[self.IdForQueryViewerCollection].getRecordsetCacheKey((function (recordsetCacheKey) {	
					
						self.QueryViewerCollection[self.IdForQueryViewerCollection].RecordsetCacheOldKey = (self.QueryViewerCollection[self.IdForQueryViewerCollection].RecordsetCacheActualKey ? self.QueryViewerCollection[self.IdForQueryViewerCollection].RecordsetCacheActualKey : "");
						self.QueryViewerCollection[self.IdForQueryViewerCollection].RecordsetCacheActualKey = recordsetCacheKey; 
						
						self.initValueRead(self, 0, true);
						
					}).closure(this));	
				} else {*/
				self.initValueRead(self, 0, true);
				//}

			}

			//set interval for handler values infinite scroll
			setInterval(function () {
				for (var t = 0; t < jQuery(".oat_winrect_container .pivot_popup_fix").length; t++) {
					if ((!jQuery(".oat_winrect_container .pivot_popup_fix").closest(".oat_winrect_container")[t].style.display) ||
						(jQuery(".oat_winrect_container .pivot_popup_fix").closest(".oat_winrect_container")[t].style.display != "none")) {

						if (jQuery(".oat_winrect_container .pivot_popup_fix").length > 0) {
							var element = jQuery(".oat_winrect_container .pivot_popup_fix")[t];
							var scrollBottom = element.scrollHeight - element.clientHeight - element.scrollTop
							if (scrollBottom < 25) {
								var UcId = element.getAttribute("ucid")
								var columnNumber = parseInt(element.getAttribute("columnNumber"))
								if (UcId == self.UcId) {
									self.readScrollValue(columnNumber)
								}
							}
						}
					}
				}
			},
				250)


		} /* initWhenServerPagination */

		this.initValueRead = function (self, columnNumber, allData) {
			if (columnNumber >= self.columns.length) {

				//add items to page select if exists
				try {
					for (var iP = 0; iP < jQuery("#" + self.UcId + "_" + self.query + "_pivot_page").find("select").length; iP++) {
						var s = jQuery("#" + self.UcId + "_" + self.query + "_pivot_page").find("select")[iP];
						var filterDim = parseInt(s.getAttribute("id").replace("page_select_", ""))
						var index = self.filterIndexes[filterDim]

						if (self.conditions[index].filteredShowValues == undefined) {
							self.conditions[index].filteredShowValues = []
						}
						var actualValues = self.conditions[index].distinctValues;
						for (var j = 0; j < actualValues.length; j++) {
							var v = actualValues[j];
							if (self.conditions[index].filteredShowValues.indexOf(v) == -1) {
								self.conditions[index].filteredShowValues.push(v);
								if (v != "#NuN#") {
									OAT.Dom.option(v, v, s);
								} else {
									OAT.Dom.option(" ", v, s);
								}
							}
						}
						if ((self.conditions[index].topFilterValue != "[all]") /*&& (self.conditions[index].topFilterValue!="")*/) {
							var v = self.conditions[index].topFilterValue
							if (self.conditions[index].filteredShowValues.indexOf(v) != -1) { //value already load
								s.selectedIndex = self.conditions[index].filteredShowValues.indexOf(v) + 1
							} else {
								self.conditions[index].filteredShowValues.push(v);
								if (v != "#NuN#") {
									OAT.Dom.option(v, v, s);
								} else {
									OAT.Dom.option(" ", v, s);
								}
								s.selectedIndex = 1
							}
						}


					}
				} catch (ERROR) {

				}



				if (allData) {
					self.callServiceWhenCustomeValues();
				}
				return;
			} else {
				var cantItems = 10;
				if ((self.QueryViewerCollection[self.IdForQueryViewerCollection].AutoRefreshGroup != "") || (allData)) {
					cantItems = 0;
				}
				self.lastRequestValue = columnNumber;
				self.QueryViewerCollection[self.IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
					var data = JSON.parse(resJSON);

					self.conditions[columnNumber].previousPage = data.PageNumber
					self.conditions[columnNumber].totalPages = data.PagesCount
					self.conditions[columnNumber].blocked = false
					
					if (allData) {
						self.conditions[columnNumber].distinctValues = []
					}
					//null value?
					if (data.Null) {
						self.conditions[columnNumber].hasNull = true;
						if (self.conditions[columnNumber].distinctValues.indexOf("#NuN#") == -1) {
							self.conditions[columnNumber].distinctValues.push("#NuN#")
						}
						var nullIncluded = true;

						if (!self.conditions[columnNumber].NullIncluded) {
							nullIncluded = false;
						}
						if ((nullIncluded) && (self.conditions[columnNumber].visibles.indexOf("#NuN#") == -1)) {
							self.conditions[columnNumber].visibles.push("#NuN#");
						}
					} else {
						self.conditions[columnNumber].hasNull = false;
					}

					var includeLists = [];
					for (var i = 0; i < data.NotNullValues.length; i++) {
						var value = data.NotNullValues[i]
						var include = false;
						if ((self.conditions[columnNumber].state == "none") &&
							(self.UserFilterValues.length > 0) && (self.UserFilterValues[columnNumber] != undefined)
							&& (self.UserFilterValues[columnNumber].length > 0) && (self.UserFilterValues[columnNumber].indexOf(value.trimpivot()) != -1)) {
							include = true;
							includeLists.push(value)
						}

						if (self.conditions[columnNumber].distinctValues.indexOf(value) == -1) {
							self.conditions[columnNumber].distinctValues.push(value)
						}
						if ((self.conditions[columnNumber].state == "all")
							&& (self.conditions[columnNumber].visibles.indexOf(value) == -1)) {
							self.conditions[columnNumber].visibles.push(value)
						}
						if ((self.conditions[columnNumber].state == "none")
							&& (self.conditions[columnNumber].blackList.indexOf(value) == -1)
							&& (!include)) {
							self.conditions[columnNumber].blackList.push(value)
						}

						if ((allData) && (self.UserExpandValues.length > 0)) {//collapsed values
							if (self.UserExpandValues[columnNumber] != undefined) {
								if ((self.UserExpandValues[columnNumber][0] == "#ALLCOLLAPSE#") ||
									(self.UserExpandValues[columnNumber].indexOf(value.trimpivot()) == -1)) {
									self.conditions[columnNumber].collapsedValues.push(value);
								}
							}
						}

					}

					for (var i = 0; i < includeLists.length; i++) {
						self.createFilterInfo({ op: "pop", values: includeLists[i], dim: columnNumber }, true);
					}

					columnNumber++;
					self.initValueRead(self, columnNumber, allData)
				}).closure(this), [self.columns[columnNumber].getAttribute("dataField"), 1, cantItems, ""]);
			}
		}

		this.callServiceWhenCustomeValues = function () {
			self.pageData.CollapseInfo = self.CreateExpandCollapseInfo("");

			self.QueryViewerCollection[self.IdForQueryViewerCollection].getPageDataForPivotTable((function (resXML) {
				if (!qv.util.anyError(resXML) || self.QueryViewerCollection[self.IdForQueryViewerCollection].debugServices) {

					self.pageData = OATGetNewDataFromXMLForPivot(resXML, self.pageData, self.ShowMeasuresAsRows);
					self.preGoWhenServerPagination(true);
					qv.util.hideActivityIndicator(self.QueryViewerCollection[self.IdForQueryViewerCollection]);

				} else {
					var errMsg = qv.util.getErrorFromText(resXML);
					qv.util.renderError(self.QueryViewerCollection[self.IdForQueryViewerCollection], errMsg);
				}
			}).closure(this), [1, self.rowsPerPage, true, self.pageData.AxisInfo, self.pageData.DataInfo, self.pageData.FilterInfo, self.pageData.CollapseInfo, true]);

		}



		/* callback routines */
		this.getOrderReference = function (conditionIndex, anchorRef, functionRef, divRef) { // ** move a row or column to filter bar ---
			return function (target, x, y) {
				/* somehow reorder conditions */

				if ((self.conditions[conditionIndex].validPosition != undefined) && (self.conditions[conditionIndex].validPosition.indexOf("filters") == -1)) {
					return;
				}
				self.lightOff();

				/* filters */
				if (target == self.filterDiv) {
					self.stateChanged = true
					self.filterIndexes.push(conditionIndex);
					self.conditions[conditionIndex].blackList = [];
					for (var i = 0; i < self.rowConditions.length; i++) {
						if (self.rowConditions[i] == conditionIndex) { self.rowConditions.splice(i, 1); }
					}
					for (var i = 0; i < self.colConditions.length; i++) {
						if (self.colConditions[i] == conditionIndex) { self.colConditions.splice(i, 1); }
					}

					if (!self.serverPagination) {
						if (!self.autoPaging) {
							self.preGoWhenMoveTopFilter(conditionIndex);
						} else {
							self.preGoWhenFilterByTopFilter(false)
						}
					}
					self.onDragundDropEventHandle(conditionIndex, "filters") //call event

					self.DiseablePivot();
					setTimeout(function () {
						if (!self.serverPagination) {
							self.go(false);
						} else {
							self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, self.conditions[conditionIndex].dataField, { op: "all", value: "", dim: conditionIndex }, "", "")
						}
						self.EneablePivot();
					}, 200)
					return;
				}

				var sourceCI = conditionIndex; /* global index */
				var targetCI = target.conditionIndex; /* global index */
				if (sourceCI == targetCI) {
					if (gx.util.browser.webkit) {
						if (anchorRef != undefined) {
							anchorRef.displayRef2([x, y])
							functionRef([x, y, divRef])
						}
					}
					return;
				} /* dragged onto the same */
				var sourceType = false; var sourceI = -1; /* local */
				var targetType = false; var targetI = -1; /* local */
				for (var i = 0; i < self.rowConditions.length; i++) {
					if (self.rowConditions[i] == sourceCI) { sourceType = self.rowConditions; sourceI = i; }
					if (self.rowConditions[i] == targetCI) { targetType = self.rowConditions; targetI = i; }
				}
				for (var i = 0; i < self.colConditions.length; i++) {
					if (self.colConditions[i] == sourceCI) { sourceType = self.colConditions; sourceI = i; }
					if (self.colConditions[i] == targetCI) { targetType = self.colConditions; targetI = i; }
				}
				if (targetCI == -1) {
					/* no cols - lets create one */
					self.colConditions.push(sourceCI);
					self.rowConditions.splice(sourceI, 1);
					if (!autoPaging) {
						self.preGoWhenMoveTopFilter(conditionIndex);
					} else {
						self.preGoWhenFilterByTopFilter(false)
					}
					self.go(self);
					return;
				}
				if (targetCI == -2) {
					/* no rows - lets create one */
					self.rowConditions.push(sourceCI);
					self.colConditions.splice(sourceI, 1);
					if (!autoPaging) {
						self.preGoWhenMoveTopFilter(conditionIndex);
					} else {
						self.preGoWhenFilterByTopFilter(false)
					}
					self.go(self);
					return;
				}
				if (sourceType == targetType) {
					/* same condition type */
					if (sourceI + 1 == targetI) {
						/* dragged on condition immediately after */
						targetType.splice(targetI + 1, 0, sourceCI);
						targetType.splice(sourceI, 1);
					} else {
						targetType.splice(sourceI, 1);
						targetType.splice(targetI, 0, sourceCI);
					}
				} else {
					/* different condition type */
					sourceType.splice(sourceI, 1);
					targetType.splice(targetI, 0, sourceCI);
				}
				if (!self.serverPagination) {
					self.go(false);
				} else {
					self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, self.conditions[conditionIndex].dataField, "", "", "")
				}
			}
		}


		this.getOrderReferenceProg = function (conditionIndex) { // ** move a row or column to filter bar programatically---


			if ((self.conditions[conditionIndex].validPosition != undefined) && (self.conditions[conditionIndex].validPosition.indexOf("filters") == -1)) {
				return;
			}

			self.stateChanged = true
			if (self.filterIndexes.indexOf(conditionIndex) < 0) {
				self.filterIndexes.push(conditionIndex);
			}
			self.conditions[conditionIndex].blackList = [];
			for (var i = 0; i < self.rowConditions.length; i++) {
				if (self.rowConditions[i] == conditionIndex) { self.rowConditions.splice(i, 1); }
			}
			for (var i = 0; i < self.colConditions.length; i++) {
				if (self.colConditions[i] == conditionIndex) { self.colConditions.splice(i, 1); }
			}

			if (!self.serverPagination) {
				if (!self.autoPaging) {
					self.preGoWhenMoveTopFilter(conditionIndex);
				} else {
					self.preGoWhenFilterByTopFilter(false)
				}
			}
			self.onDragundDropEventHandle(conditionIndex, "filters") //call event

			self.DiseablePivot();
			setTimeout(function () {
				if (!self.serverPagination) {
					self.go(false);
				} else {
					self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, self.conditions[conditionIndex].dataField, { op: "all", value: "", dim: conditionIndex }, "", "")
				}
				self.EneablePivot();
			}, 200)
			return;



		}

		this.getClickReference = function (cond, dimensionNumber, contentDiv) {
			var anchorRef = OAT.Anchor.assign(contentDiv, {
				title: " ",
				content: self.propPage,
				result_control: false,
				activation: "click",
				type: OAT.WinData.TYPE_RECT,
				width: "auto",
				containerQuery: qv.util.GetContainerControlClass(self.QueryViewerCollection[self.IdForQueryViewerCollection]) + " FilterPopup "
			});

			jQuery(contentDiv).data('anchorRef', anchorRef);

			var refresh = function () {
				self.propPage._Instant_hide();
				self.go(false);
			}
			return [function (event) {

				self.ShowPopUp(cond, dimensionNumber, event);

			}, anchorRef]
		}

		this.ShowPopUp = function (cond, dimensionNumber, event) {

			var refresh = function () {
				jQuery(".oat_winrect_container").css({ display: "none" });
			}
			var eventDiv;
			var coords;
			if (event.currentTarget != undefined) {
				eventDiv = event.currentTarget;
				coords = OAT.Dom.eventPos(event);
			} else {
				eventDiv = event[2]
				coords = [event[0], event[1]]
			}
			var toAppend = [];

			self.propPage.style.left = coords[0] + "px";
			self.propPage.style.top = coords[1] + "px";


			if (self.isSD) { //android
				jQuery(".oat_winrect_container").css({ left: "-1500px", top: jQuery(eventDiv).offset().top + "px" })
				jQuery(".oat_winrect_container").addClass("oat_winrect_container_small")
			} else {
				jQuery(".oat_winrect_container").css({ left: jQuery(eventDiv).offset().left + "px", top: jQuery(eventDiv).offset().top + "px" })
			}

			self.propPage.setAttribute('id', 'pop-up');
			self.propPage.setAttribute('class', 'oatpop-up');
			OAT.Dom.clear(self.propPage);
			toAppend.push(self.propPage);
			/* contents */


			jQuery(".oat_winrect_title").find(".winrect_title_label").remove()

			var spantitle = OAT.Dom.create("label");
			if (self.isSD) {
				spantitle.setAttribute("class", "winrect_title_label winrect_title_label_small");
			} else {
				spantitle.setAttribute("class", "winrect_title_label");
			}
			OAT.addTextNode(spantitle, self.columns[dimensionNumber].getAttribute("displayName"));
			jQuery(".oat_winrect_title").append(spantitle)


			if (!disableColumnSort) {
				var div_order = document.createElement("div");
				div_order.setAttribute("class", "first_popup_subdiv");

				var asc = OAT.Dom.radio("order");
				var ascForId = "pivot_order_asc" + "_" + self.containerName + "_" + self.columns[dimensionNumber].getAttribute("dataField");
				asc.id = ascForId;
				OAT.Dom.attach(asc, "change", function () {
					try {
						var datastr = "<DATA event=\"OrderChanged\" name=\"" + self.columns[dimensionNumber].getAttribute("name") + "\" displayName=\"" + self.columns[dimensionNumber].getAttribute("displayName") + "\"  order=\"ascending\">"
						datastr = datastr + "</DATA>"
						if (qv.util.isGeneXusPreview())
							window.external.SendText(self.QueryViewerCollection[self.IdForQueryViewerCollection].ControlName, datastr);
					} catch (error) { }

					if (self.serverPagination) {
						cond.sort = 1; self.stateChanged = true;
						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, cond.dataField, "", "", "")
						var idI = "i_" + this.getAttribute("id");
						var inputAsc = document.getElementById(idI);
						inputAsc.textContent = "radio_button_checked";
						var inputDsc = document.getElementById(idI.replace("asc", "desc"));
						inputDsc.textContent = "radio_button_unchecked";
					} else {
						if ((cond.sort == 0) || (cond.sort == 2)) cond.sort = 0
						else cond.sort = 1;
						self.stateChanged = true; self.sort(cond, dimensionNumber);

						self.DiseablePivot();
						setTimeout(function () {
							self.go(false);
							self.EneablePivot();
						}, 200)

					}
				});
				div_order.appendChild(asc);

				var IStyle = gx.util.browser.isIE() ? "top:-10px;" : ""; 

				var alabel = OAT.Dom.create("label");
				alabel.htmlFor = ascForId;
				div_order.appendChild(alabel);
				div_order.appendChild(OAT.Dom.create("br"));
				OAT.addImageNode(alabel, (cond.sort == 1)?"radio_button_checked":"radio_button_unchecked", IStyle, "i_"+ascForId);
				OAT.addTextNode(alabel, gx.getMessage("GXPL_QViewerJSAscending"))
				
				var desc = OAT.Dom.radio("order");
				var dscForId = "pivot_order_desc" + "_" + self.containerName + "_" + self.columns[dimensionNumber].getAttribute("dataField");
				desc.id = dscForId;
				OAT.Dom.attach(desc, "change", function () {
					try {
						var datastr = "<DATA event=\"OrderChanged\" name=\"" + self.columns[dimensionNumber].getAttribute("name") + "\" displayName=\"" + self.columns[dimensionNumber].getAttribute("displayName") + "\"  order=\"descending\">"
						datastr = datastr + "</DATA>"
						if (qv.util.isGeneXusPreview())
							window.external.SendText(self.QueryViewerCollection[self.IdForQueryViewerCollection].ControlName, datastr);
					} catch (error) { }


					if (self.serverPagination) {
						cond.sort = -1; self.stateChanged = true;
						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, cond.dataField, "", "", "")
						var idI = "i_" + this.getAttribute("id");
						var inputDsc = document.getElementById(idI);
						inputDsc.textContent = "radio_button_checked";
						var inputAsc = document.getElementById(idI.replace("desc", "asc"));
						inputAsc.textContent = "radio_button_unchecked";
						
					} else {
						if ((cond.sort == 0) || (cond.sort == 2)) cond.sort = 2;
						else cond.sort = -1;
						self.stateChanged = true; self.sort(cond, dimensionNumber);
						if (!self.serverPagination) {
							self.updateSortImage(eventDiv.firstChild.children[1], 2);
						}
						self.DiseablePivot();
						setTimeout(function () {
							self.go(false);
							self.EneablePivot();
						}, 200)
					}
				});
				div_order.appendChild(desc);

				var dlabel = OAT.Dom.create("label");
				dlabel.htmlFor = dscForId;
				div_order.appendChild(dlabel);
				OAT.addImageNode(dlabel, (cond.sort == 1)?"radio_button_unchecked":"radio_button_checked", IStyle, "i_"+dscForId);
				OAT.addTextNode(dlabel, gx.getMessage("GXPL_QViewerJSDescending"))
				

				toAppend.push(div_order);

				var hr1 = OAT.Dom.create("hr", {});
				toAppend.push(hr1);
			}

			var hr2 = OAT.Dom.create("hr", {});
			var hr4 = OAT.Dom.create("hr", {});

			if (((cond.hideSubtotalOption === undefined) || (!cond.hideSubtotalOption))
				&& ((!self.autoPaging) || (self.colConditions.length == 0))
			) {
				var subtotals = OAT.Dom.create("div");
				if (disableColumnSort) {
					subtotals.setAttribute("class", "first_popup_subdiv");
				}
				var subtotal_sel_div = document.createElement("div");
				var class_check_div = (cond.subtotals) ? "check_item_img" : "uncheck_item_img";
				if (self.isSD) { //android
					var class_check_div = (cond.subtotals) ? "check_item_img_small" : "uncheck_item_img_small";
				}
				subtotal_sel_div.setAttribute("class", class_check_div);
				OAT.Dom.attach(subtotal_sel_div, "click", function () {
					var checkedClass = "check_item_img"
					var unCheckedClass = "uncheck_item_img"
					if (self.isSD) { //android
						checkedClass = "check_item_img_small"
						unCheckedClass = "uncheck_item_img_small"
					}

					cond.subtotals = !(this.getAttribute("class") === checkedClass);
					var newClass = (this.getAttribute("class") === checkedClass) ? unCheckedClass : checkedClass;
					this.setAttribute("class", newClass);
					jQuery(this).find("i")[0].textContent = cond.subtotals ? "check_box" : "check_box_outline_blank";
					self.stateChanged = true;
					
					try {
						var datastr = "<DATA event=\"SubtotalsChanged\" name=\"" + self.columns[dimensionNumber].getAttribute("name") + "\" displayName=\"" + self.columns[dimensionNumber].getAttribute("displayName") + "\"  subtotals=\"" + cond.subtotals + "\">"
						datastr = datastr + "</DATA>"
						if (qv.util.isGeneXusPreview())
							window.external.SendText(self.QueryViewerCollection[self.IdForQueryViewerCollection].ControlName, datastr);
					} catch (error) { }

					if (self.autoPaging) {
						self.DiseablePivot();
						setTimeout(function () {
							createPaginationInfo(self, self.RowsWhenMoveToFilter); self.go(false);
							self.EneablePivot();
						}
							, 500)
					} else if (!self.serverPagination) {
						self.DiseablePivot();
						setTimeout(function () {
							self.go(false);
							self.EneablePivot();
						}, 500)
					} else {
						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, cond.dataField, "", "", "")
					}
				});

				var sl = OAT.Dom.create("label");
				
				OAT.addImageNode(sl, cond.subtotals ? "check_box" : "check_box_outline_blank", "");
				
				OAT.addTextNode(sl, gx.getMessage("GXPL_QViewerJSSubtotals"))
				sl.htmlFor = "pivot_checkbox_subtotals";
				subtotal_sel_div.appendChild(sl);
				OAT.Dom.append([subtotals, subtotal_sel_div]);
				toAppend.push(subtotals);
				toAppend.push(hr2);
			}

			if (self.stateChanged) {
				var restoreview = OAT.Dom.create("div");
				var restoreview_sel_div = document.createElement("div");

				OAT.Dom.attach(restoreview_sel_div, "click", function () {
					if ((!self.autoPaging) && (!self.serverPagination)) {
						self.cleanState();
						for (var c = 0; c < self.conditions.length; c++) {
							self.sort(self.conditions[c], c)
						}
						cond.subtotals = true;

						self.DiseablePivot();
						setTimeout(function () {
							self.EneablePivot();
							self.go(false);
							refresh(); self.stateChanged = false;

							self.EneablePivot();
						}, 200)
					} else if (!self.serverPagination) {
						self.cleanState();
						for (var c = 0; c < self.conditions.length; c++) {
							self.sort(self.conditions[c], c)
						}
						if (jQuery("#" + self.containerName + " #tablePagination_currPage")[0] != undefined) {
							jQuery("#" + self.containerName + " #tablePagination_currPage")[0].value = 1;
						}
						self.actualPaginationPage = 1;
						self.DiseablePivot();
						setTimeout(function () {
							self.preGo(false, null, null, -1);
							refresh(); self.stateChanged = false;

							self.EneablePivot();
						}, 200)
					} else {
						self.cleanStateWhenServerPagination();
						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, cond.dataField, "", "", "")
						refresh(); self.stateChanged = false;
					}
				});


				var rl = OAT.Dom.create("label");
				OAT.addTextNode(rl, gx.getMessage("GXPL_QViewerJSRestoreDefaultView"))
				rl.htmlFor = "pivot_checkbox_restoreview";
				restoreview_sel_div.appendChild(rl);
				OAT.Dom.append([restoreview, restoreview_sel_div]);
				toAppend.push(restoreview);
			}

			var appendActionsSeparator = false;

			/* for pivoting purpuses*/
			if (measures.length > 0) {
				var pivotpurp = OAT.Dom.create("div");
				var pivotpurp_sel_div = document.createElement("div");

				OAT.Dom.attach(pivotpurp_sel_div, "click", function () {
					if ((!self.autoPaging) && (!self.serverPagination)) {
						self.stateChanged = true; self.changedFromColumnToRow(dimensionNumber);

						self.DiseablePivot();
						setTimeout(function () {
							self.go(false); refresh();
							self.EneablePivot();
						}, 200)
					} else if (!self.serverPagination) {
						if (self.columns.length < 4) {
							self.stateChanged = true; self.changedFromColumnToRow(dimensionNumber);

							self.DiseablePivot();
							setTimeout(function () {
								self.preGo(false, null, null, -1);
								self.distinctDivs(self.conditions[dimensionNumber], distinct, dimensionNumber);
								refresh();
								self.EneablePivot();
							}, 200)
						}
					} else {
						self.stateChanged = true;
						self.changedFromColumnToRow(dimensionNumber);
						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, cond.dataField, "", "", "")
						refresh();
					}
				});

				var pvpl = OAT.Dom.create("label");
				if (self.rowConditions.findIndex(dimensionNumber) != -1)
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerJSPivotDimensionToColumn"))
				else
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerJSPivotDimensionToRow"))

				pvpl.htmlFor = "pivot_checkbox_restoreview";

				pivotpurp_sel_div.appendChild(pvpl);
				OAT.Dom.append([pivotpurp, pivotpurp_sel_div]);
				toAppend.push(pivotpurp);
				appendActionsSeparator = true;
			}
			/* end pivoting option*/

			/*for Ipad & Iphone move to top filter*/
			if (measures.length > 0) {
				var ua = navigator.userAgent.toLowerCase();
				var isAndroid = ua.indexOf("android") > -1;
				if (gx.util.browser.isIPad() || gx.util.browser.isIPhone() || isAndroid) {
					if (self.filterIndexes.findIndex(dimensionNumber) === -1) {
						var Ipadpurp = OAT.Dom.create("div");
						var Ipadpurp_sel_div = document.createElement("div");


						OAT.Dom.attach(Ipadpurp_sel_div, "click", function () {
							if (!self.serverPagination) {
								self.filterIndexes.push(dimensionNumber);
								self.conditions[dimensionNumber].blackList = [];
								for (var i = 0; i < self.rowConditions.length; i++) {
									if (self.rowConditions[i] == dimensionNumber) { self.rowConditions.splice(i, 1); }
								}
								for (var i = 0; i < self.colConditions.length; i++) {
									if (self.colConditions[i] == dimensionNumber) { self.colConditions.splice(i, 1); }
								}
								if (!self.autoPaging) {
									self.preGoWhenMoveTopFilter(dimensionNumber);
								} else {
									self.preGoWhenFilterByTopFilter(false)
								}
								self.go(false); refresh();
							} else {
								self.getOrderReferenceProg(dimensionNumber);
								refresh();
							}
						});

						var ippl = OAT.Dom.create("label");
						OAT.addTextNode(ippl, gx.getMessage("GXPL_QViewerJSMoveToFilterBar"))
						ippl.htmlFor = "pivot_checkbox_movetocolumn";
						Ipadpurp_sel_div.appendChild(ippl);

						OAT.Dom.append([Ipadpurp, Ipadpurp_sel_div]);
						toAppend.push(Ipadpurp);
						appendActionsSeparator = true;
					}
				}
			}
			/*end move to top filter*/

			if (appendActionsSeparator)
				toAppend.push(hr4);

			var distinct = OAT.Dom.create("div");
			distinct.setAttribute("class", "last_div_popup");
			var br1, br2, br3;
			if (!gx.util.browser.isIE()) {
				br1 = OAT.Dom.create("br"); var br2 = OAT.Dom.create("br"); var br3 = OAT.Dom.create("br");
			} else {
				br1 = OAT.Dom.create("span"); var br2 = OAT.Dom.create("span"); var br3 = OAT.Dom.create("span");
			}
			toAppend.push(distinct);

			OAT.Dom.append(toAppend);

			self.distinctDivs(cond, distinct, dimensionNumber);

			if (!disableColumnSort) {
				/* this needs to be here because of IE :/ */
				asc.checked = (cond.sort == 1) || (cond.sort == 0);
				asc.__checked = asc.checked;
				desc.checked = (cond.sort == -1) || (cond.sort == 2);
				desc.__checked = desc.checked;
			}


			//for smart device center pop-up
			if (self.isSD) {//android
				setTimeout(function () {

					var screenWidth = window.innerWidth;
					var initialPopUpWidth = jQuery(".oat_winrect_container")[0].clientWidth


					if (initialPopUpWidth == 0) {
						var last = jQuery(".oat_winrect_container").length;
						initialPopUpWidth = jQuery(".oat_winrect_container")[last - 1].clientWidth
					}


					if (initialPopUpWidth < 245) {
						initialPopUpWidth = 245
					}

					var padding = (screenWidth - initialPopUpWidth) / 2 + jQuery(window).scrollLeft()

					jQuery(".oat_winrect_container").css({ left: padding + "px", width: initialPopUpWidth + "px" })


				}, 50)
			}
		}
		
		this.updateRowConditions = function(dimensionNumber, measures, fromFilters){
			var addCol = false
			var unhiddenDim = self.initRowConditions.length + self.initColConditions.length <= self.rowConditions.length + self.colConditions.length
			if (unhiddenDim) addCol = true;
			
			var tempRowConditions = [];
			for (var nI = 0; nI < self.initRowConditions.length - (measures.length - 1); nI++) {
				if (self.initRowConditions[nI] == dimensionNumber) {
					tempRowConditions.push(dimensionNumber)
				}
				if (self.rowConditions.indexOf(self.initRowConditions[nI]) > -1) {
					tempRowConditions.push(self.initRowConditions[nI])
				}
			}
			for (var nI = 0; nI < self.initColConditions.length; nI++) {
				if (self.initColConditions[nI] == dimensionNumber) {
					tempRowConditions.push(dimensionNumber)
				}
				if (self.rowConditions.indexOf(self.initColConditions[nI]) > -1) {
					tempRowConditions.push(self.initColConditions[nI])
				}
			}
			for (var nI = 0; nI < self.initFilterIndexes.length; nI++) {
				if (self.initFilterIndexes[nI] == dimensionNumber) {
					tempRowConditions.push(dimensionNumber)
				}
				if (self.rowConditions.indexOf(self.initFilterIndexes[nI]) > -1) {
					tempRowConditions.push(self.initFilterIndexes[nI])
				}
			}
			if (tempRowConditions.indexOf(dimensionNumber) < 0) {
					tempRowConditions.push(dimensionNumber)
			}
			if (addCol) {
				for (var nO = 0; nO < self.rowConditions.length; nO++){
					if (tempRowConditions.indexOf(self.rowConditions[nO]) < 0)
					{
						tempRowConditions.push(self.rowConditions[nO])
					}
				}
			}
			tempRowConditions.sort((function () {
				return function (a, b) {
					return (a == b ? 0 : (a < b ? -1 : 1));
				};
			})(0));
			for (var nI = self.initRowConditions.length - (measures.length - 1); nI < Math.min(self.initRowConditions.length , self.dataColumnIndex); nI++) {
				if (tempRowConditions.indexOf(self.initRowConditions[nI]) < 0)
					tempRowConditions.push(self.initRowConditions[nI])
			}

			self.rowConditions = [];
			for (var nI = 0; nI < tempRowConditions.length; nI++) {
				self.rowConditions[nI] = tempRowConditions[nI];
			}
		}
		
		this.changedFromColumnToRow = function (dimensionNumber) {

			var index = self.rowConditions.findIndex(dimensionNumber);
			var position = "columns";
			if (index != -1) { //when move to row
				self.rowConditions.splice(index, 1);
				if (measures.length > 1)
					self.colConditions = [dimensionNumber].concat(self.colConditions);
				else
					self.colConditions.push(dimensionNumber);
			} else {
				if (!self.serverPagination) {
					position = "rows";
					index = self.colConditions.findIndex(dimensionNumber);
					self.colConditions.splice(index, 1);
					if (measures.length > 1)
						self.rowConditions = [dimensionNumber].concat(self.rowConditions);
					else
						self.rowConditions.push(dimensionNumber);
				} else {
					position = "rows";
					index = self.colConditions.findIndex(dimensionNumber);
					self.colConditions.splice(index, 1);
					
					self.updateRowConditions(dimensionNumber, measures, false);
				}
			}

			self.onDragundDropEventHandle(dimensionNumber, position);
		}

		

		this.getDelFilterReference = function (index) {
			return function () {
				var idx = self.filterIndexes.findIndex(index);
				if (idx != -1) {
					self.filterIndexes.splice(idx, 1);
				}
				
				self.updateRowConditions(index, measures, true);
				
				for (var ifs = 0; ifs < self.filterDiv.selects.length; ifs++) {
					if (index == self.filterDiv.selects[ifs].filterIndex) {
						self.filterDiv.selects.splice(ifs, 1);
						break;
					}
				}

				self.stateChanged = true
				if (!self.serverPagination) {
					if (!self.autoPaging) {
						self.preGoWhenMoveTopFilter(-1);
					} else {
						self.preGoWhenFilterByTopFilter(false)
					}
				}
				self.onDragundDropEventHandle(index, "rows")

				self.DiseablePivot();
				setTimeout(function () {
					if (!self.serverPagination) {
						self.go(false);
					} else {
						self.conditions[index].topFilterValue = "[all]"
						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, self.conditions[index].dataField, { op: "all", values: "", dim: index }, "", "")
					}
					self.EneablePivot();
				}, 200)
			}
		}

		this.valueIsShowed = function (value, dimensionNumber) {
			if (!self.serverPagination) {
				for (var l = 0; l < self.filteredData.length; l++) {
					if (self.filteredData[l][dimensionNumber] === value) {
						return true;
					}
				}
				return false;
			} else {
				if (self.conditions[dimensionNumber].state == "all") {
					return true;
				} else if (self.conditions[dimensionNumber].state == "none") {
					return false;
				} else if (self.conditions[dimensionNumber].blackList.findIndex(value) != -1) {
					return false;
				} else if (self.conditions[dimensionNumber].distinctValues.findIndex(value) != -1) {
					return true;
				} else if (self.conditions[dimensionNumber].defaultAction == "Exclude") {
					return false;
				} else {
					return true;
				}
			}
		}

		this.distinctDivs = function (cond, div, dimensionNumber, allFilters) { /* set of distinct values checkboxes */
			var getPair = function (text, id) {
				var div = OAT.Dom.create("div");

				var checkedClass = "check_item_img"
				var unCheckedClass = "uncheck_item_img"
				if (self.isSD) {//android
					checkedClass = "check_item_img_small"
					unCheckedClass = "uncheck_item_img_small"
				}
				
				OAT.addImageNode(div, self.valueIsShowed(value, dimensionNumber) ? "check_box" : "check_box_outline_blank", "");

				var class_check_div = (cond.blackList.findIndex(value) == -1) && self.valueIsShowed(value, dimensionNumber) ? checkedClass : unCheckedClass;
				if (self.serverPagination) {
					var class_check_div = self.valueIsShowed(value, dimensionNumber) ? checkedClass : unCheckedClass;
				}
				div.setAttribute("class", class_check_div);
				var ch = OAT.Dom.create("input");
				ch.type = "checkbox";
				ch.id = id;
				var t = OAT.Dom.create("label");
				OAT.addTextNode(t, text)
				t.htmlFor = id;
				div.appendChild(t);
				return [div, ch];
			}


			var getRefBool = function (checked, value) {


				setTimeout(function () {

					if (self.serverPagination) {
						var oper = "pop";
						if (!checked) {
							oper = "push";
						}

						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, self.conditions[dimensionNumber].dataField, { op: oper, values: value, dim: dimensionNumber }, "", "")

						self.stateChanged = true;
						self.onFilteredChangedEventHandleWhenServerPagination(dimensionNumber);
						self.EneablePivot();
						return;
					}

					var splice = false;
					if (checked) {
						if (!self.autoPaging) {
							var index = cond.blackList.findIndex(value);
							if (index != -1) {
								cond.blackList.splice(index, 1);
							}

							if (self.autoPaging) {
								var index = cond.blackList.findIndex(value);
								while (index != -1) {
									cond.blackList.splice(index, 1);
									index = cond.blackList.findIndex(value);
								}
							}


							var whiteindex = cond.whiteList.findIndex(value);
							if ((index == -1)) {
								for (var rw = 0; rw < self.allData.length; rw++) { //search for columns or columns with that value in all data
									if (self.allData[rw][dimensionNumber] === value) {
										for (var it = 0; it < self.allData[rw].length; it++) {
											//is condition dimsension?
											if (it != dimensionNumber) {
												var indexCol = self.rowConditions.findIndex(it)
												if (indexCol != -1) {
													var colValue = self.allData[rw][it];
													while (self.conditions[indexCol].blackList.findIndex(colValue) != -1) {
														self.conditions[indexCol].blackList.splice(self.conditions[indexCol].blackList.findIndex(colValue), 1);
													}
												}
											}
										}
									}
								}
								cond.whiteList.push(value);
							}

							while (self.GreyList.findIndex(value) != -1) {
								index2 = self.GreyList.findIndex(value);
								self.GreyList.splice(index2, 1);
							}

							if (self.autoPaging) {
								splice = true;
							}
						} else { //add one item when autoPaging
							var index = self.conditions[dimensionNumber].blackList.findIndex(value);
							if (index != -1) {
								self.conditions[dimensionNumber].blackList.splice(index, 1);
							}

							var index = self.conditions[dimensionNumber].blackList.findIndex(value);
							while (index != -1) {
								self.conditions[dimensionNumber].blackList.splice(index, 1);
								index = self.conditions[dimensionNumber].blackList.findIndex(value);
							}

							var whiteindex = self.conditions[dimensionNumber].whiteList.findIndex(value);
							if ((index == -1)) {
								for (var rw = 0; rw < self.allData.length; rw++) { //search for columns or columns with that value in all data
									if (self.allData[rw][dimensionNumber] === value) {
										for (var it = 0; it < self.allData[rw].length; it++) {
											//is condition dimsension?
											if (it != dimensionNumber) {
												var indexCol = self.rowConditions.findIndex(it)
												if (indexCol != -1) {
													var colValue = self.allData[rw][it];
													while (self.conditions[indexCol].blackList.findIndex(colValue) != -1) {
														self.conditions[indexCol].blackList.splice(self.conditions[indexCol].blackList.findIndex(colValue), 1);
													}
												}
											}
										}
									}
								}
								self.conditions[dimensionNumber].whiteList.push(value);
							}

							while (self.GreyList.findIndex(value) != -1) {
								index2 = self.GreyList.findIndex(value);
								self.GreyList.splice(index2, 1);
							}

							if (self.autoPaging) {
								splice = true;
							}
						}
					} else {
						if (!self.autoPaging) {
							cond.blackList.push(value);
						} else {
							self.conditions[dimensionNumber].blackList.push(value);
						}
					}
					self.onFilteredChangedEventHandle(dimensionNumber);
					self.stateChanged = true;
					if (!self.autoPaging) {
						self.go(false);
					} else {
						if (jQuery("#" + self.containerName + " #tablePagination_currPage")[0] != undefined) {
							jQuery("#" + self.containerName + " #tablePagination_currPage")[0].value = 1;
							self.actualPaginationPage = 1;
						}
						if (!splice) {
							self.preGo(false, null, value, dimensionNumber);
						} else {
							self.preGo(false, null, value, -1);
						}
					}

					self.EneablePivot();
					//jQuery("#" + UcId + "_" + self.query + "_pivot_page").unblock()

				}, 200);

			}

			var allRef = function () {
				self.DiseablePivot();

				setTimeout(function () {


					if (self.serverPagination) {
						var oper = "all";
						//self.conditions[dimensionNumber].blackList = [];

						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, self.conditions[dimensionNumber].dataField, { op: oper, values: "", dim: dimensionNumber }, "", "")

						self.stateChanged = true;
						self.onFilteredChangedEventHandleWhenServerPagination(dimensionNumber);
						self.distinctDivs(cond, div, dimensionNumber);
						self.EneablePivot();
						return;
					}

					if (!self.autoPaging) {
						cond.blackList = [];
					} else {
						self.conditions[dimensionNumber].blackList = [];
					}
					self.stateChanged = true;
					self.onFilteredChangedEventHandle(dimensionNumber);
					if (!self.autoPaging) {
						self.go(false);
					} else {
						if (jQuery("#" + self.containerName + " #tablePagination_currPage")[0] != undefined) {
							jQuery("#" + self.containerName + " #tablePagination_currPage")[0].value = 1;
							self.actualPaginationPage = 1;
						}
						self.preGo(false, null, null, -1);
					}
					self.distinctDivs(cond, div, dimensionNumber);
					self.EneablePivot();
				}, 200)
			}

			var noneRef = function () {
				self.DiseablePivot()

				setTimeout(function () {
					if (self.serverPagination) {
						var oper = "none";
						/*self.conditions[dimensionNumber].blackList = [];
						for (var i = 0; i < self.conditions[dimensionNumber].distinctValues.length; i++) { 
							self.conditions[dimensionNumber].blackList.push(self.conditions[dimensionNumber].distinctValues[i]); 
						}*/

						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, self.conditions[dimensionNumber].dataField, { op: oper, values: "", dim: dimensionNumber }, "", "")

						self.stateChanged = true;
						self.onFilteredChangedEventHandleWhenServerPagination(dimensionNumber);
						self.distinctDivs(cond, div, dimensionNumber);
						self.EneablePivot();
						return;
					}
					cond.blackList = [];
					if (!self.autoPaging) {
						for (var i = 0; i < cond.distinctValues.length; i++) { cond.blackList.push(cond.distinctValues[i]); }
					} else {
						for (var i = 0; i < self.GeneralDistinctValues[dimensionNumber].length; i++) { self.conditions[dimensionNumber].blackList.push(self.GeneralDistinctValues[dimensionNumber][i]); }//cond.blackList.push(self.GeneralDistinctValues[dimensionNumber][i]); }
					}
					self.stateChanged = true;
					self.onFilteredChangedEventHandle(dimensionNumber);
					self.go(false);
					self.distinctDivs(cond, div, dimensionNumber);
					self.EneablePivot();
				}, 200)
			}

			var reverseRef = function () {
				self.DiseablePivot();

				setTimeout(function () {
					if (self.serverPagination) {
						var oper = "reverse";
						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, self.conditions[dimensionNumber].dataField, { op: oper, values: "", dim: dimensionNumber }, "", "")

						self.stateChanged = true;
						self.onFilteredChangedEventHandleWhenServerPagination(dimensionNumber);
						self.distinctDivs(cond, div, dimensionNumber);
						self.EneablePivot();
						return;
					}

					var newBL = [];
					if (!self.autoPaging) {
						for (var i = 0; i < cond.distinctValues.length; i++) {
							var val = cond.distinctValues[i];
							if (cond.blackList.findIndex(val) == -1) { newBL.push(val); }
						}
					} else {
						for (var i = 0; i < self.GeneralDistinctValues[dimensionNumber].length; i++) {
							var val = self.GeneralDistinctValues[dimensionNumber][i];
							if (self.conditions[dimensionNumber].blackList.findIndex(val) == -1) { newBL.push(val); }
						}
					}
					if (!self.autoPaging) {
						cond.blackList = newBL;
					} else {
						self.conditions[dimensionNumber].blackList = newBL;
					}
					self.stateChanged = true;
					self.onFilteredChangedEventHandle(dimensionNumber);

					if (!self.autoPaging) {
						self.go(false);
					} else {
						self.preGo(false, null, null, -1);
					}

					self.distinctDivs(cond, div, dimensionNumber);
					self.EneablePivot();
				}, 200)
			}

			var searchFilterClick = function () {
				self.getValuesForColumn(self.UcId, dimensionNumber, this.value)
			}

			OAT.Dom.clear(div);
			var d = OAT.Dom.create("div");
			d.setAttribute("class", "div_buttons_popup");
			var all = document.createElement("button");
			all.textContent = gx.getMessage("GXPL_QViewerJSAll");
			all.setAttribute("class", "btn");
			jQuery(all).click(allRef);

			var none = document.createElement("button");
			none.textContent = gx.getMessage("GXPL_QViewerJSNone");
			none.setAttribute("class", "btn");
			jQuery(none).click(noneRef);

			var reverse = document.createElement("button");
			reverse.textContent = gx.getMessage("GXPL_QViewerJSReverse");
			reverse.setAttribute("class", "btn");
			jQuery(reverse).click(reverseRef);


			OAT.Dom.append([d, all, none, reverse], [div, d]);

			if (self.serverPagination) {
				var d2 = OAT.Dom.create("div");
				d2.setAttribute("class", "div_filter_input");

				if (self.serverPagination) {
					var searchInput = document.createElement("input");
					searchInput.textContent = "none";
					searchInput.setAttribute("class", "search_input");
					searchInput.setAttribute("type", "text");
					searchInput.setAttribute("label", "Search filter...");
					searchInput.setAttribute("title", "Search filter...");
					searchInput.setAttribute("placeholder", "Search filter...");
					searchInput.setAttribute("id", self.UcId + dimensionNumber);
					jQuery(searchInput).keyup(searchFilterClick);

					OAT.Dom.append([d2, searchInput], [div, d2]);
				}
			}

			if (!self.autoPaging) {

				var fixHeigthDiv = OAT.Dom.create("div");
				if (self.serverPagination) {
					cond = self.conditions[dimensionNumber]
				}
				if (cond.distinctValues.length <= 9) {
					fixHeigthDiv.setAttribute("class", "pivot_popup_auto");
				} else {
					fixHeigthDiv.setAttribute("class", "pivot_popup_fix");
				}


				for (var i = 0; i < cond.distinctValues.length; i++) {

					var value = cond.distinctValues[i];
					if (!((self.serverPagination) && (self.conditions[dimensionNumber].hasNull) && (value.trimpivot() == self.defaultPicture.getAttribute("textForNullValues")))) {

						var pict_value = self.dimensionPictureValue(value, dimensionNumber);
						pict_value = pict_value.replace(/\&amp;/g, "&").replace(/\u00A0/g, " ")
						if (pict_value.length > 33) {
							var resto = (pict_value.substring(32, pict_value.length).trimpivot().length > 0) ? '...' : '';
							pict_value = pict_value.substring(0, 32) + resto
						}
						pict_value = pict_value.replace(/ /g, "\u00A0") + '\u00A0\u00A0\u00A0\u00A0\u00A0'
						var pair = getPair(pict_value, "pivot_distinct_" + i);
						pair[0].setAttribute('value', value);
						fixHeigthDiv.appendChild(pair[0]);



						OAT.Dom.attach(pair[0], "click", function () {
							self.DiseablePivot();

							var checkedClass = "check_item_img"
							var unCheckedClass = "uncheck_item_img"
							if (self.isSD) {//android
								checkedClass = "check_item_img_small"
								unCheckedClass = "uncheck_item_img_small"
							}

							var checked = !(this.getAttribute("class") === checkedClass);
							var newClass = (this.getAttribute("class") === checkedClass) ? unCheckedClass : checkedClass;
							this.setAttribute("class", newClass);
							
							jQuery(this).find("i")[0].textContent = checked ? "check_box" : "check_box_outline_blank";
							
							getRefBool(checked, this.getAttribute("value"));//this.textContent);            														
						});

					}
				}
				fixHeigthDiv.setAttribute("ucid", self.UcId);
				fixHeigthDiv.setAttribute("columnnumber", dimensionNumber);
				fixHeigthDiv.setAttribute("id", "values_" + self.UcId + "_" + dimensionNumber)
				div.appendChild(fixHeigthDiv);
			} else {

				var fixHeigthDiv = OAT.Dom.create("div");
				if (self.GeneralDistinctValues[dimensionNumber].length <= 9) {
					fixHeigthDiv.setAttribute("class", "pivot_popup_auto");
				} else {
					fixHeigthDiv.setAttribute("class", "pivot_popup_fix");
				}

				for (var i = 0; i < self.GeneralDistinctValues[dimensionNumber].length; i++) {
					var value = self.GeneralDistinctValues[dimensionNumber][i];
					var pict_value = self.dimensionPictureValue(value, dimensionNumber);
					try {
						if ((value == "#NuN#") && (!self.formulaInfo.measureFormula[dimensionNumber].hasFormula)) {
							pict_value = "&nbsp;"
						}
					} catch (Error) { }

					pict_value = pict_value.replace(/\&amp;/g, "&").replace(/\&nbsp;/g, " ")
					if (pict_value.length > 33) {
						var resto = (pict_value.substring(32, pict_value.length).trimpivot().length > 0) ? '...' : '';
						pict_value = pict_value.substring(0, 32) + resto
					}
					pict_value = pict_value.replace(/ /g, "&nbsp;") + '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'

					var pair = getPair(pict_value, "pivot_distinct_" + i);
					pair[0].setAttribute('value', value);
					fixHeigthDiv.appendChild(pair[0]);

					//opciones - esta o no entre los distinctValues, si esta se muesta o no, y si no esta aparece en  black list o no 	
					var checked_value = ((self.conditions[dimensionNumber].blackList.findIndex(value) == -1) && self.valueIsShowed(value, dimensionNumber) || ((self.conditions[dimensionNumber].distinctValues.findIndex(value) == -1) && (self.conditions[dimensionNumber].blackList.findIndex(value) == -1)));
					var class_check_div = (checked_value) ? "check_item_img" : "uncheck_item_img";
					if (self.isSD) {//android
						class_check_div = (checked_value) ? "check_item_img_small" : "uncheck_item_img_small";
					}
					pair[0].setAttribute("class", class_check_div);
					OAT.Dom.attach(pair[0], "click", function () {
						self.DiseablePivot();
						var checkedClass = "check_item_img"
						var unCheckedClass = "uncheck_item_img"
						if (self.isSD) {//android
							checkedClass = "check_item_img_small"
							unCheckedClass = "uncheck_item_img_small"
						}

						var checked = !(this.getAttribute("class") === checkedClass);
						var newClass = (this.getAttribute("class") === checkedClass) ? unCheckedClass : checkedClass;
						this.setAttribute("class", newClass);
						getRefBool(checked, this.getAttribute("value"));//this.textContent);            														
					});

				}
				div.appendChild(fixHeigthDiv);

			}
		}


		this.DiseablePivot = function () {
			try {
				var divDis = jQuery('<div class="disable_popup" ></div>');

				if (jQuery("#" + self.containerName).length > 0) {
					var ht = Math.min(jQuery("#" + UcId + "_" + self.query + "_pivot_page")[0].clientHeight
						+ jQuery("#" + UcId + "_" + self.query + "_pivot_content")[0].clientHeight,
						jQuery("#" + self.containerName)[0].clientHeight
					)
					var wd = Math.min(jQuery("#" + UcId + "_" + self.query)[0].clientWidth,
						jQuery("#" + self.containerName)[0].clientWidth
					)
					if (jQuery("#" + self.containerName).closest(".gxwebcomponent").length > 0) { //for gxQuery
						if (jQuery("#" + UcId + "_" + self.query + "_tablePagination").length > 0) {
							ht = ht + jQuery("#" + UcId + "_" + self.query + "_tablePagination")[0].clientHeight
						}
						jQuery(divDis).css({
							'width': wd,
							'height': ht,
							'position': 'absolute',
							'top': jQuery("#" + self.containerName)[0].offsetTop,//jQuery("#" + self.containerName)[0].offsetTop,
							'left': jQuery("#" + self.containerName)[0].offsetLeft,
							'background-color': 'rgba(0,0,0,0.1)',
							'cursor': 'wait',
							'z-index': 99
						});
					} else {
						jQuery(divDis).css({
							'width': wd,
							'height': ht,
							'position': 'absolute',
							'top': jQuery("#" + self.containerName)[0].offsetTop,//jQuery("#" + self.containerName).offset().top,//0 	
							'left': jQuery("#" + UcId + "_" + self.query).offset().left,
							'background-color': 'rgba(0,0,0,0.1)',
							'cursor': 'wait',
							'z-index': 999
						});
					}

					jQuery("#" + self.containerName).append(divDis)

				} else {
					var ht = Math.min(jQuery("#" + UcId + "_" + self.query).closest(".gx_usercontrol").find(".pivot_filter_div")[0].clientHeight
						+ jQuery("#" + UcId + "_" + self.query).closest(".conteiner_table_div")[0].clientHeight,
						jQuery("#" + UcId + "_" + self.query).closest(".gx_usercontrol")[0].clientHeight
					)

					var wd = Math.min(jQuery("#" + UcId + "_" + self.query)[0].clientWidth,
						jQuery("#" + UcId + "_" + self.query).closest(".gx_usercontrol")[0].clientWidth
					)

					if (jQuery("#" + UcId + "_" + self.query).closest(".gx_usercontrol").find(".pivot_pag_div").length > 0) {
						ht = ht + jQuery("#" + UcId + "_" + self.query).closest(".gx_usercontrol").find(".pivot_pag_div")[0].clientHeight
					}

					jQuery(divDis).css({
						'width': wd,
						'height': ht,
						'position': 'absolute',
						'top': jQuery("#" + UcId + "_" + self.query).closest(".gx_usercontrol")[0].offsetTop,
						'left': jQuery("#" + UcId + "_" + self.query).closest(".gx_usercontrol")[0].offsetLeft,
						'background-color': 'rgba(0,0,0,0.1)',
						'cursor': 'wait',
						'z-index': 99
					});

					jQuery("#" + UcId + "_" + self.query).closest(".gx_usercontrol").append(divDis)
				}
				jQuery(".oat_winrect_container").block({ message: null })
			} catch (ERROR) { }
		}

		this.EneablePivot = function () {
			jQuery(".disable_popup").remove()
			while (jQuery(".disable_popup").length > 0) {
				jQuery(".disable_popup").remove()
			}
			jQuery(".oat_winrect_container").unblock()
		}

		this.addExpandCollapseFunctionality = function (th, item, rowConditionNumber, expanded, rowDimension) {
			if (true) {
				var divImg = OAT.Dom.create("div", { });

				if (expanded) {
					divImg.className += " expanded";
					OAT.addImageNode(divImg, "indeterminate_check_box", "");
				} else {
					divImg.className += " collapsed";
					OAT.addImageNode(divImg, "add_box", "");
				}
				th.insertBefore(divImg, th.firstChild);
				th.style.paddingLeft = "0px";

				var spanTxt = jQuery(th).find("#span_txt_pivot")[0]


				if (rowDimension) {
					self.setExpandCollapseEventHandlers(divImg, item.value, "DIMENSION", self.rowConditions[rowConditionNumber], item);
					if ((self.QueryViewerCollection[self.IdForQueryViewerCollection].ItemDoubleClick == undefined) &&
						(self.QueryViewerCollection[self.IdForQueryViewerCollection].ItemClick == undefined) &&
						(!self.selection.Allow)) {
						self.setExpandCollapseEventHandlers(spanTxt, item.value, "DIMENSION", self.rowConditions[rowConditionNumber], item);
						jQuery(spanTxt).css({ cursor: "pointer" });
					}
				} else {
					self.setExpandCollapseEventHandlers(divImg, item.value, "DIMENSION", self.colConditions[rowConditionNumber], item);
					if ((self.QueryViewerCollection[self.IdForQueryViewerCollection].ItemDoubleClick == undefined) &&
						(self.QueryViewerCollection[self.IdForQueryViewerCollection].ItemClick == undefined) &&
						(!self.selection.Allow)) {
						self.setExpandCollapseEventHandlers(spanTxt, item.value, "DIMENSION", self.colConditions[rowConditionNumber], item);
						jQuery(spanTxt).css({ cursor: "pointer" });
					}
				}

			}
			return th;
		}

		this.setClickEventHandlers = function (td, itemValue, MeasureOrDimension, dimensionNumber, itemData) {
			if ((!self.ShowMeasuresAsRows) || (self.h < 500)) {
				var span = jQuery(td).find("#span_txt_pivot")[0];
				if (span) {
					jQuery(span).data('itemValue', itemValue);
					jQuery(span).data('typeMorD', MeasureOrDimension);
					jQuery(span).data('numberMorD', dimensionNumber);
					jQuery(span).data('itemInfo', itemData);
					
					
					jQuery(td).data('itemValue', itemValue);
					jQuery(td).data('typeMorD', MeasureOrDimension);
					jQuery(td).data('numberMorD', dimensionNumber);
					jQuery(td).data('itemInfo', itemData);
					
				
					var qViewer = self.QueryViewerCollection[IdForQueryViewerCollection];
					var raiseItemClick = MeasureOrDimension == "DIMENSION" ? qViewer.Metadata.Axes[dimensionNumber].RaiseItemClick : qViewer.Metadata.Data[dimensionNumber].RaiseItemClick;
					
					if (qViewer.ItemClick && raiseItemClick) {
						span.onclick = function () { 
							self.onClickEventHandle(this); 
							if (self.selection.Allow){ 
								self.onClickSelectNode(this);
							}
						}
						span.classList.add("gx-qv-clickable-element")
					} else if (self.selection.Allow){ 
						span.onclick = function () { 
							self.onClickSelectNode(this); 
						} 
					}	
				}
			}
		}

		this.setExpandCollapseEventHandlers = function (td, itemValue, MeasureOrDimension, dimensionNumber, itemData) {
			if ((!self.ShowMeasuresAsRows) || (self.h < 500)) {
				jQuery(td).data('itemValue', itemValue);
				//jQuery(td).data('typeMorD', MeasureOrDimension);
				jQuery(td).data('numberMorD', dimensionNumber);
				jQuery(td).data('itemInfoEC', itemData);
				td.onclick = function () { 
					self.onClickExpandCollapse(this); 
				}
			}
		}

		this.getPerFilterValue = function (prevFilterSelectedValue, actualfilterIndex) {
			var hayfiltro = false;
			for (var i = 0; i < prevFilterSelectedValue.length; i++) {
				if (prevFilterSelectedValue[i] != null) {
					hayfiltro = true;
				}
			}
			if (!hayfiltro) return false;

			var distinctPerFilterValue = [];
			for (var i = 0; i < self.GeneralDataRows.length; i++) { //for each row
				var coincide = true;
				for (var j = 0; j < prevFilterSelectedValue.length; j++) {
					if (prevFilterSelectedValue[j] != null) {
						if (self.GeneralDataRows[i][self.filterIndexes[j]] != prevFilterSelectedValue[j]) {
							coincide = false;
						}
					}
				}
				if (coincide) {
					distinctPerFilterValue.push(self.GeneralDataRows[i][self.filterIndexes[actualfilterIndex]])
				}
			}

			return distinctPerFilterValue;

		}

		this.drawFilters = function () {
			var savedValues = [];
			var div = self.filterDiv;

			var ua = navigator.userAgent.toLowerCase();
			var isAndroid = ua.indexOf("android") > -1;
			if ((gx.util.browser.isIE()) || (isAndroid)) {
				self.filterDiv.className += " pivot_filter_div";
			} else {
				self.filterDiv.classList.add("pivot_filter_div");
			}
			if (self.filterIndexes.length == 0) {
				OAT.addTextNode(self.filterDiv, "drop filters here")
			}

			for (var i = 0; i < div.selects.length; i++) {
				savedValues.push([div.selects[i].filterIndex, div.selects[i].selectedIndex, div.selects[i].value]);
			}
			OAT.Dom.clear(div);
			self.gd.addTarget(div);
			div.selects = [];
			if (!self.filterIndexes.length) {
				var strng = gx.getMessage("GXPL_QViewerJSDropFiltersHere");
				//if(gx.util.browser.isIPad() || gx.util.browser.isIPhone()) {
				if (self.isSD) {
					strng = "";
				}
				var ua = navigator.userAgent.toLowerCase();
				var isAndroid = ua.indexOf("android") > -1; //&& ua.indexOf("mobile");
				if (isAndroid) {
					strng = "";
				}


				if ((strng[strng.length - 1] === "\"") || (strng[strng.length - 1] === "'") || (strng[strng.length - 1] === "]") || (strng[strng.length - 1] === "}") || (strng[strng.length - 1] === "`")) {
					strng = strng.substring(0, strng.length - 1);
				}

				var spanText = document.createElement('span')
				spanText.textContent = strng;

				div.appendChild(spanText);
			}

			var loadItems = function () {
				var s = this;
				var actualValues = self.conditions[this.filterIndex].distinctValues;
				for (var j = 0; j < actualValues.length; j++) {
					var v = actualValues[j];
					if (self.conditions[this.filterIndex].filteredShowValues.indexOf(v) == -1) {
						self.conditions[this.filterIndex].filteredShowValues.push(v);
						if (v != "#NuN#") {
							try {
								OAT.Dom.option(self.dimensionPictureValue(v, this.filterIndex), v, s);
							} catch (Error) {
								OAT.Dom.option(v, v, s);
							}
						} else {
							OAT.Dom.option(" ", v, s);
						}
					}
				}
				//load all other items
				self.lastRequestValue = this.filterIndex; var columnNumber = this.filterIndex;
				if (self.conditions[columnNumber].previousPage < self.conditions[columnNumber].totalPages) {
					self.QueryViewerCollection[self.IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
						var data = JSON.parse(resJSON);

						self.conditions[columnNumber].previousPage = data.PageNumber
						self.conditions[columnNumber].totalPages = data.PagesCount
						self.conditions[columnNumber].blocked = true
						//null value?
						if ((data.Null) && (!self.conditions[columnNumber].hasNull)) {
							self.conditions[columnNumber].hasNull = true;
							if (self.conditions[columnNumber].distinctValues.indexOf("#NuN#") == -1) {
								self.conditions[columnNumber].distinctValues.push("#NuN#")
							}
							if (self.conditions[columnNumber].defaultAction == "Include") {
								if (self.conditions[columnNumber].visibles.indexOf("#NuN#") == -1) {
									self.conditions[columnNumber].visibles.push("#NuN#");
								}
							} else {
								if (self.conditions[columnNumber].blackList.indexOf("#NuN#") == -1) {
									self.conditions[columnNumber].blackList.push("#NuN#");
								}
							}
						}

						for (var i = 0; i < data.NotNullValues.length; i++) {
							var value = data.NotNullValues[i]
							if (self.conditions[columnNumber].distinctValues.indexOf(value) == -1) {
								self.conditions[columnNumber].distinctValues.push(value)

								if ((self.conditions[columnNumber].defaultAction == "Include")
									&& (self.conditions[columnNumber].visibles.indexOf(value) == -1)) {
									self.conditions[columnNumber].visibles.push(value)
								}
								if ((self.conditions[columnNumber].state == "Exclude")
									&& (self.conditions[columnNumber].blackList.indexOf(value) == -1)) {
									self.conditions[columnNumber].blackList.push(value)
								}
							}
						}

						var actualValues = self.conditions[columnNumber].distinctValues;
						for (var j = 0; j < actualValues.length; j++) {
							var v = actualValues[j];
							if (self.conditions[columnNumber].filteredShowValues.indexOf(v) == -1) {
								self.conditions[columnNumber].filteredShowValues.push(v);
								if (v != "#NuN#") {
									try {
										OAT.Dom.option(self.dimensionPictureValue(v, columnNumber), v, s);
									} catch (Error) {
										OAT.Dom.option(v, v, s);
									}
								} else {
									OAT.Dom.option(" ", v, s);
								}
							}
						}

					}).closure(this), [self.columns[this.filterIndex].getAttribute("dataField"), 1, 0, ""]);
				}
			}
			var callgo = function () {
				self.stateChanged = true
				if (self.serverPagination) {
					self.DiseablePivot();
					self.conditions[this.filterIndex].topFilterValue = this.value
					self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, self.conditions[this.filterIndex].dataField, { op: "pagefilter", values: this.value, dim: this.filterIndex }, "", "")
					self.EneablePivot();
					return;
				} else {
					if (this.value == "[all]"/*""*/)//selected option [all]
					{
						if (!self.autoPaging) {
							self.preGoWhenMoveTopFilter(this.filterIndex)
						} else {
							self.preGoWhenFilterByTopFilter(false)
						}
					}
					else {
						self.preGoWhenFilterByTopFilter(false);
					}
					self.actualPaginationPage = 1
				}
				self.DiseablePivot();

				setTimeout(function () {
					self.go(false);
					self.EneablePivot();
				}, 200)
			}
			var prevFilterSelectedValue = [];
			var loaded = [];
			for (var i = 0; i < self.filterIndexes.length; i++) {
				if (loaded.indexOf(self.filterIndexes[i]) < 0) {
					loaded.push(self.filterIndexes[i])
					var index = self.filterIndexes[i];
					var s = OAT.Dom.create("select");
					s.setAttribute("id", "page_select_" + i)
					OAT.Dom.option(gx.getMessage("GXPL_QViewerJSAllOption")/*"[all]"*/, "[all]"/*""*/, s);

					var actualValues;
					if (self.serverPagination) {
						actualValues = []
					} else {
						actualValues = self.getPerFilterValue(prevFilterSelectedValue, i);
					}

					if (self.GeneralDistinctValues.length > 0) {
						for (var j = 0; j < self.GeneralDistinctValues[index].length; j++) {
							var v = self.GeneralDistinctValues[index][j];
							if (!actualValues) {
								if (v != "#NuN#") {
									try {
										OAT.Dom.option(self.dimensionPictureValue(v, index), v, s);
									} catch (Error) {
										OAT.Dom.option(v, v, s);
									}
								} else {
									OAT.Dom.option(" ", v, s);
								}
							} else {
								if (actualValues.indexOf(v) != -1) {
									if (v != "#NuN#") {
										try {
											OAT.Dom.option(self.dimensionPictureValue(v, index), v, s);
										} catch (Error) {
											OAT.Dom.option(v, v, s);
										}
									} else {
										OAT.Dom.option(" ", v, s);
									}
								}
							}
						}

						try {
							var pos = 0;
							for (var j = 0; j < self.GeneralDistinctValues[index].length; j++) {
								var v = self.GeneralDistinctValues[index][j];
								if (self.conditions[index].topFilterValue === v) {
									s.selectedIndex = pos + 1;
								}
								if (!actualValues) {
									pos++;
								} else {
									if (actualValues.indexOf(v) != -1) {
										pos++;
									}
								}
							}
						} catch (error) {

						}
					}

					if (self.serverPagination) {
						self.conditions[index].filteredShowValues = []
						var actualValues = self.conditions[index].distinctValues;
						for (var j = 0; j < actualValues.length; j++) {
							var v = actualValues[j];
							if (self.conditions[index].filteredShowValues.indexOf(v) == -1) {
								self.conditions[index].filteredShowValues.push(v);
								if (v != "#NuN#") {
									try {
										OAT.Dom.option(self.dimensionPictureValue(v, index), v, s);
									} catch (Error) {
										OAT.Dom.option(v, v, s);
									}
								} else {
									OAT.Dom.option(" ", v, s);
								}
							}
						}
						if ((self.conditions[index].topFilterValue != "[all]") /*&& (self.conditions[index].topFilterValue!="")*/) {
							var v = self.conditions[index].topFilterValue
							if (self.conditions[index].filteredShowValues.indexOf(v) != -1) { //value already load
								s.selectedIndex = self.conditions[index].filteredShowValues.indexOf(v) + 1
							} else {
								self.conditions[index].filteredShowValues.push(v);
								if (v != "#NuN#") {
									try {
										OAT.Dom.option(self.dimensionPictureValue(v, index), v, s);
									} catch (Error) {
										OAT.Dom.option(v, v, s);
									}
								} else {
									OAT.Dom.option(" ", v, s);
								}
								s.selectedIndex = 1
							}
						}
					}

					s.filterIndex = index;
					for (var j = 0; j < savedValues.length; j++) {
						if (savedValues[j][0] == index) {
							for (var it = 0; it < s.length; it++) {
								if (s[it].value == savedValues[j][2]) {
									s.selectedIndex = it
								}
							}
						}
					}

					if (s.selectedIndex > 0) {
						prevFilterSelectedValue[i] = s.value;
					} else {
						prevFilterSelectedValue[i] = null
					}

					if (self.serverPagination) {
						OAT.Dom.attach(s, "click", loadItems);
					}
					OAT.Dom.attach(s, "change", callgo);
					div.selects.push(s);
					var d = OAT.Dom.create("div");
					d.setAttribute("class", "inner_filter_div");

					OAT.addTextNode(d, self.headerRow[index] + ":\u00A0")


					var close = document.createElement("div");
					close.setAttribute("class", "close_span_filter");
					OAT.addImageNode(close, "close", "");
					
					close.style.cursor = "pointer";
					var ref = self.getDelFilterReference(index);
					OAT.Dom.attach(close, "click", ref);

					if (self.serverPagination) {
						OAT.Dom.append([self.filterDiv, d], [d, s, close]);
					} else if (self.GeneralDataRows.length == 0) {
						OAT.Dom.append([self.filterDiv, d], [d, s]);
					} else {
						OAT.Dom.append([self.filterDiv, d], [d, s, close]);
					}
				}
			}


			//draw export image and pop up of export options
			var exportImg = OAT.Dom.create("div");
			exportImg.href = "#";
			if (self.isSD) {//android
				exportImg.setAttribute("class", "exportOptionsAnchor exportOptionsAnchor_small");
			} else {
				exportImg.setAttribute("class", "exportOptionsAnchor");
			}
			
			OAT.addImageNode(exportImg, "menu", "")
			
			self.exportPage = OAT.Dom.create("div", {});
			var checkToClose = function (b) {
				source = OAT.Event.source(b);
				var clean = false;
				var closing = false;
				for (var i = 0; i < jQuery(".oat_winrect_container").length; i++) {
					var obj = jQuery(".oat_winrect_container")[i];
					if (!(source == obj) && !OAT.Dom.isChild(source, obj)) {
						clean = true;
					} else {
						clean = false; break;
					}
				}
				for (var i = 0; i < jQuery(".oat_winrect_container").length; i++) {
					if (jQuery(".oat_winrect_container")[i].style.display != "none") {
						closing = true;
					}
				}
				if ((self.serverPagination) &&
					((source.getAttribute("class") == "oat_winrect_close_b") || (!OAT.Dom.isChild(source, obj))) &&
					(closing)) {
					self.resetAllScrollValue(self.UcId);
				}
				if (clean) {
					jQuery(".oat_winrect_container").css({ display: "none" });
				}
			};

			OAT.Dom.attach(document, "mousedown", checkToClose)


			OAT.Anchor.assign(exportImg, {
				title: " ",
				content: self.exportPage,
				result_control: false,
				activation: "click",
				type: OAT.WinData.TYPE_RECT,
				width: "auto",
				containerQuery: qv.util.GetContainerControlClass(self.QueryViewerCollection[self.IdForQueryViewerCollection]) + " ExportPopup "
			});

			var clickRef = function (event) {
				var coords = OAT.Event.position(event);
				self.exportPage.style.left = coords[0] + "px";
				self.exportPage.style.top = coords[1] + "px";
				self.exportPage.id = "exportOptionsContainer";


				var screenWidth = window.innerWidth;
				var initialPopUpWidth = Math.max(jQuery(".ExportPopup")[0].clientWidth, 300)
				var offsetLeft = jQuery(event.currentTarget).offset().left

				var iconExport = event.currentTarget

				/* title */
				jQuery(".oat_winrect_title").find(".winrect_title_label").remove()

				var spantitle = OAT.Dom.create("label");
				if (self.isSD) {
					jQuery(".oat_winrect_container").addClass("oat_winrect_container_small")
					spantitle.setAttribute("class", "winrect_title_label winrect_title_label_small");
				} else {
					spantitle.setAttribute("class", "winrect_title_label");
				}
				OAT.addTextNode(spantitle, gx.getMessage("GXPL_QViewerPopupTitle"));
				jQuery(".oat_winrect_title").append(spantitle)


				jQuery(".ExportPopup").css({ left: -2500 + "px", top: 0 + "px" })


				OAT.Dom.clear(self.exportPage);

				var div_upper = document.createElement("div");
				div_upper.setAttribute("class", "upper_container");

				//botton to allow show all filters in pop up
				jQuery('#divtoxml').remove();
				jQuery('#divtoxls').remove();
				jQuery('#divtoxlsx').remove();
				jQuery('#divtoexport').remove();
				jQuery('#divtohtml').remove();
				var someExport = false;
				self.appendExportToXmlOption(div_upper, someExport);
				self.appendExportToHtmlOption(div_upper, someExport);
				self.appendExportToPdfOption(div_upper, someExport);
				self.appendExportToExcelOption(div_upper, someExport);
				self.appendExportToExcel2010Option(div_upper, someExport);

				self.exportPage.appendChild(div_upper);

				//if (someExport){
				var hr = OAT.Dom.create("hr", {});
				self.exportPage.appendChild(hr);
				//}

				var div_down = document.createElement("div");
				div_down.setAttribute("class", "down_container");
				self.exportPage.appendChild(div_down);

				var label = document.createElement("span");
				label.textContent = gx.getMessage("GXPL_QViewerJSVisibleColumns");
				var div_label = document.createElement("div");
				div_label.setAttribute("class", "div_label_win");
				div_label.appendChild(label);
				div_down.appendChild(div_label);


				var generatePair = function (index, isDimension) {
					if ((isDimension) && (self.initMetadata.Dimensions[index].validPosition == ""))
					{
						return false;
					}
					
					var dataField; var displayName;
					if (isDimension) {
						dataField = self.initMetadata.Dimensions[index].dataField;
						displayName = self.initMetadata.Dimensions[index].displayName;
					} else {
						dataField = self.initMetadata.Measures[index].dataField;
						displayName = self.initMetadata.Measures[index].displayName;
					}

					var state = self.headerRow.indexOf(displayName) != -1;
					var pair = OAT.Dom.create("div");
					var check_class = (state) ? "check_item_img" : "uncheck_item_img";
					if (self.isSD) {//android
						check_class = (state) ? "check_item_img_small" : "uncheck_item_img_small";
					}
					OAT.addImageNode(pair, state ? "check_box" : "check_box_outline_blank", "");

					pair.setAttribute("class", check_class);
					pair.setAttribute("dataField", displayName);
					pair.setAttribute("isDimension", isDimension);
					pair.setAttribute("index", index);
					var span = OAT.Dom.create("span");
					if (isDimension) {
						OAT.addTextNode(span, " " + self.initMetadata.Dimensions[index].displayName)
					} else {
						OAT.addTextNode(span, " " + self.initMetadata.Measures[index].displayName)
					}
					var show = ((self.formulaInfo.itemPosition[dataField] == undefined) || (self.formulaInfo.cantFormulaMeasures == 0))
					if (isDimension) {
						show = show && (self.initMetadata.Dimensions[index].validPosition != "hidden")
					} else {
						show = show && (self.initMetadata.Measures[index].validPosition != "hidden")
					}
					if (show) {
						pair.appendChild(span);
						OAT.Event.attach(pair, "click", function () { // this hide or show the columns
							var isDimension = (pair.getAttribute("isDimension") == "true");
							var dataField = pair.getAttribute("dataField");
							var index = parseInt(pair.getAttribute("index"));

							var checkedClass = "check_item_img"
							var unCheckedClass = "uncheck_item_img"
							if (self.isSD) {//android
								checkedClass = "check_item_img_small"
								unCheckedClass = "uncheck_item_img_small"
							}

							var newClass = (this.getAttribute("class") === checkedClass) ? unCheckedClass : checkedClass;
							this.setAttribute("class", newClass);
							
							jQuery(this).find("i")[0].textContent = (this.getAttribute("class") === checkedClass) ? "check_box" : "check_box_outline_blank";

							if (isDimension) {
								self.initMetadata.Dimensions[index].Visible = !self.initMetadata.Dimensions[index].Visible
								self.preGoWhenShowHideDimension(index);
							} else {
								self.initMetadata.Measures[index].Visible = !self.initMetadata.Measures[index].Visible
								self.preGoWhenShowHideMeasures(index);
							}

						});
					}


					return pair;
				}

				var start = (self.autoNumber ? 1 : 0);
				for (var i = start; i < self.initMetadata.Dimensions.length; i++) {
					var pair = generatePair(i, true);
					if (pair)
						div_down.appendChild(pair);
				}
				for (var i = start; i < self.initMetadata.Measures.length; i++) {
					var pair = generatePair(i, false);
					if (pair)
						div_down.appendChild(pair);
				}




				setTimeout(function () {

					var screenWidth = window.innerWidth;
					var initialPopUpWidth = jQuery(".ExportPopup")[0].clientWidth


					if (initialPopUpWidth == 0) {
						var last = jQuery(".ExportPopup").length;
						initialPopUpWidth = jQuery(".ExportPopup")[last - 1].clientWidth
					}

					if (self.isSD) {//android		
						if (initialPopUpWidth < 240) {
							initialPopUpWidth = 240
						}

						var padding = (screenWidth - initialPopUpWidth) / 2 + jQuery(window).scrollLeft()

						jQuery(".ExportPopup").css({ left: padding + "px", top: jQuery(iconExport).offset().top + "px", width: initialPopUpWidth + "px" })

					} else {

						var offsetLeft = jQuery(iconExport).offset().left

						if (offsetLeft + initialPopUpWidth + 15 < screenWidth) {
							jQuery(".ExportPopup").css({ left: jQuery(iconExport).offset().left + "px", top: jQuery(iconExport).offset().top + "px" })
						} else {
							jQuery(".ExportPopup").css({ left: (offsetLeft - initialPopUpWidth + 16) + "px", top: jQuery(iconExport).offset().top + "px" })
						}

					}
				}, 50)



			} /* clickref */
			OAT.Event.attach(exportImg, "click", clickRef);

			if ((self.QueryViewerCollection[IdForQueryViewerCollection].ExportToXML) || (self.QueryViewerCollection[IdForQueryViewerCollection].ExportToHTML)
				|| (self.QueryViewerCollection[IdForQueryViewerCollection].ExportToPDF) || (self.QueryViewerCollection[IdForQueryViewerCollection].ExportToXLS)
				|| (self.QueryViewerCollection[IdForQueryViewerCollection].ExportToXLSX)) {
				self.filterDiv.appendChild(exportImg);
			}

		}

		this.appendExportToXmlOption = function (content, someExport) {
			var exportXMLButton;
			//if (self.QueryViewerCollection[self.controlName.toUpperCase() + "_" + self.controlName].ExportToXML){
			if (self.QueryViewerCollection[IdForQueryViewerCollection].ExportToXML) {
				if (gx.util.browser.isIE() && 9 >= gx.util.browser.ieVersion()) {
					exportXMLButton = document.createElement("div");
					exportXMLButton.style.marginBottom = "10px"
					exportXMLButtonSub = OAT.Dom.create("div", { paddingLeft: "1px", position: "relative", cssFloat: "left" });
					exportXMLButtonSub.setAttribute('id', 'divtoxml');
					var FileName = self.query
					if (FileName == "") {
						FileName = "Query"
						try {
							FileName = self.controlName.split("_")[0]
						} catch (error) { }
					}
					setTimeout(function () {
						jQuery("#divtoxml").downloadify({
							filename: function () {
								return FileName + '.xml';
							},
							data: function () {
								return '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + self.ExportToXML();
							},
							onComplete: function () {
							},
							onCancel: function () {
							},
							onError: function () {
							},
							swf: self.swfPath,
							downloadImage: self.downloadImagePath,
							width: 21,
							height: 21,
							transparent: true,
							append: false
						});
					}, 100);

					exportXMLButton.appendChild(exportXMLButtonSub);
					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXml"))
					pvpl.style.paddingLeft = "9px";
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXMLButton.appendChild(pvpl);



				} else {
					exportXMLButton = OAT.Dom.create("div");
					//exportXMLButton.style.marginBottom = "10px"

					exportXMLButtonSub = self.createExportButton(exportXMLButton)

					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXml"))
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXMLButton.appendChild(pvpl);
					var span = document.createElement("span");
					exportXMLButton.appendChild(span);

					OAT.Dom.attach(exportXMLButtonSub, "click", function () {
						if (self.serverPagination) {
							self.getDataForPivot(self.UcId, 1, -1, true, "", "", "XML", "", "", true)
						} else {
							str = self.ExportToXML();

							if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari
								window.open('data:text/xml,' + encodeURIComponent('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + str));
							} else {
								var blob = new Blob([str], { type: "text/xml" });
								if (self.query != "") {
									saveAs(blob, self.query + ".xml");
								} else {
									var name = 'Query'
									try {
										name = self.controlName.substr(4).split("_")[0]
									} catch (error) { }
									saveAs(blob, name + ".xml");
								}
							}
						}
					});
				}
				if (someExport) {
					if (!gx.util.browser.isIE()) {
						content.appendChild(OAT.Dom.create("br"));
					}
				}
				content.appendChild(exportXMLButton);
				someExport = true;
			}
		}

		this.ExportToXMLWhenServerPagination = function () {
			self.QueryViewerCollection[self.IdForQueryViewerCollection].calculatePivottableData((function (resText) {
				self.allDataWithoutSort = OATgetDataFromXMLOldFormat(resText, self.pageData.dataFields)
				self.allData = self.allDataWithoutSort

				var prevConditions = jQuery.extend(true, [], self.conditions);
				for (var t = 0; t < self.conditions.length; t++) {
					if (self.conditions[t]) {
						for (var i = 0; i < self.allData.length; i++) {
							var value = self.allData[i][t];
							if (value == undefined) {
								value = " ";
								self.allData[i][index] = " ";
							}
							if (self.conditions[t].distinctValues.findIndex(value) == -1) {
								self.conditions[t].distinctValues.push(value);
							}
						}
						try {
							self.sort(self.conditions[t], t);
						} catch (ERROR) { }
					}
				}

				self.applyFilters();
				self.createAggStructure();
				self.fillAggStructure();
				self.checkAggStructure();
				//self.count();

				str = self.ExportToXML();
				self.allDataWithoutSort = []; self.allData = []; self.filteredData = [];
				self.conditions = prevConditions;

				if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari
					window.open('data:text/xml,' + encodeURIComponent('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + str));
				} else {
					var blob = new Blob([str], { type: "text/xml" });
					if (self.query != "") {
						saveAs(blob, self.query + ".xml");
					} else {
						var name = 'Query'
						try {
							name = self.controlName.substr(4).split("_")[0]
						} catch (error) { }
						saveAs(blob, name + ".xml");
					}
				}

			}).closure(this))
		}

		this.ExportToHTMLWhenServerPagination = function () {
			var dir = gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/css/pivot.css')

			var str = "<!DOCTYPE><HTML><BODY>";
			str = str + "<HEAD>";
			str = str + '<META content="text/html; charset=utf-8" http-equiv="Content-Type"/>'

			str = str + '<link id="gxtheme_css_reference" rel="stylesheet" type="text/css" href="' + dir + '" />'
			
			//add other css file
			for(var i = 0; i < jQuery('link').length; i++)
			{
				if ($('link')[i].href.indexOf("QueryViewer.css") < 0) {
					str = str + '<link id="gxtheme_css_reference" rel="stylesheet" type="text/css" href="' + $('link')[i].href + '" />'
				}
			}
			
			str = str + "</HEAD><DIV style=\"margin-bottom: 5px;\">"
			
			str = str + '<div class="gx_usercontrol qv-pivottable QueryViewer-pivottable">'
			
			str = str + '<table class="pivot_table" style="width: 100%;">'
			
			str = str + OAT.removeIconFont(jQuery("#" + self.controlName + "_" + self.query)[0].innerHTML.replace(/display: none;/g, "").replace(/sort-asc/g, "").replace(/sort-desc/g, ""));
			
			str = str + '</table>'
			
			str = str + '</div>'
			str = str + "</DIV></BODY></HTML>";

			if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari
				window.open('data:text/html,' + str);
			} else {
				var blob = new Blob([str], { type: "text/html" });
				if (self.query != "") {
					saveAs(blob, self.query + ".html");
				} else {
					var name = 'Query'
					try {
						name = self.controlName.substr(4).split("_")[0]
					} catch (error) { }
					saveAs(blob, name + ".html");
				}
			}
		}

		this.appendExportToHtmlOption = function (content, someExport) {
			var exportHTMLButton;
			if (self.QueryViewerCollection[IdForQueryViewerCollection].ExportToHTML) {
				if (!gx.util.browser.isIE() || 9 < gx.util.browser.ieVersion()) {

					var exportHTMLButton = OAT.Dom.create("div");
					// exportHTMLButton.style.marginBottom = "10px"

					exportButtonSub = self.createExportButton(exportHTMLButton)

					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportHtml"))
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportHTMLButton.appendChild(pvpl);



					OAT.Dom.attach(exportButtonSub, "click", function () {
						if (self.serverPagination) {
							self.getDataForPivot(self.UcId, 1, -1, true, "", "", "HTML", "", "", true)
						} else {
							var dir = gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/css/pivot.css')

							var str = "<!DOCTYPE><HTML><BODY>";
							str = str + "<HEAD>";
							str = str + '<META content="text/html; charset=utf-8" http-equiv="Content-Type"/>'
							//str = str + '<link id="gxtheme_css_reference" rel="stylesheet" type="text/css" href="' + dir + '/QueryViewer/oatPivot/css/pivot.css" />'
							str = str + '<link id="gxtheme_css_reference" rel="stylesheet" type="text/css" href="' + dir + '" />'
							str = str + "</HEAD><DIV style=\"margin-bottom: 5px;\">"
							str = str + jQuery("#" + self.controlName + "_" + self.query)[0].outerHTML.replace(/display: none;/g, "").replace(/sort-asc/g, "").replace(/sort-desc/g, "");
							str = str + "</DIV></BODY></HTML>";
							//if(!gx.util.browser.isIE()) {
							if ((gx.util.browser.webkit) && (!gx.util.browser.chrome)) { //for safari
								window.open('data:text/html,' + str);
							} else {
								var blob = new Blob([str], { type: "text/html" });
								if (self.query != "") {
									saveAs(blob, self.query + ".html");
								} else {
									var name = 'Query'
									try {
										name = self.controlName.substr(4).split("_")[0]
									} catch (error) { }
									saveAs(blob, name + ".html");
								}
							}
						}
					});
				} else {
					exportHTMLButton = document.createElement("div");
					exportHTMLButton.style.marginBottom = "10px"
					exportHTMLButtonSub = OAT.Dom.create("div", { paddingLeft: "1px", position: "relative", cssFloat: "left" });
					exportHTMLButtonSub.setAttribute('id', 'divtohtml')
					var FileName = self.query
					if (FileName == "") {
						FileName = "Query"
						try {
							FileName = self.controlName.split("_")[0]
						} catch (error) { }
					}
					setTimeout(function () {
						jQuery("#divtohtml").downloadify({
							filename: function () {
								return FileName + '.html';
							},
							data: function () {
								var dir = gx.util.resourceUrl(self.relativePath + 'QueryViewer/oatPivot/css/pivot.css')

								var str = "<!DOCTYPE><HTML><BODY>";
								str = str + "<HEAD>";
								str = str + '<META content="text/html; charset=utf-8" http-equiv="Content-Type"/>'
								str = str + '<link id="gxtheme_css_reference" rel="stylesheet" type="text/css" href="' + dir + '" />'
								str = str + "</HEAD><DIV style=\"margin-bottom: 5px;\">"
								str = str + jQuery("#" + self.controlName + "_" + self.query)[0].outerHTML.replace(/display: none;/g, "").replace(/sort-asc/g, "").replace(/sort-desc/g, "");
								str = str + "</DIV></BODY></HTML>";
								return str;
							},
							onComplete: function () {
							},
							onCancel: function () {
							},
							onError: function () {
							},
							swf: self.swfPath,
							downloadImage: self.downloadImagePath,
							width: 21,
							height: 21,
							transparent: true,
							append: false
						});
					}, 100);

					exportHTMLButton.appendChild(exportHTMLButtonSub);
					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportHtml"))
					pvpl.style.paddingLeft = "9px";
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportHTMLButton.appendChild(pvpl);
				}
				if (someExport) {
					if (!gx.util.browser.isIE()) {
						content.appendChild(OAT.Dom.create("br"));
					}
				}
				content.appendChild(exportHTMLButton);
				someExport = true;
			}
		}


		this.appendExportToPdfOption = function (content, someExport) {
			var exportPdfButton;
			if (self.QueryViewerCollection[IdForQueryViewerCollection].ExportToPDF) {
				someExport = true;
				if (gx.util.browser.isIE() && (9 >= gx.util.browser.ieVersion())) {
					exportPdfButton = document.createElement("div");
					exportPdfButton.style.marginBottom = "10px"
					exportPdfButtonSub = OAT.Dom.create("div", { paddingLeft: "1px", position: "relative", cssFloat: "left" });

					exportPdfButtonSub.setAttribute('id', 'divtoexport')
					var FileName = self.query
					if (FileName == "") {
						FileName = "Query"
						try {
							FileName = self.controlName.split("_")[0]
						} catch (error) { }
					}
					setTimeout(function () {
						jQuery("#divtoexport").downloadify({
							filename: function () {
								return FileName + '.pdf';
							},
							data: function () {
								return btoa(OAT.GeneratePDFOutput(self));
							},
							onComplete: function () {
							},
							onCancel: function () {
							},
							onError: function () {
							},
							dataType: 'base64',
							swf: self.swfPath,
							downloadImage: self.downloadImagePath,
							width: 21,
							height: 21,
							transparent: true,
							append: false
						});
					}, 100);

					exportPdfButton.appendChild(exportPdfButtonSub);
					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportPdf"))
					pvpl.style.paddingLeft = "9px";
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportPdfButton.appendChild(pvpl);
				} else {
					var exportPdfButton = OAT.Dom.create("div");

					exportButtonSub = self.createExportButton(exportPdfButton)

					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportPdf"))
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportPdfButton.appendChild(pvpl);

					var FileName = self.query
					if (FileName == "") {
						FileName = "Query"
						try {
							FileName = self.controlName.split("_")[0]
						} catch (error) { }
					}
					OAT.Dom.attach(exportButtonSub, "click", function () {
						if (self.serverPagination) {
							self.getDataForPivot(self.UcId, 1, -1, true, "", "", "PDF", "", "", true)
						} else {
							OAT.GeneratePDFOutput(self, FileName)
						}
					});
				}

				content.appendChild(exportPdfButton);
			}
		}



		this.appendExportToExcelOption = function (content, someExport) {
			var exportXLSButton;
			if (self.QueryViewerCollection[IdForQueryViewerCollection].ExportToXLS) {

				if (!gx.util.browser.isIE() || (9 < gx.util.browser.ieVersion())) {
					var exportXLSButton = OAT.Dom.create("div");

					exportButtonSub = self.createExportButton(exportXLSButton)

					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXls2003"))
					gx.getMessage("GXPL_QViewerContextMenuExportPdf")
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXLSButton.appendChild(pvpl);

					var FileName = self.query
					if (FileName == "") {
						FileName = "Query"
						try {
							FileName = self.controlName.split("_")[0]
						} catch (error) { }
					}
					OAT.Dom.attach(exportButtonSub, "click", function () {
						if (self.serverPagination) {
							self.getDataForPivot(self.UcId, 1, -1, true, "", "", "XLS", "", "", true)
						} else {
							self.ExportToExcel(FileName);
						}
					});
				} else {
					exportXLSButton = document.createElement("div");
					exportXLSButton.style.marginBottom = "10px"
					exportXLSButtonSub = OAT.Dom.create("div", { paddingLeft: "1px", position: "relative", cssFloat: "left" });

					exportXLSButtonSub.setAttribute('id', 'divtoxls');
					var FileName = self.query
					if (FileName == "") {
						FileName = "Query"
						try {
							FileName = self.controlName.split("_")[0]
						} catch (error) { }
					}
					setTimeout(function () {
						jQuery("#divtoxls").downloadify({
							filename: function () {
								return FileName + '.xls';
							},
							data: function () {
								return self.ExportToExcel();
							},
							onComplete: function () {
							},
							onCancel: function () {
							},
							onError: function () {
							},
							//transparent: false,
							swf: self.swfPath,
							downloadImage: self.downloadImagePath,
							width: 21,
							height: 21,
							transparent: true,
							append: false
						});
					}, 100);
					exportXLSButton.appendChild(exportXLSButtonSub);
					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXls2003"))
					pvpl.style.paddingLeft = "9px";
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXLSButton.appendChild(pvpl);
				}
				if (someExport) {
					if (!gx.util.browser.isIE()) {
						content.appendChild(OAT.Dom.create("br"));
					}
				}
				content.appendChild(exportXLSButton);
				someExport = true;
			}
		}

		this.ExportToXLSXWhenServerPagination = function () {
			self.QueryViewerCollection[self.IdForQueryViewerCollection].calculatePivottableData((function (resText) {


				var dataFields = [];
				for (var t = 0; t < self.pageData.dataFields.length; t++) {
					dataFields.push(self.pageData.dataFields[t]);
				}
				for (var t = 0; t < self.pageData.AxisInfo.length; t++) {
					try {
						if (self.pageData.AxisInfo[t].Axis.Type == "Hidden") {
							var index = dataFields.indexOf(self.pageData.AxisInfo[t].DataField);
							if (index > -1) {
								dataFields.splice(index, 1)
							}
						}
					} catch (ERROR) {

					}
				}
				
				for (var t = 0; t < self.initMetadata.Measures.length; t++){
					if ((self.initMetadata.Measures[t].Visible) &&  (dataFields.indexOf(self.initMetadata.Measures[t].name) < 0))
					{
						dataFields.push(self.initMetadata.Measures[t].name)
					} 
				}

				for (var t = 0; t < measures.length; t++) {
					if (measures[t].getAttribute("aggregation") == "average") {
						self.formulaInfo.measureFormula[t].hasFormula = true;
						self.formulaInfo.measureFormula[t].textFormula = measures[t].getAttribute("dataField") + "_N/" + measures[t].getAttribute("dataField") + "_D"

						self.formulaInfo.cantFormulaMeasures++;

						var inlineFormula = self.formulaInfo.measureFormula[t].textFormula

						var inline = inlineFormula
						var opers = ['*', '-', '+', '/', '(', ')']
						for (var j = 0; j < opers.length; j++) {
							var inline2 = inline.split(opers[j])
							if (inline2.length > 1) {
								inline = ""
								for (var i = 0; i < inline2.length - 1; i++) {
									inline = inline + inline2[i] + " " + opers[j] + " "
								}
								inline = inline + inline2[inline2.length - 1]
							}
						}

						var polishNot = InfixToPostfix(inline)
						formulaInfo.measureFormula[t].polishNotationText = polishNot
						var items = polishNot.split(" ")
						while (items.indexOf("") != -1) {
							items.splice(items.indexOf(""), 1)
						}
						var relatedMeasure = []
						for (var k = 0; k < items.length; k++) {
							if ((opers.indexOf(items[k]) == -1) && (isNaN(parseInt(items[k])))) {
								//add item
								var operPositionInDataRow = formulaInfo.itemPosition[items[k]]
								if (relatedMeasure.indexOf(operPositionInDataRow) == -1)
									relatedMeasure.push(operPositionInDataRow)
							}
						}

						self.formulaInfo.measureFormula[t].relatedMeasures = relatedMeasure

						var arrayNot = polishNot.split(" ")
						while (arrayNot.indexOf("") != -1) {
							arrayNot.splice(arrayNot.indexOf(""), 1)
						}
						self.formulaInfo.measureFormula[t].PolishNotation = arrayNot
					}
				}

				var res = OATgetDataFromXMLOldFormat(resText, dataFields/*self.pageData.dataFields*/, self.OrderFildsHidden)
				self.GeneralDataRows = res[0]
				self.recordForFormula = res[1]
				self.allData = self.GeneralDataRows

				var prevConditions = jQuery.extend(true, [], self.conditions);
				self.GeneralDistinctValues = [];
				for (var t = 0; t < self.conditions.length; t++) {
					if (self.conditions[t]) {
						self.GeneralDistinctValues[t] = []
						for (var i = 0; i < self.allData.length; i++) {
							var value = self.allData[i][t];
							if (value == undefined) {
								value = " ";
								self.allData[i][index] = " ";
							}
							if (self.conditions[t].distinctValues.findIndex(value) == -1) {
								self.conditions[t].distinctValues.push(value);
							}
							if (self.GeneralDistinctValues[t].findIndex(value) == -1) {
								self.GeneralDistinctValues[t].push(value);
							}
						}
						try {
							self.sort(self.conditions[t], t);
						} catch (ERROR) { }
					}
				}

				self.applyFilters();
				self.createAggStructure();
				self.fillAggStructure();
				self.checkAggStructure();
				//self.count();

				var FileName = self.query
				if (FileName == "") {
					FileName = "Query"
					try {
						FileName = self.controlName.split("_")[0]
					} catch (error) { }
				}
				OAT.GenerateExcelOutput(FileName, self, measures);

				str = self.ExportToXML();
				self.GeneralDataRows = []; self.allData = []; self.filteredData = []; self.GeneralDistinctValues = [];
				self.conditions = prevConditions;

				//quitar formulas averages
				for (var t = 0; t < measures.length; t++) {
					if (measures[t].getAttribute("aggregation") == "average") {
						self.formulaInfo.measureFormula[t] = { hasFormula: false };
						self.formulaInfo.cantFormulaMeasures--;
					}
				}
			}).closure(this))
		}

		this.appendExportToExcel2010Option = function (content, someExport) {
			var exportXLSButton;
			if ((self.QueryViewerCollection[IdForQueryViewerCollection].ExportToXLSX) && ((self.allData.length > 0) || (self.serverPagination))) {

				if ((!gx.util.browser.isIE()) || (9 < gx.util.browser.ieVersion())) {
					var exportXLSButton = OAT.Dom.create("div");

					exportButtonSub = self.createExportButton(exportXLSButton)

					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXlsx"))
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXLSButton.appendChild(pvpl);

					var FileName = self.query
					if (FileName == "") {
						FileName = "Query"
						try {
							//FileName = self.controlName.substr(4).split("_")[0]
							FileName = self.controlName.split("_")[0]
						} catch (error) { }
					}
					OAT.Dom.attach(exportXLSButton, "click", function () {
						if (self.serverPagination) {
							self.getDataForPivot(self.UcId, 1, -1, true, "", "", "XLSX", "", "", true);
						} else {
							OAT.GenerateExcelOutput(FileName, self, measures);//self.ExportToExcel2010(FileName);
						}
					});
				} else {
					exportXLSButton = document.createElement("div");
					exportXLSButton.style.marginBottom = "10px"
					exportXLSButtonSub = OAT.Dom.create("div", { paddingLeft: "1px", position: "relative", cssFloat: "left" });

					exportXLSButtonSub.setAttribute('id', 'divtoxlsx');
					var FileName = self.query
					if (FileName == "") {
						FileName = "Query"
						try {
							FileName = self.controlName.split("_")[0]
						} catch (error) { }
					}
					setTimeout(function () {
						jQuery("#divtoxlsx").downloadify({
							filename: function () {
								return FileName + '.xlsx';
							},
							data: function () {
								return OAT.GenerateExcelOutput("", self, measures);//self.ExportToExcel2010();
							},
							onComplete: function () {
							},
							onCancel: function () {
							},
							onError: function () {
							},
							dataType: 'base64',
							//transparent: false,
							swf: self.swfPath,
							downloadImage: self.downloadImagePath,
							width: 21,
							height: 21,
							transparent: true,
							append: false
						});
					}, 100);
					exportXLSButton.appendChild(exportXLSButtonSub);
					var pvpl = OAT.Dom.create("label");
					OAT.addTextNode(pvpl, gx.getMessage("GXPL_QViewerContextMenuExportXlsx"))
					pvpl.style.paddingLeft = "9px";
					pvpl.htmlFor = "pivot_checkbox_restoreview";
					exportXLSButton.appendChild(pvpl);
				}
				if (someExport) {
					if (!gx.util.browser.isIE()) {
						content.appendChild(OAT.Dom.create("br"));
					}
				}
				content.appendChild(exportXLSButton);
				someExport = true;
			}
		}


		this.createExportButton = function (divContainer) {

			var exportButtonSub = OAT.Dom.create("div", {});
			exportButtonSub.setAttribute('id', 'divtoxml');
			divContainer.appendChild(exportButtonSub);

			if (self.isSD) {//android				
				exportButtonSub.setAttribute("class", "download_file_img_small");
			} else {
				exportButtonSub.setAttribute("class", "download_file_img");
			}
			
			OAT.addImageNode(exportButtonSub, "save_alt", "");

			divContainer.setAttribute("class", "export_item_div");
			if (self.isSD) {//android		
				divContainer.setAttribute("class", "export_item_div export_item_div_small");
			}
			return divContainer;
		}

		this.countTotals = function () { /* totals */
			self.rowTotals = [[], []];
			self.colTotals = [[], []];
			self.gTotal = [];
			for (var i = 0; i < self.w; i++) { self.colTotals[0].push([]); self.colTotals[1].push([]); }
			for (var i = 0; i < self.h; i++) { self.rowTotals[0].push([]); self.rowTotals[1].push([]); }

			var colTotalsWithNun = [];
			for (var i = 0; i < self.w; i++) {
				for (var j = 0; j < self.h; j++) {
					var val = self.tabularData[i][j][0];
					if ((val != self.EmptyValue) && (val != "#NuN#")) {
						if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
							self.colTotals[0][i].push(self.tabularData[i][j][2][0])
						} else {
							self.colTotals[0][i].push(val);
						}
						self.colTotals[1][i].push(self.tabularData[i][j][1]);
						if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
							self.rowTotals[0][j].push(self.tabularData[i][j][2][0]);
						} else {
							self.rowTotals[0][j].push(val);
						}
						self.rowTotals[1][j].push(self.tabularData[i][j][1]);
						if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
							self.gTotal.push(self.tabularData[i][j][2][0]);
						} else {
							self.gTotal.push(val);
						}
					} else if (val == "#NuN#") {
						colTotalsWithNun[i] = true;
					}
				}
			}

			var func = OAT.Statistics[OAT.Statistics.list[self.options.aggTotals].func]; /* statistics */
			for (var i = 0; i < self.rowTotals[0].length; i++) {
				if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
					self.rowTotals[0][i] = self.calculateFormulaTotal(self.rowTotals[0][i], measures.length - 1, "MesaureAsColumn");
				} else {
					self.rowTotals[0][i] = func(self.rowTotals[0][i]);
				}
			}
			for (var i = 0; i < self.colTotals[0].length; i++) {
				if ((self.colTotals[0][i].length == 0) && (colTotalsWithNun[i])) self.colTotals[0][i] = "#NuN#"
				else {
					if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
						self.colTotals[0][i] = self.calculateFormulaTotal(self.colTotals[0][i], measures.length - 1, "MesaureAsColumn")
					} else {
						self.colTotals[0][i] = func(self.colTotals[0][i]);
					}
				}
			}


			if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
				self.gTotal = self.calculateFormulaTotal(self.gTotal, measures.length - 1, "MesaureAsColumn")
			} else {
				self.gTotal = func(self.gTotal);
			}
		}

		this.countSubTotals = function () { /* sub-totals */
			function clean(ptrArray, count) {
				for (var i = 0; i < ptrArray.length - 1; i++) {
					var stack = ptrArray[i];
					for (var j = 0; j < stack.length; j++) {
						stack[j].totals = [];
						stack[j].filtrows = [];
						for (var k = 0; k < count; k++) { stack[j].totals.push([]); stack[j].filtrows.push([]); }
					}
				}
			}
			clean(self.colPointers, self.h);
			clean(self.rowPointers, self.w);

			function addTotal(arr, arrIndex, totalIndex, value, filtrows) {
				if (!arr.length) { return; }
				var item = arr[arr.length - 1][arrIndex].parent;
				while (item.parent) {
					item.totals[totalIndex].push(value);
					item.filtrows[totalIndex].push(filtrows);
					item = item.parent;
				}
			}
			for (var i = 0; i < self.w; i++) {
				for (var j = 0; j < self.h; j++) {
					var val = self.tabularData[i][j][0];
					var filtrows = self.tabularData[i][j][1];
					if (val != self.EmptyValue) {
						if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
							addTotal(self.colPointers, i, j, self.tabularData[i][j][2][0], filtrows);
							addTotal(self.rowPointers, j, i, self.tabularData[i][j][2][0], filtrows);
						} else {
							addTotal(self.colPointers, i, j, val, filtrows);
							addTotal(self.rowPointers, j, i, val, filtrows);
						}
					}
				}
			}

			function apply(ptrArray, func) {
				for (var i = 0; i < ptrArray.length - 1; i++) {
					var stack = ptrArray[i];
					for (var j = 0; j < stack.length; j++) {
						var totals = stack[j].totals;
						var filtrows = stack[j].filtrows;
						for (var k = 0; k < totals.length; k++) {
							if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
								var addValue = self.calculateFormulaTotal(totals[k], measures.length - 1, "MesaureAsColumn")
								totals[k] = { array: totals[k], value: addValue, rows: filtrows[k] };
							} else {
								totals[k] = { array: totals[k], value: func(totals[k]), rows: filtrows[k] };
							}
						}
					}
				}
			}
			var func = OAT.Statistics[OAT.Statistics.list[self.options.aggTotals].func]; /* statistics */
			apply(self.colPointers, func);
			apply(self.rowPointers, func);
		}

		this.countPointers = function () { /* create arrays of pointers to levels of agg structures */
			function DeepCopy(item) {
				var a = [];
				for (var i=0;i<item.length;i++) { a.push(item[i]); }
				return a;
			}
			
			function count(struct, arr, propName) {
				if (!self.ShowMeasuresAsRows) {
					self[propName] = [];
					var stack = [struct];
					for (var i = 0; i < arr.length; i++) {
						var newstack = [];
						for (var j = 0; j < stack.length; j++) {
							var item = stack[j];
							for (var k = 0; k < item.items.length; k++) {
								newstack.push(item.items[k]);
							}
						}
						stack = newstack;
						self[propName].push(DeepCopy(stack));
					}
				} else {
					self[propName] = [];
					var stack = [struct];
					var dim = arr.length - (measures.length - 1) + 1
					if (propName == "colPointers") {
						dim = arr.length
					}
					for (var i = 0; i < dim; i++) {
						var newstack = [];
						for (var j = 0; j < stack.length; j++) {
							var item = stack[j];
							for (var k = 0; k < item.items.length; k++) {
								newstack.push(item.items[k]);
							}
						}
						stack = newstack;
						self[propName].push(DeepCopy(stack));
					}
				}
			}

			count(self.rowStructure, self.rowConditions, "rowPointers");
			count(self.colStructure, self.colConditions, "colPointers");
		}

		this.countOffsets = function () { /* starting offsets for aggregate structures */
			function count(ptrArray) {
				for (var i = 0; i < ptrArray.length; i++) {
					var stack = ptrArray[i];
					var counter = 0;
					for (var j = 0; j < stack.length; j++) {
						var item = stack[j];
						item.offset = counter;
						counter += item.spanData;
					}
				}
			}

			count(self.rowPointers);
			count(self.colPointers);
		}

		this.count = function () { /* create tabularData from filteredData Sets the span of ths */
			/* compute spans = table dimensions */
			function spans(ptr, arr, isForRow, actualDepth, maxDepth) { /* return span for a given aggregate pointer */
				var s = 0;
				var sD = 0; var draw = 0;
				if (!ptr.items) {
					ptr.span = 1;
					ptr.spanData = 1;
					ptr.spanDraw = 1;
					return [ptr.span, ptr.spanData, ptr.spanDraw];
				}

				for (var i = 0; i < ptr.items.length; i++) {
					var tmp = spans(ptr.items[i], arr, isForRow, actualDepth + 1, maxDepth);
					s += tmp[0];
					sD += tmp[1];
					if ((!isForRow) || (actualDepth < maxDepth)) {
						draw += tmp[2];
					}
				}


				ptr.span = s;
				ptr.spanData = sD;
				ptr.spanDraw = draw;
				if (ptr.items.length && ptr.items[0].items) {
					if (!self.ShowMeasuresAsRows) {
						var cond = self.conditions[arr[ptr.items[0].depth]];
						if ((cond.subtotals) && ((!self.autoPaging) || (self.colConditions.length == 0))) { // aument span value for subtotal rows

							var punt = ptr.items;
							var prof = 0;
							if (ptr.items.length > 0) {
								while (punt != false) //calc depth 
								{
									prof++;
									punt = punt[0].items;
								}
							}
							for (var hi = 0; hi < ptr.items.length; hi++) {
								var cantmeasures = measures.length;
								if ((ptr.items[hi].items != null) && ((prof - cantmeasures > 0))) { //((columns.length < 3) && (ptr.items[hi].items.length > 1)) || 
									//if depth of subitem (that is the next dimension columns) if mayor than 1 (there are another column --a dimension?)then an aditional row is needed for the sum of the next dimension
									ptr.span = ptr.span + 1;
									ptr.spanDraw = ptr.spanDraw + 1;
								}
							}
						}
					}
				}
				if ((!isForRow) || (actualDepth < maxDepth)) {
				} else {
					ptr.spanDraw = 1;
				}
				if ((ptr.collapsed != undefined) && (ptr.collapsed)) {
					ptr.span = 1; ptr.spanDraw = 1;
					//ptr.spanData = 2;
					return [ptr.span, ptr.spanData, ptr.spanDraw];
				}
				return [ptr.span, ptr.spanData, ptr.spanDraw];
			}
			function spansWhenMeasuresAsRows(ptr, arr, actualDepth, maxDepth) { /* return span for a given aggregate pointer */
				var s = 0;
				var sD = 0;
				if (!ptr.items) {
					ptr.span = 1;
					ptr.spanData = 1;
					return [ptr.span, ptr.spanData];
				}
				var ramasSecas = 0;
				for (var i = 0; i < ptr.items.length; i++) {
					var tmp = spansWhenMeasuresAsRows(ptr.items[i], arr, actualDepth + 1, maxDepth);
					s += tmp[0];
					sD += tmp[1];
					if (tmp[0] == 0) ramasSecas = ramasSecas + 1;
				}
				ptr.span = s;
				ptr.spanData = sD;
				if ((actualDepth != -1) && (actualDepth < maxDepth)) {
					var cond = self.conditions[arr[actualDepth + 1]];
					if (cond.subtotals) { // aument span value for subtotal rows
						//for(var hi=0; hi < ptr.items.length; hi++){
						ptr.span = ptr.span + measures.length * (ptr.items.length - ramasSecas);
						//}
					}

				}
				if ((ptr.collapsed != undefined) && (ptr.collapsed)) {
					ptr.span = 1;
					//ptr.spanData = 2;
					return [ptr.span, ptr.spanData];
				}
				return [ptr.span, ptr.spanData];
			}

			if (!self.ShowMeasuresAsRows) {
				var maxDepth = self.rowConditions.length - (measures.length - 1) - 1
				var initDepth = -1
				spans(self.rowStructure, self.rowConditions, true, initDepth, maxDepth);
				spans(self.colStructure, self.colConditions, false);
			} else {
				var maxDepth = self.rowConditions.length - (measures.length - 1) - 2
				var initDepth = -1
				spansWhenMeasuresAsRows(self.rowStructure, self.rowConditions, initDepth, maxDepth);
				spansWhenMeasuresAsRows(self.colStructure, self.colConditions, 0, 0);
			}

			self.countPointers();
			self.countOffsets();


			/* create blank table */
			self.tabularData = [];
			var filterDataId = []; var formulaData = []
			self.w = 1;
			self.h = 1;
			if (self.colConditions.length) { self.w = self.colPointers[self.colPointers.length - 1].length; }
			if (self.rowConditions.length) { self.h = self.rowPointers[self.rowPointers.length - 1].length; }

			if (!self.ShowMeasuresAsRows) {

				for (var i = 0; i < self.w; i++) {
					var col = new Array(self.h);
					var fil = new Array(self.h); var fla = new Array(self.h);
					for (var j = 0; j < self.h; j++) { col[j] = []; fil[j] = []; fla[j] = [] }
					self.tabularData.push(col);
					filterDataId.push(fil); formulaData.push(fla);
				}

				function coords(struct, arr, row) {
					var pos = 0;
					var ptr = struct;
					for (var i = 0; i < arr.length; i++) {
						var rindex = arr[i];
						var value = row[rindex];
						var o = false;
						for (var j = 0; j < ptr.items.length; j++) {
							if (ptr.items[j].value != value) {
								pos += ptr.items[j].spanData;
							} else {
								o = ptr.items[j];
								break;
							}
						}
						if (!self.autoPaging) {

							if (o)
								ptr = o;
						} else {
							if (o) { ptr = o; }
							else { return -1; }
						}
					} /* for all conditions */
					return pos;
				}

				function coordsY(struct, arr, row) {
					var pos = 0;
					var ptr = struct;
					var lessArr = [];
					for (var i = 0; i < (self.rowConditions.length - measures.length + 1); i++) {
						lessArr.push(arr[i])
					}

					for (var i = 0; i < lessArr.length; i++) {
						var rindex = lessArr[i];
						var value = row[rindex];
						var o = false;
						for (var j = 0; j < ptr.items.length; j++) {
							if (ptr.items[j].value != value) {
								pos += ptr.items[j].spanData;
							} else {
								o = ptr.items[j];
								break;
							}
						}
						if (!self.autoPaging) {

							if (o)
								ptr = o;
						} else {
							if (o) { ptr = o; }
							else { return -1; }
						}
					} /* for all conditions */
					return pos;
				}


				for (var i = 0; i < self.filteredData.length; i++) { /* reposition value array to grid */
					var row = self.filteredData[i];
					var x = coords(self.colStructure, self.colConditions, row);
					//C1Line
					var y = coordsY(self.rowStructure, self.rowConditions, row);
					//var y = coords(self.rowStructure, self.rowConditions, row);
					var val = row[self.dataColumnIndex];
					val = val.toString();
					val = val.replace(/,/g, '.');
					val = val.replace(/%/g, '');
					val = val.replace(/ /g, '');
					if (val != "#NuN#") {
						val = parseFloat(val);
						if (isNaN(val)) { val = 0; }
					}
					if (!self.autoPaging) {
						if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
							var formval = self.getFormulaRowByDataRow(row, measures.length - 1, "grandTotal-Tab")
							if (val == 0) {
								self.tabularData[x][y].push(val);
								self.tabularData[x][y] = self.calculateFormulaTotal([formval], measures.length - 1, "MesaureAsColumn")
							} else {
								self.tabularData[x][y].push(self.calculateFormulaTotal([formval], measures.length - 1, "MesaureAsColumn"));
							}
							formulaData[x][y].push(formval);
						} else {
							self.tabularData[x][y].push(val);
						}
						filterDataId[x][y].push(i);
					} else {
						if ((x != -1) && (y != -1)) {
							self.tabularData[x][y].push(val);
							filterDataId[x][y].push(i);
							if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
								var formval = self.getFormulaRowByDataRow(row, measures.length - 1, "grandTotal-Tab")
								formulaData[x][y].push(formval);
							}
						}
					}
				}
				var func = OAT.Statistics[OAT.Statistics.list[self.options.agg].func]; /* statistics */
				for (var i = 0; i < self.w; i++) {
					for (var j = 0; j < self.h; j++) {
						var cellNotFill = (self.tabularData[i][j].length == 0)
						var isNuN = ((self.tabularData[i][j].length == 1) && (self.tabularData[i][j][0] == "#NuN#"))
						var result = parseFloat(func(self.tabularData[i][j]));
						if ((!cellNotFill) && (!isNuN))//(result != 0)
							self.tabularData[i][j] = [result, filterDataId[i][j]];
						else if (!isNuN)
							self.tabularData[i][j] = [self.EmptyValue, filterDataId[i][j]]; /* this 0 is for non value, but if use for TOTAL and subTotal purposes*/
						else {
							self.tabularData[i][j] = ["#NuN#", filterDataId[i][j]];
						}
						if ((measures.length > 0) && (self.formulaInfo.measureFormula[measures.length - 1].hasFormula)) {
							if ((!cellNotFill) && (!isNuN)) {
								self.tabularData[i][j] = [result, filterDataId[i][j]];
							}
							self.tabularData[i][j].push(formulaData[i][j])
						}
					}
				}

				self.options.subtotals = 0;
				for (var i = 0; i < self.conditions.length; i++) {
					var cond = self.conditions[i];
					if (cond.subtotals) { self.options.subtotals = true; }
				}
		/*if (self.options.subtotals) {*/ self.countSubTotals(); /*}*/
				if (self.options.totals) { self.countTotals(); }

			}
		} /* Pivot::count() */

		this._drawGTotal = function (tr, grandTotals) {
			var td = OAT.Dom.create("td", {}, "gtotal grandtotalvalue");
			if (self.gTotal != NaN) {

				if ((self.autoPaging) && (self.FilterByTopFilter)) {
					var grandLastMeasureTotal = calculateGrandTotalForLastMeasure(self);
					OAT.addTextNode(td, self.defaultPictureValue(grandLastMeasureTotal.toString(), true, 0))
					td = self.applyConditionalFormats(td, grandLastMeasureTotal.toString(), true, 0);
					self.setClickEventHandlers(td, grandLastMeasureTotal.toString(), "MEASURE", measures.length - 1, 'GrandTotal');
				} else if ((!self.autoPaging) || (self.FilterByTopFilter)) {
					if (isNaN(self.gTotal)) { self.gTotal = 0; }
					OAT.addTextNode(td, self.defaultPictureValue(self.gTotal.toString(), true, 0))
					td = self.applyConditionalFormats(td, self.gTotal.toString(), true, 0);
					self.setClickEventHandlers(td, self.gTotal.toString(), "MEASURE", measures.length - 1, 'GrandTotal');
				} else {
					var resSum = grandTotals;//sumGrandPagingTotals(this.GeneralDataRows, self.conditions, measures.length, self.formulaInfo, self);
					OAT.addTextNode(td, self.defaultPictureValue(resSum[resSum.length - 1].toString(), true, 0))
					td = self.applyConditionalFormats(td, resSum[resSum.length - 1].toString(), true, 0);
					self.setClickEventHandlers(td, resSum[resSum.length - 1].toString(), "MEASURE", measures.length - 1, 'GrandTotal');
				}
			} else {
				OAT.addTextNode(td, "-")
			}
			tr.appendChild(td);
		}

		this._drawRowTotals = function (tr, GrandTotals, partialGrandtotalsmeasuresList, columnsDataHide) { //for Grand Total only
			var granSumaLateral = []; for (var iGSL = 0; iGSL < measures.length - 1; iGSL++) { granSumaLateral[iGSL] = []; }
			var func = OAT.Statistics[OAT.Statistics.list[self.options.aggTotals].func]; /* statistics */
			if (self.colConditions.length) {
				for (var i = 0; i < self.w; i++) {
					var filteredRowNumber = -1;
					if (self.colConditions.length > 0) {
						for (var fg = 0; fg < measures.length - 1; fg++) {
							var td = OAT.Dom.create("td", {},"gtotal grandtotalvalue");//total
							for (var ti = 0; ti < partialGrandtotalsmeasuresList.length; ti++) {
								if (partialGrandtotalsmeasuresList[ti][2] === i) /*if is the record for this row*/ {
									if (func(partialGrandtotalsmeasuresList[ti][0][fg]) != NaN) { /*partial grand total, the sum of all values from the above row*/
										OAT.addTextNode(td, self.defaultPictureValue(func(partialGrandtotalsmeasuresList[ti][0][fg]).toString(), false, fg))
										td = self.applyConditionalFormats(td, func(partialGrandtotalsmeasuresList[ti][0][fg]).toString(), false, fg);//partialGrandtotalsmeasuresList[ti][1]);
										self.setClickEventHandlers(td, func(partialGrandtotalsmeasuresList[ti][0][fg]).toString(), "MEASURE", fg, ['PartialGrandTotal', partialGrandtotalsmeasuresList[ti][3]]);
										filteredRowNumber = ti;
										granSumaLateral[fg].push(func(partialGrandtotalsmeasuresList[ti][0][fg]));
									} else {
										OAT.addTextNode(td, "-")
									}
								} else {
									if ((partialGrandtotalsmeasuresList[ti][2] == undefined) && (partialGrandtotalsmeasuresList[ti][0][0][fg] != undefined)){
										if (partialGrandtotalsmeasuresList[ti][0][2] === i) {
											var values = [];
											for (var vl = 0; vl < partialGrandtotalsmeasuresList[ti][0][0][fg].length; vl++){
												values.push(partialGrandtotalsmeasuresList[ti][0][0][fg][vl][0])
											}
										
											if (func(values) != NaN) { /*partial grand total, the sum of all values from the above row*/
												OAT.addTextNode(td, self.defaultPictureValue(func(values).toString(), false, fg))
												td = self.applyConditionalFormats(td, func(values).toString(), false, fg);//partialGrandtotalsmeasuresList[ti][1]);
												self.setClickEventHandlers(td, func(values).toString(), "MEASURE", fg, ['PartialGrandTotal', partialGrandtotalsmeasuresList[ti][0][3]]);
												filteredRowNumber = ti;
												granSumaLateral[fg].push(func(values));
											} else {
												OAT.addTextNode(td, "-")
											}
										}
									}
									
									
									
								}
							}
							if (columnsDataHide.indexOf(i) == -1) {
								tr.appendChild(td);
							}
						}
					}

					var td = OAT.Dom.create("td", {}, "gtotal grandtotalvalue");
					if (!isNaN(self.colTotals[0][i]) || self.colTotals[0][i] == "#NuN#" || self.colTotals[0][i] == "#FoE#") {
						OAT.addTextNode(td, self.defaultPictureValue(self.colTotals[0][i].toString(), true, 0))
						td = self.applyConditionalFormats(td, self.colTotals[0][i].toString(), true, 0);
						if (filteredRowNumber != -1) {
							self.setClickEventHandlers(td, self.colTotals[0][i].toString(), "MEASURE", measures.length - 1, ['PartialGrandTotal', partialGrandtotalsmeasuresList[filteredRowNumber][3]]);
						} else {
							self.setClickEventHandlers(td, self.colTotals[0][i].toString(), "MEASURE", measures.length - 1, ['PtrTotals', self.colTotals[1][i]]);
						}
					} else {
						OAT.addTextNode(td, "")
					}
					if (columnsDataHide.indexOf(i) == -1) {
						tr.appendChild(td);
					}
					if (!self.colPointers.length) { continue; }
					var item = self.colPointers[self.colPointers.length - 1][i].parent;
					while (item.parent) {
						var cond = self.conditions[self.colConditions[item.depth]];
						if (cond.subtotals && item.offset + item.spanData - 1 == i) {
							var td = OAT.Dom.create("td", {}, "gtotal grandtotalvalue");
							var tmp = [];
							for (var l = 0; l < item.totals.length; l++) { tmp.push(item.totals[l].array); }

							if (func(tmp) != NaN) {
								OAT.addTextNode(td, self.defaultPictureValue(func(tmp).toString(), true, 0))
								td = self.applyConditionalFormats(td, func(tmp).toString(), true, 0);
								self.setClickEventHandlers(td, func(tmp).toString(), "MEASURE", measures.length - 1, 'GrandTotal');
							} else {
								OAT.addTextNode(td, "-")
							}
							tr.appendChild(td);
						} /* irregular subtotal */
						item = item.parent;
					}
				}
			}


			/* draw grand total for several values*/
			if (self.colConditions.length > 0) {
				for (var ind = 0; ind < measures.length - 1; ind++) {
					var td = OAT.Dom.create("td", {}, "gtotal grandtotalvalue");
					OAT.addTextNode(td, self.defaultPictureValue(func(granSumaLateral[ind]).toString(), false, ind))
					td = self.applyConditionalFormats(td, func(granSumaLateral[ind]).toString(), false, ind);   //
					self.setClickEventHandlers(td, func(granSumaLateral[ind]).toString(), "MEASURE", ind, 'GrandTotal');
					tr.appendChild(td);
				}
			}

			self._drawGTotal(tr, GrandTotals);

		}

		this._drawRowSubtotals = function (tr, i, ptr, subtotalsmeasuresList, td_temp_forCollapseInfo, itemColumnNumber, td_temp_forTotalOfCollapseInfo) { /* subtotals for i-th row */
			var func = OAT.Statistics[OAT.Statistics.list[self.options.aggTotals].func]; /* statistics */
			var partialSubtotals = []; for (var iPS = 0; iPS < measures.length - 1; iPS++) { partialSubtotals[iPS] = [] } //para agregar los valores totales de las ultimas columnas
			for (var k = 0; k < self.w; k++) {
				var td = OAT.Dom.create("td", {}, "gtotal firstlevelvalue");//gtotal
				if (ptr.totals[k].array.length > 0) {				/* sumo valores para filas de subtotales solo si hay valores para sumar si no, se muestran espacios en blanco*/
					if (self.colConditions.length > 0) {
						for (var fg = 0; fg < measures.length - 1; fg++) {
							var td2 = OAT.Dom.create("td", {}, "total");

							if (subtotalsmeasuresList[0] != undefined) {
								for (var colP = 0; colP < subtotalsmeasuresList.length; colP++) {
									if (subtotalsmeasuresList[colP][2] == (k)) {//es la columna que corresponde
										var tempValues = []
										for (var iSML = 0; iSML < subtotalsmeasuresList[colP][0][fg].length; iSML++) {
											if (itemColumnNumber < subtotalsmeasuresList[colP][0][fg][iSML][1]) {
												tempValues.push(subtotalsmeasuresList[colP][0][fg][iSML][0])
												subtotalsmeasuresList[colP][0][fg][iSML][1] = itemColumnNumber
											}
										}
										if ((func(tempValues) != NaN)) {
											OAT.addTextNode(td2, self.defaultPictureValue(func(tempValues).toString(), false, fg))
											td2 = self.applyConditionalFormats(td2, func(tempValues).toString(), false, fg);//subtotalsmeasuresList[0][1]);
											self.setClickEventHandlers(td2, func(tempValues).toString(), "MEASURE", fg, ['PartialGrandTotal', subtotalsmeasuresList[0][3]]);
											partialSubtotals[fg].push(func(tempValues));
										} else {
											OAT.addTextNode(td2, "")
										}

									}
								}
							}
							tr.appendChild(td2);
						}
					}
					OAT.addTextNode(td, self.defaultPictureValue(ptr.totals[k].value.toString(), true, 0))
					if (td_temp_forCollapseInfo) {
						OAT.addTextNode(td_temp_forCollapseInfo, self.defaultPictureValue(ptr.totals[k].value.toString(), true, 0))
					}
					td = self.applyConditionalFormats(td, ptr.totals[k].value.toString(), true, 0);
					self.setClickEventHandlers(td, ptr.totals[k].value.toString(), "MEASURE", measures.length - 1, ['PtrTotals', ptr.totals[k].rows]); //ptr.items has the relation of the filteredRows from this subtotal
				} else {
					if (self.colConditions.length > 0) {
						for (var fg = 0; fg < measures.length - 1; fg++) {
							var td2 = OAT.Dom.create("td", {}, "total");
							OAT.addTextNode(td2, "")
							tr.appendChild(td2);
						}
					}
					OAT.addTextNode(td, "")
				}

				tr.appendChild(td);
				if (!self.colPointers.length) { continue; }
				var item = self.colPointers[self.colPointers.length - 1][k].parent;

				while (item.parent) {
					var cond = self.conditions[self.colConditions[item.depth]];
					if (cond.subtotals && item.offset + item.spanData - 1 == k) {
						var td = OAT.Dom.create("td", {}, "subtotal");
						tr.appendChild(td);
						var tmp = [];
						for (var l = 0; l < ptr.totals.length; l++) {
							if (l >= item.offset && l < item.spanData + item.offset) { tmp.push(ptr.totals[l].array); }
						} /* for all possible totals of this row */

						if (func(tmp) != NaN) {
							OAT.addTextNode(td, self.defaultPictureValue(func(tmp).toString(), true, 0))
							td = self.applyConditionalFormats(td, func(tmp).toString(), true, 0);
							self.setClickEventHandlers(td, func(tmp).toString(), "MEASURE", measures.length - 1, '');
						} else {
							OAT.addTextNode(td, "-")
						}
					} /* irregular subtotal */
					item = item.parent;
				}
			} /* for all regular subtotals */

			/* here the value for the latest columns of a subtotal row*/
			if (self.options.totals && self.colConditions.length) {

				if (self.colConditions.length > 0) {
					var td = OAT.Dom.create("td", {}, "total"); /* here the first measures (as rowConditions) */
					for (var ind = 0; ind < measures.length - 1; ind++) {

						var td = OAT.Dom.create("td", {}, "total");
						var tmp = partialSubtotals[ind];
						if (func(tmp) != NaN) {
							OAT.addTextNode(td, self.defaultPictureValue(func(tmp).toString(), false, ind))
							td = self.applyConditionalFormats(td, func(tmp).toString(), false, ind);
						} else {
							OAT.addTextNode(td, "-")
						}
						tr.appendChild(td);


					}
				}

				var tmp = [];
				for (var l = 0; l < ptr.totals.length; l++) { tmp.push(ptr.totals[l].array); }
				var td = OAT.Dom.create("td", {}, "total");

				if (self.formulaInfo.measureFormula[measures.length - 1].hasFormula) {
					var totals_ = self.calculateFormulaTotal(tmp, measures.length - 1, "MeasureInRows");
					if ((totals_ != NaN) && (!isNaN(totals_))) {
						OAT.addTextNode(td, self.defaultPictureValue(totals_.toString(), true, 0))
						td = self.applyConditionalFormats(td, totals_.toString(), true, 0);
						self.setClickEventHandlers(td, totals_.toString(), "MEASURE", measures.length - 1, '');
					} else {
						OAT.addTextNode(td, "-")
					}
				} else {
					if (func(tmp) != NaN) {
						OAT.addTextNode(td, self.defaultPictureValue(func(tmp).toString(), true, 0))
						if (td_temp_forTotalOfCollapseInfo) {
							OAT.addTextNode(td_temp_forTotalOfCollapseInfo, self.defaultPictureValue(func(tmp).toString(), true, 0))
							td_temp_forTotalOfCollapseInfo = false;
						}
						td = self.applyConditionalFormats(td, func(tmp).toString(), true, 0);
						self.setClickEventHandlers(td, func(tmp).toString(), "MEASURE", measures.length - 1, '');
					} else {
						OAT.addTextNode(td, "-")
					}
				}
				tr.appendChild(td);
			}
		}

		this._drawRowSubtotalsAutoPaging = function (tr, subtotals) { /* subtotals for i-th row */
			for (var fg = 0; fg < subtotals.length; fg++) {
				var lastMeasure = (fg == subtotals.length - 1) ? true : false;
				var td2 = OAT.Dom.create("td", {}, "total");
				if (subtotals[fg] != NaN) {
					OAT.addTextNode(td2, self.defaultPictureValue(subtotals[fg].toString(), lastMeasure, fg))
					td2 = self.applyConditionalFormats(td2, subtotals[fg].toString(), lastMeasure, fg);
					self.setClickEventHandlers(td2, subtotals[fg].toString(), "MEASURE", fg, '');
				} else {
					OAT.addTextNode(td2, " ")
				}
				tr.appendChild(td2);
			}

		}

		this._sumValuesInDept = function (item, dept, array) {
			if (dept === 0) {
				var items = item.items;
				var totals_ = 0;
				if (items != false) {
					for (var iv = 0; iv < items.length; iv++) {
						totals_ = totals_ + parseFloat(items[iv].value);
						if (items[iv].value == "#NuN#") {
							array.push("#NuN#");
						} else {
							array.push(parseFloat(items[iv].value));
						}
					}
				} else {
					array.push(parseFloat(item.value));
					return parseFloat(item.value);
				}
				return totals_
			} else {
				var subitems = item.items;
				var subtotals_ = 0;
				for (var iv = 0; iv < subitems.length; iv++) {
					subtotals_ = subtotals_ + self._sumValuesInDept(subitems[iv], dept - 1, array);
				}
				return subtotals_
			}
		}

		this._sumValuesInDeptFormula = function (item, dept, array, dimNum) {
			if (dept === 0) {
				var items = item.items;
				if (items != false) {
					for (var iv = 0; iv < items.length; iv++) {
						var ref = items[iv];
						for (var l = 0; l < dimNum; l++) {
							ref = ref.parent
						}
						var addRow = self.getFormulaRowByCoord(ref, [], dimNum, "")
						array.push([addRow]);
					}
				} else {
					var addRow = self.getFormulaRowByCoord(items[iv], [], dimNum, "")
					array.push([addRow]);
					return
				}
				return
			} else {
				var subitems = item.items;
				var subtotals_ = 0;
				for (var iv = 0; iv < subitems.length; iv++) {
					self._sumValuesInDeptFormula(subitems[iv], dept - 1, array, dimNum);
				}
				return
			}
		}

		this._drawRowSubtotalsForMeasures = function (tr, i, ptr, dept, dimNum, th, td_collection_forCollapseInfo) { // subtotals for i-th row Idem al anterior pero calcula medidas para mesaures

			var func = OAT.Statistics[OAT.Statistics.list[self.options.aggTotals].func]; // statistics 
			var td = OAT.Dom.create("td", {}, "gtotal firstlevelvalue");//subtotal
			var _measureNumber = dept;
			var cantDimensions = self.rowConditions.length - (measures.length - 1); //esta es la cantidad de dimensiones, es decir columnas iniciales que no son valores

			if ((cantDimensions >= 3) && (dimNum != -1)) {
				dept = (cantDimensions - dimNum) + dept - 1;
			} else {
				dept = cantDimensions - 1 + dept; //"quito" el primer y sumo profundidad de esta mesearue
			}

			var tmp = [];
			if (self.formulaInfo.measureFormula[_measureNumber].hasFormula) {
				var totals_ = self._sumValuesInDeptFormula(ptr, dept, tmp, _measureNumber);
			} else {
				var totals_ = self._sumValuesInDept(ptr, dept, tmp);
			}
			var y;
			if (tmp.length > 0) {
				if (self.formulaInfo.measureFormula[_measureNumber].hasFormula) {
					var res = self.calculateFormulaTotal(tmp, _measureNumber, "MeasureInRows")
					if (res != NaN) {
						OAT.addTextNode(td, self.defaultPictureValue(res.toString(), false, _measureNumber))
						td = self.applyConditionalFormats(td, res.toString(), false, _measureNumber); //before: dept
						self.setClickEventHandlers(td, res.toString(), "MEASURE", _measureNumber, ['PtrTotals', ptr.filtrows]);
						if (th != undefined) {
							self.setClickEventHandlers(th, th.textContent, "DIMENSION", _measureNumber, ['PtrTotals', ptr.filtrows]);
						}
					} else {
						OAT.addTextNode(td, "")
					}
				} else {
					if (func(tmp) != NaN) {
						OAT.addTextNode(td, self.defaultPictureValue(func(tmp).toString(), false, _measureNumber))
						td = self.applyConditionalFormats(td, func(tmp).toString(), false, _measureNumber); //before: dept
						self.setClickEventHandlers(td, func(tmp).toString(), "MEASURE", _measureNumber, ['PtrTotals', ptr.filtrows]);
						if (th != undefined) {
							self.setClickEventHandlers(th, th.textContent, "DIMENSION", _measureNumber, ['PtrTotals', ptr.filtrows]);
						}
					} else {
						OAT.addTextNode(td, "")
					}
				}
			} else {
				OAT.addTextNode(td, "")
			}

			if ((td_collection_forCollapseInfo != undefined) && (td_collection_forCollapseInfo[_measureNumber])) {
				OAT.addTextNode(td_collection_forCollapseInfo[_measureNumber], td.textContent)
				td_collection_forCollapseInfo[_measureNumber] = false
			}

			tr.appendChild(td);
		}


		this._drawCorner = function (th, target) {
			if (measures.length > 0) {
				OAT.addTextNode(th, self.headerRow[self.dataColumnIndex])
				th.className = "h2titlewhite";
				this.setTitleTexrtAlign(th, th.textContent);
			}
		}

		this._drawCornerCustom = function (th, target) {
			OAT.addTextNode(th, "")
			th.className = "h2titlewhite";
			this.setTitleTexrtAlign(th, th.textContent);
		}

		this._drawRowConditionsHeadingsCustom = function (tr) {
			/* rowConditions headings */
			for (var j = 0; j < self.rowConditions.length; j++) {
				var cond = self.conditions[self.rowConditions[j]];
				if (self.isMeasureByName(self.headerRow[self.rowConditions[j]])) {
					if (!self.ShowMeasuresAsRows) {
						var th = OAT.Dom.create("th", {}, "h2titlewhite");
						var div = OAT.Dom.create("div");
						OAT.addTextNode(div, self.headerRow[self.rowConditions[j]])
						this.setTitleTexrtAlign(div, self.headerRow[self.rowConditions[j]]);
						th.rowSpan = self.colConditions.length + 2;
					}
				} else {
					var th = OAT.Dom.create("th", {}, "h2title");
					var divCont = OAT.Dom.create("div", { position: "relative" });

					var div = OAT.Dom.create("div", { overflow: "hidden" });
					if (!self.serverPagination) {
						OAT.addTextNode(div, self.headerRow[self.rowConditions[j]] + "\u00A0\u00A0\u00A0")
					} else {
						OAT.addTextNode(div, self.headerRow[self.rowConditions[j]].replace(/ /g, "\u00A0") + "\u00A0\u00A0\u00A0\u00A0")
					}
					if ((self.GeneralDataRows.length > 0) || (self.serverPagination)) {
						var resp = self.getClickReference(cond, self.rowConditions[j], div);
						var ref = resp[0]
						var anchorRef = resp[1]
						OAT.Dom.attach(th, "click", ref);
						var callback = self.getOrderReference(self.rowConditions[j], anchorRef, ref, div);
						self.gd.addSource(div, self.process, callback);
						self.gd.addTarget(th);
					}
					th.conditionIndex = self.rowConditions[j];
					if (!self.ShowMeasuresAsRows) {
						th.rowSpan = self.colConditions.length + 2;
					} else {
						th.rowSpan = self.colConditions.length + 1;
					}

					var divImg = OAT.Dom.create("div", { position: "absolute", right: "-6px", bottom: "0px"});
					OAT.addImageNode(divImg, "arrow_drop_up", "");
					try {
						this.updateSortImage(divImg, cond.sort);
					} catch (Error) { }
					OAT.Dom.append([th, divCont], [divCont, div], [divCont, divImg], [tr, th]);
				}
			}
			if (self.ShowMeasuresAsRows) //add title of Measure
			{
				var largo = 80;
				var th = OAT.Dom.create("th", {}, "h2title");
				var divCont = OAT.Dom.create("div", { position: "relative", width: largo + "px" });
				var div = OAT.Dom.create("div", { overflow: "hidden" });
				OAT.addTextNode(div, gx.getMessage("GXPL_QViewerJSMeasures") + "\u00A0\u00A0\u00A0")
				OAT.Dom.append([th, divCont], [divCont, div], [tr, th]);
				th.rowSpan = self.colConditions.length + 1;
				OAT.Dom.append([th, div], [tr, th]);
			}
		}

		this.isMeasureByName = function (headerName) {
			var ismeasure = false;
			for (var i = 0; i < measures.length - 1; i++) {
				if (measures[i].attributes.getNamedItem("displayName").nodeValue == headerName) {
					ismeasure = true;
				}
			}
			return ismeasure;
		}

		this.setTitleTexrtAlign = function (div, header) {
			for (var i = 0; i < measures.length; i++) {
				if (measures[i].getAttribute("displayName") === header) {
					if ((measures[i].getAttribute("dataType") === "integer") || (measures[i].getAttribute("dataType") === "real")) {
						div.style.textAlign = "right"
					}
					if (measures[i].getAttribute("date") === "integer") {
						div.style.textAlign = "left"
					}
				}
			}
		}

		this.updateSortImage = function (div, order) {
			var path = "none";
			switch (order) {
				case 0: path = "asc"; break;
				case 1: path = "asc"; break;   
				case -1: path = "desc"; break; 
				case 2: path = "desc"; break;
			}

			var ua = navigator.userAgent.toLowerCase();
			var isAndroid = ua.indexOf("android") > -1;
			if (gx.util.browser.isIE() || (isAndroid)) {
				div.className.replace("sort-none");
				div.className.replace("sort-asc");
				div.className.replace("sort-desc");
			} else {
				div.classList.remove("sort-none");
				div.classList.remove("sort-asc");
				div.classList.remove("sort-desc");
			}
			if (gx.util.browser.isIE() || (isAndroid)) {
				div.className += " sort-" + path;
			} else {
				div.classList.add("sort-" + path);
			}
			jQuery(div).find("i")[0].textContent = (path == "asc") ? "arrow_drop_up" : "arrow_drop_down";
		}

		this._drawRowConditionsHeadings = function (tbody) {
			/* rowConditions headings */
			var tr = OAT.Dom.create("tr");
			for (var j = 0; j < self.rowConditions.length; j++) {
				var cond = self.conditions[self.rowConditions[j]];
				if (self.isMeasureByName(self.headerRow[self.rowConditions[j]])) {
					if (!self.ShowMeasuresAsRows) {
						var th = OAT.Dom.create("th", {}, "h2titlewhite");
						var div = OAT.Dom.create("div");
						OAT.addTextNode(div, self.headerRow[self.rowConditions[j]])
						self.setTitleTexrtAlign(div, self.headerRow[self.rowConditions[j]]);
						OAT.Dom.append([th, div], [tr, th]);
					}
				} else {
					var largo = (self.headerRow[self.rowConditions[j]].length > 8) ? self.headerRow[self.rowConditions[j]].length * 10 : 80;
					var th = OAT.Dom.create("th", {}, "h2title");
					var divCont = OAT.Dom.create("div", { position: "relative", width: largo + "px" });
					var div = OAT.Dom.create("div", { overflow: "hidden" });
					OAT.addTextNode(div, self.headerRow[self.rowConditions[j]] + "\u00A0\u00A0\u00A0")
					var resp = self.getClickReference(cond, self.rowConditions[j], div);
					var ref = resp[0]
					var anchorRef = resp[1]
					OAT.Dom.attach(th, "click", ref);
					var callback = self.getOrderReference(self.rowConditions[j], anchorRef, ref, div);
					self.gd.addSource(div, self.process, callback);
					self.gd.addTarget(th);
					th.conditionIndex = self.rowConditions[j];

					var divImg = OAT.Dom.create("div", { position: "absolute", right: "-6px", bottom: "0px"});
					OAT.addImageNode(divImg, "arrow_drop_up", "");
					if (cond != undefined) {
						this.updateSortImage(divImg, cond.sort);
					} else {
						this.updateSortImage(divImg, 0);
					}

					OAT.Dom.append([th, divCont], [divCont, div], [divCont, divImg], [tr, th]);
				}
			}


			if (self.ShowMeasuresAsRows) {
				//"Measure" Title
				var largo = 80;
				var th = OAT.Dom.create("th", {}, "h2title");
				var divCont = OAT.Dom.create("div", { position: "relative", width: largo + "px" });
				var div = OAT.Dom.create("div", { overflow: "hidden" });

				OAT.addTextNode(div, gx.getMessage("GXPL_QViewerJSMeasures") + "\u00A0\u00A0\u00A0")
				OAT.Dom.append([th, divCont], [divCont, div], [tr, th]);
				//"Value" Title
				var th = OAT.Dom.create("th", {}, "h2titlewhite");
				var div = OAT.Dom.create("div");

				OAT.addTextNode(div, gx.getMessage("GXPL_QViewerJSValue"))
				th.style.textAlign = "right"
				OAT.Dom.append([th, div], [tr, th]);
			}


			var th = OAT.Dom.create("th"); /* blank space above */
			if (!self.colConditions.length) {
				self._drawCorner(th, true);
				th.conditionIndex = -1;
			} else { th.style.border = "none"; }
			if (self.colStructure.span != null) {
				th.colSpan = self.colStructure.span + (self.options.headingBefore ? 1 : 0) + (self.options.totals ? 1 : 0);
			} else {
				th.colSpan = (self.options.headingBefore ? 1 : 0) + (self.options.totals ? 1 : 0);
			}
			if ((measures.length > 0) && (!self.ShowMeasuresAsRows)) {
				tr.appendChild(th);
			}
			if (self.colConditions.length) { /* blank space after */
				var th = OAT.Dom.create("th", { border: "none", width: "0px;" });
				//th.hidden = true;
				tr.appendChild(th);
			}
			if ((measures.length > 0) && (tr.cells[1] != undefined) && (tr.cells[1].textContent == "")) { tr.hidden = true; } //hideemptycolrow
			else {
				self.appendRowToTable(tbody, tr, true);
				//tbody.appendChild(tr);
			}
			/////////////////////////////////////////////////// MOVE FILTERS TO TOOLBAR
			if ((measures.length > 0) && (tr.cells[1] != undefined) && (tr.cells[1].textContent == "")) {
				var toolbarTable = document.getElementById(self.controlName + "_" + self.query + "_toolbar");
				toolbarTable.rows[0].appendChild(tr.cells[0]);
			}
			/////////////////////////////////////////////////// MOVE FILTERS TO TOOLBAR
		}

		this._drawColConditionsHeadingsCustom = function (tr, i, last) {
			var cond = self.conditions[self.colConditions[i]];
			var th = OAT.Dom.create("th", { cursor: "pointer" }, "h2title");
			var largo = (self.headerRow[self.colConditions[i]].length > 8) ? ((self.headerRow[self.colConditions[i]].length + 3) * 10) : 80;
			var divCont = OAT.Dom.create("div", { position: "relative", width: largo + "px" });
			if (last) {
				th.style.borderRightColor = "transparent";
			}
			var div = OAT.Dom.create("div", { overflow: "hidden" });
			if (!self.serverPagination) {
				OAT.addTextNode(div, self.headerRow[self.colConditions[i]] + "\u00A0\u00A0")
			} else {
				OAT.addTextNode(div, self.headerRow[self.colConditions[i]].replace(/ /g, "\u00A0") + "\u00A0\u00A0\u00A0")
			}
			if ((self.GeneralDataRows.length > 0) || (self.serverPagination)) {
				var resp = self.getClickReference(cond, self.colConditions[i], div);
				var ref = resp[0]
				var anchorRef = resp[1]

				OAT.Dom.attach(th, "click", ref);
				var callback = self.getOrderReference(self.colConditions[i], anchorRef, ref, div);
				self.gd.addSource(div, self.process, callback);
				self.gd.addTarget(th);
			}

			var divImg = OAT.Dom.create("div", { position: "absolute", right: "0px", bottom: "2px", width: "12px", height: "12px" });
			OAT.addImageNode(divImg, "arrow_drop_up", "");
			try {
				this.updateSortImage(divImg, cond.sort);
			} catch (error) { }
			divCont.appendChild(div);
			
			divCont.appendChild(divImg);
			

			th.conditionIndex = self.colConditions[i];
			th.appendChild(divCont);
			//th.hidden = true;
			tr.appendChild(th);

			return tr;
		}

		this._drawColConditionsHeadings = function (tr, i) {
			var cond = self.conditions[self.colConditions[i]];
			var th = OAT.Dom.create("th", { cursor: "pointer" }, "even gx-pv-even-row");
			var div = OAT.Dom.create("div");
			OAT.addTextNode(div, self.headerRow[self.colConditions[i]])
			var resp = self.getClickReference(cond, self.colConditions[i], div);
			var ref = resp[0]
			var anchorRef = resp[1]
			OAT.Dom.attach(th, "click", ref);
			var callback = self.getOrderReference(self.colConditions[i], anchorRef, ref, div);
			self.gd.addSource(div, self.process, callback);
			self.gd.addTarget(th);
			th.conditionIndex = self.colConditions[i];
			th.appendChild(div);
			th.hidden = true;


			/////////////////////////////////////////////////// MOVE FILTERS TO TOOLBAR
			if (th.textContent == self.headerRow[self.colConditions[i]]) {
				var toolbarTable = document.getElementById(self.controlName + "_" + self.query + "_toolbar");
				th.hidden = false;
				toolbarTable.rows[0].appendChild(th);
			}
			/////////////////////////////////////////////////// MOVE FILTERS TO TOOLBAR
		}

		this.getClassName = function (i, j) { /* decide odd/even class */
			return "even gx-pv-even-row";
		}

		this.setStyleValues = function (elem, styleValues) {
			function hexToRgb(hex) {
				// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
				var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
				hex = hex.replace(shorthandRegex, function (m, r, g, b) {
					return r + r + g + g + b + b;
				});

				var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
				return result ? {
					r: parseInt(result[1], 16),
					g: parseInt(result[2], 16),
					b: parseInt(result[3], 16)
				} : null;
			}

			var styleSplit = styleValues.split(";");
			for (var j = 0; j < styleSplit.length; j++) {
				var particularStyleSplit = styleSplit[j].split(":");

				switch (particularStyleSplit[0]) {
					case "color": if ((particularStyleSplit[1][0] != undefined) && (particularStyleSplit[1][0] === '#')) {
						elem.style.color = 'rgb(' + hexToRgb(particularStyleSplit[1]).r + ',' + hexToRgb(particularStyleSplit[1]).g + ',' + hexToRgb(particularStyleSplit[1]).b + ')'
					} else {
						elem.style.color = particularStyleSplit[1];
					}
						break;
					case "fontStyle": elem.style.fontStyle = particularStyleSplit[1];
						break;
					case "backgroundColor": elem.style.backgroundColor = particularStyleSplit[1];
						break;
					case "textDecoration": elem.style.textDecoration = particularStyleSplit[1];
						break;
					case "fontWeight": elem.style.fontWeight = particularStyleSplit[1];
						break;
					case "fontFamily": elem.style.fontFamily = particularStyleSplit[1];
						break;
					case "fontVariant": elem.style.fontVariant = particularStyleSplit[1];
						break;
					case "fontSize": elem.style.fontSize = particularStyleSplit[1].replace("px", "") + "px";
						break;
					case "textAlign": elem.style.textAlign = particularStyleSplit[1];
						break;
					case "lineHeight": elem.style.lineHeight = particularStyleSplit[1];
						break;
					case "textIndent": elem.style.textIndent = particularStyleSplit[1];
						break;
					case "verticalAlign": elem.style.verticalAlign = particularStyleSplit[1];
						break;
					case "wordSpacing": elem.style.wordSpacing = particularStyleSplit[1];
						break;
					case "display": elem.style.display = particularStyleSplit[1];
						break;
					case "borderThickness": elem.style.borderThickness = particularStyleSplit[1];
						elem.style.borderWidth = particularStyleSplit[1] + "px";
						break;
					case "borderColor": elem.style.borderColor = particularStyleSplit[1];
						break;
					case "borderWith": elem.style.borderWith = particularStyleSplit[1];
						break;
					case "borderStyle": elem.style.borderStyle = particularStyleSplit[1];
						break;
					case "padding": elem.style.padding = particularStyleSplit[1];
						break;
					case "paddingBottom": elem.style.paddingBottom = particularStyleSplit[1];
						break;
					case "paddingLeft": elem.style.paddingLeft = particularStyleSplit[1];
						break;
					case "paddingRight": elem.style.paddingRight = particularStyleSplit[1];
						break;
					case "paddingTop": elem.style.paddingTop = particularStyleSplit[1];
						break;
				}
			}
			return elem;
		}

		this.underRecursionStyle = false;
		this.applyFormatValues = function (th, value, columnNumber) { /* Format for dimensions ("header columns") */
			//apply default format
			var defaultFormats = self.columns[columnNumber].getAttribute("format");
			if ((defaultFormats != null) && (defaultFormats != "")) {
				th = self.setStyleValues(th, defaultFormats);
			}
			//apply format value
			self.underRecursionStyle = false;
			for (var i = 0; i < self.formatValues.length; i++) {
				if (self.formatValues[i].columnNumber == columnNumber) { //a format for this column
					if (self.formatValues[i].value === value.trimpivot()) {
						th = self.setStyleValues(th, self.formatValues[i].format);
						if ((self.formatValues[i].recursive != undefined) && (self.formatValues[i].recursive == "yes")) {
							self.underRecursionStyle = true;
						}
					}
				}
			}
			var measureDataType = self.columns[columnNumber].getAttribute("dataType");
			//apply conditional values
			var equal = [];
			var notequal = [];
			var greaterThan = [];
			var greaterOrEqual = [];
			var lessThan = [];
			var lessOrEqual = [];
			var greaterOrEqual = [];
			var between = [];
			for (var i = 0; i < self.conditionalFormatsColumns.length; i++) {
				if (self.conditionalFormatsColumns[i].columnNumber == columnNumber) {
					if (self.conditionalFormatsColumns[i].operation1 == "equal") {
						if ((measureDataType === "real") || (measureDataType === "integer")) {
							equal[0] = parseFloat(self.conditionalFormatsColumns[i].value1);
						} else {
							equal[0] = self.conditionalFormatsColumns[i].value1
						}
						equal[1] = self.conditionalFormatsColumns[i].format;
					}
					if (self.conditionalFormatsColumns[i].operation1 == "notequal") {
						if ((measureDataType === "real") || (measureDataType === "integer")) {
							notequal[0] = parseFloat(self.conditionalFormatsColumns[i].value1);
						} else {
							notequal[0] = self.conditionalFormatsColumns[i].value1
						}
						notequal[1] = self.conditionalFormatsColumns[i].format;
					}
					if (self.conditionalFormatsColumns[i].operation1 == "less") {
						if ((measureDataType === "real") || (measureDataType === "integer")) {
							lessThan[0] = parseFloat(self.conditionalFormatsColumns[i].value1);
						} else {
							lessThan[0] = self.conditionalFormatsColumns[i].value1;
						}
						lessThan[1] = self.conditionalFormatsColumns[i].format;
					}
					if (self.conditionalFormatsColumns[i].operation1 == "greater") {
						if ((measureDataType === "real") || (measureDataType === "integer")) {
							greaterThan[0] = parseFloat(self.conditionalFormatsColumns[i].value1);
						} else {
							greaterThan[0] = self.conditionalFormatsColumns[i].value1;
						}
						greaterThan[1] = self.conditionalFormatsColumns[i].format;
					}
					if ((self.conditionalFormatsColumns[i].operation1 == "greaterequal") && (self.conditionalFormatsColumns[i].operation2 == undefined)) {
						if ((measureDataType === "real") || (measureDataType === "integer")) {
							greaterOrEqual[0] = parseFloat(self.conditionalFormatsColumns[i].value1);
						} else {
							greaterOrEqual[0] = self.conditionalFormatsColumns[i].value1;
						}
						greaterThan[1] = self.conditionalFormatsColumns[i].format;
					}
					if (self.conditionalFormatsColumns[i].operation1 == "lessequal") {
						if ((measureDataType === "real") || (measureDataType === "integer")) {
							lessOrEqual[0] = parseFloat(self.conditionalFormatsColumns[i].value1);
						} else {
							lessOrEqual[0] = self.conditionalFormatsColumns[i].value1
						}
						lessThan[1] = self.conditionalFormatsColumns[i].format;
					}
					if (self.conditionalFormatsColumns[i].operation2 && self.conditionalFormatsColumns[i].operation1 == "greaterequal") {  //when interval
						//greaterOrEqual = []
						if ((measureDataType === "real") || (measureDataType === "integer")) {
							between[0] = parseFloat(self.conditionalFormatsColumns[i].value1);
						} else {
							between[0] = self.conditionalFormatsColumns[i].value1;
						}
						if (self.conditionalFormatsColumns[i].operation2 && self.conditionalFormatsColumns[i].operation2 == "lessequal") {
							if ((measureDataType === "real") || (measureDataType === "integer")) {
								between[1] = parseFloat(self.conditionalFormatsColumns[i].value2);
							} else {
								between[1] = self.conditionalFormatsColumns[i].value2;
							}
							between[2] = self.conditionalFormatsColumns[i].format;
						}
					}
				}
			}

			var comparisons = new Array(3);

			th.style.textAlign = "left";
			if (measureDataType === "real") {
				th.style.textAlign = "left";
				value = parseFloat(value);
			}

			if (measureDataType === "integer") {

				th.style.textAlign = "right";
				value = parseInt(value);

			}

			if (measureDataType === "real") {
				th.style.textAlign = "right";
			}

			if (measureDataType != "date") {
				if ((equal[0] != undefined) && (value == equal[0])) {
					th = self.setStyleValues(th, equal[1]);
				}
				if ((notequal[0] != undefined) && (value != notequal[0])) {
					th = self.setStyleValues(th, notequal[1]);
				}
				if (((greaterThan[0] != undefined) && (value > greaterThan[0])) ||
					((greaterOrEqual[0] != undefined) && (value >= greaterOrEqual[0]))) {
					th = self.setStyleValues(th, greaterThan[1]);
				}
				if (((lessThan[0] != undefined) && (value < lessThan[0])) ||
					((lessOrEqual[0] != undefined) && (value <= lessOrEqual[0]))) {
					th = self.setStyleValues(th, lessThan[1]);
				}
				if ((between[0] != undefined && between[1] != undefined) && (value >= between[0] && value <= between[1])) {
					th = self.setStyleValues(th, between[2]);
				}
				return th;
			}


			if (measureDataType === "date") {
				th.style.textAlign = "right";
				var dates = value.split("-");
				if ((self.defaultPicture.getAttribute("dateFormat") != undefined) && (self.defaultPicture.getAttribute("dateFormat") != null)) {
					picture = self.defaultPicture.getAttribute("dateFormat").split("");
				}
				var dateElements = new Array(3);
				dateElements[0] = parseInt(dates[0]);
				dateElements[1] = parseInt(dates[1]);
				dateElements[2] = parseInt(dates[2]);


				if ((greaterThan[0] != undefined)) {
					var cmpar = greaterThan[0].split("-");
					var cmparElements = new Array(3);
					cmparElements[1] = parseInt(cmpar[1]);
					cmparElements[2] = parseInt(cmpar[2]);
					cmparElements[0] = parseInt(cmpar[0]);

					if ((cmparElements[0] < dateElements[0]) || ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] < dateElements[1]))
						|| ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] <= dateElements[1]) && (cmparElements[2] < dateElements[2]))) {
						th = self.setStyleValues(th, greaterThan[1]);
					}

				}


				if ((lessThan[0] != undefined)) {
					var cmpar = lessThan[0].split("-");
					cmparElements = new Array(3);
					cmparElements[1] = parseInt(cmpar[1]);
					cmparElements[2] = parseInt(cmpar[2]);
					cmparElements[0] = parseInt(cmpar[0]);

					if ((cmparElements[0] > dateElements[0]) || ((cmparElements[0] >= dateElements[0]) && (cmparElements[1] > dateElements[1]))
						|| ((cmparElements[0] >= dateElements[0]) && (cmparElements[1] >= dateElements[1]) && (cmparElements[2] > dateElements[2]))) {
						th = self.setStyleValues(th, lessThan[1]);
					}

				}

				if ((between[0] != undefined) && (between[1] != undefined)) {
					var cmpar = between[0].split("-");
					var cmpar2 = between[1].split("-");
					cmparElements = new Array(3);
					cmparElements2 = new Array(3);
					cmparElements[1] = parseInt(cmpar[1]);
					cmparElements[2] = parseInt(cmpar[2]);
					cmparElements[0] = parseInt(cmpar[0]);

					cmparElements2[1] = parseInt(cmpar2[1]);
					cmparElements2[2] = parseInt(cmpar2[2]);
					cmparElements2[0] = parseInt(cmpar2[0]);

					if (((cmparElements[0] <= dateElements[0]) || ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] < dateElements[1]))
						|| ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] <= dateElements[1]) && (cmparElements[2] < dateElements[2])))
						&&
						((cmparElements2[0] > dateElements[0]) || ((cmparElements2[0] >= dateElements[0]) && (cmparElements2[1] > dateElements[1]))
							|| ((cmparElements2[0] >= dateElements[0]) && (cmparElements2[1] >= dateElements[1]) && (cmparElements2[2] > dateElements[2])))
					) {
						th = self.setStyleValues(th, between[2]);
					}

				}

			}


			if (value > greaterThan[0]) {
				th = self.setStyleValues(th, greaterThan[1]);
			} else {
				if (value < lessThan[0]) {
					th = self.setStyleValues(th, lessThan[1]);
				} else {
					if (value >= between[0] && value <= between[1]) {
						th = self.setStyleValues(th, between[2]);
					}
				}
			}

			return th;
		}

		this.applyConditionalFormats = function (td, value, lastMEasure, measureNumber) { /* format for measures (row data) */
			if (measures.length > 0) {
				var defaultFormats;
				var measureDataType;
				if (lastMEasure) {
					measureNumber = measures.length - 1;
					measureDataType = measures[measures.length - 1].getAttribute("dataType");
					defaultFormats = measures[measures.length - 1].getAttribute("format");
				} else {
					measureDataType = measures[measureNumber].getAttribute("dataType");
					defaultFormats = measures[measureNumber].getAttribute("format");
				}

				//apply default format
				if ((defaultFormats != null) && (defaultFormats != "")) {
					td = self.setStyleValues(td, defaultFormats);
				}

				//apply format value
				for (var i = 0; i < self.formatValuesMeasures.length; i++) {
					if (self.formatValuesMeasures[i].columnNumber == measureNumber) { //a format for this column
						if (self.formatValuesMeasures[i].value === value) {
							td = self.setStyleValues(td, self.formatValuesMeasures[i].format);
						}
					}
				}

				if (self.underRecursionStyle) {
					for (var i = 0; i < self.formatValues.length; i++) {
						td = self.setStyleValues(td, self.formatValues[i].format);
					}
				}
				//apply conditional values
				var equal = [];
				var notequal = [];
				var greaterThan = [];
				var greaterOrEqual = [];
				var lessThan = [];
				var lessOrEqual = [];
				var greaterOrEqual = [];
				var between = [];
				for (var i = 0; i < self.conditionalFormats.length; i++) {
					if (self.conditionalFormats[i].columnNumber == measureNumber) {
						if (self.conditionalFormats[i].operation1 == "equal") {
							if ((measureDataType === "real") || (measureDataType === "integer")) {
								equal[0] = parseFloat(self.conditionalFormats[i].value1);
							} else {
								equal[0] = self.conditionalFormats[i].value1
							}
							equal[1] = self.conditionalFormats[i].format;
						}
						if (self.conditionalFormats[i].operation1 == "notequal") {
							if ((measureDataType === "real") || (measureDataType === "integer")) {
								notequal[0] = parseFloat(self.conditionalFormats[i].value1);
							} else {
								notequal[0] = self.conditionalFormats[i].value1
							}
							notequal[1] = self.conditionalFormats[i].format;
						}
						if (self.conditionalFormats[i].operation1 == "less") {
							if ((measureDataType === "real") || (measureDataType === "integer")) {
								lessThan[0] = parseFloat(self.conditionalFormats[i].value1);
							} else {
								lessThan[0] = self.conditionalFormats[i].value1
							}
							lessThan[1] = self.conditionalFormats[i].format;
						}
						if (self.conditionalFormats[i].operation1 == "lessequal") {
							if ((measureDataType === "real") || (measureDataType === "integer")) {
								lessOrEqual[0] = parseFloat(self.conditionalFormats[i].value1);
							} else {
								lessOrEqual[0] = self.conditionalFormats[i].value1
							}
							lessThan[1] = self.conditionalFormats[i].format;
						}
						if (self.conditionalFormats[i].operation1 == "greater") {
							if ((measureDataType === "real") || (measureDataType === "integer")) {
								greaterThan[0] = parseFloat(self.conditionalFormats[i].value1);
							} else {
								greaterThan[0] = self.conditionalFormats[i].value1;
							}
							greaterThan[1] = self.conditionalFormats[i].format;
						}
						if (self.conditionalFormats[i].operation1 == "greaterequal") {
							if ((measureDataType === "real") || (measureDataType === "integer")) {
								greaterOrEqual[0] = parseFloat(self.conditionalFormats[i].value1);
							} else {
								greaterOrEqual[0] = self.conditionalFormats[i].value1;
							}
							greaterThan[1] = self.conditionalFormats[i].format;
						}
						if (self.conditionalFormats[i].operation2 && self.conditionalFormats[i].operation1 == "greaterequal") {  //when interval
							greaterOrEqual = []
							if ((measureDataType === "real") || (measureDataType === "integer")) {
								between[0] = parseFloat(self.conditionalFormats[i].value1);
							} else {
								between[0] = self.conditionalFormats[i].value1;
							}
							if (self.conditionalFormats[i].operation2 && self.conditionalFormats[i].operation2 == "lessequal") {
								if ((measureDataType === "real") || (measureDataType === "integer")) {
									between[1] = parseFloat(self.conditionalFormats[i].value2);
								} else {
									between[1] = self.conditionalFormats[i].value2;
								}
								between[2] = self.conditionalFormats[i].format;
							}
						}
					}
				}

				if (measureDataType != "date") {
					if ((equal[0] != undefined) && (value == equal[0])) {
						td = self.setStyleValues(td, equal[1]);
					}
					if ((notequal[0] != undefined) && (value != notequal[0])) {
						td = self.setStyleValues(td, notequal[1]);
					}
					if (((greaterThan[0] != undefined) && (value > greaterThan[0])) ||
						((greaterOrEqual[0] != undefined) && (value >= greaterOrEqual[0]))) {
						td = self.setStyleValues(td, greaterThan[1]);
					}
					if (((lessThan[0] != undefined) && (value < lessThan[0])) ||
						((lessOrEqual[0] != undefined) && (value <= lessOrEqual[0]))) {
						td = self.setStyleValues(td, lessThan[1]);
					}
					if ((between[0] != undefined && between[1] != undefined) && (value >= between[0] && value <= between[1])) {
						td = self.setStyleValues(td, between[2]);
					}
				}

				if (measureDataType === "date") {
					var dates = value.split("-");
					if ((self.defaultPicture.getAttribute("dateFormat") != undefined) && (self.defaultPicture.getAttribute("dateFormat") != null)) {
						picture = self.defaultPicture.getAttribute("dateFormat").split("");
					}
					var dateElements = new Array(3);
					dateElements[0] = parseInt(dates[0]);
					dateElements[1] = parseInt(dates[1]);
					dateElements[2] = parseInt(dates[2]);
					//for (var i=0; i<=2; i++ ){
					//if (picture[i] != undefined){
					//	if (picture[i] === "M") dateElements[1] = parseInt(dates[1]);
					//	if (picture[i] === "D") dateElements[2] = parseInt(dates[2]);
					//	if (picture[i] === "Y") dateElements[0] = parseInt(dates[0]);
					//} //falta el caso en que no hay picture por defecto
					//}
					try {
						if ((equal[0] != undefined) || (greaterOrEqual[0] != undefined) || (lessOrEqual[0] != undefined)) {
							var cmpar;
							if (equal[0] != undefined) {
								cmpar = equal[0].split("-");
							} else if (greaterOrEqual[0] != undefined) {
								cmpar = greaterOrEqual[0].split("-");
							} else if (greaterOrEqual[0] != undefined) {
								cmpar = lessOrEqual[0].split("-");
							}
							var cmparElements = new Array(3);
							cmparElements[1] = parseInt(cmpar[1]);
							cmparElements[2] = parseInt(cmpar[2]);
							cmparElements[0] = parseInt(cmpar[0]);

							if ((cmparElements[0] == dateElements[0]) || ((cmparElements[0] == dateElements[0]) && (cmparElements[1] == dateElements[1]))) {
								if (equal[1] != undefined)
									td = self.setStyleValues(td, equal[1]);
								else if (greaterThan[1] != undefined)
									td = self.setStyleValues(td, greaterThan[1]);
								else if (lessThan[1] != undefined)
									td = self.setStyleValues(td, lessThan[1]);
							}

						}

						if ((notequal[0] != undefined)) {
							var cmpar = notequal[0].split("-");
							var cmparElements = new Array(3);
							cmparElements[1] = parseInt(cmpar[1]);
							cmparElements[2] = parseInt(cmpar[2]);
							cmparElements[0] = parseInt(cmpar[0]);

							if ((cmparElements[0] != dateElements[0]) || ((cmparElements[0] != dateElements[0]) && (cmparElements[1] != dateElements[1]))) {
								td = self.setStyleValues(td, notequal[1]);
							}

						}

						if ((greaterThan[0] != undefined) || (greaterOrEqual[0] != undefined)) {
							var cmpar;
							if (greaterThan[0].split("-") != undefined) {
								cmpar = greaterThan[0].split("-");
							} else {
								cmpar = greaterOrEqual[0].split("-");
							}
							var cmparElements = new Array(3);
							cmparElements[1] = parseInt(cmpar[1]);
							cmparElements[2] = parseInt(cmpar[2]);
							cmparElements[0] = parseInt(cmpar[0]);

							if ((cmparElements[0] < dateElements[0]) || ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] < dateElements[1]))
								|| ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] <= dateElements[1]) && (cmparElements[2] < dateElements[2]))) {
								td = self.setStyleValues(td, greaterThan[1]);
							}

						}


						if ((lessThan[0] != undefined) || (lessOrEqual[0] != undefined)) {
							var cmpar;
							if (lessThan[0].split("-") != undefined) {
								cmpar = lessThan[0].split("-");
							} else {
								cmpar = lessOrEqual[0].split("-");
							}
							cmparElements = new Array(3);
							cmparElements[1] = parseInt(cmpar[1]);
							cmparElements[2] = parseInt(cmpar[2]);
							cmparElements[0] = parseInt(cmpar[0]);

							if ((cmparElements[0] > dateElements[0]) || ((cmparElements[0] >= dateElements[0]) && (cmparElements[1] > dateElements[1]))
								|| ((cmparElements[0] >= dateElements[0]) && (cmparElements[1] >= dateElements[1]) && (cmparElements[2] > dateElements[2]))) {
								td = self.setStyleValues(td, lessThan[1]);
							}

						}

						if ((between[0] != undefined) && (between[1] != undefined)) {
							var cmpar = between[0].split("-");
							var cmpar2 = between[1].split("-");
							cmparElements = new Array(3);
							cmparElements2 = new Array(3);
							cmparElements[1] = parseInt(cmpar[1]);
							cmparElements[2] = parseInt(cmpar[2]);
							cmparElements[0] = parseInt(cmpar[0]);

							cmparElements2[1] = parseInt(cmpar2[1]);
							cmparElements2[2] = parseInt(cmpar2[2]);
							cmparElements2[0] = parseInt(cmpar2[0]);

							if (((cmparElements[0] <= dateElements[0]) || ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] < dateElements[1]))
								|| ((cmparElements[0] <= dateElements[0]) && (cmparElements[1] <= dateElements[1]) && (cmparElements[2] < dateElements[2])))
								&&
								((cmparElements2[0] > dateElements[0]) || ((cmparElements2[0] >= dateElements[0]) && (cmparElements2[1] > dateElements[1]))
									|| ((cmparElements2[0] >= dateElements[0]) && (cmparElements2[1] >= dateElements[1]) && (cmparElements2[2] > dateElements[2])))
							) {
								td = self.setStyleValues(td, between[2]);
							}

						}

					} catch (ERROR) {

					}
				}



			}
			return td;

		}

		this.dimensionPictureValue = function (value, dimensionNumber) {  //Picture for dimensions values
			if (value == "#NuN#") {
				var defaultNull = self.defaultPicture.getAttribute("textForNullValues");
				if (defaultNull != undefined) {
					return defaultNull;
				}
				return "";
			}
			var result = "";
			var dat
			var customPicture;

			dat = self.columns[dimensionNumber].getAttribute("dataType");
			customPicture = self.columns[dimensionNumber].getAttribute("picture");
			var newValue = OAT.ApplyPictureValue(value, dat, self.defaultPicture, customPicture);

			return newValue;
		}

		this.getMeasureNumber = function (dataField, measures) {
			for (var mI = 0; mI < measures.length; mI++) {
				if (measures[mI].getAttribute("dataField") == dataField) {
					return mI;
				}
			}
		}

		this.getMeasureName = function (dataField, measures) {
			for (var mI = 0; mI < measures.length; mI++) {
				if (measures[mI].getAttribute("dataField") == dataField) {
					return measures[mI].getAttribute("displayName");
				}
			}
		}

		this.defaultPictureValue = function (value, lastMEasure, measureNumber) { //Picture for measures values
			if (value == "#NuN#") {
				var defaultNull = self.defaultPicture.getAttribute("textForNullValues");
				if (defaultNull != undefined) {
					return defaultNull;
				}
				return "";
			}
			if ((value == "#NaV#") || (isNaN(value))) {
				return "-"
			}
			var result = "";
			var dat
			var customPicture;

			if (measures.length > 0) {
				if (lastMEasure) {
					dat = measures[measures.length - 1].getAttribute("dataType");
					customPicture = measures[measures.length - 1].getAttribute("picture");
				} else {
					dat = measures[measureNumber].getAttribute("dataType");
					customPicture = measures[measureNumber].getAttribute("picture");
				}
				var newValue = OAT.ApplyPictureValue(value, dat, self.defaultPicture, customPicture);
				return newValue;
			} else {
				return value;
			}
		}

		this.concatToGrandTotal = function (grandTotal, subArray) {
			var res = grandTotal;
			for (var sAi = 0; sAi < subArray.length; sAi++) { //for every element of a subtotal
				var exists = false;
				for (var ief = 0; ief < res.length; ief++) {
					if ((self.colConditions.length > 0) && (subArray[sAi][2] == undefined))
					{
						if (res[ief][0][2] == subArray[sAi][0][2]){
							exists = true;
							
							if (res[ief][0][0][subArray[sAi][0][1]] == undefined){
								res[ief][0][0][subArray[sAi][0][1]] = []
							} 
							res[ief][0][0][subArray[sAi][0][1]].push(subArray[sAi][0][0][subArray[sAi][0][1]][0][0])
							//res[ief][0][0][0].push(subArray[sAi][0][0][subArray[sAi][0][1]][0][0])
						}
					} else {
						if (res[ief][2] === subArray[sAi][2]) {
							exists = true;
							for (var rMPos = 0; rMPos < measures.length - 1; rMPos++)
								/*res[ief][0][rMPos] = res[ief][0][rMPos].concat(subArray[sAi][0][rMPos]);*/
								for (var iRMPos = 0; iRMPos < subArray[sAi][0][rMPos].length; iRMPos++) {
									if (subArray[sAi][0][rMPos][iRMPos][1] == 99) {
										res[ief][0][rMPos].push(subArray[sAi][0][rMPos][iRMPos][0]);
									}
								}
						}
					}
			
				}
				if (!exists) {
					var deepCopy = jQuery.extend(true, [], subArray[sAi]);
					var temp = []
					for (var iDC = 0; iDC < deepCopy[0].length; iDC++) {
						var subTemp = []
						for (var subIDC = 0; subIDC < deepCopy[0][iDC].length; subIDC++) {
							subTemp.push(deepCopy[0][iDC][subIDC][0]);
						}
						
						temp.push(subTemp)
					}
					
					
					if ((self.colConditions.length > 0) && (iDC = 2))
					{
							temp[2] = subArray[sAi][0][2]
					}
					deepCopy[0] = temp
					res.push(deepCopy);
					
				}
			}
			return res;
		}

		this.countedRows = 0;

		this.appendRowToTable = function (tbody, row, isTitleRow) {
			if (((!self.autoPaging) /*|| (self.FilterByTopFilter)*/) && (pageSize) && (!self.serverPagination)) {
				if (!isTitleRow) {
					self.countedRows++;
				}
				if (self.countedRows > pageSize) {
					row.style.display = "none";
				}
			}
			if ((self.serverPagination) && (self.ExportTo)) {
				if (!isTitleRow) {
					self.countedRows++;
				}
				if (self.countedRows > self.rowsPerPage) {
					row.style.display = "none";
				}
			}
			if (isTitleRow) {
				row.setAttribute("title_row", true);
			}

			if (self.autoPaging) { //&& (self.paginationInfo) && (self.paginationInfo.HideLastSubTotal)) {
				var extrarows = (!self.paginationInfo) ? 0 : self.paginationInfo.pages[self.actualPaginationPage - 1].extraRows
				if (!isTitleRow) {
					if (self.countedRows < extrarows) {
						row.style.display = "none";
					}
					self.countedRows++;
				}
				if (self.countedRows > (self.autoPagingRowsPerPage + extrarows)) {
					row.style.display = "none";
				}
			}

			tbody.appendChild(row);
		}

		this.drawTable = function () {
			OAT.Dom.clear(self.div);
			// START create toolbar table

			self.div.setAttribute("class", "conteiner_table_div");
			var myTable = OAT.Dom.create("table", {}, "");
			myTable.id = self.controlName + "_" + self.query + "_toolbar";
			var myTbody = OAT.Dom.create("tbody");
			var myRow = OAT.Dom.create("tr");
			self.div.appendChild(myTable);
			// END

			var table = OAT.Dom.create("table", {}, "pivot_table");
			table.id = this.controlName + "_" + this.query;
			//add control name and query name as the id of main table
			var tbody = OAT.Dom.create("tbody");


			if ((self.autoPaging) && (self.allData.length < self.filteredData.length) && (self.colPointers.length > 1)) {
				self.allData = self.filteredData;
			} else if ((self.autoPaging) && (self.filteredData.length > self.allData.length) && (self.colPointers.length === 0)) {
				self.filteredData = self.allData;
			}

			self.drawFilters();
			self.countedRows = 0;
			if ((gx.util.browser.isIE())) {
				var divIeContainer = document.createElement("div");
				divIeContainer.setAttribute("class", "divIeContainer");
				self.div.appendChild(divIeContainer);
				OAT.Dom.append([table, tbody], [divIeContainer, table]);
				table.style.marginBottom = "0px";
			} else {
				OAT.Dom.append([table, tbody], [self.div, table]);
			}

			self.countedRows = 0;
			var firstRow;
			var firstRowTotalSpan = self.colConditions.length;
			if (self.colConditions.length > 0) {
				var i = 0;
				var tr = OAT.Dom.create("tr");
				self._drawRowConditionsHeadingsCustom(tr);
				// create a list of the dimension name, that are not pivot, with heigth span equal to   colConditions.length
				for (var ni = 0; ni < self.colConditions.length; ni++) {// creat a list of the dimension name, that are pivot as columns
					tr = self._drawColConditionsHeadingsCustom(tr, ni, (ni === self.colConditions.length - 1));
				}
				//tr.setAttribute("title_row", true);
				self.appendRowToTable(tbody, tr, true);//tbody.appendChild(tr);
				firstRow = tr;
			}
			try {
				var _mtotalSpan = 0 - firstRowTotalSpan;
				var collapsedColInfo = [false, 0, 0] //firts son of a collapsed parent, the collapsed parent, total hidden 
				var columnsDataHide = []
				var columnsDataHideFillWithBlanck = []
				var td_temp_forCollapseInfo = false; var td_temp_forTotalOfCollapseInfo = false;
				var td_collection_forCollapseInfo = [];
				for (var i = 0; i < measures.length; i++) {
					td_collection_forCollapseInfo[i] = false;
				}

				for (var i = 0; i < self.colConditions.length; i++) {
					var tr = OAT.Dom.create("tr");

					var stack = self.colPointers[i];
					var drawColumn = 0; //number of actual column being draw 
					for (var j = 0; j < stack.length; j++) {//column values here the diferents values of the pivoted dimensions
						var item = stack[j];
						var th = OAT.Dom.create("th", {}, "even gx-pv-even-row");
						if (item.span === 0)
							item.span = 1;
						th.colSpan = item.span * measures.length;
						if (measures.length == 0) {
							th.colSpan = item.span;
						}
						if (item.span === 0) {//calc for the span of the top right blanck cell
							_mtotalSpan++;
						} else {
							_mtotalSpan = _mtotalSpan + (item.span * measures.length);
							if (measures.length == 0) {
								_mtotalSpan = _mtotalSpan + item.span
							}
						}
						OAT.addTextNode(th, self.dimensionPictureValue(item.value, self.colConditions[i]))


						th = self.applyFormatValues(th, item.value, self.colConditions[i]);


						//find if some parent of the item is collapsed
						var tempItem = item;
						var hide = false;
						var blankcell = false;
						while (tempItem.parent) {
							if (tempItem.parent.collapsed == undefined) {
								collapsedColInfo[0] = false;
								break;
							}
							if (tempItem.parent.collapsed) {
								if ((!collapsedColInfo[0]) || (tempItem.parent != collapsedColInfo[1])) {
									blankcell = true;
									if (i == self.colConditions.length - 1) {
										columnsDataHideFillWithBlanck.push(j);
									}
								} else {
									collapsedColInfo[2]++;
								}
								if ((i == self.colConditions.length - 1) && (!blankcell)) //the last col conditions
								{
									columnsDataHide.push(j);
								}
								collapsedColInfo[0] = true;
								collapsedColInfo[1] = tempItem.parent;
								OAT.addTextNode(th, "")
								hide = true;
								th.colSpan = 1;
								break;
							} else {
								tempItem = tempItem.parent;
							}
						}
						var itemCollapsed = (self.conditions[self.colConditions[i]].collapsedValues.indexOf(item.value) != -1);
						if ((!hide) && (i < self.colConditions.length - 1)) {
							th = self.addExpandCollapseFunctionality(th, item, i, !itemCollapsed, false);
						}
						if ((!hide) || (blankcell)) { //when no hide or when collapse add one column blank cells
							tr.appendChild(th);
						}

						var cond = self.conditions[self.colConditions[item.depth]];
						if ((cond.subtotals && i + 1 < self.colConditions.length) && (measures.length > 0)) {// subtotal columns
							var th = OAT.Dom.create("th", {}, "h2subtitle ");
							OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotalFor") + " " + self.dimensionPictureValue(item.value, self.colConditions[i]))
							th.rowSpan = self.colConditions.length - i + 1;
							_mtotalSpan = _mtotalSpan + self.colConditions.length - i;
							if (!((collapsedColInfo[0]) && (collapsedColInfo[1] != item))) { //if an item parent is collapse dont show subtotals
								tr.appendChild(th);
							}
						}

						//advance the column counter
						drawColumn = drawColumn + item.span * measures.length
					}
					if ((self.options.totals && i == 0) && (measures.length > 0)) {
						var th = OAT.Dom.create("th", {}, "h2subtitle");
						OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotal"))
						//"TOTAL" gran total
						th.rowSpan = self.colConditions.length;
						if (self.colConditions.length > 0) {
							th.colSpan = measures.length;
							_mtotalSpan = _mtotalSpan + self.colConditions.length + (measures.length - 1)
						} else {
							_mtotalSpan = _mtotalSpan + self.colConditions.length
						}
						totalSpan = self.colConditions.length
						tr.appendChild(th);
					}
					if (self.options.headingAfter) {// column headings after
						self._drawColConditionsHeadings(tr, i);
					}
					//tr.setAttribute("title_row", true);
					self.appendRowToTable(tbody, tr, true);//tbody.appendChild(tr);

				}

				/*add a column only with the name of  measures */
				if (self.colConditions.length > 0) {
					var tr = OAT.Dom.create("tr");
					for (var j = 0; j <= stack.length - collapsedColInfo[2]; j++) {
						for (var m = 0; m < measures.length; m++) {
							var th = OAT.Dom.create("th", {}, "h2titlewhite");
							th.colSpan = 1;
							OAT.addTextNode(th, measures[m].attributes.getNamedItem("displayName").nodeValue)
							self.setTitleTexrtAlign(th, th.textContent);
							tr.appendChild(th);
						}
					}
					//tr.setAttribute("title_row", true);
					self.appendRowToTable(tbody, tr, true);//tbody.appendChild(tr);
				}
				/* end of column only with the name of  measures */

				if (_mtotalSpan > 0) {
					var th = OAT.Dom.create("th", {}, "h2subtitle ");
					OAT.addTextNode(th, "")
					th.colSpan = _mtotalSpan;
					th.style.borderLeftColor = "transparent";
					firstRow.appendChild(th);
				}

				/* first connector */
				if ((self.rowConditions.length && self.options.headingBefore) && (self.colConditions.length === 0)) {
					self._drawRowConditionsHeadings(tbody);
				} else if ((self.rowConditions.length == 0) && (self.options.headingBefore) && (self.colConditions.length === 0)) {
					try {
						self._drawRowConditionsHeadings(tbody);
					} catch (Error) { }
				}

				var several_totals = measures.length > 1;
				var colSpan;
				if (several_totals) {
					colSpan = self.rowConditions.length - (measures.length - 1);
				} else {
					colSpan = self.rowConditions.length;
				}

				var collapsedInfo = [false, 9999, true, 0]
				//[working under collapse item, row condition of the collapse item, first row of collapses rows, actual row condition]
				var subtotalsmeasuresList = [];
				/* store values to show in the subtotal row */
				var grandtotalsmeasuresList = [];
				//C1Line
				var lineaEnBlanco = false;
				for (var i = 0; i < self.h; i++) {

					var tr = OAT.Dom.create("tr");
					if (self.rowConditions.length) {
						var item = self.rowPointers[self.rowConditions.length - 1][i];
						/* stack has number of values equal to height of table */
						var ptrArray = [];
						var ptr = item;
						while (ptr.parent) {
							ptrArray.unshift(ptr);
							ptr = ptr.parent;
						}
					}

					for (var j = 0; j < self.rowConditions.length - (measures.length - 1); j++) {/* row header values */
						var item = ptrArray[j];
						if ((item != undefined) && (item.offset == i)) {
							//add collapse image option
							var itemCollapsed = (self.conditions[self.rowConditions[j]].collapsedValues.indexOf(item.value) != -1);
							if (j >= (self.rowConditions.length - (measures.length - 1) - 1)) {
								itemCollapsed = false;
							}

							var th = OAT.Dom.create("th", {}, "even gx-pv-even-row");
							if ((!collapsedInfo[0]) || (collapsedInfo[1] >= j)) {//if the line is not collapsed
								th.rowSpan = ptrArray[j].spanDraw;

								OAT.addTextNode(th, self.dimensionPictureValue(item.value, self.rowConditions[j]))
								/* picture for columns */
								th = self.applyFormatValues(th, item.value, self.rowConditions[j]);
								/* format  for columns */
								self.setClickEventHandlers(th, item.value, "DIMENSION", self.rowConditions[j], item);

								if ((j < self.rowConditions.length - (measures.length - 1) - 1) && ((measures.length > 0) || (j < self.rowConditions.length - 1))) {
									th = self.addExpandCollapseFunctionality(th, item, j, !itemCollapsed, true);
								}
							} else {
								th.rowSpan = 1;
								OAT.addTextNode(th, "")
								/* picture for columns */
							}

							if (collapsedInfo[1] >= j) {
								collapsedInfo[0] = itemCollapsed;
								collapsedInfo[3] = item;
								if (itemCollapsed) {
									collapsedInfo[1] = j;
								} else {
									collapsedInfo[1] = 9999;
								}
								collapsedInfo[2] = true;
							}

							lineaEnBlanco = false;
							tr.appendChild(th);
						} else {
							if (measures.length > 0) {
								lineaEnBlanco = true;
							}
						}
					}
					/* blank space before */
					if ((self.rowConditions.length - (measures.length - 1) == 0) && (i > 0) && (measures.length > 0)) {
						lineaEnBlanco = true;
					}

					/* initial "crude data" part of a row, only the data of the measures shows in one column*/
					var mesauresList = new Array();

					var measureslength = measures.length;
					if (measureslength === 0) {
						measureslength = 1;
					}

					for (var ji = 0; ji < (measureslength - 1); ji++) {
						var item = ptrArray[self.rowConditions.length - (measureslength - 1) + ji];

						var td = OAT.Dom.create("td", {}, "even gx-pv-even-row");

						if (item.value != self.EmptyValue) {
							if ((!collapsedInfo[0]) || (self.autoPaging)) {
								OAT.addTextNode(td, self.defaultPictureValue(item.value, false, ji))
								td = self.applyConditionalFormats(td, item.value, false, ji);
								self.setClickEventHandlers(td, item.value, "MEASURE", ji, item);
							}
						} else {
							OAT.addTextNode(td, "")
						}
						if (collapsedInfo[0] && (!td_collection_forCollapseInfo[ji])) {
							td_collection_forCollapseInfo[ji] = td;
						}

						if (!mesauresList[ji]) {
							mesauresList[ji] = []
						}
						var rowNumValue = (ptrArray[ptrArray.length - 1].row != undefined) ? ptrArray[ptrArray.length - 1].row : item.row
						mesauresList[ji].push([[item.value, [rowNumValue]]]);
						/* when some conditions is move to columns, remember the value and the asociate filteredDataRow*/

						if (self.colConditions.length === 0) {
							tr.appendChild(td);
						}
					}

					if (self.colConditions.length && i == 0 && self.options.headingBefore) {
						var th = OAT.Dom.create("th");
						if (!self.rowConditions.length) {
							self._drawCorner(th, true);
							th.conditionIndex = -2;
						} else {
							th.style.border = "none";
						}
						th.rowSpan = self.rowStructure.span;
						th.hidden = true;
					}
					var tdTempSubtotalForColumn = false;
					var sumaLaterales = []; for (var iSL = 0; iSL < measureslength - 1; iSL++) { sumaLaterales[iSL] = []; }
					for (var j = 0; j < self.w; j++) {/* data */
						var result = self.tabularData[j][i][0];
						var isNun = false;
						try {
							isNun = ((result == "#NaV#") && (self.tabularData[j][i][1].length > 0));
						} catch (Error) { }
						/* add empty space for measures and col condition, and fill if here theres a value */
						if (self.colConditions.length > 0) {
							for (var fg = 0; fg < measureslength - 1; fg++) {
								var td = OAT.Dom.create("td", {}, self.getClassName(i, j));
								if ((result != self.EmptyValue) || isNun) {
									//C1Line
									var valMeasureToAdd = getValueMeasureFromMeasureList(mesauresList, self.tabularData[j][i][1][0], fg, self.filteredData, measures.length)
									OAT.addTextNode(td, self.defaultPictureValue(valMeasureToAdd, false, fg))
									td = self.applyConditionalFormats(td, valMeasureToAdd, false, fg);
									self.setClickEventHandlers(td, valMeasureToAdd, "MEASURE", fg, self.tabularData[j][i][1]);
									var pres = false;
									for (var mll = 0; mll < subtotalsmeasuresList.length; mll++) {
										if (subtotalsmeasuresList[mll][2] === j) {
											if (valMeasureToAdd == "#NuN#") {
												subtotalsmeasuresList[mll][0][fg].push(["#NuN#", 99]);
											} else if (valMeasureToAdd == "#FoE#") {
												listValoresMeasures[fg].push([["#FoE#", 99]])
											} else {
												subtotalsmeasuresList[mll][0][fg].push([parseFloat(valMeasureToAdd), 99]); //el segundo valor el maximo nivel en que ya se uso el valor
											}
											subtotalsmeasuresList[mll][3].push(self.tabularData[j][i][1].slice());
											pres = true
										}
									}

									if (!pres) {
										var listValoresMeasures = []; for (var lVMi = 0; lVMi < measureslength - 1; lVMi++) { listValoresMeasures[lVMi] = [] }
										if (valMeasureToAdd == "#NuN#") {
											listValoresMeasures[fg].push([["#NuN#", 99]])
										} else if (valMeasureToAdd == "#FoE#") {
											listValoresMeasures[fg].push([["#FoE#", 99]])
										} else {
											listValoresMeasures[fg].push([[parseFloat(valMeasureToAdd), 99]])
										}
										subtotalsmeasuresList.push([[listValoresMeasures, fg, j, self.tabularData[j][i][1].slice()]]);
									}
									if (!isNaN(parseFloat(valMeasureToAdd))) {
										sumaLaterales[fg].push(parseFloat(valMeasureToAdd));
									}
								} else {
									OAT.addTextNode(td, "")
								}
								if (columnsDataHideFillWithBlanck.indexOf(j) != -1) {
									OAT.addTextNode(td, "")
								}
								if (columnsDataHide.indexOf(j) == -1) { //dont add if column is hide because of collapse column dimension
									tr.appendChild(td);
								}
							}
						}
						/* */

						var td = OAT.Dom.create("td", {}, self.getClassName(i, j));

						if (columnsDataHide.indexOf(j) == -1) {
							if ((result != self.EmptyValue) && (measures.length > 0)) {
								OAT.addTextNode(td, self.defaultPictureValue(result.toString(), true, 0))
								td = self.applyConditionalFormats(td, result.toString(), true, 0);
								self.setClickEventHandlers(td, result, "MEASURE", measureslength - 1, self.tabularData[j][i][1]);
							} else {
								OAT.addTextNode(td, "")
							}

							if ((((columnsDataHideFillWithBlanck.indexOf(j) != -1) || (collapsedInfo[0]))) && (!self.autoPaging)) {
								if (!td_temp_forCollapseInfo) td_temp_forCollapseInfo = td;
								if (!tdTempSubtotalForColumn) tdTempSubtotalForColumn = td;
								OAT.addTextNode(td, "")
							}

							if ((measures.length > 0)) {//&& (!collapsedInfo[0])) {
								tr.appendChild(td);
							}
						}
						/* column subtotals */
						if (measures.length > 0) {
							if (self.colPointers.length > 0) { // && self.options.subtotals
								var item = self.colPointers[self.colPointers.length - 1][j].parent;
								while (item.parent) {
									var tempItem = item.parent
									var collapseFather = false;
									while (tempItem != undefined) {
										collapseFather = ((item.parent.collapsed != undefined) && (item.parent.collapsed)) ? true : false;
										tempItem = tempItem.parent
									}

									if (!collapseFather) {
										var cond = self.conditions[self.colConditions[item.depth]];
										if (item.offset + item.spanData - 1 == j) { //&& cond.subtotals) {
											var td = OAT.Dom.create("td", {}, "subtotal");

											if (item.totals[i].value > 0) {
												OAT.addTextNode(td, self.defaultPictureValue(item.totals[i].value.toString(), true, 0))
												td = self.applyConditionalFormats(td, item.totals[i].value.toString(), true, 0);
												self.setClickEventHandlers(td, item.totals[i].value.toString(), "MEASURE", measureslength - 1, item);
												if (tdTempSubtotalForColumn != false) {
													OAT.addTextNode(tdTempSubtotalForColumn, self.defaultPictureValue(item.totals[i].value.toString(), true, 0))
													tdTempSubtotalForColumn = false;
												}
											} else {
												OAT.addTextNode(td, "")
											}
											if (cond.subtotals/*self.options.subtotals*/) {
												tr.appendChild(td);
											}
										}
									}
									item = item.parent;
								}
							} /* if subtotals */
						}
					}/* for all rows */

					if (self.options.totals && self.colConditions.length) {/* columns totals */
						/* totals for other measure when move to column (its not properly a total, indeed is the value for that row of the measure)*/
						if (self.colConditions.length > 0) {//dont last mesaures totals
							for (var fg = 0; fg < measureslength - 1; fg++) {
								var td = OAT.Dom.create("td", {}, "total");
								//get total 
								//C1Line
								var _colTotal = 0;
								for (var posIt = 0; posIt < sumaLaterales[fg].length; posIt++) {
									if (!isNaN(sumaLaterales[fg][posIt])) {
										_colTotal = parseFloat(sumaLaterales[fg][posIt]) + _colTotal
									}
								}

								OAT.addTextNode(td, self.defaultPictureValue(_colTotal.toString(), false, fg))
								td = self.applyConditionalFormats(td, _colTotal.toString(), false, fg);
								self.setClickEventHandlers(td, _colTotal.toString(), "MEASURE", fg, ['PtrTotals', self.rowTotals[1][i]]);
								tr.appendChild(td);
							}
						}
						/* */
						if (self.rowConditions.length) {//last meseasure total
							var td = OAT.Dom.create("td", {}, "total");
							if (!isNaN(self.rowTotals[0][i])) {
								OAT.addTextNode(td, self.defaultPictureValue(self.rowTotals[0][i].toString(), true, 0))
								td = self.applyConditionalFormats(td, self.rowTotals[0][i].toString(), true, 0);
								self.setClickEventHandlers(td, self.rowTotals[0][i].toString(), "MEASURE", measureslength - 1, ['PtrTotals', self.rowTotals[1][i]]);

								if ((((columnsDataHideFillWithBlanck.indexOf(j) != -1) || (collapsedInfo[0]))) && (!self.autoPaging)) {
									if (td_temp_forCollapseInfo)
										if (!td_temp_forTotalOfCollapseInfo) td_temp_forTotalOfCollapseInfo = td;
								}

							} else {
								OAT.addTextNode(td, "-")
							}
							//check the value of asociate filteredData row
							if (measures.length > 0)
								tr.appendChild(td);
						} else {
							self._drawGTotal(tr);
						}
					}

					if (self.colConditions.length && i == 0 && self.options.headingAfter) {/* blank space after */
						var th = OAT.Dom.create("th");
						if (!self.rowConditions.length) {
							self._drawCorner(th, true);
							th.conditionIndex = -2;
						} else {
							th.style.border = "none";
						}
						th.rowSpan = self.rowStructure.span + (self.options.totals && self.rowConditions.length ? 1 : 0);
						tr.appendChild(th);
					}
					if (collapsedInfo[0] && !collapsedInfo[2]) {

					} else {
						if (!lineaEnBlanco) {//C1Line
							self.appendRowToTable(tbody, tr, false);//tbody.appendChild(tr);
							collapsedInfo[2] = false;
						}
					}

					var subTotalRowNumber = self.rowConditions.length - 2;
					if ((several_totals) && (self.rowConditions.length - 2 >= 0) && (ptrArray[self.rowConditions.length - 2] != undefined) && (ptrArray[self.rowConditions.length - 2].items != undefined) && (ptrArray[self.rowConditions.length - 2].items.length <= 1) && (self.colConditions.length <= 0)) {
						subTotalRowNumber = self.rowConditions.length - 2 - (measureslength - 1);
					}
					if (self.rowConditions.length - (measures.length - 1) <= 0) { //si todas las conditions de la row son masures o se movieron al filtro
						subTotalRowNumber = -1 //no hay subtotales que mostrar
					}

					for (var j = subTotalRowNumber; j >= 0; j--) {//subtotal rows
						var item = ptrArray[j];
						//last row's item		
						var eleije = item.value;
						var cond = self.conditions[self.rowConditions[item.depth]];

						var subTotalMostrado = false;

						var conditionNumber = item.conditionNumber;
						var itemColumnNumber = self.rowConditions.indexOf(conditionNumber) + 1
						var dimensionTotalColumns = self.rowConditions.length - measures.length + 1 //if dimensionTotalColumns > itemColumnNumber => item es measure //if dimesnionTotalColumns == itemColumnNumber => item es dimension, pero la ultima de las filas (no suma, su info siempre se colapsa en una linea) 
						if ((item.offset + item.spanData - 1 == i) && ((columns.length < 2) || (self.colConditions.length != 0) || (j < columns.length - 1))
							&& ((self.colConditions.length == 0) || (itemColumnNumber < dimensionTotalColumns))
							&& ((!self.autoPaging) || (self.colConditions.length == 0))
							//&& ((self.colConditions.length == 0) || (measures.length < 2) || (self.rowConditions.length - 1 < 2) || ((j < self.rowConditions.length - measures.length + 1) && ((self.rowConditions.length - measures.length)>= 3)) )//(j <= self.rowConditions.length - self.colConditions.length - 1) )
						)
						//index j, must be an item of the uppers row, valid to add as subtotal, only first position of array ptrArray
						{
							//decide where to add or not subTotal row 
							var aPsums;
							if (self.autoPaging) {
								var dRow = getDataRowFromItem(item);
								//the item to sum as an array
								aPsums = getTotalsForDataRow(self.GeneralDataRows, dRow, measureslength, self.conditions, self.filterIndexes, self.allData, self.filterDiv.selects, self);
							}
							var tr = OAT.Dom.create("tr");
							var th = OAT.Dom.create("th", {}, "h2subtitle subtitleFirstLevel");

							th.colSpan = colSpan - j;

							if (item.value != "#NuN#") {
								OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotalFor") + " " + self.dimensionPictureValue(item.value,conditionNumber))
							} else {
								OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotalFor") + " " + " ")
							}
							tr.appendChild(th);

							if (!self.autoPaging) {
								if (several_totals) {//here: the sum of subtotales except the last measure
									for (var ind = 0; ind < measureslength - 1; ind++) {
										if (self.colConditions.length === 0) {
											var sub_td = false;
											if (!(collapsedInfo[0] && !collapsedInfo[2] && (collapsedInfo[3] != item) && (j >= collapsedInfo[1]))) {
												sub_td = td_collection_forCollapseInfo
											}
											if (ind > 0) {
												self._drawRowSubtotalsForMeasures(tr, i, item, ind, j, undefined, sub_td)//td_collection_forCollapseInfo);
												//j actual dimension
											} else {
												self._drawRowSubtotalsForMeasures(tr, i, item, ind, j, th, sub_td)//td_collection_forCollapseInfo);
												//j actual dimension //only th, to add the event on click
											}
										}
										var totals_ = 0;
									}
								}
							}
							grandtotalsmeasuresList = self.concatToGrandTotal(grandtotalsmeasuresList, subtotalsmeasuresList);

							if (measures.length > 0) {
								if (self.autoPaging) {
									if (aPsums)
										self._drawRowSubtotalsAutoPaging(tr, aPsums);
								} else {
									var sub_td = td_temp_forCollapseInfo
									if (collapsedInfo[0] && !collapsedInfo[2] && (collapsedInfo[3] != item) && (j >= collapsedInfo[1])) {
										sub_td = false;
									} else {
										td_temp_forCollapseInfo = false;
									}
									if (sub_td) {
										self._drawRowSubtotals(tr, i, item, subtotalsmeasuresList, sub_td, itemColumnNumber, td_temp_forTotalOfCollapseInfo);
										td_temp_forTotalOfCollapseInfo = false;
									} else {
										self._drawRowSubtotals(tr, i, item, subtotalsmeasuresList, sub_td, itemColumnNumber, false);
									}

									/* add "regular" subtotals */
								}
							}
							//subtotalsmeasuresList = [];
							if ((!self.autoPaging) || (aPsums)) {
								if (collapsedInfo[0] && !collapsedInfo[2] && (collapsedInfo[3] != item) && (j >= collapsedInfo[1])) {

								} else {
									if (cond.subtotals) {
										self.appendRowToTable(tbody, tr, false);//tbody.appendChild(tr);
									}
								}
							}
						}
					}

					if ((subTotalRowNumber === -1)) {
						grandtotalsmeasuresList = self.concatToGrandTotal(grandtotalsmeasuresList, subtotalsmeasuresList);
						subtotalsmeasuresList = [];
					} else if ((self.rowConditions.length - measures.length) == 0) { //cuando no se calulan los subtotales porque solo hay una dimension en las filas
						//agrego para el gran total
						grandtotalsmeasuresList = self.concatToGrandTotal(grandtotalsmeasuresList, subtotalsmeasuresList);
						subtotalsmeasuresList = [];
					}

					//if ((subtotalsmeasuresList.length > 0) && (self.rowConditions.length - 1 >= 2)) { //si no se calculan o muestran
					//el (self.rowConditions.length - 1 >= 2) es por el caso 2dim 2measures n=> no borra, pero con 3dim o mas si
					//grandtotalsmeasuresList = self.concatToGrandTotal(grandtotalsmeasuresList, subtotalsmeasuresList);
					//subtotalsmeasuresList = [];
					//}
				} /* for each row */

			} catch (ERROR) {
				//alert(ERROR);
			}

			/* code for the last row, GRAND TOTAL ROW */
			/* GRAND TOTAL ROW	*/
			if ((measures.length > 0) && ((!self.autoPaging) || (self.colConditions.length == 0))) {

				if ((self.options.totals && self.rowConditions.length) && ((!self.autoPaging) || (self.TotalPagesPaging == self.actualPaginationPage) /*|| (self.FilterByTopFilter)*/)) {
					var tr = OAT.Dom.create("tr");

					if (colSpan != 0) {
						var th = OAT.Dom.create("th", {}, "h2subtitle grandtotaltitle");
						OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotal"))
						th.colSpan = colSpan;
						tr.appendChild(th);
					}

					var GrandTotals = new Array();
					if ((self.autoPaging) /*&& (!self.FilterByTopFilter)*/) {
						GrandTotals = sumGrandPagingTotals(this.GeneralDataRows, self.conditions, measures.length, self.formulaInfo, self);
					}
					if ((several_totals)) {// && (self.colConditions.length ===0)){
						for (var ind = 0; ind < measures.length - 1; ind++) {
							numCol = self.rowConditions.length - (measures.length - 1) + ind;

							var td = OAT.Dom.create("td", {}, "gtotal grandtotalvalue");
							var values_ = this.rowPointers[numCol];
							var totals_ = 0;

							var valuesToOperate = []
							for (var i = 0; i < values_.length; i++) {
								if (self.formulaInfo.measureFormula[ind].hasFormula) {
									var ref = values_[i]
									for (var t = 0; t < ind; t++) {
										ref = ref.parent
									}
									valuesToOperate.push(self.getFormulaRowByCoord(ref, false, ind, "MeasureInRows"))
								}
								if (OATIsNotEmptyValue(values_[i].value)) {
									totals_ = totals_ + parseFloat(values_[i].value);
								}
							}

							if ((!self.autoPaging) /*|| (self.FilterByTopFilter)*/) {
								if (self.formulaInfo.measureFormula[ind].hasFormula) {
									totals_ = self.calculateFormulaTotal(valuesToOperate, ind, "MeasureInRows");
									GrandTotals[ind] = totals_;
								} else {
									GrandTotals[ind] = totals_;
								}
							}

							if (self.colConditions.length === 0) {
								if ((self.autoPaging) /*&& (!self.FilterByTopFilter)*/) {
									if (!isNaN(totals_)) {
										OAT.addTextNode(td, self.defaultPictureValue(GrandTotals[ind].toString(), false, ind))
										td = self.applyConditionalFormats(td, GrandTotals[ind].toString(), false, ind);
									} else {
										OAT.addTextNode(td, "")
									}
									tr.appendChild(td);
								} else {
									if (!isNaN(totals_)) {
										OAT.addTextNode(td, self.defaultPictureValue(totals_.toString(), false, ind))
										td = self.applyConditionalFormats(td, totals_.toString(), false, ind);
										self.setClickEventHandlers(td, totals_.toString(), "MEASURE", ind, 'GrandTotal');
										if (ind == 0) {
											self.setClickEventHandlers(td, gx.getMessage("GXPL_QViewerJSTotal"), "DIMENSION", ind, 'GrandTotal');
										}
									} else {
										OAT.addTextNode(td, "")
									}
									tr.appendChild(td);
								}
							}
						}
					}

					self._drawRowTotals(tr, GrandTotals, grandtotalsmeasuresList, columnsDataHide);
					self.appendRowToTable(tbody, tr, false);//tbody.appendChild(tr);
				}

				/* second connector */
				if (self.rowConditions.length && self.options.headingAfter) {
					self._drawRowConditionsHeadings(tbody);
				}
			}

		} /* drawTable */


		this.drawTableWhenServerPagination = function () {
			OAT.Dom.clear(self.div);
			// START create toolbar table

			self.div.setAttribute("class", "conteiner_table_div");
			var myTable = OAT.Dom.create("table", {}, "");
			myTable.id = self.controlName + "_" + self.query + "_toolbar";
			var myTbody = OAT.Dom.create("tbody");
			var myRow = OAT.Dom.create("tr");
			self.div.appendChild(myTable);
			// END

			var table = OAT.Dom.create("table", {}, "pivot_table");
			table.id = this.controlName + "_" + this.query;
			//add control name and query name as the id of main table
			var tbody = OAT.Dom.create("tbody");

			self.drawFilters();
			self.countedRows = 0;
			if ((gx.util.browser.isIE())) {
				var divIeContainer = document.createElement("div");
				divIeContainer.setAttribute("class", "divIeContainer");
				self.div.appendChild(divIeContainer);
				OAT.Dom.append([table, tbody], [divIeContainer, table]);
				table.style.marginBottom = "0px";
			} else {
				OAT.Dom.append([table, tbody], [self.div, table]);
			}

			self.countedRows = 0;
			var firstRow;
			var firstRowTotalSpan = self.colConditions.length;
			if (self.colConditions.length > 0) {
				var i = 0;
				var tr = OAT.Dom.create("tr");
				self._drawRowConditionsHeadingsCustom(tr);
				// create a list of the dimension name, that are not pivot, with heigth span equal to   colConditions.length
				for (var ni = 0; ni < self.colConditions.length; ni++) {// creat a list of the dimension name, that are pivot as columns
					tr = self._drawColConditionsHeadingsCustom(tr, ni, (ni === self.colConditions.length - 1));
				}
				//tr.setAttribute("title_row", true);
				self.appendRowToTable(tbody, tr, true);//tbody.appendChild(tr);
				firstRow = tr;
			}
			try {

				for (var i = 0; i < self.colConditions.length; i++) { //show columns particular values
					var tr = OAT.Dom.create("tr");


					var j = 0
					while (j < self.pageData.columnsHeaders.length) {



						if ((!self.pageData.columnsHeaders[j].subTotal)) {

							var colSpan = 1;
							var columnValue = (self.pageData.columnsHeaders[j].subHeaders.length > i) ? self.pageData.columnsHeaders[j].subHeaders[i].value : "";
							while ((j + 1 < self.pageData.columnsHeaders.length)
								&& ((!self.pageData.columnsHeaders[j + 1].subTotal) || (i < self.pageData.columnsHeaders[j + 1].subHeaders.length - 1))
								&& ((self.pageData.columnsHeaders[j + 1].subHeaders.length > i) && (self.pageData.columnsHeaders[j + 1].subHeaders[i].value == columnValue))) {
								colSpan++;
								j++;
							}
							j++;


							var th = OAT.Dom.create("th", {}, "even gx-pv-even-row");
							th.colSpan = colSpan;
							OAT.addTextNode(th, self.dimensionPictureValue(columnValue.trimpivot(), self.colConditions[i]))
							th = self.applyFormatValues(th, columnValue.trimpivot(), self.colConditions[i]);
							tr.appendChild(th);
						} else {
							var isGrandTotal = (j >= (self.pageData.columnsHeaders.length - measures.length))
							if (self.ShowMeasuresAsRows) {
								isGrandTotal = (j >= (self.pageData.columnsHeaders.length - 1))
							}
							if (isGrandTotal) {
								//Grand Total
								if (i == 0) {
									var th = OAT.Dom.create("th", {}, "h2subtitle");
									OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotal"))
									th.rowSpan = self.colConditions.length;
									if (!self.ShowMeasuresAsRows) {
										th.colSpan = measures.length;
									}
									tr.appendChild(th);
								}
								if (!self.ShowMeasuresAsRows) {
									j = j + measures.length
								} else {
									j++;
								}
							} else {
								//subtotal columns
								if (i < self.pageData.columnsHeaders[j].subHeaders.length) {
									var th = OAT.Dom.create("th", {}, "h2subtitle ");

									var columnValue = (self.pageData.columnsHeaders[j].subHeaders.length > i) ? self.pageData.columnsHeaders[j].subHeaders[i].value : "";
									OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotalFor") + " " + self.dimensionPictureValue(columnValue.trimpivot(), self.colConditions[i] ))
									th.rowSpan = self.colConditions.length - i;
									if (!self.ShowMeasuresAsRows) {
										th.colSpan = measures.length;
									}
									tr.appendChild(th);
								}

								if (!self.ShowMeasuresAsRows) {
									j = j + measures.length
								} else {
									j++;
								}
							}
						}
					}
					self.appendRowToTable(tbody, tr, true);
				}

				if (self.colConditions.length > 0) {
					if (self.pageData.columnsHeaders.length - self.colConditions.length > 0) { //fill first row
						var th = OAT.Dom.create("th", {}, "h2subtitle ");
						OAT.addTextNode(th, "")
						th.colSpan = self.pageData.columnsHeaders.length - self.colConditions.length
						th.style.borderLeftColor = "transparent";
						firstRow.appendChild(th);
					}

					//add a column only with the name of  measures
					if (!self.ShowMeasuresAsRows) {
						var tr = OAT.Dom.create("tr");
						for (var j = 0; j < (self.pageData.columnsHeaders.length / measures.length); j++) {
							for (var m = 0; m < measures.length; m++) {
								var th = OAT.Dom.create("th", {}, "h2titlewhite");
								th.colSpan = 1;
								OAT.addTextNode(th, measures[m].attributes.getNamedItem("displayName").nodeValue)
								self.setTitleTexrtAlign(th, th.textContent);
								tr.appendChild(th);
							}
						}
						self.appendRowToTable(tbody, tr, true);
					}
					//end of column only with the name of  measures
				}



				// first connector
				if ((self.rowConditions.length && self.options.headingBefore) && (self.colConditions.length === 0)) {
					self._drawRowConditionsHeadings(tbody);
				} else if ((self.rowConditions.length == 0) && (self.options.headingBefore) && (self.colConditions.length === 0)) {
					try {
						self._drawRowConditionsHeadings(tbody);
					} catch (Error) { }
				}

				var several_totals = measures.length > 1;
				var colSpan;
				if (several_totals) {
					colSpan = self.rowConditions.length - (measures.length - 1);
				} else {
					colSpan = self.rowConditions.length;
				}


				var lineaEnBlanco = false;
				//for all rows
				for (var i = 0; i < self.pageData.rows.length; i++) {

					var tr = OAT.Dom.create("tr");
					var row = self.pageData.rows[i];
					// row header values
					for (var j = 0; j < row.headers.length; j++) {
						//add collapse image option
						var item = row.headers[j]

						if (item.rowSpan > 0) {
							var th = OAT.Dom.create("th", {}, "even gx-pv-even-row");

							th.rowSpan = item.rowSpan

							OAT.addTextNode(th, self.dimensionPictureValue(item.value.trimpivot(), self.rowConditions[j]))
							//picture for columns
							th = self.applyFormatValues(th, item.value, self.rowConditions[j]);
							//format for columns 
							//event handlers
							self.setClickEventHandlers(th, item.value, "DIMENSION", self.rowConditions[j], { cell: j, row: row });
							if ((j < self.rowConditions.length - (measures.length - 1) - 1) && (!self.ShowMeasuresAsRows)) {
								var itemCollapsed = (self.conditions[self.rowConditions[j]].collapsedValues.indexOf(item.value) != -1)
								th = self.addExpandCollapseFunctionality(th, item, j, !itemCollapsed, true);
							}
							lineaEnBlanco = false;
							tr.appendChild(th);
						}

					}

					//add blank spaces when row is collapsed
					if (row.headers.length < self.rowConditions.length - (measures.length - 1)) {
						var collapsedCells = self.rowConditions.length - (measures.length - 1) - row.headers.length;
						for (var cc = 0; cc < collapsedCells; cc++) {
							var th = OAT.Dom.create("th", {}, "even gx-pv-even-row");
							OAT.addTextNode(th, "")
							tr.appendChild(th);
						}
					}

					// blank space before
					if ((self.rowConditions.length - (measures.length - 1) == 0) && (i > 0) && (measures.length > 0)) {
						lineaEnBlanco = true;
					}

					if (self.ShowMeasuresAsRows) {
						// add cell with measure name 
						var td = OAT.Dom.create("td", {}, "even gx-pv-even-row");

						var measureTitle = self.getMeasureName(row.dataField, measures);
						OAT.addTextNode(td, measureTitle)
						td.style.textAlign = "left"
						self.setClickEventHandlers(td, measureTitle, "MEASURE", getMeasureNumberByName(measureTitle, measures), "GrandTotal");

						tr.appendChild(td);
						// end cell with measure name 
					}

					// initial "crude data" part of a row, only the data of the measures shows in one column
					var mesauresList = new Array();

					var measureslength = measures.length;
					if (measureslength === 0) {
						measureslength = 1;
					}

					if (!row.subTotal) { //value cells
						for (var ji = 0; ji < row.cells.length; ji++) {
							var value = row.cells[ji].value;

							if ((self.colConditions.length > 0) && (self.pageData.columnsHeaders[ji].subTotal)) { //subtotal or total column
								var td = OAT.Dom.create("td", {}, "subtotal");

								if (value != self.EmptyValue) {
									var mN = self.getMeasureNumber(row.cells[ji].dataField, measures);

									OAT.addTextNode(td, self.defaultPictureValue(value, false, mN))
									td = self.applyConditionalFormats(td, value, false, mN);
									self.setClickEventHandlers(td, value, "MEASURE", mN, ['PtrTotals', value, row, ji]);
								} else {
									OAT.addTextNode(td, "")
								}
								tr.appendChild(td);
							} else { //normal crude data
								var td = OAT.Dom.create("td", {}, "even gx-pv-even-row");

								if (value != self.EmptyValue) {
									var mN = self.getMeasureNumber(row.cells[ji].dataField, measures);

									OAT.addTextNode(td, self.defaultPictureValue(value, false, mN))
									td = self.applyConditionalFormats(td, value, false, mN);
									self.setClickEventHandlers(td, value, "MEASURE", mN, { cell: ji, row: row });
								} else {
									OAT.addTextNode(td, "")
								}
								tr.appendChild(td);
							}
						}
					} else {
						//subtotal or total row
						var tr = OAT.Dom.create("tr");

						if (row.headers.length == 0) {
							//grand Total
							var th = OAT.Dom.create("th", {}, "h2subtitle grandtotaltitle");
							OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotal"))
							th.colSpan = colSpan;
							if (self.ShowMeasuresAsRows) {
								if (row.rowSpan > 0) {
									th.rowSpan = row.rowSpan
									tr.appendChild(th);
								}
							} else {
								tr.appendChild(th);
							}
						} else {
							//sub total
							if (i == 0) {//append header, not totalized, only for firsr row
								for (var h = 0; h < row.headers.length - 1; h++) {
									var item = row.headers[h]
									var th = OAT.Dom.create("th", {}, "even gx-pv-even-row");
									th.rowSpan = item.rowSpan
									OAT.addTextNode(th, self.dimensionPictureValue(item.value.trimpivot(), self.rowConditions[h]))
									th = self.applyFormatValues(th, item.value, self.rowConditions[h]);
									self.setClickEventHandlers(th, item.value, "DIMENSION", self.rowConditions[h], { cell: h, row: row, isTotal: false });
									tr.appendChild(th);
								}
							}

							var subtitleClass = (row.headers.length == 1) ? "subtitleFirstLevel" : "";


							var th = OAT.Dom.create("th", {}, "h2subtitle " + subtitleClass);
							th.colSpan = colSpan - (row.headers.length - 1);
							var value = row.headers[row.headers.length - 1].value.trimpivot()
							if (value == "#NuN#") {
								OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotalFor") + " " + self.defaultPicture.getAttribute("textForNullValues"))
							} else {
								OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotalFor") + " " +  self.dimensionPictureValue( OAT.Dom.fromSafeXML(value), self.rowConditions[row.headers.length - 1] ) )
							}
							self.setClickEventHandlers(th, gx.getMessage("GXPL_QViewerJSTotalFor") + " " + item.value, "DIMENSION", getMeasureNumberByDataField(item.dataField, columns), ['PtrTotals', value, row, -1]);
							if (self.ShowMeasuresAsRows) {
								if (row.rowSpan > 0) {
									th.rowSpan = row.rowSpan
									tr.appendChild(th);
								}
							} else {
								tr.appendChild(th);
							}
						}

						if (self.ShowMeasuresAsRows) {
							// add cell with measure name
							var valueClass = (row.headers.length == 0) ? "grandtotalvalue" : (row.headers.length == 1) ? "firstlevelvalue" : "";

							var td = OAT.Dom.create("td", {}, "gtotal " + valueClass);

							var measureTitle = self.getMeasureName(row.dataField, measures);
							OAT.addTextNode(td, measureTitle)
							td.style.textAlign = "left"

							tr.appendChild(td);
							// end cell with measure names
						}

						for (var ind = 0; ind < row.cells.length; ind++) {
							var value = row.cells[ind].value;

							var mN = self.getMeasureNumber(row.cells[ind].dataField, measures);

							var valueClass = (row.headers.length == 0) ? "grandtotalvalue" : (row.headers.length == 1) ? "firstlevelvalue" : "";

							var td = OAT.Dom.create("td", {}, "gtotal " + valueClass);
							OAT.addTextNode(td, self.defaultPictureValue(value, false, mN))
							td = self.applyConditionalFormats(td, value, false, mN);
							if ((row.headers.length == 0) && (self.colConditions.length == 0)) {
								self.setClickEventHandlers(td, value, "MEASURE", mN, 'GrandTotal');
							} else {
								self.setClickEventHandlers(td, value, "MEASURE", mN, ['PtrTotals', value, row, ind]);
							}
							tr.appendChild(td);
						}
					}


					self.appendRowToTable(tbody, tr, false);

				} // for each row

			} catch (ERROR) {
				//alert(ERROR);
			}



		} /* drawTableWhenServerPagination */



		this.drawTableWhenShowMeasuresAsRows = function () {
			OAT.Dom.clear(self.div);
			// START create toolbar table

			self.div.setAttribute("class", "conteiner_table_div");
			var myTable = OAT.Dom.create("table", {}, "");
			myTable.id = self.controlName + "_" + self.query + "_toolbar";
			var myTbody = OAT.Dom.create("tbody");
			var myRow = OAT.Dom.create("tr");
			self.div.appendChild(myTable);
			// END

			var table = OAT.Dom.create("table", {}, "pivot_table");
			table.id = this.controlName + "_" + this.query;
			//add control name and query name as the id of main table
			var tbody = OAT.Dom.create("tbody");

			self.drawFilters();
			self.countedRows = 0;
			if ((gx.util.browser.isIE())) {
				var divIeContainer = document.createElement("div");
				divIeContainer.setAttribute("class", "divIeContainer");
				self.div.appendChild(divIeContainer);
				OAT.Dom.append([table, tbody], [divIeContainer, table]);
				table.style.marginBottom = "0px";
			} else {
				OAT.Dom.append([table, tbody], [self.div, table]);
			}

			if ((self.autoPaging) && (self.allData.length < self.filteredData.length) && (self.colPointers.length > 1)) {
				self.allData = self.filteredData;
			} else if ((self.autoPaging) && (self.filteredData.length > self.allData.length) && (self.colPointers.length === 0)) {
				self.filteredData = self.allData;
			}

			var firstRow;
			var firstRowTotalSpan = self.colConditions.length;
			if (self.colConditions.length > 0) {
				var i = 0;
				var tr = OAT.Dom.create("tr");
				self._drawRowConditionsHeadingsCustom(tr);
				// create a list of the dimension name, that are not pivot, with heigth span equal to   colConditions.length
				for (var ni = 0; ni < self.colConditions.length; ni++) {// creat a list of the dimension name, that are pivot as columns
					tr = self._drawColConditionsHeadingsCustom(tr, ni, (ni === self.colConditions.length - 1));
				}
				tr.setAttribute("title_row", true);
				//tbody.appendChild(tr);
				self.appendRowToTable(tbody, tr, true);
				firstRow = tr;
			}
			try {
				var _mtotalSpan = 0 - firstRowTotalSpan;
				var collapsedColInfo = [false, 0, 0] //firts son of a collapsed parent, the collapsed parent, total hidden 
				var columnsDataHide = []
				var columnsDataHideFillWithBlanck = []
				var td_temp_forCollapseInfo = false;
				var td_collection_forCollapseInfo = [];
				for (var i = 0; i < measures.length; i++) {
					td_collection_forCollapseInfo[i] = false;
				}

				for (var i = 0; i < self.colConditions.length; i++) {
					var tr = OAT.Dom.create("tr");

					var stack = self.colPointers[i];
					var drawColumn = 0; //number of actual column being draw 
					for (var j = 0; j < stack.length; j++) {//column values here the diferents values of the pivoted dimensions
						var item = stack[j];
						var th = OAT.Dom.create("th", {}, "even gx-pv-even-row");
						if (item.span === 0)
							item.span = 1;
						th.colSpan = item.span/* * (measures.length-1); */
						if (i == 0) {
							if (item.span === 0) {//calc for the span of the top right blanck cell
								_mtotalSpan++;
							} else {
								_mtotalSpan = _mtotalSpan + (item.span * measures.length);
							}
						}
						OAT.addTextNode(th, self.dimensionPictureValue(item.value, self.colConditions[i]))

						th = self.applyFormatValues(th, item.value, self.colConditions[i]);


						//find if some parent of the item is collapsed
						var tempItem = item;
						var hide = false;
						var blankcell = false;
						while (tempItem.parent) {
							if (tempItem.parent.collapsed == undefined) {
								collapsedColInfo[0] = false;
								break;
							}
							if (tempItem.parent.collapsed) {
								if ((!collapsedColInfo[0]) || (tempItem.parent != collapsedColInfo[1])) {
									blankcell = true;
									if (i == self.colConditions.length - 1) {
										columnsDataHideFillWithBlanck.push(j);
									}
								} else {
									collapsedColInfo[2]++;
								}
								if ((i == self.colConditions.length - 1) && (!blankcell)) //the last col conditions
								{
									columnsDataHide.push(j);
								}
								collapsedColInfo[0] = true;
								collapsedColInfo[1] = tempItem.parent;
								OAT.addTextNode(th, "")
								hide = true;
								th.colSpan = 1;
								break;
							} else {
								tempItem = tempItem.parent;
							}
						}

						if ((!hide) || (blankcell)) { //when no hide or when collapse add one column blank cells
							tr.appendChild(th);
						}


						//advance the column counter
						drawColumn = drawColumn + item.span * measures.length
					}
					if (self.options.totals && i == 0) {
						var th = OAT.Dom.create("th", {}, "h2subtitle");
						OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotal"))
						//"TOTAL" gran total
						th.rowSpan = self.colConditions.length;
						if (self.colConditions.length > 0) {
							th.colSpan = measures.length;
							_mtotalSpan = _mtotalSpan + self.colConditions.length + (measures.length - 1)
						} else {
							_mtotalSpan = _mtotalSpan + self.colConditions.length
						}
						totalSpan = self.colConditions.length
						tr.appendChild(th);
					}
					if (self.options.headingAfter) {// column headings after
						self._drawColConditionsHeadings(tr, i);
					}
					tr.setAttribute("title_row", true);
					//tbody.appendChild(tr);
					self.appendRowToTable(tbody, tr, true);
				}


				if (_mtotalSpan > 2) {
					var th = OAT.Dom.create("th", {}, "h2subtitle ");
					OAT.addTextNode(th, "")
					if (_mtotalSpan < 1000) {
						th.colSpan = _mtotalSpan;
					}
					th.style.borderLeftColor = "transparent";
					firstRow.appendChild(th);
				}

				/* first connector */
				if ((self.rowConditions.length && self.options.headingBefore) && (self.colConditions.length === 0)) {
					self._drawRowConditionsHeadings(tbody);
				}

				var several_totals = measures.length > 1;
				var colSpan;
				if (several_totals) {
					colSpan = self.rowConditions.length - (measures.length - 1);
				} else {
					colSpan = self.rowConditions.length;
				}

				var collapsedInfo = [false, 9999, true, 0]
				//[working under collapse item, row condition of the collapse item, first row of collapses rows, actual row condition]
				var subtotalsmeasuresList = []; for (var l = 0; l < measures.length; l++) { subtotalsmeasuresList[l] = []; subtotalsmeasuresList[l][0] = []; }
				/* store values to show in the grandTotal row */
				var grandtotalsmeasuresList = []; for (var l = 0; l < measures.length; l++) { grandtotalsmeasuresList[l] = []; grandtotalsmeasuresList[l][0] = []; }

				var searchIn = []; for (var l = 0; l < self.recordForFormula.length; l++) { searchIn[l] = self.recordForFormula[l]; }
				var searchVal = [];
				if (self.colConditions.length > 0) {
					searchVal = []; for (var l = 0; l < self.allData.length; l++) { searchVal[l] = self.allData[l]; }
				}
				var rowsPositions = [];
				for (var i = 0; i < self.h; i++) {
					//actualColumnIndex = 0;
					var tr = OAT.Dom.create("tr");
					if (self.rowConditions.length) {
						var dim = self.rowConditions.length - (measures.length - 1)
						var item = self.rowPointers[dim][i];
						/* stack has number of values equal to height of table */
						var ptrArray = [];
						var ptr = item;
						while (ptr.parent) {
							ptrArray.unshift(ptr);
							ptr = ptr.parent;
						}
					} else {
						var ptrArray = [self.rowPointers[0][0]];
					}

					var firstCellPositionOfthisRow = -1//the column number where is draw the cell of this row

					for (var j = 0; j < self.rowConditions.length - (measures.length - 1); j++) {/* row header values */
						var item = ptrArray[j];
						if ((item != undefined) && (item.offset == i)) {
							if (firstCellPositionOfthisRow == -1) {
								firstCellPositionOfthisRow = j
							}
							//add collapse image option
							var itemCollapsed = (self.conditions[self.rowConditions[j]].collapsedValues.indexOf(item.value) != -1);
							if (j >= (self.rowConditions.length - (measures.length - 1) - 1)) {
								itemCollapsed = false;
							}

							var th = OAT.Dom.create("th", {}, "even gx-pv-even-row");
							if ((!collapsedInfo[0]) || (collapsedInfo[1] >= j)) {//if the line is not collapsed
								th.rowSpan = ptrArray[j].span;
								OAT.addTextNode(th, self.dimensionPictureValue(item.value, self.rowConditions[j]))
								/* picture for columns */
								th = self.applyFormatValues(th, item.value, self.rowConditions[j]);
								/* format  for columns */
								self.setClickEventHandlers(th, item.value, "DIMENSION", self.rowConditions[j], item);

							} else {
								th.rowSpan = 1;
								OAT.addTextNode(th, "")
								/* picture for columns */
							}

							if (collapsedInfo[1] >= j) {
								collapsedInfo[0] = itemCollapsed;
								collapsedInfo[3] = item;
								if (itemCollapsed) {
									collapsedInfo[1] = j;
								} else {
									collapsedInfo[1] = 9999;
								}
								collapsedInfo[2] = true;
							}


							tr.appendChild(th);
						}
					}
					/* blank space before */
					var measureslength = measures.length;
					if (measureslength === 0) {
						measureslength = 1;
					}

					/* add cell with measure name */
					var td = OAT.Dom.create("td", {}, "even gx-pv-even-row");
					var item = ptrArray[self.rowConditions.length - (measureslength - 1)];
					if (item.value != self.EmptyValue) {
						if (!collapsedInfo[0]) {
							OAT.addTextNode(td, item.value)
							td.style.textAlign = "left"
							self.setClickEventHandlers(td, item.value, "MEASURE", getMeasureNumberByName(measureTitle, measures), "GrandTotal");
						}
					} else {
						OAT.addTextNode(td, "")
					}
					tr.appendChild(td);
					/* end cell with measure name */

					/* initial "crude data" part of a row, only the data of the measures shows in one column*/
					var mesauresList = new Array();
					/* store values to lateral total */
					var lateralMeasureList = [];
					/* add cell with measure value */
					var measureTitle = item.value;
					var measureNumber = getMeasureNumberByName(measureTitle, measures);
					if (self.colConditions.length == 0) {
						var itemMV = item.items[0];
						var td = OAT.Dom.create("td", {}, "even gx-pv-even-row");
						if (itemMV != self.EmptyValue) {
							if (!collapsedInfo[0]) {
								OAT.addTextNode(td, self.defaultPictureValue(itemMV.value, false, measureNumber))
								td = self.applyConditionalFormats(td, itemMV.value, false, measureNumber);

								//for total calculation
								self.setClickEventHandlers(td, itemMV.value, "MEASURE", measureNumber, [Math.floor(item.row / measures.length)]);
								if (self.formulaInfo.measureFormula[measureNumber].hasFormula) {
									var formulaRow = self.getFormulaRowByCoord(item, [], measureNumber, "MeasureInRows", searchIn);
									if (formulaRow != self.EmptyValue) {
										grandtotalsmeasuresList[measureNumber][0].push(formulaRow)
										subtotalsmeasuresList[measureNumber][0].push([formulaRow, -1])

									}
								} else {
									var saveValue = (itemMV.value != "#NuN#") ? parseFloat(itemMV.value) : "#NuN#";
									grandtotalsmeasuresList[measureNumber][0].push(saveValue)
									subtotalsmeasuresList[measureNumber][0].push([saveValue, -1])

								}
							}
						} else {
							OAT.addTextNode(td, "")
						}
						if (collapsedInfo[0] && (!td_collection_forCollapseInfo[ji])) {
							td_collection_forCollapseInfo[ji] = td;
						}

						mesauresList.push([[itemMV.value, [itemMV.row]]]);
						if (self.colConditions.length === 0) {
							tr.appendChild(td);
						}
						/* end add cell with measure value */
					} else {
						/* add cells with measures value */
						var colPointerNumber = self.colPointers.length - 1
						if (self.colPointers[self.colPointers.length - 1].length == 0) colPointerNumber--;
						if (self.colPointers[colPointerNumber] != undefined) {
							if (measureNumber == 0) {
								if ((rowsPositions.length > 0) && (!isNaN(rowsPositions[0]))) {
									searchVal.splice(rowsPositions[0], 1)
								}
								rowsPositions = [];
							}
							for (var j = 0; j < self.colPointers[colPointerNumber].length; j++) {
								var columnCoord = self.colPointers[colPointerNumber][j]
								var rowCoord = item


								var value
								if (measureNumber > 0) {
									try {
										if (rowsPositions[j] != self.EmptyValue) {
											value = [searchVal[rowsPositions[j]][self.headerRow.indexOf(measureTitle)], rowsPositions[j]]
										} else {
											value = self.EmptyValue;
										}
									} catch (Error) {
										var t;
									}
								} else {
									value = self.getMeasureValueCoord(rowCoord, columnCoord, self.headerRow.indexOf(measureTitle), searchVal);
									if ((value != self.EmptyValue) && (measureNumber == 0)) {
										rowsPositions.push(value[1]);
									} else if (measureNumber == 0) { rowsPositions.push(self.EmptyValue); }
								}
								var td = OAT.Dom.create("td", {}, "even gx-pv-even-row");
								if (value != self.EmptyValue) {
									OAT.addTextNode(td, self.defaultPictureValue(value[0], false, measureNumber))
									td = self.applyConditionalFormats(td, value[0], false, measureNumber);

									self.setClickEventHandlers(td, value[0], "MEASURE", measureNumber, [value[1]]);

									//for total calculation
									var subValue = parseFloat(value[0])
									if (value[0] == "#NuN#") { subValue = "#NuN#" }
									if (self.formulaInfo.measureFormula[measureNumber].hasFormula) {
										subValue = self.getFormulaRowByCoord(rowCoord, columnCoord, measureNumber, "MeasureInRows", searchIn);
										if (subValue == self.EmptyValue) { subValue = NaN }
									}

									if (grandtotalsmeasuresList[measureNumber][j] == undefined) {
										grandtotalsmeasuresList[measureNumber][j] = [subValue];
									} else {
										grandtotalsmeasuresList[measureNumber][j].push(subValue);
									}
									if (subtotalsmeasuresList[measureNumber][j] == undefined) {
										subtotalsmeasuresList[measureNumber][j] = [[subValue, -1]];
									} else {
										subtotalsmeasuresList[measureNumber][j].push([subValue, -1])
									}
									lateralMeasureList.push(subValue);

								} else {
									OAT.addTextNode(td, "")
									if (grandtotalsmeasuresList[measureNumber][j] == undefined) {
										grandtotalsmeasuresList[measureNumber][j] = [0];
									} else {
										grandtotalsmeasuresList[measureNumber][j].push(0);
									}
									if (subtotalsmeasuresList[measureNumber][j] == undefined) {
										subtotalsmeasuresList[measureNumber][j] = [[NaN, -1]];
									} else {
										subtotalsmeasuresList[measureNumber][j].push([NaN, -1])
									}
								}
								tr.appendChild(td);
							}
						}
						/* end cells with mwasures values*/
					}


					if (self.colConditions.length && i == 0 && self.options.headingAfter) {/* blank space after */
						var th = OAT.Dom.create("th");
						if (!self.rowConditions.length) {
							self._drawCorner(th, true);
							th.conditionIndex = -2;
						} else {
							th.style.border = "none";
						}
						th.rowSpan = self.rowStructure.span + (self.options.totals && self.rowConditions.length ? 1 : 0);
						tr.appendChild(th);
					}
					if (collapsedInfo[0] && !collapsedInfo[2]) {

					} else {
						self.appendRowToTable(tbody, tr, false);
						//tbody.appendChild(tr);
						collapsedInfo[2] = false;
					}

					var subTotalRowNumber = self.rowConditions.length - 2;
					if ((several_totals) && (self.rowConditions.length - 2 >= 0) && (ptrArray[self.rowConditions.length - 2] != undefined) && (ptrArray[self.rowConditions.length - 2].items != undefined) && (ptrArray[self.rowConditions.length - 2].items.length <= 1) && (self.colConditions.length <= 0)) {
						subTotalRowNumber = self.rowConditions.length - 2 - (measureslength - 1);
					}

					//add lateral total
					if ((self.options.totals && self.colConditions.length)) {
						var td = OAT.Dom.create("td", {}, "total");
						total_ = 0
						if (lateralMeasureList.length > 0) {
							if (self.formulaInfo.measureFormula[getMeasureNumberByName(measureTitle, measures)].hasFormula) {
								total_ = self.calculateFormulaTotal(lateralMeasureList, getMeasureNumberByName(measureTitle, measures), "MeasureInRows")
							} else {
								total_ = lateralMeasureList.reduce(function (a, b) { if (!isNaN(a) && !isNaN(b)) { return a + b } if (isNaN(a) && isNaN(b)) { return 0 } else if (isNaN(a)) { return b } else { return a; }; })
								if (isNaN(total_) && (total_ != "#NuN#") && (total_ != "#FoE#")) total_ = 0;
							}
						}
						if (total_ != 0) {
							OAT.addTextNode(td, self.defaultPictureValue(total_.toString(), false, getMeasureNumberByName(measureTitle, measures)))
							td = self.applyConditionalFormats(td, total_.toString(), false, getMeasureNumberByName(measureTitle, measures));
						} else {
							OAT.addTextNode(td, "")
						}
						tr.appendChild(td);
					}
					lateralMeasureList = [];
					//add subtotals row
					if (self.options.totals) {
						if (((self.rowConditions.length - (measures.length - 1)) > 1)) {
							var MaxDept = self.rowConditions.length - (measures.length - 1) - 2
							for (var relativeDim = MaxDept; relativeDim >= 0; relativeDim--) {
								var addSubTotal = false;
								//var relativeDim = 0 
								if (i + 1 < self.rowPointers[dim].length) {
									var itemTemp = self.rowPointers[dim][i + 1];
									var ptrArrayTemp = [];
									var ptrTemp = itemTemp;
									while (ptrTemp.parent) {
										ptrArrayTemp.unshift(ptrTemp);
										ptrTemp = ptrTemp.parent;
									}
									//var nexRowValue = ptrArrayTemp[relativeDim].value 
									//var actualValue = ptrArray[relativeDim].value
									//addSubTotal = (nexRowValue != actualValue) //if next value is different add subtotal
									for (var pDim = relativeDim; pDim >= 0; pDim--) {
										if (ptrArrayTemp[pDim].value != ptrArray[pDim].value) {
											addSubTotal = true;
										}
									}
								} else {
									addSubTotal = true
								}

								addSubTotal = addSubTotal && (self.conditions[self.rowConditions[relativeDim]].subtotals == 1)

								if (addSubTotal) {
									for (var sumM = 0; sumM < measures.length; sumM++) { //one row for each measures
										var tr = OAT.Dom.create("tr");

										if (sumM == 0) {
											var th = OAT.Dom.create("th", {}, "h2subtitle");
											th.colSpan = (self.rowConditions.length - (measures.length - 1)) - relativeDim;
											th.rowSpan = measures.length
											OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotalFor") + " " + ptrArray[relativeDim].value)
											tr.appendChild(th);
										}

										//add measure name
										var td = OAT.Dom.create("td", {}, "total");
										var value = measures[sumM].getAttribute("displayName");
										OAT.addTextNode(td, value)
										td.style.textAlign = "left"
										self.setClickEventHandlers(td, value, "MEASURE", sumM, "GrandTotal");
										tr.appendChild(td);

										//add sub total value
										if (self.colConditions.length == 0) {
											//add sub-total value
											var td = OAT.Dom.create("td", {}, "total");
											var valuesToOperate = []
											for (var vt = 0; vt < subtotalsmeasuresList[sumM][0].length; vt++) {
												if ((subtotalsmeasuresList[sumM][0][vt][1] == -1) || (subtotalsmeasuresList[sumM][0][vt][1] > relativeDim)) {
													if ((!isNaN(subtotalsmeasuresList[sumM][0][vt][0]) || (subtotalsmeasuresList[sumM][0][vt][0] == "#NuN#")) || self.formulaInfo.measureFormula[sumM].hasFormula) {
														valuesToOperate.push(subtotalsmeasuresList[sumM][0][vt][0])
														subtotalsmeasuresList[sumM][0][vt][1] = relativeDim
													}
												}
											}
											var total_ = 0
											if (valuesToOperate.length != 0) {
												if (self.formulaInfo.measureFormula[sumM].hasFormula) {
													total_ = self.calculateFormulaTotal(valuesToOperate, sumM, "MeasureInRows")
												} else {
													if (self.IsReduceNuN(valuesToOperate)) total_ = "#NuN#"; else
														total_ = valuesToOperate.reduce(function (a, b) { if (!isNaN(a) && !isNaN(b)) { return a + b } if (isNaN(a) && isNaN(b)) { return 0 } else if (isNaN(a)) { return b } else { return a; }; })
													if (isNaN(total_) && (total_ != "#NuN#") && (total_ != "#FoE#")) total_ = 0;
												}
											}
											lateralMeasureList.push(parseFloat(total_))
											if (total_ != 0) {
												OAT.addTextNode(td, self.defaultPictureValue(total_.toString(), false, sumM))
												td = self.applyConditionalFormats(td, total_.toString(), false, sumM);
											} else {
												OAT.addTextNode(td, "")
											}

											tr.appendChild(td);


										} else {
											//add sub-total values
											var colPointerNumber = self.colPointers.length - 1
											if (self.colPointers[self.colPointers.length - 1].length == 0) colPointerNumber--;
											if (self.colPointers[colPointerNumber] != undefined) {
												for (var cP = 0; cP < self.colPointers[colPointerNumber].length; cP++) {
													var td = OAT.Dom.create("td", {}, "total");
													var valuesToOperate = []
													for (var vt = 0; vt < subtotalsmeasuresList[sumM][cP].length; vt++) {
														if ((subtotalsmeasuresList[sumM][cP][vt][1] == -1) || (subtotalsmeasuresList[sumM][cP][vt][1] > relativeDim)) {
															if ((!isNaN(subtotalsmeasuresList[sumM][cP][vt][0])) || (subtotalsmeasuresList[sumM][cP][vt][0] == "#NuN#") || self.formulaInfo.measureFormula[sumM].hasFormula) {
																valuesToOperate.push(subtotalsmeasuresList[sumM][cP][vt][0])
																subtotalsmeasuresList[sumM][cP][vt][1] = relativeDim
															}
														}
													}
													var total_ = 0
													if (valuesToOperate.length != 0) {
														if (self.formulaInfo.measureFormula[sumM].hasFormula) {
															total_ = self.calculateFormulaTotal(valuesToOperate, sumM, "MeasureInRows")
														} else {
															if (self.IsReduceNuN(valuesToOperate)) total_ = "#NuN#"; else
																total_ = valuesToOperate.reduce(function (a, b) { if (!isNaN(a) && !isNaN(b)) { return a + b } if (isNaN(a) && isNaN(b)) { return 0 } else if (isNaN(a)) { return b } else { return a; }; })
															if (isNaN(total_) && (total_ != "#NuN#") && (total_ != "#FoE#")) total_ = 0;
														}
													}
													if ((total_ != 0) && ((!isNaN(total_)) || (total_ == "#NuN#") || (total_ == "#FoE#"))) {
														if (self.formulaInfo.measureFormula[sumM].hasFormula) {
															lateralMeasureList.push(valuesToOperate)
														} else {
															lateralMeasureList.push(parseFloat(total_))
														}
														OAT.addTextNode(td, self.defaultPictureValue(total_.toString(), false, sumM))
														td = self.applyConditionalFormats(td, total_.toString(), false, sumM);
													} else {
														OAT.addTextNode(td, "")
													}
													tr.appendChild(td);
												}
											}
											if ((self.colConditions.length)) { //add lateral total to this sub-total row
												var td = OAT.Dom.create("td", {}, "gtotal");
												var total_ = 0
												if (lateralMeasureList.length != 0) {
													if (self.formulaInfo.measureFormula[sumM].hasFormula) {
														total_ = self.calculateFormulaTotal(lateralMeasureList, sumM, "MeasureInRows")
													} else {
														if (self.IsReduceNuN(lateralMeasureList)) total_ = "#NuN#"; else
															total_ = lateralMeasureList.reduce(function (a, b) { if (!isNaN(a) && !isNaN(b)) { return a + b } if (isNaN(a) && isNaN(b)) { return 0 } else if (isNaN(a)) { return b } else { return a; }; })
													}
												}
												OAT.addTextNode(td, self.defaultPictureValue(total_.toString(), false, sumM))
												td = self.applyConditionalFormats(td, total_.toString(), false, sumM);
												tr.appendChild(td);
												lateralMeasureList = [];
											}
										}

										self.appendRowToTable(tbody, tr, false);
									}
								}
							}
						}
					}


				} /* for each row */



				/* code for the last row, GRAND TOTAL ROW */
				/* GRAND TOTAL ROW	*/
				if ((measures.length > 0) && ((self.rowConditions.length - measures.length + 1) > 0)) {

					if ((self.options.totals && self.rowConditions.length) && ((!self.autoPaging) || (self.TotalPagesPaging == self.actualPaginationPage) || (self.FilterByTopFilter))) {

						for (var m = 0; m < measures.length; m++) { //for every measure

							var tr = OAT.Dom.create("tr");

							if ((colSpan != 0) && (m == 0)) { //add grandTotal title cell
								var th = OAT.Dom.create("th", {}, "h2subtitle");
								OAT.addTextNode(th, gx.getMessage("GXPL_QViewerJSTotal"))
								th.colSpan = colSpan;
								th.rowSpan = measures.length;
								tr.appendChild(th);
							}

							//add measure title cell
							var td = OAT.Dom.create("td", {}, "gtotal");
							var value = measures[m].getAttribute("displayName");
							if (value != self.EmptyValue) {
								OAT.addTextNode(td, value)
								td.style.textAlign = "left"
								self.setClickEventHandlers(td, value, "MEASURE", m, "GrandTotal");
							} else {
								OAT.addTextNode(td, "")
							}
							tr.appendChild(td);

							var lateralMeasureList = [];
							if (self.colConditions.length == 0) {
								//add grand total value
								var td = OAT.Dom.create("td", {}, "gtotal");
								var total_ = 0
								if (grandtotalsmeasuresList[m][0].length > 0) {
									if (self.formulaInfo.measureFormula[m].hasFormula) {
										total_ = self.calculateFormulaTotal(grandtotalsmeasuresList[m][0], m, "MeasureInRows")
									} else {
										if (self.IsReduceNuN(grandtotalsmeasuresList[m][0])) total_ = "#NuN#"; else
											total_ = grandtotalsmeasuresList[m][0].reduce(function (a, b) { if (!isNaN(a) && !isNaN(b)) { return a + b } if (isNaN(a) && isNaN(b)) { return 0 } else if (isNaN(a)) { return b } else { return a; }; })
									}
								}
								if (!isNaN(total_) || (total_ == "#NuN#") || (total_ == "#FoE#")) {
									OAT.addTextNode(td, self.defaultPictureValue(total_.toString(), false, m))
									td = self.applyConditionalFormats(td, total_.toString(), false, m);
								} else {
									OAT.addTextNode(td, "")
								}

								tr.appendChild(td);

								//lateralMeasureList.push(parseFloat(total_))
							} else {
								//add grand total values
								var colPointerNumber = self.colPointers.length - 1
								if (self.colPointers[self.colPointers.length - 1].length == 0) colPointerNumber--;
								if (self.colPointers[colPointerNumber] != undefined) {
									for (var j = 0; j < self.colPointers[colPointerNumber].length; j++) {
										var td = OAT.Dom.create("td", {}, "gtotal");
										var total_ = 0
										if ((grandtotalsmeasuresList[m][j] != undefined) && (grandtotalsmeasuresList[m][j].length > 0)) {
											if (self.formulaInfo.measureFormula[m].hasFormula) {
												total_ = self.calculateFormulaTotal(grandtotalsmeasuresList[m][j], m, "MeasureInRows")
											} else {
												if (self.IsReduceNuN(grandtotalsmeasuresList[m][j])) total_ = "#NuN#"; else
													total_ = grandtotalsmeasuresList[m][j].reduce(function (a, b) { if (!isNaN(a) && !isNaN(b)) { return a + b } if (isNaN(a) && isNaN(b)) { return 0 } else if (isNaN(a)) { return b } else { return a; }; })
											}
										}
										if (!isNaN(total_) || (total_ == "#NuN#") || (total_ == "#FoE#")) {
											OAT.addTextNode(td, self.defaultPictureValue(total_.toString(), false, m))
											td = self.applyConditionalFormats(td, total_.toString(), false, m);
										} else {
											OAT.addTextNode(td, "")
										}

										tr.appendChild(td);

										if (self.formulaInfo.measureFormula[m].hasFormula) {
											lateralMeasureList.push(grandtotalsmeasuresList[m][j])
										} else {
											if (!isNaN(total_)) {
												lateralMeasureList.push(parseFloat(total_))
											}
										}
									}
								}
							}

							//add lateral total to grand total
							if ((self.options.totals && self.colConditions.length)) {
								var td = OAT.Dom.create("td", {}, "gtotal");
								var total_ = 0
								if (lateralMeasureList.length != 0) {
									if (self.formulaInfo.measureFormula[m].hasFormula) {
										total_ = self.calculateFormulaTotal(lateralMeasureList, m, "MeasureInRows")
									} else {
										if (self.IsReduceNuN(lateralMeasureList)) total_ = "#NuN#"; else
											total_ = lateralMeasureList.reduce(function (a, b) { if (!isNaN(a) && !isNaN(b)) { return a + b } if (isNaN(a) && isNaN(b)) { return 0 } else if (isNaN(a)) { return b } else { return a; }; })
									}
								}
								OAT.addTextNode(td, self.defaultPictureValue(total_.toString(), false, m))
								td = self.applyConditionalFormats(td, total_.toString(), false, m);
								tr.appendChild(td);
							}


							self.appendRowToTable(tbody, tr, false);
						}
					}


				}




			} catch (ERROR) {

			}

		} /* drawTableWhenShowMeasuresAsRows */


		this.IsReduceNuN = function (values) {
			isNuN = false;
			for (var vft = 0; vft < values.length; vft++) {
				if ((values[vft] != "#NuN#") && (values[vft] != 0)) {
					return false;
				}
				if (values[vft] == "#NuN#") isNuN = true;
			}
			return isNuN;
		}

		this.applyFilters = function () { /* create filteredData from allData */
			self.filteredData = [];
			for (var i = 0; i < self.allData.length; i++) {
				if (self.filterOK(self.allData[i])) { self.filteredData.push(self.allData[i]); }
			}
		}


		this.createTempDataStructForAggStepOptimization = function () {
			try {
				for (var row = 0; row < self.GeneralDataRows.length; row++) {
					for (var i = 0; i < self.GeneralDataRows[0].length; i++) {
						for (var j = 0; j < self.GeneralDataRows[0].length; j++) {
							if (self.TempDataStructForAggStepOptimization[self.GeneralDataRows[row][i]] == undefined) {
								self.TempDataStructForAggStepOptimization[self.GeneralDataRows[row][i]] = [];
							}
							self.TempDataStructForAggStepOptimization[self.GeneralDataRows[row][i]][self.GeneralDataRows[row][j]] = true;
						}
					}
				}
			} catch (error) {
				//alert(error)
			}
		}

		this.getMeasureValue = function (item, measureNumber, colDim) {
			var rowFromItem = [];
			var temp = item;
			var dimValues = [];

			var dimPosition = [];
			for (var i = 0; i < colDim.length - measures.length + 1; i++) {
				dimPosition[i] = colDim[colDim.length - measures.length + 1 - (i + 1)];
			}


			for (var i = 0; i < dimPosition.length; i++) {
				dimValues[dimPosition[i]] = temp.value;
				temp = temp.parent//temp.items
			}

			var value = ""
			var hallado = false
			var searchIn = self.allData
			if (self.filterIndexes.length > 0) { searchIn = self.filteredData }
			for (var i = 0; i < searchIn.length; i++) { //allData
				var coincide = false
				for (var j = 0; j < dimPosition.length; j++) {
					if (searchIn[i][dimPosition[j]] == dimValues[dimPosition[j]]) {
						coincide = true;
					} else {
						coincide = false;
						break;
					}
				}
				if (coincide) {
					value = searchIn[i][colDim.length + self.filterIndexes.length - measures.length + 1 + measureNumber];
					hallado = true
					break;
				}
			}
			if (hallado)
				return value;
			else
				return self.EmptyValue;
			//TODO: repetir la bsuqueda en GeneralDataRows
		}

		this.getMeasureValueCoord = function (rowsCoord, colCoord, measurePosition, searchVal) {
			var rowFromItem = [];
			var dimValues = [];

			var dimPosition = [];
			for (var i = 0; i < self.rowConditions.length - measures.length + 1; i++) {
				dimPosition[i] = self.rowConditions[self.rowConditions.length - measures.length + 1 - (i + 1)];
			}


			for (var i = self.colConditions.length - 1; i >= 0; i--) {
				dimValues[self.colConditions[i]] = colCoord.value;
				colCoord = colCoord.parent
			}
			var temp = rowsCoord.parent;
			for (var i = 0; i < dimPosition.length; i++) {
				dimValues[dimPosition[i]] = temp.value;
				temp = temp.parent//temp.items
			}

			var value = ""
			var hallado = false
			var numRow = 0
			var searchIn = searchVal

			for (var i = 0; i < searchIn.length; i++) {
				var coincide = false
				for (var j = 0; j < dimValues.length; j++) {
					if (searchIn[i][j] == dimValues[j]) {
						coincide = true;
					} else {
						if ((dimValues[j] == undefined) && (self.filterIndexes.length > 0)) {
							coincide = true;
						} else {
							coincide = false;
							break;
						}
					}
				}
				if (coincide) {
					value = searchIn[i][measurePosition];
					numRow = i;
					hallado = true;
					break;
				}
			}
			if (hallado) {
				return [value, numRow];
			} else
				return self.EmptyValue;
		}

		this.getFormulaRowByCoord = function (rowsCoord, colCoord, measureNumber, caseId, tosearch) {

			var rowFromItem = [];
			var dimValues = [];

			var dimPosition = [];
			for (var i = 0; i < self.rowConditions.length - measures.length + 1; i++) {
				dimPosition[i] = self.rowConditions[self.rowConditions.length - measures.length + 1 - (i + 1)];
			}

			if (colCoord) {
				for (var i = self.colConditions.length - 1; i >= 0; i--) {
					dimValues[self.colConditions[i]] = colCoord.value;
					colCoord = colCoord.parent
				}
			}
			var temp = rowsCoord.parent;
			for (var i = 0; i < dimPosition.length; i++) {
				dimValues[dimPosition[i]] = temp.value;
				temp = temp.parent//temp.items
			}

			for (var i = 0; i < self.filterIndexes.length; i++) {
				var s = self.filterDiv.selects[i];
				var val = OAT.$v(s)
				if (val == "[all]"/*""*/) {
					dimValues[self.filterIndexes[i]] = undefined
				} else {
					dimValues[self.filterIndexes[i]] = val
				}
			}

			var value = ""
			var hallado = false
			var numRow = 0
			if (tosearch != undefined) { searchIn = tosearch }
			else {
				var searchIn = self.recordForFormula
			}
			var coinciden = [];
			//if (self.filterIndexes.length > 0){ searchIn = self.filteredData }
			var addedValues = []; for (var o = 0; o < self.formulaInfo.recordDataLength; o++) { addedValues[o] = 0 }
			for (var i = 0; i < searchIn.length; i++) {
				var coincide = false
				for (var j = 0; j < dimValues.length; j++) {
					if (searchIn[i][j] == dimValues[j]) {
						coincide = true;
					} else {
						if ((dimValues[j] == undefined) && (self.filterIndexes.indexOf(j) != -1)) {
							coincide = true;
						} else {
							coincide = false;
							break;
						}
					}
				}
				if (coincide) {
					for (var t = 0; t < self.formulaInfo.measureFormula[measureNumber].relatedMeasures.length; t++) {
						var pos = self.formulaInfo.measureFormula[measureNumber].relatedMeasures[t]
						if (searchIn[i][pos] == undefined) {
							if (addedValues[pos] == 0) addedValues[pos] = "#NuN#";
						} else {
							if (addedValues[pos] == "#NuN#") addedValues[pos] = 0;
							addedValues[pos] = addedValues[pos] + parseFloat(searchIn[i][pos]);
						}
					}
					hallado = true
					coinciden.push(i);
				}
			}
			if (hallado) {
				if (self.formulaInfo.cantFormulaMeasures == 1) {
					for (var pC = 0; pC < coinciden.length; pC++) {
						tosearch.splice(coinciden[pC], 1)
					}
				}
				return addedValues;
			} else
				return self.EmptyValue;


		}



		this.calculateFormulaTotal = function (inputData, measureNumber, caseId) {
			try {
				var addedValues = [];

				if (inputData.length == 0) return "#NuN#"

				//if ( caseId == "MeasureInRows"){
				for (var j = 0; j < inputData.length; j++) {
					//if (inputData[j] == "#NuN#"){
					//	return "#NuN#";
					//}
					if ((inputData[j] != self.EmptyValue) && (inputData[j] != 0) && ((inputData[j] != "#NuN#") || (self.ShowMeasuresAsRows))) {
						for (var i = 0; i < inputData[j].length; i++) {
							if (addedValues[i] == undefined) { addedValues[i] = 0 }
							if (!isNaN(inputData[j][i]) && (inputData[j][i] != "#NuN#")) {
								if (addedValues[i] == "#NuN#") addedValues[i] = 0;
								addedValues[i] = addedValues[i] + inputData[j][i];
							}
							if (inputData[j][i] == "#NuN#" && addedValues[i] == 0) {
								addedValues[i] = "#NuN#"
							}
						}
					}
				}
				//}
				if (!self.ShowMeasuresAsRows) {
					if (addedValues.length == 0) return "#NuN#"
				} else {
					if (addedValues.length == 0) return NaN
				}
				var result = EvaluateExpressionPivotJs(self.formulaInfo.measureFormula[measureNumber].PolishNotation,
					addedValues, self.formulaInfo)
				if ((result == Infinity) || isNaN(result)) {
					return "#FoE#";
				}

				return result;
			} catch (Error) {
				return self.EmptyValue;
			}

		}
		this.addToStack = function (iterator, item, value, conditionList) {
			if (self.GeneralDataRows.length > 3000)
				return true
			if (iterator < 1)
				return true;
			if (item.value == undefined)
				return true;

			var value_cond_row_pos = self.conditions[conditionList[iterator]].dataRowPosition;
			var value_prev_cond_row_pos = self.conditions[conditionList[iterator - 1]].dataRowPosition;
			//search if the row exists
			if ((self.allData.length > 800) && (self.filterIndexes.length > 0)) {
				return true
			}

			for (var i = 0; i < self.allData.length; i++) {
				if (self.allData[i][value_cond_row_pos] == value) {
					if (item.value == self.allData[i][value_prev_cond_row_pos]) {
						return true;
					}
				}
			}

			if ((!self.autoPaging) || (self.rowConditions.length < 8)) {
				for (var i = 0; i < self.GeneralDataRows.length; i++) {
					if (self.GeneralDataRows[i][value_cond_row_pos] == value) {
						if (item.value == self.GeneralDataRows[i][value_prev_cond_row_pos]) {
							return true;
						}
					}
				}
			}
			return false;
		}

		this.createAggStructure = function () { /* create a multidimensional aggregation structure */
			function createPart(struct, arr, rows, tempSearchData) {
				struct.items = false;
				struct.depth = -1;
				var stack = [struct];
				var dimensionLenght = arr.length;
				if ((self.ShowMeasuresAsRows) && rows) {
					dimensionLenght -= measures.length - 1;
				}
				for (var i = 0; i < dimensionLenght; i++) { /* for all conditions */
					/*ordenar tempSearchData*/
					var cond = self.conditions[arr[i]];


					var filaAOrdenar = self.conditions[arr[i]].dataRowPosition
					var index = filaAOrdenar;

					var coef = cond.sort;


					if ((i >= 1) && (!self.autoPaging) && (self.rowConditions.length > 16) && (self.GeneralDataRows.length > 1200)) {
						cond = self.conditions[arr[i - 1]];
						filaAOrdenar = self.conditions[arr[i - 1]].dataRowPosition
						index = filaAOrdenar;

						coef = cond.sort;
					}

					if ((coef != 0) && (coef != 2)) {
						var sortNumeric = true;
						for (var ival = 0; ival < cond.distinctValues.length; ival++) {
							if ((sortNumeric) && (cond.distinctValues[ival] != parseInt(cond.distinctValues[ival]))) {
								sortNumeric = false; break;
							}
						}
						if (sortNumeric) {
							tempSearchData.sort((function (index) {
								return function (a, b) {
									return coef * (parseInt(a[index]) === parseInt(b[index]) ? 0 : (parseInt(a[index]) < parseInt(b[index]) ? -1 : 1));
								};
							})(index));
						} else {
							tempSearchData.sort((function (index) {
								return function (a, b) {
									return coef * (a[index] === b[index] ? 0 : (a[index] < b[index] ? -1 : 1));
								};
							})(index));
						}
					}




					var newstack = [];

					var itemsInclude = cond.distinctValues.length;
					//if ((coef != 0) && (coef == 1)) cond.distinctValues.sort();

					if ((i >= 1) && (!self.autoPaging) && (self.rowConditions.length > 16) && (self.GeneralDataRows.length > 1200)) {
						var value_cond_row_pos = self.conditions[arr[i]].dataRowPosition;
						var newStackValues = [];
						for (var j = 0; j < stack.length; j++) {
							var items = [];

							for (var l = 0; l < tempSearchData.length; l++) {
								var crudeRow = tempSearchData[l];

								value = tempSearchData[l][value_cond_row_pos];

								var res = self.addToStack3(i, stack[j], tempSearchData[l], arr, coef, sortNumeric)
								if (res == 'break') break;

								if (newStackValues.indexOf(value) == -1) {
									//stack[j] y crudeRow "coinciden"



									if (res) {
										newStackValues.push(value);

										var collapsed = false;
										if (cond.collapsedValues.indexOf(value) != -1)
											collapsed = true;
										var o = { value: value, parent: stack[j], used: false, items: false, depth: i, collapsed: collapsed, conditionNumber: arr[i] };
										items.push(o);
										newstack.push(o);

									}
								}

							}
							newStackValues = [];


							stack[j].items = items;
						}


					} else {
						for (var j = 0; j < stack.length; j++) { // for all items to be filled 
							var items = [];

							var valuePositionInSearchData = [0];
							for (var k = 0; k < itemsInclude; k++) { // for all currently distinct values

								var value = cond.distinctValues[k];
								if (cond.blackList.findIndex(value) == -1) { //if not in black list

									if (self.addToStack2(i, stack[j], value, arr, tempSearchData, valuePositionInSearchData, coef, sortNumeric)) {//search if this rows exists

										var collapsed = false;
										if (cond.collapsedValues.indexOf(value) != -1)
											collapsed = true;
										var o = { value: value, parent: stack[j], used: false, items: false, depth: i, collapsed: collapsed, conditionNumber: arr[i] };
										items.push(o);
										newstack.push(o);

									}


								}
							} // distinct values 
							stack[j].items = items;
						} // items in stack
					}


					stack = newstack;
				} /* conditions */


				//add measure & value row
				if ((self.ShowMeasuresAsRows) && (rows)) {
					//if (arr.length > 0){
					var newstack = [];
					for (var j = 0; j < stack.length; j++) { /* for all items to be filled */
						var items = [];
						var itemsInclude = measures.length;

						for (var k = 0; k < itemsInclude; k++) { //for all measures
							var measureName = measures[k].getAttribute("displayName")
							var collapsed = false;
							var o = { value: measureName, parent: stack[j], used: false, items: false, depth: dimensionLenght, collapsed: collapsed };
							//items.push(o);
							var podar = false
							if (self.colConditions.length == 0) {
								var measureValue = self.getMeasureValue(stack[j], k, arr);
								if (measureValue == self.EmptyValue) {
									podar = true;
								} else {
									var v = { value: measureValue, parent: o, used: false, items: false, depth: dimensionLenght + 1, collapsed: collapsed };
									o.items = []
									o.items.push(v)
								}
							}
							//var collapseFalse
							if (!podar) {
								items.push(o)
								if (self.colConditions.length == 0) {
									newstack.push(v);
								} else {
									newstack.push(o);
								}
							}
						}
						stack[j].items = items;
					}
					stack = newstack;
					//}
				}
			}

			//create copy of self.allData
			var tempSearchData = [];
			for (var i = 0; i < self.allData.length; i++) {
				tempSearchData.push(self.allData[i])
			}

			//self.createTempDataStructForAggStepOptimization();
			createPart(self.rowStructure, self.rowConditions, true, tempSearchData);
			createPart(self.colStructure, self.colConditions, false, tempSearchData);
			//self.TempDataStructForAggStepOptimization = [];
		}

		this.addToStack3 = function (iterator, item, row, conditionList, orden, sortNumeric) {
			if (item.value == undefined)
				return true;

			//var value_cond_row_pos = self.conditions[conditionList[iterator]].dataRowPosition;
			var value_prev_cond_row_pos = self.conditions[conditionList[iterator - 1]].dataRowPosition;

			if (item.value == row[value_prev_cond_row_pos]) {

				var tempItem = item;
				var flag = true;
				for (var resto = 1; resto < iterator; resto++) {
					var value_prev = self.conditions[conditionList[iterator - 1 - resto]].dataRowPosition;
					tempItem = tempItem.parent;
					if (tempItem.value != row[value_prev]) {
						flag = false;
						break;
					}
				}
				if (flag) return true;

			} else {
				if ((orden == 0) || (orden == 2) ||
					((orden == 1) && (!sortNumeric) && (row[value_prev_cond_row_pos] <= item.value)) ||
					((orden == -1) && (!sortNumeric) && (row[value_prev_cond_row_pos] >= item.value)) ||
					((orden == 1) && (sortNumeric) && (parseInt(row[value_prev_cond_row_pos]) <= parseInt(item.value))) ||
					((orden == -1) && (sortNumeric) && (parseInt(row[value_prev_cond_row_pos]) >= parseInt(item.value)))
				) {
					return false
				} else {
					return 'break'
				}
			}

		}

		this.addToStack2 = function (iterator, item, value, conditionList, tempSearchData, valuePosition, orden, sortNumeric) {
			if ((self.GeneralDataRows.length > 3000) && ((!self.autoPaging) /*|| (self.rowConditions.length < 8)*/))
				return true
			if (iterator < 1)
				return true;
			if (item.value == undefined)
				return true;

			var value_cond_row_pos = self.conditions[conditionList[iterator]].dataRowPosition;
			var value_prev_cond_row_pos = self.conditions[conditionList[iterator - 1]].dataRowPosition;
			//search if the row exists
			if ((self.allData.length > 1000) && (self.filterIndexes.length > 0) && (self.rowConditions.length < 8)) {
				return true
			}

			var first = true;
			for (var i = valuePosition[0]; i < tempSearchData.length/*self.allData.length*/; i++) {
				if ((orden == 0) || (orden == 2) ||
					((orden == 1) && (!sortNumeric) && (tempSearchData[i][value_cond_row_pos] <= value)) ||
					((orden == -1) && (!sortNumeric) && (tempSearchData[i][value_cond_row_pos] >= value)) ||
					((orden == 1) && (sortNumeric) && (parseInt(tempSearchData[i][value_cond_row_pos]) <= parseInt(value))) ||
					((orden == -1) && (sortNumeric) && (parseInt(tempSearchData[i][value_cond_row_pos]) >= parseInt(value)))
				) {
					if (tempSearchData[i][value_cond_row_pos] == value) {
						if ((first) && (orden != 0) && (orden != 2)) {
							valuePosition[0] = i; first = false;
						}
						if (item.value == tempSearchData[i][value_prev_cond_row_pos]) {
							var tempItem = item;
							var flag = true;
							for (var resto = 1; resto < iterator; resto++) {
								var value_prev = self.conditions[conditionList[iterator - 1 - resto]].dataRowPosition;
								tempItem = tempItem.parent;
								if (tempItem.value != tempSearchData[i][value_prev]) {
									flag = false;
									break;
								}
							}
							if (flag) return true;
						}
					}
				} else {//se supero el valor
					break;
				}
			}

			if ((/*(!self.autoPaging) ||*/ (self.GeneralDataRows.length < 500)) //limitado evitar loop grande
				&& (self.GeneralDataRows.length > self.allData.length)) {
				for (var i = 0; i < self.GeneralDataRows.length; i++) {
					if (self.GeneralDataRows[i][value_cond_row_pos] == value) {
						if (item.value == self.GeneralDataRows[i][value_prev_cond_row_pos]) {
							if (iterator > 1) {

								var value_prev = self.conditions[conditionList[iterator - 2]].dataRowPosition;
								if (item.parent.value == self.GeneralDataRows[i][value_prev]) {
									return true
								}

							} else {
								return true;
							}
						}
					}
				}
			}
			return false;
		}

		this.fillAggStructure = function () { /* mark used branches of aggregation structure */
			function fillPart(struct, arr, row, rowNumber) {
				if (!self.ShowMeasuresAsRows) {
					var ptr = struct;
					for (var i = 0; i < arr.length; i++) {
						var rindex = arr[i];
						var value = row[rindex];
						var o = false;
						for (var j = 0; j < ptr.items.length; j++) {
							if (ptr.items[j].value == value) {
								o = ptr.items[j];
								ptr.items[j].row = rowNumber;
								break;
							}
						}
						if (!self.autoPaging) {
							//if (!o) {
							//	/*alert("Value not found in distinct?!?!? PANIC!!!"); 
							if (o) ptr = o;
						} else {
							if (o) ptr = o;
						}
					} /* for all conditions */
					ptr.used = true;
				} else {
					var posTitleMeasure = row.length - measures.length;
					row.splice(posTitleMeasure, 0, "");
					for (var m = 0; m < measures.length; m++) {
						//agrego a la fila el valor de la medida
						var measureName = measures[m].getAttribute("displayName")
						row[posTitleMeasure] = measureName;

						var ptr = struct;
						for (var i = 0; i < arr.length; i++) {
							var rindex = arr[i];//i; //arr[i]; 
							var value = row[rindex];
							var o = false;
							for (var j = 0; j < ptr.items.length; j++) {
								if (ptr.items[j].value == value) {
									o = ptr.items[j];
									//ptr.items[j].row = rowNumber*measures.length + m;
									break;
								}
							}
							if (!self.autoPaging) {
								//if (!o) { 
								//	/*alert("Value not found in distinct?!?!? PANIC!!!"); */}
								if (o) ptr = o;
							} else {
								if (o) ptr = o;
							}
						} /* for all conditions */
						ptr.used = true;
					}
					row.splice(posTitleMeasure, 1)
				}
			}

			function fillAllPart(struct) {
				var ptr = struct;
				if (!ptr.items) {
					ptr.used = true;
					return;
				}
				for (var i = 0; i < ptr.items.length; i++) { fillAllPart(ptr.items[i]); }
			}

			if (self.options.showEmpty) {
				fillAllPart(self.rowStructure);
				fillAllPart(self.colStructure);
			} else {
				for (var i = 0; i < self.filteredData.length; i++) {
					var row = self.filteredData[i];
					fillPart(self.rowStructure, self.rowConditions, row, i);
					fillPart(self.colStructure, self.colConditions, row, i);
				}
			}
		}

		this.checkAggStructure = function () { /* check structure for empty parts and delete them */
			function check(ptrT) { /* recursive function */
				if (!self.ShowMeasuresAsRows) {
					if (!ptrT.items) { return ptrT.used; } /* for leaves, return their usage state */
					for (var i = ptrT.items.length - 1; i >= 0; i--) { /* if node, decide based on children count */
						if (!check(ptrT.items[i])) {
							ptrT.items.splice(i, 1);
						}
					}
					return (ptrT.items.length > 0); /* return children state */
				} else {
					if (self.colConditions > 0) {
						var tempPt = ptrT
						if (!tempPt.items) { return tempPt.used; }
						var itemLg = tempPt.items.length
						var to = 5;
						var iterI;
						for (iterI = itemLg - 1; iterI > -1; iterI--) {
							if (iterI > -1) {
								var ol = 0;
								var resultado = check(tempPt.items[iterI]);
								if ((resultado != undefined) && (!resultado)) {
									tempPt.items.splice(iterI, 1);
								}
							}
						}
						return (tempPt.items.length > 0);
					}
				}
			}

			check(self.rowStructure);
			if (!self.ShowMeasuresAsRows) {
				check(self.colStructure);
			}
		}

		this.applyDefaultFormats = function (td, value) {
			var type = typeof value;
			switch (type) {
				case "number":
					value = gx.text.charReplace(value.toString(), ".", gx.decimalPoint);
					OAT.addTextNode(td, value)
					break;
				case "date":
					break;
			}
			return td;
		}

		this.refreshPivot = function (metadata, data, sameQuery) {
			if ((metadata != "") && (data != "")) {
				var parser = new DOMParser();
				var xmlData = parser.parseFromString(metadata, 'text/xml');
				var dimensions = xmlData.getElementsByTagName("OLAPDimension");
				var index;

				//add hide elements to blacklist
				for (var bli = 0; bli < self.conditions.length; bli++) {
					if ((self.conditions[bli]) && (self.serverPagination)) {
						var tempBlack = jQuery.extend(true, [], self.conditions[bli].blackList);
						for (var ib = 0; ib < tempBlack.length; ib++) {
							self.createFilterInfo({ op: "pop", values: tempBlack[ib], dim: bli });
						}
					}
					self.conditions[bli].blackList = []
				}

				var rowPosition = []; var colPosition = [];
				for (var dim = 0; dim < dimensions.length; dim++) { //for every dimensions of the other querie

					var dimID = dimensions[dim].getElementsByTagName("name")[0].childNodes[0].nodeValue; //get the name - "Identifier" of this dimension

					//now search for this name at this querie
					var dimPos = -1;
					for (var itC = 0; itC < self.columns.length; itC++) {
						if (self.columns[itC].attributes.getNamedItem("name").nodeValue === dimID)
							dimPos = itC;		//this is the number identifier of this dimension at this pivot	
					}


					if (dimPos != -1) {//the dimension exist in this pivot
						//columns and rows dimensions and filters
						var position = dimensions[dim].getElementsByTagName("condition")[0].childNodes[0].nodeValue; //where's the dimension? row, columns, filter
						if (position === "row") {
							index = self.colConditions.findIndex(dimPos);
							if (index != -1) { //if it is as columns, change to rows
								self.colConditions.splice(index, 1);
								if (measures.length > 1)
									self.rowConditions = [dimPos].concat(self.rowConditions);
								else
									self.rowConditions.push(dimPos);
							} else {
								index = self.filterIndexes.findIndex(dimPos);
								if (index != -1) {
									self.filterIndexes.splice(index, 1);
									if (measures.length > 1)
										self.rowConditions = [dimPos].concat(self.rowConditions);
									else
										self.rowConditions.push(dimPos);
								}
							}
							rowPosition[parseInt(dimensions[dim].getElementsByTagName("position")[0].childNodes[0].nodeValue)] = dimPos
						} else if (position === "col") {
							index = self.rowConditions.findIndex(dimPos);
							if (index != -1) {
								self.rowConditions.splice(index, 1);
								if (measures.length > 1)
									self.colConditions = [dimPos].concat(self.colConditions);
								else
									self.colConditions.push(dimPos);
							} else {
								index = self.filterIndexes.findIndex(dimPos);
								if (index != -1) {
									self.filterIndexes.splice(index, 1);
									if (measures.length > 1)
										self.colConditions = [dimPos].concat(self.colConditions);
									else
										self.colConditions.push(dimPos);
								}
							}
							colPosition[parseInt(dimensions[dim].getElementsByTagName("position")[0].childNodes[0].nodeValue)] = dimPos
						} else if (position === "none") {//to filter
							index = self.colConditions.findIndex(dimPos);
							if (index != -1) {
								self.colConditions.splice(index, 1);
								if (measures.length > 1)
									self.filterIndexes = [dimPos].concat(self.filterIndexes);
								else
									self.filterIndexes.push(dimPos);
							} else {
								index = self.rowConditions.findIndex(dimPos);
								if (index != -1) {
									self.rowConditions.splice(index, 1);
									if (measures.length > 1)
										self.filterIndexes = [dimPos].concat(self.filterIndexes);
									else
										self.filterIndexes.push(dimPos);
								}
							}

						}

						//set order value
						var order = dimensions[dim].getElementsByTagName("order")[0].childNodes[0].nodeValue;
						if (self.serverPagination) {
							if (order == "descending") {
								self.conditions[dimPos].sort = -1
							} else {
								self.conditions[dimPos].sort = 1
							}
						} else {
							if (order == "descending") {
								if ((self.conditions[dimPos].sort == 0) || (self.conditions[dimPos].sort == 2)) self.conditions[dimPos].sort = 2;
								else self.conditions[dimPos].sort = -1;
								self.stateChanged = true; self.sort(self.conditions[dimPos], dimPos);
							} else {
								if ((self.conditions[dimPos].sort == 0) || (self.conditions[dimPos].sort == 2)) self.conditions[dimPos].sort = 0
								else self.conditions[dimPos].sort = 1;
								self.stateChanged = true; self.sort(self.conditions[dimPos], dimPos);
							}
						}

						//reset blacklists
						var hides = dimensions[dim].getElementsByTagName("hide")[0].childNodes;
						for (var sofs = 0; sofs < hides.length; sofs++) {
							if (hides[sofs].tagName === "value") {
								var index = self.conditions[dimPos].blackList.findIndex(hides[sofs].textContent);
								//if not already in the list
								if (index === -1) {
									for (var t = 0; t < self.conditions[dimPos].distinctValues.length; t++) {
										var trimValue = self.conditions[dimPos].distinctValues[t].toString().trimpivot();
										if (trimValue == hides[sofs].textContent) {
											if (!self.serverPagination) {
												self.conditions[dimPos].blackList.push(self.conditions[dimPos].distinctValues[t]);
											} else {
												self.createFilterInfo({ op: "push", values: self.conditions[dimPos].distinctValues[t], dim: dimPos });
											}
										}
									}
								}
							}
						}
						//set values of filter bars
						if (dimensions[dim].getElementsByTagName("filterdivs").length > 0) {
							var fils = dimensions[dim].getElementsByTagName("filterdivs")[0].childNodes;
							for (var sofs = 0; sofs < fils.length; sofs++) {
								if (fils[sofs].tagName === "value") {
									var findex = self.filterIndexes.findIndex(dimPos);
									if (findex != -1) {
										if (self.filterDiv.selects[findex] != undefined) {
											self.filterDiv.selects[findex].value = fils[sofs].textContent;
										}
									}
								}
							}
						}

					} //else the dimension not exists in this pivot




				}

				//set dimension position
				if ((self.rowConditions.length - (measures.length - 1)) == rowPosition.length) {
					for (var i = 0; i < rowPosition.length; i++) {
						self.rowConditions[i] = rowPosition[i];
					}
				}
				if (self.colConditions.length == colPosition.length) {
					for (var i = 0; i < colPosition.length; i++) {
						self.colConditions[i] = colPosition[i];
					}
				}


				if (!self.serverPagination) {
					self.go(false, true);
				} else {
					for (var c = 0; c < self.columns.length; c++) {
						self.pageData.AxisInfo = self.createAxisInfo(self.columns[c].getAttribute("dataField"));
					}
					self.pageData.CollapseInfo = self.CreateExpandCollapseInfo("");
					self.pageData.DataInfo = self.createDataInfo()
					self.QueryViewerCollection[self.IdForQueryViewerCollection].getPageDataForPivotTable((function (resXML) {
						if (!qv.util.anyError(resXML) || self.QueryViewerCollection[self.IdForQueryViewerCollection].debugServices) {

							self.pageData = OATGetNewDataFromXMLForPivot(resXML, self.pageData, self.ShowMeasuresAsRows);
							self.goWhenServerPagination(false, true);
							qv.util.hideActivityIndicator(self.QueryViewerCollection[self.IdForQueryViewerCollection]);

						} else {
							var errMsg = qv.util.getErrorFromText(resXML);
							qv.util.renderError(self.QueryViewerCollection[self.IdForQueryViewerCollection], errMsg);
						}

					}).closure(this), [1, self.rowsPerPage, true, self.pageData.AxisInfo, self.pageData.DataInfo, self.pageData.FilterInfo, self.pageData.CollapseInfo, true]);
				}
			}
		}

		this.changePaginationRows = function (page, gonext, lastPage) {
			if (self.autoPaging) {
				var tempDataRows = self.GeneralDataRows;
				if (self.RowsWhenMoveToFilter.length > 0) { //there's no top filter dimension
					tempDataRows = self.RowsWhenMoveToFilter;
				}

				self.allData = [];
				var init = 0
				if (page > 1) {
					if (lastPage) {
						init = tempDataRows.length - 1;
					} else if (gonext) {
						init = self.nextRowWhenAutopaging
					} else {
						init = self.prevRowWhenAutopaging
					}
				}
				var end = init + self.autoPagingRowsPerPage;

				var dataRows = [];

				if ((!this.paginationInfo) || (!this.paginationInfo.pages)) { //calculate first and last row
					createPaginationInfo(self, tempDataRows);
				}

				dataRows = self.paginationInfo.pages[page - 1].rows
				//search rows for blank cell when dimension in columns
				if (self.colConditions.length > 0) {
					dataRows = self.rowsForBlankCells(dataRows);
				}


				self.allData = dataRows;


				var prevConditions = self.conditions //save black lists
				self.conditions = [];
				for (var i = 0; i < self.headerRow.length; i++) {
					self.pseudoInitCondition(i, prevConditions);
				}


			}
		}

		this.rowsForBlankCells = function (rows) {
			//get dimension values on columms and rows
			var diferentColValues = [];
			var diferentRowValues = [];
			var refValuesCol = []; var refValuesRow = [];
			for (var dV = 0; dV < rows.length; dV++) {
				var dimVals = [];
				var colVals = [];
				for (var cVI = 0; cVI < self.rowConditions.length - (measures.length - 1); cVI++) {
					colVals[cVI] = rows[dV][self.rowConditions[cVI]];
				}
				for (var dVI = 0; dVI < self.colConditions.length; dVI++) {
					dimVals[dVI] = rows[dV][self.colConditions[dVI]];
				}
				if (refValuesCol.indexOf(dimVals.toString()) == -1) {
					diferentColValues.push(dimVals);
					refValuesCol.push(dimVals.toString());
				}
				if (refValuesRow.indexOf(colVals.toString()) == -1) {
					diferentRowValues.push(colVals);
					refValuesRow.push(colVals.toString());
				}
			}

			//create partial rows from dimension values on columns and rows
			var partialRows = [];
			for (var rC = 0; rC < diferentColValues.length; rC++) {
				for (var rV = 0; rV < diferentRowValues.length; rV++) {
					var partRow = [];
					for (var cVI = 0; cVI < self.rowConditions.length - (measures.length - 1); cVI++) {
						partRow[self.rowConditions[cVI]] = diferentRowValues[rV][cVI];
					}
					for (var dVI = 0; dVI < self.colConditions.length; dVI++) {
						partRow[self.colConditions[dVI]] = diferentColValues[rC][dVI];
					}
					partialRows.push(partRow);
				}
			}

			//get all needed rows
			rows = [];
			for (var a = 0; a < partialRows.length; a++) {
				var newRow = self.getRowFromDimensionRow(partialRows[a], self.GeneralDataRows);
				rows.push(newRow);
			}

			return rows;
		}

		this.getRowFromDimensionRow = function (row, rowCollection) {
			for (var rCL = 0; rCL < rowCollection.length; rCL++) {
				var same = true;
				for (var rwoI = 0; rwoI < row.length; rwoI++) {
					if (row[rwoI] != undefined) {
						if (row[rwoI] != rowCollection[rCL][rwoI]) {
							same = false;
							break;
						}
					}
				}
				if (same) {
					return rowCollection[rCL]
				}
			}
			return null
		}

		this.countNotFiltered = function (datas) {
			var total = 0;
			for (var i = 0; i < datas.length; i++) {
				if (!self.notInBlackList(datas[i], self.conditions)) {
					total++;
				}
			}

			var rs = parseInt(total / self.autoPagingRowsPerPage);
			if ((total % self.autoPagingRowsPerPage) != 0) {
				rs++;
			}
			return rs;
		}

		this.setNewPagesAccount = function (cantPages) {
			try {
				if (jQuery("#" + self.controlName + " #tablePagination_totalPages").length > 0) {
					OAT.replaceTextNode(jQuery("#" + self.containerName + " #tablePagination_totalPages")[0], " " + cantPages)
				} else {
					OAT.replaceTextNode(jQuery("#" + self.controlName + "_" + self.query + "_tablePagination " + "#tablePagination_totalPages")[0], " " + cantPages)
				}
			} catch (ERROR) {
				if (self.paginationInfo.totalPages > 1) {
					var options = {
						currPage: self.actualPaginationPage,
						ignoreRows: jQuery('tbody tr[title_row=true]', jQuery("#" + self.controlName + "_" + self.query)),
						optionsForRows: [10, 15, 20],
						rowsPerPage: self.autoPagingRowsPerPage,
						topNav: false,
						controlName: self.controlName + "_" + self.query,
						cantPages: self.paginationInfo.totalPages
					}

					OAT.partialTablePagination(jQuery("#" + self.controlName + "_" + self.query), options);

					jQuery("#" + self.controlName + "_" + self.query).css("margin-bottom", "0px");
				}
			}
		}


		this.notInBlackList = function (row, conditions) {
			var esta = false;
			for (var i = 0; i < row.length; i++) {
				if ((conditions[i] != undefined) && (conditions[i].blackList != undefined) && (conditions[i].blackList.findIndex(row[i]) != -1)) {
					esta = true;
				}
			}
			return esta;
		}


		this.preGoWhenShowHideMeasures = function (index) {
			var displayName = self.initMetadata.Measures[index].displayName;

			//column hide
			var columnIndex = self.headerRow.indexOf(displayName);
			if (!self.initMetadata.Measures[index].Visible) {
				if (measures.length > 1) {
					self.rowConditions.splice(self.rowConditions.length - 1, 1)
					self.dataColumnIndex = self.dataColumnIndex - 1
				}
				/*if (self.dataColumnIndex == columnIndex){
					if (measures.length > 1){
						self.dataColumnIndex = self.rowConditions[self.rowConditions.length-1];
						self.rowConditions.splice(self.rowConditions.length-1,1)
						//self.rowConditions.splice(self.dataColumnIndex,1)
					}
				} else {
					self.rowConditions.splice(self.rowConditions.indexOf(columnIndex),1)
				}*/
			} else {
				var presentMeasures = measures.length - 1;
				for (var o = 0; o < presentMeasures; o++) {
					self.rowConditions.splice(self.rowConditions.length - 1, 1)
				}
				if ((presentMeasures >= 0) && (measures[0].getAttribute("dataField") != "F0")) {
					var cols = self.rowConditions.length + self.colConditions.length + self.filterIndexes.length;
					if (measures.length > 0) {
						var prevCol = cols;
						cols = cols + measures.length;
						for (var i = prevCol; i < cols; i++) {
							self.rowConditions.push(i);
						}
					}
				}
			}

			for (var i = 0; i < self.columns.length; i++) {
				var dF = self.columns[i].getAttribute("dataField")
				var index = self.initMetadata.DataFields.indexOf(dF);
				self.initMetadata.Conditions[index] = self.conditions[i];
			}

			this.goWhenHide();
		}


		this.preGoWhenShowHideDimension = function (index) {
			for (var ip = 0; ip < self.columns.length; ip++) {
				var dF = self.columns[ip].getAttribute("dataField")
				var ix = self.initMetadata.DataFields.indexOf(dF);
				self.initMetadata.Conditions[ix] = self.conditions[ip];
			}

			var conditionIndex;
			var DataFile = self.initMetadata.DataFields[index]
			for (var ip = 0; ip < self.columns.length; ip++) {
				var dF = self.columns[ip].getAttribute("dataField")
				if (DataFile == dF) {
					conditionIndex = ip
				}
			}


			if (!self.initMetadata.Dimensions[index].Visible) {
				self.initMetadata.DimensionPosition[index] = "row"
				//self.conditions[conditionIndex].position = "row"
				if (self.colConditions.indexOf(conditionIndex) > -1) {
					self.initMetadata.DimensionPosition[index] = "col"
					//self.conditions[conditionIndex].position = "col"
				}
				if (self.filterIndexes.indexOf(conditionIndex) > -1) {
					self.initMetadata.DimensionPosition[index] = "fil"
					//self.conditions[conditionIndex].position = "fil"
				}
			}

			var displayName = self.initMetadata.Dimensions[index].displayName;

			//column hide
			var columnIndex = self.headerRow.indexOf(displayName);
			if (!self.initMetadata.Dimensions[index].Visible) {
				if (self.rowConditions.indexOf(columnIndex) > -1) {
					self.rowConditions.splice(self.rowConditions.indexOf(columnIndex), 1)
				} else if (self.colConditions.indexOf(columnIndex) > -1) {
					self.colConditions.splice(self.colConditions.indexOf(columnIndex), 1)
				} else if (self.filterIndexes.indexOf(columnIndex) > -1) {
					self.filterIndexes.splice(self.filterIndexes.indexOf(columnIndex), 1)
				}

				//correct measure and dimension number
				self.dataColumnIndex = self.dataColumnIndex - 1
				for (var i = 0; i < self.rowConditions.length; i++) {
					if (self.rowConditions[i] > columnIndex) {
						self.rowConditions[i] = self.rowConditions[i] - 1
					}
				}
				for (var i = 0; i < self.colConditions.length; i++) {
					if (self.colConditions[i] > columnIndex) {
						self.colConditions[i] = self.colConditions[i] - 1
					}
				}
				for (var i = 0; i < self.filterIndexes.length; i++) {
					if (self.filterIndexes[i] > columnIndex) {
						self.filterIndexes[i] = self.filterIndexes[i] - 1
					}
				}

			} else {
				var previousPosition = self.initMetadata.DimensionPosition[index]//self.initMetadata.Conditions[index].position;

				if (previousPosition == undefined) {
					var defpos = self.initMetadata.Dimensions[index].defaultPosition

					if (defpos.indexOf("rows") > -1) previousPosition = "row";
					else
						if (defpos.indexOf("columns") > -1) previousPosition = "col";
						else
							if (defpos.indexOf("filters") > -1) previousPosition = "fil";
							else previousPosition = "row";

				}


				var posIndex = 0
				for (var i = 0; i < index; i++) {
					if (self.initMetadata.Dimensions[i].Visible) posIndex = posIndex + 1
				}

				index = posIndex;
				if (previousPosition == "row") {
					var tempRowConsition = [];
					var existe = (self.rowConditions.indexOf(index) > -1)
					for (var t = 0; t < self.rowConditions.length; t++) {
						if (self.rowConditions[t] < index) {
							tempRowConsition.push(self.rowConditions[t])
						} else if (self.rowConditions[t] == index) {
							tempRowConsition.push(index)
							tempRowConsition.push(index + 1)
							existe = true
						} else {
							if (!existe) {
								tempRowConsition.push(index)
								existe = true
							}
							tempRowConsition.push(self.rowConditions[t] + 1)
						}
					}
					if (!existe) {
						tempRowConsition.push(index)
					}
					self.rowConditions = []
					self.rowConditions = tempRowConsition

					self.dataColumnIndex = self.dataColumnIndex + 1


					var tempColConsition = [];
					for (var t = 0; t < self.colConditions.length; t++) {
						if (self.colConditions[t] >= index) {
							tempColConsition.push(self.colConditions[t] + 1)
						} else {
							tempColConsition.push(self.colConditions[t])
						}
					}
					self.colConditions = []
					self.colConditions = tempColConsition

					var tempFilConsition = [];
					for (var t = 0; t < self.filterIndexes.length; t++) {
						if (self.filterIndexes[t] >= index) {
							tempFilConsition.push(self.filterIndexes[t] + 1)
						} else {
							tempFilConsition.push(self.filterIndexes[t])
						}
					}
					self.filterIndexes = []
					self.filterIndexes = tempFilConsition


				} else if (previousPosition == "col") {

					var tempRowConsition = [];
					for (var t = 0; t < self.rowConditions.length; t++) {
						if (self.rowConditions[t] >= index) {
							tempRowConsition.push(self.rowConditions[t] + 1)
						} else {
							tempRowConsition.push(self.rowConditions[t])
						}
					}
					self.rowConditions = []
					self.rowConditions = tempRowConsition

					self.dataColumnIndex = self.dataColumnIndex + 1



					var tempColConsition = [];
					var existe = (self.colConditions.indexOf(index) > -1)
					for (var t = 0; t < self.colConditions.length; t++) {
						if (self.colConditions[t] < index) {
							tempColConsition.push(self.colConditions[t])
						} else if (self.colConditions[t] == index) {
							tempColConsition.push(index)
							tempColConsition.push(index + 1)
							existe = true
						} else {
							if (!existe) {
								tempColConsition.push(index)
								existe = true
							}
							tempColConsition.push(self.colConditions[t] + 1)
						}
					}
					if (!existe) {
						tempColConsition.push(index)
					}
					self.colConditions = []
					self.colConditions = tempColConsition




					var tempFilConsition = [];
					for (var t = 0; t < self.filterIndexes.length; t++) {
						if (self.filterIndexes[t] >= index) {
							tempFilConsition.push(self.filterIndexes[t] + 1)
						} else {
							tempFilConsition.push(self.filterIndexes[t])
						}
					}
					self.filterIndexes = []
					self.filterIndexes = tempFilConsition
				} else if (previousPosition == "fil") {

					var tempRowConsition = [];
					for (var t = 0; t < self.rowConditions.length; t++) {
						if (self.rowConditions[t] >= index) {
							tempRowConsition.push(self.rowConditions[t] + 1)
						} else {
							tempRowConsition.push(self.rowConditions[t])
						}
					}
					self.rowConditions = []
					self.rowConditions = tempRowConsition

					self.dataColumnIndex = self.dataColumnIndex + 1


					var tempColConsition = [];
					for (var t = 0; t < self.colConditions.length; t++) {
						if (self.colConditions[t] >= index) {
							tempColConsition.push(self.colConditions[t] + 1)
						} else {
							tempColConsition.push(self.colConditions[t])
						}
					}
					self.colConditions = []
					self.colConditions = tempColConsition


					var tempFilConsition = [];
					var existe = (self.filterIndexes.indexOf(index) > -1)
					for (var t = 0; t < self.filterIndexes.length; t++) {
						if (self.filterIndexes[t] < index) {
							tempFilConsition.push(self.filterIndexes[t])
						} else if (self.filterIndexes[t] == index) {
							tempFilConsition.push(index)
							tempFilConsition.push(index + 1)
							existe = true
						} else {
							if (!existe) {
								tempFilConsition.push(index)
								existe = true
							}
							tempFilConsition.push(self.filterIndexes[t] + 1)
						}
					}
					if (!existe) {
						tempFilConsition.push(index)
					}
					self.filterIndexes = []
					self.filterIndexes = tempFilConsition
				}
				//correccion de las medidas
				/*var presentMeasures = measures.length - 1;
				for (var o = 0; o < presentMeasures; o++){
					self.rowConditions.splice(self.rowConditions.length-1,1)
				}
				
				
				
				if (presentMeasures >= 0){
					var cols = self.rowConditions.length + self.colConditions.length + self.filterIndexes.length;
					if (measures.length > 0) {
						var prevCol = cols;
						cols = cols + measures.length; 
						for(var i = prevCol; i < cols; i++)
						{
							self.rowConditions.push(i);
						}
					}
				}*/
			}
			
			self.initRowConditions = []
			for(var i = 0; i<self.rowConditions.length; i++){
				self.initRowConditions.push(self.rowConditions[i])
			}
			
			this.goWhenHide();
		}

		this.goWhenHide = function (clean) {
			var hideDimension = [];
			for (var i = 0; i < self.initMetadata.Dimensions.length; i++) {
				if (!self.initMetadata.Dimensions[i].Visible) {
					hideDimension.push(self.initMetadata.Dimensions[i].dataField)
				}
			}
			var hideMeasures = [];
			for (var i = 0; i < self.initMetadata.Measures.length; i++) {
				if (!self.initMetadata.Measures[i].Visible) {
					hideMeasures.push(self.initMetadata.Measures[i].dataField)
				}
			}

			var stateHidden = {
				DataFields: self.initMetadata.DataFields,
				Dimensions: self.initMetadata.Dimensions,
				Measures: self.initMetadata.Measures,
				DimensionPosition: self.initMetadata.DimensionPosition,
				Conditions: self.initMetadata.Conditions,
				version: self.rememberLayoutStateVersion
			}
			self.saveHiddenState(stateHidden)


			var result = OATParseMetadata(self.initMetadata.Metadata, hideDimension, hideMeasures, self.serverPagination)
			var newMetadata = result[0]; self.HideDataFilds = result[2]; self.OrderFildsHidden = result[1];

			var xmlDoc = jQuery.parseXML(newMetadata);
			measures = xmlDoc.getElementsByTagName("OLAPMeasure");
			self.columns = xmlDoc.getElementsByTagName("OLAPDimension");

			var result = OATGetColumnsAndMeasureMeatadata(self.columns, measures, self.formulaInfo, self.OrderFildsHidden)
			self.headerRow = result[0];
			self.formulaInfo.measureFormula = result[2];
			self.conditionalFormats = result[3];
			self.conditionalFormatsColumns = result[4];

			var orderFilds = result[1];

			if (!self.serverPagination) {
				var dataRows = [];
				var result = OATgetAllDataFromXMLOldFormat(self.initMetadata.DataString, orderFilds, self.OrderFildsHidden);
				dataRows = result[0]
				self.recordForFormula = result[1];

				if (result[1].length > 0) {
					self.formulaInfo.recordDataLength = result[1][0].length
				}
			}

			if (measures.length > 0) {
				self.dataColumnIndex = self.headerRow.length - 1;
			} else {
				if (!self.serverPagination) {
					for (var i = 0; i < dataRows.length; i++) {
						dataRows[i].push("0");
					}
				}
			}

			if (!self.serverPagination) {
				reLoadDataArrays(dataRows, self.formulaInfo, self.headerRow, self.columns, self, measures, self.recordForFormula)
			}

			//self.GeneralDataRows = OATgetDataFromXMLOldFormat(self.initMetadata.DataString, orderFilds)

			//self.allData = self.GeneralDataRows
			if (self.serverPagination) {
				self.conditions = [];
				for (var i = 0; i < self.headerRow.length; i++) {
					self.initCondition(i);
					//add info for server paging porpouse
					if (self.conditions[i] && self.columns[i]) {
						self.conditions[i].dataField = self.columns[i].getAttribute("dataField")
						self.conditions[i].state = "all"
						self.conditions[i].defaultAction = "Include"
						self.conditions[i].visibles = []
						self.conditions[i].searchInfo = { previousPage: 0, totalPages: 0, filteredText: "", values: [] }
					}
					self.applyCustomFilters(i);
				}

				for (var i = 0; i < self.columns.length; i++) {
					var dF = self.columns[i].getAttribute("dataField")
					var index = self.initMetadata.DataFields.indexOf(dF);
					if (self.initMetadata.Conditions[index] != "") {
						self.initMetadata.Conditions[index].dataRowPosition = self.conditions[i].dataRowPosition
						self.conditions[i] = self.initMetadata.Conditions[index];
					}
				}

				self.cleanGridCache();

				self.pageData.AxisInfo = self.createAxisInfo();

				self.pageData.DataInfo = self.createDataInfo()

				self.QueryViewerCollection[self.IdForQueryViewerCollection].getPageDataForPivotTable((function (resXML) {
					if (!qv.util.anyError(resXML) || self.QueryViewerCollection[self.IdForQueryViewerCollection].debugServices) {
						self.pageData = OATGetNewDataFromXMLForPivot(resXML, self.pageData, self.ShowMeasuresAsRows);
						self.goWhenServerPagination(false, false);
						qv.util.hideActivityIndicator(self.QueryViewerCollection[self.IdForQueryViewerCollection]);
					} else {
						var errMsg = qv.util.getErrorFromText(resXML);
						qv.util.renderError(self.QueryViewerCollection[self.IdForQueryViewerCollection], errMsg);
					}
				}).closure(this), [1, self.rowsPerPage, true, self.pageData.AxisInfo, self.pageData.DataInfo, self.pageData.FilterInfo, self.pageData.CollapseInfo, true]);

				if (clean) {
					self.initValueRead(self, 0);
				} else {

					for (var i = 0; i < self.columns.length; i++) {
						if (self.conditions[i].totalPages == undefined) {
							//load values
							var cantItems = 10;
							if ((self.QueryViewerCollection[self.IdForQueryViewerCollection].AutoRefreshGroup != "")) {
								cantItems = 0;
							}
							var columnNumber = i;
							self.QueryViewerCollection[self.IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
								var data = JSON.parse(resJSON);

								self.conditions[columnNumber].previousPage = data.PageNumber
								self.conditions[columnNumber].totalPages = data.PagesCount
								self.conditions[columnNumber].blocked = false
								//null value?
								if (data.Null) {
									self.conditions[columnNumber].hasNull = true;
									if (self.conditions[columnNumber].distinctValues.indexOf("#NuN#") == -1) {
										self.conditions[columnNumber].distinctValues.push("#NuN#")
									}
									var nullIncluded = true;

									if (!self.conditions[columnNumber].NullIncluded) {
										nullIncluded = false;
									}
									if ((nullIncluded) && (self.conditions[columnNumber].visibles.indexOf("#NuN#") == -1)) {
										self.conditions[columnNumber].visibles.push("#NuN#");
									}
								} else {
									self.conditions[columnNumber].hasNull = false;
								}

								var includeLists = [];
								for (var i = 0; i < data.NotNullValues.length; i++) {
									var value = data.NotNullValues[i]
									var include = false;
									if ((self.conditions[columnNumber].state == "none") &&
										(self.UserFilterValues.length > 0) && (self.UserFilterValues[columnNumber] != undefined)
										&& (self.UserFilterValues[columnNumber].length > 0) && (self.UserFilterValues[columnNumber].indexOf(value.trimpivot()) != -1)) {
										include = true;
										includeLists.push(value)
									}

									if (self.conditions[columnNumber].distinctValues.indexOf(value) == -1) {
										self.conditions[columnNumber].distinctValues.push(value)
									}
									if ((self.conditions[columnNumber].state == "all")
										&& (self.conditions[columnNumber].visibles.indexOf(value) == -1)) {
										self.conditions[columnNumber].visibles.push(value)
									}
									if ((self.conditions[columnNumber].state == "none")
										&& (self.conditions[columnNumber].blackList.indexOf(value) == -1)
										&& (!include)) {
										self.conditions[columnNumber].blackList.push(value)
									}

									if ((self.UserExpandValues.length > 0)) {//collapsed values
										if (self.UserExpandValues[columnNumber] != undefined) {
											if ((self.UserExpandValues[columnNumber][0] == "#ALLCOLLAPSE#") ||
												(self.UserExpandValues[columnNumber].indexOf(value.trimpivot()) == -1)) {
												self.conditions[columnNumber].collapsedValues.push(value);
											}
										}
									}

								}

								for (var i = 0; i < includeLists.length; i++) {
									self.createFilterInfo({ op: "pop", values: includeLists[i], dim: columnNumber }, true);
								}



							}).closure(this), [self.columns[columnNumber].getAttribute("dataField"), 1, cantItems, ""]);
						}
					}

				}

			}

			if (!self.serverPagination) {
				self.conditions = [];
				for (var i = 0; i < self.headerRow.length; i++) {
					self.initCondition(i);
				}

				for (var i = 0; i < self.columns.length; i++) {
					var dF = self.columns[i].getAttribute("dataField")
					var index = self.initMetadata.DataFields.indexOf(dF);
					if (self.initMetadata.Conditions[index] != "") {
						self.initMetadata.Conditions[index].dataRowPosition = self.conditions[i].dataRowPosition
						self.conditions[i] = self.initMetadata.Conditions[index];
					}
				}
				self.autoPaging = false;

				self.init();
				if (self.filterIndexes.length > 0) {
					self.preGoWhenMoveTopFilter(self.filterIndexes[0], true)
					if (self.tempBlackLists) {
						if (!self.autoPaging) {
							//reload blacklist & sort
							for (var i = 0; i < self.conditions.length; i++) {
								if (self.conditions[i]) {
									if (self.tempBlackLists[i]) {
										self.conditions[i].blackList = self.tempBlackLists[i]
									}
									if (self.tempCollapsedValues[i]) {
										self.conditions[i].collapsedValues = self.tempCollapsedValues[i]
									}
								}
							}
						}
					}
					try {
						if (self.oldSortValues.length > 0) {
							for (var fsort = 0; fsort < self.conditions.length; fsort++) {
								if (self.conditions[fsort]) {
									self.conditions[fsort].sort = self.oldSortValues[fsort];
									self.sort(self.conditions[fsort]);
								}
							}
						}
					} catch (Error) {
					}
					self.go(false, false);
				} else {
					self.go(false, false);
				}
			}
		}

		this.preGo = function (load, autorefreshflag, value, column, init) {
			/*get previous state, when first load*/
			if ((init) && (rememberLayout)) {
				var mState = self.getState();
				if ((mState != null) && (mState.version === self.rememberLayoutStateVersion)) {
					if ((mState.query == self.query) && (this.conditions.length == mState.conditions.length) && (mState.filterIndexes.length == 0)) {
						for (var ci = 0; ci <= mState.conditions.length - 1; ci++) {
							if ((mState.conditions[ci] != false) && (self.conditions[ci] != false)) {
								for (var p = 0; p < mState.conditions[ci].blackList.length; p++) {
									if ((self.conditions[ci].blackList.indexOf(mState.conditions[ci].blackList[p]) == -1) &&
										(self.conditions[ci].distinctValues.indexOf(mState.conditions[ci].blackList[p]) != -1)) {
										self.conditions[ci].blackList.push(mState.conditions[ci].blackList[p])
									}
								}
								self.conditions[ci].sort = mState.conditions[ci].sort;
							}
						}

						self.rowConditions = mState.rowConditions;
						self.colConditions = mState.colConditions;
						self.rowsPerPage = mState.rowsPerPage;
					}
				}
			}
			/*end get state*/
			//setear datos a pivotear
			var tempDataRows;
			if (self.filterIndexes.length > 0) {
				collapseRowForCollapseValues(self);
				tempDataRows = self.RowsWhenMoveToFilter;
			} else {
				tempDataRows = self.GeneralDataRows;
			}
			//aplicar filtros

			var oldDataRows = dataRows;
			dataRows = [];
			var i = 0; var j = 0;
			var tempConsiderNoNewHelper = [];
			while ((i < this.autoPagingRowsPerPage) && (j < tempDataRows.length)) {
				if ((column == -1) || ((j < tempDataRows.length) && (tempDataRows[j][column] != value))) {

					if (self.isNotFilterByTopFilter(tempDataRows[j]) && (!self.notInBlackList(tempDataRows[j], self.conditions))) { //ver que no sea esta fila filtrada por ninguna condicion
						//case undefined & value
						if ((tempDataRows[j][column] == undefined) && (value == " ")) {
							var isNoNew = self.canBeConsiderNoNew(tempDataRows[j], dataRows, tempConsiderNoNewHelper);
							dataRows.push([tempDataRows[j]]);
							if (!isNoNew) {
								i++;
							}
						} else {
							var isNoNew = self.canBeConsiderNoNew(tempDataRows[j], dataRows, tempConsiderNoNewHelper);
							dataRows.push([tempDataRows[j]]);
							if (!isNoNew) {
								i++;
							}
						}


					}
				}
				j++; //in case there no enought data rows
			}

			if (dataRows.length < 1) { //case when theres no value to show
				dataRows = oldDataRows;
				this.go(false, autorefreshflag)
			}

			self.allData = dataRows;

			var prevConditions = self.conditions //save black lists
			self.conditions = [];

			for (var i = 0; i < self.headerRow.length; i++) { //Modificar init conditions para mantener los que no se muestran
				self.pseudoInitCondition(i, prevConditions);
			}

			setTimeout(function () { createPaginationInfo(self, self.RowsWhenMoveToFilter); }, 500)

			this.go(false, autorefreshflag)
		}

		this.canBeConsiderNoNew = function (row, dataRows, helperList) {
			if (self.colConditions.length > 0) {
				var notNew = false;
				for (var i = 0; i < dataRows.length; i++) {
					var same = true;
					for (var j = 0; j < self.rowConditions.length; j++) {
						if (dataRows[i][self.rowConditions[j]] != row[self.rowConditions[j]]) {
							same = false;
						}
					}
					if (same == true) {
						notNew = true;
						break;
					}
				}
			}
			if (self.filterIndexes.length > 0)//si hay dimensiones en los filtros superiores, hay filas que pueden colapsarse
			{
				var notNew = false;

				for (var i = 0; i < helperList.length; i++) {
					var same = true;
					for (var j = 0; j < self.rowConditions.length - measures.length + 1; j++) {

						if (helperList[i][self.rowConditions[j]] != row[self.rowConditions[j]]) {
							same = false;
						}

					}
					if (same == true) {
						notNew = true;
						break;
					}
				}
				if (!notNew) {
					helperList.push(row);
				}


			}
			return notNew;
		}

		this.preGoWhenMoveTopFilter = function (filterIndex, initLoad) {
			if (initLoad == undefined) {
				for (var i = 0; i < self.filterDiv.selects.length; i++) {
					self.filterDiv.selects[i].value = "[all]"
				}
			} else {
				var out = false;
				for (var i = 0; i < self.filterDiv.selects.length; i++) {
					if (self.filterDiv.selects[i].value != "[all]") {
						out = true;
					}
				}
				if ((out) && (!self.autoPaging)) return;
			}
			self.FilterByTopFilter = false
			//get the index of the columns values in the data records of GeneralData, less filter index
			var dataColumns = [];
			for (var i = 0; i < columns.length; i++) {
				var pos = i;//parseInt(columns[i].attributes.dataField.nodeValue.substr(1)) -1;
				if (((pos) != filterIndex) && (self.filterIndexes.findIndex(pos) == -1)) {
					dataColumns.push(pos)
				}
			}

			var dataRows = self.GeneralDataRows;

			if (!self.autoPaging) {
				//remove extra data rows, that have the same columns values, except for the value of the columns index
				var tempDataRows = [];
				for (var i = 0; i < dataRows.length; i++) {

					var existe = false;
					var previousRecord = 0;
					for (var j = 0; j < tempDataRows.length; j++) {
						var same = true;
						for (var h = 0; h < dataColumns.length; h++) {
							if (dataRows[i][dataColumns[h]] != tempDataRows[j][dataColumns[h]]) {

								same = false;
								break;
							}
						}
						if (same) {
							previousRecord = j;
							existe = true;
							break;
						}
					}
					if (!existe) {
						var newRecord = [];
						for (var p = 0; p < dataRows[i].length; p++) {
							newRecord.push([dataRows[i][p]]);
						}
						tempDataRows.push([newRecord]);

						for (var t = 0; t < measures.length; t++) {
							var pos;
							if (t < measures.length - 1) {
								pos = self.rowConditions[self.rowConditions.length - measures.length + 1 + t]
							} else {
								pos = self.dataColumnIndex
							}
							if ((self.formulaInfo.measureFormula[t].hasFormula) && (self.filterIndexes.length > 0)) {
								var valuesToOperate = self.getFormulaRowByDataRow(dataRows[i], t, "")
								if ((valuesToOperate != self.EmptyValue) && (valuesToOperate != "#NuN#")) {
									var result = self.calculateFormulaTotal([valuesToOperate], t, "MeasureInRows")
									if (!isNaN(result)) {
										newRecord[pos] = result.toString()
									}
								}
							}
						}

					} else { //increase prevoius record value

						//increase the entry of the column index (the last one)
						if (measures.length > 0) {
							if (!self.formulaInfo.measureFormula[measures.length - 1].hasFormula) {
								if ((tempDataRows[previousRecord][self.dataColumnIndex] != "#NuN#") && (dataRows[i][self.dataColumnIndex] != "#NuN#")) {
									tempDataRows[previousRecord][self.dataColumnIndex] = (parseFloat(tempDataRows[previousRecord][self.dataColumnIndex]) + parseFloat(dataRows[i][self.dataColumnIndex])).toString()
								} else if (tempDataRows[previousRecord][self.dataColumnIndex] == "#NuN#") {
									tempDataRows[previousRecord][self.dataColumnIndex] = dataRows[i][self.dataColumnIndex]
								}
							}
						}
						//increase the entries of other columns
						for (var t = 0; t < measures.length - 1; t++) {
							var pos = self.rowConditions[self.rowConditions.length - measures.length + 1 + t]
							if ((self.formulaInfo.measureFormula[t].hasFormula) && (self.filterIndexes.length > 0)) {
								//var addedValues = self.getFormulaRowByDataRow(dataRows[i], t, "")
							} else {
								tempDataRows[previousRecord][pos] = (parseFloat(tempDataRows[previousRecord][pos]) + parseFloat(dataRows[i][pos])).toString()
							}
						}
					}
				}
				//end remove extra data rows, that have the same columns values, except for the value of the columns index

				self.allData = tempDataRows;
				self.conditions = [];
				for (var i = 0; i < self.headerRow.length; i++) {
					self.initCondition(i);
				}
				for (var i = 0; i < self.headerRow.length; i++) {
					self.restoreSubtotalsAndSortLayout(i)
				}
			} else {
				//remove collapsed rows	
				collapseRowForCollapseValues(self);
				//end remove collapsed rows
				//self.RowsWhenMoveToFilter = tempDataRows;
				var tempDataRows2 = self.RowsWhenMoveToFilter;
				var dataRows = [];
				var i = 0;
				var j = 0;

				value = null; var ConsiderNoNewHelper = [];
				while ((i < this.autoPagingRowsPerPage) && (j < tempDataRows2.length)) {
					if ((!self.notInBlackList(tempDataRows2[j], self.conditions)) && (self.isNotFilterByTopFilter(tempDataRows2[j]))) { //ver que no sea esta fila filtrada por ninguna condicion
						//case undefined & value
						var isNoNew = self.canBeConsiderNoNew(tempDataRows2[j], dataRows, ConsiderNoNewHelper);
						dataRows.push([tempDataRows2[j]]);
						if (!isNoNew) {
							i++;
						} else {
							//alert('not new')
						}
					}
					j++; //in case there no enought data rows
				}
				self.allData = dataRows;
				self.nextRowWhenAutopaging = j;
				self.prevRowWhenAutopaging = 0;

				var prevConditions = self.conditions //save black lists
				self.conditions = [];

				for (var i = 0; i < self.headerRow.length; i++) { //Modificar init conditions para mantener los que no se muestran
					self.pseudoInitCondition(i, prevConditions);
				}

				self.TotalPagesPaging = parseInt(self.RowsWhenMoveToFilter.length / self.autoPagingRowsPerPage);
				if ((self.RowsWhenMoveToFilter.length % self.autoPagingRowsPerPage) != 0) {
					self.TotalPagesPaging++;
				}


				setTimeout(function () { createPaginationInfo(self, self.RowsWhenMoveToFilter); }, 500)

			}

		}

		this.isNotFilterByTopFilter = function (row) {
			for (var i = 0; i < self.filterIndexes.length; i++) { /* for all filters */
				var fi = self.filterIndexes[i]; /* this column is important */
				var s = self.filterDiv.selects[i]; /* select node */
				if ((s != undefined) && (s.selectedIndex && (OAT.$v(s) != "[all]") && (OAT.$v(s) != row[fi]))) { return false; }
			}
			return true;
		}

		this.preGoWhenFilterByTopFilter = function (init) {
			if (!self.autoPaging) {
				self.FilterByTopFilter = true;
				self.allData = self.GeneralDataRows;
				self.conditions = [];

				for (var i = 0; i < self.headerRow.length; i++) {
					self.initCondition(i);
				}
				for (var i = 0; i < self.headerRow.length; i++) {
					self.restoreSubtotalsAndSortLayout(i)
				}
			} else {
				//remove collapsed rows	
				collapseRowForCollapseValues(self);
				//end remove collapsed rows

				self.FilterByTopFilter = true;
				self.allData = self.GeneralDataRows;

				var tempDataRows2 = self.RowsWhenMoveToFilter//self.allData;
				dataRows = [];
				var i = 0;
				var j = 0;
				column = -1;
				value = null; var ConsiderNoNewHelper = [];
				while ((i < this.autoPagingRowsPerPage) && (j < tempDataRows2.length)) {
					if ((column == -1) || ((j < tempDataRows2.length) && (tempDataRows2[j][column] != value))) {

						if (self.isNotFilterByTopFilter(tempDataRows2[j]) && !self.notInBlackList(tempDataRows2[j], self.conditions)) { //ver que no sea esta fila filtrada por ninguna condicion
							var isNoNew = self.canBeConsiderNoNew(tempDataRows2[j], dataRows, ConsiderNoNewHelper);
							dataRows.push([tempDataRows2[j]]);
							if (!isNoNew) {
								i++;
							} 
						}
					}
					j++; //in case there no enought data rows
				}
				self.allData = dataRows;
				self.nextRowWhenAutopaging = j;
				self.prevRowWhenAutopaging = 0;
				
				var prevConditions = self.conditions //save black lists
				self.conditions = [];

				for (var i = 0; i < self.headerRow.length; i++) { //Modificar init conditions para mantener los que no se muestran
					self.pseudoInitCondition(i, prevConditions);
				}

				setTimeout(function () { createPaginationInfo(self, self.RowsWhenMoveToFilter); }, 500)

			}
		}

		//call only on initial load (when autopaging only)
		//looks if are collapse values and collapse row or return false
		this.preGoWhenCollapsedValue = function () {
			//remove collapsed rows	
			var areValuesCollapsed = collapseRowForCollapseValues(self);
			//end remove collapsed rows
			if (!areValuesCollapsed) return false

			var tempDataRows2 = self.RowsWhenMoveToFilter;
			var dataRows = [];
			var i = 0;
			var j = 0;

			value = null; var ConsiderNoNewHelper = [];
			while ((i < this.autoPagingRowsPerPage) && (j < tempDataRows2.length)) {
				if (!self.notInBlackList(tempDataRows2[j], self.conditions)) { //ver que no sea esta fila filtrada por ninguna condicion
					var isNoNew = self.canBeConsiderNoNew(tempDataRows2[j], dataRows, ConsiderNoNewHelper);
					dataRows.push([tempDataRows2[j]]);
					if (!isNoNew) {
						i++;
					} else {
						//alert('not new')
					}
				}
				j++; //in case there no enought data rows
			}
			self.allData = dataRows;
			self.nextRowWhenAutopaging = j;
			self.prevRowWhenAutopaging = 0;
			var prevConditions = self.conditions //save black lists
			self.conditions = [];

			for (var i = 0; i < self.headerRow.length; i++) { //Modificar init conditions para mantener los que no se muestran
				self.pseudoInitCondition(i, prevConditions);
			}

			self.TotalPagesPaging = parseInt(self.RowsWhenMoveToFilter.length / self.autoPagingRowsPerPage);
			if ((self.RowsWhenMoveToFilter.length % self.autoPagingRowsPerPage) != 0) {
				self.TotalPagesPaging++;
			}

			setTimeout(function () { createPaginationInfo(self, self.RowsWhenMoveToFilter); }, 500)

			return true;
		}

		this.go = function (load, autorefreshflag) {

			if (dataRows[0] != undefined) { //if data available

				if (!load) {
					self.gd.clearSources();
					self.gd.clearTargets();
					self.drawFilters();
					try {
						self.applyFilters();
						self.createAggStructure();
						self.fillAggStructure();
						self.checkAggStructure();
						self.count(); /* fill tabularData with values */
					} catch (ERROR) {
						//alert(ERROR)
					}
					if (((autorefreshflag === undefined) || (autorefreshflag === null) || (!autorefreshflag))) {
						//something change, call QQ
						var meta = self.createXMLMetadata();
						var listennings = self.QueryViewerCollection[UcId];
						if ((listennings != "") && (listennings != null) && (listennings != undefined)) {
							qv.util.autorefresh.UpdateLayoutSameGroup(listennings, meta);
						}
					}
				}

				/* get filtered selected values*/
				var filterDivSelects = new Array();
				for (var fiv = 0; fiv < self.filterDiv.selects.length; fiv++) {
					filterDivSelects[fiv] = self.filterDiv.selects[fiv].value;
				}

				if (!self.firstTime) {

					var state = {
						query: self.query,
						conditions: self.conditions,
						colConditions: self.colConditions,
						rowConditions: self.rowConditions,
						filterIndexes: self.filterIndexes,
						filterDivSelects: filterDivSelects,
						rowsPerPage: self.rowsPerPage,
						version: self.rememberLayoutStateVersion
					};


					if ((!self.deleteState)) {
						self.saveState(state);
					} else {
						self.cleanState();
					}

					self.readState = true;
				} else {
					self.firstTime = false;
				}

				if (!self.ShowMeasuresAsRows) {
					self.drawTable();
					qv.util.hideActivityIndicator(self.QueryViewerCollection[self.IdForQueryViewerCollection])
				} else {
					self.drawTableWhenShowMeasuresAsRows()
				}


				//add paging functionality
				var actual_rowsPerPage = 0;
				if (jQuery("#" + this.controlName + "_" + self.query + "tablePagination_rowsPerPage").length > 0) {
					actual_rowsPerPage = parseInt(jQuery("#" + this.controlName + "_" + self.query + "tablePagination_rowsPerPage")[0].value);
					if (!isNaN(actual_rowsPerPage)) {
						pageSize = actual_rowsPerPage;
					}
				}



				var options = {
					currPage: 1,
					ignoreRows: jQuery('tbody tr[title_row=true]', jQuery("#" + this.controlName + "_" + self.query)),
					optionsForRows: [10, 15, 20],
					rowsPerPage: self.rowsPerPage != 'undefined' ? self.rowsPerPage : 50,
					topNav: false,
					controlName: this.controlName + "_" + self.query
				}
				if ((!self.autoPaging) && (pageSize)) {
					OAT.tablePagination(jQuery("#" + this.controlName + "_" + self.query), options);
					jQuery("#" + this.controlName + "_" + self.query).css("margin-bottom", "0px");
				}


				if ((self.autoPaging) && (self.allData.length < self.GeneralDataRows.length) &&
					((self.filteredData.length >= self.autoPagingRowsPerPage) || (self.actualPaginationPage > 1) || ((self.paginationInfo) && (self.paginationInfo.pages.length > 1)))
				) {
					//if pivot has less than 10 rows => no need to paging
					var options = {
						currPage: self.actualPaginationPage,
						ignoreRows: jQuery('tbody tr[title_row=true]', jQuery("#" + this.controlName + "_" + self.query)),
						optionsForRows: [10, 15, 20],
						rowsPerPage: self.autoPagingRowsPerPage,
						topNav: false,
						controlName: this.controlName + "_" + self.query,
						cantPages: self.TotalPagesPaging
					}

					OAT.partialTablePagination(jQuery("#" + self.controlName + "_" + self.query), options);

					jQuery("#" + this.controlName + "_" + self.query).css("margin-bottom", "0px");
				}

				if (!autoResize) {
					var clientWdt = jQuery("#" + this.containerName)[0].clientWidth
					jQuery("#" + this.controlName + "_" + self.query).css({ width: (clientWdt) + "px" })
				}
				var wd = jQuery("#" + this.controlName + "_" + self.query)[0].offsetWidth;
				try {
					if (jQuery("#MAINFORM")[0].className.indexOf("form-horizontal") > -1) {
						wd = wd + 4;
					}
				} catch (Error) {
				}
				var wd2 = jQuery("#" + this.controlName + "_" + self.query)[0].offsetWidth - 1;
				jQuery("#" + UcId + "_" + self.query + "_pivot_page").css({ width: wd + "px" });
				jQuery("#" + this.controlName + "_" + self.query + "_tablePagination").css({ width: wd2 + "px" });
				if ((jQuery("#" + this.controlName + "_" + self.query + "_tablePagination_paginater").length > 0) && (jQuery("#" + this.controlName + "_" + self.query + "_tablePagination")[0].getBoundingClientRect().bottom < jQuery("#" + this.controlName + "_" + self.query + "_tablePagination_paginater")[0].getBoundingClientRect().bottom)) {
					jQuery("#" + this.controlName + "_" + self.query + "_tablePagination")
				}
				setInterval(function () {
					//verificar que sea pivot
					if ((jQuery("#" + self.controlName + "_" + self.query).length > 0) && (jQuery("#" + self.controlName + "_" + self.query)[0].getAttribute("class") === "pivot_table")) {
						if ((jQuery("#" + self.controlName + "_" + self.query + "_tablePagination_paginater").length > 0) && (jQuery("#" + self.controlName + "_" + self.query + "_tablePagination")[0].getBoundingClientRect().bottom < jQuery("#" + self.controlName + "_" + self.query + "_tablePagination_paginater")[0].getBoundingClientRect().bottom)) {
							jQuery("#" + this.controlName + "_" + self.query + "_tablePagination")
						}
					}
				},
					150)

				//end paging functionality
				if (self.colConditions.length === 0) {
					jQuery(".h2title > div").css({ width: "100%" });
				}

			}
		}

		this.gridCache = []

		this.cleanGridCache = function () {
			self.gridCache = [];
		}

		this.addPageToCache = function (pageNum, data) {
			self.gridCache.push({ page: pageNum, data: data });
		}

		this.getPageDataFromCache = function (pageNum) {
			for (var it = 0; it < self.gridCache.length; it++) {
				if (self.gridCache[it].page == pageNum) {
					return self.gridCache[it].data;
				}
			}
			return false;
		}

		this.goWhenServerPagination = function (load, autorefreshflag) {

			if (!self.getPageDataFromCache(self.pageData.ServerPageNumber)) { //add page data to cache
				self.addPageToCache(self.pageData.ServerPageNumber, self.pageData.rows)
			}
			//call navigational events
			if (self.pageData.ServerPageNumber != self.pageData.PreviousPageNumber) {
				self.QueryViewerCollection[self.IdForQueryViewerCollection].CurrentPage = self.pageData.ServerPageNumber;
				if (self.pageData.ServerPageNumber == 1) {
					if (typeof (self.QueryViewerCollection[self.IdForQueryViewerCollection].OnFirstPage) == 'function') self.QueryViewerCollection[self.IdForQueryViewerCollection].OnFirstPage()
				} else if (self.pageData.ServerPageNumber == self.pageData.ServerPageCount) {
					if (typeof (self.QueryViewerCollection[self.IdForQueryViewerCollection].OnLastPage) == 'function') self.QueryViewerCollection[self.IdForQueryViewerCollection].OnLastPage()
				} else if (self.pageData.ServerPageNumber < self.pageData.PreviousPageNumber) {
					if (typeof (self.QueryViewerCollection[self.IdForQueryViewerCollection].OnPreviousPage) == 'function') self.QueryViewerCollection[self.IdForQueryViewerCollection].OnPreviousPage()
				} else {
					if (typeof (self.QueryViewerCollection[self.IdForQueryViewerCollection].OnNextPage) == 'function') self.QueryViewerCollection[self.IdForQueryViewerCollection].OnNextPage()
				}
				self.pageData.PreviousPageNumber = self.pageData.ServerPageNumber
			}


			if (!load) {
				self.gd.clearSources();
				self.gd.clearTargets();
				self.drawFilters();
				if (self.QueryViewerCollection[self.IdForQueryViewerCollection].AutoRefreshGroup != "") {
					if (((autorefreshflag === undefined) || (autorefreshflag === null) || (!autorefreshflag))) {
						if ((!self.firstTime) || ((self.getState()) && (self.getState().version == self.rememberLayoutStateVersion))) {
							//something change, call QQ
							var meta;
							if (!self.serverPagination) {
								meta = self.createXMLMetadata();
							} else {
								meta = self.getMetadataXML();
								meta = meta.replace(/\&amp;/g, "&");
							}
							var listennings = self.QueryViewerCollection[self.IdForQueryViewerCollection];
							if ((listennings != "") && (listennings != null) && (listennings != undefined)) {
								qv.util.autorefresh.UpdateLayoutSameGroup(listennings, meta);
							}
						}
					}
				}
			}

			/* get filtered selected values*/
			var filterDivSelects = new Array();
			for (var fiv = 0; fiv < self.filterDiv.selects.length; fiv++) {
				filterDivSelects[fiv] = self.filterDiv.selects[fiv].value;
			}

			if (!self.firstTime) {

				var state = {
					query: self.query,
					conditions: self.conditions,
					colConditions: self.colConditions,
					rowConditions: self.rowConditions,
					filterIndexes: self.filterIndexes,
					filterDivSelects: filterDivSelects,
					rowsPerPage: self.rowsPerPage,
					AxisInfo: self.pageData.AxisInfo,
					FilterInfo: self.pageData.FilterInfo,
					version: self.rememberLayoutStateVersion,
					DataInfo: self.pageData.DataInfo
				};


				if ((!self.deleteState)) {
					self.saveState(state);
				} else {
					self.cleanState();
				}

				self.readState = true;
			} else {
				self.firstTime = false;
			}

			self.drawTableWhenServerPagination();

			//add paging functionality
			var actual_rowsPerPage = 0;

			if ((self.pageData.ServerPageCount > 0) && ((self.pageData.ServerPageCount > 1) || (self.pageData.rows.length > 10))
				&& (self.rowsPerPage > 0)) {
				//if pivot has less than 10 rows => no need to paging
				var options = {
					currPage: self.pageData.ServerPageNumber,
					ignoreRows: jQuery('tbody tr[title_row=true]', jQuery("#" + this.controlName + "_" + self.query)),
					optionsForRows: [10, 15, 20],
					rowsPerPage: self.rowsPerPage,
					topNav: false,
					controlName: this.controlName + "_" + self.query,
					cantPages: self.pageData.ServerPageCount,
					controlUcId: UcId,
					control: self
				}

				OAT.partialTablePagination(jQuery("#" + self.controlName + "_" + self.query), options);

				jQuery("#" + this.controlName + "_" + self.query).css("margin-bottom", "0px");

			}

			if ((jQuery("#" + this.controlName + "_" + self.query).length > 0) && (!autoResize)) {
				var clientWdt = jQuery("#" + this.containerName)[0].clientWidth
				jQuery("#" + this.controlName + "_" + self.query).css({ width: (clientWdt - 4) + "px" })
			}

			try {
				var wd = jQuery("#" + this.controlName + "_" + self.query)[0].offsetWidth - 4;
				if (jQuery("#MAINFORM")[0].className.indexOf("form-horizontal") > -1) {
					wd = wd + 4;
				}
			} catch (Error) {
			}



			try {
				var wd2 = jQuery("#" + this.controlName + "_" + self.query)[0].offsetWidth - 1;
				jQuery("#" + UcId + "_" + self.query + "_pivot_page").css({ width: wd + "px" }); //jQuery("#" + this.controlName + "_" + self.query + "_pivot_page").css({width: wd+"px" });
				jQuery("#" + this.controlName + "_" + self.query + "_tablePagination").css({ width: wd2 + "px" });

				if ((jQuery("#" + this.controlName + "_" + self.query + "_tablePagination_paginater").length > 0) && (jQuery("#" + this.controlName + "_" + self.query + "_tablePagination")[0].getBoundingClientRect().bottom < jQuery("#" + this.controlName + "_" + self.query + "_tablePagination_paginater")[0].getBoundingClientRect().bottom)) {

					jQuery("#" + this.controlName + "_" + self.query + "_tablePagination")

				}
			} catch (Error) {
			}
			
			//draw selected node
			self.RedrawSelectedNode();
			
			setInterval(function () {
				//verificar que sea pivot
				if ((jQuery("#" + self.controlName + "_" + self.query).length > 0) && (jQuery("#" + self.controlName + "_" + self.query)[0].getAttribute("class") === "pivot_table")) {
					if ((jQuery("#" + self.controlName + "_" + self.query + "_tablePagination_paginater").length > 0) && (jQuery("#" + self.controlName + "_" + self.query + "_tablePagination")[0].getBoundingClientRect().bottom < jQuery("#" + self.controlName + "_" + self.query + "_tablePagination_paginater")[0].getBoundingClientRect().bottom)) {
						jQuery("#" + this.controlName + "_" + self.query + "_tablePagination")
					}
				}
			},	150)

			


		}

		this.getDataForPivot = function (UcId, pageNumber, rowsPerPage, recalculateCantPages, AxisChangeDataField, DataFieldFilter,
			ExportTo, restoreDefaultView, layoutForCollapseExpand, notAutorefresh) {
			if ((recalculateCantPages)) {
				self.cleanGridCache();
			}

			if ((recalculateCantPages) && (rowsPerPage > -1)) {
				self.rowsPerPage = rowsPerPage;
			}
			self.pageData.PreviousPageNumber = self.pageData.ServerPageNumber
			if ((!recalculateCantPages) && (self.getPageDataFromCache(pageNumber))) {
				self.pageData.ServerPageNumber = pageNumber
				self.pageData.rows = self.getPageDataFromCache(self.pageData.ServerPageNumber)
				self.preGoWhenServerPagination(true);
			} else {
				//re-create axis info
				if (AxisChangeDataField != "") {
					self.pageData.AxisInfo = self.createAxisInfo(AxisChangeDataField);
				}
				if (DataFieldFilter != "") {
					self.createFilterInfo(DataFieldFilter);
				}
				self.pageData.CollapseInfo = self.CreateExpandCollapseInfo("");

				self.ExportTo = ""
				if (rowsPerPage < 0) { //for export show all pivot
					rowsPerPage = 0;
					self.ExportTo = ExportTo
				}

				var layoutChange = true;
				if ((pageNumber > 1) || (!recalculateCantPages)) {
					layoutChange = false;
				}
				if ((layoutForCollapseExpand != undefined) && (layoutForCollapseExpand != "")) {
					layoutChange = true;
				}

				self.pageData.AxisInfo = self.createAxisInfo(AxisChangeDataField);
				self.pageData.DataInfo = self.createDataInfo();
				self.QueryViewerCollection[self.IdForQueryViewerCollection].getPageDataForPivotTable((function (resXML) {
					self.pageData = OATGetNewDataFromXMLForPivot(resXML, self.pageData, self.ShowMeasuresAsRows, self.ExportTo);
					self.preGoWhenServerPagination(notAutorefresh);
					if (self.ExportTo != "") {
						var FileName = self.query
						if (FileName == "") {
							FileName = "Query"
							try {
								FileName = self.controlName.split("_")[0]
							} catch (error) { }
						}
						if (self.ExportTo == "HTML") {
							self.ExportToHTMLWhenServerPagination()
						}
						if (self.ExportTo == "PDF") {
							OAT.GeneratePDFOutput(self, FileName)
						}
						if (self.ExportTo == "XLS") {
							self.ExportToExcel(FileName);
						}
						if (self.ExportTo == "XML") {
							self.ExportToXMLWhenServerPagination();
						}
						if (self.ExportTo == "XLSX") {
							self.ExportToXLSXWhenServerPagination();
						}
						self.cleanGridCache();
					}
					qv.util.hideActivityIndicator(self.QueryViewerCollection[self.IdForQueryViewerCollection]);
				}).closure(this), [pageNumber, rowsPerPage, recalculateCantPages, self.pageData.AxisInfo, self.pageData.DataInfo,
						self.pageData.FilterInfo, self.pageData.CollapseInfo, layoutChange]);

			}

		}

		this.CreateExpandCollapseInfo = function (dataField) {
			var CollapseInfo = [];
			var obj = {};
			for (var i = 0; i < self.columns.length; i++) {
				var pos = -1;
				for (var j = 0; j < self.conditions.length; j++) {
					if (self.conditions[j].dataField == self.columns[i].getAttribute("dataField")) {
						pos = j;
					}
				}
				if (self.conditions[pos].collapsedValues.length) {
					var notNullVal = {
						Expanded: [],
						Collapsed: self.conditions[pos].collapsedValues,
						DefaultAction: "Expand"
					}
					var obj = {
						DataField: self.conditions[pos].dataField,
						NullExpanded: true,//TODO: caso Null value
						NotNullValues: notNullVal
					}
					CollapseInfo.push(obj);
				}
			}
			return CollapseInfo
		}

		this.createAxisInfo = function (dataField) {
			var AxisInfo = []; var hiddenPos = 1;
			for (var i = 0; i < self.initMetadata.Dimensions.length; i++) {
				var pos = -1;
				//if hidden?
				var hidden = !self.initMetadata.Dimensions[i].Visible;
				/*for (var h=0; h < self.initMetadata.Dimensions.length; h++){
					if (self.columns[i].getAttribute("dataField") == self.initMetadata.Dimensions[h].dataField){
						hidden = !self.initMetadata.Dimensions[h].Visible
					}
				}*/

				var type = "Rows"; var position = 1;
				var Order = "Ascending";
				var Subtotal = true;
				if (!hidden) {


					for (var j = 0; j < self.conditions.length; j++) {
						if (self.conditions[j].dataField == self.initMetadata.Dimensions[i].dataField) {
							pos = j;
						}
					}
					Order = (self.conditions[pos].sort == 1) ? "Ascending" : "Descending"
					Subtotal = ((self.conditions[pos].subtotals == 1) || (self.conditions[pos].subtotals)) ? true : false

					if (self.rowConditions.indexOf(pos) > -1) {
						position = self.rowConditions.indexOf(pos) + 1
					}
					if (self.colConditions.indexOf(pos) > -1) {
						type = "Columns";
						position = self.colConditions.indexOf(pos) + 1
					}
					if (self.filterIndexes.indexOf(pos) > -1) {
						type = "Pages";
						position = self.filterIndexes.indexOf(pos) + 1
					}
				} else {
					type = "Hidden"
					position = hiddenPos
					hiddenPos = hiddenPos + 1
				}
				var obj = {
					DataField: self.initMetadata.Dimensions[i].dataField,
					Order: Order,
					Axis: {
						Type: type,
						Position: position
					},
					Subtotals: Subtotal
				}
				AxisInfo.push(obj)
			}
			return AxisInfo;
		}

		this.createDataInfo = function () {
			var DataInfo = []; var hiddenPos = 1;
			var visiblePos = 1
			for (var h = 0; h < self.initMetadata.Measures.length; h++) {

				//if hidden?
				var hidden = !self.initMetadata.Measures[h].Visible;

				var type = self.initMetadata.Measures[h].Visible ? "Data" : "Hidden";
				var position = self.initMetadata.Measures[h].Visible ? visiblePos : hiddenPos;


				var obj = {
					DataField: self.initMetadata.Measures[h].dataField,
					Axis: {
						Type: type,
						Position: position
					}
				}
				DataInfo.push(obj)
				if (self.initMetadata.Measures[h].Visible) {
					visiblePos = visiblePos + 1
				} else {
					hiddenPos = hiddenPos + 1
				}

			}
			return DataInfo;
		}

		this.createFilterInfo = function (NewFilter, isFromMetadata) {
			DataFieldFilter = self.conditions[NewFilter.dim].dataField
			if ((NewFilter.op == "all") || ((NewFilter.op == "pagefilter") && (NewFilter.values == "[all]"))) {
				//remove filter from filterInof
				var pos = -1;
				for (var p = 0; p < self.pageData.FilterInfo.length; p++) {
					if (DataFieldFilter == self.pageData.FilterInfo[p].DataField) { pos = p; break; }
				}
				if (pos > -1) self.pageData.FilterInfo.splice(pos, 1)
				self.conditions[NewFilter.dim].state = "all"
				self.conditions[NewFilter.dim].visibles = []
				self.conditions[NewFilter.dim].blackList = []
				self.conditions[NewFilter.dim].defaultAction = "Include"
				return;
			}

			if (self.conditions[NewFilter.dim].state == "none") {
				self.conditions[NewFilter.dim].visibles = []
				for (var u = 0; u < self.conditions[NewFilter.dim].distinctValues.length; u++) {
					if (self.conditions[NewFilter.dim].blackList.indexOf(self.conditions[NewFilter.dim].distinctValues[u]) == -1) {
						self.conditions[NewFilter.dim].blackList.push(self.conditions[NewFilter.dim].distinctValues[u])
					}
				}
			} else if (self.conditions[NewFilter.dim].state == "all") {
				self.conditions[NewFilter.dim].blackList = []
				for (var u = 0; u < self.conditions[NewFilter.dim].distinctValues.length; u++) {
					if (self.conditions[NewFilter.dim].visibles.indexOf(self.conditions[NewFilter.dim].distinctValues[u]) == -1) {
						self.conditions[NewFilter.dim].visibles.push(self.conditions[NewFilter.dim].distinctValues[u])
					}
				}
			}

			var notNullValue = [];
			if (NewFilter.op == "none") {
				notNullValue = [];
				self.conditions[NewFilter.dim].state = "none"
				self.conditions[NewFilter.dim].visibles = []
				self.conditions[NewFilter.dim].blackList = []
				self.conditions[NewFilter.dim].defaultAction = "Exclude"
			} else {
				if (NewFilter.op == "push") {
					self.conditions[NewFilter.dim].state = ""
					var pos = self.conditions[NewFilter.dim].visibles.indexOf(NewFilter.values)
					if (pos > -1) self.conditions[NewFilter.dim].visibles.splice(pos, 1);
					if (self.conditions[NewFilter.dim].blackList.indexOf(NewFilter.values) == -1)
						self.conditions[NewFilter.dim].blackList.push(NewFilter.values)
				} else if (NewFilter.op == "pop") {
					self.conditions[NewFilter.dim].state = ""
					if (self.conditions[NewFilter.dim].visibles.indexOf(NewFilter.values) == -1)
						self.conditions[NewFilter.dim].visibles.push(NewFilter.values)
					var pos = self.conditions[NewFilter.dim].blackList.indexOf(NewFilter.values)
					if (pos > -1) self.conditions[NewFilter.dim].blackList.splice(pos, 1);
				} else if (NewFilter.op == "pagefilter") {
					self.conditions[NewFilter.dim].state = ""
					self.conditions[NewFilter.dim].defaultAction = "Exclude"
					self.conditions[NewFilter.dim].visibles = [];
					self.conditions[NewFilter.dim].visibles.push(NewFilter.values);
					for (var p = 0; p < self.conditions[NewFilter.dim].distinctValues.length; p++) {
						var val = self.conditions[NewFilter.dim].distinctValues[p]
						if ((self.conditions[NewFilter.dim].blackList.indexOf(val) == -1) && (val != NewFilter.values)) {
							self.conditions[NewFilter.dim].blackList.push(val)
						}
					}
				} else if (NewFilter.op == "reverse") {
					if (self.conditions[NewFilter.dim].defaultAction == "Include") {
						self.conditions[NewFilter.dim].defaultAction = "Exclude"
					} else {
						self.conditions[NewFilter.dim].defaultAction = "Include"
					}
					if (self.conditions[NewFilter.dim].state == "none") {//si el estado anterior es none pasa a all
						var pos = -1;
						for (var p = 0; p < self.pageData.FilterInfo.length; p++) {
							if (DataFieldFilter == self.pageData.FilterInfo[p].DataField) { pos = p; break; }
						}
						if (pos > -1) self.pageData.FilterInfo.splice(pos, 1)
						self.conditions[NewFilter.dim].state = "all"
						self.conditions[NewFilter.dim].visibles = []
						self.conditions[NewFilter.dim].blackList = []
						return;
					} else if (self.conditions[NewFilter.dim].state == "all") {//si el estado anterior es all pasa a none
						notNullValue = [];
						self.conditions[NewFilter.dim].state = "none"
						self.conditions[NewFilter.dim].visibles = []
						self.conditions[NewFilter.dim].blackList = []
					} else {

						var tempArrayVisibles = []; for (var tit = 0; tit < self.conditions[NewFilter.dim].visibles.length; tit++) { tempArrayVisibles.push(self.conditions[NewFilter.dim].visibles[tit]) }
						var tempArrayHiddens = []; for (var tit = 0; tit < self.conditions[NewFilter.dim].blackList.length; tit++) { tempArrayHiddens.push(self.conditions[NewFilter.dim].blackList[tit]) }

						self.conditions[NewFilter.dim].visibles = []
						self.conditions[NewFilter.dim].blackList = []

						for (var u = 0; u < self.conditions[NewFilter.dim].distinctValues.length; u++) {
							var val = self.conditions[NewFilter.dim].distinctValues[u];
							if (tempArrayVisibles.indexOf(val) == -1) {
								self.conditions[NewFilter.dim].visibles.push(val)
							} else {
								self.conditions[NewFilter.dim].blackList.push(val)
							}
						}
						for (var u = 0; u < tempArrayHiddens.length; u++) {
							if (self.conditions[NewFilter.dim].visibles.indexOf(tempArrayHiddens[u]) == -1) {
								self.conditions[NewFilter.dim].visibles.push(tempArrayHiddens[u])
							}
						}
						for (var u = 0; u < tempArrayVisibles.length; u++) {
							if (self.conditions[NewFilter.dim].blackList.indexOf(tempArrayVisibles[u]) == -1) {
								self.conditions[NewFilter.dim].blackList.push(tempArrayVisibles[u])
							}
						}
					}
				}
			}

			var filterExist = false; var nullIncluded = true;
			var included = [];
			for (var t = 0; t < self.conditions[NewFilter.dim].visibles.length; t++) {
				if (self.conditions[NewFilter.dim].visibles[t] != "#NuN#") {
					included.push(self.conditions[NewFilter.dim].visibles[t])
				}
			}
			var excluded = [];
			if (self.conditions[NewFilter.dim].state != "none") {
				for (var t = 0; t < self.conditions[NewFilter.dim].distinctValues.length; t++) {
					var val = self.conditions[NewFilter.dim].distinctValues[t]
					if ((val != "#NuN#") && (included.indexOf(val) == -1)) {
						excluded.push(val)
					}
				}
				for (var t = 0; t < self.conditions[NewFilter.dim].blackList.length; t++) {
					if ((self.conditions[NewFilter.dim].blackList[t] != "#NuN#")
						&& (excluded.indexOf(self.conditions[NewFilter.dim].blackList[t]) == -1)) {
						excluded.push(self.conditions[NewFilter.dim].blackList[t])
					}
				}
				if ((included.length == 0) && ((self.conditions[NewFilter.dim].defaultAction == "Exclude"))) {
					excluded = [];
				}
			}

			if (NewFilter.op == "none") {
				nullIncluded = false;
				included = []; excluded = [];
			} else {
				if ((self.conditions[NewFilter.dim].distinctValues.indexOf("#NuN#") > -1) ||
					(excluded.indexOf(self.conditions[NewFilter.dim].blackList[t]) != -1)) {
					if (self.conditions[NewFilter.dim].visibles.indexOf("#NuN#") == -1) {
						nullIncluded = false;
					}
				} else {
					if (self.conditions[NewFilter.dim].defaultAction == "Exclude") {
						nullIncluded = false;
					}
				}
			}

			if ((self.conditions[NewFilter.dim].hasNull) && (!(NewFilter.op == "none"))) {
				//asociated psuedo-Null
				var reallyPseudoNull = self.defaultPicture.getAttribute("textForNullValues")
				var finded = false
				var data_length = 0;
				for (var u = 0; u < self.conditions[NewFilter.dim].distinctValues.length; u++) {
					data_length = self.conditions[NewFilter.dim].distinctValues[u].length;
				}
				for (var u = 0; u < self.conditions[NewFilter.dim].distinctValues.length; u++) {
					if (self.conditions[NewFilter.dim].distinctValues[u].trimpivot() == self.defaultPicture.getAttribute("textForNullValues")) {
						reallyPseudoNull = self.conditions[NewFilter.dim].distinctValues[u];
						finded = true;
						break;
					}
				}
				if (!finded) {
					for (var t = 0; t < data_length - self.defaultPicture.getAttribute("textForNullValues").length; t++) {
						reallyPseudoNull = reallyPseudoNull + " ";
					}
				}

				if (!nullIncluded) {
					if (excluded.indexOf(reallyPseudoNull) == -1) {
						excluded.push(reallyPseudoNull)
						if (self.conditions[NewFilter.dim].blackList.indexOf(reallyPseudoNull) == -1) {
							self.conditions[NewFilter.dim].blackList.push(reallyPseudoNull)
						}
					}
					if (included.indexOf(reallyPseudoNull) != -1) {
						included.splice(included.indexOf(reallyPseudoNull), 1)
					}
					if (self.conditions[NewFilter.dim].visibles.indexOf(reallyPseudoNull) != -1) {
						self.conditions[NewFilter.dim].visibles.splice(self.conditions[NewFilter.dim].visibles.indexOf(reallyPseudoNull), 1)
					}
				} else {
					if (included.indexOf(reallyPseudoNull) == -1) {
						if (excluded.indexOf(reallyPseudoNull) != -1) {
							excluded.splice(excluded.indexOf(reallyPseudoNull), 1)
							included.push(reallyPseudoNull)
						} else {
							if (self.conditions[NewFilter.dim].defaultAction == "Exclude") {
								included.push(reallyPseudoNull)
							}
						}
						if (self.conditions[NewFilter.dim].blackList.indexOf(reallyPseudoNull) != -1) {
							self.conditions[NewFilter.dim].blackList.splice(self.conditions[NewFilter.dim].blackList.indexOf(reallyPseudoNull), 1)
							if (self.conditions[NewFilter.dim].visibles.indexOf(reallyPseudoNull) == -1) {
								self.conditions[NewFilter.dim].visibles.push(reallyPseudoNull)
							}
						}
					}
				}
			}

			var allValuesLoaded = (self.conditions[NewFilter.dim].previousPage == self.conditions[NewFilter.dim].totalPages)
			var noFilterNeeded = (((nullIncluded) || (!self.conditions[NewFilter.dim].hasNull))
				&& (excluded.length == 0) && (NewFilter.op != "none") && (NewFilter.op != "push")
				&& ((self.conditions[NewFilter.dim].defaultAction == "Include") || (allValuesLoaded))
				&& (!isFromMetadata)
				&& (!(NewFilter.op == "reverse"))
			);

			var pos = 0; var toDelete = false;
			for (var t = 0; t < self.pageData.FilterInfo.length; t++) {
				if (self.pageData.FilterInfo[t].DataField == DataFieldFilter) {
					filterExist = true; toDelete = true;
					self.pageData.FilterInfo[t].NullIncluded = nullIncluded
					self.pageData.FilterInfo[t].NotNullValues.Included = included
					self.pageData.FilterInfo[t].NotNullValues.Excluded = excluded
					self.pageData.FilterInfo[t].NotNullValues.DefaultAction = self.conditions[NewFilter.dim].defaultAction
					pos = t;
				}
			}
			if ((noFilterNeeded) && (toDelete)) {
				self.pageData.FilterInfo.splice(pos, 1)
			}
			if ((!filterExist) && (!noFilterNeeded)) {
				var notNullValues = { Included: included, Excluded: excluded, DefaultAction: self.conditions[NewFilter.dim].defaultAction }
				filter = { DataField: DataFieldFilter, NullIncluded: nullIncluded, NotNullValues: notNullValues }
				self.pageData.FilterInfo.push(filter);
			}

		}

		this.moveToNextPage = function () {
			if (this.pageData.ServerPageNumber < this.pageData.ServerPageCount) {
				this.getDataForPivot(this.UcId, this.pageData.ServerPageNumber + 1, this.rowsPerPage, false, "", "", "", "")
			}
		}

		this.moveToFirstPage = function () {
			if (this.pageData.ServerPageNumber > 1) {
				this.getDataForPivot(this.UcId, 1, this.rowsPerPage, false, "", "", "", "");
			}
		}

		this.moveToLastPage = function () {
			if (this.pageData.ServerPageNumber < this.pageData.ServerPageCount) {
				this.getDataForPivot(this.UcId, this.pageData.ServerPageCount, this.rowsPerPage, false, "", "", "", "");
			}
		}

		this.moveToPreviousPage = function () {
			if (this.pageData.ServerPageNumber > 1) {
				self.getDataForPivot(UcId, this.pageData.ServerPageNumber - 1, this.rowsPerPage, false, "", "", "", "");
			}
		}

		this.preGoWhenServerPagination = function (load) {
			self.goWhenServerPagination(load, false);
		}


		this.readScrollValue = function (columnNumber) {
			var dataField = self.conditions[columnNumber].dataField;

			if (!self.conditions[columnNumber].blocked) {
				self.conditions[columnNumber].blocked = true;
				if (!self.conditions[columnNumber].filtered) {
					var page = self.conditions[columnNumber].previousPage + 1;
					self.lastRequestValue = columnNumber;
					self.QueryViewerCollection[self.IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
						var res = JSON.parse(resJSON);
						self.appendNewValueData(self.lastRequestValue, res)
					}).closure(this), [dataField, page, 10, ""]);
				} else {
					var ValuePageInfo = self.conditions[columnNumber].searchInfo
					var page = ValuePageInfo.previousPage + 1;
					self.lastRequestValue = dataField;
					var filterText = ValuePageInfo.filteredText
					self.QueryViewerCollection[self.IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
						var res = JSON.parse(resJSON);
						self.appendNewFilteredValueData(res, columnNumber, filterText)
					}).closure(this), [dataField, page, 10, ValuePageInfo.filteredText]);
				}
			}
		}

		this.getValuesForColumn = function (UcId, columnNumber, filterValue) {
			var dataField = self.conditions[columnNumber].dataField;
			if (filterValue != "") {
				var page = 1
				var filterValuePars = filterValue.replace(/\\/g, "\\\\")
				self.QueryViewerCollection[self.IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
					var res = JSON.parse(resJSON);
					self.changeValues(UcId, dataField, columnNumber, res, filterValuePars);
				}).closure(this), [dataField, page, 10, filterValuePars]);
			} else {
				self.resetScrollValue(UcId, dataField, columnNumber)
			}
		}

		this.appendNewValueData = function (columnNumber, data) {
			if (data.PageNumber > self.conditions[columnNumber].previousPage) {
				self.conditions[columnNumber].previousPage = data.PageNumber
				self.conditions[columnNumber].totalPages = data.PagesCount
				var newValues = [];

				if (data.Null) {
					if (self.conditions[columnNumber].indexOf("#NuN#") == -1) {
						self.conditions[columnNumber].distinctValues.push("#NuN#")
					}
				}

				//add to differentValues
				for (var i = 0; i < data.NotNullValues.length; i++) {
					var val = data.NotNullValues[i]
					if (self.conditions[columnNumber].distinctValues.indexOf(val) == -1) {
						self.conditions[columnNumber].distinctValues.push(val)
						newValues.push(val)
					}//lo mismo
					if (self.conditions[columnNumber].defaultAction == "Include") {
						if ((self.conditions[columnNumber].visibles.indexOf(val) == -1)
							&& (self.conditions[columnNumber].blackList.indexOf(val) == -1)) {
							self.conditions[columnNumber].visibles.push(val)
						}
					} else {
						if ((self.conditions[columnNumber].visibles.indexOf(val) == -1)
							&& (self.conditions[columnNumber].blackList.indexOf(val) == -1)) {
							self.conditions[columnNumber].blackList.push(val)
						}
					}
				}

				for (var nI = 0; nI < newValues.length; nI++) {
					var checked = true;
					if (self.conditions[columnNumber].state != "all") {
						if (self.conditions[columnNumber].blackList.indexOf(newValues[nI]) != -1) {
							checked = false;
						}
					}

					if (!((self.conditions[columnNumber].hasNull) && (newValues[nI].trimpivot() == self.defaultPicture.getAttribute("textForNullValues")))) {
						self.appendNewPairToPopUp(newValues[nI], columnNumber, checked)
					}
				}
			}
			if (self.conditions[columnNumber].previousPage < data.PagesCount)
				self.conditions[columnNumber].blocked = false;
		}

		this.changeValues = function (UcId, dataField, columnNumber, data, filterText) { //when filter by search filter, delete pairs and show new ones
			var searchInput = jQuery("#" + UcId + columnNumber)[0];

			var sInput = searchInput.value;
			if (searchInput.value) {
				sInput = sInput.replace(/\\/g, "\\\\")
			}
			if (((searchInput.value) || (searchInput.value == "")) && (sInput != filterText)) {
				return;
			}

			self.conditions[columnNumber].filtered = true;
			self.conditions[columnNumber].blocked = true;
			self.removeAllPairsFromPopUp(columnNumber, data.PagesCount > 1);

			//set filtered pagination info
			self.conditions[columnNumber].searchInfo.previousPage = 1
			self.conditions[columnNumber].searchInfo.totalPages = data.PagesCount
			self.conditions[columnNumber].searchInfo.filteredText = filterText;

			for (var i = 0; i < data.NotNullValues.length; i++) {
				var value = data.NotNullValues[i]
				var alreadyInValues = (self.conditions[columnNumber].distinctValues.indexOf(value) != -1)
				//append to different values
				if (self.conditions[columnNumber].distinctValues.indexOf(value) == -1) {
					self.conditions[columnNumber].distinctValues.push(value)
				}
				if ((self.conditions[columnNumber].state == "all") ||
					((self.conditions[columnNumber].defaultAction == "Include") && (!alreadyInValues))) {
					//if Include new values and is a new value
					if ((self.conditions[columnNumber].visibles.indexOf(value) == -1)
						&& (self.conditions[columnNumber].blackList.indexOf(value) == -1)) {
						self.conditions[columnNumber].visibles.push(value)
					}
				}
				//


				var checked = true;
				if (self.conditions[columnNumber].state != "all") {
					if (self.conditions[columnNumber].visibles.findIndex(value) < 0) {
						checked = false;
					}
				}
				self.conditions[columnNumber].searchInfo.values.push(value);
				if (!((self.conditions[columnNumber].hasNull) && (value.trimpivot() == self.defaultPicture.getAttribute("textForNullValues")))) {
					self.appendNewPairToPopUp(value, columnNumber, checked);
				}
			}

			if (data.PagesCount > 0)
				self.conditions[columnNumber].blocked = false;
		}

		this.resetScrollValue = function (UcId, dataField, columnNumber) { //after filtered when input serach is clean, restor values without filter
			self.conditions[columnNumber].filtered = false;
			self.conditions[columnNumber].blocked = true;

			self.removeAllPairsFromPopUp(columnNumber, data.PagesCount > 1);

			for (var u = 0; u < self.conditions[columnNumber].distinctValues.length; u++) {
				var checked = true;
				var value = self.conditions[columnNumber].distinctValues[u];
				if (self.conditions[columnNumber].state != "all") {
					if (self.conditions[columnNumber].visibles.findIndex(value) < 0) {
						checked = false;
					}
				}

				if (!((self.conditions[columnNumber].hasNull) && (value.trimpivot() == self.defaultPicture.getAttribute("textForNullValues")))) {
					self.appendNewPairToPopUp(value, columnNumber, checked)
				}
			}

			if (self.conditions[columnNumber].previousPage < self.conditions[columnNumber].totalPages)
				self.conditions[columnNumber].blocked = false;
		}

		this.resetAllScrollValue = function (UcId) { //when closing the filter popup
			for (var id = 0; id < self.conditions.length; id++) {
				self.conditions[id].filtered = false;
				self.conditions[id].blocked = true;
				if (self.conditions[id].previousPage < self.conditions[id].totalPages)
					self.conditions[id].blocked = false;
			}
		}

		this.appendNewFilteredValueData = function (data, columnNumber, filterValue) { //add pairs when filtering by filter input
			var dataField = self.lastRequestValue

			var ValuePageInfo = self.conditions[columnNumber].searchInfo
			if (((filterValue) || (filterValue == "")) && (ValuePageInfo.filteredText != filterValue)) {
				return;
			}
			if (data.PageNumber > ValuePageInfo.previousPage) {
				self.conditions[columnNumber].searchInfo.previousPage = data.PageNumber
				self.conditions[columnNumber].searchInfo.totalPages = data.PagesCount

				if (data.Null) {
					if (self.conditions[columnNumber].distinctValues.indexOf("#NuN#") == -1) {
						self.conditions[columnNumber].distinctValues.push("#NuN#")
					}
				}

				for (var i = 0; i < data.NotNullValues.length; i++) {
					var value = data.NotNullValues[i]
					var alreadyInValues = (self.conditions[columnNumber].distinctValues.indexOf(value) != -1)
					//append to different values
					if (self.conditions[columnNumber].distinctValues.indexOf(value) == -1) {
						self.conditions[columnNumber].distinctValues.push(value)
					}
					if ((self.conditions[columnNumber].defaultAction == "Include") && (!alreadyInValues)) {
						if ((self.conditions[columnNumber].visibles.indexOf(value) == -1)
							&& (self.conditions[columnNumber].blackList.indexOf(value) == -1)) {
							self.conditions[columnNumber].visibles.push(value)
						}
					} else {
						if ((self.conditions[columnNumber].visibles.indexOf(value) == -1)
							&& (self.conditions[columnNumber].blackList.indexOf(value) == -1)) {
							self.conditions[columnNumber].blackList.push(value)
						}
					}

					var checked = true;
					if (self.conditions[columnNumber].state != "all") {
						if (self.conditions[columnNumber].visibles.findIndex(value) < 0) {
							checked = false;
						}
					}
					if (!((self.conditions[columnNumber].hasNull) && (value.trimpivot() == self.defaultPicture.getAttribute("textForNullValues")))) {
						self.appendNewPairToPopUp(value, columnNumber, checked)
					}
				}
				if (self.conditions[columnNumber].searchInfo.previousPage < self.conditions[columnNumber].searchInfo.totalPages)
					self.conditions[columnNumber].blocked = false;
			}
		},

			this.appendNewPairToPopUp = function (value, colNumber, checked) {
				var getPair = function (text, id, check) {
					var div = OAT.Dom.create("div");
					var class_check_div = self.valueIsShowed(value, colNumber) ? "check_item_img" : "uncheck_item_img";
					if (self.isSD) {//android
						class_check_div = self.valueIsShowed(value, colNumber) ? "check_item_img_small" : "uncheck_item_img_small";
					}
					
					OAT.addImageNode(div, self.valueIsShowed(value, colNumber) ? "check_box" : "check_box_outline_blank", "");

					div.setAttribute("class", class_check_div);
					var ch = OAT.Dom.create("input");
					ch.type = "checkbox";
					ch.id = id;
					var t = OAT.Dom.create("label");
					OAT.addTextNode(t, text)
					t.htmlFor = id;
					div.appendChild(t);
					return [div, ch];
				}

				var getRefBool = function (checked, value) {
					if (self.serverPagination) {
						var oper = "pop";
						if (!checked) {
							oper = "push";
						}

						self.getDataForPivot(self.UcId, 1, self.rowsPerPage, true, self.conditions[colNumber].dataField, { op: oper, values: value, dim: colNumber }, "", "")

						self.stateChanged = true;
						self.onFilteredChangedEventHandleWhenServerPagination(colNumber);
						self.EneablePivot();
						return;
					}
				}


				var pict_value = self.dimensionPictureValue(value, colNumber);
				if (value == "#NuN#") {
					pict_value = "\u00A0"
				}
				pict_value = pict_value.replace(/\&amp;/g, "&").replace(/\&nbsp;/g, " ")
				if (pict_value.length > 33) {
					var resto = (pict_value.substring(32, pict_value.length).trimpivot().length > 0) ? '...' : '';
					pict_value = pict_value.substring(0, 32) + resto
				}

				pict_value = pict_value.replace(/ /g, "\u00A0") + '\u00A0\u00A0\u00A0\u00A0\u00A0'
				var pair = getPair(pict_value, "pivot_distinct_" + i, checked);
				pair[0].setAttribute('value', value);
				var fixHeigthDiv = jQuery("#values_" + self.UcId + "_" + colNumber)[0]
				fixHeigthDiv.appendChild(pair[0]);

				if (fixHeigthDiv.children.length > 9) {
					fixHeigthDiv.setAttribute("class", "pivot_popup_fix");
				}

				OAT.Dom.attach(pair[0], "click", function () {
					self.DiseablePivot();

					var checkedClass = "check_item_img"
					var unCheckedClass = "uncheck_item_img"
					if (self.isSD) {//android
						checkedClass = "check_item_img_small"
						unCheckedClass = "uncheck_item_img_small"
					}

					var checked = !(this.getAttribute("class") === checkedClass);
					var newClass = (this.getAttribute("class") === checkedClass) ? unCheckedClass : checkedClass;
					
					jQuery(this).find("i")[0].textContent = checked ? "check_box" : "check_box_outline_blank";
					
					this.setAttribute("class", newClass);
					getRefBool(checked, this.getAttribute("value"));//this.textContent);            														
				});
			}

		this.removeAllPairsFromPopUp = function (colNumber, withScroll) {
			var checkedClass = "check_item_img"
			var unCheckedClass = "uncheck_item_img"
			if (self.isSD) {//android
				checkedClass = "check_item_img_small"
				unCheckedClass = "uncheck_item_img_small"
			}

			jQuery("#values_" + self.UcId + "_" + colNumber).find("." + checkedClass).remove()
			jQuery("#values_" + self.UcId + "_" + colNumber).find("." + unCheckedClass).remove()

			jQuery(".last_div_popup ." + checkedClass).remove()
			jQuery(".last_div_popup ." + unCheckedClass).remove()

			//set class of pairs container
			if (withScroll) {
				jQuery("#values_" + self.UcId + "_" + colNumber).removeClass("pivot_popup_auto");
				jQuery("#values_" + self.UcId + "_" + colNumber).addClass("pivot_popup_fix");
			} else {
				jQuery("#values_" + self.UcId + "_" + colNumber).removeClass("pivot_popup_fix");
				jQuery("#values_" + self.UcId + "_" + colNumber).addClass("pivot_popup_auto");
			}
		}

		var alreadyclicked = false;
		var alreadyclickedTimeout;
		this.onClickEventHandle = function (elemvalue, type, number, item) {
			if (alreadyclicked) {
				//double click
				alreadyclicked = false;
				clearTimeout(alreadyclickedTimeout);
				var datastr = self.ClickHandle(elemvalue);
				datastr = datastr.replace(/\&/g, '&amp;');
				qv.pivot.onItemClickEvent(this.QueryViewerCollection[IdForQueryViewerCollection], datastr, true);
			} else {
				alreadyclicked = true;
				var delay = 300
				if (self.QueryViewerCollection[IdForQueryViewerCollection].ItemDoubleClick == undefined) {
					delay = 0
				}
				alreadyclickedTimeout = setTimeout(function () {
					alreadyclicked = false;
					//single click
					var datastr = self.ClickHandle(elemvalue);
					datastr = datastr.replace(/\&/g, '&amp;');
					qv.pivot.onItemClickEvent(self.QueryViewerCollection[IdForQueryViewerCollection], datastr, false)
				}, delay);
			}
		}

		this.onClickExpandCollapse = function (elemvalue) {

			var value = jQuery(elemvalue).data('itemValue');
			//var type = jQuery(elemvalue).data('typeMorD');
			var number = jQuery(elemvalue).data('numberMorD');
			var item = jQuery(elemvalue).data('itemInfoEC');
			if (self.conditions[number].collapsedValues.indexOf(value) == -1) {
				//collapse value
				self.conditions[number].collapsedValues.push(value);

				if ((!self.serverPagination)) {
					var datastr = self.ExpandCollapseHandle(elemvalue, "ItemCollapse");
					datastr = datastr.replace(/\&/g, '&amp;');
					qv.pivot.onItemExpandCollapseEvent(self.QueryViewerCollection[IdForQueryViewerCollection], datastr, true)
				} else {
					self.ExpandCollapseHandleWhenServerPagination(elemvalue, "collapse")
				}
			} else {
				//expand value
				self.conditions[number].collapsedValues.splice(self.conditions[number].collapsedValues.indexOf(value), 1);

				if ((!self.serverPagination)) {
					var datastr = self.ExpandCollapseHandle(elemvalue, "ItemExpand");
					datastr = datastr.replace(/\&/g, '&amp;');
					qv.pivot.onItemExpandCollapseEvent(self.QueryViewerCollection[IdForQueryViewerCollection], datastr, false)
				} else {
					self.ExpandCollapseHandleWhenServerPagination(elemvalue, "expande")
				}
			}
			if (this.autoPaging) {
				collapseRowForCollapseValues(self);
				self.actualPaginationPage = 1
				self.changePaginationRows(1);
				self.go(false);
			} else if (!self.serverPagination) {
				self.go(false);
			} 
		}

		this.onDblClickEventHandle = function (elemvalue) {
			var datastr = self.ClickHandle(elemvalue);
			datastr = datastr.replace(/\&/g, '&amp;');
			qv.pivot.onItemClickEvent(this.QueryViewerCollection[IdForQueryViewerCollection], datastr, true);
		}

		this.cleanValueForNull = function (value) {
			if (value == "#NuN#") {
				var defaultNull = self.defaultPicture.getAttribute("textForNullValues");
				if (defaultNull != undefined) {
					return defaultNull;
				}
				return "";
			}
			return value;
		}

		this.isClickedRow = function (row, value, columnOfValue, otherrow, dimension) {
			if (self.rowConditions.indexOf(dimension) == -1) {
				return true;
			}
			for (var col = 0; col < columnOfValue; col++) {
				var dimensionNumber = self.rowConditions[col];
				if (row[dimensionNumber] != otherrow[dimensionNumber]) {
					return false;
				}
			}
			return true;
		}

		this.isClickedRowMeasure = function (row, value, otherrow) {
			for (var col = 0; col < row.length; col++) {
				if ((row[col] != undefined) && (row[col] != otherrow[col])) {
					return false;
				}
			}
			return true;
		}

		this.onClickSelectNode = function (elemvalue) { 
			var value = jQuery(elemvalue).data('itemValue');
			var type = jQuery(elemvalue).data('typeMorD');
			var number = jQuery(elemvalue).data('numberMorD');
			var item = jQuery(elemvalue).data('itemInfo');
			
			
			self.selection.SelectedNode = [];
			
			self.SelectNodes(value, type, number, item);
			
		}

		this.ClickHandle = function (elemvalue) { 
			var value = jQuery(elemvalue).data('itemValue');
			var type = jQuery(elemvalue).data('typeMorD');
			var number = jQuery(elemvalue).data('numberMorD');
			var item = jQuery(elemvalue).data('itemInfo');
			var selected = OAT.IsNodeSelected(elemvalue.parentElement);
			var datastr = "<DATA><ITEM type=\"" + type + "\" ";
			
			
			if (type === "MEASURE") {
				datastr = datastr + "name=\"" + measures[number].getAttribute("name") + "\" ";
				datastr = datastr + "displayName=\"" + measures[number].getAttribute("displayName") + "\" ";
				datastr = datastr + "selected=\"" + selected.toString() + "\" ";
				datastr = datastr + "location=\"data\">"
				datastr = datastr + self.cleanValueForNull(value)
			} else {//DIMENSION
				datastr = datastr + "name=\"" + self.columns[number].getAttribute("name") + "\" ";
				datastr = datastr + "displayName=\"" + self.columns[number].getAttribute("displayName") + "\" ";
				datastr = datastr + "selected=\"" + selected.toString() + "\" ";
				datastr = datastr + "location=\"rows\">"
				datastr = datastr + self.cleanValueForNull(value)
			}

			datastr = datastr + "</ITEM>";
			//datastr = datastr + "</DATA>";

			datastr = datastr + "<CONTEXT>";
			datastr = datastr + "<RELATED>";
			var previuosDat = datastr;
			try {
				if (!self.serverPagination) {
					if (item != "") {
						if ((item != "GrandTotal") && ((item[0] === undefined) || ((item[0] != "PartialGrandTotal") && (item[0] != "RowSubtotal") && (item[0] != "PtrTotals")))) {//regular case, simple data
							var numRow
							if (item.row != undefined)
								numRow = item.row;
							else
								numRow = item[0];

							for (var i = 0; i < this.columns.length; i++) {
								datastr = datastr + "<ITEM name=\"" + this.columns[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES>";
								if (type === "MEASURE") {
									datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.filteredData[numRow][i]) + "</VALUE>";
								} else {
									var prevValues = [];
									for (var iCV = 0; iCV < this.GeneralDataRows.length; iCV++) {
										if ((this.GeneralDataRows[iCV][number] === value) && (self.isClickedRow(this.filteredData[numRow], value, number, this.GeneralDataRows[iCV], number))
											&& (prevValues.indexOf(this.GeneralDataRows[iCV][i]) === -1)
											&& self.filterOK(this.GeneralDataRows[iCV])) {
											prevValues = prevValues.concat(this.GeneralDataRows[iCV][i])
											datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.GeneralDataRows[iCV][i]) + "</VALUE>";
										}
									}
								}
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}

							for (var i = 0; i < measures.length; i++) {
								datastr = datastr + "<ITEM name=\"" + measures[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES>";
								if (type === "MEASURE") {
									datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.filteredData[numRow][i + this.columns.length]) + "</VALUE>";
								} else {
									var prevValues = [];
									for (var iCV = 0; iCV < this.allDataWithoutSort.length; iCV++) {
										if ((this.allDataWithoutSort[iCV][number] === value) && self.filterOK(this.allDataWithoutSort[iCV])
											&& (prevValues.indexOf(this.allDataWithoutSort[iCV][i + this.columns.length]) === -1)) {
											prevValues = prevValues.concat(this.allDataWithoutSort[iCV][i + this.columns.length])
											datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.allDataWithoutSort[iCV][i + this.columns.length]) + "</VALUE>";
										}
									}
								}
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}
						} else if (item === "GrandTotal") {	//Grand Total, include all filteredData
							datastr = datastr;

							for (var i = 0; i < this.columns.length; i++) {
								datastr = datastr + "<ITEM name=\"" + this.columns[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES>";
								var prevValues = [];
								for (var iCV = 0; iCV < this.GeneralDataRows.length; iCV++) {
									if ((prevValues.indexOf(this.GeneralDataRows[iCV][i]) === -1) && self.filterOK(this.GeneralDataRows[iCV])) {
										prevValues = prevValues.concat(this.GeneralDataRows[iCV][i])
										datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.GeneralDataRows[iCV][i]) + "</VALUE>";
									}
								}
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}

							for (var i = 0; i < measures.length; i++) {
								datastr = datastr + "<ITEM name=\"" + measures[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES>";
								var prevValues = [];
								for (var iCV = 0; iCV < this.allDataWithoutSort.length; iCV++) {
									if ((prevValues.indexOf(this.allDataWithoutSort[iCV][i + this.columns.length]) === -1) && self.filterOK(this.allDataWithoutSort[iCV])) {
										prevValues = prevValues.concat(this.allDataWithoutSort[iCV][i + this.columns.length])
										datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.allDataWithoutSort[iCV][i + this.columns.length]) + "</VALUE>";
									}
								}
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}

						} else if (item[0] === "PartialGrandTotal") { //Partials sums, partial totals for the last row 
							datastr = datastr;

							for (var i = 0; i < this.columns.length; i++) {
								datastr = datastr + "<ITEM name=\"" + this.columns[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES>";
								datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.filteredData[item[1][0]][i]) + "</VALUE>";
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}

							var uniqueRows = [];
							jQuery.each(item[1], function (i, el) {
								if (jQuery.inArray(el, uniqueRows) === -1) uniqueRows.push(el);
							});

							for (var i = 0; i < measures.length; i++) {
								datastr = datastr + "<ITEM name=\"" + measures[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES>";
								for (var iCV = 0; iCV < uniqueRows.length; iCV++) {
									datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.filteredData[uniqueRows[iCV]][i + this.columns.length]) + "</VALUE>";
								}
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}


						} else if (item[0] === 'RowSubtotal') { //partial sums, for rows distinct of the last row
							datastr = datastr;
							var items = item[1].items;

							for (var i = 0; i < this.columns.length; i++) {
								datastr = datastr + "<ITEM name=\"" + this.columns[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES>";
								for (var j = 0; j < items.length; j++) {
									datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.filteredData[items[j].row][i]) + "</VALUE>";
								}
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}

							for (var i = 0; i < measures.length; i++) {
								datastr = datastr + "<ITEM name=\"" + measures[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES>";
								for (var j = 0; j < items.length; j++) {
									datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.filteredData[items[j].row][i + this.columns.length]) + "</VALUE>";
								}
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}


						} else if (item[0] === 'PtrTotals') {
							var filtRows = [];
							for (var i = 0; i < item[1].length; i++) {			//get the list of filtered rows involve in this sum
								for (var j = 0; j < item[1][i].length; j++) {
									if (filtRows.findIndex(item[1][i][j]) === -1) {
										filtRows.push(item[1][i][j]);
									}
								}
							}

							for (var i = 0; i < this.columns.length; i++) {
								datastr = datastr + "<ITEM name=\"" + this.columns[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES>";
								var prevValues = [];
								for (var j = 0; j < filtRows.length; j++) {
									if (prevValues.indexOf(this.filteredData[filtRows[j]][i]) === -1) {
										prevValues = prevValues.concat(this.filteredData[filtRows[j]][i])
										datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.filteredData[filtRows[j]][i]) + "</VALUE>";
									}
								}
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}

							for (var i = 0; i < measures.length; i++) {
								datastr = datastr + "<ITEM name=\"" + measures[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES>";
								var prevValues = [];
								for (var iCV = 0; iCV < filtRows.length; iCV++) {
									if (prevValues.indexOf(this.filteredData[filtRows[iCV]][i + this.columns.length]) === -1) {
										prevValues = prevValues.concat(this.filteredData[filtRows[iCV]][i + this.columns.length])
										datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.filteredData[filtRows[iCV]][i + this.columns.length]) + "</VALUE>";
									}
								}
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}


						}

					}
				} else {
					//when server pagination

					var dataFieldsList = []
					for (var i = 0; i < self.conditions.length; i++){
						if (self.conditions[i].dataField != undefined) {
							dataFieldsList.push(self.conditions[i].dataField)
						} 
					}
					for (var i = 0; i < measures.length; i++){
						if (measures[i].getAttribute("dataField") != undefined) {
							dataFieldsList.push(measures[i].getAttribute("dataField"))
						}
					}

					//if (self.allRowsPivot == "vacio") {
						self.allRowsPivot = []
						self.allFullRowsPivot = []
						var temp = self.QueryViewerCollection[self.IdForQueryViewerCollection].getPivottableDataSync();
						var stringRecord = temp.split("<Record>")
						for (var i = 1; i < stringRecord.length; i++) {
							var recordData = [];
							var fullRecordData = [];
							for (var j = 0; j < dataFieldsList.length; j++) {
								recordData[j] = "#NuN#"
								var dt = stringRecord[i].split("<" + dataFieldsList[j] + ">")
								if (dt.length > 1) {
									var at = dt[1].split("</" + dataFieldsList[j] + ">")
									recordData[j] = at[0]
									fullRecordData[j] = recordData[j]
								} else {
									if (stringRecord[i].indexOf("<" + dataFieldsList[j] + "/>") >= 0) {
										recordData[j] = ""
										fullRecordData[j] = ""
									} else {
										recordData[j] = "#NuN#"
										fullRecordData[j] = "#NuN#"
									}
								}
							}
							if ((type == "MEASURE") && (self.formulaInfo.cantFormulaMeasures) && (self.formulaInfo.measureFormula[number].hasFormula)){
								recordData[number + this.columns.length] = parseFloat(recordData[number + this.columns.length]).toFixed(15).toString()
								fullRecordData[number + this.columns.length] = parseFloat(fullRecordData[number + this.columns.length]).toFixed(15).toString()
							} 
								
							self.allRowsPivot.push(recordData);

							//add hide columns values
							for (var j = 0; j < self.HideDataFilds.length; j++) {
								var dt = stringRecord[i].split("<" + self.HideDataFilds[j] + ">")
								if (dt.length > 1) {
									var at = dt[1].split("</" + self.HideDataFilds[j] + ">")
									fullRecordData[fullRecordData.length] = at[0]
								} else {
									if (stringRecord[i].indexOf("<" + self.HideDataFilds[j] + "/>") >= 0) {
										fullRecordData[fullRecordData.length] = ""
									} else {
										fullRecordData[fullRecordData.length] = "#NuN#"
									}
								}
							}
							self.allFullRowsPivot.push(fullRecordData);

						}

					//}

					var isNotSubtotal = false;
					if (item.row) {
						isNotSubtotal = !item.row.subTotal
						if ((!isNotSubtotal) && (item.isTotal != undefined) && (!item.isTotal)) {
							isNotSubtotal = true;
						}
					}

					if ((item.row != undefined) && (isNotSubtotal)) {
						var row = item.row
						var cellNumber = item.cell
						var numRow = self.pageData.rows.indexOf(row)
						var colPos = item.cell
						var numCol = self.pageData.columnsHeaders[colPos]

						var pseudoRow = [];
						for (var i = 0; i < self.pageData.dataFields.length; i++) {
							pseudoRow[i] = undefined;
						}
						
						
						
						for (var i = 0; i < row.headers.length; i++) {
							var pos = dataFieldsList.indexOf(row.headers[i].dataField) //self.pageData.dataFields.indexOf(row.headers[i].dataField)
							if ((row.headers[i] != undefined) && (row.headers[i].value != undefined)) {
								pseudoRow[pos] = row.headers[i].value
							}
						}
						if (numCol != undefined){
							for (var i = 0; i < numCol.subHeaders.length; i++) {
								if (numCol.subHeaders[i] != undefined) {
									var pos = self.pageData.dataFields.indexOf(numCol.subHeaders[i].dataField)
									if (numCol.subHeaders[i].value != undefined) {
										pseudoRow[pos] = numCol.subHeaders[i].value
									}
								}
							}
						}

						for (var i = 0; i < this.columns.length; i++) {
							datastr = datastr + "<ITEM name=\"" + this.columns[i].getAttribute("name") + "\">"
							datastr = datastr + "<VALUES";
							var existNullValue = false;
							var stringValues = "";
							
							if ((type === "MEASURE")) {
								if (pseudoRow[i] != undefined) {
									if (pseudoRow[i] != "#NuN#"){	
										stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(pseudoRow[i]) + "</VALUE>";
									} else {
										existNullValue = true
									}
								} else {
									if (self.filterIndexes.indexOf(i) != -1) {
										var prevValues = [];
										for (var iCV = 0; iCV < self.allRowsPivot.length; iCV++) {
											if ((prevValues.indexOf(self.allRowsPivot[iCV][i]) === -1) && (self.filterOK(self.allRowsPivot[iCV])) &&
												self.isClickedRowMeasure(pseudoRow, value, self.allRowsPivot[iCV])) {
												prevValues = prevValues.concat(self.allRowsPivot[iCV][i])
												if (self.allRowsPivot[iCV][i] != "#NuN#"){	
													stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(self.allRowsPivot[iCV][i]) + "</VALUE>";
												} else {
													existNullValue = true
												}
											}
										}
									}
								}
							} else {
								var prevValues = [];
								for (var iCV = 0; iCV < self.allRowsPivot.length; iCV++) {
									if ((self.allRowsPivot[iCV][number] === value) && (self.isClickedRow(pseudoRow, value, cellNumber, self.allRowsPivot[iCV], number))
										&& (prevValues.indexOf(self.allRowsPivot[iCV][i]) === -1) && self.filterOK(self.allRowsPivot[iCV])) {
										prevValues = prevValues.concat(self.allRowsPivot[iCV][i])
										if (self.allRowsPivot[iCV][i] != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(self.allRowsPivot[iCV][i]) + "</VALUE>";
										} else {
											existNullValue = true
										}
									}
								}
							}
							
							if (existNullValue){
								datastr = datastr + " Null=\"true\""
							}
							datastr = datastr + ">" + stringValues 
							datastr = datastr + "</VALUES>";
							datastr = datastr + "</ITEM>";
						}

						for (var i = 0; i < measures.length; i++) {
							datastr = datastr + "<ITEM name=\"" + measures[i].getAttribute("name") + "\">"
							datastr = datastr + "<VALUES";
							var existNullValue = false;
							var stringValues = "";
							
							if (type === "MEASURE") {
								if (pseudoRow[i + this.columns.length] != undefined) {
									if (pseudoRow[i + this.columns.length] != "#NuN#"){
										stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(pseudoRow[i + this.columns.length]) + "</VALUE>";
									} else {
										existNullValue = true
									}
								} else {
									if (number == i) {
										if (value != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(value) + "</VALUE>";
										} else {
											existNullValue = true
										}
									} else {
										var prevValues = [];
										for (var iCV = 0; iCV < self.allRowsPivot.length; iCV++) {
											if ((parseFloat(self.allRowsPivot[iCV][number + this.columns.length]) === parseFloat(value)) && (self.isClickedRowMeasure(pseudoRow, value, self.allRowsPivot[iCV]))
												&& self.filterOK(self.allRowsPivot[iCV]) && (prevValues.indexOf(self.allRowsPivot[iCV][i + this.columns.length]) === -1)) {
												if (self.allRowsPivot[iCV][i + this.columns.length] != "#NuN#"){
													stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(self.allRowsPivot[iCV][i + this.columns.length]) + "</VALUE>";
												} else {
													existNullValue = true
												}
											}
										}
									}
								}
							} else {
								var prevValues = [];
								for (var iCV = 0; iCV < self.allRowsPivot.length; iCV++) {
									if ((self.allRowsPivot[iCV][number] === value) && (self.isClickedRow(pseudoRow, value, cellNumber, self.allRowsPivot[iCV], number))
										&& self.filterOK(self.allRowsPivot[iCV]) && (prevValues.indexOf(self.allRowsPivot[iCV][i + this.columns.length]) === -1)) {
										prevValues = prevValues.concat(self.allRowsPivot[iCV][i + this.columns.length])
										if (self.allRowsPivot[iCV][i + this.columns.length] != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(self.allRowsPivot[iCV][i + this.columns.length]) + "</VALUE>";
										} else {
											existNullValue = true
										}
									}
								}
							}
							
							if (existNullValue){
								datastr = datastr + " Null=\"true\""
							}
							datastr = datastr + ">" + stringValues 
							datastr = datastr + "</VALUES>";
							datastr = datastr + "</ITEM>";
						}

						//add hidden values
						for (var i = 0; i < self.HideDataFilds.length; i++) {
							datastr = datastr + "<ITEM name=\"" + self.OrderFildsHidden[i] + "\">"
							datastr = datastr + "<VALUES";
							var existNullValue = false;
							var stringValues = "";
							
							var coinc = function (row1, row2) {
								for (var o = 0; o < row1.length; o++) {
									if ((row1[o] != undefined) && (row1[o] != row2[o])) {
										return false;
									}
								}
								return true;
							}
							
							var stringValues = "";
							if (type === "MEASURE") {
								var prevValues = [];
								for (var iCV = 0; iCV < self.allFullRowsPivot.length; iCV++) {
									if (coinc(pseudoRow, self.allFullRowsPivot[iCV]) && self.isClickedRowMeasure(pseudoRow, value, self.allFullRowsPivot[iCV])
										&& self.filterOK(self.allFullRowsPivot[iCV]) && (prevValues.indexOf(self.allFullRowsPivot[iCV][i + this.columns.length + measures.length]) === -1)) {
										prevValues = prevValues.concat(self.allFullRowsPivot[iCV][i + this.columns.length + measures.length])
										if (self.allFullRowsPivot[iCV][i + this.columns.length + measures.length] != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(self.allFullRowsPivot[iCV][i + this.columns.length + measures.length]) + "</VALUE>";
										} else {
											existNullValue = true
										}
									}
								}
							} else {
								var prevValues = [];
								for (var iCV = 0; iCV < self.allFullRowsPivot.length; iCV++) {
									if ((self.allFullRowsPivot[iCV][number] === value) && (self.isClickedRow(pseudoRow, value, cellNumber, self.allFullRowsPivot[iCV], number))
										&& self.filterOK(self.allFullRowsPivot[iCV]) && (prevValues.indexOf(self.allFullRowsPivot[iCV][i + this.columns.length + measures.length]) === -1)) {
										prevValues = prevValues.concat(self.allFullRowsPivot[iCV][i + this.columns.length + measures.length])
										if (self.allFullRowsPivot[iCV][i + this.columns.length + measures.length] != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(self.allFullRowsPivot[iCV][i + this.columns.length + measures.length]) + "</VALUE>";
										} else {
											existNullValue = true
										}
									}
								}
							}
							
							
							if (existNullValue){
								datastr = datastr + " Null=\"true\""
							}
							datastr = datastr + ">" + stringValues 
							datastr = datastr + "</VALUES>";
							datastr = datastr + "</ITEM>";
						}
					} else {
						if (item === "GrandTotal") {	//Grand Total, include all data

							for (var i = 0; i < this.columns.length; i++) {
								datastr = datastr + "<ITEM name=\"" + this.columns[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES";
								var existNullValue = false;
								var stringValues = "";
							
								var prevValues = [];
								for (var iCV = 0; iCV < self.allRowsPivot.length; iCV++) {
									if ((prevValues.indexOf(self.allRowsPivot[iCV][i]) === -1) && self.filterOK(self.allRowsPivot[iCV])) {
										prevValues = prevValues.concat(self.allRowsPivot[iCV][i])
										if (self.allRowsPivot[iCV][i] != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(self.allRowsPivot[iCV][i]) + "</VALUE>";
										} else {
											existNullValue = true
										}
									}
								}
								
								if (existNullValue){
									datastr = datastr + " Null=\"true\""
								}
								datastr = datastr + ">" + stringValues 
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}

							//add hide values
							for (var i = 0; i < self.HideDataFilds.length; i++) {
								datastr = datastr + "<ITEM name=\"" + self.OrderFildsHidden[i] + "\">"
								datastr = datastr + "<VALUES";
								var existNullValue = false;
								var stringValues = "";
								
								var prevValues = [];
								for (var iCV = 0; iCV < self.allFullRowsPivot.length; iCV++) {
									if ((prevValues.indexOf(self.allFullRowsPivot[iCV][i + this.columns.length + measures.length]) === -1) && self.filterOK(self.allFullRowsPivot[iCV])) {
										prevValues = prevValues.concat(self.allFullRowsPivot[iCV][i + this.columns.length + measures.length])
										if (self.allFullRowsPivot[iCV][i + this.columns.length + measures.length] != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(self.allFullRowsPivot[iCV][i + this.columns.length + measures.length]) + "</VALUE>";
										} else {
											existNullValue = true
										}
									}
								}
								if (existNullValue){
									datastr = datastr + " Null=\"true\""
								}
								datastr = datastr + ">" + stringValues 
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}


							for (var i = 0; i < measures.length; i++) {
								datastr = datastr + "<ITEM name=\"" + measures[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES";
								var existNullValue = false;								
								var stringValues = "";
								
								var prevValues = [];
								for (var iCV = 0; iCV < self.allRowsPivot.length; iCV++) {
									if ((prevValues.indexOf(self.allRowsPivot[iCV][i + this.columns.length]) === -1) && self.filterOK(self.allRowsPivot[iCV])) {
										prevValues = prevValues.concat(self.allRowsPivot[iCV][i + this.columns.length])
										if (self.allRowsPivot[iCV][i + this.columns.length] != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(self.allRowsPivot[iCV][i + this.columns.length]) + "</VALUE>";
										} else {
											existNullValue = true
										}
									}
								}
								
								if (existNullValue){
									datastr = datastr + " Null=\"true\""
								}
								datastr = datastr + ">" + stringValues 
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}


						} else if (item[0] === 'PtrTotals') {
							var row = item[2]
							var colPos = item[3]
							if (colPos > -1) {
								var numCol = self.pageData.columnsHeaders[colPos]
							}

							var pseudoRow = [];
							for (var i = 0; i < self.pageData.dataFields.length; i++) {
								pseudoRow[i] = undefined;
							}
							for (var i = 0; i < row.headers.length; i++) {
								var pos = self.pageData.dataFields.indexOf(row.headers[i].dataField)
								if ((row.headers[i] != undefined) && (row.headers[i].value != undefined)) {
									pseudoRow[pos] = row.headers[i].value
								}
							}
							if (colPos > -1) {
								for (var i = 0; i < numCol.subHeaders.length; i++) {
									if (numCol.subHeaders[i] != undefined) {
										var pos = self.pageData.dataFields.indexOf(numCol.subHeaders[i].dataField)
										if (numCol.subHeaders[i].value != undefined) {
											pseudoRow[pos] = numCol.subHeaders[i].value
										}
									}
								}
							}
							var filtRows = []; var filtFullRows = [];
							for (var i = 0; i < self.allRowsPivot.length; i++) {			//get the list of filtered rows involve in this sum
								if (self.filterOK(self.allRowsPivot[i])) {
									if (self.isClickedRowMeasure(pseudoRow, value, self.allRowsPivot[i])) {
										filtRows.push(self.allRowsPivot[i]);
										if (self.HideDataFilds.length > 0) {
											filtFullRows.push(self.allFullRowsPivot[i])
										}
									}
								}
							}

							for (var i = 0; i < this.columns.length; i++) {
								datastr = datastr + "<ITEM name=\"" + this.columns[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES";
								var existNullValue = false;								
								var stringValues = "";
								
								var prevValues = [];
								for (var j = 0; j < filtRows.length; j++) {
									if (prevValues.indexOf(filtRows[j][i]) === -1) {
										prevValues = prevValues.concat(filtRows[j][i])
										if (filtRows[j][i] != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(filtRows[j][i]) + "</VALUE>";
										} else {
											existNullValue = true
										}
									}
								}
								
								if (existNullValue){
									datastr = datastr + " Null=\"true\""
								}
								datastr = datastr + ">" + stringValues 
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}

							//add hide values
							for (var i = 0; i < self.HideDataFilds.length; i++) {
								datastr = datastr + "<ITEM name=\"" + self.OrderFildsHidden[i] + "\">"
								datastr = datastr + "<VALUES";
								var existNullValue = false;								
								var stringValues = "";
								
								var prevValues = [];
								for (var j = 0; j < filtRows.length; j++) {
									if (prevValues.indexOf(filtRows[j][i]) === -1) {
										prevValues = prevValues.concat(filtRows[j][i])
										if (filtFullRows[j][i + this.columns.length + measures.length] != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(filtFullRows[j][i + this.columns.length + measures.length]) + "</VALUE>";
										} else {
											existNullValue = true
										}
									}
								}
								
								if (existNullValue){
									datastr = datastr + " Null=\"true\""
								}
								datastr = datastr + ">" + stringValues 
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}

							for (var i = 0; i < measures.length; i++) {
								datastr = datastr + "<ITEM name=\"" + measures[i].getAttribute("name") + "\">"
								datastr = datastr + "<VALUES";
								var existNullValue = false;								
								var stringValues = "";
								
								var prevValues = [];
								for (var iCV = 0; iCV < filtRows.length; iCV++) {
									if (prevValues.indexOf(filtRows[iCV][i + this.columns.length]) === -1) {
										prevValues = prevValues.concat(filtRows[iCV][i + this.columns.length])
										if (filtRows[iCV][i + this.columns.length] != "#NuN#"){
											stringValues = stringValues + "<VALUE>" + self.cleanValueForNull(filtRows[iCV][i + this.columns.length]) + "</VALUE>";
										} else {
											existNullValue = true
										}
									}
								}
								
								if (existNullValue){
									datastr = datastr + " Null=\"true\""
								}
								datastr = datastr + ">" + stringValues 
								datastr = datastr + "</VALUES>";
								datastr = datastr + "</ITEM>";
							}
						}


					}

				}
			} catch (Error) {
				datastr = previuosDat;
			}
			datastr = datastr + "</RELATED>";
			datastr = datastr + "<FILTERS>";
			previuosDat = datastr;
			try {
				for (var i = 0; i < self.filterIndexes.length; i++) {
					datastr = datastr + "<ITEM name=\"" + this.columns[self.filterIndexes[i]].getAttribute("name") + "\" displayName=\"" + this.columns[self.filterIndexes[i]].getAttribute("displayName") + "\">";
					datastr = datastr + "<VALUES>"
					datastr = datastr + "<VALUE>"
					if (self.filterDiv.selects[i].value === "[all]") {
						datastr = datastr + gx.getMessage("GXPL_QViewerJSAllOption");//"\"ALL\"";
					}
					else {
						datastr = datastr + self.cleanValueForNull(self.filterDiv.selects[i].value);
					}
					datastr = datastr + "</VALUE>"
					datastr = datastr + "</VALUES>"
					datastr = datastr + '</ITEM>';
				}
			} catch (Error) {
				datastr = previuosDat;
			}
			datastr = datastr + "</FILTERS>";
			datastr = datastr + "</CONTEXT>";
			datastr = datastr + "</DATA>"

			return datastr;
		}



		this.SelectNodes = function(SelectedValue, SelectedType, SelectedMorDNumber, SelectedItem, refresh, selectedItemNumber, conditions) {

			var found = false;

			var dataField = (SelectedType == "DIMENSION") ? self.columns[SelectedMorDNumber].getAttribute("dataField") : measures[SelectedMorDNumber].getAttribute("dataField");

			for (var i = 0; i < jQuery("#" + self.controlName + "_" + self.query + " tr").length && (!found); i++) {//search selected cell in every row
				var tRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[i];
				for (var j = 0; j < tRow.children.length && (!found); j++) {
					var value = jQuery(tRow.children[j]).data('itemValue');
					var type = jQuery(tRow.children[j]).data('typeMorD');
					var number = jQuery(tRow.children[j]).data('numberMorD');
					var item = jQuery(tRow.children[j]).data('itemInfo');

					if (item && (SelectedMorDNumber == number) && (SelectedType == type)) {

						if ((SelectedItem == "GrandTotal") && (item == "GrandTotal")) {

							if (OAT.IsNodeSelected(tRow.children[j])) {
								if (!refresh) {
									OAT.ClearSelectedNodes(jQuery("#" + self.controlName + "_" + self.query));
									self.selection.SelectedNode = [];
								}
							} else {

								if (!refresh) {
									OAT.SetSelectedNodeBackgroundColor(tRow.children[j], self.selection.Color, jQuery("#" + self.controlName + "_" + self.query))
								} else {
									OAT.SetNodeBackgroundColor(tRow.children[j], self.selection.Color)
								}

								if (!refresh)
									self.selection.SelectedNode.push( {
										value : SelectedValue,
										dataField : dataField,
										type : SelectedType,
										rowData : ["GrandTotal"],
										clicked : true
									} );

								if (self.selection.EntireLine) {
									//select only data column

									selectedCellOffset = tRow.children[j].offsetLeft
									
									var firstRow = (self.colConditions.length > 0) ? self.colConditions.length + 1 : 0;
									
									for (var prevRow = firstRow+1; prevRow < jQuery("#" + self.controlName + "_" + self.query + " tr").length; prevRow++) {
										var row = jQuery("#" + self.controlName + "_" + self.query + " tr")[prevRow];
										OAT.SelectAllRow(row, self.selection.Color)
									}

								}

							}

						} else if ((SelectedItem[0] == "PtrTotals") && (item != "GrandTotal") && (item.length > 0) && (SelectedType == "MEASURE")) {
							var sameRow = ((SelectedItem[2].headers.length == item[2].headers.length) && (SelectedItem[3] == item[3]));
							if (sameRow) {
								for (var h = 0; h < SelectedItem[2].headers.length; h++) {
									if (SelectedItem[2].headers[h].value != item[2].headers[h].value) {
										sameRow = false;
									}
								}
							}

							if (sameRow) {
								found = true;
								if (OAT.IsNodeSelected(tRow.children[j])) {
									if (!refresh) {
										OAT.ClearSelectedNodes(jQuery("#" + self.controlName + "_" + self.query));
										self.selection.SelectedNode = [];
									}
								} else {

									if (!refresh) {
										OAT.SetSelectedNodeBackgroundColor(tRow.children[j], self.selection.Color, jQuery("#" + self.controlName + "_" + self.query))
									} else {
										OAT.SetNodeBackgroundColor(tRow.children[j], self.selection.Color)
									}

									if (!refresh)
										self.selection.SelectedNode.push( {
											value : SelectedValue,
											dataField : dataField,
											type : SelectedType,
											rowData : [SelectedItem],
											clicked : true
										} );
										
										
										
									if (self.selection.EntireLine) {
										//search first dimension subtotal/total
										var foundTotal = false;
										for (var posTotal = 0; posTotal < tRow.children.length && (!foundTotal); posTotal++) {
											var typeTotal = jQuery(tRow.children[posTotal]).data('typeMorD');
											var itemTotal = jQuery(tRow.children[posTotal]).data('itemInfo');
											
											if ((typeTotal == "DIMENSION") && (itemTotal[0]!=undefined) && (itemTotal[0] == "PtrTotals"))
											{
												
												OAT.SetNodeBackgroundColor(tRow.children[posTotal], self.selection.Color)
												
												
												//select items from the same row
												OAT.SelectAllRow(tRow, self.selection.Color, posTotal)
												
												selectedCellOffset = tRow.children[posTotal].offsetLeft
												selectedRowOffset = tRow.children[0].offsetLeft
												
												
												var exit = false;
												var lastRow = -1;
												var firstRow = (self.colConditions.length > 0) ? self.colConditions.length + 1 : 0;
												for (var prevRow = i - 1; (prevRow > firstRow) && !exit; prevRow--) {
													var row = jQuery("#" + self.controlName + "_" + self.query + " tr")[prevRow];
													var iterRowOffset = row.children[0].offsetLeft

													if (jQuery(row.children[0]).hasClass("h2subtitle")) {
														if (iterRowOffset <= selectedRowOffset) {
															exit = true;
															lastRow = prevRow;
														}
													}

													if (!exit) {
														OAT.SelectAllRow(row, self.selection.Color)
													}
												}
												
												
												for (var prevRow = lastRow; prevRow >= 0; prevRow--) {
													var topRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[prevRow];

													if (!jQuery(topRow.children[0]).hasClass("h2subtitle")) {
														for (var iterTopRow = 0; iterTopRow < topRow.children.length; iterTopRow++) {
															var rowSpan = parseInt(jQuery(topRow.children[iterTopRow]).attr("rowspan"));
															if (prevRow + rowSpan > i) {
																OAT.SetNodeBackgroundColor(topRow.children[iterTopRow], self.selection.Color)
															}
														}
													}
												}
												
											}
										}
								
									}	

								}

							}
						} else if (self.sameValue(SelectedValue, value, SelectedType, SelectedMorDNumber, SelectedItem)) {

							if ((SelectedItem.cell != undefined) && (SelectedItem.cell == item.cell)) {
								if (SelectedItem.row != undefined && item.row != undefined) {
									var sameRow = (SelectedItem.row.headers.length == item.row.headers.length);
									for (var h = 0; h < SelectedItem.row.headers.length; h++) {
										if (SelectedItem.row.headers[h].value != item.row.headers[h].value) {
											sameRow = false;
										}
									}
									if (sameRow) {
										found = true;
										if (OAT.IsNodeSelected(tRow.children[j])) {
											if (!refresh) {
												OAT.ClearSelectedNodes(jQuery("#" + self.controlName + "_" + self.query));
												self.selection.SelectedNode = [];
											}
										} else {

											if (!refresh) {
												OAT.SetSelectedNodeBackgroundColor(tRow.children[j], self.selection.Color, jQuery("#" + self.controlName + "_" + self.query))
											} else {
												OAT.SetNodeBackgroundColor(tRow.children[j], self.selection.Color)
											}

											if (!refresh)
												self.selection.SelectedNode.push ({
													value : SelectedValue,
													dataField : dataField,
													type : SelectedType,
													rowData : [self.createDataRowFromItem(item, SelectedType)],
													clicked : true
												});

											if (self.selection.EntireLine) {
												//select items from the same row
												OAT.SelectAllRow(tRow, self.selection.Color, j);

												//search previous rows
												for (var prevRow = i - 1; prevRow >= 0; prevRow--) {
													var topRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[prevRow];
													for (var iterTopRow = 0; iterTopRow < topRow.children.length; iterTopRow++) {
														var rowSpan = parseInt(jQuery(topRow.children[iterTopRow]).attr("rowspan"));
														if (prevRow + rowSpan > i) {
															OAT.SetNodeBackgroundColor(topRow.children[iterTopRow], self.selection.Color)
														}
													}
												}

												//search bellow rows
												var selectedItemRowSpam = parseInt(jQuery(tRow.children[j]).attr("rowspan"));
												if (selectedItemRowSpam >= 1) {
													for (var postRow = i + 1; postRow < i + selectedItemRowSpam; postRow++) {
														var bellowRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[postRow];
														OAT.SelectAllRow(bellowRow, self.selection.Color)
													}

													//search for subtotals of selected item
													var postRow = i + selectedItemRowSpam;
													var bellowRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[postRow];
													if ((bellowRow != undefined) && jQuery(bellowRow.children[0]).hasClass("h2subtitle") && !jQuery(bellowRow.children[0]).hasClass("grandtotaltitle")) {
														selectedCellOffset = tRow.children[j].offsetLeft

														rowOffset = bellowRow.children[0].offsetLeft

														if (rowOffset == selectedCellOffset) {
															OAT.SelectAllRow(bellowRow, self.selection.Color)
														}

													}
												}

												if ((self.colConditions.length > 0) && (SelectedType == "MEASURE")) {

													selectedCellOffset = tRow.children[j].offsetLeft

													for (var prevRow = 1; prevRow < jQuery("#" + self.controlName + "_" + self.query + " tr").length; prevRow++) {
														if (prevRow != i) {
															var exit = false
															var row = jQuery("#" + self.controlName + "_" + self.query + " tr")[prevRow];
															for (var iterRow = 0; iterRow < row.children.length && !exit; iterRow++) {
																var offsetIter = row.children[iterRow].offsetLeft + row.children[iterRow].offsetWidth
																if (offsetIter > selectedCellOffset + 1){
																	exit = true;
																	OAT.SetNodeBackgroundColor(row.children[iterRow], self.selection.Color)
																}
															}
														}
													}
												}

											}
										}
									}
								}
							} else if ((SelectedItem[0] == "PtrTotals") && (SelectedItem[1] == item[1]) && (SelectedType == "DIMENSION")) {
								var sameRow = ((SelectedItem[2].headers.length == item[2].headers.length) && (SelectedItem[3] == item[3]));
								if (sameRow) {
									for (var h = 0; h < SelectedItem[2].headers.length; h++) {
										if (SelectedItem[2].headers[h].value != item[2].headers[h].value) {
											sameRow = false;
										}
									}
								}

								if (sameRow) {
									found = true;
									if (OAT.IsNodeSelected(tRow.children[j])) {
										if (!refresh) {
											OAT.ClearSelectedNodes(jQuery("#" + self.controlName + "_" + self.query));
											self.selection.SelectedNode = [];
										}
									} else {

										OAT.ClearSelectedNodes(jQuery("#" + self.controlName + "_" + self.query));

										if (!refresh) {
											OAT.SetSelectedNodeBackgroundColor(tRow.children[j], self.selection.Color, jQuery("#" + self.controlName + "_" + self.query))
										} else {
											OAT.SetNodeBackgroundColor(tRow.children[j], self.selection.Color)
										}

										if (!refresh)
											self.selection.SelectedNode.push({
												value : SelectedValue,
												dataField : dataField,
												type : SelectedType,
												rowData : [SelectedItem],
												clicked : true
											});

										if (self.selection.EntireLine) {
											//select items from the same row
											OAT.SelectAllRow(tRow, self.selection.Color, j)

											selectedCellOffset = tRow.children[j].offsetLeft
											selectedRowOffset = tRow.children[0].offsetLeft

											var exit = false;
											var lastRow = -1;
											var firstRow = (self.colConditions.length > 0) ? self.colConditions.length + 1 : 0;
											for (var prevRow = i - 1; (prevRow > firstRow) && !exit; prevRow--) {
												var row = jQuery("#" + self.controlName + "_" + self.query + " tr")[prevRow];
												var iterRowOffset = row.children[0].offsetLeft

												if (jQuery(row.children[0]).hasClass("h2subtitle")) {
													if (iterRowOffset <= selectedRowOffset) {
														exit = true;
														lastRow = prevRow;
													}
												}

												if (!exit) {
													OAT.SelectAllRow(row, self.selection.Color)
												}
											}

											for (var prevRow = lastRow; prevRow >= 0; prevRow--) {
												var topRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[prevRow];

												if (!jQuery(topRow.children[0]).hasClass("h2subtitle")) {
													for (var iterTopRow = 0; iterTopRow < topRow.children.length; iterTopRow++) {
														var rowSpan = parseInt(jQuery(topRow.children[iterTopRow]).attr("rowspan"));
														if (prevRow + rowSpan > i) {
															OAT.SetNodeBackgroundColor(topRow.children[iterTopRow], self.selection.Color)
														}
													}
												}
											}

										}

									}
								}
							} else if ((SelectedItem == "EventSelection")) {

								if (self.sameValue(SelectedValue, value, SelectedType, SelectedMorDNumber, SelectedItem)) {

									if (!jQuery(tRow.children[0]).hasClass("h2subtitle") && !jQuery(tRow.children[j]).hasClass("gtotal") && !jQuery(tRow.children[j]).hasClass("subtotal")) {
										
										if (self.checkConditions(conditions, item)) {

											OAT.SetNodeBackgroundColor(tRow.children[j], self.selection.Color, jQuery("#" + self.controlName + "_" + self.query))

											if (self.selection.SelectedNode.length <= selectedItemNumber) {
												self.selection.SelectedNode.push({
													value : SelectedValue,
													dataField : dataField,
													type : SelectedType,
													rowData : [self.createDataRowFromItem(item, SelectedType)],
													clicked : false
												});
											} else {
												self.selection.SelectedNode[selectedItemNumber].rowData.push(self.createDataRowFromItem(item, SelectedType));
											}

											if (self.selection.EntireLine) {

												OAT.SelectAllRow(tRow, self.selection.Color, j)

												for (var pos = i - 1; pos > 0; pos--) {
													var iterRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[pos];
													for (var cell = 0; cell < iterRow.children.length; cell++) {
														var rowSpan = parseInt(jQuery(iterRow.children[cell]).attr("rowspan"));
														if (pos + rowSpan > i) {
															OAT.SetNodeBackgroundColor(iterRow.children[cell], self.selection.Color)
														}
													}
												}
												var itemRowSpan = parseInt(jQuery(tRow.children[j]).attr("rowspan"));
												if (itemRowSpan >= 1) {
													for (var pos = i + 1; pos < i + itemRowSpan; pos++) {
														OAT.SelectAllRow(jQuery("#" + self.controlName + "_" + self.query + " tr")[pos], self.selection.Color)
													}

													var pos = i + itemRowSpan;
													var iterRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[pos];
													if ((iterRow != undefined) && jQuery(iterRow.children[0]).hasClass("h2subtitle") && !jQuery(iterRow.children[0]).hasClass("grandtotaltitle")) {
														selectedCellOffset = tRow.children[j].offsetLeft
														rowOffset = iterRow.children[0].offsetLeft
														if (rowOffset == selectedCellOffset) {
															OAT.SelectAllRow(iterRow, self.selection.Color)
														}
													}
												}

												if ((self.colConditions.length > 0) && (SelectedType == "MEASURE")) {

													selectedCellOffset = tRow.children[j].offsetLeft
													for (var prevRow = 1; prevRow < jQuery("#" + self.controlName + "_" + self.query + " tr").length; prevRow++) {
														if (prevRow != i) {
															var exit = false
															var row = jQuery("#" + self.controlName + "_" + self.query + " tr")[prevRow];
															for (var iterRow = 0; iterRow < row.children.length && !exit; iterRow++) {
																var offsetIter = row.children[iterRow].offsetLeft + row.children[iterRow].offsetWidth
																if (offsetIter > selectedCellOffset) {
																	exit = true;
																	OAT.SetNodeBackgroundColor(row.children[iterRow], self.selection.Color)
																}
															}
														}
													}
												}
											}
										}

									}
								}
							}
						}
					}
				}
			}
		}

		
		
		this.getRowInitialShift = function(table, rowNumber){
			var initialShift = 0;
			
			for(var prevRow = rowNumber-1; prevRow >=0; prevRow--)
			{
					var topRow = table[prevRow];
					for (var iterTopRow = 0; iterTopRow < topRow.children.length; iterTopRow++){
						var rowSpan = parseInt(jQuery(topRow.children[iterTopRow]).attr("rowspan"));
						if (prevRow + rowSpan > rowNumber) {
							initialShift=initialShift+1
						}
					}
			}
										
			return  initialShift;
		}
		
		this.getCellPositionSpanWithSpans = function(table, rowNumber, posWithoutSpan)
		{
			
			var row = table[rowNumber];
			var position = 0;
			var posWithSpan = posWithoutSpan;
			
			var cellPos = 0;
			for (var iterTopRow = 0; iterTopRow < row.children.length && position < posWithoutSpan; iterTopRow++)
			{
				var colspan	= parseInt(jQuery(row.children[iterTopRow]).attr("colspan"));
				if (colspan > 1) {
					(posWithSpan < colspan) ? (posWithSpan = posWithSpan - (colspan)) : (posWithSpan = posWithSpan - (colspan),cellPos = cellPos + 1);
					position = position + colspan; 
				} else {
					position = position + 1
					cellPos = cellPos + 1; 
				}
					  
			}
			return cellPos;
		}
		
		this.RedrawSelectedNode = function() {
			if (self.selection.SelectedNode) {

				for (var s = 0; s < self.selection.SelectedNode.length; s++) {
					var SelectedMorDNumber;
					if (self.selection.SelectedNode[s].type == "DIMENSION") {
						for (var i = 0; i < self.columns.length; i++) {
							if (self.selection.SelectedNode[s].dataField == self.columns[i].getAttribute("dataField")) {
								SelectedMorDNumber = i;
							}
						}
					} else {
						for (var i = 0; i < measures.length; i++) {
							if (self.selection.SelectedNode[s].dataField == measures[i].getAttribute("dataField")) {
								SelectedMorDNumber = i;
							}
						}
					}

					if (self.selection.SelectedNode[s].rowData[0] == "GrandTotal") {
						self.SelectNodes(self.selection.SelectedNode[s].value, self.selection.SelectedNode[s].type, SelectedMorDNumber, "GrandTotal", true);
					} else if ((self.selection.SelectedNode[s].rowData[0].length > 0) && (self.selection.SelectedNode[s].rowData[0][0] == "PtrTotals")) {//sub total
						self.SelectNodes(self.selection.SelectedNode[s].value, self.selection.SelectedNode[s].type, SelectedMorDNumber, self.selection.SelectedNode[s].rowData[0], true);
					} else {

						for (var i = 0; i < jQuery("#" + self.controlName + "_" + self.query + " tr").length; i++) {//search selected cell in every row
							var tRow = jQuery("#" + self.controlName + "_" + self.query + " tr")[i];
							for (var j = 0; j < tRow.children.length; j++) {
								var value = jQuery(tRow.children[j]).data('itemValue');
								var type = jQuery(tRow.children[j]).data('typeMorD');
								var number = jQuery(tRow.children[j]).data('numberMorD');
								var item = jQuery(tRow.children[j]).data('itemInfo');

								if ((self.sameValue(self.selection.SelectedNode[s].value, value, self.selection.SelectedNode[s].type, SelectedMorDNumber, item)) && (SelectedMorDNumber == number) && (self.selection.SelectedNode[s].type == type)) {
									if (item.row != undefined) {
										var itemDataRow = self.createDataRowFromItem(item, type);

										for (var v = 0; v < self.selection.SelectedNode[s].rowData.length; v++) {

											var sameRow = true;

											for (var t = 0; t < self.selection.SelectedNode[s].rowData[v].length; t++) {
												if ((self.selection.SelectedNode[s].rowData[v][t] != undefined) && (itemDataRow[t] != undefined) && (!(self.filterIndexes.indexOf(t) > -1)) && (!(self.colConditions.indexOf(t) > -1))) {
													if ((self.selection.SelectedNode[s].rowData[v][t] != "[all]") && (itemDataRow[t] != "[all]") && (self.selection.SelectedNode[s].rowData[v][t].trim() != itemDataRow[t].trim())) {
														sameRow = false;
													}
												}
											}

											if (sameRow)
												self.SelectNodes(self.selection.SelectedNode[s].value, self.selection.SelectedNode[s].type, SelectedMorDNumber, item, true, s);

										}

									}
								}
							}
						}
					}
				}
			}

		}

		
		this.sameValue = function(val1, val2, type, NumberMorD, item){
			try {
				var sameValue = false;
				if (val2 != undefined){ 	 
					var dataType = (type == "DIMENSION") ? self.columns[NumberMorD].getAttribute("dataType") : measures[NumberMorD].getAttribute("dataType");
						 
					if ((dataType == "real") || (dataType == "integer")){
						sameValue = (parseFloat(val1) == parseFloat(val2));	
						if ((!sameValue) && (type == "DIMENSION") && (item[0] != undefined) && (item[0] == "PtrTotals") && (val1.trim() == val2.trim())) 
							return true;
					} else {
					 	sameValue = (val1.trim() == val2.trim());	
					} 
				}
				return sameValue;
			} catch (error) {
				return false;
			}
		}
		
		
		this.checkConditions = function(conditions, item){
			var sameRow = true;
			for(var s = 0; s < conditions.length; s++){
				if (!item.row || !item.row.headers) return false;
				for(var h = 0; h < item.row.headers.length; h++){
					if (item.row.headers[h].dataField == conditions[s].DataField){
						
						var numberMorD;
						for (var i = 0; i < self.columns.length; i++) {
							if (item.row.headers[h].dataField  == self.columns[i].getAttribute("dataField")) {
								numberMorD = i;
							}
						}
						
						if (!self.sameValue(conditions[s].Value, item.row.headers[h].value, "DIMENSION", numberMorD, item))
						{
							return false
						}
						
					}
				}
				
				
				for(var c = 0; c < item.row.cells.length; c++){
					//get dataField of cell
					var numberMorD;
					var nameMeasure;
					for (var i = 0; i < measures.length; i++) {
						if (item.row.cells[c].dataField == measures[i].getAttribute("dataField")) {
							numberMorD = i;
							nameMeasure = measures[i].getAttribute("name");
						}
					}
					
					if (nameMeasure == conditions[s].Name){
						
						if (!self.sameValue(conditions[s].Value, item.row.cells[c].value, "MEASURE", numberMorD, item))
						{
							return false
						}
						
					}
					
				}
				
			}
			return sameRow;
		}		
		
		this.selectValue = function (selection) {

			OAT.ClearSelectedNodes(jQuery("#" + self.controlName + "_" + self.query));
			self.selection.SelectedNode = [];
			
			var s = -2;			
			var maxNumberMorD = -2
			var MorD;
			var numberMorD;
			
			for (var t = 0; t < selection.length; t++)
			{
				var tempMorD;
				var tempnumberMorD;
				for (var i = 0; i < measures.length; i++) {
					if (selection[t].Name == measures[i].getAttribute("name")) {
						tempMorD = "MEASURE"
						tempnumberMorD = i;
					}
				}

				for (var i = 0; i < self.columns.length; i++) {
					if (selection[t].Name == self.columns[i].getAttribute("name")) {
						tempMorD = "DIMENSION"
						tempnumberMorD = i;
					}
				}	
				
				
				if (self.rowConditions.indexOf(tempnumberMorD) >=  maxNumberMorD)
				{
					s = t;
					maxNumberMorD = self.rowConditions.indexOf(tempnumberMorD);
					MorD = tempMorD;
					numberMorD = tempnumberMorD;
				}
					
				
			}
			
			self.SelectNodes(selection[s].Value, MorD, numberMorD, "EventSelection", false, 0, selection);

		}
		
		
		this.deselectValue = function(){
			OAT.ClearSelectedNodes(jQuery("#" + self.controlName + "_" + self.query));
			self.selection.SelectedNode = [];
		}
		
		this.createDataRowFromItem = function(item, type){
			var row = item.row
			var cellNumber = item.cell
			var numRow = self.pageData.rows.indexOf(row)
			var colPos = item.cell
			var numCol = self.pageData.columnsHeaders[colPos]

			var pseudoRow = [];
			for (var i = 0; i < self.pageData.dataFields.length; i++) {
				pseudoRow[i] = undefined;
			}
			if ((row != undefined) && (row.headers != undefined)){
				for (var i = 0; i < row.headers.length; i++) {
					var pos = self.pageData.dataFields.indexOf(row.headers[i].dataField)
					if ((row.headers[i] != undefined) && (row.headers[i].value != undefined)) {
						pseudoRow[pos] = row.headers[i].value
					}
				}
			}
			
			if (type != "DIMENSION") {
				
				if (numCol != undefined){
					for (var i = 0; i < numCol.subHeaders.length; i++) {
						if (numCol.subHeaders[i] != undefined) {
							var pos = self.pageData.dataFields.indexOf(numCol.subHeaders[i].dataField)
							if (numCol.subHeaders[i].value != undefined) {
								pseudoRow[pos] = numCol.subHeaders[i].value
							}
						}
					}
				}
			
			}
			
			for (var i = 0; i < self.filterIndexes.length; i++){
				pseudoRow[self.filterIndexes[i]] = self.filterDiv.selects[i].value;
			}
			
			return pseudoRow;
		}
		
		this.ExpandCollapseHandle = function (elemvalue, eventName) {
			var value = jQuery(elemvalue).data('itemValue');
			var type = jQuery(elemvalue).data('typeMorD');
			var number = jQuery(elemvalue).data('numberMorD');
			var item = jQuery(elemvalue).data('itemInfo');
			var datastr = "<DATA event=\"" + eventName + "\"><ITEM ";

			datastr = datastr + "name=\"" + columns[number].getAttribute("name") + "\" ";
			datastr = datastr + "displayName=\"" + columns[number].getAttribute("displayName") + "\" ";
			datastr = datastr + ">";
			datastr = datastr + self.cleanValueForNull(value)
			datastr = datastr + "</ITEM>";


			datastr = datastr + "<CONTEXT>";
			datastr = datastr + "<EXPANDEDVALUES>";
			var previuosDat = datastr;
			try {
				if (item != "") {
					var numRow
					if (item.row != undefined)
						numRow = item.row;
					else
						numRow = item[0];

					var prevValues = [];
					for (var iCV = 0; iCV < this.GeneralDataRows.length; iCV++) {
						if (prevValues.indexOf(this.GeneralDataRows[iCV][number]) == -1) {
							prevValues = prevValues.concat(this.GeneralDataRows[iCV][number])
							if (self.conditions[number].collapsedValues.indexOf(this.GeneralDataRows[iCV][number]) === -1) {
								datastr = datastr + "<VALUE>" + self.cleanValueForNull(this.GeneralDataRows[iCV][number]) + "</VALUE>";
							}
						}
					}
				}
			} catch (Error) {
				datastr = previuosDat;
			}

			datastr = datastr + "</EXPANDEDVALUES>";
			datastr = datastr + "</CONTEXT>";
			datastr = datastr + "</DATA>"

			return datastr;
		}

		this.ExpandCollapseHandleWhenServerPagination = function (elemvalue, action) {
			if ((typeof (self.QueryViewerCollection[IdForQueryViewerCollection].ItemExpand) == 'function') || (qv.util.isGeneXusPreview())) {
				var number = jQuery(elemvalue).data('numberMorD');
				if (self.conditions[number].previousPage >= self.conditions[number].totalPages) {
					var datastr = self.ExpandCollapseHandleWhenServerPaginationCreateXML(elemvalue, action)
					datastr = datastr.replace(/\&/g, '&amp;');
					//if (qv.util.isGeneXusPreview())
					//window.external.SendText(self.QueryViewerCollection[self.IdForQueryViewerCollection].ControlName, datastr);
					qv.pivot.onItemExpandCollapseEvent(self.QueryViewerCollection[IdForQueryViewerCollection], datastr, (action == "collapse"))
					self.getDataForPivot(self.UcId, self.pageData.ServerPageNumber, self.rowsPerPage, true, "", "", "", "", true)
				} else {
					self.lastColumnNumber = number;
					self.QueryViewerCollection[self.IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
						var data = JSON.parse(resJSON);
						var columnNumber = self.lastColumnNumber

						self.conditions[columnNumber].previousPage = data.PageNumber
						self.conditions[columnNumber].totalPages = data.PagesCount
						self.conditions[columnNumber].blocked = true

						//null value?
						if ((data.Null) && (!self.conditions[columnNumber].hasNull)) {
							self.conditions[columnNumber].hasNull = true;
							if (self.conditions[columnNumber].distinctValues.indexOf("#NuN#") == -1) {
								self.conditions[columnNumber].distinctValues.push("#NuN#")
							}
							if (self.conditions[columnNumber].defaultAction == "Include") {
								if (self.conditions[columnNumber].visibles.indexOf("#NuN#") == -1) {
									self.conditions[columnNumber].visibles.push("#NuN#");
								}
							} else {
								if (self.conditions[columnNumber].blackList.indexOf("#NuN#") == -1) {
									self.conditions[columnNumber].blackList.push("#NuN#");
								}
							}
						}

						for (var i = 0; i < data.NotNullValues.length; i++) {
							var val = data.NotNullValues[i]
							if (self.conditions[columnNumber].distinctValues.indexOf(val) == -1) {
								self.conditions[columnNumber].distinctValues.push(val)

								if ((self.conditions[columnNumber].defaultAction == "Include")
									&& (self.conditions[columnNumber].visibles.indexOf(val) == -1)) {
									self.conditions[columnNumber].visibles.push(val)
								}
								if ((self.conditions[columnNumber].state == "Exclude")
									&& (self.conditions[columnNumber].blackList.indexOf(val) == -1)) {
									self.conditions[columnNumber].blackList.push(val)
								}
							}
						}

						var datastr = self.ExpandCollapseHandleWhenServerPaginationCreateXML(elemvalue, action)
						datastr = datastr.replace(/\&/g, '&amp;');

						self.getDataForPivot(self.UcId, self.pageData.ServerPageNumber, self.rowsPerPage, true, "", "", "", "", true);
						setTimeout(function () {
							//if (qv.util.isGeneXusPreview())
							//window.external.SendText(self.QueryViewerCollection[self.IdForQueryViewerCollection].ControlName, datastr);
							qv.pivot.onItemExpandCollapseEvent(self.QueryViewerCollection[IdForQueryViewerCollection], datastr, (action == "collapse"))
						}, 2000);
					}).closure(this), [self.columns[number].getAttribute("dataField"), 1, 0, ""]);
				}
			} else {
				self.getDataForPivot(self.UcId, self.pageData.ServerPageNumber, self.rowsPerPage, true, "", "", "", "", true);
			}
		}

		this.ExpandCollapseHandleWhenServerPaginationCreateXML = function (elemvalue, action) {
			var value = jQuery(elemvalue).data('itemValue');
			var type = jQuery(elemvalue).data('typeMorD');
			var number = jQuery(elemvalue).data('numberMorD');
			var item = jQuery(elemvalue).data('itemInfo');

			actionName = 'event="ItemExpand"'
			if (action == "collapse") {
				actionName = 'event="ItemCollapse"'
			}

			var datastr = "<DATA " + actionName + "><ITEM ";

			datastr = datastr + "name=\"" + columns[number].getAttribute("name") + "\" ";
			datastr = datastr + "displayName=\"" + columns[number].getAttribute("displayName") + "\" ";
			datastr = datastr + ">";
			datastr = datastr + value
			datastr = datastr + "</ITEM>";


			datastr = datastr + "<CONTEXT>";
			datastr = datastr + "<EXPANDEDVALUES>";

			for (var ex = 0; ex < self.conditions[number].distinctValues.length; ex++) {
				if (self.conditions[number].collapsedValues.indexOf(self.conditions[number].distinctValues[ex]) == -1) {
					datastr = datastr + "<VALUE>" + self.conditions[number].distinctValues[ex] + "</VALUE>"
				}
			}

			datastr = datastr + "</EXPANDEDVALUES>";
			datastr = datastr + "</CONTEXT>";
			datastr = datastr + "</DATA>"

			return datastr;
		}

		this.onFilteredChangedEventHandle = function (dimensionNumber) {
			var datastr = "<DATA event=\"FilterChanged\" name=\"" + this.columns[dimensionNumber].getAttribute("name") + "\" displayName=\"" + this.columns[dimensionNumber].getAttribute("displayName") + "\">"
			for (var i = 0; i < self.conditions[dimensionNumber].distinctValues.length; i++) {
				var value = self.conditions[dimensionNumber].distinctValues[i];
				var checked = ((self.conditions[dimensionNumber].blackList.findIndex(value) == -1) && self.valueIsShowed(value, dimensionNumber) || (/*(cond.distinctValues.find(value) == -1) &&*/ (self.conditions[dimensionNumber].blackList.findIndex(value) == -1)));
				if (checked) {
					datastr = datastr + '<VALUE>' + value + '</VALUE>';
				}
			}
			datastr = datastr + "</DATA>"
			if (qv.util.isGeneXusPreview())
				window.external.SendText(self.QueryViewerCollection[self.IdForQueryViewerCollection].ControlName, datastr);
			if (this.QueryViewerCollection[IdForQueryViewerCollection].FilterChanged) {
				datastr = datastr.replace(/\&/g, '&amp;');
				var xml_doc = qv.util.dom.xmlDocument(datastr);
				var Node = qv.util.dom.selectXPathNode(xml_doc, "/DATA");
				this.QueryViewerCollection[IdForQueryViewerCollection].FilterChangedData = {}
				this.QueryViewerCollection[IdForQueryViewerCollection].FilterChangedData.Name = Node.getAttribute("name");
				this.QueryViewerCollection[IdForQueryViewerCollection].FilterChangedData.SelectedValues = [];
				var valueIndex = -1;
				for (var i = 0; i < Node.childNodes.length; i++)
					if (Node.childNodes[i].nodeName == "VALUE") {
						valueIndex++;
						this.QueryViewerCollection[IdForQueryViewerCollection].FilterChangedData.SelectedValues[valueIndex] = Node.childNodes[i].firstChild.nodeValue;
					}
				this.QueryViewerCollection[IdForQueryViewerCollection].FilterChanged();
			}
		}

		this.onFilteredChangedEventHandleWhenServerPagination = function (dimensionNumber) {
			if ((self.QueryViewerCollection[IdForQueryViewerCollection].FilterChanged) || (qv.util.isGeneXusPreview())) {
				if (self.conditions[dimensionNumber].previousPage >= self.conditions[dimensionNumber].totalPages) {
					self.onFilteredChangedEventHandleWhenServerPaginationCreateXML(dimensionNumber, self.conditions[dimensionNumber].distinctValues, self.conditions[dimensionNumber].blackList);
				} else {
					self.lastColumnNumber = dimensionNumber;
					self.QueryViewerCollection[self.IdForQueryViewerCollection].getAttributeValues((function (resJSON) {
						setTimeout(function () {
							var data = JSON.parse(resJSON);
							self.onFilteredChangedEventHandleWhenServerPaginationCreateXML(self.lastColumnNumber, data.NotNullValues, self.conditions[dimensionNumber].blackList);
						}, 200)
					}).closure(this), [self.columns[dimensionNumber].getAttribute("dataField"), 1, 0, ""]);
				}
			}
		}

		this.onFilteredChangedEventHandleWhenServerPaginationCreateXML = function (dimensionNumber, distinctValues, blackList) {
			var datastr = "<DATA event=\"FilterChanged\" name=\"" + self.columns[dimensionNumber].getAttribute("name") + "\" displayName=\"" + self.columns[dimensionNumber].getAttribute("displayName") + "\">"
			for (var i = 0; i < distinctValues.length; i++) {
				var value = distinctValues[i]
				var checked = true;
				if (self.conditions[dimensionNumber].state == "all") {
					checked = true;
				} else if (self.conditions[dimensionNumber].state == "none") {
					checked = false;
				} else if (self.conditions[dimensionNumber].blackList.findIndex(value) != -1) {
					checked = false;
				} else if (distinctValues.findIndex(value) != -1) {
					checked = true;
				} else if (self.conditions[dimensionNumber].defaultAction == "Exclude") {
					checked = false;
				}
				if (checked) {
					datastr = datastr + '<VALUE>' + value + '</VALUE>';
				}
			}
			datastr = datastr + "</DATA>"

			if (qv.util.isGeneXusPreview())
				window.external.SendText(self.QueryViewerCollection[self.IdForQueryViewerCollection].ControlName, datastr);
			if ((self.QueryViewerCollection[IdForQueryViewerCollection].FilterChanged)) {
				datastr = datastr.replace(/\&/g, '&amp;');
				var xml_doc = qv.util.dom.xmlDocument(datastr);
				var Node = qv.util.dom.selectXPathNode(xml_doc, "/DATA");
				self.QueryViewerCollection[IdForQueryViewerCollection].FilterChangedData = {}
				self.QueryViewerCollection[IdForQueryViewerCollection].FilterChangedData.Name = Node.getAttribute("name");
				self.QueryViewerCollection[IdForQueryViewerCollection].FilterChangedData.SelectedValues = [];
				var valueIndex = -1;
				for (var i = 0; i < Node.childNodes.length; i++) {
					if (Node.childNodes[i].nodeName == "VALUE") {
						valueIndex++;
						self.QueryViewerCollection[IdForQueryViewerCollection].FilterChangedData.SelectedValues[valueIndex] = Node.childNodes[i].firstChild.nodeValue;
					}
				}
				self.QueryViewerCollection[IdForQueryViewerCollection].FilterChanged();
			}
		}

		this.onDragUndDrop = function (dimensionNumber, distinctValues, blackList) {
			var datastr = "<DATA name=\"" + self.columns[dimensionNumber].getAttribute("name") + "\" displayName=\"" + self.columns[dimensionNumber].getAttribute("displayName") + "\">"
			for (var i = 0; i < distinctValues.length; i++) {
				var value = distinctValues[i];
				var checked = true;
				if (self.conditions[dimensionNumber].state == "all") {
					checked = true;
				} else if (self.conditions[dimensionNumber].state == "none") {
					checked = true;
				} else if (self.conditions[dimensionNumber].defaultAction == "Exclude") {
					checked = false;
				}
				if (checked) {
					datastr = datastr + '<VALUE>' + value + '</VALUE>'
				}
			}
			datastr = datastr + "</DATA>"

			datastr = datastr.replace(/\&/g, '&amp;');
			for (var i = 0; i < Node.children.length; i++) {
				if (Node.childNodes[i].nodeName == "VALUE") {
					valueIndex++;
					self.QueryViewerCollection[IdForQueryViewerCollection].FilterChangedData.SelectedValues[valuesIndex] = Node.childNodes[i].firstChild.nodeValues;
				}
			}
			datastr = datastr + "<VALUE>" + value + "</VALUE>"
			self.QueryViewerCollection[IdForQueryViewerCollection].FilterChanged();
		}

		this.onDragundDropEventHandle = function (conditionIndex, position) {
			var datastr = "<DATA event=\"DragAndDrop\" name=\"" + this.columns[conditionIndex].getAttribute("name") + "\" displayName=\"" + this.columns[conditionIndex].getAttribute("displayName") + "\" position=\"" + position + "\"/>"


			try {
				datastr = datastr.replace(/\&/g, '&amp;');
				qv.pivot.onOAT_PIVOTDragAndDropEvent(this.QueryViewerCollection[IdForQueryViewerCollection], datastr);
			} catch (Error) {

			}
		}

		/*this.getGenerator = function () {
			var gen;
			if (gx.gen.isDotNet()) gen = "C#";
			else if (gx.gen.ruby) gen = "Ruby";
			else gen = "Java";
			return gen;
		}*/

		if ((self.autoPaging) && (self.colConditions.length > 0)) {
			dataRows = self.rowsForBlankCells(dataRows);
		}

		if (self.serverPagination) {
			self.initWhenServerPagination();
			//self.goWhenServerPagination(false)
		} else {
			self.init();


			if ((self.autoPaging) || (self.rowConditions.length <= 16) || (self.GeneralDataRows.length <= 1200)) {
				if (self.filterIndexes.length > 0) {
					self.preGoWhenMoveTopFilter(self.filterIndexes[0], true)
					self.stateChanged = true;
					if (self.tempBlackLists) {
						if (!self.autoPaging) {
							for (var i = 0; i < self.conditions.length; i++) {
								if (self.conditions[i]) {
									if (self.tempBlackLists[i]) {
										self.conditions[i].blackList = self.tempBlackLists[i]
									}
									if (self.tempCollapsedValues[i]) {
										self.conditions[i].collapsedValues = self.tempCollapsedValues[i]
									}
								}
							}
						}
					}
					try {
						if (self.oldSortValues.length > 0) {
							for (var fsort = 0; fsort < self.conditions.length; fsort++) {
								if (self.conditions[fsort]) {
									self.conditions[fsort].sort = self.oldSortValues[fsort];
									self.sort(self.conditions[fsort]);
								}
							}
						}
					} catch (Error) {
					}
					self.go(false);
				} else if (!self.autoPaging) {
					self.go(true);
				} else {
					var areCollapsedValues = self.preGoWhenCollapsedValue()
					if (areCollapsedValues) {
						self.go(false)
					} else {
						self.preGo(false, null, null, -1, true);
					}
				}
			} else {
				setTimeout(function () {
					if (self.filterIndexes.length > 0) {
						self.preGoWhenMoveTopFilter(self.filterIndexes[0], true)
						self.stateChanged = true;
						if (self.tempBlackLists) {
							if (!self.autoPaging) {
								//reload blacklist & sort
								for (var i = 0; i < self.conditions.length; i++) {
									if (self.conditions[i]) {
										if (self.tempBlackLists[i]) {
											self.conditions[i].blackList = self.tempBlackLists[i]
										}
										if (self.tempCollapsedValues[i]) {
											self.conditions[i].collapsedValues = self.tempCollapsedValues[i]
										}
									}
								}
							}
						}
						try {
							if (self.oldSortValues.length > 0) {
								for (var fsort = 0; fsort < self.conditions.length; fsort++) {
									if (self.conditions[fsort]) {
										self.conditions[fsort].sort = self.oldSortValues[fsort];
										self.sort(self.conditions[fsort]);
									}
								}
							}
						} catch (Error) {
						}
						self.go(false);
					} else if (!self.autoPaging) {
						self.go(true);
					} else {
						var areCollapsedValues = self.preGoWhenCollapsedValue()
						if (areCollapsedValues) {
							self.go(false)
						} else {
							self.preGo(false, null, null, -1, true);
						}
					}
				}, 500)
			}
		}
	}
	try {
		OAT.Loader.featureLoaded("pivot");
	} catch (ERROR) {

	}


	function sortUnidimensionalArray(arr, index, self) { /* sort distinct values of a condition */
		//var months = ["january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"];
		var sortFunc;
		var coef = 1;
		var numSort = function (a, b) {
			if (a == b) { return 0; }
			return coef * (parseInt(a) > parseInt(b) ? 1 : -1);
		}
		var dictSort = function (a, b) {
			if (a == b) { return 0; }
			return coef * (a > b ? 1 : -1);
		}


		//new code
		var sortInt = true;
		for (var ival = 0; ival < arr.length; ival++) {
			if ((sortInt) && (arr[ival] != parseInt(arr[ival]))) {
				sortInt = false;
			}
		}
		if (sortInt) { sortFunc = numSort; } else { sortFunc = dictSort; } //decides the type of sorting
		//end new code
		var testValue = arr[0];

		//if (months.find(testValue.toString().toLowerCase()) != -1) { sortFunc = dateSort; }

		arr.sort(sortFunc);

		//when custom order 
		for (var h = 0; h < self.columns[index].childNodes.length; h++) {
			if ((self.columns[index].childNodes[h] != undefined) &&
				(self.columns[index].childNodes[h].localName != undefined) &&
				(self.columns[index].childNodes[h].localName === "customOrder")) {
				arr = []
				for (var n = 0; n < self.columns[index].childNodes[h].childNodes.length; n++) {
					if (self.columns[index].childNodes[h].childNodes[n].localName == "Value") {
						arr.push(self.columns[index].childNodes[h].childNodes[n].textContent);
					}
				}
			}
		}



		return arr;
	} /* sort */

	function fillGeneralDistinctValues(numConds, self, rows) {
		self.GeneralDistinctValues = [];
		for (var i = 0; i < numConds; i++) {
			var elems = [];
			for (var j = 0; j < rows.length; j++) {
				if (rows[j][i] == undefined) {
					if (elems.findIndex(" ") == -1) {
						elems.push(" ");
					}
				} else {
					if (elems.findIndex(rows[j][i]) == -1) {
						elems.push(rows[j][i]);
					}
				}
			}

			self.GeneralDistinctValues[i] = sortUnidimensionalArray(elems, i, self);
		}
	}

	function fromUndefinedToBlanck(dataRows) {
		for (var i = 0; i < dataRows.length; i++) {
			for (var j = 0; j < dataRows[i].length; j++) {
				if (dataRows[i][j] == undefined) {
					dataRows[i][j] = " ";
				}
			}
		}
	}

	function sumGrandPagingTotals(allDataRows, conditions, cant_measures, formulaInfo, self) {
		var size = allDataRows[0].length;
		var init_measure_pos = size - cant_measures;
		var sums = [];
		for (var j = 0; j < cant_measures; j++) { //set initial value 0, cant_measures is the number of measures
			if (formulaInfo.measureFormula[j].hasFormula) {
				sums[j] = [];
				for (var o = 0; o < self.formulaInfo.recordDataLength; o++) { sums[j][o] = 0 }
			} else {
				sums[j] = 0;
			}
		}
		var firstValueToSum = true;
		for (var i = 0; i < allDataRows.length; i++) {
			if (self.isNotFilterByTopFilter(allDataRows[i]) && !self.notInBlackList(allDataRows[i], self.conditions)) {
				for (var t = 0; t < cant_measures; t++) {
					if (!formulaInfo.measureFormula[t].hasFormula) {
						if ((allDataRows[i][init_measure_pos + t] != "#NuN#") && (sums[t] != "#NuN#")) {
							sums[t] = sums[t] + parseFloat(allDataRows[i][init_measure_pos + t]);
						} else if ((firstValueToSum) && (allDataRows[i][init_measure_pos + t] == "#NuN#")) {
							sums[t] = "#NuN#";
						} else if ((sums[t] == "#NuN#") && (allDataRows[i][init_measure_pos + t] != "#NuN#")) {
							sums[t] = parseFloat(allDataRows[i][init_measure_pos + t]);
						}
					}
				}
				firstValueToSum = false;
			}
		}


		for (var m = 0; m < cant_measures; m++) {
			if (formulaInfo.measureFormula[m].hasFormula) {
				for (var i = 0; i < self.recordForFormula.length; i++) {
					for (var t = 0; t < self.formulaInfo.measureFormula[m].relatedMeasures.length; t++) {
						var pos = self.formulaInfo.measureFormula[m].relatedMeasures[t]
						if (!isNaN(parseFloat(self.recordForFormula[i][pos]))) {
							sums[m][pos] = sums[m][pos] + parseFloat(self.recordForFormula[i][pos]);
						}
					}
				}
			}
		}

		for (var m = 0; m < cant_measures; m++) {
			if (formulaInfo.measureFormula[m].hasFormula) {
				sums[m] = self.calculateFormulaTotal([sums[m]], m, "MeasureInRows")
			}
		}
		return sums;
	}

	function notInBlackListB(row, conditions) {
		var esta = false;
		for (var i = 0; i < row.length; i++) {
			if ((conditions[i] != undefined) && (conditions[i].blackList != undefined) && (conditions[i].blackList.findIndex(row[i]) != -1)) {
				esta = true;
			}
		}
		return esta;
	}

	//return the partial DataRow, from "item", item represents the dimesnion values of a row, ej> [dimension1Value, dimensio2Value] 
	function getDataRowFromItem(item) {
		var dataR = [];
		var obj = item;

		while (obj.depth > 0) {
			dataR = [obj.value].concat(dataR);
			obj = obj.parent;
		}

		dataR = [obj.value].concat(dataR);
		return dataR;
	}

	//recives the dimensions value, ej> [dimension1Value, dimensio2Value]
	//returns the total sum of measures values 
	function getTotalsForDataRow(allData, dataR, cant_measures, conditions, filteredIndexes, pageData, filterValues, self) {
		var size = allData[0].length;
		var init_measure_pos = size - cant_measures;
		var sums = [];
		for (var j = 0; j < cant_measures; j++) { //set initial value 0, cant_measures is the number of measures
			sums[j] = 0;
		} //set initial value 0, cant_measures is the number of measures 

		var tempFilteredIndexes = []; for (var pFId = 0; pFId < filteredIndexes.length; pFId++) { tempFilteredIndexes[pFId] = filteredIndexes[pFId]; }
		tempFilteredIndexes.sort();
		for (var p = 0; p < tempFilteredIndexes.length; p++) { //if same dimension has been move up to the top filter
			if (tempFilteredIndexes[p] < dataR.length) {

				if (filterValues[p].value == "[all]") {
					dataR.splice(tempFilteredIndexes[p], 0, "#-#!");
				} else {
					dataR.splice(tempFilteredIndexes[p], 0, filterValues[p].value);
				}
			}
		}


		var belongToPageData = false;
		//for each row of data
		var firstValueToSum = true;
		for (var j = 0; j < allData.length; j++) {
			if (self.isNotFilterByTopFilter(allData[j]) && !self.notInBlackList(allData[j], self.conditions)) {
				var coincide = true;
				//if checks with dataR
				for (var i = 0; i < dataR.length; i++) {
					if ((allData[j][i] != dataR[i]) && (dataR[i] != '#-#!')) {
						coincide = false;
					}
					if (!coincide) {
						break;
					}
				}
				//sum values
				if (coincide) {
					if (!belongToPageData) {
						belongToPageData = belongToCollection(allData[j], pageData)
					}
					for (var t = 0; t < cant_measures; t++) {
						if ((allData[j][init_measure_pos + t] != "#NuN#") && (sums[t] != "#NuN#")) {
							sums[t] = sums[t] + parseFloat(allData[j][init_measure_pos + t]);
						} else if ((firstValueToSum) && (allData[j][init_measure_pos + t] == "#NuN#")) {
							sums[t] = "#NuN#";
						} else if ((sums[t] == "#NuN#") && (allData[j][init_measure_pos + t] != "#NuN#")) {
							sums[t] = parseFloat(allData[j][init_measure_pos + t]);
						}
					}
					firstValueToSum = false
				}
			}
		}


		//calculate mesaure formula
		try {
			for (var m = 0; m < cant_measures; m++) {
				if (self.formulaInfo.measureFormula[m].hasFormula) {
					var formval = self.getFormulaRowByDataRow(dataR, m, "");
					sums[m] = self.calculateFormulaTotal([formval], m, "MesaureAsColumn");
				}
			}
		} catch (Error) { }

		if (!belongToPageData)
			return false

		return sums;
	}

	function belongToCollection(row, rowCollection) {
		for (var j = 0; j < rowCollection.length; j++) {
			var coincide = true;
			for (var i = 0; i < row.length - measures.length; i++) {
				if (rowCollection[j][i] != row[i]) {
					coincide = false;
				}
				if (!coincide) {
					break;
				}
			}
			if (coincide) return true;
		}
		return false;
	}

	//remove rows until get the pagination size
	//precond - data is order
	function removeExtraRows(dataRows, measures, rowsPerPage) {
		//get temporal Distinct Values
		var dtValues = [];
		var totalRows = 1; //last gand total
		var initVal = dataRows[0][0];
		if (dataRows[0].length - 0 - 1 > 0) {
			totalRows = 1 + totalRows;
		}
		var rows = [];
		var cantRows = dataRows.length;
		for (var i = 0; i < dataRows.length; i++) { //for every element from the first column
			if (initVal == dataRows[i][0]) {
				rows.push([dataRows[i]]);
				if (dataRows[0].length - measures - 0 - 1 === 0) {
					totalRows = totalRows + 1;
				}
			} else {
				totalRows = 1 + totalRows; //the subtotal for this element
				initVal = dataRows[i][0];
				if (dataRows[0].length - measures - 1 > 0) { //recursive call
					totalRows = totalRows + getTrueCantRows(rows, 1, measures); //add the rows added for sub elements
				}
				rows = [];
				rows.push([dataRows[i]]);
			}

			if (totalRows > rowsPerPage) {
				cantRows = i;
				break;
			}
		}
		if (dataRows[0].length - measures - 0 - 1 > 0) { //recursive call for the las subgroup
			totalRows = totalRows + getTrueCantRows(rows, 1, measures); //add the rows added for sub elements
		}
		return i;
	}

	function collapseRowForCollapseValues(self, dataToCollapse) {
		//delete pagination info
		self.paginationInfo = false;

		//remove extra row when dimensions at filter
		if (self.filterIndexes.length > 0) {

			self.FilterByTopFilter = true;
			self.allData = self.GeneralDataRows;
			var dataRows = self.GeneralDataRows;

			var dataColumns = [];
			for (var i = 0; i < self.columns.length; i++) { //get pos. column not in top filter & not filter in top filter
				if ((self.filterIndexes.findIndex(i) == -1)) {
					dataColumns.push(i)
				} else {
					var fi = self.filterIndexes.findIndex(i)
					var s = self.filterDiv.selects[fi];
					if ((s != undefined) && (OAT.$v(s) != "[all]")) { dataColumns.push(i) }
				}
			}

			var tempDataRows = [];
			for (var i = 0; i < dataRows.length; i++) {

				var existe = false;
				var previousRecord = 0;
				for (var j = 0; j < tempDataRows.length; j++) {
					var same = true;
					for (var h = 0; h < dataColumns.length; h++) {
						if (dataRows[i][dataColumns[h]] != tempDataRows[j][dataColumns[h]]) {

							same = false;
							break;
						}
					}
					if (same) {
						previousRecord = j;
						existe = true;
						break;
					}
				}
				if (!existe) {
					var newRecord = [];
					for (var p = 0; p < dataRows[i].length; p++) {
						newRecord.push([dataRows[i][p]]);
					}
					tempDataRows.push([newRecord]);

					for (var t = 0; t < measures.length; t++) {
						var pos;
						if (t < measures.length - 1) {
							pos = self.rowConditions[self.rowConditions.length - measures.length + 1 + t]
						} else {
							pos = self.dataColumnIndex
						}
						if ((self.formulaInfo.measureFormula[t].hasFormula) && (self.filterIndexes.length > 0)) {
							var valuesToOperate = self.getFormulaRowByDataRow(dataRows[i], t, "")
							if ((valuesToOperate != self.EmptyValue) && (valuesToOperate != "#NuN#")) {
								var result = self.calculateFormulaTotal([valuesToOperate], t, "MeasureInRows")
								if (!isNaN(result)) {
									newRecord[pos] = result.toString()
								}
							}
						}
					}

				} else { //increase prevoius record value

					//increase the entry of the column index (the last one)
					if (measures.length > 0) {
						if (!self.formulaInfo.measureFormula[measures.length - 1].hasFormula) {
							if ((tempDataRows[previousRecord][self.dataColumnIndex] != "#NuN#") && (dataRows[i][self.dataColumnIndex] != "#NuN#")) {
								tempDataRows[previousRecord][self.dataColumnIndex] = (parseFloat(tempDataRows[previousRecord][self.dataColumnIndex]) + parseFloat(dataRows[i][self.dataColumnIndex])).toString()
							} else if (tempDataRows[previousRecord][self.dataColumnIndex] == "#NuN#") {
								tempDataRows[previousRecord][self.dataColumnIndex] = dataRows[i][self.dataColumnIndex]
							}
						}
					}
					//increase the entries of other columns
					for (var t = 0; t < measures.length - 1; t++) {
						var pos = self.rowConditions[self.rowConditions.length - measures.length + 1 + t]
						if ((self.formulaInfo.measureFormula[t].hasFormula) && (self.filterIndexes.length > 0)) {
							//var addedValues = self.getFormulaRowByDataRow(dataRows[i], t, "")
						} else {
							tempDataRows[previousRecord][pos] = (parseFloat(tempDataRows[previousRecord][pos]) + parseFloat(dataRows[i][pos])).toString()
						}
					}
				}
			}
			//end remove extra data rows, that have the same columns values, except for the value of the columns index

			self.RowsWhenMoveToFilter = tempDataRows;
		}
		//end remove extra row when dimensions at filter

		//remove extra row when values collapse
		var tempCollapsesRows = [];

		var rowsWithCollapseValues = []
		var collapsesValues = []
		for (var i = 0; i < self.conditions.length; i++) {
			if ((self.conditions[i].collapsedValues != undefined) && (self.conditions[i].collapsedValues.length > 0)) {
				rowsWithCollapseValues.push(self.conditions[i].dataRowPosition)
				collapsesValues.push(self.conditions[i].collapsedValues)
			}
		}

		if (rowsWithCollapseValues.length > 0) //are values collapses?
		{
			var dataRows = self.GeneralDataRows
			if (self.RowsWhenMoveToFilter.length > 0) {
				dataRows = self.RowsWhenMoveToFilter
			}
			self.FilterByTopFilter = true //similar behaviour to top filter

			var tempDataRows = [];

			for (var i = 0; i < dataRows.length; i++) {
				var added = false;

				for (var r = 0; r < rowsWithCollapseValues.length; r++) {
					if (collapsesValues[r].findIndex(dataRows[i][rowsWithCollapseValues[r]]) != -1) {
						added = true;
						if (self.isNotFilterByTopFilter(dataRows[i])
							&& !self.notInBlackList(dataRows[i], self.conditions)) {

							var existe = false;
							var previousRecord = 0;
							for (var j = 0; j < tempDataRows.length; j++) {
								var same = true;
								for (var h = 0; h <= rowsWithCollapseValues[r]; h++) {
									if (dataRows[i][h] != tempDataRows[j][h]) {
										same = false;
										break;
									}
								}
								if (same) {
									previousRecord = j;
									existe = true;
									break;
								}
							}

							if (!existe) {
								var newRecord = [];
								for (var p = 0; p < dataRows[i].length; p++) {
									newRecord.push([dataRows[i][p]]);
								}
								tempDataRows.push([newRecord]);

								for (var t = 0; t < measures.length; t++) {
									var pos;
									if (t < measures.length - 1) {
										pos = self.rowConditions[self.rowConditions.length - measures.length + 1 + t]
									} else {
										pos = self.dataColumnIndex
									}
									if ((self.formulaInfo.measureFormula[t].hasFormula) && (self.filterIndexes.length > 0)) {
										var valuesToOperate = self.getFormulaRowByDataRow(dataRows[i], t, "")
										if ((valuesToOperate != self.EmptyValue) && (valuesToOperate != "#NuN#")) {
											var result = self.calculateFormulaTotal([valuesToOperate], t, "MeasureInRows")
											if (!isNaN(result)) {
												newRecord[pos] = result.toString()
											}
										}
									}
								}
							} else { //increase prevoius record value
								//increase the entry of the column index (the last one)
								if (measures.length > 0) {
									if (!self.formulaInfo.measureFormula[measures.length - 1].hasFormula) {
										if ((tempDataRows[previousRecord][self.dataColumnIndex] != "#NuN#") && (dataRows[i][self.dataColumnIndex] != "#NuN#")) {
											tempDataRows[previousRecord][self.dataColumnIndex] = (parseFloat(tempDataRows[previousRecord][self.dataColumnIndex]) + parseFloat(dataRows[i][self.dataColumnIndex])).toString()
										} else if (tempDataRows[previousRecord][self.dataColumnIndex] == "#NuN#") {
											tempDataRows[previousRecord][self.dataColumnIndex] = dataRows[i][self.dataColumnIndex]
										}
									}
								}
								//increase the entries of other columns
								for (var t = 0; t < measures.length - 1; t++) {
									var pos = self.rowConditions[self.rowConditions.length - measures.length + 1 + t]
									if ((self.formulaInfo.measureFormula[t].hasFormula) && (self.filterIndexes.length > 0)) {
										//var addedValues = self.getFormulaRowByDataRow(dataRows[i], t, "")
									} else {
										tempDataRows[previousRecord][pos] = (parseFloat(tempDataRows[previousRecord][pos]) + parseFloat(dataRows[i][pos])).toString()
									}
								}
							}



						}
						break;
					}
				}

				if (!added) {
					var newRecord = [];
					for (var p = 0; p < dataRows[i].length; p++) {
						newRecord.push([dataRows[i][p]]);
					}
					tempDataRows.push([newRecord]);

					for (var t = 0; t < measures.length; t++) {
						var pos;
						if (t < measures.length - 1) {
							pos = self.rowConditions[self.rowConditions.length - measures.length + 1 + t]
						} else {
							pos = self.dataColumnIndex
						}
						if ((self.formulaInfo.measureFormula[t].hasFormula) && (self.filterIndexes.length > 0)) {
							var valuesToOperate = self.getFormulaRowByDataRow(dataRows[i], t, "")
							if ((valuesToOperate != self.EmptyValue) && (valuesToOperate != "#NuN#")) {
								var result = self.calculateFormulaTotal([valuesToOperate], t, "MeasureInRows")
								if (!isNaN(result)) {
									newRecord[pos] = result.toString()
								}
							}
						}
					}
				}
			}

			self.RowsWhenMoveToFilter = tempDataRows

		}

		if (self.filterIndexes.length > 0) {
			var dataColumns = [];
			for (var i = 0; i < self.columns.length; i++) { //get pos. column not in top filter & not filter in top filter
				if ((self.filterIndexes.findIndex(i) == -1)) {
					dataColumns.push(i)
				} else {
					var fi = self.filterIndexes.findIndex(i)
					var s = self.filterDiv.selects[fi];
					if ((s != undefined) && (OAT.$v(s) != "[all]")) { dataColumns.push(i) }
				}
			}

			var dataRows = self.RowsWhenMoveToFilter;
			//reordenar segun datos a agrupar
			var sortIntMemory = [];

			//get sort value
			for (var index = dataRows[0].length - 1; index > -1; index--) {
				var sortInt = true;
				for (var ival = 0; ival < dataRows.length; ival++) {
					if ((sortInt) && (dataRows[ival][index] != parseInt(dataRows[ival][index]))) {
						sortInt = false;
						break;
					}
				}
				sortIntMemory[index] = sortInt;
			}

			var index = dataColumns[0];
			if (sortIntMemory[index]) {
				dataRows = dataRows.sort((function (index) {
					return function (a, b) {
						return (parseInt(a[index]) === parseInt(b[index]) ? 0 : (parseInt(a[index]) < parseInt(b[index]) ? -1 : 1));
					};
				})(index));
			} else {
				dataRows = dataRows.sort((function (index) {
					return function (a, b) {
						return (a[index] === b[index] ? 0 : (a[index] < b[index] ? -1 : 1));
					};
				})(index));
			}

			var actualVal = dataRows[0][index]; //sort from the first row column
			var initPos = 0;
			for (var i = 0; i < dataRows.length; i++) {
				if ((actualVal != dataRows[i][index])) {
					actualVal = dataRows[i][index]
					dataRows = OAT.PartialSort(dataRows, initPos, i - 1, index + 1, self.headerRow.length, sortIntMemory)
					initPos = i;
				} else if ((i == dataRows.length - 1)) {
					dataRows = OAT.PartialSort(dataRows, initPos, i, index + 1, self.headerRow.length, sortIntMemory)
				}
			}

			self.RowsWhenMoveToFilter = dataRows
		}
		//count all items to show
		if ((self.filterIndexes.length > 0) || (rowsWithCollapseValues.length > 0)) {
		} else {
			self.RowsWhenMoveToFilter = self.GeneralDataRows
		}


		return rowsWithCollapseValues.length > 0

	}

	function calculateTotalRowsWithSubtotalRows(previusData, newData, self) {
		var subs = []
		for (var con = 0; con < self.rowConditions.length - 1 - (measures.length - 1); con++) {
			if (self.conditions[self.rowConditions[con]]) {
				subs[con] = (self.conditions[self.rowConditions[con]].subtotals == 1) ? 1 : 0;
			}
		}
		/*if (dataRows.length == 0){
			return 0;
		}*/
		var subtotals = 0;
		for (var j = 0; j < self.rowConditions.length - 1 - (measures.length - 1); j++) {
			if (self.conditions[self.rowConditions[j]].collapsedValues.indexOf(previusData[self.rowConditions[j]]) != -1) {
				subtotals = 1;
				break
			}
			if (previusData[self.rowConditions[j]] != newData[self.rowConditions[j]]) {
				subtotals = subtotals + subs.reduce(function (a, b) { return a + b; }) 	// + (self.rowConditions.length-1-(measures.length-1)-j);
				break;
			}
			subs[j] = 0;
		}
		return subtotals;
		/*var r = dataRows.length-1
		while (r >= 0){
			var previousRecord = dataRows[r];
			for(var j = 0; j < self.rowConditions-1; j++){
				if (dataRows[j] != newData[j]){
					subtotals = subtotals + (self.rowConditions - j);
				}
			}
		}*/
	}

	function showSubtotalRowsForFirstColumn(previusData, newData, self) {
		var subs = []
		for (var con = 0; con < self.rowConditions.length - 1 - (measures.length - 1); con++) {
			if (self.conditions[self.rowConditions[con]]) {
				subs[con] = (self.conditions[self.rowConditions[con]].subtotals == 1) ? 1 : 0;
			}
		}

		var subtotals = 0;
		var j = 0;

		if (self.conditions[self.rowConditions[j]].collapsedValues.indexOf(previusData[self.rowConditions[j]]) != -1) {
			substotals = 1;

		} else if (previusData[self.rowConditions[j]] != newData[self.rowConditions[j]]) {
			subtotals = 1;
		}
		subs[j] = 0;

		return subtotals;
	}


	function createPaginationInfo(self, data) {
		if (!self.paginationInfo) {
			self.paginationInfo = {}
			self.paginationInfo.pages = []
		}
		var actualPage = 0;
		var firstRowActualPage = 0;
		var lastRowActualPage = 0;
		var cantRowsActualPage = 0;
		var tempDataRows = []

		var extraRows = 0;
		//for (var iter = 0; iter < data.length; iter++){
		var iter = 0;
		while (iter < data.length) {
			if (cantRowsActualPage >= self.autoPagingRowsPerPage) {
				var lastSumShow = false//(cantRowsActualPage == self.autoPagingRowsPerPage) //**
				self.paginationInfo.pages[actualPage] = { firstRow: firstRowActualPage, lastRow: lastRowActualPage, rows: tempDataRows, lastSumShow: lastSumShow, extraRows: extraRows };
				actualPage++;
				firstRowActualPage = iter;
				cantRowsActualPage = 0;
				tempDataRows = [];
				extraRows = 0;
			}

			var descartado = false;
			if (!self.notInBlackList(data[iter], self.conditions) && self.isNotFilterByTopFilter(data[iter])) { //ver que no sea esta fila filtrada por ninguna condicion
				var sum = 0;

				if ((tempDataRows.length == 0) && (actualPage > 0) && (!self.paginationInfo.pages[actualPage - 1].lastSumShow)) { //verifico que no quede la suma de la primer columna por mostrar de la pagina anterior
					sum = showSubtotalRowsForFirstColumn(self.paginationInfo.pages[actualPage - 1].rows[self.paginationInfo.pages[actualPage - 1].rows.length - 1],
						data[iter], self)
					if ((sum > 0)) {
						tempDataRows.push([self.paginationInfo.pages[actualPage - 1].rows[self.paginationInfo.pages[actualPage - 1].rows.length - 1]])
						extraRows = calculateTotalRowsWithSubtotalRows(tempDataRows[0], data[iter], self)
						sum = 1;
					}
				} //end verifico que no queden sumas por mostrar de la pagina anterior

				if ((tempDataRows.length > 0) && ((tempDataRows.length != 1) || (extraRows == 0))) {
					sum = calculateTotalRowsWithSubtotalRows(tempDataRows[tempDataRows.length - 1], data[iter], self)
				}

				if (cantRowsActualPage + 1 + sum <= self.autoPagingRowsPerPage) {
					tempDataRows.push([data[iter]])
					cantRowsActualPage = cantRowsActualPage + 1 + sum
					lastRowActualPage = iter;
					iter++;
				} else {
					cantRowsActualPage = cantRowsActualPage + sum

					var lastSumShow = (sum > 0) && (cantRowsActualPage == self.autoPagingRowsPerPage) //se mostro la ultima suma
					self.paginationInfo.pages[actualPage] = { firstRow: firstRowActualPage, lastRow: lastRowActualPage, rows: tempDataRows, lastSumShow: lastSumShow, extraRows: extraRows };
					actualPage++;
					firstRowActualPage = iter;
					cantRowsActualPage = 0;
					tempDataRows = [];
					extraRows = 0;
				}
			} else {
				iter++;
			}


		}

		if (cantRowsActualPage < self.autoPagingRowsPerPage) {
			self.paginationInfo.pages[actualPage] = { firstRow: firstRowActualPage, lastRow: lastRowActualPage, rows: tempDataRows, extraRows: 0 };
			actualPage++;
		}
		self.paginationInfo.totalPages = actualPage;

		self.setNewPagesAccount(self.paginationInfo.totalPages);
		self.TotalPagesPaging = self.paginationInfo.totalPages
	}

	function calculateGrandTotalForLastMeasure(self) {
		if (self.actualPaginationPage == self.TotalPagesPaging) {
			var dataRows = self.GeneralDataRows
			if (self.RowsWhenMoveToFilter.length > 0) {
				dataRows = self.RowsWhenMoveToFilter
			}
			var sum = 0;
			var allNuNValues = true;
			var valuesToOperate = [];
			for (var r = 0; r < dataRows.length; r++) {
				if (self.isNotFilterByTopFilter(dataRows[r]) && !self.notInBlackList(dataRows[r], self.conditions)) {
					if (self.formulaInfo.measureFormula[measures.length - 1].hasFormula) {
						var formInfo = self.getFormulaRowByDataRow(dataRows[r], measures.length - 1, "")
						if ((formInfo != self.EmptyValue) && (formInfo != "#NuN#")) {
							valuesToOperate.push(formInfo)
						}
					} else {
						if (!isNaN(parseFloat(dataRows[r][self.dataColumnIndex]))) {
							allNuNValues = false;
							sum = sum + parseFloat(dataRows[r][self.dataColumnIndex])
						}
					}
				}
			}

			if (self.formulaInfo.measureFormula[measures.length - 1].hasFormula) {
				return self.calculateFormulaTotal([valuesToOperate], measures.length - 1, "MeasureInRows")
			} else {
				if (!allNuNValues) {
					return sum;
				} else {
					return "#NuN#"
				}
			}
		} else {
			return 0
		}
	}


	function getTrueCantRows(dataRows, actualcolumn, measures) {
		var totalRows = 0;
		if (dataRows[0].length - measures - actualcolumn - 1 != 0) {
			totalRows = 1 + totalRows;
		}
		var initVal = dataRows[0][actualcolumn];
		var rows = [];
		for (var i = 0; i < dataRows.length; i++) { //for every element from the first column
			if (initVal == dataRows[i][actualcolumn]) {
				rows.push([dataRows[i]]);
				if (dataRows[0].length - measures - actualcolumn - 1 === 0) {
					totalRows = totalRows + 1;
				}
			} else {
				totalRows = 1 + totalRows; //the subtotal for this element
				initVal = dataRows[i][actualcolumn];
				if (dataRows[0].length - measures - actualcolumn - 1 > 0) { //recursive call
					totalRows = totalRows + getTrueCantRows(rows, actualcolumn + 1, measures); //add the rows added for sub elements
				}
				rows = [];
				rows.push([dataRows[i]]);
			}
		}
		if (dataRows[0].length - measures - actualcolumn - 1 > 0) { //recursive call
			totalRows = totalRows + getTrueCantRows(rows, actualcolumn + 1, measures); //add the rows added for sub elements
		}
		return totalRows;
	}

	function getMeasureNumberByName(name, measures) {
		var number = 0;
		for (var i = 0; i < measures.length; i++) {
			if (measures[i].getAttribute("displayName") == name) {
				return i
			}
		}
		return 0
	}

	function getMeasureNumberByDataField(dataField, measures) {
		var number = 0;
		for (var i = 0; i < measures.length; i++) {
			if (measures[i].getAttribute("dataField") == dataField) {
				return i
			}
		}
		return 0
	}

	function saveAsIE() {
		var add_point = function (x, y, dragging) {
			x_points.push(x);
			y_points.push(y);
			drag_points.push(dragging);
		};
		var draw = function () {
			canvas.width = canvas.width;
			ctx.lineWidth = 6;
			ctx.lineJoin = "round";
			ctx.strokeStyle = "#000000";
			var
				i = 0
				, len = x_points.length
				;
			for (; i < len; i++) {
				ctx.beginPath();
				if (i && drag_points[i]) {
					ctx.moveTo(x_points[i - 1], y_points[i - 1]);
				} else {
					ctx.moveTo(x_points[i] - 1, y_points[i]);
				}
				ctx.lineTo(x_points[i], y_points[i]);
				ctx.closePath();
				ctx.stroke();
			}
		};
		var stop_drawing = function () {
			drawing = false;
		};
		var BB = get_blob();
		saveAs(
			new BB(
				[self.file.fileName || self.file.fileContent]
				, { type: "text/plain;charset=" + self.file.fileContent.toBase64() }
			)
			, (self.file.fileName || self.file.fileContent) + "." + self.fileExtension
		);
	}

	//C1Line
	function getValueMeasureFromMeasureList(measureList, rowNumber, fg, filterData, cantMeasures) {
		for (var itMl = 0; itMl < measureList.length; itMl++) {
			if ((measureList[itMl][fg] != undefined) && (measureList[itMl][fg][1] != undefined) && (measureList[itMl][fg][1][0] == rowNumber)) {
				return measureList[itMl][fg][0]
			}
		}
		//when is not in the measure list search in filterData
		return filterData[rowNumber][filterData[0].length - cantMeasures + fg]
	}


	function reLoadDataArrays(dataRows, formulaInfo, headerRow, columns, self, measures, fullRecord) {
		fromUndefinedToBlanck(dataRows);

		if (dataRows[0] != undefined) {

			//agregar indice de fila
			if (formulaInfo.cantFormulaMeasures > 0) {
				for (var i = 0; i < dataRows.length; i++) {
					dataRows[i][headerRow.length] = i;
				}
			}
			//end agregar indice a filas
			var sortIntMemory = [];

			//get sort value
			for (var index = headerRow.length - 1; index > -1; index--) { //*dataRows[0].length*/
				var sortInt = true;
				for (var ival = 0; ival < dataRows.length; ival++) {
					if ((sortInt) && (dataRows[ival][index] != parseInt(dataRows[ival][index]))) {
						sortInt = false;
						break;
					}
				}
				sortIntMemory[index] = sortInt;
			}
			var index = 0;
			if (sortIntMemory[index]) {
				dataRows = dataRows.sort((function (index) {
					return function (a, b) {
						return (parseInt(a[index]) === parseInt(b[index]) ? 0 : (parseInt(a[index]) < parseInt(b[index]) ? -1 : 1));
					};
				})(index));
			} else {
				dataRows = dataRows.sort((function (index) {
					return function (a, b) {
						return (a[index] === b[index] ? 0 : (a[index] < b[index] ? -1 : 1));
					};
				})(index));
			}

			var actualVal = dataRows[0][index];
			var initPos = 0;
			for (var i = 0; i < dataRows.length; i++) {
				if ((actualVal != dataRows[i][index])) {
					actualVal = dataRows[i][index]
					dataRows = OAT.PartialSort(dataRows, initPos, i - 1, index + 1, headerRow.length, sortIntMemory)
					initPos = i;
				} else if ((i == dataRows.length - 1)) {
					dataRows = OAT.PartialSort(dataRows, initPos, i, index + 1, headerRow.length, sortIntMemory)
				}
			}

		}
		//collapse repeate rows
		var tempDataRows = dataRows;
		dataRows = [];
		if (tempDataRows.length > 0) {
			dataRows[0] = tempDataRows[0]
		}
		var act_pos = 0;
		for (var i = 1; i < tempDataRows.length; i++) {
			var repeated = true;
			for (var j = 0; j < columns.length; j++) {
				if (tempDataRows[i][j] != tempDataRows[i - 1][j]) { repeated = false; break; }
			}
			if (repeated) {
				for (var j = columns.length; j < columns.length + measures.length; j++) {
					var tot = parseFloat(dataRows[act_pos][j]) + parseFloat(tempDataRows[i][j])
					if ((dataRows[act_pos][j] == "#NuN#") && (tempDataRows[i][j] == "#NuN#")) {
						tot = "#NuN#"
					} else if (dataRows[act_pos][j] == "#NuN#") {
						tot = tempDataRows[i][j] + ""
					} else if (tempDataRows[i][j] == "#NuN#") {
						tot = dataRows[act_pos][j] + ""
					}
					dataRows[act_pos][j] = tot + "";
				}
				//colapsar filas de formula
				if (formulaInfo.cantFormulaMeasures > 0) {
					var filaSumar = dataRows[act_pos][headerRow.length];
					var filaRepetida = tempDataRows[i][headerRow.length];
					for (var formulasI = 0; formulasI < formulaInfo.measureFormula.length; formulasI++) { //campos formulas
						if (formulaInfo.measureFormula[formulasI].hasFormula) {
							for (var formulasJ = 0; formulasJ < formulaInfo.measureFormula[formulasI].relatedMeasures.length; formulasJ++) {
								var pos = formulaInfo.measureFormula[formulasI].relatedMeasures[formulasJ];
								var tot = parseFloat(fullRecord[filaSumar][pos]) + parseFloat(fullRecord[filaRepetida][pos])
								fullRecord[filaSumar][pos] = tot + "";
							}
						}
					}
					for (var j = columns.length; j < columns.length + measures.length; j++) { //restantes medidas para mantener coherencia
						var tot = parseFloat(fullRecord[filaSumar][j]) + parseFloat(fullRecord[filaRepetida][j])
						fullRecord[filaSumar][j] = tot + "";
					}
					for (var posB = 0; posB < headerRow.length; posB++) { //anular fila ya sumada
						fullRecord[filaRepetida][posB] = "";
					}
				}
				//end colapsar formula info
			} else {
				act_pos++
				dataRows[act_pos] = tempDataRows[i];
			}
		}

		//eliminar indice de fila
		if (formulaInfo.cantFormulaMeasures > 0) {
			if (dataRows[0] != undefined) {
				for (var it = 0; it < dataRows.length; it++) {
					dataRows[it].splice(headerRow.length, 1)
				}
			}
		}
		//end borrar incide a filas
		self.recordForFormula = fullRecord;
		self.formulaInfo = formulaInfo;

		//calculate single measure formula value
		for (var mforF = 0; mforF < measures.length; mforF++) {
			if ((formulaInfo.measureFormula[mforF]) && (formulaInfo.measureFormula[mforF].hasFormula)) {
				for (var rforF = 0; rforF < dataRows.length; rforF++) {
					if (dataRows[rforF][dataRows[rforF].length - measures.length + mforF] == 0) {
						var formula = self.getFormulaRowByDataRow(dataRows[rforF], mforF, "");
						var result = EvaluateExpressionPivotJs(formulaInfo.measureFormula[mforF].PolishNotation, formula, formulaInfo)
						if ((result == Infinity) || isNaN(result)) {
							dataRows[rforF][dataRows[rforF].length - measures.length + mforF] = "#FoE#";
						}
					}
				}
			}
		}

		self.GeneralDataRows = dataRows;
		self.autoPagingRowsPerPage = (pageSize != undefined) ? parseInt(pageSize) : 10;
		self.TotalPagesPaging = parseInt(dataRows.length / self.autoPagingRowsPerPage);
		if ((dataRows.length % self.autoPagingRowsPerPage) != 0) {
			self.TotalPagesPaging++;
		}
		self.allData = dataRows;


		if (dataRows.length > 0) {
			fillGeneralDistinctValues(headerRow.length - measures.length, self, dataRows);
		}
	}

}



/* END OF FILE - ..\oatPivot\oat_pivot.src.js - */
/* START OF FILE - ..\oatPivot\oat_statistic.src.js - */
if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {

	OAT.Statistics = {
		list: [{
			longDesc: "Count",
			shortDesc: "COUNT",
			func: "count"
		}, {
			longDesc: "Sum",
			shortDesc: "SUM",
			func: "sum"
		}, {
			longDesc: "Product",
			shortDesc: "PRODUCT",
			func: "product"
		}, {
			longDesc: "Arithmetic mean",
			shortDesc: "MEAN",
			func: "amean"
		}, {
			longDesc: "Maximum",
			shortDesc: "MAX",
			func: "max"
		}, {
			longDesc: "Minimum",
			shortDesc: "MIN",
			func: "min"
		}, {
			longDesc: "Distinct values",
			shortDesc: "DISTINCT",
			func: "distinct"
		}, {
			longDesc: "Variance",
			shortDesc: "VAR",
			func: "variance"
		}, {
			longDesc: "Standard deviation",
			shortDesc: "STDDEV",
			func: "deviation"
		}, {
			longDesc: "Median",
			shortDesc: "MEDIAN",
			func: "median"
		}, {
			longDesc: "Mode",
			shortDesc: "MODE",
			func: "mode"
		}],
		count: function (a) {
			return a.length
		},
		sum: function (a) {
			if (a == "#FoE#") return "#NaV#"
			var allNuN = (a.length > 0);
			for (var c = 0, b = 0; b < a.length; b++) {
				if (a[b] != "#NuN#") allNuN = false;
				if (!isNaN(a[b]))
					c += a[b];
			}
			if (allNuN) return "#NuN#"
			return c
		},
		product: function (a) {
			for (var c = 1, b = 0; b < a.length; b++)
				c *= a[b];
			return c
		},
		amean: function (a) {
			for (var c = 0, b = 0; b < a.length; b++)
				c += a[b];
			return c = a.length ? c / a.length : 0
		},
		max: function (a) {
			for (var c = Number.MIN_VALUE, b = 0; b < a.length; b++)a[b] > c && (c = a[b]);
			return c
		},
		min: function (a) {
			for (var c = Number.MAX_VALUE, b = 0; b < a.length; b++)a[b] < c && (c = a[b]);
			return c
		},
		distinct: function (a) {
			for (var c = 0, b = {}, d = 0; d < a.length; d++)
				b[a[d]] = 1;
			for (p in b)
				c++;
			return c
		},
		deviation: function (a) {
			a = OAT.Statistics.variance(a);
			return Math.sqrt(a)
		},
		variance: function (a) {
			if (2 > a.length)
				return 0;
			for (var c = 0, b = OAT.Statistics.amean(a), d = 0; d < a.length; d++)
				c += (a[d] - b) * (a[d] - b);
			return c / (a.length - 1)
		},
		median: function (a) {
			return a.sort(function (a, b) { return a - b })[Math.floor(a.length / 2)]
		},
		mode: function (a) {
			for (var c = {}, b = 0; b < a.length; b++) {
				var d = a[b] + "";
				d in c ? c[d]++ : c[d] = 1
			}
			var a = 0, b = "", e;
			for (e in c) d = c[e], d > a && (a = d, b = e);
			return parseFloat(b)
		}
	};
	try {
		OAT.Loader.featureLoaded("statistics");
	} catch (ERROR) {

	}

	OAT.WinData = {
		TYPE_TEMPLATE: -1,
		TYPE_AUTO: 0,
		TYPE_MS: 1,
		TYPE_MAC: 2,
		TYPE_ROUND: 3,
		TYPE_RECT: 4,
		TYPE_ODS: 5
	};
	OAT.Win = function (a) {
		var b = this;
		this.options = {
			title: "",
			x: 0,
			y: 0,
			visibleButtons: "cmMfr",
			enabledButtons: "cmMfr",
			innerWidth: 0,
			innerHeight: 0,
			outerWidth: 350,
			outerHeight: !1,
			stackGroupBase: 100,
			type: OAT.WinData.TYPE_AUTO,
			template: !1,
			className: !1
		};
		for (var c in a)
			this.options[c] = a[c];
		b.dom = {
			buttons: {
				c: !1,
				m: !1,
				M: !1,
				f: !1,
				r: !1
			},
			container: !1,
			content: !1,
			title: !1,
			caption: !1,
			status: !1,
			resizeContainer: !1
		};
		b.moveTo = function (a, c) {
			b.dom.container.style.left = a + "px";
			b.dom.container.style.top = c + "px"
		};
		b.innerResizeTo = function () {
		};
		b.outerResizeTo = function () {
		};
		b.show = function () {
			document.body.appendChild(b.dom.container);
			OAT.Dom.show(b.dom.container)
		};
		b.hide = function () {
			OAT.Dom.hide(b.dom.container)
		};
		b.close = b.hide();
		b.minimize = function () {
		};
		b.maximize = function () {
		};
		b.flip = function () {
		};
		b.accomodate = function (a) {
			a = OAT.Dom.getWH(a);
			b.innerResizeTo(a[0], a[1])
		};
		b.options.type == OAT.WinData.TYPE_TEMPLATE && OAT.WinTemplate(b);
		b.options.type == OAT.WinData.TYPE_MS && OAT.WinMS(b);
		b.options.type == OAT.WinData.TYPE_MAC && OAT.WinMAC(b);
		b.options.type == OAT.WinData.TYPE_RECT && OAT.WinRECT(b, a.containerQuery);
		b.options.type == OAT.WinData.TYPE_ROUND && OAT.WinROUND(b);
		b.options.type == OAT.WinData.TYPE_ODS && OAT.WinODS(b);
		-1 != b.options.enabledButtons.indexOf("m") && b.dom.buttons.m && OAT.Dom.attach(b.dom.buttons.m, "click", b.minimize);
		-1 != b.options.enabledButtons.indexOf("M") && b.dom.buttons.M && OAT.Dom.attach(b.dom.buttons.M, "click", b.maximize);
		-1 != b.options.enabledButtons.indexOf("c") && b.dom.buttons.c && OAT.Dom.attach(b.dom.buttons.c, "click", b.hide);
		-1 != b.options.enabledButtons.indexOf("f") && b.dom.buttons.f && OAT.Dom.attach(b.dom.buttons.f, "click", b.flip);
		-1 != b.options.enabledButtons.indexOf("r") && b.dom.buttons.r && OAT.Resize.create(b.dom.buttons.r, b.dom.resizeContainer, OAT.Resize.TYPE_XY);
		b.dom.title && OAT.Drag.create(b.dom.title, b.dom.container);
		b.moveTo(b.options.x, b.options.y);
		(b.options.outerWidth || b.options.outerHeight) && b.outerResizeTo(b.options.outerWidth, b.options.outerHeight);
		(b.options.innerWidth || b.options.innerHeight) && b.innerResizeTo(b.options.innerWidth, b.options.innerHeight);
		b.dom.caption && (OAT.addTextNode(b.dom.caption, b.options));
		b.options.stackGroupBase && OAT.WinManager.addWindow(b.options.stackGroupBase, b.dom.container);
		b.hide()
	};
	OAT.WinTemplate = function (a) {
		var b = a.options.template;
		if (b) {
			for (var c = "function" == typeof b ? b() : OAT.$(b).cloneNode(!0), g = {
				oat_w_ctr: "container",
				oat_w_title_ctr: "title",
				oat_w_title_t_ctr: "caption",
				oat_w_content: "content",
				oat_w_max_b: ["buttons", "M"],
				oat_w_min_b: ["buttons", "m"],
				oat_w_close_b: ["buttons", "c"],
				oat_w_flip_b: ["buttons", "f"],
				oat_w_resize_handle: ["buttons", "r"]
			}, e = [c], b = c.getElementsByTagName("*"), c = 0; c < b.length; c++)
				e.push(b[c]);
			for (c = 0; c < e.length; c++) {
				var b = e[c], f;
				for (f in g)
					if (OAT.Dom.isClass(b, f)) {
						var d = g[f];
						d instanceof Array ? a.dom[d[0]][d[1]] = b : a.dom[d] = b
					}
			}
			a.moveTo = function (b, c) {
				a.dom.container.style.left = b + "px";
				a.dom.container.style.top = c + "px"
			};
			a.outerResizeTo = function (b, c) {
				a.dom.container.style.width = b ? b + "px" : "auto";
				a.dom.container.style.height = c ? c + "px" : "auto"
			};
			a.innerResizeTo = function (b, c) {
				a.dom.content.style.width = b ? b + "px" : "auto";
				a.dom.content.style.height = c ? c + "px" : "auto"
			}
		} else
			alert("OAT Window cannot be created, as a template is required but not specified!")
	};
	OAT.WinMS = function (a) {
		OAT.Style.include("winms.css");
		a.dom.container = OAT.Dom.create("div", {
			position: "absolute"
		}, "oat_winms_container");
		a.dom.resizeContainer = a.dom.container;
		a.dom.content = OAT.Dom.create("div", {}, "oat_winms_content");
		a.dom.title = OAT.Dom.create("div", {}, "oat_winms_title");
		a.dom.caption = OAT.Dom.create("span", {}, "oat_winms_caption");
		a.dom.status = OAT.Dom.create("div", {}, "oat_winms_status");
		OAT.Dom.append([a.dom.container, a.dom.title, a.dom.content, a.dom.status]);
		-1 != a.options.visibleButtons.indexOf("c") && (a.dom.buttons.c = OAT.Dom.create("div", {}, "oat_winms_close_b"), OAT.Dom.append([a.dom.title, a.dom.buttons.c]));
		-1 != a.options.visibleButtons.indexOf("M") && (a.dom.buttons.M = OAT.Dom.create("div", {}, "oat_winms_max_b"), OAT.Dom.append([a.dom.title, a.dom.buttons.M]));
		-1 != a.options.visibleButtons.indexOf("m") && (a.dom.buttons.m = OAT.Dom.create("div", {}, "oat_winms_min_b"), OAT.Dom.append([a.dom.title, a.dom.buttons.m]));
		-1 != a.options.visibleButtons.indexOf("r") && (a.dom.buttons.r = OAT.Dom.create("div", {}, "oat_winms_resize_b"), OAT.Dom.append([a.dom.container, a.dom.buttons.r]));
		OAT.Dom.append([a.dom.title, a.dom.caption]);
		a.outerResizeTo = function (b, c) {
			a.dom.container.style.width = b ? b + "px" : "auto";
			a.dom.container.style.height = c ? c + "px" : "auto"
		}
	};
	OAT.WinMAC = function (a) {
		OAT.Style.include("winmac.css");
		a.dom.container = OAT.Dom.create("div", {
			position: "absolute"
		}, "oat_winmac_container");
		a.dom.resizeContainer = a.dom.container;
		a.dom.content = OAT.Dom.create("div", {}, "oat_winmac_content");
		a.dom.title = OAT.Dom.create("div", {}, "oat_winmac_title");
		a.dom.caption = OAT.Dom.create("span", {}, "oat_winmac_caption");
		a.dom.status = OAT.Dom.create("div", {}, "oat_winmac_status");
		OAT.Dom.append([a.dom.container, a.dom.title, a.dom.content, a.dom.status]);
		a.dom.buttons.lc = OAT.Dom.create("div", {}, "oat_winmac_leftCorner");
		OAT.Dom.append([a.dom.title, a.dom.buttons.lc]);
		a.dom.buttons.rc = OAT.Dom.create("div", {}, "oat_winmac_rightCorner");
		OAT.Dom.append([a.dom.title, a.dom.buttons.rc]);
		-1 != a.options.visibleButtons.indexOf("c") && (a.dom.buttons.c = OAT.Dom.create("div", {}, "oat_winmac_close_b"), OAT.Dom.append([a.dom.title, a.dom.buttons.c]));
		-1 != a.options.visibleButtons.indexOf("M") && (a.dom.buttons.M = OAT.Dom.create("div", {}, "oat_winmac_max_b"), OAT.Dom.append([a.dom.title, a.dom.buttons.M])); -1 != a.options.visibleButtons.indexOf("m") && (a.dom.buttons.m = OAT.Dom.create("div", {}, "oat_winmac_min_b"), OAT.Dom.append([a.dom.title, a.dom.buttons.m]));
		-1 != a.options.visibleButtons.indexOf("r") && (a.dom.buttons.r = OAT.Dom.create("div", {}, "oat_winmac_resize_b"), OAT.Dom.append([a.dom.container, a.dom.buttons.r]));
		OAT.Dom.append([a.dom.title, a.dom.caption]);
		a.outerResizeTo = function (b, c) {
			a.dom.container.style.width = b ? b + "px" : "auto";
			a.dom.container.style.height = c ? c - 8 + "px" : "auto"
		}
	};
	OAT.WinRECT = function (a, className) {
		//OAT.Style.include("winrect.css");
		if (className != undefined)
			a.dom.container = OAT.Dom.create("div", {
				position: "absolute"
			}, className + " oat_winrect_container");
		else
			a.dom.container = OAT.Dom.create("div", {
				position: "absolute"
			}, "oat_winrect_container");

		a.dom.resizeContainer = a.dom.container;
		//a.dom.content = OAT.Dom.create("div", {}, "oat_winrect_content");

		var ua = navigator.userAgent.toLowerCase();
		var isAndroid = ua.indexOf("android") > -1;
		if ((gx.util.browser.isIPad() || gx.util.browser.isIPhone() || isAndroid) || (false)) {
			a.dom.content = OAT.Dom.create("div", {}, "oat_winrect_content oat_winrect_content_small");
			a.dom.title = OAT.Dom.create("div", {}, "oat_winrect_title oat_winrect_title_small");
		} else {
			a.dom.content = OAT.Dom.create("div", {}, "oat_winrect_content");
			a.dom.title = OAT.Dom.create("div", {}, "oat_winrect_title");
		}


		a.dom.caption = OAT.Dom.create("span", {}, "oat_winrect_caption");
		a.dom.status = OAT.Dom.create("div", {}, "oat_winrect_status");

		OAT.Dom.append([a.dom.container, a.dom.title, a.dom.content, a.dom.status]);

		if ((gx.util.browser.isIPad() || gx.util.browser.isIPhone() || isAndroid) || (false)) {
			a.dom.buttons.c = OAT.Dom.create("div", {}, "oat_winrect_close_b oat_winrect_close_small");
		} else {
			a.dom.buttons.c = OAT.Dom.create("div", {}, "oat_winrect_close_b");
		}
		OAT.addImageNode(a.dom.buttons.c, "close", "");

		OAT.Dom.append([a.dom.title, a.dom.buttons.c]);

		a.outerResizeTo = function (b, c) {
			a.dom.container.style.width = b ? b + "px" : "auto";
			a.dom.container.style.height = c ? c + "px" : "auto"
		}
	};
	OAT.WinROUND = function (a) {
		OAT.Style.include("winround.css");
		a.dom.container = OAT.Dom.create("div", {
			position: "absolute"
		}, "oat_winround_container");
		a.dom.resizeContainer = a.dom.container;
		a.dom.table = OAT.Dom.create("table", {}, "oat_winround_wrapper");
		a.dom.tr_t = OAT.Dom.create("tr", {});
		a.dom.td_lt = OAT.Dom.create("td", {}, "oat_winround_lt");
		a.dom.td_t = OAT.Dom.create("td", {}, "oat_winround_t");
		a.dom.td_rt = OAT.Dom.create("td", {}, "oat_winround_rt");
		a.dom.tr_m = OAT.Dom.create("tr", {});
		a.dom.td_l = OAT.Dom.create("td", {}, "oat_winround_l");
		a.dom.td_m = OAT.Dom.create("td", {}, "oat_winround_m");
		a.dom.td_r = OAT.Dom.create("td", {}, "oat_winround_r");
		a.dom.tr_b = OAT.Dom.create("tr", {});
		a.dom.td_lb = OAT.Dom.create("td", {}, "oat_winround_lb");
		a.dom.td_b = OAT.Dom.create("td", {}, "oat_winround_b");
		a.dom.td_rb = OAT.Dom.create("td", {}, "oat_winround_rb");
		a.dom.content = OAT.Dom.create("div", {}, "oat_winround_content");
		a.dom.title = OAT.Dom.create("div", {}, "oat_winround_title");
		a.dom.caption = OAT.Dom.create("span", {}, "oat_winround_caption");
		a.dom.status = OAT.Dom.create("div", {}, "oat_winround_status");
		-1 != a.options.visibleButtons.indexOf("c") && (a.dom.buttons.c = OAT.Dom.create("div", {}, "oat_winround_close_b"), OAT.Dom.append([a.dom.title, a.dom.buttons.c]));
		-1 != a.options.visibleButtons.indexOf("r") && (a.dom.buttons.r = OAT.Dom.create("div", {}, "oat_winround_resize_b"), OAT.Dom.append([a.dom.td_rb, a.dom.buttons.r]));
		OAT.Dom.append([a.dom.title, a.dom.caption]);
		OAT.Browser.isIE ? (
			OAT.addTextNode(a.dom.container, '<table class="oat_winround_wrapper"><tr><td class="oat_winround_lt"></td><td class="oat_winround_t"></td><td class="oat_winround_rt"></td></tr><tr><td class="oat_winround_l"></td><td class="oat_winround_m"></td><td class="oat_winround_r"></td></tr><tr><td class="oat_winround_lb"></td><td class="oat_winround_b"></td><td class="oat_winround_rb"></td></tr></table>'),
			a.dom.container.childNodes[0].childNodes[0].childNodes[0].childNodes[1].appendChild(a.dom.title), a.dom.container.childNodes[0].childNodes[0].childNodes[1].childNodes[1].appendChild(a.dom.content), a.dom.container.childNodes[0].childNodes[0].childNodes[2].childNodes[1].appendChild(a.dom.status), a.dom.container.childNodes[0].childNodes[0].childNodes[2].childNodes[2].appendChild(a.dom.buttons.r)) : (OAT.Dom.append([a.dom.tr_t, a.dom.td_lt, a.dom.td_t, a.dom.td_rt]), OAT.Dom.append([a.dom.tr_m, a.dom.td_l, a.dom.td_m, a.dom.td_r]), OAT.Dom.append([a.dom.tr_b, a.dom.td_lb, a.dom.td_b, a.dom.td_rb]), OAT.Dom.append([a.dom.table, a.dom.tr_t, a.dom.tr_m, a.dom.tr_b]), OAT.Dom.append([a.dom.td_t, a.dom.title]), OAT.Dom.append([a.dom.td_m, a.dom.content]), OAT.Dom.append([a.dom.td_b, a.dom.status]), OAT.Dom.append([a.dom.container, a.dom.table]));
		a.outerResizeTo = function (b, c) {
			a.dom.container.style.width = b ? b + "px" : "auto";
			a.dom.container.style.height = c ? c + "px" : "auto"
		}
	};
	OAT.WinODS = function (a) {
		OAT.Style.include("winods.css");
		a.dom.container = OAT.Dom.create("div", {
			position: "absolute"
		}, "oat_winods_container");
		a.dom.resizeContainer = a.dom.container;
		a.dom.content = OAT.Dom.create("div", {}, "oat_winods_content");
		a.dom.title = OAT.Dom.create("div", {}, "oat_winods_title");
		a.dom.caption = OAT.Dom.create("span", {}, "oat_winods_caption");
		a.dom.status = OAT.Dom.create("div", {}, "oat_winods_status");
		OAT.Dom.append([a.dom.container, a.dom.title, a.dom.content, a.dom.status]);
		-1 != a.options.visibleButtons.indexOf("c") && (a.dom.buttons.c = OAT.Dom.create("div", {}, "oat_winods_close_b"), OAT.Dom.append([a.dom.title, a.dom.buttons.c]));
		-1 != a.options.visibleButtons.indexOf("r") && (a.dom.buttons.r = OAT.Dom.create("div", {}, "oat_winods_resize_b"), OAT.Dom.append([a.dom.container, a.dom.buttons.r]));
		OAT.Dom.append([a.dom.title, a.dom.caption]);
		a.outerResizeTo = function (b, c) {
			a.dom.container.style.width = b ? b + "px" : "auto";
			a.dom.container.style.height = c ? c + "px" : "auto"
		}
	};
	OAT.WinManager = {
		stackingGroups: {},
		addWindow: function (a, b) {
			if (a in OAT.WinManager.stackingGroups)
				var c = OAT.WinManager.stackingGroups[a];
			else
				c = new OAT.Layers(a), OAT.WinManager.stackingGroups[a] = c
			c.addLayer(b, "click")
		},
		removeWindow: function () {
			if (zI in OAT.WinManager.stackingGroups)
				var a = OAT.WinManager.stackingGroups[zI];
			else
				a = new OAT.Layers(zI), OAT.WinManager.stackingGroups[zI] = a
			a.removeLayer(container)
		}
	};
	try {
		OAT.Loader.featureLoaded("win");
	} catch (ERROR) {

	}

	OAT.Resize = {
		TYPE_X: 1, TYPE_Y: 2, TYPE_XY: 3, element: [], mouse_x: 0, mouse_y: 0, move: function (a) {
			if (OAT.Resize.element.length) {
				for (var e = a.clientX - OAT.Resize.mouse_x, f = a.clientY - OAT.Resize.mouse_y, b = 1, c = 0; c < OAT.Resize.element.length; c++) {
					var d = OAT.Resize.element[c][0], d = OAT.Dom.getWH(d), i = OAT.Resize.element[c][2], g = e, h = f; switch (OAT.Resize.element[c][1]) {
						case OAT.Resize.TYPE_X: h = 0; break; case -OAT.Resize.TYPE_X: g = -e; h = 0; break; case OAT.Resize.TYPE_Y: g = 0; break; case -OAT.Resize.TYPE_Y: g = 0; h = -f; break; case -OAT.Resize.TYPE_XY: g =
							-e, h = -f
					}i(d[0] + g, d[1] + h) && (b = 0)
				} if (b) {
					for (c = 0; c < OAT.Resize.element.length; c++)switch (d = OAT.Resize.element[c][0], OAT.Resize.element[c][1]) { case OAT.Resize.TYPE_X: OAT.Dom.resizeBy(d, e, 0); break; case -OAT.Resize.TYPE_X: OAT.Dom.resizeBy(d, -e, 0); break; case OAT.Resize.TYPE_Y: OAT.Dom.resizeBy(d, 0, f); break; case -OAT.Resize.TYPE_Y: OAT.Dom.resizeBy(d, 0, -f); break; case OAT.Resize.TYPE_XY: OAT.Dom.resizeBy(d, e, f); break; case -OAT.Resize.TYPE_XY: OAT.Dom.resizeBy(d, -e, -f) }OAT.Resize.mouse_x = a.clientX; OAT.Resize.mouse_y =
						a.clientY
				}
			}
		}, up: function () { for (var a = 0; a < OAT.Resize.element.length; a++)OAT.Resize.element[a][3](); OAT.Resize.element = [] }, create: function (a, e, f, b, c) {
			var d = OAT.$(a), a = OAT.$(e), e = function () { return !1 }, i = function () { return !1 }; b && (e = b); c && (i = c); switch (f) { case OAT.Resize.TYPE_XY: d.style.cursor = "nw-resize"; break; case OAT.Resize.TYPE_X: d.style.cursor = "w-resize"; break; case OAT.Resize.TYPE_Y: d.style.cursor = "n-resize" }b = function (a) {
				OAT.Resize.element = d._Resize_movers; OAT.Resize.mouse_x = a.clientX; OAT.Resize.mouse_y = a.clientY;
				a.cancelBubble = !0
			}; d._Resize_movers || (OAT.Dom.attach(d, "mousedown", b), d._Resize_movers = []); d._Resize_movers.push([a, f, e, i])
		}, remove: function (a, e) { var f = OAT.$(a); OAT.$(e); if (f._Resize_movers) { for (var b = -1, c = 0; c < f._Resize_movers.length; c++)f._Resize_movers[c][0] == e && (b = c); -1 != b && f._Resize_movers.splice(b, 1) } }, removeAll: function (a) { a = OAT.$(a); a._Resize_movers && (a._Resize_movers = []) }, createDefault: function (a, e, f) {
			if (OAT.Preferences.allowDefaultResize) {
				var b = OAT.Dom.create("div", {
					position: "absolute", width: "10px",
					height: "10px", right: "0px", fontSize: "1px", bottom: "0px"
				}); a.appendChild(b); OAT.Resize.create(b, a, OAT.Resize.TYPE_XY, e, f); OAT.Dom.hide(b); var c = function () { b._Resize_pending && OAT.Dom.hide(b) }; OAT.Dom.attach(a, "mouseover", function () { OAT.Dom.show(b); b._Resize_pending = 0 }); OAT.Dom.attach(a, "mouseout", function () { b._Resize_pending = 1; setTimeout(c, 2E3) })
			}
		}
	}; OAT.Dom.attach(document, "mousemove", OAT.Resize.move); OAT.Dom.attach(document, "mouseup", OAT.Resize.up);
	try {
		OAT.Loader.featureLoaded("resize");
	} catch (ERROR) {

	}

	OAT.XMLHTTP = function () {
		this.obj = this.iframe = !1;
		this.open = function (a, c, d) {
			this.iframe ? this.temp_src = c : this.obj.open(a, c, d)
		};
		this.send = function (a) {
			this.iframe ? this.ifr.src = this.temp_src : this.obj.send(a)
		};
		this.setResponse = function (a) {
			this.iframe ? OAT.Dom.attach(this.ifr, "load", a) : this.obj.onreadystatechange = a
		};
		this.getResponseText = function () {

		};
		this.getResponseXML = function () {
			return this.iframe ? (alert("IFRAME mode active -> XML data not supported"), "") : this.obj.responseXML
		};
		this.getReadyState = function () {
			return this.iframe ? 4 : this.obj.readyState
		};
		this.getStatus = function () {
			return this.iframe ? 200 : this.obj.status
		};
		this.setRequestHeader = function (a, c) {
			this.iframe || this.obj.setRequestHeader(a, c)
		};
		this.getAllResponseHeaders = function () {
			return !this.iframe ? this.obj.getAllResponseHeaders() : {}
		};
		this.isIframe = function () {
			return this.iframe
		};
		window.XMLHttpRequest ? this.obj = new XMLHttpRequest : window.ActiveXObject && (this.obj = new ActiveXObject("Microsoft.XMLHTTP"));
		this.obj || (this.iframe = !0, this.ifr = OAT.Dom.create("iframe"), this.ifr.style.display = "none", this.ifr.src = "javascript:;", document.body.appendChild(this.ifr))
	};
	OAT.XMLHTTP_supported = function () {
		return !(new OAT.XMLHTTP).isIframe()
	};
	try {
		OAT.Loader.featureLoaded("ajax");
	} catch (ERROR) {

	}


	OAT.AnchorData = { active: !1, window: !1 };
	OAT.Anchor = {
		appendContent: function (b) {
			if (b.content && b.window) {
				"function" == typeof b.content && (b.content = b.content());
				var d = b.window;
				OAT.Dom.clear(d.dom.content);
				d.dom.content.appendChild(b.content); OAT.Anchor.fixSize(d)
			}
		},
		callForData: function (b, d) {
			var e = b.window;
			b.stat = 1;

			b.status && (OAT.addTextNode(e.dom.status, b.status));
			var a = b.datasource;
			if (a) {
			a.connection = b.connection; var f = b.elm.innerHTML, c = function () {
				e.dom.caption.innerHTML = b.elm.innerHTML;
				if (b.title) e.dom.caption.innerHTML = b.title
			}; a.bindRecord(c); a.bindEmpty(c)
			}
			switch (b.result_control) {
				case "grid": c = new OAT.FormObject.grid(0, 0, 0, 1); c.showAll = !0; b.content = c.elm; c.elm.style.position = "relative"; c.init(); a.bindRecord(c.bindRecordCallback); a.bindPage(c.bindPageCallback); a.bindHeader(c.bindHeaderCallback); break; case "form": var h = !1; b.content = OAT.Dom.create("div");
					h = new OAT.Form(b.content, { onDone: function () { e.resizeTo(h.totalWidth + 5, h.totalHeight + 5); b.anchorTo(d[0], d[1]) } }); a.bindFile(function (a) {
						a = OAT.Xml.createXmlDoc(a);
						h.createFromXML(a)
					}); break; case "timeline": c = new OAT.FormObject.timeline(0, 20, 0); b.content = c.elm; c.elm.style.position = "relative"; c.elm.style.width = b.width - 5 + "px"; c.elm.style.height = b.height - 65 + "px"; c.init(); for (var i = 0; i < c.datasources[0].fieldSets.length; i++)c.datasources[0].fieldSets[i].realIndexes = [i]; a.bindPage(c.bindPageCallback)
			}OAT.Anchor.appendContent(b); if (a) {
				a.options.query = a.options.query.replace(/\$link_name/g, f); b.connection.options.endpoint = b.href; b.connection.options.url = b.href; switch (a.type) {
					case OAT.DataSourceData.TYPE_SPARQL: f =
						new OAT.SparqlQuery; f.fromString(a.options.query); f = f.variables.length ? "format=xml" : "format=rdf"; a.options.query = "query=" + encodeURIComponent(a.options.query) + "&" + f; break; case OAT.DataSourceData.TYPE_GDATA: a.options.query = a.options.query ? "q=" + encodeURIComponent(a.options.query) : ""
				}a.advanceRecord(0)
			}
		}, fixSize: function (b) {
			setTimeout(
				function () {
					/*if(OAT.AJAX.requests.length)
						OAT.Anchor.fixSize(b);
					else
						for(var d = OAT.Dom.getWH(b.dom.content)[1]; OAT.Dom.getWH(b.dom.content)[1] + 50 > OAT.Dom.getWH(b.dom.container)[1]; ) {650 > OAT.Dom.getWH(b.dom.container)[0] && (b.dom.container.style.width = OAT.Dom.getWH(b.dom.container)[0] + 100 + "px");
							if(d == OAT.Dom.getWH(b.dom.content)[1]) {
								b.dom.container.style.width = OAT.Dom.getWH(b.dom.container)[0] - 100 + "px";
								300 < OAT.Dom.getWH(b.dom.content)[1] && (b.dom.content.style.height = "300px", b.dom.content.style.overflow = "auto");
								b.dom.container.style.height = OAT.Dom.getWH(b.dom.content)[1] + 40 + "px";
								break
							}
							d = OAT.Dom.getWH(b.dom.content)[1]
						}*/
				}
				, 50)
		}
		, assign: function (b, d) {
			var e = OAT.$(b),
				a = {
					href: !1,
					newHref: "javascript:void(0)",
					connection: !1,
					datasource: !1,
					content: !1,
					status: !1,
					title: !1,
					result_control: "grid",
					activation: "hover",
					width: 340,
					height: !1,
					elm: e,
					window: !1,
					arrow: !1,
					type: OAT.WinData.TYPE_RECT,
					visibleButtons: "cr",
					enabledButtons: "cr",
					template: !1
				},
				f;
			for (f in d)
				a[f] = d[f];
			var c = new OAT.Win({
				outerWidth: a.width,
				outerHeight: a.height,
				title: "",
				type: a.type,
				status: a.status,
				visibleButtons: a.visibleButtons,
				enabledButtons: a.enabledButtons,
				template: a.template,
				containerQuery: a.containerQuery
			});
			OAT.Dom.attach(c.dom.container, "mouseover", function () {
				var a = OAT.AnchorData.active; a && "hover" == a.activation && a.endClose()
			});
			OAT.Dom.attach(c.dom.container, "mouseout", function () {
				var a = OAT.AnchorData.active;
				a && "hover" == a.activation && a.startClose()
			});
			f = OAT.Dom.create("div", {});
			//OAT.Dom.append([c.dom.container, f]);

			//a.arrow = f;
			a.window = c;
			c.close = function () {
				OAT.Dom.hide(c.dom.container)
			};
			c.onclose = c.close;
			c.close();
			a.stat = 0;
			!a.href && "href" in e && (a.href = e.href);
			"a" == e.tagName.toString().toLowerCase() && OAT.Dom.changeHref(e, a.newHref);
			a.displayRef = function (b) {
				var c = a.window;
				c.hide();
				OAT.AnchorData.active = a;
				b = OAT.Dom.eventPos(b);
				OAT.AnchorData.window = c;
				a.stat ? OAT.Anchor.appendContent(a) : OAT.Anchor.callForData(a, b);
				a.activation == "focus" && (b = OAT.Dom.position(e));
				a.anchorTo(b[0], b[1]);
				c.show();
				a.anchorTo(b[0], b[1])
			};
			a.displayRef2 = function (b) {
				var c = a.window;
				c.hide();
				OAT.AnchorData.active = a;
				//b = OAT.Dom.eventPos(b);
				OAT.AnchorData.window = c;
				a.stat ? OAT.Anchor.appendContent(a) : OAT.Anchor.callForData(a, b);
				a.activation == "focus" && (b = OAT.Dom.position(e));
				a.anchorTo(b[0], b[1]);
				c.show();
				a.anchorTo(b[0], b[1])
			};
			a.anchorTo = function (b, c) {
				var e = a.window, d = OAT.Dom.getFreeSpace(b, c), f = OAT.Dom.getWH(e.dom.container);
				if (d[1])
					var j = c - 30 - f[1], g = "bottom";
				else {
					j = c + 30;
					g = "top"
				}
				if (d[0]) {
					d = b + 20 - f[0];
					g = g + "right"
				} else {
					d = b - 30;
					g = g + "left"
				} d < 0 && (d = 10);
				j < 0 && (j = 10);
				//OAT.Dom.addClass(a.arrow, "oat_anchor_arrow_" + g);
				e.moveTo(d, j - 20)
			};
			a.closeRef = function () {

				if (a.closeFlag) {
					a.window.hide();
					OAT.AnchorData.active = false
				}
			};
			a.close = function () { a.window.hide() };
			a.startClose = function () { a.closeFlag = 1; setTimeout(a.closeRef, 1E3) };
			a.endClose = function () { a.closeFlag = 0 };
			switch (a.activation) {
				case "hover": OAT.Dom.attach(e, "mouseover", a.displayRef);
					OAT.Dom.attach(e, "mouseout", a.startClose);
					break; case "click": OAT.Dom.attach(e, "click", a.displayRef);
					break; case "dblclick": OAT.Dom.attach(e, "dblclick", a.displayRef);
					break; case "focus": OAT.Dom.attach(e, "focus", a.displayRef), OAT.Dom.attach(e, "blur", a.close)
			}

			return a

		},


		close: function (b, d) {
			b = OAT.$(b);
			"BODY" != b.tagName && (b.className.match(/^oat_win.+_container$/) ? (OAT.Dom.hide(b), d && this.close(b.parentNode)) : this.close(b.parentNode))
		},
		openAnchor: function () {
			var c = this.window;
			c.hide();
			OAT.AnchorData.active = this;
			b = OAT.Dom.eventPos(b);
			OAT.AnchorData.window = c;
			a.stat ? OAT.Anchor.appendContent(a) : OAT.Anchor.callForData(a, b);
			a.activation == "focus" && (b = OAT.Dom.position(e));
			a.anchorTo(b[0], b[1]);
			c.show();
			a.anchorTo(b[0], b[1])
		}
	};
	try {
		OAT.Loader.featureLoaded("anchor");
	} catch (ERROR) {

	}


	OAT.Animation = function (f, d) {
		var b = this;
		this.elm = OAT.$(f);
		this.options = {
			delay: 50,
			startFunction: function () {
			},
			conditionFunction: function () {
			},
			stepFunction: function () {
			},
			stopFunction: function () {
			}
		};
		for (var e in d)
			b.options[e] = d[e];
		this.step = function () {
			setTimeout(function () {
				b.running && (b.options.conditionFunction(b) ? (b.running = 0, b.options.stopFunction(b), OAT.MSG.send(b, OAT.MSG.ANIMATION_STOP, b)) : (b.options.stepFunction(b), b.step(b)))
			}, b.options.delay)
		};
		this.start = function () {
			b.running = 1;
			b.options.startFunction(b);
			b.step()
		};
		this.stop = function () {
			b.running = 0
		}
	};
	OAT.AnimationSize = function (f, d) {
		var b = this;
		this.options = {
			width: -1,
			height: -1,
			delay: 50,
			speed: 1
		};
		for (var e in d)
			b.options[e] = d[e];
		this.animation = new OAT.Animation(f, {
			delay: b.options.delay,
			startFunction: function (a) {
				a.stepX = 0;
				a.stepY = 0;
				var c = OAT.Dom.getWH(a.elm);
				a.width = c[0];
				a.height = c[1];
				a.diffX = -1 == b.options.width ? 0 : b.options.width - c[0];
				a.diffY = -1 == b.options.height ? 0 : b.options.height - c[1];
				a.signX = 0 <= a.diffX ? 1 : -1;
				a.signY = 0 <= a.diffY ? 1 : -1;
				var c = a.diffX * a.diffX, d = a.diffY * a.diffY;
				a.stepX = a.signX * Math.sqrt(b.options.speed * b.options.speed * c / (c + d));
				a.stepY = a.signY * Math.sqrt(b.options.speed * b.options.speed * d / (c + d))
			},
			stopFunction: function (a) {
			-1 != b.options.width && (a.elm.style.width = b.options.width + "px");
				-1 != b.options.height && (a.elm.style.height = b.options.height + "px")
			},
			conditionFunction: function (a) {
				var c = 0 < a.signX ? a.width >= b.options.width : a.width <= b.options.width, a = 0 < a.signY ? a.height >= b.options.height : a.height <= b.options.height;
				-1 == b.options.width && (c = 1);
				-1 == b.options.height && (a = 1);
				return c && a
			},
			stepFunction: function (a) {
				a.width += a.stepX;
				a.height += a.stepY;
				var c = parseInt(a.width), d = parseInt(a.height);
				-1 != b.options.width && (a.elm.style.width = (0 <= c ? c : 0) + "px");
				-1 != b.options.height && (a.elm.style.height = (0 <= d ? d : 0) + "px")
			}
		});
		this.start = b.animation.start;
		this.stop = b.animation.stop
	};
	OAT.AnimationPosition = function (f, d) {
		var b = this;
		this.options = {
			left: -1,
			top: -1,
			delay: 50,
			speed: 1
		};
		for (var e in d)
			b.options[e] = d[e];
		this.animation = new OAT.Animation(f, {
			delay: b.options.delay,
			startFunction: function (a) {
				a.stepX = 0;
				a.stepY = 0;
				var c = OAT.Dom.getLT(a.elm);
				a.left = c[0];
				a.top = c[1];
				a.diffX = -1 == b.options.left ? 0 : b.options.left - c[0];
				a.diffY = -1 == b.options.top ? 0 : b.options.top - c[1];
				a.signX = 0 <= a.diffX ? 1 : -1;
				a.signY = 0 <= a.diffY ? 1 : -1;
				var c = a.diffX * a.diffX, d = a.diffY * a.diffY;
				a.stepX = a.signX * Math.sqrt(b.options.speed * b.options.speed * c / (c + d));
				a.stepY = a.signY * Math.sqrt(b.options.speed * b.options.speed * d / (c + d))
			},
			stopFunction: function (a) {
			-1 != b.options.left && (a.elm.style.left = b.options.left + "px");
				-1 != b.options.top && (a.elm.style.top = b.options.top + "px")
			},
			conditionFunction: function (a) {
				var c = 0 < a.signX ? a.left >= b.options.left : a.left <= b.options.left, a = 0 < a.signY ? a.top >= b.options.top : a.top <= b.options.top;
				-1 == b.options.left && (c = 1);
				-1 == b.options.top && (a = 1);
				return c && a
			},
			stepFunction: function (a) {
				a.left += a.stepX;
				a.top += a.stepY;
				var c = parseInt(a.left), d = parseInt(a.top);
				-1 != b.options.left && (a.elm.style.left = c + "px");
				-1 != b.options.top && (a.elm.style.top = d + "px")
			}
		});
		this.start = b.animation.start;
		this.stop = b.animation.stop
	};
	OAT.AnimationOpacity = function (f, d) {
		var b = this;
		this.options = {
			opacity: 1,
			delay: 50,
			speed: 0.1
		};
		for (var e in d)
			b.options[e] = d[e];
		this.animation = new OAT.Animation(f, {
			delay: b.options.delay,
			startFunction: function (a) {
				a.opacity = 1;
				OAT.Browser.isGecko && (a.opacity = parseFloat(OAT.Dom.style(a.elm, "opacity")));
				if (OAT.Browser.isIE) {
					var c = OAT.Dom.style(a.elm, "filter").match(/alpha\(opacity=([^\)]+)\)/);
					c && (a.opacity = parseFloat(c[1]) / 100)
				}
				a.step_ = 1;
				a.diff = b.options.opacity - a.opacity;
				a.sign = 0 <= a.diff ? 1 : -1;
				a.step_ = a.sign * b.options.speed
			},
			stopFunction: function (a) {
				OAT.Style.opacity(a.elm, b.options.opacity)
			},
			conditionFunction: function (a) {
				return 0 < a.sign ? a.opacity + 1.0E-4 >= b.options.opacity : a.opacity - 1.0E-4 <= b.options.opacity
			},
			stepFunction: function (a) {
				a.opacity += a.step_;
				OAT.Style.opacity(a.elm, a.opacity)
			}
		});
		this.start = b.animation.start;
		this.stop = b.animation.stop
	};
	OAT.AnimationCSS = function (f, d) {
		var b = this;
		this.options = {
			delay: 50,
			property: !1,
			start: 0,
			step: 1,
			stop: 10
		};
		for (var e in d)
			b.options[e] = d[e];
		this.animation = new OAT.Animation(f, {
			delay: b.options.delay,
			startFunction: function (a) {
				a[b.options.property] = b.options.start;
				a.elm.style[b.options.property] = b.options.start
			},
			stopFunction: function (a) {
				a.elm.style[b.options.property] = b.options.stop
			},
			conditionFunction: function (a) {
				return a[b.options.property] == b.options.stop
			},
			stepFunction: function (a) {
				a[b.options.property] += b.options.step;
				a.elm.style[b.options.property] = a[b.options.property]
			}
		});
		this.start = b.animation.start;
		this.stop = b.animation.stop
	};
	try {
		OAT.Loader.featureLoaded("animation");
	} catch (ERROR) {

	}

	OAT.getURL = function () {
		try {
			var dir = location.href.substring(0, location.href.lastIndexOf('\/'));
			var dom = dir;
			if (dom.substr(0, 7) == 'http:\/\/')
				dom = dom.substr(7);
			var path = '';
			var pos = dom.indexOf('\/');
			if (pos > -1) {
				path = dom.substr(pos + 1);
				dom = dom.substr(0, pos);
			}
			var page = location.href.substring(dir.length + 1, location.href.length + 1);
			var pos = page.indexOf('?');
			if (pos > -1) {
				page = page.substring(0, pos);
			}
			pos = page.indexOf('#');
			if (pos > -1) {
				page = page.substring(0, pos);
			}
			var ext = '';
			pos = page.indexOf('.');
			if (pos > -1) {
				ext = page.substring(pos + 1);
				page = page.substr(0, pos);
			}
			var file = page;
			if (ext != '')
				file += '.' + ext;
			if (file == '')
				page = 'index';
			args = location.search.substr(1).split("?");

			return path + page;
		} catch (ERROR) {
			return "";
		}
	}

	OAT.PartialSort = function (data, a, z, index, arrayLength, sortIntMemory) {
		var partialArray = []
		for (var p = 0; p <= z - a; p++) {
			partialArray[p] = data[a + p]
		}

		if (sortIntMemory[index]) {
			partialArray.sort((function (index) {
				return function (a, b) {
					return (parseInt(a[index]) === parseInt(b[index]) ? 0 : (parseInt(a[index]) < parseInt(b[index]) ? -1 : 1));
				};
			})(index));
		} else {
			partialArray.sort((function (index) {
				return function (a, b) {
					return (a[index] === b[index] ? 0 : (a[index] < b[index] ? -1 : 1));
				};
			})(index));
		}

		//recursive call
		if (index < arrayLength - 1) {
			var actualVal = partialArray[0][index];
			var initPos = 0;
			for (var i = 0; i < partialArray.length; i++) {
				if ((actualVal != partialArray[i][index])) {
					actualVal = partialArray[i][index]
					partialArray = OAT.PartialSort(partialArray, initPos, i - 1, index + 1, arrayLength, sortIntMemory)
					initPos = i;
				} else if ((i == partialArray.length - 1)) {
					partialArray = OAT.PartialSort(partialArray, initPos, i, index + 1, arrayLength, sortIntMemory)
				}
			}
		}

		for (var p = a; p <= z; p++) {
			data[p] = partialArray[p - a]
		}
		return data
	}





}
/* END OF FILE - ..\oatPivot\oat_statistic.src.js - */
/* START OF FILE - ..\oatPivot\oat_tablePagination.src.js - */
if (!gx.util.browser.isIE() || 8 < gx.util.browser.ieVersion()) {

	OAT.tablePagination = function (container, settings) {
		var defaults = {
				rowsPerPage: 5,
				currPage: 1,
				jstype: "pivot",
				optionsForRows: [5, 10, 25, 50, 100],
				ignoreRows: [],
				topNav: false
		};
		settings = jQuery.extend(defaults, settings);
		return container.each(function () {
				var table = jQuery(this)[0];
				var totalPagesId, currPageId, rowsPerPageId, firstPageId, prevPageId, nextPageId, lastPageId;
				totalPagesId = '#tablePagination_totalPages';
				currPageId = '#tablePagination_currPage';
				rowsPerPageId = '#' + settings.controlName + 'tablePagination_rowsPerPage';
				firstPageId = '#tablePagination_firstPage';
				prevPageId = '#tablePagination_prevPage';
				nextPageId = '#tablePagination_nextPage';
				lastPageId = '#tablePagination_lastPage';
				var tblLocation = (defaults.topNav) ? "prev" : "next";

				try {
					defaults.rowsPerPage = parseInt(defaults.rowsPerPage);
				} catch (ERROR) {
					defaults.rowsPerPage = 10;
				}

				var possibleTableRows = jQuery.makeArray(jQuery('tbody tr', table));
				var tableRows = jQuery.grep(possibleTableRows, function (value, index) {
					return (jQuery.inArray(value, defaults.ignoreRows) == -1);
				}, false)

				var numRows = tableRows.length
				var totalPages = resetTotalPages();
				var currPageNumber = (defaults.currPage > totalPages) ? 1 : defaults.currPage;
				if (jQuery.inArray(defaults.rowsPerPage, defaults.optionsForRows) == -1)
					defaults.optionsForRows.push(defaults.rowsPerPage);

				function hideOtherPages(pageNum) {
					if (pageNum == 0 || pageNum > totalPages)
						return;
					var startIndex = (pageNum - 1) * defaults.rowsPerPage;
					var endIndex = (startIndex + defaults.rowsPerPage - 1);
					jQuery(tableRows).show(); //show all rows
					var filteredRow = 0;
					for (var i = 0; i < tableRows.length; i++) {
						if (i < startIndex || i > endIndex) {
							jQuery(tableRows[i]).hide() //hide row because of pagination
						}
						if (settings.jstype === "pivot") {
							while (tableRows[i].childNodes[0].getAttribute('pivotCorrect') != null) {
								tableRows[i].deleteCell(0);
							}
						}
						if (tableRows[i].getAttribute("visibQ") == "tf") {
							jQuery(tableRows[i]).hide() //hide row is filtered
						}
					}

					if ((settings.jstype === "pivot") && (startIndex > 1)) /* if previuos rows have a inital span td */ {
						if ((tableRows[startIndex].childNodes[0].getAttribute('spanCorrect') === null)
							|| (tableRows[startIndex].childNodes[0].getAttribute('spanCorrect') === "0")) {
							var previuos = tableRows[startIndex - 1];

							for (var prw = 1; prw < startIndex + 1; prw++) {
								if (startIndex - prw < 0) break;
								var previuos = tableRows[startIndex - prw];

								for (var itemtd = 0; itemtd < previuos.childNodes.length; itemtd++) { /*begin "for" for previous row*/

									if ((previuos.childNodes[itemtd] != undefined) && (previuos.childNodes[itemtd].getAttribute('rowspan') != undefined) && (previuos.childNodes[itemtd].getAttribute('rowspan') > 1)) {
										if ((previuos.childNodes[itemtd].getAttribute('rowspan') <= prw) || (previuos.childNodes[itemtd].getAttribute('hidden') != null)) {
											break;
										}

										for (var posR = startIndex; posR < startIndex + (previuos.childNodes[itemtd].getAttribute('rowspan') - prw); posR++) {
											var oldspan = 0;
											var newcolspan = 0;
											var plusspan = 0;
											if ((tableRows[posR].childNodes[0].getAttribute('colspan') != undefined) && (tableRows[posR].childNodes[0].getAttribute('colspan') != null)) {
												oldspan = parseInt(tableRows[posR].childNodes[0].getAttribute('colspan'));
											} else {
												oldspan = 1;
											}
											var plusspan;
											if ((previuos.childNodes[itemtd].getAttribute('colspan') != undefined) && (previuos.childNodes[itemtd].getAttribute('colspan') != null)) {
												plusspan = parseInt(previuos.childNodes[itemtd].getAttribute('colspan'));
											} else {
												plusspan = 1;
											}

											var newcolspan = plusspan + oldspan;
											var newCell = tableRows[posR].insertCell(itemtd);
											newCell.setAttribute('pivotCorrect', true);
											newCell.setAttribute('colspan', plusspan);
											newCell.setAttribute('class', 'pivotAdd');
											newCell.setAttribute('style', previuos.childNodes[itemtd].style.cssText + 'border-bottom: none; border-top: none;');
											if (posR === startIndex) {
												newCell.innerHTML = previuos.childNodes[itemtd].innerHTML;
												newCell.className = previuos.childNodes[itemtd].className + " pivotAdd";
												var imgCollapse = newCell.childNodes[0];
												newCell.removeChild(imgCollapse)
											}
											/*if the modified item has rowSpan > 1 then jump "rowSpan-1" rows*/
											if ((tableRows[posR].childNodes[0].getAttribute('rowspan') != undefined) && (tableRows[posR].childNodes[0].getAttribute('rowspan') != null)) {
												posR = posR + parseInt(tableRows[posR].childNodes[0].getAttribute('rowspan')) - 1;
											}

										}

									}

								}/*end for*/
							}

						}

					}

				}

				function resetTotalPages() {
					var preTotalPages = Math.round(numRows / defaults.rowsPerPage);
					var totalPages = (preTotalPages * defaults.rowsPerPage < numRows) ? preTotalPages + 1 : preTotalPages;
					if (jQuery(table)[tblLocation]().find(totalPagesId).length > 0)
						jQuery(table)[tblLocation]().find(totalPagesId).html(totalPages);
					return totalPages;
				}

				function resetCurrentPage(currPageNum) { //here sets the value of the current page
					if (currPageNum < 1 || currPageNum > totalPages)
						return;
					currPageNumber = currPageNum;
					hideOtherPages(currPageNumber);

					(currPageNumber > 1) ? jQuery("#tablePagination_firstPage,#tablePagination_prevPage").removeClass("disabled_pivot_button") :
						jQuery("#tablePagination_firstPage,#tablePagination_prevPage").addClass("disabled_pivot_button");

					(currPageNumber != totalPages) ? jQuery("#tablePagination_nextPage,#tablePagination_lastPage").removeClass("disabled_pivot_button") :
						jQuery("#tablePagination_nextPage,#tablePagination_lastPage").addClass("disabled_pivot_button");

					jQuery(table)[tblLocation]().find(currPageId).val(currPageNumber)
				}

				function resetPerPageValues() {
					var isRowsPerPageMatched = false;
					var optsPerPage = defaults.optionsForRows;
					optsPerPage.sort(function (a, b) { return a - b; });
					var perPageDropdown = jQuery(table)[tblLocation]().find(rowsPerPageId)[0];
					perPageDropdown.length = 0;
					for (var i = 0; i < optsPerPage.length; i++) {
						if (optsPerPage[i] == defaults.rowsPerPage) {
							perPageDropdown.options[i] = new Option(optsPerPage[i], optsPerPage[i], true, true);
							isRowsPerPageMatched = true;
						}
						else {
							perPageDropdown.options[i] = new Option(optsPerPage[i], optsPerPage[i]);
						}
					}

					if (tableRows.length <= defaults.rowsPerPage) {
						jQuery('#' + settings.controlName + '_tablePagination').css('display', 'none');
					} else {
						jQuery('#' + settings.controlName + '_tablePagination').css('display', '');
					}

					if ((totalPages == 1) || (totalPages == 0)) {
						jQuery('#' + settings.controlName + '_tablePagination_paginater').css('display', 'none');
					} else {
						jQuery('#' + settings.controlName + '_tablePagination_paginater').css('display', '');
					}
				}

				function createPaginationElements() {
					var size = 1;
					try {
						var mul = 100;
						if (((gx.util.browser.webkit) /*|| gx.util.browser.isIE()*/) &&
							(!(jQuery("#" + settings.controlName).closest(".gxwebcomponent").length > 0))) {
							mul = mul * 100;
						}

						if (currPageNumber > mul * 10) {
							if (jQuery("#" + settings.controlName).closest(".gxwebcomponent").length > 0) {
								size = size + 2;
							}

							var d = currPageNumber / mul
							while (d > 10) {
								d = d / 10;
								size++;
							}
						}
					} catch (ERROR) { }


					var prevButtonsClass = (currPageNumber == 1) ? " disabled_pivot_button" : ""
					var postButtonsClass = (currPageNumber == totalPages) ? " disabled_pivot_button" : ""

					var ua = navigator.userAgent.toLowerCase();
					var isAndroid = ua.indexOf("android") > -1;
					if (!((gx.util.browser.isIPad() || gx.util.browser.isIPhone() || isAndroid) || (false))) {
						var htmlBuffer = [];
						htmlBuffer.push("<div id='" + settings.controlName + "_tablePagination' class='pivot_pag_div'>");
						htmlBuffer.push("<span id='tablePagination_perPage'>");

						htmlBuffer.push("<select id='" + settings.controlName + "tablePagination_rowsPerPage'><option value='5'>5</option></select>");

						htmlBuffer.push(" " + gx.getMessage("GXPL_QViewerJSPerPage") + " ");
						htmlBuffer.push("</span>");
						htmlBuffer.push("<span id='" + settings.controlName + "_tablePagination_paginater'>");
							
						htmlBuffer.push("<div class='pagefirst " + prevButtonsClass + "' id='tablePagination_firstPage' >");
						htmlBuffer.push('<i class="material-icons">first_page</i>')
						htmlBuffer.push("</div>")
							
						htmlBuffer.push("<div class='pageprev " + prevButtonsClass + "' id='tablePagination_prevPage' >");
						htmlBuffer.push('<i class="material-icons">navigate_before</i>')
						htmlBuffer.push("</div>")
							
						htmlBuffer.push("<span style=''>&nbsp;" + gx.getMessage("GXPL_QViewerJSPage") + "&nbsp;</span>");
						htmlBuffer.push("<input id='tablePagination_currPage' type='input' value='" + currPageNumber + "' size='" + size + "'>");
						htmlBuffer.push("<span>&nbsp;" + gx.getMessage("GXPL_QViewerJSOf") + "</span><span id='tablePagination_totalPages'>&nbsp;" + totalPages + "</span>");
						
						htmlBuffer.push("<div class='pagenext " + postButtonsClass + "' id='tablePagination_nextPage' >");
						htmlBuffer.push('<i class="material-icons">navigate_next</i>')
						htmlBuffer.push("</div>")
						
						htmlBuffer.push("<div class='pagelast " + postButtonsClass + "' id='tablePagination_lastPage'>");
						htmlBuffer.push('<i class="material-icons">last_page</i>')
						htmlBuffer.push("</div>")
						
						htmlBuffer.push("</span>");
						htmlBuffer.push("</div>");
						return htmlBuffer.join("").toString();
					} else {
						var htmlBuffer = [];
						htmlBuffer.push("<div id='" + settings.controlName + "_tablePagination' class='pivot_pag_div pivot_pag_div_sd'>");
						htmlBuffer.push("<span id='tablePagination_perPage'>");

						htmlBuffer.push("<select id='" + settings.controlName + "tablePagination_rowsPerPage'><option value='5'>5</option></select>");

						htmlBuffer.push(" " + gx.getMessage("GXPL_QViewerJSPerPage") + " ");
						htmlBuffer.push("</span>");
						htmlBuffer.push("<span id='" + settings.controlName + "_tablePagination_paginater'>");
						
						htmlBuffer.push("<div class='pagefirst " + prevButtonsClass + "' id='tablePagination_firstPage' >");
						htmlBuffer.push('<i class="material-icons">first_page</i>')
						htmlBuffer.push("</div>")
						
						htmlBuffer.push("<div class='pageprev " + prevButtonsClass + "' id='tablePagination_prevPage' >");
						htmlBuffer.push('<i class="material-icons">navigate_before</i>')
						htmlBuffer.push("</div>")
						
						
						htmlBuffer.push("<span style=''>&nbsp;" + gx.getMessage("GXPL_QViewerJSPage") + "&nbsp;</span>");
						htmlBuffer.push("<input id='tablePagination_currPage' type='input' value='" + currPageNumber + "' size='" + size + "'>");
						htmlBuffer.push("<span>&nbsp;" + gx.getMessage("GXPL_QViewerJSOf") + "</span><span id='tablePagination_totalPages'>&nbsp;" + totalPages + "</span>");
						
						htmlBuffer.push("<div class='pagenext " + postButtonsClass + "' id='tablePagination_nextPage' >");
						htmlBuffer.push('<i class="material-icons">navigate_next</i>')
						htmlBuffer.push("</div>")
						
						htmlBuffer.push("<div class='pagelast " + postButtonsClass + "' id='tablePagination_lastPage'>");
						htmlBuffer.push('<i class="material-icons">last_page</i>')
						htmlBuffer.push("</div>")
						
						
						htmlBuffer.push("</span>");
						htmlBuffer.push("</div>");
						return htmlBuffer.join("").toString();

					}

				}

				if (jQuery(table)[tblLocation]().find(totalPagesId).length == 0) {
					if (defaults.topNav) {
						jQuery(this).before(createPaginationElements());
					} else {
						jQuery(this).after(createPaginationElements());
						if (totalPages == 1) {
							jQuery('#' + settings.controlName + '_tablePagination_paginater').css('display', 'none');
						} else {
							jQuery('#' + settings.controlName + '_tablePagination_paginater').css('display', '');
						}
					}
				}
				else {
					jQuery(table)[tblLocation]().find(currPageId).val(currPageNumber);
				}
				resetPerPageValues();
				hideOtherPages(currPageNumber);

				jQuery(table)[tblLocation]().find(firstPageId).bind('click', function (e) {
					resetCurrentPage(1)
				});

				jQuery(table)[tblLocation]().find(prevPageId).bind('click', function (e) {
					resetCurrentPage(currPageNumber - 1)
				});

				jQuery(table)[tblLocation]().find(nextPageId).bind('click', function (e) {
					resetCurrentPage(parseInt(currPageNumber) + 1)
				});

				jQuery(table)[tblLocation]().find(lastPageId).bind('click', function (e) {
					resetCurrentPage(totalPages)
				});

				jQuery(table)[tblLocation]().find(currPageId).bind('change', function (e) {
					resetCurrentPage(this.value)
				});

				jQuery(table)[tblLocation]().find(rowsPerPageId).bind('change', function (e) {
					defaults.rowsPerPage = parseInt(this.value, 10);
					totalPages = resetTotalPages();
					resetCurrentPage(1)
					if (totalPages == 1) {
						jQuery('#' + settings.controlName + '_tablePagination_paginater').css('display', 'none');
					} else {
						jQuery('#' + settings.controlName + '_tablePagination_paginater').css('display', '');
					}
				});

			})
	}
	

	var currPageNumber = [];

	OAT.partialTablePagination = function (container, settings) {
		var defaults = {
				rowsPerPage: 5,
				currPage: 1,
				jstype: "pivot",
				optionsForRows: [5, 10, 25, 50, 100],
				ignoreRows: [],
				topNav: false,
				cantPages: 10
		};
		settings = jQuery.extend(defaults, settings);
		
		return container.each(function () {
				var table = jQuery(this)[0];
				var totalPagesId, currPageId, rowsPerPageId, firstPageId, prevPageId, nextPageId, lastPageId;
				totalPagesId = '#tablePagination_totalPages';
				currPageId = '#tablePagination_currPage';
				rowsPerPageId = '#' + settings.controlName + 'tablePagination_rowsPerPage';
				firstPageId = '#tablePagination_firstPage';
				prevPageId = '#tablePagination_prevPage';
				nextPageId = '#tablePagination_nextPage';
				lastPageId = '#tablePagination_lastPage';
				var tblLocation = (defaults.topNav) ? "prev" : "next";

				try {
					defaults.rowsPerPage = parseInt(defaults.rowsPerPage);
				} catch (ERROR) {
					defaults.rowsPerPage = 10;
				}

				var possibleTableRows = jQuery.makeArray(jQuery('tbody tr', table));
				var tableRows = jQuery.grep(possibleTableRows, function (value, index) {
					return (jQuery.inArray(value, defaults.ignoreRows) == -1);
				}, false)

				var numRows = tableRows.length
				var totalPages = resetTotalPages();
				currPageNumber[settings.controlName] = (defaults.currPage > totalPages) ? 1 : defaults.currPage;
				if (jQuery.inArray(defaults.rowsPerPage, defaults.optionsForRows) == -1)
					defaults.optionsForRows.push(defaults.rowsPerPage);

				function resetTotalPages() {
					return defaults.cantPages;
				}

				function resetCurrentPage(currPageNum, recalculateCantPages) {	//sets current page value
					if (currPageNum < 1 || (currPageNum > jQuery("#" + settings.controlName + "_tablePagination_paginater #tablePagination_totalPages")[0].innerHTML.replace("&nbsp;", "")))
						return;
					currPageNumber[settings.controlName] = currPageNum;
					jQuery(table)[tblLocation]().find(currPageId).val(currPageNumber[settings.controlName]);

					(currPageNumber[settings.controlName] > 1) ? jQuery("#tablePagination_firstPage,#tablePagination_prevPage").removeClass("disabled_pivot_button") :
						jQuery("#tablePagination_firstPage,#tablePagination_prevPage").addClass("disabled_pivot_button");

					(currPageNumber[settings.controlName] != totalPages) ? jQuery("#tablePagination_nextPage,#tablePagination_lastPage").removeClass("disabled_pivot_button") :
						jQuery("#tablePagination_nextPage,#tablePagination_lastPage").addClass("disabled_pivot_button");


					if ((settings.control) && (settings.jstype == "table")) {
						var cantRows = (recalculateCantPages) ? defaults.rowsPerPage : OAT_JS.grid.gridData[settings.controlUcId].rowsPerPage
						settings.control.getDataForTable(settings.controlUcId, currPageNum, cantRows, recalculateCantPages, "", "", "", "", "", true)
					} else if (settings.control) {
						var cantRows = (recalculateCantPages) ? defaults.rowsPerPage : settings.control.rowsPerPage
						settings.control.getDataForPivot(settings.controlUcId, currPageNum, cantRows, recalculateCantPages, "", "", "", "", "", true)
					}
				}

				function resetPerPageValues() {
					var isRowsPerPageMatched = false;
					var optsPerPage = defaults.optionsForRows;
					optsPerPage.sort(function (a, b) { return a - b; });
					var perPageDropdown = jQuery(table)[tblLocation]().find(rowsPerPageId)[0];
					perPageDropdown.length = 0;
					for (var i = 0; i < optsPerPage.length; i++) {
						if (optsPerPage[i] == defaults.rowsPerPage) {
							perPageDropdown.options[i] = new Option(optsPerPage[i], optsPerPage[i], true, true);
							isRowsPerPageMatched = true;
						}
						else {
							perPageDropdown.options[i] = new Option(optsPerPage[i], optsPerPage[i]);
						}
					}



					if ((totalPages == 1) || (totalPages == 0)) {
						jQuery('#' + settings.controlName + '_tablePagination_paginater').css('display', 'none');
					} else {
						jQuery('#' + settings.controlName + '_tablePagination_paginater').css('display', '');
					}
				}

				function createPaginationElements() {
					var size = 1;
					try {
						var mul = 100;
						if (((gx.util.browser.webkit) /*|| gx.util.browser.isIE()*/) &&
							(!(jQuery("#" + settings.controlName).closest(".gxwebcomponent").length > 0))) {
							mul = mul * 100;
						}

						if (currPageNumber[settings.controlName] > mul * 10) {
							if (jQuery("#" + settings.controlName).closest(".gxwebcomponent").length > 0) {
								size = size + 2;
							}

							var d = currPageNumber[settings.controlName] / mul
							while (d > 10) {
								d = d / 10;
								size++;
							}
						}
					} catch (ERROR) { }


					var prevButtonsClass = (currPageNumber[settings.controlName] == 1) ? " disabled_pivot_button" : ""
					var postButtonsClass = (currPageNumber[settings.controlName] == totalPages) ? " disabled_pivot_button" : ""


					var ua = navigator.userAgent.toLowerCase();
					var isAndroid = ua.indexOf("android") > -1;
					if (!((gx.util.browser.isIPad() || gx.util.browser.isIPhone() || isAndroid) || (false))) {
						var htmlBuffer = [];
						htmlBuffer.push("<div id='" + settings.controlName + "_tablePagination' class='pivot_pag_div'>");
						htmlBuffer.push("<span id='tablePagination_perPage'>");

						htmlBuffer.push("<select id='" + settings.controlName + "tablePagination_rowsPerPage'></select>");

						htmlBuffer.push(" " + gx.getMessage("GXPL_QViewerJSPerPage") + " ");
						htmlBuffer.push("</span>");
						htmlBuffer.push("<span id='" + settings.controlName + "_tablePagination_paginater'>");
							
						htmlBuffer.push("<div class='pagefirst " + prevButtonsClass + "' id='tablePagination_firstPage' >");
						htmlBuffer.push('<i class="material-icons">first_page</i>')
						htmlBuffer.push("</div>")
							
						htmlBuffer.push("<div class='pageprev " + prevButtonsClass + "' id='tablePagination_prevPage' >");
						htmlBuffer.push('<i class="material-icons">navigate_before</i>')
						htmlBuffer.push("</div>")
							
						htmlBuffer.push("<span style=''>&nbsp;" + gx.getMessage("GXPL_QViewerJSPage") + "&nbsp;</span>");
						htmlBuffer.push("<input id='tablePagination_currPage' type='input' value='" + currPageNumber[settings.controlName] + "' size='" + size + "'>");
						htmlBuffer.push("<span>&nbsp;" + gx.getMessage("GXPL_QViewerJSOf") + "</span><span id='tablePagination_totalPages'>&nbsp;" + totalPages + "</span>");
						
						htmlBuffer.push("<div class='pagenext " + postButtonsClass + "' id='tablePagination_nextPage' >");
						htmlBuffer.push('<i class="material-icons">navigate_next</i>')
						htmlBuffer.push("</div>")
						
						htmlBuffer.push("<div class='pagelast " + postButtonsClass + "' id='tablePagination_lastPage'>");
						htmlBuffer.push('<i class="material-icons">last_page</i>')
						htmlBuffer.push("</div>")
						
						htmlBuffer.push("</span>");
						htmlBuffer.push("</div>");
						return htmlBuffer.join("").toString();
					} else {
						var htmlBuffer = [];
						htmlBuffer.push("<div id='" + settings.controlName + "_tablePagination' class='pivot_pag_div pivot_pag_div_sd'>");
						htmlBuffer.push("<span id='tablePagination_perPage'>");

						htmlBuffer.push("<select id='" + settings.controlName + "tablePagination_rowsPerPage'><option value='5'>5</option></select>");

						htmlBuffer.push(" " + gx.getMessage("GXPL_QViewerJSPerPage") + " ");
						htmlBuffer.push("</span>");
						htmlBuffer.push("<span id='" + settings.controlName + "_tablePagination_paginater'>");
						
						htmlBuffer.push("<div class='pagefirst " + prevButtonsClass + "' id='tablePagination_firstPage' >");
						htmlBuffer.push('<i class="material-icons">first_page</i>')
						htmlBuffer.push("</div>")
						
						htmlBuffer.push("<div class='pageprev " + prevButtonsClass + "' id='tablePagination_prevPage' >");
						htmlBuffer.push('<i class="material-icons">navigate_before</i>')
						htmlBuffer.push("</div>")
						
						
						htmlBuffer.push("<span style=''>&nbsp;" + gx.getMessage("GXPL_QViewerJSPage") + "&nbsp;</span>");
						htmlBuffer.push("<input id='tablePagination_currPage' type='input' value='" + currPageNumber[settings.controlName] + "' size='" + size + "'>");
						htmlBuffer.push("<span>&nbsp;" + gx.getMessage("GXPL_QViewerJSOf") + "</span><span id='tablePagination_totalPages'>&nbsp;" + totalPages + "</span>");
						
						htmlBuffer.push("<div class='pagenext " + postButtonsClass + "' id='tablePagination_nextPage' >");
						htmlBuffer.push('<i class="material-icons">navigate_next</i>')
						htmlBuffer.push("</div>")
						
						htmlBuffer.push("<div class='pagelast " + postButtonsClass + "' id='tablePagination_lastPage'>");
						htmlBuffer.push('<i class="material-icons">last_page</i>')
						htmlBuffer.push("</div>")
						
						
						htmlBuffer.push("</span>");
						htmlBuffer.push("</div>");
						return htmlBuffer.join("").toString();
					}
				}

				if (jQuery(table)[tblLocation]().find(totalPagesId).length == 0) {
					if (defaults.topNav) {
						jQuery(this).before(createPaginationElements());
					} else {
						jQuery(this).after(createPaginationElements());
					}
				}
				else {
					jQuery(table)[tblLocation]().find(currPageId).val(currPageNumber[settings.controlName]);
				}
				resetPerPageValues();

				jQuery(table)[tblLocation]().find(firstPageId).bind('click', function (e) {
					resetCurrentPage(1, false)
				});

				jQuery(table)[tblLocation]().find(prevPageId).bind('click', function (e) {
					resetCurrentPage(currPageNumber[settings.controlName] - 1, false)
				});

				jQuery(table)[tblLocation]().find(nextPageId).bind('click', function (e) {
					resetCurrentPage(parseInt(currPageNumber[settings.controlName]) + 1, false)  //bind event 
				});

				jQuery(table)[tblLocation]().find(lastPageId).bind('click', function (e) {
					resetCurrentPage(parseInt(jQuery("#" + settings.controlName + "_tablePagination_paginater #tablePagination_totalPages")[0].textContent.replace("&nbsp;", "")), false);
				});

				jQuery(table)[tblLocation]().find(currPageId).bind('change', function (e) {
					resetCurrentPage(parseInt(this.value, 10), false)
				});

				jQuery(table)[tblLocation]().find(rowsPerPageId).bind('change', function (e) {
					defaults.rowsPerPage = parseInt(this.value, 10);
					totalPages = resetTotalPages();
					resetCurrentPage(1, true);
				});

			})
		
		
	}

}






/* END OF FILE - ..\oatPivot\oat_tablePagination.src.js - */
