← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 9881: (PT) Sub totals implemented.

 

Merge authors:
  Jan Henrik Øverland (janhenrik-overland)
------------------------------------------------------------
revno: 9881 [merge]
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2013-02-22 18:28:58 +0100
message:
  (PT) Sub totals implemented.
modified:
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/plugin.js
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/styles/style.css


--
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-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js	2013-02-19 10:56:48 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js	2013-02-22 17:27:36 +0000
@@ -30,6 +30,14 @@
 
 		init.afterRender = function() {
 			pt.cmp.dimension.panels[0].expand();
+
+			pt.viewport.westRegion.on('resize', function() {
+				var panel = pt.util.dimension.panel.getExpanded();
+
+				if (panel) {
+					panel.onExpand();
+				}
+			});
 		};
 
 		return init;
@@ -43,6 +51,34 @@
 				setHeight: function(mx) {
 					var h = pt.viewport.westRegion.getHeight() - pt.conf.layout.west_fill;
 					pt.cmp.dimension.panel.setHeight(h > mx ? mx : h);
+				},
+
+				getExpanded: function() {
+					for (var i = 0, panel; i < pt.cmp.dimension.panels.length; i++) {
+						panel = pt.cmp.dimension.panels[i];
+
+						if (!panel.collapsed) {
+							return panel;
+						}
+					}
+
+					return null;
+				}
+			}
+		};
+
+		util.window = {
+			setAnchorPosition: function(w, target) {
+				var vpw = pt.viewport.getWidth(),
+					targetx = target ? target.getPosition()[0] : 4,
+					winw = w.getWidth(),
+					y = target ? target.getPosition()[1] + target.getHeight() + 6 : 35;
+
+				if ((targetx + winw) > vpw) {
+					w.setPosition((vpw - winw - 4), y);
+				}
+				else {
+					w.setPosition(targetx, y);
 				}
 			}
 		};
@@ -255,6 +291,7 @@
 	PT.app.SettingsWindow = function(pt) {
 		var dimension,
 			dimensionStore,
+			dimensionOrder,
 			row,
 			rowStore,
 			col,
@@ -273,27 +310,26 @@
 			selectPanel,
 			window,
 
-			margin = 5,
+			margin = 2,
 			defaultWidth = 160,
 			defaultHeight = 158,
 			maxHeight = (pt.viewport.getHeight() - 100) / 2;
 
+		dimensionOrder = function() {
+			var order = ['dx', 'coc', 'pe', 'ou'],
+				ougsOrder = [];
+
+			for (var i = 0; i < pt.init.ougs.length; i++) {
+				ougsOrder.push(pt.init.ougs[i].id);
+			}
+
+			return order.concat(ougsOrder);
+		}();
+
 		getData = function() {
-			var groupSets = [],
-				data = [
-					{id: 'coc', name: 'Categories'}
-				];
-
-			for (var i = 0; i < pt.init.ougs.length; i++) {
-				var gs = pt.init.ougs[i];
-
-				groupSets.push({
-					id: gs.id,
-					name: gs.name
-				});
-			}
-
-			return data.concat(groupSets);
+			var data = [{id: 'coc', name: 'Categories'}];
+
+			return data.concat(pt.init.ougs);
 		};
 
 		getStore = function(data) {
@@ -352,11 +388,12 @@
 			cls: 'pt-toolbar-multiselect-leftright',
 			width: defaultWidth,
 			height: (getCmpHeight() * 2) + margin,
-			style: 'margin-right:' + margin + 'px',
+			style: 'margin-right:' + margin + 'px; margin-bottom:0px',
 			valueField: 'id',
 			displayField: 'name',
 			dragGroup: 'settingsDD',
 			dropGroup: 'settingsDD',
+			ddReorder: false,
 			store: dimensionStore,
 			tbar: {
 				height: 25,
@@ -381,7 +418,7 @@
 			cls: 'pt-toolbar-multiselect-leftright',
 			width: defaultWidth,
 			height: getCmpHeight(),
-			style: 'margin-right:' + margin + 'px',
+			style: 'margin-bottom:0px',
 			valueField: 'id',
 			displayField: 'name',
 			dragGroup: 'settingsDD',
@@ -415,6 +452,7 @@
 			cls: 'pt-toolbar-multiselect-leftright',
 			width: defaultWidth,
 			height: getCmpHeight(),
+			style: 'margin-bottom:' + margin + 'px',
 			valueField: 'id',
 			displayField: 'name',
 			dragGroup: 'settingsDD',
@@ -448,7 +486,7 @@
 			cls: 'pt-toolbar-multiselect-leftright',
 			width: defaultWidth,
 			height: getCmpHeight(),
-			style: 'margin-right:' + margin + 'px',
+			style: 'margin-right:' + margin + 'px; margin-bottom:' + margin + 'px',
 			valueField: 'id',
 			displayField: 'name',
 			dragGroup: 'settingsDD',
@@ -508,9 +546,8 @@
 		};
 
 		window = Ext.create('Ext.window.Window', {
-			title: 'Pivot settings', //i18n
-			layout: 'fit',
-			bodyStyle: 'background-color:#fff; padding:5px 5px 0px',
+			title: 'Table layout', //i18n
+			bodyStyle: 'background-color:#fff; padding:2px',
 			closeAction: 'hide',
 			autoShow: true,
 			modal: true,
@@ -539,15 +576,15 @@
 				{
 					text: '<b>Update</b>',
 					handler: function() {
-						pt.viewport.update();
+						pt.viewport.updateViewport();
 						window.hide();
 					}
 				}
 			],
 			listeners: {
 				show: function(w) {
-					var x = (pt.viewport.getWidth() / 2) - (w.getWidth() / 2);
-					w.setPosition(x, 60);
+					pt.util.window.setAnchorPosition(w, pt.viewport.layoutButton);
+					nissa = w;
 				}
 			}
 		});
@@ -680,6 +717,14 @@
 
 					return data.items.length ? data : null;
 				},
+				onExpand: function() {
+					pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_indicator);
+					pt.util.multiselect.setHeight(
+						[indicatorAvailable, indicatorSelected],
+						this,
+						pt.conf.layout.west_fill_accordion_indicator
+					);
+				},
 				items: {
 					xtype: 'panel',
 					bodyStyle: 'border:0 none; padding:0',
@@ -687,12 +732,12 @@
 						{
 							xtype: 'combobox',
 							cls: 'pt-combo',
-							style: 'margin-bottom:6px',
+							style: 'margin-bottom:4px',
 							width: pt.conf.layout.west_fieldset_width - pt.conf.layout.west_width_padding,
 							valueField: 'id',
 							displayField: 'name',
 							fieldLabel: 'Select group', //i18n pt.i18n.select_group
-							labelStyle: 'padding-left:7px',
+							labelStyle: 'padding-left:6px',
 							editable: false,
 							store: {
 								xtype: 'store',
@@ -762,13 +807,8 @@
 					added: function() {
 						pt.cmp.dimension.panels.push(this);
 					},
-					expand: function() {
-						pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_indicator);
-						pt.util.multiselect.setHeight(
-							[indicatorAvailable, indicatorSelected],
-							this,
-							pt.conf.layout.west_fill_accordion_indicator
-						);
+					expand: function(p) {
+						p.onExpand();
 					}
 				}
 			};
@@ -868,16 +908,24 @@
 
 					return data.items.length ? data : null;
 				},
+				onExpand: function() {
+					pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_dataelement);
+					pt.util.multiselect.setHeight(
+						[dataElementAvailable, dataElementSelected],
+						this,
+						pt.conf.layout.west_fill_accordion_indicator
+					);
+				},
 				items: [
 					{
 						xtype: 'combobox',
 						cls: 'pt-combo',
-						style: 'margin-bottom:6px',
+						style: 'margin-bottom:4px',
 						width: pt.conf.layout.west_fieldset_width - pt.conf.layout.west_width_padding,
 						valueField: 'id',
 						displayField: 'name',
 						fieldLabel: 'Select group', //i18n pt.i18n.select_group
-						labelStyle: 'padding-left:7px',
+						labelStyle: 'padding-left:6px',
 						editable: false,
 						store: {
 							xtype: 'store',
@@ -946,13 +994,8 @@
 					added: function() {
 						pt.cmp.dimension.panels.push(this);
 					},
-					expand: function() {
-						pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_dataelement);
-						pt.util.multiselect.setHeight(
-							[dataElementAvailable, dataElementSelected],
-							this,
-							pt.conf.layout.west_fill_accordion_indicator
-						);
+					expand: function(p) {
+						p.onExpand();
 					}
 				}
 			};
@@ -1039,6 +1082,7 @@
 			dataSet = {
 				xtype: 'panel',
 				title: '<div class="pt-panel-title-data">Reporting rates</div>', //i18n
+				bodyStyle: 'padding-top:3px',
 				hideCollapseTool: true,
 				getData: function() {
 					var data = {
@@ -1052,6 +1096,14 @@
 
 					return data.items.length ? data : null;
 				},
+				onExpand: function() {
+					pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_dataset);
+					pt.util.multiselect.setHeight(
+						[dataSetAvailable, dataSetSelected],
+						this,
+						pt.conf.layout.west_fill_accordion_dataset
+					);
+				},
 				items: [
 					{
 						xtype: 'panel',
@@ -1067,13 +1119,8 @@
 					added: function() {
 						pt.cmp.dimension.panels.push(this);
 					},
-					expand: function() {
-						pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_dataset);
-						pt.util.multiselect.setHeight(
-							[dataSetAvailable, dataSetSelected],
-							this,
-							pt.conf.layout.west_fill_accordion_dataset
-						);
+					expand: function(p) {
+						p.onExpand();
 					}
 				}
 			};
@@ -1382,6 +1429,14 @@
 
 					return data.items.length ? data : null;
 				},
+				onExpand: function() {
+					pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_period);
+					pt.util.multiselect.setHeight(
+						[fixedPeriodAvailable, fixedPeriodSelected],
+						this,
+						pt.conf.layout.west_fill_accordion_period
+					);
+				},
 				items: [
 					{
 						xtype: 'panel',
@@ -1391,7 +1446,7 @@
 							{
 								xtype: 'combobox',
 								cls: 'pt-combo',
-								style: 'margin-bottom:6px',
+								style: 'margin-bottom:4px',
 								width: pt.conf.layout.west_fieldset_width - pt.conf.layout.west_width_padding - 62 - 62 - 7,
 								valueField: 'id',
 								displayField: 'name',
@@ -1421,7 +1476,7 @@
 							{
 								xtype: 'button',
 								text: 'Prev year', //i18n
-								style: 'margin-left:4px',
+								style: 'margin-left:4px; border-radius:2px',
 								height: 24,
 								handler: function() {
 									var cb = this.up('panel').down('combobox');
@@ -1434,7 +1489,7 @@
 							{
 								xtype: 'button',
 								text: 'Next year', //i18n
-								style: 'margin-left:3px',
+								style: 'margin-left:3px; border-radius:2px',
 								height: 24,
 								handler: function() {
 									var cb = this.up('panel').down('combobox');
@@ -1461,18 +1516,14 @@
 					added: function() {
 						pt.cmp.dimension.panels.push(this);
 					},
-					expand: function() {
-						pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_period);
-						pt.util.multiselect.setHeight(
-							[fixedPeriodAvailable, fixedPeriodSelected],
-							this,
-							pt.conf.layout.west_fill_accordion_period
-						);
+					expand: function(p) {
+						p.onExpand();
 					}
 				}
 			};
 
 			organisationUnit = {
+				//id: 'organisationunit_t',
 				xtype: 'panel',
 				title: '<div class="pt-panel-title-organisationunit">Organisation units</div>', //i18n pt.i18n.organisation_units
 				bodyStyle: 'padding-top:6px',
@@ -1491,10 +1542,14 @@
 
 					return data.items.length ? data : null;
 				},
+				onExpand: function() {
+					pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_organisationunit);
+					pt.cmp.dimension.organisationUnit.treepanel.setHeight(this.getHeight() - pt.conf.layout.west_fill_accordion_organisationunit);
+				},
 				items: [
 					{
 						layout: 'column',
-						bodyStyle: 'border:0 none; padding-bottom:3px; padding-left:3px',
+						bodyStyle: 'border:0 none; padding-bottom:3px; padding-left:7px',
 						items: [
 							{
 								xtype: 'checkbox',
@@ -1531,7 +1586,7 @@
 					{
 						id: 'organisationunit_t',
 						xtype: 'toolbar',
-						style: 'margin-bottom: 5px',
+						style: 'margin-bottom: 4px',
 						width: pt.conf.layout.west_fieldset_width - pt.conf.layout.west_width_padding,
 						xable: function(checked, value) {
 							if (checked || value) {
@@ -1542,13 +1597,13 @@
 							}
 						},
 						defaults: {
-							height: 24
+							height: 22
 						},
 						items: [
 							{
 								xtype: 'label',
 								text: 'Auto-select organisation units by', //i18n
-								style: 'padding-left:8px; color:#666; line-height:24px'
+								style: 'padding-left:8px; color:#666; line-height:23px'
 							},
 							'->',
 							{
@@ -1766,21 +1821,11 @@
 						pt.cmp.dimension.panels.push(this);
 					},
 					expand: function(p) {
-						pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_organisationunit);
-						pt.cmp.dimension.organisationUnit.treepanel.setHeight(p.getHeight() - pt.conf.layout.west_fill_accordion_organisationunit);
-						//pt.cmp.dimension.organisationUnit.treepanel.selectRootIf();
+						p.onExpand();
 					}
 				}
 			};
 
-			options = {
-				xtype: 'panel',
-				title: '<div class="pt-panel-title-options">Options</div>', //i18n pt.i18n.chart_options
-				hideCollapseTool: true,
-				cls: 'pt-accordion-options',
-				items: []
-			};
-
 			getOrganisationUnitGroupSetPanels = function() {
 				var	getAvailableStore,
 					getSelectedStore,
@@ -1927,8 +1972,10 @@
 						pt.util.multiselect.filterAvailable(available, selected);
 					});
 
-					panel = Ext.create('Ext.panel.Panel', {
+					panel = {
+						xtype: 'panel',
 						title: '<div class="pt-panel-title-organisationunit">' + groupSet.name + '</div>', //i18n
+						bodyStyle: 'padding-top:3px',
 						hideCollapseTool: true,
 						getData: function() {
 							var data = {
@@ -1942,6 +1989,19 @@
 
 							return data.items.length ? data : null;
 						},
+						onExpand: function() {
+							if (!availableStore.isLoaded) {
+								availableStore.load();
+							}
+
+							pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_dataset);
+
+							pt.util.multiselect.setHeight(
+								[available, selected],
+								this,
+								pt.conf.layout.west_fill_accordion_dataset
+							);
+						},
 						items: [
 							{
 								xtype: 'panel',
@@ -1957,21 +2017,11 @@
 							added: function() {
 								pt.cmp.dimension.panels.push(this);
 							},
-							expand: function() {
-								if (!availableStore.isLoaded) {
-									availableStore.load();
-								}
-
-								pt.util.dimension.panel.setHeight(pt.conf.layout.west_maxheight_accordion_dataset);
-
-								pt.util.multiselect.setHeight(
-									[available, selected],
-									this,
-									pt.conf.layout.west_fill_accordion_dataset
-								);
+							expand: function(p) {
+								p.onExpand();
 							}
 						}
-					});
+					};
 
 					return panel;
 				};
@@ -1979,7 +2029,8 @@
 				getPanels = function() {
 					var ougs = pt.init.ougs,
 						panels = [],
-						groupSet;
+						groupSet,
+						last;
 
 					for (var i = 0, panel; i < ougs.length; i++) {
 						groupSet = ougs[i];
@@ -1989,6 +2040,9 @@
 						panels.push(panel);
 					}
 
+					last = panels[panels.length - 1];
+					last.cls = 'pt-accordion-last';
+
 					return panels;
 				};
 
@@ -2053,22 +2107,19 @@
 							];
 
 							panels = panels.concat(getOrganisationUnitGroupSetPanels());
-							panels.push(options);
 
 							return panels;
 						}(),
 						listeners: {
 							added: function() {
 								pt.cmp.dimension.panel = this;
-								pacc = this;
 							}
 						}
 					}
 				],
 				listeners: {
 					added: function() {
-						//pt.cmp.dimension.panel = this;
-						acc = this;
+						pt.cmp.dimension.panel = this;
 					}
 				}
 			};
@@ -2082,6 +2133,28 @@
 				items: accordion
 			});
 
+			layoutButton = Ext.create('Ext.button.Button', {
+				text: 'Layout',
+				handler: function() {
+					if (!pt.viewport.settingsWindow) {
+						pt.viewport.settingsWindow = PT.app.SettingsWindow(pt);
+					}
+
+					pt.viewport.settingsWindow.show();
+				}
+			});
+
+			optionsButton = Ext.create('Ext.button.Button', {
+				text: 'Options',
+				handler: function() {
+					if (!pt.viewport.optionsWindow) {
+						pt.viewport.optionsWindow = PT.app.OptionsWindow(pt);
+					}
+
+					pt.viewport.optionsWindow.show();
+				}
+			});
+
 			centerRegion = Ext.create('Ext.panel.Panel', {
 				region: 'center',
 				bodyStyle: 'padding:1px',
@@ -2102,21 +2175,24 @@
 							}
 						},
 						{
-							text: 'Settings',
-							handler: function() {
-								if (!pt.viewport.settingsWindow) {
-									pt.viewport.settingsWindow = PT.app.SettingsWindow(pt);
-								}
-
-								pt.viewport.settingsWindow.show();
-							}
-						},
-						{
 							text: '<b>Update</b>',
 							handler: function() {
 								update();
 							}
 						},
+						layoutButton,
+						optionsButton,
+						{
+							xtype: 'tbseparator',
+							height: 18,
+							style: 'border-color: transparent #d1d1d1 transparent transparent; margin-right: 4px',
+						},
+						{
+							text: 'Favorites',
+							handler: function() {
+							}
+						},
+
                         '->',
                         {
                             xtype: 'button',
@@ -2188,21 +2264,25 @@
 
 			viewport = Ext.create('Ext.container.Viewport', {
 				layout: 'border',
+				westRegion: westRegion,
+				centerRegion: centerRegion,
+				updateViewport: update,
+				layoutButton: layoutButton,
+				optionsButton: optionsButton,
 				items: [
 					westRegion,
 					centerRegion
 				],
 				listeners: {
+					render: function(vp) {
+						pt.viewport = vp;
+					},
 					afterrender: function() {
 						pt.init.afterRender();
 					}
 				}
 			});
 
-			viewport.westRegion = westRegion;
-			viewport.centerRegion = centerRegion;
-			viewport.update = update;
-
 			addListeners = function() {
 				pt.store.indicatorAvailable.on('load', function() {
 					pt.util.multiselect.filterAvailable(indicatorAvailable, indicatorSelected);

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js	2013-02-19 10:52:09 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js	2013-02-22 16:25:57 +0000
@@ -124,18 +124,18 @@
 	conf.layout = {
         west_width: 424,
         west_fieldset_width: 416,
-        west_width_padding: 12,
+        west_width_padding: 6,
         west_fill: 6,
-        west_fill_accordion_indicator: 74,
-        west_fill_accordion_dataelement: 74,
-        west_fill_accordion_dataset: 44,
-        west_fill_accordion_period: 264,
-        west_fill_accordion_organisationunit: 103,
-        west_maxheight_accordion_indicator: 500,
-        west_maxheight_accordion_dataelement: 500,
-        west_maxheight_accordion_dataset: 500,
-        west_maxheight_accordion_period: 700,
-        west_maxheight_accordion_organisationunit: 756,
+        west_fill_accordion_indicator: 65,
+        west_fill_accordion_dataelement: 65,
+        west_fill_accordion_dataset: 35,
+        west_fill_accordion_period: 257,
+        west_fill_accordion_organisationunit: 96,
+        west_maxheight_accordion_indicator: 620,
+        west_maxheight_accordion_dataelement: 620,
+        west_maxheight_accordion_dataset: 620,
+        west_maxheight_accordion_period: 820,
+        west_maxheight_accordion_organisationunit: 900,
         west_maxheight_accordion_organisationunitgroup: 298,
         west_maxheight_accordion_options: 449,
         east_tbar_height: 31,
@@ -404,6 +404,10 @@
 		roundIf: function(x, fix) {
 			var dec = pt.util.number.getNumberOfDecimals(x);
 			return parseFloat(dec > fix ? x.toFixed(fix) : x);
+		},
+
+		pp: function(x) {
+			return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
 		}
 	};
 
@@ -702,13 +706,11 @@
 
 					return a;
 				}();
-
-console.log("aUniqueIds", aUniqueIds);
-
 //aUniqueIds	= [ [de1, de2, de3],
 //					[p1],
 //					[ou1, ou2, ou3, ou4] ]
 
+
 				for (var i = 0, dim; i < aUniqueIds.length; i++) {
 					nNumCols = aUniqueIds[i].length;
 
@@ -716,30 +718,35 @@
 					nCols = nCols * nNumCols;
 					aAccNumCols.push(nCols);
 				}
-
-console.log("");
-console.log("aNumCols", aNumCols);
-console.log("nCols", nCols);
-console.log("aAccNumCols", aAccNumCols);
-
 	//aNumCols		= [3, 1, 4]
-	//nCols			= 12 (3 * 1 * 4)
+	//nCols			= (12) [3, 3, 12] (3 * 1 * 4)
 	//aAccNumCols	= [3, 3, 12]
 
+	//nCols			= 12
+
+
 				for (var i = 0; i < aUniqueIds.length; i++) {
-					aSpan.push(aNumCols[i] === 1 ? nCols : nCols / aAccNumCols[i]); //if one, span all
+					if (aNumCols[i] === 1) {
+						if (i === 0) {
+							aSpan.push(nCols); //if just one and top level, span all
+						}
+						else {
+							aSpan.push(aSpan[0]); //if just one and not top level, span same as top level
+						}
+					}
+					else {
+						aSpan.push(nCols / aAccNumCols[i]);
+					}
 				}
-
-console.log("aSpan", aSpan);
-
-	//aSpan			= [10, 2, 1]
+	//aSpan			= [4, 12, 1]
+
 
 				aGuiItems.push(aUniqueIds[0]);
 
 				if (aUniqueIds.length > 1) {
 					for (var i = 1, a, n; i < aUniqueIds.length; i++) {
 						a = [];
-						n = aNumCols[i] === 1 ? 1 : aAccNumCols[i-1];
+						n = aNumCols[i] === 1 ? aNumCols[0] : aAccNumCols[i-1];
 
 						for (var j = 0; j < n; j++) {
 							a = a.concat(aUniqueIds[i]);
@@ -748,13 +755,12 @@
 						aGuiItems.push(a);
 					}
 				}
-
-console.log("aGuiItems", aGuiItems);
 	//aGuiItems	= [ [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)
 	//		  	  ]
 
+
 				for (var i = 0, aAllRow, aUniqueRow, span, factor; i < aUniqueIds.length; i++) {
 					aAllRow = [];
 					aUniqueRow = aUniqueIds[i];
@@ -771,13 +777,12 @@
 
 					aAllItems.push(aAllRow);
 				}
-
-console.log("aAllItems", aAllItems);
 	//aAllItems	= [ [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)
 	//		  	  ]
 
+
 				for (var i = 0, id; i < nCols; i++) {
 					id = '';
 
@@ -787,12 +792,9 @@
 
 					aColIds.push(id);
 				}
-
-console.log("aColIds", aColIds);
 	//aColIds	= [ aaaaaaaaBBBBBBBBccccccc, aaaaaaaaaccccccccccbbbbbbbbbb, ... ]
 
 
-			console.log("");
 				return {
 					items: axis,
 					xItems: {
@@ -852,26 +854,64 @@
 					getTotalHtmlArray,
 					getHtml,
 
+					getUniqueFactor = function(xAxis) {
+						if (!xAxis) {
+							return null;
+						}
+
+						var unique = xAxis.xItems.unique;
+
+						if (unique) {
+							if (unique.length < 2) {
+								return 1;
+							}
+							else {
+								return xAxis.size / unique[0].length;
+							}
+						}
+
+						return null;
+					},
+
+					colUniqueFactor = getUniqueFactor(xColAxis),
+					rowUniqueFactor = getUniqueFactor(xRowAxis),
+
 					valueItems = [],
 					totalColItems = [],
 					htmlArray;
 
+				doSubTotals = function(xAxis) {
+					var multiItemDimension = 0,
+						unique;
+
+					if (!(true && xAxis && xAxis.dims > 1)) {
+						return false;
+					}
+
+					unique = xAxis.xItems.unique;
+
+					for (var i = 0; i < unique.length; i++) {
+						if (unique[i].length > 1) {
+							multiItemDimension++;
+						}
+					}
+
+					return (multiItemDimension > 1);
+				};
+
 				getEmptyHtmlArray = function() {
 					return (xColAxis && xRowAxis) ?
-						'<td class="pivot-empty scroll-fixed" colspan="' + xRowAxis.dims + '" rowspan="' + xColAxis.dims + '"></td>' : '';
+						'<td class="pivot-dim-empty " colspan="' + xRowAxis.dims + '" rowspan="' + xColAxis.dims + '">&nbsp;</td>' : '';
 				};
 
 				getColAxisHtmlArray = function() {
-					var a = [],
-						dims;
+					var a = [];
 
 					if (!(xColAxis && Ext.isObject(xColAxis))) {
 						return a;
 					}
 
-					dims = xColAxis.dims;
-
-					for (var i = 0, dimItems, colSpan, dimHtml; i < dims; i++) {
+					for (var i = 0, dimItems, colSpan, dimHtml; i < xColAxis.dims; i++) {
 						dimItems = xColAxis.xItems.gui[i];
 						colSpan = xColAxis.span[i];
 						dimHtml = [];
@@ -882,10 +922,15 @@
 
 						for (var j = 0, id; j < dimItems.length; j++) {
 							id = dimItems[j];
-							dimHtml.push('<td class="pivot-dim scroll-fixed" colspan="' + colSpan + '">' + xResponse.metaData[id] + '</td>');
+							dimHtml.push('<td class="pivot-dim" colspan="' + colSpan + '">' + xResponse.metaData[id] + '</td>');
+
+							//todo subtotal
+							if (doSubTotals(xColAxis) && i === 0) {
+								dimHtml.push('<td class="pivot-dim-subtotal" rowspan="' + xColAxis.dims + '"></td>');
+							}
 
 							if (i === 0 && j === (dimItems.length - 1)) {
-								dimHtml.push('<td class="pivot-dimtotal scroll-fixed" rowspan="' + dims + '">Total</td>');
+								dimHtml.push('<td class="pivot-dim-total" rowspan="' + xColAxis.dims + '">Total</td>');
 							}
 						}
 
@@ -899,30 +944,40 @@
 				getRowAxisHtmlArray = function() {
 					var a = [],
 						size,
-						dims,
-						allObjects;
+						allObjects,
+						uniqueSize,
+						count = 0;
 
 					if (!(xRowAxis && Ext.isObject(xRowAxis))) {
 						return a;
 					}
 
 					size = xRowAxis.size;
-					dims = xRowAxis.dims;
 					allObjects = xRowAxis.xItems.allObjects;
+					uniqueSize = xRowAxis.xItems.unique[xRowAxis.xItems.unique.length - 1].length;
 
 					// Dim html items
-					for (var i = 0, row; i < size; i++) {
+					for (var i = 0, row, rowCount = 0; i < size; i++) {
 						row = [];
+						rowCount++;
 
-						for (var j = 0, object; j < dims; j++) {
+						for (var j = 0, object; j < xRowAxis.dims; j++) {
 							object = allObjects[j][i];
 
 							if (object.rowSpan) {
-								row.push('<td class="pivot-dim scroll-relative" rowspan="' + object.rowSpan + '">' + xResponse.metaData[object.id] + '</td>');
+								row.push('<td class="pivot-dim nobreak" rowspan="' + object.rowSpan + '">' + xResponse.metaData[object.id] + '</td>');
 							}
 						}
 
 						a.push(row);
+
+						//todo subtotal
+						if (doSubTotals(xRowAxis) && rowCount === rowUniqueFactor) {
+							row = [];
+							row.push('<td class="pivot-dim-subtotal" colspan="' + xRowAxis.dims + '"></td>');
+							a.push(row);
+							rowCount = 0;
+						}
 					}
 
 					return a;
@@ -931,27 +986,108 @@
 				getValueHtmlArray = function() {
 					var a = [],
 						htmlValueItems = [],
+						htmlValueColItems = [],
 						colSize = xColAxis ? xColAxis.size : 1,
-						rowSize = xRowAxis ? xRowAxis.size : 1;
+						rowSize = xRowAxis ? xRowAxis.size : 1,
+						rowRootSize = xRowAxis ? xRowAxis.xItems.unique[0].length : null,
+						hasSubtotals,
+						subtotal,
+						td;
 
-					// Value items
+					// Value / htmlvalue items
 					for (var i = 0, valueItemRow, htmlValueItemRow; i < rowSize; i++) {
 						valueItemRow = [];
 						htmlValueItemRow = [];
 
 						for (var j = 0, id, value; j < colSize; j++) {
 							id = (xColAxis ? xColAxis.ids[j] : '') + (xRowAxis ? xRowAxis.ids[i] : '');
+
 							value = xResponse.idValueMap[id] ? parseFloat(xResponse.idValueMap[id]) : 0; //todo
 							htmlValue = xResponse.idValueMap[id] ? parseFloat(xResponse.idValueMap[id]) : '-'; //todo
 
 							valueItemRow.push(value);
-							htmlValueItemRow.push({id: id, value: htmlValue});
+							htmlValueItemRow.push({value: value, htmlValue: htmlValue, cls: 'pivot-value'});
 						}
 
 						valueItems.push(valueItemRow);
 						htmlValueItems.push(htmlValueItemRow);
 					}
 
+					if (doSubTotals(xColAxis)) {
+						var tmp = [];
+
+						for (var i = 0, row, rowSubTotal, colCount; i < htmlValueItems.length; i++) {
+							row = [];
+							rowSubTotal = 0;
+							colCount = 0;
+
+							for (var j = 0, item; j < htmlValueItems[i].length; j++) {
+								item = htmlValueItems[i][j];
+								rowSubTotal += item.value;
+								colCount++;
+
+								row.push(item);
+
+								if (colCount === colUniqueFactor) {
+									row.push({value: rowSubTotal, htmlValue: rowSubTotal, cls: 'pivot-value-subtotal'});
+									colCount = 0;
+									rowSubTotal = 0;
+								}
+							}
+
+							tmp.push(row);
+						}
+
+						htmlValueItems = tmp;
+					}
+
+					if (doSubTotals(xRowAxis)) {
+						var tmp = [],
+							subTotals = [],
+							count;
+
+						// Create sub total arrays
+						for (var i = 0; i < rowRootSize; i++) {
+							subTotals.push([]);
+						}
+
+						// Populate sub total arrays
+						for (var i = 0, subTotal, subTotalsIndex; i < htmlValueItems[0].length; i++) {
+							subTotal = 0;
+							subTotalsIndex = 0;
+
+							for (var j = 0, rowCount = 0, item; j < xRowAxis.size; j++) {
+								item = htmlValueItems[j][i];
+								subTotal += item.value;
+								rowCount++;
+
+								if (rowCount === rowUniqueFactor) {
+									var cls = xColAxis && doSubTotals(xColAxis) && (item.cls === 'pivot-value-subtotal') ? 'pivot-value-subtotal-total' : 'pivot-value-subtotal';
+									subTotals[subTotalsIndex].push({value: subTotal, htmlValue: subTotal, cls: cls});
+									rowCount = 0;
+									subTotal = 0;
+									subTotalsIndex++;
+								}
+							}
+						}
+
+						// Add sub total arrays to htmlValueItems
+						for (var i = 0, count = 0; i < htmlValueItems.length; i++) {
+							tmp.push(htmlValueItems[i]);
+							count++;
+
+							if (count === rowUniqueFactor) {
+								count = 0;
+
+								var sta = subTotals.shift();
+
+								tmp.push(sta);
+							}
+						}
+
+						htmlValueItems = tmp;
+					}
+
 					// Value html items
 					for (var i = 0, row; i < htmlValueItems.length; i++) {
 						row = [];
@@ -963,7 +1099,7 @@
 								//cls = value < 5000 ? 'bad' : (value < 20000 ? 'medium' : 'good'); //basic legendset
 							//}
 
-							row.push('<td id="' + item.id + '" class="pivot-value scroll-relative">' + item.value + '</td>');
+							row.push('<td class="' + item.cls + '">' + pt.util.number.pp(item.htmlValue) + '</td>');
 						}
 
 						a.push(row);
@@ -974,22 +1110,41 @@
 
 				getRowTotalHtmlArray = function() {
 					var totalRowItems = [],
+						vItems = Ext.clone(valueItems),
 						a = [];
 
 					if (xColAxis) {
 
 						// Total row items
-						for (var i = 0, rowSum; i < valueItems.length; i++) {
-							rowSum = Ext.Array.sum(valueItems[i]);
-							totalRowItems.push(rowSum);
+						for (var i = 0, rowSum; i < vItems.length; i++) {
+							rowSum = Ext.Array.sum(vItems[i]);
+							totalRowItems.push({value: rowSum, htmlValue: rowSum, cls: 'pivot-value-total'});
+						}
+
+						if (xRowAxis && doSubTotals(xRowAxis)) {
+							var tmp = [];
+
+							for (var i = 0, rowCount = 0, subTotal = 0; i < totalRowItems.length; i++) {
+								tmp.push(totalRowItems[i]);
+								rowCount++;
+								subTotal += totalRowItems[i].value;
+
+								if (rowCount === rowUniqueFactor) {
+									tmp.push({value: subTotal, htmlValue: subTotal, cls: 'pivot-value-total-subgrandtotal'});
+									rowCount = 0;
+									subTotal = 0;
+								}
+							}
+
+							totalRowItems = tmp;
 						}
 
 						// Total row html items
-						for (var i = 0, rowSum; i < totalRowItems.length; i++) {
-							rowSum = totalRowItems[i];
-							rowSum = pt.util.number.roundIf(rowSum, 1);
+						for (var i = 0, item; i < totalRowItems.length; i++) {
+							item = totalRowItems[i];
+							item.htmlValue = pt.util.number.roundIf(item.htmlValue, 1);
 
-							a.push(['<td id="nissa" class="pivot-valuetotal scroll-relative">' + rowSum.toString() + '</td>']);
+							a.push(['<td class="' + item.cls + '">' + pt.util.number.pp(item.htmlValue) + '</td>']);
 						}
 					}
 
@@ -1010,15 +1165,34 @@
 								colSum += valueItems[j][i];
 							}
 
-							totalColItems.push(colSum);
+							totalColItems.push({value: colSum, htmlValue: colSum, cls: 'pivot-value-total'});
+						}
+
+						if (xColAxis && doSubTotals(xColAxis)) {
+							var tmp = [];
+
+							for (var i = 0, item, subTotal = 0, colCount = 0; i < totalColItems.length; i++) {
+								item = totalColItems[i];
+								tmp.push(item);
+								subTotal += item.value;
+								colCount++;
+
+								if (colCount === colUniqueFactor) {
+									tmp.push({value: subTotal, htmlValue: subTotal, cls: 'pivot-value-total-subgrandtotal'});
+									subTotal = 0;
+									colCount = 0;
+								}
+							}
+
+							totalColItems = tmp;
 						}
 
 						// Total col html items
-						for (var i = 0, colSum; i < totalColItems.length; i++) {
-							colSum = totalColItems[i];
-							colSum = pt.util.number.roundIf(colSum, 1);
+						for (var i = 0, item; i < totalColItems.length; i++) {
+							item = totalColItems[i];
+							item.htmlValue = pt.util.number.roundIf(item.htmlValue, 1);
 
-							a.push('<td class="pivot-valuetotal scroll-relative">' + colSum.toString() + '</td>');
+							a.push('<td class="' + item.cls + '">' + pt.util.number.pp(item.htmlValue) + '</td>');
 						}
 					}
 
@@ -1027,13 +1201,18 @@
 
 				getGrandTotalHtmlArray = function() {
 					var grandTotalSum,
+						values = [],
 						a = [];
 
+					for (var i = 0; i < totalColItems.length; i++) {
+						values.push(totalColItems[i].value);
+					}
+
 					if (xColAxis && xRowAxis) {
-						grandTotalSum = Ext.Array.sum(totalColItems) || 0;
+						grandTotalSum = Ext.Array.sum(values) || 0;
 						grandTotalSum = pt.util.number.roundIf(grandTotalSum, 1);
 
-						a.push('<td class="pivot-valuegrandtotal scroll-relative">' + grandTotalSum.toString() + '</td>');
+						a.push('<td class="pivot-value-grandtotal">' + pt.util.number.pp(grandTotalSum) + '</td>');
 					}
 
 					return a;
@@ -1063,7 +1242,7 @@
 						a = [];
 
 					if (xRowAxis) {
-						dimTotalArray = ['<td class="pivot-dimtotal scroll-relative" colspan="' + xRowAxis.dims + '">Total</td>'];
+						dimTotalArray = ['<td class="pivot-dim-total" colspan="' + xRowAxis.dims + '">Total</td>'];
 					}
 
 					row = [].concat(dimTotalArray || [], Ext.clone(colTotal) || [], Ext.clone(grandTotal) || []);
@@ -1077,17 +1256,10 @@
 					var s = '<table id="pivottable" class="pivot">';
 
 					for (var i = 0; i < htmlArray.length; i++) {
-						if (i < 2) {
-							s += '<tr class="scroll-fixed-tr">' + htmlArray[i].join('') + '</tr>';
-						}
-						else {
-							s += '<tr>' + htmlArray[i].join('') + '</tr>';
-						}
+						s += '<tr>' + htmlArray[i].join('') + '</tr>';
 					}
 
-					s += '</table>';
-
-					return s;
+					return s += '</table>';
 				};
 
 				htmlArray = [].concat(getColAxisHtmlArray(), getRowHtmlArray(), getTotalHtmlArray());
@@ -1137,9 +1309,6 @@
 							console.log(response);
 							return;
 						}
-//todo
-response.metaData['PT59n8BQbqM'] = '(Outreach)';
-response.metaData['pq2XI5kz2BY'] = '(Fixed)';
 
 						xSettings = getSyncronizedXSettings(xSettings, response);
 

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/plugin.js'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/plugin.js	2013-02-09 00:30:56 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/plugin.js	2013-02-21 14:57:02 +0000
@@ -50,7 +50,7 @@
 		'pe': ['201201', '201202', '201203'],
 		'Bpx0589u8y0': ['MAs88nJc9nL', 'PVLOW4bCshG'],
 		'ou': ['ImspTQPwCqd']
-	}		
+	}
 };
 
 xResponse = {
@@ -64,7 +64,7 @@
 			index: 0,
 			size: 3,
 			items: [
-			
+
 		}
 	],
 	metaData: {
@@ -94,7 +94,35 @@
 			index: 0,
 			size: 3,
 			items: [
-			
+
 		}
 	}
 };
+
+xAxis = {
+	dims: 2,
+	size: 15,
+	ids: ["O3qECFGrzeFeT1vvFVhLHc", "O3qECFGrzeFio8xTtlZV18", x15],
+	span: [5, 1],
+	items: [
+		{
+			name: 'dx',
+			items: ["O3qECFGrzeF", "t3QKFZbCf2B", "OLlWZUfLtsR"]
+		},
+		etc
+	],
+	xItems: {
+		all: [
+			[x15, "O3qECFGrzeF"],
+			[x15, "eT1vvFVhLHc"]
+		],
+		gui: [
+			[x3],
+			[x15]
+		],
+		unique: [
+			[x3],
+			[x5]
+		]
+	}
+};

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/styles/style.css'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/styles/style.css	2013-02-19 10:52:09 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/styles/style.css	2013-02-22 16:25:57 +0000
@@ -54,6 +54,13 @@
 
 body {
     font-size: 10px;
+
+	-webkit-touch-callout: none;
+	-webkit-user-select: none;
+	-khtml-user-select: none;
+	-moz-user-select: none;
+	-ms-user-select: none;
+	user-select: none;
 }
 
 .pt-accordion-options .x-panel-body-default {
@@ -74,6 +81,10 @@
 	position: fixed;
 }
 
+.nobreak {
+	white-space: nowrap;
+}
+
 /*----------------------------------------------------------------------------
  * Pivot
  *--------------------------------------------------------------------------*/
@@ -82,6 +93,13 @@
 	border-collapse: collapse;
 	border-spacing: 0px;
 	border: 0 none;
+
+	-webkit-touch-callout: all;
+	-webkit-user-select: all;
+	-khtml-user-select: all;
+	-moz-user-select: all;
+	-ms-user-select: all;
+	user-select: all;
 }
 .pivot td {
 	padding: 5px;
@@ -89,25 +107,42 @@
 	text-align: center;
 }
 
-.pivot-empty {
-	background-color: #deeafc;
-}
-
 .pivot-dim {
 	background-color: #dae6f8;
 }
-.pivot-dimtotal {
-	background-color: #b0c4de;
+.pivot-dim-subtotal {
+	background-color: #cad6e8;
+}
+.pivot-dim-total {
+	background-color: #bac6d8;
+}
+.pivot-dim-empty {
+	background-color: #dae6f8;
 }
 
 .pivot-value {
 	background-color: #fff;
-}
-.pivot-valuetotal {
-	background-color: #eaeaea;
-}
-.pivot-valuegrandtotal {
-	background-color: #ccc;
+	white-space: nowrap;
+}
+.pivot-value-subtotal {
+	background-color: #f5f5f5;
+	white-space: nowrap;
+}
+.pivot-value-subtotal-total {
+	background-color: #e8e8e8;
+	white-space: nowrap;
+}
+.pivot-value-total {
+	background-color: #e4e4e4;
+	white-space: nowrap;
+}
+.pivot-value-total-subgrandtotal {
+	background-color: #d9d9d9;
+	white-space: nowrap;
+}
+.pivot-value-grandtotal {
+	background-color: #c8c8c8;
+	white-space: nowrap;
 }
 
 td .good div {
@@ -352,7 +387,6 @@
 	margin-top: 5px;
 }
 
-
 /*----------------------------------------------------------------------------
  * Menu
  *--------------------------------------------------------------------------*/
@@ -710,15 +744,12 @@
  *--------------------------------------------------------------------------*/
 
 	/* accordion title bar, shared */
-.pt-accordion .x-accordion-item .x-accordion-hd, .pt-accordion .pt-accordion-options .x-accordion-hd {
+.pt-accordion .x-accordion-item .x-accordion-hd {
 	padding: 6px 5px 4px 8px;
 	border: 0 none;
 	cursor: pointer;
 	border-top-left-radius: 1px;
 	border-top-right-radius: 1px;
-}
-	/* accordion title dock, default */
-.pt-accordion .x-accordion-item .x-accordion-hd {
     background-image: none;
     background-color: #e0e0e0;
     background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dcdcdc), color-stop(100%, #e5e5e5)) !important;
@@ -728,24 +759,13 @@
     background-image: -ms-linear-gradient(top, #dcdcdc, #e5e5e5) !important;
     background-image: linear-gradient(top, #dcdcdc, #e5e5e5) !important;
 }
-	/* accordion title dock, options */
-.pt-accordion .pt-accordion-options .x-accordion-hd {
-    background-image: none;
-    background-color: #d0d0d0;
-    background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #cccccc), color-stop(100%, #d3d3d3)) !important;
-    background-image: -webkit-linear-gradient(top, #cccccc, #d3d3d3) !important;
-    background-image: -moz-linear-gradient(top, #cccccc, #d3d3d3) !important;
-    background-image: -o-linear-gradient(top, #cccccc, #d3d3d3) !important;
-    background-image: -ms-linear-gradient(top, #cccccc, #d3d3d3) !important;
-    background-image: linear-gradient(top, #cccccc, #d3d3d3) !important;
-}
 	/* accordion title dock, default, collapsed */
 .pt-accordion .collapsed .x-accordion-hd {
 	padding-bottom: 5px !important;
 }
 
 	/* accordion title dock outer, shared */
-.pt-accordion .x-accordion-item, .pt-accordion-options .x-accordion-item {
+.pt-accordion .x-accordion-item {
 	border-top-left-radius: 2px;
 	border-top-right-radius: 2px;
 }
@@ -754,9 +774,9 @@
 	border: 1px solid #c5c5c5;
 	border-bottom: 0 none;
 }
-	/* accordion title dock outer, options */
-.pt-accordion .pt-accordion-options {
-	border: 1px solid #c0c0c0;
+	/* accordion title dock outer, last */
+.pt-accordion .pt-accordion-last {
+	border: 1px solid #c5c5c5;
 }
 
 	/* accordion title dock text, shared */
@@ -767,7 +787,7 @@
 
 	/* accordion item body */
 .pt-accordion .x-accordion-body {
-	padding: 8px 6px 0px 6px;
+	padding: 5px 3px 0px;
 	border-top: 1px solid #c5c5c5 !important;
 }