← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 20953: PT noext.

 

------------------------------------------------------------
revno: 20953
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2015-11-04 16:10:58 +0100
message:
  PT noext.
modified:
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/index2.html
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/core2.js


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/index2.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/index2.html	2015-10-27 15:20:53 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/index2.html	2015-11-04 15:10:58 +0000
@@ -17,9 +17,11 @@
         <div class="spinner"></div>
     </div>
 
+<!--
     <script type="text/javascript" src="../dhis-web-commons/javascripts/ext/ext-all.js"></script>
     <script type="text/javascript" src="../dhis-web-commons/javascripts/ext-ux/layout/component/form/MultiSelect.js"></script>
     <script type="text/javascript" src="../dhis-web-commons/javascripts/ext-ux/form/MultiSelect.js"></script>
+-->
 
     <script type="text/javascript" src="../dhis-web-commons/javascripts/jQuery/jquery.min.js"></script>
     <script type="text/javascript" src="../dhis-web-commons/javascripts/jQuery/calendars/jquery.calendars.min.js"></script>

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/core2.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/core2.js	2015-11-04 11:01:11 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/core2.js	2015-11-04 15:10:58 +0000
@@ -11,21 +11,24 @@
             isObject,
             isEmpty,
             isDefined,
+            isIE,
+            numberConstrain,
             arrayFrom,
             arrayClean,
             arrayPluck,
-            arrayIndexOf,
             arrayUnique,
             arrayContains,
             clone,
-            enumerables = ['valueOf', 'toLocaleString', 'toString', 'constructor'];
-
-        // enumerables
-        (function() {
-            for (i in { toString: 1 }) {
-                enumerables = null;
-            }
-        })();
+            uuid,
+            enumerables = function() {
+                var enu = ['valueOf', 'toLocaleString', 'toString', 'constructor'];
+
+                for (var i in { toString: 1 }) {
+                    enu = null;
+                }
+
+                return enu;
+            }();
 
         isString = function(param) {
             return typeof param === 'string';
@@ -53,6 +56,7 @@
             return typeof param === 'boolean';
         };
 
+        // dep: isArray
         isEmpty = function(array, allowEmptyString) {
             return (array == null) || (!allowEmptyString ? array === '' : false) || (isArray(array) && array.length === 0);
         };
@@ -66,23 +70,94 @@
             return type === 'string' || type === 'number' || type === 'boolean';
         };
 
+        isIE = function() {
+            var ua = window.navigator.userAgent;
+
+            // test values
+            // IE 10: ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)';
+            // IE 11: ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko';
+            // IE 12 / Spartan: ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0';
+
+            var msie = ua.indexOf('MSIE ');
+            if (msie > 0) {
+                // IE 10 or older => return version number
+                return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
+            }
+
+            var trident = ua.indexOf('Trident/');
+            if (trident > 0) {
+                // IE 11 => return version number
+                var rv = ua.indexOf('rv:');
+                return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
+            }
+
+            var edge = ua.indexOf('Edge/');
+                if (edge > 0) {
+                // IE 12 => return version number
+                return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
+            }
+
+            // other browser
+            return false;
+        };
+
+        numberConstrain = function(number, min, max) {
+            number = parseFloat(number);
+
+            if (!isNaN(min)) {
+                number = Math.max(number, min);
+            }
+            if (!isNaN(max)) {
+                number = Math.min(number, max);
+            }
+            return number;
+        };
+
+        // dep: isArray
         arrayFrom = function(param, isNewRef) {
+            var toArray = function(iterable, start, end) {
+                if (!iterable || !iterable.length) {
+                    return [];
+                }
+
+                if (typeof iterable === 'string') {
+                    iterable = iterable.split('');
+                }
+
+                if (supportsSliceOnNodeList) {
+                    return slice.call(iterable, start || 0, end || iterable.length);
+                }
+
+                var array = [],
+                    i;
+
+                start = start || 0;
+                end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;
+
+                for (i = start; i < end; i++) {
+                    array.push(iterable[i]);
+                }
+
+                return array;
+            };
+
             if (param === undefined || param === null) {
                 return [];
             }
 
-            if (Ext.isArray(param)) {
+            if (isArray(param)) {
                 return (isNewRef) ? slice.call(param) : param;
             }
 
             var type = typeof param;
             if (param && param.length !== undefined && type !== 'string' && (type !== 'function' || !param.apply)) {
-                return ExtArray.toArray(param);
+                return toArray(param);
             }
 
             return [param];
         };
 
+        // dep: isEmpty
         arrayClean = function(array) {
             var results = [],
                 i = 0,
@@ -113,21 +188,6 @@
             return newArray;
         };
 
-        arrayIndexOf = ('indexOf' in Array.prototype) ? function(array, item, from) {
-            return Array.prototype.indexOf.call(array, item, from);
-         } : function(array, item, from) {
-            var i, len = array.length;
-
-            for (i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++) {
-                if (array[i] === item) {
-                    return i;
-                }
-            }
-
-            return -1;
-        };
-
-        // dep: arrayIndexOf
         arrayUnique = function(array) {
             var newArray = [],
                 i = 0,
@@ -137,7 +197,7 @@
             for (; i < len; i++) {
                 item = array[i];
 
-                if (arrayIndexOf(newArray, item) === -1) {
+                if (newArray.indexOf(item) === -1) {
                     newArray.push(item);
                 }
             }
@@ -145,19 +205,8 @@
             return newArray;
         };
 
-        // dep: arrayIndexOf
-        arrayContains = ('indexOf' in Array.prototype) ? function(array, item) {
+        arrayContains = function(array, item) {
             return Array.prototype.indexOf.call(array, item) !== -1;
-        } : function(array, item) {
-            var i, len;
-
-            for (i = 0, len = array.length; i < len; i++) {
-                if (array[i] === item) {
-                    return true;
-                }
-            }
-
-            return false;
         };
 
         clone = function(item) {
@@ -182,14 +231,14 @@
                 clone = [];
 
                 while (i--) {
-                    clone[i] = Ext.clone(item[i]);
+                    clone[i] = clone(item[i]);
                 }
             }
             else if (type === '[object Object]' && item.constructor === Object) {
                 clone = {};
 
                 for (key in item) {
-                    clone[key] = Ext.clone(item[key]);
+                    clone[key] = clone(item[key]);
                 }
 
                 if (enumerables) {
@@ -205,6 +254,14 @@
             return clone || item;
         };
 
+        uuid = function () {
+            var s4 = function() {
+                return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
+            };
+
+            return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
+        };
+
         NS.isString = isString;
         NS.isNumber = isNumber;
         NS.isNumeric = isNumeric;
@@ -213,13 +270,15 @@
         NS.isObject = isObject;
         NS.isEmpty = isEmpty;
         NS.isDefined = isDefined;
+        NS.isIE = isIE;
+        NS.numberConstrain = numberConstrain;
         NS.arrayFrom = arrayFrom;
         NS.arrayClean = arrayClean;
         NS.arrayPluck = arrayPluck;
-        NS.arrayIndexOf = arrayIndexOf;
         NS.arrayUnique = arrayUnique;
         NS.arrayContains = arrayContains;
         NS.clone = clone;
+        NS.uuid = uuid;
     })();
 
     // date manager TODO import
@@ -642,6 +701,16 @@
                     });
                 };
 
+                t.getDimensionNames = function() {
+                    var names = [];
+
+                    this.forEach(function(dimension) {
+                        names.push(dimension.dimension);
+                    });
+
+                    return names;
+                };
+
                 t.sorted = function() {
                     return NS.clone(this).sort(function(a, b) { return a.dimension > b.dimension;});
                 };
@@ -682,7 +751,7 @@
 
                 t.parentGraphMap = NS.isObject(config.parentGraphMap) ? config.parentGraphMap : null;
 
-                if (Ext.isObject(config.program)) {
+                if (NS.isObject(config.program)) {
                     t.program = config.program;
                 }
 
@@ -731,7 +800,7 @@
                 $.extend(t, forceApplyConfig);
 
                 // uninitialized
-                t.dimensionNameIdsMap;
+                t.dimensionNameRecordIdsMap;
             };
 
             Layout.prototype.log = function(text, noError) {
@@ -774,9 +843,9 @@
                 return isSorted ? dimensions.sort(function(a, b) {return a.dimension > b.dimension;}) : dimensions;
             };
 
-            Layout.prototype.getDimensionNameIdsMap = function() {
-                if (this.dimensionNameIdsMap) {
-                    return this.dimensionNameIdsMap;
+            Layout.prototype.getDimensionNameRecordIdsMap = function() {
+                if (this.dimensionNameRecordIdsMap) {
+                    return this.dimensionNameRecordIdsMap;
                 }
 
                 var map = {};
@@ -785,7 +854,7 @@
                     map[dimension.dimension] = dimension.getRecordIds();
                 });
 
-                return this.dimensionNameIdsMap = map;
+                return this.dimensionNameRecordIdsMap = map;
             };
 
             // dep 2
@@ -918,7 +987,7 @@
                     text;
 
                 if (NS.arrayContains([413, 414], statusCode)) {
-                    if (NS.isIE) {
+                    if (NS.isIE()) {
                         text = 'Too many items selected (url has ' + url.length + ' characters). Internet Explorer accepts maximum 2048 characters.';
                     }
                     else {
@@ -1031,8 +1100,28 @@
                 return this.metaData.names[id];
             };
 
+            Response.prototype.getHierarchyNameById = function(id, isHierarchy, isHtml) {
+				var metaData = response.metaData,
+					name = '';
+
+				if (isHierarchy) {
+					var a = NS.arrayClean(metaData.ouHierarchy[id].split('/'));
+					a.shift();
+
+					for (var i = 0; i < a.length; i++) {
+						name += (isHtml ? '<span class="text-weak">' : '') + metaData.names[a[i]] + (isHtml ? '</span>' : '') + ' / ';
+					}
+				}
+
+                return name;
+            };
+
             // dep 1
 
+            Response.prototype.getItemName = function(id, isHierarchy, isHtml) {
+                return this.getHierarchyNameById(id, isHierarchy) + this.getNameById(id);
+            };
+
             Response.prototype.getValueHeader = function() {
                 return this.getHeaderByName('value');
             };
@@ -1043,10 +1132,1131 @@
                 return this.getValueHeader().getIndex();
             };
         })();
+
+        //todo TableAxis
+        (function() {
+            var TableAxis = NS.Api.TableAxis = function(layout, type) {
+				var dimensionNames,
+					spanType,
+					aDimensions = [],
+					nAxisWidth = 1,
+					nAxisHeight,
+					aaUniqueFloorIds,
+					aUniqueFloorWidth = [],
+					aAccFloorWidth = [],
+					aFloorSpan = [],
+					aaGuiFloorIds = [],
+					aaAllFloorIds = [],
+					aCondoId = [],
+					aaAllFloorObjects = [],
+					uuidObjectMap = {};
+
+				if (type === 'col') {
+					dimensionNames = layout.columns.getDimensionNames();
+					spanType = 'colSpan';
+				}
+				else if (type === 'row') {
+					dimensionNames = layout.rows.getDimensionNames();
+					spanType = 'rowSpan';
+				}
+
+				if (!(NS.isArray(dimensionNames) && dimensionNames.length)) {
+					return;
+				}
+	//dimensionNames = ['pe', 'ou'];
+
+				// aDimensions: array of dimension objects with dimensionName property
+                dimensionNames.forEach(function(name) {
+                    aDimensions.push({
+						dimensionName: name
+					});
+                });
+	//aDimensions = [{
+		//dimensionName: 'pe'
+	//}]
+
+				// aaUniqueFloorIds: array of arrays with unique ids for each dimension floor
+				aaUniqueFloorIds = function() {
+					var a = [];
+
+                    aDimensions.forEach(function(dimension) {
+                        a.push(layout.getDimensionNameRecordIdsMap()[dimension.dimensionName]);
+                    });
+
+                    return a;
+				}();
+	//aaUniqueFloorIds	= [ [de-id1, de-id2, de-id3],
+	//					    [pe-id1],
+	//					    [ou-id1, ou-id2, ou-id3, ou-id4] ]
+
+				// nAxisHeight
+				nAxisHeight = aaUniqueFloorIds.length;
+	//nAxisHeight = 3
+
+
+				// aUniqueFloorWidth, nAxisWidth, aAccFloorWidth
+				for (var i = 0, nUniqueFloorWidth; i < nAxisHeight; i++) {
+					nUniqueFloorWidth = aaUniqueFloorIds[i].length;
+
+					aUniqueFloorWidth.push(nUniqueFloorWidth);
+					nAxisWidth = nAxisWidth * nUniqueFloorWidth;
+					aAccFloorWidth.push(nAxisWidth);
+				}
+	//aUniqueFloorWidth	= [3, 1, 4]
+	//nAxisWidth		= 12 (3 * 1 * 4)
+	//aAccFloorWidth	= [3, 3, 12]
+
+				// aFloorSpan
+				for (var i = 0; i < nAxisHeight; i++) {
+					if (aUniqueFloorWidth[i] === 1) {
+						if (i === 0) { // if top floor, set maximum span
+							aFloorSpan.push(nAxisWidth);
+						}
+						else {
+							if (layout.hideEmptyRows && type === 'row') {
+								aFloorSpan.push(nAxisWidth / aAccFloorWidth[i]);
+							}
+							else { //if just one item and not top level, use same span as top level
+								aFloorSpan.push(aFloorSpan[0]);
+							}
+						}
+					}
+					else {
+						aFloorSpan.push(nAxisWidth / aAccFloorWidth[i]);
+					}
+				}
+	//aFloorSpan = [4, 12, 1]
+
+
+				// aaGuiFloorIds
+				aaGuiFloorIds.push(aaUniqueFloorIds[0]);
+
+				if (nAxisHeight.length > 1) {
+					for (var i = 1, a, n; i < nAxisHeight; i++) {
+						a = [];
+						n = aUniqueFloorWidth[i] === 1 ? aUniqueFloorWidth[0] : aAccFloorWidth[i-1];
+
+						for (var j = 0; j < n; j++) {
+							a = a.concat(aaUniqueFloorIds[i]);
+						}
+
+						aaGuiFloorIds.push(a);
+					}
+				}
+	//aaGuiFloorIds	= [ [d1, d2, d3], (3)
+	//					[p1, p2, p3, p4, p5, p1, p2, p3, p4, p5, p1, p2, p3, p4, p5], (15)
+	//					[o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2...] (30)
+	//		  	  	  ]
+
+				// aaAllFloorIds
+				for (var i = 0, aAllFloorIds, aUniqueFloorIds, span, factor; i < nAxisHeight; i++) {
+					aAllFloorIds = [];
+					aUniqueFloorIds = aaUniqueFloorIds[i];
+					span = aFloorSpan[i];
+					factor = nAxisWidth / (span * aUniqueFloorIds.length);
+
+					for (var j = 0; j < factor; j++) {
+						for (var k = 0; k < aUniqueFloorIds.length; k++) {
+							for (var l = 0; l < span; l++) {
+								aAllFloorIds.push(aUniqueFloorIds[k]);
+							}
+						}
+					}
+
+					aaAllFloorIds.push(aAllFloorIds);
+				}
+	//aaAllFloorIds	= [ [d1, d1, d1, d1, d1, d1, d1, d1, d1, d1, d2, d2, d2, d2, d2, d2, d2, d2, d2, d2, d3, d3, d3, d3, d3, d3, d3, d3, d3, d3], (30)
+	//					[p1, p2, p3, p4, p5, p1, p2, p3, p4, p5, p1, p2, p3, p4, p5, p1, p2, p3, p4, p5, p1, p2, p3, p4, p5, p1, p2, p3, p4, p5], (30)
+	//					[o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2, o1, o2] (30)
+	//		  	  	  ]
+
+				// aCondoId
+				for (var i = 0, id; i < nAxisWidth; i++) {
+					id = '';
+
+					for (var j = 0; j < nAxisHeight; j++) {
+						id += aaAllFloorIds[j][i];
+					}
+
+					if (id) {
+						aCondoId.push(id);
+					}
+				}
+	//aCondoId = [ id11+id21+id31, id12+id22+id32, ... ]
+
+
+				// allObjects
+				for (var i = 0, allFloor; i < aaAllFloorIds.length; i++) {
+					allFloor = [];
+
+					for (var j = 0, obj; j < aaAllFloorIds[i].length; j++) {
+						obj = {
+							id: aaAllFloorIds[i][j],
+							uuid: NS.uuid(),
+							dim: i,
+							axis: type
+						};
+
+						// leaf?
+						if (i === aaAllFloorIds.length - 1) {
+							obj.leaf = true;
+						}
+
+						allFloor.push(obj);
+					}
+
+					aaAllFloorObjects.push(allFloor);
+				}
+
+				// add span and children
+				for (var i = 0, aAboveFloorObjects, doorIds, uniqueDoorIds; i < aaAllFloorObjects.length; i++) {
+                    doorIds = [];
+
+					for (var j = 0, obj, doorCount = 0, oldestObj; j < aaAllFloorObjects[i].length; j++) {
+
+						obj = aaAllFloorObjects[i][j];
+                        doorIds.push(obj.id);
+
+						if (doorCount === 0) {
+
+							// span
+							obj[spanType] = aFloorSpan[i];
+
+							// children
+                            if (obj.leaf) {
+                                obj.children = 0;
+                            }
+
+							// first sibling
+							obj.oldest = true;
+
+							// root?
+							if (i === 0) {
+								obj.root = true;
+							}
+
+							// tmp oldest uuid
+							oldestObj = obj;
+						}
+
+						obj.oldestSibling = oldestObj;
+
+						if (++doorCount === aFloorSpan[i]) {
+							doorCount = 0;
+						}
+					}
+
+                    // set above floor door children to number of unique door ids on this floor
+                    if (i > 0) {
+                        aAboveFloorObjects = aaAllFloorObjects[i-1];
+                        uniqueDoorIds = NS.arrayUnique(doorIds);
+
+                        for (var j = 0; j < aAboveFloorObjects.length; j++) {
+                            aAboveFloorObjects[j].children = uniqueDoorIds.length;
+                        }
+                    }
+				}
+
+				// add parents if more than 1 floor
+				if (nAxisHeight > 1) {
+					for (var i = 1, aAllFloor; i < nAxisHeight; i++) {
+						aAllFloor = aaAllFloorObjects[i];
+
+						//for (var j = 0, obj, doorCount = 0, span = aFloorSpan[i - 1], parentObj = aaAllFloorObjects[i - 1][0]; j < aAllFloor.length; j++) {
+						for (var j = 0, doorCount = 0, span = aFloorSpan[i - 1]; j < aAllFloor.length; j++) {
+							aAllFloor[j].parent = aaAllFloorObjects[i - 1][j];
+
+							//doorCount++;
+
+							//if (doorCount === span) {
+								//parentObj = aaAllFloorObjects[i - 1][j + 1];
+								//doorCount = 0;
+							//}
+						}
+					}
+				}
+
+				// add uuids array to leaves
+				if (aaAllFloorObjects.length) {
+
+					// set span to second lowest span number: if aFloorSpan == [15,3,15,1], set span to 3
+					var nSpan = nAxisHeight > 1 ? support.prototype.array.sort(NS.clone(aFloorSpan))[1] : nAxisWidth,
+						aAllFloorObjectsLast = aaAllFloorObjects[aaAllFloorObjects.length - 1];
+
+					for (var i = 0, leaf, parentUuids, obj, leafUuids = []; i < aAllFloorObjectsLast.length; i++) {
+						leaf = aAllFloorObjectsLast[i];
+						leafUuids.push(leaf.uuid);
+						parentUuids = [];
+						obj = leaf;
+
+						// get the uuid of the oldest sibling
+						while (obj.parent) {
+							obj = obj.parent;
+							parentUuids.push(obj.oldestSibling.uuid);
+						}
+
+						// add parent uuids to leaf
+						leaf.uuids = NS.clone(parentUuids);
+
+						// add uuid for all leaves
+						if (leafUuids.length === nSpan) {
+							for (var j = (i - nSpan) + 1, leaf; j <= i; j++) {
+								leaf = aAllFloorObjectsLast[j];
+								leaf.uuids = leaf.uuids.concat(leafUuids);
+							}
+
+							leafUuids = [];
+						}
+					}
+				}
+
+				// populate uuidObject map
+				for (var i = 0; i < aaAllFloorObjects.length; i++) {
+					for (var j = 0, object; j < aaAllFloorObjects[i].length; j++) {
+						object = aaAllFloorObjects[i][j];
+
+						uuidObjectMap[object.uuid] = object;
+					}
+				}
+
+				return {
+					type: type,
+					items: aDimensions,
+					xItems: {
+						unique: aaUniqueFloorIds,
+						gui: aaGuiFloorIds,
+						all: aaAllFloorIds
+					},
+					objects: {
+						all: aaAllFloorObjects
+					},
+					ids: aCondoId,
+					span: aFloorSpan,
+					dims: nAxisHeight,
+					size: nAxisWidth,
+					uuidObjectMap: uuidObjectMap
+				};
+			};
+        })();
+
+        //todo Table
+        (function() {
+            var Table = NS.Api.Table = function(layout, response, colAxis, rowAxis) {
+				var getRoundedHtmlValue,
+					getTdHtml,
+					doSubTotals,
+					doRowTotals,
+                    doColTotals,
+                    doSortableColumnHeaders,
+					getColAxisHtmlArray,
+					getRowHtmlArray,
+					rowAxisHtmlArray,
+					getColTotalHtmlArray,
+					getGrandTotalHtmlArray,
+					getTotalHtmlArray,
+					getHtml,
+					getUniqueFactor = function(xAxis) {
+                        var unique;
+
+						if (!xAxis) {
+							return null;
+						}
+
+						unique = xAxis.xItems.unique;
+
+						if (unique) {
+							return unique.length < 2 ? 1 : (xAxis.size / unique[0].length);
+						}
+
+						return null;
+					},
+					colUniqueFactor = getUniqueFactor(colAxis),
+					rowUniqueFactor = getUniqueFactor(rowAxis),
+					valueItems = [],
+					valueObjects = [],
+					totalColObjects = [],
+					uuidDimUuidsMap = {},
+					//isLegendSet = NS.isObject(xLayout.legendSet) && NS.isArray(xLayout.legendSet.legends) && xLayout.legendSet.legends.length,
+					isLegendSet = false,
+                    tdCount = 0,
+                    htmlArray;
+
+				xResponse.sortableIdObjects = [];
+
+				getRoundedHtmlValue = function(value, dec) {
+					dec = dec || 2;
+					return parseFloat(support.prototype.number.roundIf(value, 2)).toString();
+				};
+
+				getTdHtml = function(config, metaDataId) {
+					var bgColor,
+						legends,
+						colSpan,
+						rowSpan,
+						htmlValue,
+						displayDensity,
+						fontSize,
+						isNumeric = NS.isObject(config) && NS.isString(config.type) && config.type.substr(0,5) === 'value' && !config.empty,
+						isValue = isNumeric && config.type === 'value',
+						cls = '',
+						html = '',
+                        getHtmlValue;
+
+                    getHtmlValue = function(config) {
+                        var str = config.htmlValue,
+                            n = parseFloat(config.htmlValue);
+
+                        if (config.collapsed) {
+                            return '';
+                        }
+
+                        if (isValue) {
+                            if (NS.isBoolean(str)) {
+                                return str;
+                            }
+
+                            //if (!NS.isNumber(n) || n != str || new Date(str).toString() !== 'Invalid Date') {
+                            if (!NS.isNumber(n) || n != str) {
+                                return str;
+                            }
+
+                            return n;
+                        }
+
+                        return str || '';
+                    }
+
+					if (!NS.isObject(config)) {
+						return '';
+					}
+
+                    if (config.hidden || config.collapsed) {
+                        return '';
+                    }
+
+                    // number of cells
+                    tdCount = tdCount + 1;
+
+					// background color from legend set
+					if (isValue && layout.legendSet) {
+						var value = parseFloat(config.value);
+						legends = layout.legendSet.legends;
+
+						for (var i = 0; i < legends.length; i++) {
+							if (NS.numberConstrain(value, legends[i].startValue, legends[i].endValue) === value) {
+								bgColor = legends[i].color;
+							}
+						}
+					}
+
+					colSpan = config.colSpan ? 'colspan="' + config.colSpan + '" ' : '';
+					rowSpan = config.rowSpan ? 'rowspan="' + config.rowSpan + '" ' : '';
+                    htmlValue = getHtmlValue(config);
+					htmlValue = config.type !== 'dimension' ? support.prototype.number.prettyPrint(htmlValue, layout.digitGroupSeparator) : htmlValue;
+
+					cls += config.hidden ? ' td-hidden' : '';
+					cls += config.collapsed ? ' td-collapsed' : '';
+					cls += isValue ? ' pointer' : '';
+					//cls += bgColor ? ' legend' : (config.cls ? ' ' + config.cls : '');
+                    cls += config.cls ? ' ' + config.cls : '';
+
+					// if sorting
+					if (NS.isString(metaDataId)) {
+						cls += ' td-sortable';
+
+						xResponse.sortableIdObjects.push({
+							id: metaDataId,
+							uuid: config.uuid
+						});
+					}
+
+					html += '<td ' + (config.uuid ? ('id="' + config.uuid + '" ') : '');
+					html += ' class="' + cls + '" ' + colSpan + rowSpan;
+
+					//if (bgColor && isValue) {
+                        //html += 'style="color:' + bgColor + ';padding:' + displayDensity + '; font-size:' + fontSize + ';"' + '>' + htmlValue + '</td>';
+						//html += '>';
+						//html += '<div class="legendCt">';
+						//html += '<div class="number ' + config.cls + '" style="padding:' + displayDensity + '; padding-right:3px; font-size:' + fontSize + '">' + htmlValue + '</div>';
+						//html += '<div class="arrowCt ' + config.cls + '">';
+						//html += '<div class="arrow" style="border-bottom:8px solid transparent; border-right:8px solid ' + bgColor + '">&nbsp;</div>';
+						//html += '</div></div></div></td>';
+					//}
+					//else {
+						html += 'style="' + (bgColor && isValue ? 'color:' + bgColor + '; ' : '') + '">' + htmlValue + '</td>';
+					//}
+
+					return html;
+				};
+
+                doColTotals = function() {
+					return !!layout.showColTotals;
+				};
+
+				doRowTotals = function() {
+					return !!layout.showRowTotals;
+				};
+
+				doColSubTotals = function() {
+					return !!layout.showColSubTotals && rowAxis && rowAxis.dims > 1;
+				};
+
+				doRowSubTotals = function() {
+					return !!layout.showRowSubTotals && colAxis && colAxis.dims > 1;
+				};
+
+				doSortableColumnHeaders = function() {
+					return (rowAxis && rowAxis.dims === 1);
+				};
+
+				getColAxisHtmlArray = function() {
+					var a = [],
+                        columnDimensionNames = colAxis ? layout.columns.getDimensionNames() : [],
+                        rowDimensionNames = rowAxis ? layout.rows.getDimensionNames() : [],
+						getEmptyHtmlArray;
+
+                    getEmptyNameTdConfig = function(config) {
+                        config = config || {};
+
+                        return getTdHtml({
+                            cls: config.cls ? ' ' + config.cls : 'pivot-empty',
+                            colSpan: config.colSpan ? config.colSpan : 1,
+                            rowSpan: config.rowSpan ? config.rowSpan : 1,
+                            htmlValue: config.htmlValue ? config.htmlValue : '&nbsp;'
+                        });
+                    };
+
+                    getEmptyHtmlArray = function(i) {
+                        var a = [];
+
+                        // if not the intersection cell
+                        if (i < colAxis.dims - 1) {
+                            if (rowAxis && rowAxis.dims) {
+                                for (var j = 0; j < rowAxis.dims - 1; j++) {
+                                    a.push(getEmptyNameTdConfig({
+                                        cls: 'pivot-dim-label'
+                                    }));
+                                }
+                            }
+
+                            a.push(getEmptyNameTdConfig({
+                                cls: 'pivot-dim-label',
+                                htmlValue: dimConf.objectNameMap[columnDimensionNames[i]].name
+                            }));
+                        }
+                        else {
+                            if (rowAxis && rowAxis.dims) {
+                                for (var j = 0; j < rowAxis.dims - 1; j++) {
+                                    a.push(getEmptyNameTdConfig({
+                                        cls: 'pivot-dim-label',
+                                        htmlValue: dimConf.objectNameMap[rowDimensionNames[j]].name
+                                    }));
+                                }
+                            }
+
+                            a.push(getEmptyNameTdConfig({
+                                cls: 'pivot-dim-label',
+                                htmlValue: (rowAxis ? dimConf.objectNameMap[rowDimensionNames[j]].name : '') + (colAxis && rowAxis ? '&nbsp;/&nbsp;' : '') + (colAxis ? dimConf.objectNameMap[columnDimensionNames[i]].name : '')
+                            }));
+                        }
+
+                        return a;
+                    };
+
+					if (!colAxis) {
+
+                        // show row dimension labels
+                        if (rowAxis && layout.showDimensionLabels) {
+                            var dimLabelHtml = [];
+
+                            // labels from row object names
+                            for (var i = 0; i < rowDimensionNames.length; i++) {
+                                dimLabelHtml.push(getEmptyNameTdConfig({
+                                    cls: 'pivot-dim-label',
+                                    htmlValue: dimConf.objectNameMap[rowDimensionNames[i]].name
+                                }));
+                            }
+
+                            // pivot-transparent-column unnecessary
+
+                            a.push(dimLabelHtml);
+                        }
+
+						return a;
+					}
+
+					// for each col dimension
+					for (var i = 0, dimHtml; i < colAxis.dims; i++) {
+						dimHtml = [];
+
+                        if (layout.showDimensionLabels) {
+                            dimHtml = dimHtml.concat(getEmptyHtmlArray(i));
+                        }
+                        else if (i === 0) {
+							dimHtml.push(colAxis && rowAxis ? getEmptyNameTdConfig({
+                                colSpan: rowAxis.dims,
+                                rowSpan: colAxis.dims
+                            }) : '');
+						}
+
+						for (var j = 0, obj, spanCount = 0, condoId, totalId; j < colAxis.size; j++) {
+							spanCount++;
+							condoId = null;
+							totalId = null;
+
+							obj = colAxis.objects.all[i][j];
+							obj.type = 'dimension';
+							obj.cls = 'pivot-dim';
+							obj.noBreak = false;
+							obj.hidden = !(obj.rowSpan || obj.colSpan);
+							obj.htmlValue = response.getItemName(obj.id, layout.showHierarchy, true);
+
+							// sortable column headers. last dim only.
+							if (i === colAxis.dims - 1 && doSortableColumnHeaders()) {
+
+								//condoId = colAxis.ids[j].split('-').join('');
+								condoId = colAxis.ids[j];
+							}
+
+							dimHtml.push(getTdHtml(obj, condoId));
+
+							if (i === 0 && spanCount === colAxis.span[i] && doRowSubTotals() ) {
+								dimHtml.push(getTdHtml({
+									type: 'dimensionSubtotal',
+									cls: 'pivot-dim-subtotal cursor-default',
+									rowSpan: colAxis.dims,
+									htmlValue: '&nbsp;'
+								}));
+
+								spanCount = 0;
+							}
+
+							if (i === 0 && (j === colAxis.size - 1) && doRowTotals()) {
+								totalId = doSortableColumnHeaders() ? 'total_' : null;
+
+								dimHtml.push(getTdHtml({
+									uuid: NS.uuid(),
+									type: 'dimensionTotal',
+									cls: 'pivot-dim-total',
+									rowSpan: colAxis.dims,
+									htmlValue: 'Total'
+								}, totalId));
+							}
+						}
+
+						a.push(dimHtml);
+					}
+
+					return a;
+				};
+
+				getRowHtmlArray = function() {
+					var a = [],
+						axisAllObjects = [],
+						xValueObjects,
+						totalValueObjects = [],
+						mergedObjects = [],
+						valueItemsCopy,
+						colAxisSize = colAxis ? colAxis.size : 1,
+						rowAxisSize = rowAxis ? rowAxis.size : 1,
+						recursiveReduce;
+
+					recursiveReduce = function(obj) {
+						if (!obj.children) {
+							obj.collapsed = true;
+
+							if (obj.parent) {
+								obj.parent.oldestSibling.children--;
+							}
+						}
+
+						if (obj.parent) {
+							recursiveReduce(obj.parent.oldestSibling);
+						}
+					};
+
+					// dimension
+					if (rowAxis) {
+						for (var i = 0, row; i < rowAxis.size; i++) {
+							row = [];
+
+							for (var j = 0, obj, newObj; j < rowAxis.dims; j++) {
+								obj = rowAxis.objects.all[j][i];
+								obj.type = 'dimension';
+								obj.cls = 'pivot-dim td-nobreak' + (layout.showHierarchy ? ' align-left' : '');
+								obj.noBreak = true;
+								obj.hidden = !(obj.rowSpan || obj.colSpan);
+								obj.htmlValue = response.getItemName(obj.id, layout.showHierarchy, true);
+
+								row.push(obj);
+							}
+
+							axisAllObjects.push(row);
+						}
+					}
+                    else {
+                        if (layout.showDimensionLabels) {
+                            axisAllObjects.push([{
+                                type: 'transparent',
+                                cls: 'pivot-transparent-row'
+                            }]);
+                        }
+                    }
+
+
+	//axisAllObjects = [ [ dim, dim ]
+	//				     [ dim, dim ]
+	//				     [ dim, dim ]
+	//				     [ dim, dim ] ];
+
+					// value
+					for (var i = 0, valueItemsRow, valueObjectsRow, idValueMap = xResponse.idValueMap; i < rowAxisSize; i++) {
+						valueItemsRow = [];
+						valueObjectsRow = [];
+
+						for (var j = 0, id, value, responseValue, htmlValue, empty, uuid, uuids; j < colAxisSize; j++) {
+							empty = false;
+							uuids = [];
+
+							// meta data uid
+							id = ((colAxis ? colAxis.ids[j] : '') + (rowAxis ? rowAxis.ids[i] : ''));
+
+                            // value html element id
+							uuid = NS.uuid();
+
+							// get uuids array from colaxis/rowaxis leaf
+							if (colAxis) {
+								uuids = uuids.concat(colAxis.objects.all[colAxis.dims - 1][j].uuids);
+							}
+							if (rowAxis) {
+								uuids = uuids.concat(rowAxis.objects.all[rowAxis.dims - 1][i].uuids);
+							}
+
+                            // value, htmlValue
+                            responseValue = idValueMap[id];
+
+							if (NS.isDefined(responseValue)) {
+                                value = service.response.getValue(responseValue);
+                                htmlValue = responseValue;
+							}
+							else {
+								value = 0;
+								htmlValue = '&nbsp;';
+								empty = true;
+							}
+
+							valueItemsRow.push(value);
+							valueObjectsRow.push({
+								uuid: uuid,
+								type: 'value',
+								cls: 'pivot-value' + (empty ? ' cursor-default' : ''),
+								value: value,
+								htmlValue: htmlValue,
+								empty: empty,
+								uuids: uuids
+							});
+
+							// map element id to dim element ids
+							uuidDimUuidsMap[uuid] = uuids;
+						}
+
+						valueItems.push(valueItemsRow);
+						valueObjects.push(valueObjectsRow);
+					}
+
+					// totals
+					if (colAxis && doRowTotals()) {
+						for (var i = 0, empty = [], total = 0; i < valueObjects.length; i++) {
+							for (j = 0, obj; j < valueObjects[i].length; j++) {
+								obj = valueObjects[i][j];
+
+								empty.push(obj.empty);
+								total += obj.value;
+							}
+
+							// row totals
+							totalValueObjects.push({
+								type: 'valueTotal',
+								cls: 'pivot-value-total',
+								value: total,
+								htmlValue: NS.arrayContains(empty, false) ? getRoundedHtmlValue(total) : '',
+								empty: !NS.arrayContains(empty, false)
+							});
+
+							// add row totals to idValueMap to make sorting on totals possible
+							if (doSortableColumnHeaders()) {
+								var totalId = 'total_' + rowAxis.ids[i],
+									isEmpty = !NS.arrayContains(empty, false);
+
+								xResponse.idValueMap[totalId] = isEmpty ? null : total;
+							}
+
+							empty = [];
+							total = 0;
+						}
+					}
+
+					// hide empty rows (dims/values/totals)
+					if (colAxis && rowAxis) {
+						if (layout.hideEmptyRows) {
+							for (var i = 0, valueRow, isValueRowEmpty, dimLeaf; i < valueObjects.length; i++) {
+								valueRow = valueObjects[i];
+								isValueRowEmpty = !NS.arrayContains(NS.arrayPluck(valueRow, 'empty'), false);
+
+								// if value row is empty
+								if (isValueRowEmpty) {
+
+									// hide values by adding collapsed = true to all items
+									for (var j = 0; j < valueRow.length; j++) {
+										valueRow[j].collapsed = true;
+									}
+
+									// hide totals by adding collapsed = true to all items
+									if (doRowTotals()) {
+										totalValueObjects[i].collapsed = true;
+									}
+
+									// hide/reduce parent dim span
+									dimLeaf = axisAllObjects[i][rowAxis.dims-1];
+									recursiveReduce(dimLeaf);
+								}
+							}
+						}
+					}
+
+                    xValueObjects = valueObjects;
+
+					// col subtotals
+					if (doRowSubTotals()) {
+						var tmpValueObjects = [];
+
+						for (var i = 0, row, rowSubTotal, colCount; i < xValueObjects.length; i++) {
+							row = [];
+							rowSubTotal = 0;
+							colCount = 0;
+
+							for (var j = 0, item, collapsed = [], empty = []; j < xValueObjects[i].length; j++) {
+								item = xValueObjects[i][j];
+								rowSubTotal += item.value;
+								empty.push(!!item.empty);
+								collapsed.push(!!item.collapsed);
+								colCount++;
+
+								row.push(item);
+
+								if (colCount === colUniqueFactor) {
+									var isEmpty = !NS.arrayContains(empty, false);
+									row.push({
+										type: 'valueSubtotal',
+										cls: 'pivot-value-subtotal' + (isEmpty ? ' cursor-default' : ''),
+										value: rowSubTotal,
+										htmlValue: isEmpty ? '&nbsp;' : getRoundedHtmlValue(rowSubTotal),
+										empty: isEmpty,
+										collapsed: !NS.arrayContains(collapsed, false)
+									});
+
+									colCount = 0;
+									rowSubTotal = 0;
+									empty = [];
+									collapsed = [];
+								}
+							}
+
+							tmpValueObjects.push(row);
+						}
+
+						xValueObjects = tmpValueObjects;
+					}
+
+					// row subtotals
+					if (doColSubTotals()) {
+						var tmpAxisAllObjects = [],
+							tmpValueObjects = [],
+							tmpTotalValueObjects = [],
+							getAxisSubTotalRow;
+
+						getAxisSubTotalRow = function(collapsed) {
+							var row = [];
+
+							for (var i = 0, obj; i < rowAxis.dims; i++) {
+								obj = {};
+								obj.type = 'dimensionSubtotal';
+								obj.cls = 'pivot-dim-subtotal cursor-default';
+								obj.collapsed = NS.arrayContains(collapsed, true);
+
+								if (i === 0) {
+									obj.htmlValue = '&nbsp;';
+									obj.colSpan = rowAxis.dims;
+								}
+								else {
+									obj.hidden = true;
+								}
+
+								row.push(obj);
+							}
+
+							return row;
+						};
+
+						// tmpAxisAllObjects
+						for (var i = 0, row, collapsed = []; i < axisAllObjects.length; i++) {
+							tmpAxisAllObjects.push(axisAllObjects[i]);
+							collapsed.push(!!axisAllObjects[i][0].collapsed);
+
+							// insert subtotal after last objects
+							if (!NS.isArray(axisAllObjects[i+1]) || !!axisAllObjects[i+1][0].root) {
+								tmpAxisAllObjects.push(getAxisSubTotalRow(collapsed));
+
+								collapsed = [];
+							}
+						}
+
+						// tmpValueObjects
+						for (var i = 0; i < tmpAxisAllObjects.length; i++) {
+							tmpValueObjects.push([]);
+						}
+
+						for (var i = 0; i < xValueObjects[0].length; i++) {
+							for (var j = 0, rowCount = 0, tmpCount = 0, subTotal = 0, empty = [], collapsed, item; j < xValueObjects.length; j++) {
+								item = xValueObjects[j][i];
+								tmpValueObjects[tmpCount++].push(item);
+								subTotal += item.value;
+								empty.push(!!item.empty);
+								rowCount++;
+
+								if (axisAllObjects[j][0].root) {
+									collapsed = !!axisAllObjects[j][0].collapsed;
+								}
+
+								if (!NS.isArray(axisAllObjects[j+1]) || axisAllObjects[j+1][0].root) {
+									var isEmpty = !NS.arrayContains(empty, false);
+
+									tmpValueObjects[tmpCount++].push({
+										type: item.type === 'value' ? 'valueSubtotal' : 'valueSubtotalTotal',
+										value: subTotal,
+										htmlValue: isEmpty ? '&nbsp;' : getRoundedHtmlValue(subTotal),
+										collapsed: collapsed,
+										cls: (item.type === 'value' ? 'pivot-value-subtotal' : 'pivot-value-subtotal-total') + (isEmpty ? ' cursor-default' : '')
+									});
+									rowCount = 0;
+									subTotal = 0;
+									empty = [];
+								}
+							}
+						}
+
+						// tmpTotalValueObjects
+						for (var i = 0, obj, collapsed = [], empty = [], subTotal = 0, count = 0; i < totalValueObjects.length; i++) {
+							obj = totalValueObjects[i];
+							tmpTotalValueObjects.push(obj);
+
+							collapsed.push(!!obj.collapsed);
+							empty.push(!!obj.empty);
+							subTotal += obj.value;
+							count++;
+
+							if (count === rowAxis.span[0]) {
+								var isEmpty = !NS.arrayContains(empty, false);
+
+								tmpTotalValueObjects.push({
+									type: 'valueTotalSubgrandtotal',
+									cls: 'pivot-value-total-subgrandtotal' + (isEmpty ? ' cursor-default' : ''),
+									value: subTotal,
+									htmlValue: isEmpty ? '&nbsp;' : getRoundedHtmlValue(subTotal),
+									empty: isEmpty,
+									collapsed: !NS.arrayContains(collapsed, false)
+								});
+
+								collapsed = [];
+								empty = [];
+								subTotal = 0;
+								count = 0;
+							}
+						}
+
+						axisAllObjects = tmpAxisAllObjects;
+						xValueObjects = tmpValueObjects;
+						totalValueObjects = tmpTotalValueObjects;
+					}
+
+					// merge dim, value, total
+					for (var i = 0, row; i < xValueObjects.length; i++) {
+						row = [];
+
+						//if (rowAxis) {
+							row = row.concat(axisAllObjects[i]);
+						//}
+
+						row = row.concat(xValueObjects[i]);
+
+						if (colAxis) {
+							row = row.concat(totalValueObjects[i]);
+						}
+
+						mergedObjects.push(row);
+					}
+
+					// create html items
+					for (var i = 0, row; i < mergedObjects.length; i++) {
+						row = [];
+
+						for (var j = 0; j < mergedObjects[i].length; j++) {
+							row.push(getTdHtml(mergedObjects[i][j]));
+						}
+
+						a.push(row);
+					}
+
+					return a;
+				};
+
+				getColTotalHtmlArray = function() {
+					var a = [];
+
+					if (rowAxis && doColTotals()) {
+						var xTotalColObjects;
+
+						// total col items
+						for (var i = 0, total = 0, empty = []; i < valueObjects[0].length; i++) {
+							for (var j = 0, obj; j < valueObjects.length; j++) {
+								obj = valueObjects[j][i];
+
+								total += obj.value;
+								empty.push(!!obj.empty);
+							}
+
+							// col total
+							totalColObjects.push({
+								type: 'valueTotal',
+								value: total,
+								htmlValue: NS.arrayContains(empty, false) ? getRoundedHtmlValue(total) : '',
+								empty: !NS.arrayContains(empty, false),
+								cls: 'pivot-value-total'
+							});
+
+							total = 0;
+							empty = [];
+						}
+
+						xTotalColObjects = totalColObjects;
+
+						if (colAxis && doRowSubTotals()) {
+							var tmp = [];
+
+							for (var i = 0, item, subTotal = 0, empty = [], colCount = 0; i < xTotalColObjects.length; i++) {
+								item = xTotalColObjects[i];
+								tmp.push(item);
+								subTotal += item.value;
+								empty.push(!!item.empty);
+								colCount++;
+
+								if (colCount === colUniqueFactor) {
+									tmp.push({
+										type: 'valueTotalSubgrandtotal',
+										value: subTotal,
+										htmlValue: NS.arrayContains(empty, false) ? getRoundedHtmlValue(subTotal) : '',
+										empty: !NS.arrayContains(empty, false),
+										cls: 'pivot-value-total-subgrandtotal'
+									});
+
+									subTotal = 0;
+									colCount = 0;
+								}
+							}
+
+							xTotalColObjects = tmp;
+						}
+
+						// total col html items
+						for (var i = 0; i < xTotalColObjects.length; i++) {
+							a.push(getTdHtml(xTotalColObjects[i]));
+						}
+					}
+
+					return a;
+				};
+
+				getGrandTotalHtmlArray = function() {
+					var total = 0,
+						empty = [],
+						a = [];
+
+					if (doRowTotals() && doColTotals()) {
+						for (var i = 0, obj; i < totalColObjects.length; i++) {
+							obj = totalColObjects[i];
+
+							total += obj.value;
+							empty.push(obj.empty);
+						}
+
+						if (colAxis && rowAxis) {
+							a.push(getTdHtml({
+								type: 'valueGrandTotal',
+								cls: 'pivot-value-grandtotal',
+								value: total,
+								htmlValue: NS.arrayContains(empty, false) ? getRoundedHtmlValue(total) : '',
+								empty: !NS.arrayContains(empty, false)
+							}));
+						}
+					}
+
+					return a;
+				};
+
+				getTotalHtmlArray = function() {
+					var dimTotalArray,
+						colTotal = getColTotalHtmlArray(),
+						grandTotal = getGrandTotalHtmlArray(),
+						row,
+						a = [];
+
+					if (doColTotals()) {
+						if (rowAxis) {
+							dimTotalArray = [getTdHtml({
+								type: 'dimensionSubtotal',
+								cls: 'pivot-dim-total',
+								colSpan: rowAxis.dims,
+								htmlValue: 'Total'
+							})];
+						}
+
+						row = [].concat(dimTotalArray || [], colTotal || [], grandTotal || []);
+
+						a.push(row);
+					}
+
+					return a;
+				};
+
+				getHtml = function() {
+                    var cls = 'pivot',
+                        table;
+
+                    cls += layout.displayDensity && layout.displayDensity !== conf.finals.style.normal ? ' displaydensity-' + layout.displayDensity : '';
+                    cls += layout.fontSize && layout.fontSize !== conf.finals.style.normal ? ' fontsize-' + layout.fontSize : '';
+
+					table = '<table class="' + cls + '">';
+
+					for (var i = 0; i < htmlArray.length; i++) {
+						table += '<tr>' + htmlArray[i].join('') + '</tr>';
+					}
+
+					return table += '</table>';
+				};
+
+				// get html
+				return function() {
+					htmlArray = NS.arrayClean([].concat(getColAxisHtmlArray() || [], getRowHtmlArray() || [], getTotalHtmlArray() || []));
+
+					return {
+						html: getHtml(htmlArray),
+						uuidDimUuidsMap: uuidDimUuidsMap,
+						colAxis: colAxis,
+						rowAxis: rowAxis,
+                        tdCount: tdCount
+					};
+				}();
+			};
+        })();
     })();
-
-
-
-
-
 });