← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 20027: PT plugin fixes.

 

------------------------------------------------------------
revno: 20027
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2015-09-07 14:21:50 +0200
message:
  PT plugin fixes.
added:
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/images/error_m.png
modified:
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/table.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/plugin.html
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/chart.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/core.js
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/chart.js
  dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/plugin/chart.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/scripts/table.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/table.js	2015-09-06 21:38:21 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/table.js	2015-09-07 12:21:50 +0000
@@ -2033,6 +2033,7 @@
                 type = (obj.status || 'INFO').toLowerCase();
 
 				config.title = obj.status;
+                config.cls = 'ns-window-title-messagebox';
 				config.iconCls = 'ns-window-title-messagebox ' + type;
 
                 // html
@@ -3185,7 +3186,7 @@
 			}
 		});
 
-        // user orgunit
+        // dimensions
 		requests.push({
 			url: init.contextPath + '/api/dimensions.' + type + '?fields=id,name&paging=false',
             disableCaching: false,
@@ -3213,7 +3214,8 @@
 
     applyCss = function(config) {
         var css = '',
-            arrowUrl = config.dashboard ? init.contextPath + '/dhis-web-commons/javascripts/plugin/images/arrowupdown.png' : '//dhis2-cdn.org/v217/plugin/images/arrowupdown.png';
+            arrowUrl = config.dashboard ? init.contextPath + '/dhis-web-commons/javascripts/plugin/images/arrowupdown.png' : '//dhis2-cdn.org/v220/plugin/images/arrowupdown.png',
+            errorUrl = config.dashboard ? init.contextPath + '/dhis-web-commons/javascripts/plugin/images/error_m.png' : '//dhis2-cdn.org/v220/plugin/images/error_m.png';
 
         css += 'table.pivot { font-family: arial,sans-serif,ubuntu,consolas; border-collapse: collapse; border-spacing: 0px; border: 0 none; } \n';
         css += '.td-nobreak { white-space: nowrap; } \n';
@@ -3259,6 +3261,10 @@
         // alert
         css += '.ns-plugin-alert { width: 90%; padding: 5%; color: #777 } \n';
 
+        css += '.x-window-body { font-size: 13px; } \n';
+        css += '.ns-window-title-messagebox { padding-left: 16px; background-position-y: 1px; } \n';
+        css += '.ns-window-title-messagebox.error { background-image: url("' + errorUrl + '"); } \n';
+
         Ext.util.CSS.createStyleSheet(css);
     };
 

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/plugin.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/plugin.html	2015-08-05 12:57:59 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/plugin.html	2015-09-07 12:21:50 +0000
@@ -27,34 +27,34 @@
                 userOrgUnit: 'qhqAxPSTUXp'
 			});
 
-			//DHIS.getChart({
-				//url: url,
-				//el: 'chart2',
-                ////type: 'pie',
-				//columns: [{dimension: 'in', items: [{id: 'Uvn6LCg7dVU'}, {id: 'OdiHJayrsKo'}, {id: 'sB79w2hiLp8'}, {id: 'AUqdhY4mpvp'}]}],
-				//rows: [{dimension: 'pe', items: [{id: 'LAST_6_MONTHS'}]}],
-                //filters: [{dimension: 'ou', items: [{id: 'USER_ORGUNIT'}]}],
-                //domainAxisTitle: 'PERIODS',
-                //rangeAxisTitle: 'PERCENT',
-                //domainAxisStyle: {
-                    //labelFont: '10px sans-serif',
-                    //labelRotation: 0,
-                    //titleFont: 'bold 10px sans-serif'
-                //},
-                //rangeAxisStyle: {
-                    //labelFont: '10px arial',
-                    //titleFont: 'bold 10px sans-serif'
-                //},
-                //legendStyle: {
-                    //labelMaxLength: 9,
-                    //labelFontSize: 10,
-                    //titleFont: '18px sans-serif'
-                //},
-                //seriesStyle: {
-                    //labelFont: '10px sans-serif',
-                    //labelColor: 'black'
-                //}
-			//});
+			DHIS.getChart({
+				url: url,
+				el: 'chart2',
+                //type: 'pie',
+				columns: [{dimension: 'in', items: [{id: 'Uvn6LCg7dVU'}, {id: 'OdiHJayrsKo'}, {id: 'sB79w2hiLp8'}, {id: 'AUqdhY4mpvp'}]}],
+				rows: [{dimension: 'pe', items: [{id: 'LAST_6_MONTHS'}]}],
+                filters: [{dimension: 'ou', items: [{id: 'USER_ORGUNIT'}]}],
+                domainAxisTitle: 'PERIODS',
+                rangeAxisTitle: 'PERCENT',
+                domainAxisStyle: {
+                    labelFont: '10px sans-serif',
+                    labelRotation: 0,
+                    titleFont: 'bold 10px sans-serif'
+                },
+                rangeAxisStyle: {
+                    labelFont: '10px arial',
+                    titleFont: 'bold 10px sans-serif'
+                },
+                legendStyle: {
+                    labelMaxLength: 9,
+                    labelFontSize: 10,
+                    titleFont: '18px sans-serif'
+                },
+                seriesStyle: {
+                    labelFont: '10px sans-serif',
+                    labelColor: 'black'
+                }
+			});
 		});
 	</script>
 </head>

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js	2015-09-04 14:37:08 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js	2015-09-07 12:21:50 +0000
@@ -2116,12 +2116,12 @@
 
 	// core
     extendCore = function(core) {
-        var conf = core.conf,
+        var init = core.init,
+            conf = core.conf,
 			api = core.api,
 			support = core.support,
 			service = core.service,
-			web = core.web,
-			init = core.init;
+			web = core.web;
 
         // init
         (function() {
@@ -7677,6 +7677,8 @@
 			period: period,
 			treePanel: treePanel,
 			setGui: setGui,
+            westRegion: westRegion,
+            centerRegion: centerRegion,
             update: update,
 			items: [
 				westRegion,
@@ -7780,19 +7782,25 @@
 		var requests = [],
 			callbacks = 0,
 			init = {},
+            appConfig,
 			fn;
 
 		fn = function() {
 			if (++callbacks === requests.length) {
 
-				NS.instances.push(ns);
-
-                ns.init = init;
-				ns.core = NS.getCore(ns);
+				ns.core = NS.getCore(init);
+                ns.alert = ns.core.webAlert;
 				extendCore(ns.core);
 
 				dimConf = ns.core.conf.finals.dimension;
 				ns.app.viewport = createViewport();
+
+                ns.core.app.getViewportWidth = function() { return ns.app.viewport.getWidth(); };
+                ns.core.app.getViewportHeight = function() { return ns.app.viewport.getHeight(); };
+                ns.core.app.getCenterRegionWidth = function() { return ns.app.viewport.centerRegion.getWidth(); };
+                ns.core.app.getCenterRegionHeight = function() { return ns.app.viewport.centerRegion.getHeight(); };
+
+                NS.instances.push(ns);
 			}
 		};
 

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/chart.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/chart.js	2015-08-19 21:30:33 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/chart.js	2015-09-07 12:21:50 +0000
@@ -574,17 +574,26 @@
 	DV.isDebug = false;
 	DV.isSessionStorage = ('sessionStorage' in window && window['sessionStorage'] !== null);
 
-	DV.getCore = function(ns) {
-        var init = ns.init,
-            conf = {},
+	DV.getCore = function(init, appConfig) {
+        var conf = {},
             api = {},
             support = {},
             service = {},
             web = {},
+            app = {},
+            webAlert,
             dimConf;
 
-        // tmp
-        ns.alert = function() {};
+        appConfig = appConfig || {};
+
+        // alert
+        webAlert = function() {};
+
+        // app
+        app.getViewportWidth = function() {};
+        app.getViewportHeight = function() {};
+        app.getCenterRegionWidth = function() {};
+        app.getCenterRegionHeight = function() {};
 
 		// conf
         (function() {
@@ -726,6 +735,14 @@
 				]
 			};
 
+            conf.valueType = {
+            	numericTypes: ['NUMBER','UNIT_INTERVAL','PERCENTAGE','INTEGER','INTEGER_POSITIVE','INTEGER_NEGATIVE','INTEGER_ZERO_OR_POSITIVE'],
+            	textTypes: ['TEXT','LONG_TEXT','LETTER','PHONE_NUMBER','EMAIL'],
+            	booleanTypes: ['BOOLEAN','TRUE_ONLY'],
+            	dateTypes: ['DATE','DATETIME'],
+            	aggregateTypes: ['NUMBER','UNIT_INTERVAL','PERCENTAGE','INTEGER','INTEGER_POSITIVE','INTEGER_NEGATIVE','INTEGER_ZERO_OR_POSITIVE','BOOLEAN','TRUE_ONLY']
+            };
+
             conf.layout = {
                 west_width: 424,
                 west_fieldset_width: 418,
@@ -1063,19 +1080,19 @@
 
 							// Indicators as filter
 							if (layout.filters[i].dimension === dimConf.indicator.objectName) {
-								ns.alert(DV.i18n.indicators_cannot_be_specified_as_filter || 'Indicators cannot be specified as filter.');
+								webAlert(DV.i18n.indicators_cannot_be_specified_as_filter || 'Indicators cannot be specified as filter.');
 								return;
 							}
 
 							// Categories as filter
 							if (layout.filters[i].dimension === dimConf.category.objectName) {
-								ns.alert(DV.i18n.categories_cannot_be_specified_as_filter || 'Categories cannot be specified as filter.');
+								webAlert(DV.i18n.categories_cannot_be_specified_as_filter || 'Categories cannot be specified as filter.');
 								return;
 							}
 
 							// Data sets as filter
 							if (layout.filters[i].dimension === dimConf.dataSet.objectName) {
-								ns.alert(DV.i18n.data_sets_cannot_be_specified_as_filter || 'Data sets cannot be specified as filter.');
+								webAlert(DV.i18n.data_sets_cannot_be_specified_as_filter || 'Data sets cannot be specified as filter.');
 								return;
 							}
 						}
@@ -1083,31 +1100,31 @@
 
 					// dc and in
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.indicator.objectName]) {
-						ns.alert('Indicators and detailed data elements cannot be specified together.', true);
+						webAlert('Indicators and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
 					// dc and de
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.dataElement.objectName]) {
-						ns.alert('Detailed data elements and totals cannot be specified together.', true);
+						webAlert('Detailed data elements and totals cannot be specified together.', true);
 						return;
 					}
 
 					// dc and ds
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.dataSet.objectName]) {
-						ns.alert('Data sets and detailed data elements cannot be specified together.', true);
+						webAlert('Data sets and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
 					// dc and co
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.category.objectName]) {
-						ns.alert('Categories and detailed data elements cannot be specified together.', true);
+						webAlert('Categories and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
                     // in and aggregation type
                     if (objectNameDimensionMap[dimConf.indicator.objectName] && config.aggregationType !== 'DEFAULT') {
-                        ns.alert('Indicators and aggregation types cannot be specified together.', true);
+                        webAlert('Indicators and aggregation types cannot be specified together.', true);
                         return;
                     }
 
@@ -1120,7 +1137,7 @@
 
 					// config must be an object
 					if (!(config && Ext.isObject(config))) {
-						ns.alert('Layout: config is not an object (' + init.el + ')', true);
+						webAlert('Layout: config is not an object (' + init.el + ')', true);
 						return;
 					}
 
@@ -1130,12 +1147,12 @@
 
 					// at least one dimension specified as column and row
 					if (!config.columns) {
-						ns.alert('No series items selected');
+						webAlert('No series items selected');
 						return;
 					}
 
 					if (!config.rows) {
-						ns.alert('No category items selected');
+						webAlert('No category items selected');
 						return;
 					}
 
@@ -1150,7 +1167,7 @@
 
 					// at least one period
 					if (!Ext.Array.contains(objectNames, dimConf.period.objectName)) {
-						ns.alert('At least one period must be specified as series, category or filter');
+						webAlert('At least one period must be specified as series, category or filter');
 						return;
 					}
 
@@ -1214,6 +1231,11 @@
                         layout.program = config.program;
                     }
 
+                    // relative period date
+                    if (support.prototype.date.getYYYYMMDD(config.relativePeriodDate)) {
+                        layout.relativePeriodDate = support.prototype.date.getYYYYMMDD(config.relativePeriodDate);
+                    }
+
                     // style
                     if (Ext.isObject(config.domainAxisStyle)) {
                         layout.domainAxisStyle = config.domainAxisStyle;
@@ -1231,6 +1253,7 @@
                         layout.seriesStyle = config.seriesStyle;
                     }
 
+                    // validate
 					if (!validateSpecialCases()) {
 						return;
 					}
@@ -1486,7 +1509,39 @@
 
                 return variable;
 			};
-		}());
+
+                // date
+            support.prototype.date = {};
+
+            support.prototype.date.getYYYYMMDD = function(param) {
+                if (!Ext.isString(param)) {
+                    if (!(Object.prototype.toString.call(param) === '[object Date]' && param.toString() !== 'Invalid date')) {
+                        return null;
+                    }
+                }
+
+                var date = new Date(param),
+                    month = '' + (1 + date.getMonth()),
+                    day = '' + date.getDate();
+
+                month = month.length === 1 ? '0' + month : month;
+                day = day.length === 1 ? '0' + day : day;
+
+                return date.getFullYear() + '-' + month + '-' + day;
+            };
+
+            // connection
+            support.connection = {};
+
+            support.connection.ajax = function(requestConfig, authConfig) {
+                if (authConfig.crossDomain && Ext.isString(authConfig.username) && Ext.isString(authConfig.password)) {
+                    requestConfig.headers = Ext.isObject(authConfig.headers) ? authConfig.headers : {};
+                    requestConfig.headers['Authorization'] = 'Basic ' + btoa(authConfig.username + ':' + authConfig.password);
+                }
+
+                Ext.Ajax.request(requestConfig);
+            };
+        }());
 
 		// service
 		(function() {
@@ -2233,7 +2288,7 @@
 			web.window = {};
 
 			web.window.setAnchorPosition = function(w, target) {
-				var vpw = ns.app.viewport.getWidth(),
+				var vpw = app.getViewportWidth(),
 					targetx = target ? target.getPosition()[0] : 4,
 					winw = w.getWidth(),
 					y = target ? target.getPosition()[1] + target.getHeight() + 4 : 33;
@@ -2310,7 +2365,7 @@
                 config.html += obj.message + (obj.message.substr(obj.message.length - 1) === '.' ? '' : '.');
 
                 // bodyStyle
-                config.bodyStyle = 'padding: 12px; background: #fff; max-width: 600px; max-height: ' + ns.app.centerRegion.getHeight() / 2 + 'px';
+                config.bodyStyle = 'padding: 12px; background: #fff; max-width: 600px; max-height: ' + app.getCenterRegionHeight() / 2 + 'px';
 
                 // destroy handler
                 config.modal = true;
@@ -2401,6 +2456,11 @@
                     paramString += '&program=' + xLayout.program.id;
                 }
 
+                // relative period date
+                if (xLayout.relativePeriodDate) {
+                    paramString += '&relativePeriodDate=' + xLayout.relativePeriodDate;
+                }
+
                 return paramString.replace(/#/g, '.');
             };
 
@@ -2417,7 +2477,7 @@
 
                 msg += '\n\n' + 'Hint: A good way to reduce the number of items is to use relative periods and level/group organisation unit selection modes.';
 
-                ns.alert(msg, 'warning');
+                webAlert(msg, 'warning');
 			};
 
 			// chart
@@ -2581,7 +2641,7 @@
                                 }
 
                                 trendLineFields.push(regressionKey);
-                                xResponse.metaData.names[regressionKey] = DV.i18n.trend + (ns.dashboard ? '' : ' (' + xResponse.metaData.names[failSafeColumnIds[i]] + ')');
+                                xResponse.metaData.names[regressionKey] = DV.i18n.trend + (appConfig.dashboard ? '' : ' (' + xResponse.metaData.names[failSafeColumnIds[i]] + ')');
                             }
                         }
                     }
@@ -2904,15 +2964,15 @@
                 };
 
                 getFormatedSeriesTitle = function(titles) {
-                    var itemLength = ns.dashboard ? 23 : 30,
-                        charLength = ns.dashboard ? 5 : 6,
+                    var itemLength = appConfig.dashboard ? 23 : 30,
+                        charLength = appConfig.dashboard ? 5 : 6,
                         numberOfItems = titles.length,
                         numberOfChars,
                         totalItemLength = numberOfItems * itemLength,
                         //minLength = 5,
                         maxLength = support.prototype.array.getMaxLength(titles),
                         fallbackLength = 10,
-                        maxWidth = ns.app.centerRegion.getWidth(),
+                        maxWidth = app.getCenterRegionWidth(),
                         width,
                         validateTitles;
 
@@ -2974,7 +3034,7 @@
                         }
                     }
 
-                    return ns.dashboard ? getFormatedSeriesTitle(a) : a;
+                    return appConfig.dashboard ? getFormatedSeriesTitle(a) : a;
 				};
 
                 getPieSeriesTitle = function(store) {
@@ -3003,7 +3063,7 @@
                         });
                     }
 
-                    return ns.dashboard ? getFormatedSeriesTitle(a) : a;
+                    return appConfig.dashboard ? getFormatedSeriesTitle(a) : a;
 				};
 
                 getDefaultSeries = function(store) {
@@ -3162,8 +3222,8 @@
                 };
 
                 getDefaultLegend = function(store, chartConfig) {
-                    var itemLength = ns.dashboard ? 24 : 30,
-                        charLength = ns.dashboard ? 4 : 6,
+                    var itemLength = appConfig.dashboard ? 24 : 30,
+                        charLength = appConfig.dashboard ? 4 : 6,
                         numberOfItems = 0,
                         numberOfChars = 0,
                         width,
@@ -3192,7 +3252,7 @@
 
                     width = (numberOfItems * itemLength) + (numberOfChars * charLength);
 
-                    if (width > ns.app.centerRegion.getWidth() - 6) {
+                    if (width > app.getCenterRegionWidth() - 6) {
                         position = 'right';
                     }
 
@@ -3268,7 +3328,7 @@
                         text = xLayout.title;
                     }
 
-                    fontSize = (ns.app.centerRegion.getWidth() / text.length) < 11.6 ? 12 : 17;
+                    fontSize = (app.getCenterRegionWidth() / text.length) < 11.6 ? 12 : 17;
                     titleFont = 'normal ' + fontSize + 'px ' + conf.chart.style.fontFamily;
                     titleColor = 'black';
 
@@ -3294,19 +3354,19 @@
                         font: titleFont,
                         fill: titleColor,
                         height: 20,
-                        y: ns.dashboard ? 7 : 20
+                        y: appConfig.dashboard ? 7 : 20
                     });
                 };
 
                 getDefaultChartSizeHandler = function() {
                     return function() {
-                        var width = ns.app.centerRegion.getWidth(),
-                            height = ns.app.centerRegion.getHeight();
+                        var width = app.getCenterRegionWidth(),
+                            height = app.getCenterRegionHeight();
 
 						this.animate = false;
-                        this.setWidth(ns.dashboard ? width : width - 15);
-                        this.setHeight(ns.dashboard ? height : height - 40);
-                        this.animate = !ns.dashboard;
+                        this.setWidth(appConfig.dashboard ? width : width - 15);
+                        this.setHeight(appConfig.dashboard ? height : height - 40);
+                        this.animate = !appConfig.dashboard;
                     };
                 };
 
@@ -3339,22 +3399,22 @@
                 getDefaultChart = function(config) {
                     var chart,
                         store = config.store || {},
-                        width = ns.app.centerRegion.getWidth(),
-                        height = ns.app.centerRegion.getHeight(),
+                        width = app.getCenterRegionWidth(),
+                        height = app.getCenterRegionHeight(),
                         isLineBased = Ext.Array.contains(['line', 'area'], xLayout.type),
                         defaultConfig = {
                             //animate: true,
                             animate: false,
                             shadow: false,
-                            insetPadding: ns.dashboard ? 17 : 35,
+                            insetPadding: appConfig.dashboard ? 17 : 35,
                             insetPaddingObject: {
-                                top: ns.dashboard ? 12 : 32,
-                                right: ns.dashboard ? (isLineBased ? 5 : 3) : (isLineBased ? 25 : 15),
-                                bottom: ns.dashboard ? 2 : 10,
-                                left: ns.dashboard ? (isLineBased ? 15 : 7) : (isLineBased ? 70 : 50)
+                                top: appConfig.dashboard ? 12 : 32,
+                                right: appConfig.dashboard ? (isLineBased ? 5 : 3) : (isLineBased ? 25 : 15),
+                                bottom: appConfig.dashboard ? 2 : 10,
+                                left: appConfig.dashboard ? (isLineBased ? 15 : 7) : (isLineBased ? 70 : 50)
                             },
-                            width: ns.dashboard ? width : width - 15,
-                            height: ns.dashboard ? height : height - 40,
+                            width: appConfig.dashboard ? width : width - 15,
+                            height: appConfig.dashboard ? height : height - 40,
                             theme: 'dv1'
                         };
 
@@ -3363,15 +3423,15 @@
                         defaultConfig.legend = getDefaultLegend(store, config);
 
                         if (defaultConfig.legend.position === 'right') {
-                            defaultConfig.insetPaddingObject.top = ns.dashboard ? 22 : 40;
-                            defaultConfig.insetPaddingObject.right = ns.dashboard ? 5 : 40;
+                            defaultConfig.insetPaddingObject.top = appConfig.dashboard ? 22 : 40;
+                            defaultConfig.insetPaddingObject.right = appConfig.dashboard ? 5 : 40;
                         }
                     }
 
                     // title
                     if (xLayout.hideTitle) {
-                        defaultConfig.insetPadding = ns.dashboard ? 1 : 10;
-                        defaultConfig.insetPaddingObject.top = ns.dashboard ? 3 : 10;
+                        defaultConfig.insetPadding = appConfig.dashboard ? 1 : 10;
+                        defaultConfig.insetPaddingObject.top = appConfig.dashboard ? 3 : 10;
                     }
                     else {
                         defaultConfig.items = [getDefaultChartTitle(store)];
@@ -3550,7 +3610,7 @@
                             },
                             markerConfig: {
                                 type: 'circle',
-                                radius: ns.dashboard ? 3 : 4
+                                radius: appConfig.dashboard ? 3 : 4
                             },
                             tips: getDefaultTips(),
                             title: seriesTitles[i]
@@ -3732,10 +3792,10 @@
                         store: store,
                         series: series,
                         insetPaddingObject: {
-                            top: ns.dashboard ? 15 : 40,
-                            right: ns.dashboard ? 2 : 30,
-                            bottom: ns.dashboard ? 13: 30,
-                            left: ns.dashboard ? 7 : 30
+                            top: appConfig.dashboard ? 15 : 40,
+                            right: appConfig.dashboard ? 2 : 30,
+                            bottom: appConfig.dashboard ? 13: 30,
+                            left: appConfig.dashboard ? 7 : 30
                         }
                     });
 
@@ -3864,10 +3924,10 @@
                     chart = getDefaultChart({
                         axes: [axis],
                         series: [series],
-                        width: ns.app.centerRegion.getWidth(),
-                        height: ns.app.centerRegion.getHeight() * 0.6,
+                        width: app.getCenterRegionWidth(),
+                        height: app.getCenterRegionHeight() * 0.6,
                         store: store,
-                        insetPadding: ns.dashboard ? 50 : 100,
+                        insetPadding: appConfig.dashboard ? 50 : 100,
                         theme: null,
                         //animate: {
                             //easing: 'elasticIn',
@@ -3889,8 +3949,8 @@
 
                     chart.setChartSize = function() {
 						//this.animate = false;
-                        this.setWidth(ns.app.centerRegion.getWidth());
-                        this.setHeight(ns.app.centerRegion.getHeight() * 0.6);
+                        this.setWidth(app.getCenterRegionWidth());
+                        this.setHeight(app.getCenterRegionHeight() * 0.6);
                         //this.animate = true;
                     };
 
@@ -3902,7 +3962,7 @@
 
                             if (title) {
                                 var titleWidth = Ext.isIE ? title.el.dom.scrollWidth : title.el.getWidth(),
-                                    titleX = titleWidth ? (ns.app.centerRegion.getWidth() / 2) - (titleWidth / 2) : titleXFallback;
+                                    titleX = titleWidth ? (app.getCenterRegionWidth() / 2) - (titleWidth / 2) : titleXFallback;
                                 title.setAttributes({
                                     x: titleX
                                 }, true);
@@ -3910,7 +3970,7 @@
 
                             if (subTitle) {
                                 var subTitleWidth = Ext.isIE ? subTitle.el.dom.scrollWidth : subTitle.el.getWidth(),
-                                    subTitleX = subTitleWidth ? (ns.app.centerRegion.getWidth() / 2) - (subTitleWidth / 2) : titleXFallback;
+                                    subTitleX = subTitleWidth ? (app.getCenterRegionWidth() / 2) - (subTitleWidth / 2) : titleXFallback;
                                 subTitle.setAttributes({
                                     x: subTitleX
                                 }, true);
@@ -3949,15 +4009,18 @@
 		}());
 
 		// alert
-        ns.alert = web.message.alert;
-
-		ns.conf = conf;
-		ns.api = api;
-		ns.support = support;
-		ns.service = service;
-		ns.web = web;
-
-		return ns;
+		webAlert = web.message.alert;
+
+		return {
+            init: init,
+            conf: conf,
+            api: api,
+            support: support,
+            service: service,
+            web: web,
+            app: app,
+            webAlert: webAlert
+        };
     };
 
     // PLUGIN
@@ -3985,7 +4048,8 @@
 		var isInit = false,
 			requests = [],
 			callbacks = 0,
-            type = config.plugin && config.crossDomain ? 'jsonp' : 'json',
+            type = 'json',
+            ajax,
 			fn;
 
         init.contextPath = config.url;
@@ -4002,6 +4066,15 @@
 			}
 		};
 
+        ajax = function(requestConfig, authConfig) {
+            if (authConfig.crossDomain && Ext.isString(authConfig.username) && Ext.isString(authConfig.password)) {
+                requestConfig.headers = Ext.isObject(authConfig.headers) ? authConfig.headers : {};
+                requestConfig.headers['Authorization'] = 'Basic ' + btoa(authConfig.username + ':' + authConfig.password);
+            }
+
+            Ext.Ajax.request(requestConfig);
+        };
+
         // user-account
         requests.push({
             url: init.contextPath + '/api/me/user-account.' + type,
@@ -4074,17 +4147,13 @@
 		});
 
 		for (var i = 0; i < requests.length; i++) {
-            if (type === 'jsonp') {
-                Ext.data.JsonP.request(requests[i]);
-            }
-            else {
-                Ext.Ajax.request(requests[i]);
-            }
+            ajax(requests[i], config);
 		}
 	};
 
-	applyCss = function() {
-        var css = '';
+	applyCss = function(config) {
+        var css = '',
+            errorUrl = config.dashboard ? init.contextPath + '/dhis-web-commons/javascripts/plugin/images/error_m.png' : '//dhis2-cdn.org/v220/plugin/images/error_m.png';
 
         // tooltip
         css += '.dv-chart-tips { border-radius: 2px; padding: 2px 3px 0; border: 0 none; background-color: #000; opacity: 0.9 } \n';
@@ -4100,6 +4169,10 @@
         // alert
         css += '.ns-plugin-alert { width: 90%; padding: 5%; color: #777 } \n';
 
+        css += '.x-window-body { font-size: 13px; } \n';
+        css += '.ns-window-title-messagebox { padding-left: 16px; background-position-y: 1px; } \n';
+        css += '.ns-window-title-messagebox.error { background-image: url("' + errorUrl + '"); } \n';
+
         Ext.util.CSS.createStyleSheet(css);
     };
 
@@ -4130,14 +4203,14 @@
 			return true;
 		};
 
-        extendInstance = function(ns) {
+        extendInstance = function(ns, appConfig) {
             var init = ns.core.init,
 				api = ns.core.api,
                 conf = ns.core.conf,
 				support = ns.core.support,
 				service = ns.core.service,
 				web = ns.core.web,
-                type = ns.plugin && ns.crossDomain ? 'jsonp' : 'json',
+                type = 'json',
                 headerMap = {
                     json: 'application/json',
                     jsonp: 'application/javascript'
@@ -4148,6 +4221,19 @@
                 },
                 el = Ext.get(config.el);
 
+			init.el = config.el;
+
+			// ns
+            ns.plugin = appConfig.plugin;
+            ns.dashboard = appConfig.dashboard;
+            ns.crossDomain = appConfig.crossDomain;
+            ns.skipMask = appConfig.skipMask;
+            ns.skipFade = appConfig.skipFade;
+            ns.el = appConfig.el;
+            ns.username = appConfig.username;
+            ns.password = appConfig.password;
+            ns.ajax = support.connection.ajax;
+
 			// message
 			web.message = web.message || {};
 
@@ -4354,17 +4440,6 @@
                     }
                 }
 			};
-
-            // ns
-            ns.plugin = init.plugin;
-            ns.dashboard = init.dashboard;
-            ns.crossDomain = init.crossDomain;
-            ns.skipMask = init.skipMask;
-            ns.skipFade = init.skipFade;
-
-            ns.alert = web.message.alert;
-
-			init.el = config.el;
         };
 
 		createViewport = function() {
@@ -4404,25 +4479,29 @@
 				return;
 			}
 
+            appConfig = {
+                plugin: true,
+                dashboard: Ext.isBoolean(config.dashboard) ? config.dashboard : false,
+                crossDomain: Ext.isBoolean(config.crossDomain) ? config.crossDomain : true,
+                skipMask: Ext.isBoolean(config.skipMask) ? config.skipMask : false,
+                skipFade: Ext.isBoolean(config.skipFade) ? config.skipFade : false,
+                el: Ext.isString(config.el) ? config.el : null,
+                username: Ext.isString(config.username) ? config.username : null,
+                password: Ext.isString(config.password) ? config.password : null
+            };
+
             // css
-			applyCss();
-
-            // config
-            init.plugin = true;
-            init.dashboard = Ext.isBoolean(config.dashboard) ? config.dashboard : false;
-            init.crossDomain = Ext.isBoolean(config.crossDomain) ? config.crossDomain : true;
-            init.skipMask = Ext.isBoolean(config.skipMask) ? config.skipMask : false;
-            init.skipFade = Ext.isBoolean(config.skipFade) ? config.skipFade : false;
-
-            // init
-            ns.init = init;
-            DV.instances.push(ns);
-			ns.core = DV.getCore(ns);
-			extendInstance(ns);
+			applyCss(config);
+
+            // core
+			ns.core = DV.getCore(init, appConfig);
+			extendInstance(ns, appConfig);
 
 			ns.app.viewport = createViewport();
 			ns.app.centerRegion = ns.app.viewport.centerRegion;
 
+            DV.instances.push(ns);
+
             if (el) {
                 el.setViewportWidth = function(width) {
                     ns.app.centerRegion.setWidth(width);

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/core.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/core.js	2015-09-04 14:37:08 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/core.js	2015-09-07 12:21:50 +0000
@@ -516,17 +516,26 @@
 	NS.isDebug = false;
 	NS.isSessionStorage = ('sessionStorage' in window && window['sessionStorage'] !== null);
 
-	NS.getCore = function(ns) {
-        var init = ns.init,
-            conf = {},
+	NS.getCore = function(init, appConfig) {
+        var conf = {},
             api = {},
             support = {},
             service = {},
             web = {},
+            app = {},
+            webAlert,
             dimConf;
 
-        // tmp
-        ns.alert = function() {};
+        appConfig = appConfig || {};
+
+        // alert
+        webAlert = function() {};
+
+        // app
+        app.getViewportWidth = function() {};
+        app.getViewportHeight = function() {};
+        app.getCenterRegionWidth = function() {};
+        app.getCenterRegionHeight = function() {};
 
 		// conf
         (function() {
@@ -1013,19 +1022,19 @@
 
 							// Indicators as filter
 							if (layout.filters[i].dimension === dimConf.indicator.objectName) {
-								ns.alert(NS.i18n.indicators_cannot_be_specified_as_filter || 'Indicators cannot be specified as filter.');
+								webAlert(NS.i18n.indicators_cannot_be_specified_as_filter || 'Indicators cannot be specified as filter.');
 								return;
 							}
 
 							// Categories as filter
 							if (layout.filters[i].dimension === dimConf.category.objectName) {
-								ns.alert(NS.i18n.categories_cannot_be_specified_as_filter || 'Categories cannot be specified as filter.');
+								webAlert(NS.i18n.categories_cannot_be_specified_as_filter || 'Categories cannot be specified as filter.');
 								return;
 							}
 
 							// Data sets as filter
 							if (layout.filters[i].dimension === dimConf.dataSet.objectName) {
-								ns.alert(NS.i18n.data_sets_cannot_be_specified_as_filter || 'Data sets cannot be specified as filter.');
+								webAlert(NS.i18n.data_sets_cannot_be_specified_as_filter || 'Data sets cannot be specified as filter.');
 								return;
 							}
 						}
@@ -1033,31 +1042,31 @@
 
 					// dc and in
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.indicator.objectName]) {
-						ns.alert('Indicators and detailed data elements cannot be specified together.', true);
+						webAlert('Indicators and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
 					// dc and de
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.dataElement.objectName]) {
-						ns.alert('Detailed data elements and totals cannot be specified together.', true);
+						webAlert('Detailed data elements and totals cannot be specified together.', true);
 						return;
 					}
 
 					// dc and ds
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.dataSet.objectName]) {
-						ns.alert('Data sets and detailed data elements cannot be specified together.', true);
+						webAlert('Data sets and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
 					// dc and co
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.category.objectName]) {
-						ns.alert('Categories and detailed data elements cannot be specified together.', true);
+						webAlert('Categories and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
                     // in and aggregation type
                     if (objectNameDimensionMap[dimConf.indicator.objectName] && config.aggregationType !== 'DEFAULT') {
-                        ns.alert('Indicators and aggregation types cannot be specified together.', true);
+                        webAlert('Indicators and aggregation types cannot be specified together.', true);
                         return;
                     }
 
@@ -1070,7 +1079,7 @@
 
 					// config must be an object
 					if (!(config && Ext.isObject(config))) {
-						ns.alert('Layout: config is not an object (' + init.el + ')', true);
+						webAlert('Layout: config is not an object (' + init.el + ')', true);
 						return;
 					}
 
@@ -1080,12 +1089,12 @@
 
 					// at least one dimension specified as column and row
 					if (!config.columns) {
-						ns.alert('No series items selected');
+						webAlert('No series items selected');
 						return;
 					}
 
 					if (!config.rows) {
-						ns.alert('No category items selected');
+						webAlert('No category items selected');
 						return;
 					}
 
@@ -1100,7 +1109,7 @@
 
 					// at least one period
 					if (!Ext.Array.contains(objectNames, dimConf.period.objectName)) {
-						ns.alert('At least one period must be specified as series, category or filter');
+						webAlert('At least one period must be specified as series, category or filter');
 						return;
 					}
 
@@ -1463,6 +1472,17 @@
                 return date.getFullYear() + '-' + month + '-' + day;
             };
 
+            // connection
+            support.connection = {};
+
+            support.connection.ajax = function(requestConfig, authConfig) {
+                if (authConfig.crossDomain && Ext.isString(authConfig.username) && Ext.isString(authConfig.password)) {
+                    requestConfig.headers = Ext.isObject(authConfig.headers) ? authConfig.headers : {};
+                    requestConfig.headers['Authorization'] = 'Basic ' + btoa(authConfig.username + ':' + authConfig.password);
+                }
+
+                Ext.Ajax.request(requestConfig);
+            };
         }());
 
 		// service
@@ -2210,7 +2230,7 @@
 			web.window = {};
 
 			web.window.setAnchorPosition = function(w, target) {
-				var vpw = ns.app.viewport.getWidth(),
+				var vpw = app.getViewportWidth(),
 					targetx = target ? target.getPosition()[0] : 4,
 					winw = w.getWidth(),
 					y = target ? target.getPosition()[1] + target.getHeight() + 4 : 33;
@@ -2287,7 +2307,7 @@
                 config.html += obj.message + (obj.message.substr(obj.message.length - 1) === '.' ? '' : '.');
 
                 // bodyStyle
-                config.bodyStyle = 'padding: 12px; background: #fff; max-width: 600px; max-height: ' + ns.app.centerRegion.getHeight() / 2 + 'px';
+                config.bodyStyle = 'padding: 12px; background: #fff; max-width: 600px; max-height: ' + app.getCenterRegionHeight() / 2 + 'px';
 
                 // destroy handler
                 config.modal = true;
@@ -2399,7 +2419,7 @@
 
                 msg += '\n\n' + 'Hint: A good way to reduce the number of items is to use relative periods and level/group organisation unit selection modes.';
 
-                ns.alert(msg, 'warning');
+                webAlert(msg, 'warning');
 			};
 
 			// chart
@@ -2563,7 +2583,7 @@
                                 }
 
                                 trendLineFields.push(regressionKey);
-                                xResponse.metaData.names[regressionKey] = NS.i18n.trend + (ns.dashboard ? '' : ' (' + xResponse.metaData.names[failSafeColumnIds[i]] + ')');
+                                xResponse.metaData.names[regressionKey] = NS.i18n.trend + (appConfig.dashboard ? '' : ' (' + xResponse.metaData.names[failSafeColumnIds[i]] + ')');
                             }
                         }
                     }
@@ -2886,15 +2906,15 @@
                 };
 
                 getFormatedSeriesTitle = function(titles) {
-                    var itemLength = ns.dashboard ? 23 : 30,
-                        charLength = ns.dashboard ? 5 : 6,
+                    var itemLength = appConfig.dashboard ? 23 : 30,
+                        charLength = appConfig.dashboard ? 5 : 6,
                         numberOfItems = titles.length,
                         numberOfChars,
                         totalItemLength = numberOfItems * itemLength,
                         //minLength = 5,
                         maxLength = support.prototype.array.getMaxLength(titles),
                         fallbackLength = 10,
-                        maxWidth = ns.app.centerRegion.getWidth(),
+                        maxWidth = app.getCenterRegionWidth(),
                         width,
                         validateTitles;
 
@@ -2956,7 +2976,7 @@
                         }
                     }
 
-                    return ns.dashboard ? getFormatedSeriesTitle(a) : a;
+                    return appConfig.dashboard ? getFormatedSeriesTitle(a) : a;
 				};
 
                 getPieSeriesTitle = function(store) {
@@ -2985,7 +3005,7 @@
                         });
                     }
 
-                    return ns.dashboard ? getFormatedSeriesTitle(a) : a;
+                    return appConfig.dashboard ? getFormatedSeriesTitle(a) : a;
 				};
 
                 getDefaultSeries = function(store) {
@@ -3144,8 +3164,8 @@
                 };
 
                 getDefaultLegend = function(store, chartConfig) {
-                    var itemLength = ns.dashboard ? 24 : 30,
-                        charLength = ns.dashboard ? 4 : 6,
+                    var itemLength = appConfig.dashboard ? 24 : 30,
+                        charLength = appConfig.dashboard ? 4 : 6,
                         numberOfItems = 0,
                         numberOfChars = 0,
                         width,
@@ -3174,7 +3194,7 @@
 
                     width = (numberOfItems * itemLength) + (numberOfChars * charLength);
 
-                    if (width > ns.app.centerRegion.getWidth() - 6) {
+                    if (width > app.getCenterRegionWidth() - 6) {
                         position = 'right';
                     }
 
@@ -3250,7 +3270,7 @@
                         text = xLayout.title;
                     }
 
-                    fontSize = (ns.app.centerRegion.getWidth() / text.length) < 11.6 ? 12 : 17;
+                    fontSize = (app.getCenterRegionWidth() / text.length) < 11.6 ? 12 : 17;
                     titleFont = 'normal ' + fontSize + 'px ' + conf.chart.style.fontFamily;
                     titleColor = 'black';
 
@@ -3276,19 +3296,19 @@
                         font: titleFont,
                         fill: titleColor,
                         height: 20,
-                        y: ns.dashboard ? 7 : 20
+                        y: appConfig.dashboard ? 7 : 20
                     });
                 };
 
                 getDefaultChartSizeHandler = function() {
                     return function() {
-                        var width = ns.app.centerRegion.getWidth(),
-                            height = ns.app.centerRegion.getHeight();
+                        var width = app.getCenterRegionWidth(),
+                            height = app.getCenterRegionHeight();
 
 						this.animate = false;
-                        this.setWidth(ns.dashboard ? width : width - 15);
-                        this.setHeight(ns.dashboard ? height : height - 40);
-                        this.animate = !ns.dashboard;
+                        this.setWidth(appConfig.dashboard ? width : width - 15);
+                        this.setHeight(appConfig.dashboard ? height : height - 40);
+                        this.animate = !appConfig.dashboard;
                     };
                 };
 
@@ -3321,22 +3341,22 @@
                 getDefaultChart = function(config) {
                     var chart,
                         store = config.store || {},
-                        width = ns.app.centerRegion.getWidth(),
-                        height = ns.app.centerRegion.getHeight(),
+                        width = app.getCenterRegionWidth(),
+                        height = app.getCenterRegionHeight(),
                         isLineBased = Ext.Array.contains(['line', 'area'], xLayout.type),
                         defaultConfig = {
                             //animate: true,
                             animate: false,
                             shadow: false,
-                            insetPadding: ns.dashboard ? 17 : 35,
+                            insetPadding: appConfig.dashboard ? 17 : 35,
                             insetPaddingObject: {
-                                top: ns.dashboard ? 12 : 32,
-                                right: ns.dashboard ? (isLineBased ? 5 : 3) : (isLineBased ? 25 : 15),
-                                bottom: ns.dashboard ? 2 : 10,
-                                left: ns.dashboard ? (isLineBased ? 15 : 7) : (isLineBased ? 70 : 50)
+                                top: appConfig.dashboard ? 12 : 32,
+                                right: appConfig.dashboard ? (isLineBased ? 5 : 3) : (isLineBased ? 25 : 15),
+                                bottom: appConfig.dashboard ? 2 : 10,
+                                left: appConfig.dashboard ? (isLineBased ? 15 : 7) : (isLineBased ? 70 : 50)
                             },
-                            width: ns.dashboard ? width : width - 15,
-                            height: ns.dashboard ? height : height - 40,
+                            width: appConfig.dashboard ? width : width - 15,
+                            height: appConfig.dashboard ? height : height - 40,
                             theme: 'dv1'
                         };
 
@@ -3345,15 +3365,15 @@
                         defaultConfig.legend = getDefaultLegend(store, config);
 
                         if (defaultConfig.legend.position === 'right') {
-                            defaultConfig.insetPaddingObject.top = ns.dashboard ? 22 : 40;
-                            defaultConfig.insetPaddingObject.right = ns.dashboard ? 5 : 40;
+                            defaultConfig.insetPaddingObject.top = appConfig.dashboard ? 22 : 40;
+                            defaultConfig.insetPaddingObject.right = appConfig.dashboard ? 5 : 40;
                         }
                     }
 
                     // title
                     if (xLayout.hideTitle) {
-                        defaultConfig.insetPadding = ns.dashboard ? 1 : 10;
-                        defaultConfig.insetPaddingObject.top = ns.dashboard ? 3 : 10;
+                        defaultConfig.insetPadding = appConfig.dashboard ? 1 : 10;
+                        defaultConfig.insetPaddingObject.top = appConfig.dashboard ? 3 : 10;
                     }
                     else {
                         defaultConfig.items = [getDefaultChartTitle(store)];
@@ -3532,7 +3552,7 @@
                             },
                             markerConfig: {
                                 type: 'circle',
-                                radius: ns.dashboard ? 3 : 4
+                                radius: appConfig.dashboard ? 3 : 4
                             },
                             tips: getDefaultTips(),
                             title: seriesTitles[i]
@@ -3714,10 +3734,10 @@
                         store: store,
                         series: series,
                         insetPaddingObject: {
-                            top: ns.dashboard ? 15 : 40,
-                            right: ns.dashboard ? 2 : 30,
-                            bottom: ns.dashboard ? 13: 30,
-                            left: ns.dashboard ? 7 : 30
+                            top: appConfig.dashboard ? 15 : 40,
+                            right: appConfig.dashboard ? 2 : 30,
+                            bottom: appConfig.dashboard ? 13: 30,
+                            left: appConfig.dashboard ? 7 : 30
                         }
                     });
 
@@ -3846,10 +3866,10 @@
                     chart = getDefaultChart({
                         axes: [axis],
                         series: [series],
-                        width: ns.app.centerRegion.getWidth(),
-                        height: ns.app.centerRegion.getHeight() * 0.6,
+                        width: app.getCenterRegionWidth(),
+                        height: app.getCenterRegionHeight() * 0.6,
                         store: store,
-                        insetPadding: ns.dashboard ? 50 : 100,
+                        insetPadding: appConfig.dashboard ? 50 : 100,
                         theme: null,
                         //animate: {
                             //easing: 'elasticIn',
@@ -3871,8 +3891,8 @@
 
                     chart.setChartSize = function() {
 						//this.animate = false;
-                        this.setWidth(ns.app.centerRegion.getWidth());
-                        this.setHeight(ns.app.centerRegion.getHeight() * 0.6);
+                        this.setWidth(app.getCenterRegionWidth());
+                        this.setHeight(app.getCenterRegionHeight() * 0.6);
                         //this.animate = true;
                     };
 
@@ -3884,7 +3904,7 @@
 
                             if (title) {
                                 var titleWidth = Ext.isIE ? title.el.dom.scrollWidth : title.el.getWidth(),
-                                    titleX = titleWidth ? (ns.app.centerRegion.getWidth() / 2) - (titleWidth / 2) : titleXFallback;
+                                    titleX = titleWidth ? (app.getCenterRegionWidth() / 2) - (titleWidth / 2) : titleXFallback;
                                 title.setAttributes({
                                     x: titleX
                                 }, true);
@@ -3892,7 +3912,7 @@
 
                             if (subTitle) {
                                 var subTitleWidth = Ext.isIE ? subTitle.el.dom.scrollWidth : subTitle.el.getWidth(),
-                                    subTitleX = subTitleWidth ? (ns.app.centerRegion.getWidth() / 2) - (subTitleWidth / 2) : titleXFallback;
+                                    subTitleX = subTitleWidth ? (app.getCenterRegionWidth() / 2) - (subTitleWidth / 2) : titleXFallback;
                                 subTitle.setAttributes({
                                     x: subTitleX
                                 }, true);
@@ -3931,14 +3951,17 @@
 		}());
 
 		// alert
-        ns.alert = web.message.alert;
-
-		ns.conf = conf;
-		ns.api = api;
-		ns.support = support;
-		ns.service = service;
-		ns.web = web;
-
-		return ns;
+		webAlert = web.message.alert;
+
+		return {
+            init: init,
+            conf: conf,
+            api: api,
+            support: support,
+            service: service,
+            web: web,
+            app: app,
+            webAlert: webAlert
+        };
     };
 });

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/chart.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/chart.js	2015-08-19 21:30:33 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/chart.js	2015-09-07 12:21:50 +0000
@@ -574,17 +574,26 @@
 	DV.isDebug = false;
 	DV.isSessionStorage = ('sessionStorage' in window && window['sessionStorage'] !== null);
 
-	DV.getCore = function(ns) {
-        var init = ns.init,
-            conf = {},
+	DV.getCore = function(init, appConfig) {
+        var conf = {},
             api = {},
             support = {},
             service = {},
             web = {},
+            app = {},
+            webAlert,
             dimConf;
 
-        // tmp
-        ns.alert = function() {};
+        appConfig = appConfig || {};
+
+        // alert
+        webAlert = function() {};
+
+        // app
+        app.getViewportWidth = function() {};
+        app.getViewportHeight = function() {};
+        app.getCenterRegionWidth = function() {};
+        app.getCenterRegionHeight = function() {};
 
 		// conf
         (function() {
@@ -726,6 +735,14 @@
 				]
 			};
 
+            conf.valueType = {
+            	numericTypes: ['NUMBER','UNIT_INTERVAL','PERCENTAGE','INTEGER','INTEGER_POSITIVE','INTEGER_NEGATIVE','INTEGER_ZERO_OR_POSITIVE'],
+            	textTypes: ['TEXT','LONG_TEXT','LETTER','PHONE_NUMBER','EMAIL'],
+            	booleanTypes: ['BOOLEAN','TRUE_ONLY'],
+            	dateTypes: ['DATE','DATETIME'],
+            	aggregateTypes: ['NUMBER','UNIT_INTERVAL','PERCENTAGE','INTEGER','INTEGER_POSITIVE','INTEGER_NEGATIVE','INTEGER_ZERO_OR_POSITIVE','BOOLEAN','TRUE_ONLY']
+            };
+
             conf.layout = {
                 west_width: 424,
                 west_fieldset_width: 418,
@@ -1063,19 +1080,19 @@
 
 							// Indicators as filter
 							if (layout.filters[i].dimension === dimConf.indicator.objectName) {
-								ns.alert(DV.i18n.indicators_cannot_be_specified_as_filter || 'Indicators cannot be specified as filter.');
+								webAlert(DV.i18n.indicators_cannot_be_specified_as_filter || 'Indicators cannot be specified as filter.');
 								return;
 							}
 
 							// Categories as filter
 							if (layout.filters[i].dimension === dimConf.category.objectName) {
-								ns.alert(DV.i18n.categories_cannot_be_specified_as_filter || 'Categories cannot be specified as filter.');
+								webAlert(DV.i18n.categories_cannot_be_specified_as_filter || 'Categories cannot be specified as filter.');
 								return;
 							}
 
 							// Data sets as filter
 							if (layout.filters[i].dimension === dimConf.dataSet.objectName) {
-								ns.alert(DV.i18n.data_sets_cannot_be_specified_as_filter || 'Data sets cannot be specified as filter.');
+								webAlert(DV.i18n.data_sets_cannot_be_specified_as_filter || 'Data sets cannot be specified as filter.');
 								return;
 							}
 						}
@@ -1083,31 +1100,31 @@
 
 					// dc and in
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.indicator.objectName]) {
-						ns.alert('Indicators and detailed data elements cannot be specified together.', true);
+						webAlert('Indicators and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
 					// dc and de
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.dataElement.objectName]) {
-						ns.alert('Detailed data elements and totals cannot be specified together.', true);
+						webAlert('Detailed data elements and totals cannot be specified together.', true);
 						return;
 					}
 
 					// dc and ds
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.dataSet.objectName]) {
-						ns.alert('Data sets and detailed data elements cannot be specified together.', true);
+						webAlert('Data sets and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
 					// dc and co
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.category.objectName]) {
-						ns.alert('Categories and detailed data elements cannot be specified together.', true);
+						webAlert('Categories and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
                     // in and aggregation type
                     if (objectNameDimensionMap[dimConf.indicator.objectName] && config.aggregationType !== 'DEFAULT') {
-                        ns.alert('Indicators and aggregation types cannot be specified together.', true);
+                        webAlert('Indicators and aggregation types cannot be specified together.', true);
                         return;
                     }
 
@@ -1120,7 +1137,7 @@
 
 					// config must be an object
 					if (!(config && Ext.isObject(config))) {
-						ns.alert('Layout: config is not an object (' + init.el + ')', true);
+						webAlert('Layout: config is not an object (' + init.el + ')', true);
 						return;
 					}
 
@@ -1130,12 +1147,12 @@
 
 					// at least one dimension specified as column and row
 					if (!config.columns) {
-						ns.alert('No series items selected');
+						webAlert('No series items selected');
 						return;
 					}
 
 					if (!config.rows) {
-						ns.alert('No category items selected');
+						webAlert('No category items selected');
 						return;
 					}
 
@@ -1150,7 +1167,7 @@
 
 					// at least one period
 					if (!Ext.Array.contains(objectNames, dimConf.period.objectName)) {
-						ns.alert('At least one period must be specified as series, category or filter');
+						webAlert('At least one period must be specified as series, category or filter');
 						return;
 					}
 
@@ -1214,6 +1231,11 @@
                         layout.program = config.program;
                     }
 
+                    // relative period date
+                    if (support.prototype.date.getYYYYMMDD(config.relativePeriodDate)) {
+                        layout.relativePeriodDate = support.prototype.date.getYYYYMMDD(config.relativePeriodDate);
+                    }
+
                     // style
                     if (Ext.isObject(config.domainAxisStyle)) {
                         layout.domainAxisStyle = config.domainAxisStyle;
@@ -1231,6 +1253,7 @@
                         layout.seriesStyle = config.seriesStyle;
                     }
 
+                    // validate
 					if (!validateSpecialCases()) {
 						return;
 					}
@@ -1486,7 +1509,39 @@
 
                 return variable;
 			};
-		}());
+
+                // date
+            support.prototype.date = {};
+
+            support.prototype.date.getYYYYMMDD = function(param) {
+                if (!Ext.isString(param)) {
+                    if (!(Object.prototype.toString.call(param) === '[object Date]' && param.toString() !== 'Invalid date')) {
+                        return null;
+                    }
+                }
+
+                var date = new Date(param),
+                    month = '' + (1 + date.getMonth()),
+                    day = '' + date.getDate();
+
+                month = month.length === 1 ? '0' + month : month;
+                day = day.length === 1 ? '0' + day : day;
+
+                return date.getFullYear() + '-' + month + '-' + day;
+            };
+
+            // connection
+            support.connection = {};
+
+            support.connection.ajax = function(requestConfig, authConfig) {
+                if (authConfig.crossDomain && Ext.isString(authConfig.username) && Ext.isString(authConfig.password)) {
+                    requestConfig.headers = Ext.isObject(authConfig.headers) ? authConfig.headers : {};
+                    requestConfig.headers['Authorization'] = 'Basic ' + btoa(authConfig.username + ':' + authConfig.password);
+                }
+
+                Ext.Ajax.request(requestConfig);
+            };
+        }());
 
 		// service
 		(function() {
@@ -2233,7 +2288,7 @@
 			web.window = {};
 
 			web.window.setAnchorPosition = function(w, target) {
-				var vpw = ns.app.viewport.getWidth(),
+				var vpw = app.getViewportWidth(),
 					targetx = target ? target.getPosition()[0] : 4,
 					winw = w.getWidth(),
 					y = target ? target.getPosition()[1] + target.getHeight() + 4 : 33;
@@ -2310,7 +2365,7 @@
                 config.html += obj.message + (obj.message.substr(obj.message.length - 1) === '.' ? '' : '.');
 
                 // bodyStyle
-                config.bodyStyle = 'padding: 12px; background: #fff; max-width: 600px; max-height: ' + ns.app.centerRegion.getHeight() / 2 + 'px';
+                config.bodyStyle = 'padding: 12px; background: #fff; max-width: 600px; max-height: ' + app.getCenterRegionHeight() / 2 + 'px';
 
                 // destroy handler
                 config.modal = true;
@@ -2401,6 +2456,11 @@
                     paramString += '&program=' + xLayout.program.id;
                 }
 
+                // relative period date
+                if (xLayout.relativePeriodDate) {
+                    paramString += '&relativePeriodDate=' + xLayout.relativePeriodDate;
+                }
+
                 return paramString.replace(/#/g, '.');
             };
 
@@ -2417,7 +2477,7 @@
 
                 msg += '\n\n' + 'Hint: A good way to reduce the number of items is to use relative periods and level/group organisation unit selection modes.';
 
-                ns.alert(msg, 'warning');
+                webAlert(msg, 'warning');
 			};
 
 			// chart
@@ -2581,7 +2641,7 @@
                                 }
 
                                 trendLineFields.push(regressionKey);
-                                xResponse.metaData.names[regressionKey] = DV.i18n.trend + (ns.dashboard ? '' : ' (' + xResponse.metaData.names[failSafeColumnIds[i]] + ')');
+                                xResponse.metaData.names[regressionKey] = DV.i18n.trend + (appConfig.dashboard ? '' : ' (' + xResponse.metaData.names[failSafeColumnIds[i]] + ')');
                             }
                         }
                     }
@@ -2904,15 +2964,15 @@
                 };
 
                 getFormatedSeriesTitle = function(titles) {
-                    var itemLength = ns.dashboard ? 23 : 30,
-                        charLength = ns.dashboard ? 5 : 6,
+                    var itemLength = appConfig.dashboard ? 23 : 30,
+                        charLength = appConfig.dashboard ? 5 : 6,
                         numberOfItems = titles.length,
                         numberOfChars,
                         totalItemLength = numberOfItems * itemLength,
                         //minLength = 5,
                         maxLength = support.prototype.array.getMaxLength(titles),
                         fallbackLength = 10,
-                        maxWidth = ns.app.centerRegion.getWidth(),
+                        maxWidth = app.getCenterRegionWidth(),
                         width,
                         validateTitles;
 
@@ -2974,7 +3034,7 @@
                         }
                     }
 
-                    return ns.dashboard ? getFormatedSeriesTitle(a) : a;
+                    return appConfig.dashboard ? getFormatedSeriesTitle(a) : a;
 				};
 
                 getPieSeriesTitle = function(store) {
@@ -3003,7 +3063,7 @@
                         });
                     }
 
-                    return ns.dashboard ? getFormatedSeriesTitle(a) : a;
+                    return appConfig.dashboard ? getFormatedSeriesTitle(a) : a;
 				};
 
                 getDefaultSeries = function(store) {
@@ -3162,8 +3222,8 @@
                 };
 
                 getDefaultLegend = function(store, chartConfig) {
-                    var itemLength = ns.dashboard ? 24 : 30,
-                        charLength = ns.dashboard ? 4 : 6,
+                    var itemLength = appConfig.dashboard ? 24 : 30,
+                        charLength = appConfig.dashboard ? 4 : 6,
                         numberOfItems = 0,
                         numberOfChars = 0,
                         width,
@@ -3192,7 +3252,7 @@
 
                     width = (numberOfItems * itemLength) + (numberOfChars * charLength);
 
-                    if (width > ns.app.centerRegion.getWidth() - 6) {
+                    if (width > app.getCenterRegionWidth() - 6) {
                         position = 'right';
                     }
 
@@ -3268,7 +3328,7 @@
                         text = xLayout.title;
                     }
 
-                    fontSize = (ns.app.centerRegion.getWidth() / text.length) < 11.6 ? 12 : 17;
+                    fontSize = (app.getCenterRegionWidth() / text.length) < 11.6 ? 12 : 17;
                     titleFont = 'normal ' + fontSize + 'px ' + conf.chart.style.fontFamily;
                     titleColor = 'black';
 
@@ -3294,19 +3354,19 @@
                         font: titleFont,
                         fill: titleColor,
                         height: 20,
-                        y: ns.dashboard ? 7 : 20
+                        y: appConfig.dashboard ? 7 : 20
                     });
                 };
 
                 getDefaultChartSizeHandler = function() {
                     return function() {
-                        var width = ns.app.centerRegion.getWidth(),
-                            height = ns.app.centerRegion.getHeight();
+                        var width = app.getCenterRegionWidth(),
+                            height = app.getCenterRegionHeight();
 
 						this.animate = false;
-                        this.setWidth(ns.dashboard ? width : width - 15);
-                        this.setHeight(ns.dashboard ? height : height - 40);
-                        this.animate = !ns.dashboard;
+                        this.setWidth(appConfig.dashboard ? width : width - 15);
+                        this.setHeight(appConfig.dashboard ? height : height - 40);
+                        this.animate = !appConfig.dashboard;
                     };
                 };
 
@@ -3339,22 +3399,22 @@
                 getDefaultChart = function(config) {
                     var chart,
                         store = config.store || {},
-                        width = ns.app.centerRegion.getWidth(),
-                        height = ns.app.centerRegion.getHeight(),
+                        width = app.getCenterRegionWidth(),
+                        height = app.getCenterRegionHeight(),
                         isLineBased = Ext.Array.contains(['line', 'area'], xLayout.type),
                         defaultConfig = {
                             //animate: true,
                             animate: false,
                             shadow: false,
-                            insetPadding: ns.dashboard ? 17 : 35,
+                            insetPadding: appConfig.dashboard ? 17 : 35,
                             insetPaddingObject: {
-                                top: ns.dashboard ? 12 : 32,
-                                right: ns.dashboard ? (isLineBased ? 5 : 3) : (isLineBased ? 25 : 15),
-                                bottom: ns.dashboard ? 2 : 10,
-                                left: ns.dashboard ? (isLineBased ? 15 : 7) : (isLineBased ? 70 : 50)
+                                top: appConfig.dashboard ? 12 : 32,
+                                right: appConfig.dashboard ? (isLineBased ? 5 : 3) : (isLineBased ? 25 : 15),
+                                bottom: appConfig.dashboard ? 2 : 10,
+                                left: appConfig.dashboard ? (isLineBased ? 15 : 7) : (isLineBased ? 70 : 50)
                             },
-                            width: ns.dashboard ? width : width - 15,
-                            height: ns.dashboard ? height : height - 40,
+                            width: appConfig.dashboard ? width : width - 15,
+                            height: appConfig.dashboard ? height : height - 40,
                             theme: 'dv1'
                         };
 
@@ -3363,15 +3423,15 @@
                         defaultConfig.legend = getDefaultLegend(store, config);
 
                         if (defaultConfig.legend.position === 'right') {
-                            defaultConfig.insetPaddingObject.top = ns.dashboard ? 22 : 40;
-                            defaultConfig.insetPaddingObject.right = ns.dashboard ? 5 : 40;
+                            defaultConfig.insetPaddingObject.top = appConfig.dashboard ? 22 : 40;
+                            defaultConfig.insetPaddingObject.right = appConfig.dashboard ? 5 : 40;
                         }
                     }
 
                     // title
                     if (xLayout.hideTitle) {
-                        defaultConfig.insetPadding = ns.dashboard ? 1 : 10;
-                        defaultConfig.insetPaddingObject.top = ns.dashboard ? 3 : 10;
+                        defaultConfig.insetPadding = appConfig.dashboard ? 1 : 10;
+                        defaultConfig.insetPaddingObject.top = appConfig.dashboard ? 3 : 10;
                     }
                     else {
                         defaultConfig.items = [getDefaultChartTitle(store)];
@@ -3550,7 +3610,7 @@
                             },
                             markerConfig: {
                                 type: 'circle',
-                                radius: ns.dashboard ? 3 : 4
+                                radius: appConfig.dashboard ? 3 : 4
                             },
                             tips: getDefaultTips(),
                             title: seriesTitles[i]
@@ -3732,10 +3792,10 @@
                         store: store,
                         series: series,
                         insetPaddingObject: {
-                            top: ns.dashboard ? 15 : 40,
-                            right: ns.dashboard ? 2 : 30,
-                            bottom: ns.dashboard ? 13: 30,
-                            left: ns.dashboard ? 7 : 30
+                            top: appConfig.dashboard ? 15 : 40,
+                            right: appConfig.dashboard ? 2 : 30,
+                            bottom: appConfig.dashboard ? 13: 30,
+                            left: appConfig.dashboard ? 7 : 30
                         }
                     });
 
@@ -3864,10 +3924,10 @@
                     chart = getDefaultChart({
                         axes: [axis],
                         series: [series],
-                        width: ns.app.centerRegion.getWidth(),
-                        height: ns.app.centerRegion.getHeight() * 0.6,
+                        width: app.getCenterRegionWidth(),
+                        height: app.getCenterRegionHeight() * 0.6,
                         store: store,
-                        insetPadding: ns.dashboard ? 50 : 100,
+                        insetPadding: appConfig.dashboard ? 50 : 100,
                         theme: null,
                         //animate: {
                             //easing: 'elasticIn',
@@ -3889,8 +3949,8 @@
 
                     chart.setChartSize = function() {
 						//this.animate = false;
-                        this.setWidth(ns.app.centerRegion.getWidth());
-                        this.setHeight(ns.app.centerRegion.getHeight() * 0.6);
+                        this.setWidth(app.getCenterRegionWidth());
+                        this.setHeight(app.getCenterRegionHeight() * 0.6);
                         //this.animate = true;
                     };
 
@@ -3902,7 +3962,7 @@
 
                             if (title) {
                                 var titleWidth = Ext.isIE ? title.el.dom.scrollWidth : title.el.getWidth(),
-                                    titleX = titleWidth ? (ns.app.centerRegion.getWidth() / 2) - (titleWidth / 2) : titleXFallback;
+                                    titleX = titleWidth ? (app.getCenterRegionWidth() / 2) - (titleWidth / 2) : titleXFallback;
                                 title.setAttributes({
                                     x: titleX
                                 }, true);
@@ -3910,7 +3970,7 @@
 
                             if (subTitle) {
                                 var subTitleWidth = Ext.isIE ? subTitle.el.dom.scrollWidth : subTitle.el.getWidth(),
-                                    subTitleX = subTitleWidth ? (ns.app.centerRegion.getWidth() / 2) - (subTitleWidth / 2) : titleXFallback;
+                                    subTitleX = subTitleWidth ? (app.getCenterRegionWidth() / 2) - (subTitleWidth / 2) : titleXFallback;
                                 subTitle.setAttributes({
                                     x: subTitleX
                                 }, true);
@@ -3949,15 +4009,18 @@
 		}());
 
 		// alert
-        ns.alert = web.message.alert;
-
-		ns.conf = conf;
-		ns.api = api;
-		ns.support = support;
-		ns.service = service;
-		ns.web = web;
-
-		return ns;
+		webAlert = web.message.alert;
+
+		return {
+            init: init,
+            conf: conf,
+            api: api,
+            support: support,
+            service: service,
+            web: web,
+            app: app,
+            webAlert: webAlert
+        };
     };
 
     // PLUGIN
@@ -3985,7 +4048,8 @@
 		var isInit = false,
 			requests = [],
 			callbacks = 0,
-            type = config.plugin && config.crossDomain ? 'jsonp' : 'json',
+            type = 'json',
+            ajax,
 			fn;
 
         init.contextPath = config.url;
@@ -4002,6 +4066,15 @@
 			}
 		};
 
+        ajax = function(requestConfig, authConfig) {
+            if (authConfig.crossDomain && Ext.isString(authConfig.username) && Ext.isString(authConfig.password)) {
+                requestConfig.headers = Ext.isObject(authConfig.headers) ? authConfig.headers : {};
+                requestConfig.headers['Authorization'] = 'Basic ' + btoa(authConfig.username + ':' + authConfig.password);
+            }
+
+            Ext.Ajax.request(requestConfig);
+        };
+
         // user-account
         requests.push({
             url: init.contextPath + '/api/me/user-account.' + type,
@@ -4074,17 +4147,13 @@
 		});
 
 		for (var i = 0; i < requests.length; i++) {
-            if (type === 'jsonp') {
-                Ext.data.JsonP.request(requests[i]);
-            }
-            else {
-                Ext.Ajax.request(requests[i]);
-            }
+            ajax(requests[i], config);
 		}
 	};
 
-	applyCss = function() {
-        var css = '';
+	applyCss = function(config) {
+        var css = '',
+            errorUrl = config.dashboard ? init.contextPath + '/dhis-web-commons/javascripts/plugin/images/error_m.png' : '//dhis2-cdn.org/v220/plugin/images/error_m.png';
 
         // tooltip
         css += '.dv-chart-tips { border-radius: 2px; padding: 2px 3px 0; border: 0 none; background-color: #000; opacity: 0.9 } \n';
@@ -4100,6 +4169,10 @@
         // alert
         css += '.ns-plugin-alert { width: 90%; padding: 5%; color: #777 } \n';
 
+        css += '.x-window-body { font-size: 13px; } \n';
+        css += '.ns-window-title-messagebox { padding-left: 16px; background-position-y: 1px; } \n';
+        css += '.ns-window-title-messagebox.error { background-image: url("' + errorUrl + '"); } \n';
+
         Ext.util.CSS.createStyleSheet(css);
     };
 
@@ -4130,14 +4203,14 @@
 			return true;
 		};
 
-        extendInstance = function(ns) {
+        extendInstance = function(ns, appConfig) {
             var init = ns.core.init,
 				api = ns.core.api,
                 conf = ns.core.conf,
 				support = ns.core.support,
 				service = ns.core.service,
 				web = ns.core.web,
-                type = ns.plugin && ns.crossDomain ? 'jsonp' : 'json',
+                type = 'json',
                 headerMap = {
                     json: 'application/json',
                     jsonp: 'application/javascript'
@@ -4148,6 +4221,19 @@
                 },
                 el = Ext.get(config.el);
 
+			init.el = config.el;
+
+			// ns
+            ns.plugin = appConfig.plugin;
+            ns.dashboard = appConfig.dashboard;
+            ns.crossDomain = appConfig.crossDomain;
+            ns.skipMask = appConfig.skipMask;
+            ns.skipFade = appConfig.skipFade;
+            ns.el = appConfig.el;
+            ns.username = appConfig.username;
+            ns.password = appConfig.password;
+            ns.ajax = support.connection.ajax;
+
 			// message
 			web.message = web.message || {};
 
@@ -4354,17 +4440,6 @@
                     }
                 }
 			};
-
-            // ns
-            ns.plugin = init.plugin;
-            ns.dashboard = init.dashboard;
-            ns.crossDomain = init.crossDomain;
-            ns.skipMask = init.skipMask;
-            ns.skipFade = init.skipFade;
-
-            ns.alert = web.message.alert;
-
-			init.el = config.el;
         };
 
 		createViewport = function() {
@@ -4404,25 +4479,29 @@
 				return;
 			}
 
+            appConfig = {
+                plugin: true,
+                dashboard: Ext.isBoolean(config.dashboard) ? config.dashboard : false,
+                crossDomain: Ext.isBoolean(config.crossDomain) ? config.crossDomain : true,
+                skipMask: Ext.isBoolean(config.skipMask) ? config.skipMask : false,
+                skipFade: Ext.isBoolean(config.skipFade) ? config.skipFade : false,
+                el: Ext.isString(config.el) ? config.el : null,
+                username: Ext.isString(config.username) ? config.username : null,
+                password: Ext.isString(config.password) ? config.password : null
+            };
+
             // css
-			applyCss();
-
-            // config
-            init.plugin = true;
-            init.dashboard = Ext.isBoolean(config.dashboard) ? config.dashboard : false;
-            init.crossDomain = Ext.isBoolean(config.crossDomain) ? config.crossDomain : true;
-            init.skipMask = Ext.isBoolean(config.skipMask) ? config.skipMask : false;
-            init.skipFade = Ext.isBoolean(config.skipFade) ? config.skipFade : false;
-
-            // init
-            ns.init = init;
-            DV.instances.push(ns);
-			ns.core = DV.getCore(ns);
-			extendInstance(ns);
+			applyCss(config);
+
+            // core
+			ns.core = DV.getCore(init, appConfig);
+			extendInstance(ns, appConfig);
 
 			ns.app.viewport = createViewport();
 			ns.app.centerRegion = ns.app.viewport.centerRegion;
 
+            DV.instances.push(ns);
+
             if (el) {
                 el.setViewportWidth = function(width) {
                     ns.app.centerRegion.setWidth(width);

=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/images/error_m.png'
Binary files dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/images/error_m.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/images/error_m.png	2015-09-07 12:21:50 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/plugin/chart.js'
--- dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/plugin/chart.js	2015-08-19 21:30:33 +0000
+++ dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/plugin/chart.js	2015-09-07 12:21:50 +0000
@@ -574,17 +574,26 @@
 	DV.isDebug = false;
 	DV.isSessionStorage = ('sessionStorage' in window && window['sessionStorage'] !== null);
 
-	DV.getCore = function(ns) {
-        var init = ns.init,
-            conf = {},
+	DV.getCore = function(init, appConfig) {
+        var conf = {},
             api = {},
             support = {},
             service = {},
             web = {},
+            app = {},
+            webAlert,
             dimConf;
 
-        // tmp
-        ns.alert = function() {};
+        appConfig = appConfig || {};
+
+        // alert
+        webAlert = function() {};
+
+        // app
+        app.getViewportWidth = function() {};
+        app.getViewportHeight = function() {};
+        app.getCenterRegionWidth = function() {};
+        app.getCenterRegionHeight = function() {};
 
 		// conf
         (function() {
@@ -726,6 +735,14 @@
 				]
 			};
 
+            conf.valueType = {
+            	numericTypes: ['NUMBER','UNIT_INTERVAL','PERCENTAGE','INTEGER','INTEGER_POSITIVE','INTEGER_NEGATIVE','INTEGER_ZERO_OR_POSITIVE'],
+            	textTypes: ['TEXT','LONG_TEXT','LETTER','PHONE_NUMBER','EMAIL'],
+            	booleanTypes: ['BOOLEAN','TRUE_ONLY'],
+            	dateTypes: ['DATE','DATETIME'],
+            	aggregateTypes: ['NUMBER','UNIT_INTERVAL','PERCENTAGE','INTEGER','INTEGER_POSITIVE','INTEGER_NEGATIVE','INTEGER_ZERO_OR_POSITIVE','BOOLEAN','TRUE_ONLY']
+            };
+
             conf.layout = {
                 west_width: 424,
                 west_fieldset_width: 418,
@@ -1063,19 +1080,19 @@
 
 							// Indicators as filter
 							if (layout.filters[i].dimension === dimConf.indicator.objectName) {
-								ns.alert(DV.i18n.indicators_cannot_be_specified_as_filter || 'Indicators cannot be specified as filter.');
+								webAlert(DV.i18n.indicators_cannot_be_specified_as_filter || 'Indicators cannot be specified as filter.');
 								return;
 							}
 
 							// Categories as filter
 							if (layout.filters[i].dimension === dimConf.category.objectName) {
-								ns.alert(DV.i18n.categories_cannot_be_specified_as_filter || 'Categories cannot be specified as filter.');
+								webAlert(DV.i18n.categories_cannot_be_specified_as_filter || 'Categories cannot be specified as filter.');
 								return;
 							}
 
 							// Data sets as filter
 							if (layout.filters[i].dimension === dimConf.dataSet.objectName) {
-								ns.alert(DV.i18n.data_sets_cannot_be_specified_as_filter || 'Data sets cannot be specified as filter.');
+								webAlert(DV.i18n.data_sets_cannot_be_specified_as_filter || 'Data sets cannot be specified as filter.');
 								return;
 							}
 						}
@@ -1083,31 +1100,31 @@
 
 					// dc and in
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.indicator.objectName]) {
-						ns.alert('Indicators and detailed data elements cannot be specified together.', true);
+						webAlert('Indicators and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
 					// dc and de
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.dataElement.objectName]) {
-						ns.alert('Detailed data elements and totals cannot be specified together.', true);
+						webAlert('Detailed data elements and totals cannot be specified together.', true);
 						return;
 					}
 
 					// dc and ds
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.dataSet.objectName]) {
-						ns.alert('Data sets and detailed data elements cannot be specified together.', true);
+						webAlert('Data sets and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
 					// dc and co
 					if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.category.objectName]) {
-						ns.alert('Categories and detailed data elements cannot be specified together.', true);
+						webAlert('Categories and detailed data elements cannot be specified together.', true);
 						return;
 					}
 
                     // in and aggregation type
                     if (objectNameDimensionMap[dimConf.indicator.objectName] && config.aggregationType !== 'DEFAULT') {
-                        ns.alert('Indicators and aggregation types cannot be specified together.', true);
+                        webAlert('Indicators and aggregation types cannot be specified together.', true);
                         return;
                     }
 
@@ -1120,7 +1137,7 @@
 
 					// config must be an object
 					if (!(config && Ext.isObject(config))) {
-						ns.alert('Layout: config is not an object (' + init.el + ')', true);
+						webAlert('Layout: config is not an object (' + init.el + ')', true);
 						return;
 					}
 
@@ -1130,12 +1147,12 @@
 
 					// at least one dimension specified as column and row
 					if (!config.columns) {
-						ns.alert('No series items selected');
+						webAlert('No series items selected');
 						return;
 					}
 
 					if (!config.rows) {
-						ns.alert('No category items selected');
+						webAlert('No category items selected');
 						return;
 					}
 
@@ -1150,7 +1167,7 @@
 
 					// at least one period
 					if (!Ext.Array.contains(objectNames, dimConf.period.objectName)) {
-						ns.alert('At least one period must be specified as series, category or filter');
+						webAlert('At least one period must be specified as series, category or filter');
 						return;
 					}
 
@@ -1214,6 +1231,11 @@
                         layout.program = config.program;
                     }
 
+                    // relative period date
+                    if (support.prototype.date.getYYYYMMDD(config.relativePeriodDate)) {
+                        layout.relativePeriodDate = support.prototype.date.getYYYYMMDD(config.relativePeriodDate);
+                    }
+
                     // style
                     if (Ext.isObject(config.domainAxisStyle)) {
                         layout.domainAxisStyle = config.domainAxisStyle;
@@ -1231,6 +1253,7 @@
                         layout.seriesStyle = config.seriesStyle;
                     }
 
+                    // validate
 					if (!validateSpecialCases()) {
 						return;
 					}
@@ -1486,7 +1509,39 @@
 
                 return variable;
 			};
-		}());
+
+                // date
+            support.prototype.date = {};
+
+            support.prototype.date.getYYYYMMDD = function(param) {
+                if (!Ext.isString(param)) {
+                    if (!(Object.prototype.toString.call(param) === '[object Date]' && param.toString() !== 'Invalid date')) {
+                        return null;
+                    }
+                }
+
+                var date = new Date(param),
+                    month = '' + (1 + date.getMonth()),
+                    day = '' + date.getDate();
+
+                month = month.length === 1 ? '0' + month : month;
+                day = day.length === 1 ? '0' + day : day;
+
+                return date.getFullYear() + '-' + month + '-' + day;
+            };
+
+            // connection
+            support.connection = {};
+
+            support.connection.ajax = function(requestConfig, authConfig) {
+                if (authConfig.crossDomain && Ext.isString(authConfig.username) && Ext.isString(authConfig.password)) {
+                    requestConfig.headers = Ext.isObject(authConfig.headers) ? authConfig.headers : {};
+                    requestConfig.headers['Authorization'] = 'Basic ' + btoa(authConfig.username + ':' + authConfig.password);
+                }
+
+                Ext.Ajax.request(requestConfig);
+            };
+        }());
 
 		// service
 		(function() {
@@ -2233,7 +2288,7 @@
 			web.window = {};
 
 			web.window.setAnchorPosition = function(w, target) {
-				var vpw = ns.app.viewport.getWidth(),
+				var vpw = app.getViewportWidth(),
 					targetx = target ? target.getPosition()[0] : 4,
 					winw = w.getWidth(),
 					y = target ? target.getPosition()[1] + target.getHeight() + 4 : 33;
@@ -2310,7 +2365,7 @@
                 config.html += obj.message + (obj.message.substr(obj.message.length - 1) === '.' ? '' : '.');
 
                 // bodyStyle
-                config.bodyStyle = 'padding: 12px; background: #fff; max-width: 600px; max-height: ' + ns.app.centerRegion.getHeight() / 2 + 'px';
+                config.bodyStyle = 'padding: 12px; background: #fff; max-width: 600px; max-height: ' + app.getCenterRegionHeight() / 2 + 'px';
 
                 // destroy handler
                 config.modal = true;
@@ -2401,6 +2456,11 @@
                     paramString += '&program=' + xLayout.program.id;
                 }
 
+                // relative period date
+                if (xLayout.relativePeriodDate) {
+                    paramString += '&relativePeriodDate=' + xLayout.relativePeriodDate;
+                }
+
                 return paramString.replace(/#/g, '.');
             };
 
@@ -2417,7 +2477,7 @@
 
                 msg += '\n\n' + 'Hint: A good way to reduce the number of items is to use relative periods and level/group organisation unit selection modes.';
 
-                ns.alert(msg, 'warning');
+                webAlert(msg, 'warning');
 			};
 
 			// chart
@@ -2581,7 +2641,7 @@
                                 }
 
                                 trendLineFields.push(regressionKey);
-                                xResponse.metaData.names[regressionKey] = DV.i18n.trend + (ns.dashboard ? '' : ' (' + xResponse.metaData.names[failSafeColumnIds[i]] + ')');
+                                xResponse.metaData.names[regressionKey] = DV.i18n.trend + (appConfig.dashboard ? '' : ' (' + xResponse.metaData.names[failSafeColumnIds[i]] + ')');
                             }
                         }
                     }
@@ -2904,15 +2964,15 @@
                 };
 
                 getFormatedSeriesTitle = function(titles) {
-                    var itemLength = ns.dashboard ? 23 : 30,
-                        charLength = ns.dashboard ? 5 : 6,
+                    var itemLength = appConfig.dashboard ? 23 : 30,
+                        charLength = appConfig.dashboard ? 5 : 6,
                         numberOfItems = titles.length,
                         numberOfChars,
                         totalItemLength = numberOfItems * itemLength,
                         //minLength = 5,
                         maxLength = support.prototype.array.getMaxLength(titles),
                         fallbackLength = 10,
-                        maxWidth = ns.app.centerRegion.getWidth(),
+                        maxWidth = app.getCenterRegionWidth(),
                         width,
                         validateTitles;
 
@@ -2974,7 +3034,7 @@
                         }
                     }
 
-                    return ns.dashboard ? getFormatedSeriesTitle(a) : a;
+                    return appConfig.dashboard ? getFormatedSeriesTitle(a) : a;
 				};
 
                 getPieSeriesTitle = function(store) {
@@ -3003,7 +3063,7 @@
                         });
                     }
 
-                    return ns.dashboard ? getFormatedSeriesTitle(a) : a;
+                    return appConfig.dashboard ? getFormatedSeriesTitle(a) : a;
 				};
 
                 getDefaultSeries = function(store) {
@@ -3162,8 +3222,8 @@
                 };
 
                 getDefaultLegend = function(store, chartConfig) {
-                    var itemLength = ns.dashboard ? 24 : 30,
-                        charLength = ns.dashboard ? 4 : 6,
+                    var itemLength = appConfig.dashboard ? 24 : 30,
+                        charLength = appConfig.dashboard ? 4 : 6,
                         numberOfItems = 0,
                         numberOfChars = 0,
                         width,
@@ -3192,7 +3252,7 @@
 
                     width = (numberOfItems * itemLength) + (numberOfChars * charLength);
 
-                    if (width > ns.app.centerRegion.getWidth() - 6) {
+                    if (width > app.getCenterRegionWidth() - 6) {
                         position = 'right';
                     }
 
@@ -3268,7 +3328,7 @@
                         text = xLayout.title;
                     }
 
-                    fontSize = (ns.app.centerRegion.getWidth() / text.length) < 11.6 ? 12 : 17;
+                    fontSize = (app.getCenterRegionWidth() / text.length) < 11.6 ? 12 : 17;
                     titleFont = 'normal ' + fontSize + 'px ' + conf.chart.style.fontFamily;
                     titleColor = 'black';
 
@@ -3294,19 +3354,19 @@
                         font: titleFont,
                         fill: titleColor,
                         height: 20,
-                        y: ns.dashboard ? 7 : 20
+                        y: appConfig.dashboard ? 7 : 20
                     });
                 };
 
                 getDefaultChartSizeHandler = function() {
                     return function() {
-                        var width = ns.app.centerRegion.getWidth(),
-                            height = ns.app.centerRegion.getHeight();
+                        var width = app.getCenterRegionWidth(),
+                            height = app.getCenterRegionHeight();
 
 						this.animate = false;
-                        this.setWidth(ns.dashboard ? width : width - 15);
-                        this.setHeight(ns.dashboard ? height : height - 40);
-                        this.animate = !ns.dashboard;
+                        this.setWidth(appConfig.dashboard ? width : width - 15);
+                        this.setHeight(appConfig.dashboard ? height : height - 40);
+                        this.animate = !appConfig.dashboard;
                     };
                 };
 
@@ -3339,22 +3399,22 @@
                 getDefaultChart = function(config) {
                     var chart,
                         store = config.store || {},
-                        width = ns.app.centerRegion.getWidth(),
-                        height = ns.app.centerRegion.getHeight(),
+                        width = app.getCenterRegionWidth(),
+                        height = app.getCenterRegionHeight(),
                         isLineBased = Ext.Array.contains(['line', 'area'], xLayout.type),
                         defaultConfig = {
                             //animate: true,
                             animate: false,
                             shadow: false,
-                            insetPadding: ns.dashboard ? 17 : 35,
+                            insetPadding: appConfig.dashboard ? 17 : 35,
                             insetPaddingObject: {
-                                top: ns.dashboard ? 12 : 32,
-                                right: ns.dashboard ? (isLineBased ? 5 : 3) : (isLineBased ? 25 : 15),
-                                bottom: ns.dashboard ? 2 : 10,
-                                left: ns.dashboard ? (isLineBased ? 15 : 7) : (isLineBased ? 70 : 50)
+                                top: appConfig.dashboard ? 12 : 32,
+                                right: appConfig.dashboard ? (isLineBased ? 5 : 3) : (isLineBased ? 25 : 15),
+                                bottom: appConfig.dashboard ? 2 : 10,
+                                left: appConfig.dashboard ? (isLineBased ? 15 : 7) : (isLineBased ? 70 : 50)
                             },
-                            width: ns.dashboard ? width : width - 15,
-                            height: ns.dashboard ? height : height - 40,
+                            width: appConfig.dashboard ? width : width - 15,
+                            height: appConfig.dashboard ? height : height - 40,
                             theme: 'dv1'
                         };
 
@@ -3363,15 +3423,15 @@
                         defaultConfig.legend = getDefaultLegend(store, config);
 
                         if (defaultConfig.legend.position === 'right') {
-                            defaultConfig.insetPaddingObject.top = ns.dashboard ? 22 : 40;
-                            defaultConfig.insetPaddingObject.right = ns.dashboard ? 5 : 40;
+                            defaultConfig.insetPaddingObject.top = appConfig.dashboard ? 22 : 40;
+                            defaultConfig.insetPaddingObject.right = appConfig.dashboard ? 5 : 40;
                         }
                     }
 
                     // title
                     if (xLayout.hideTitle) {
-                        defaultConfig.insetPadding = ns.dashboard ? 1 : 10;
-                        defaultConfig.insetPaddingObject.top = ns.dashboard ? 3 : 10;
+                        defaultConfig.insetPadding = appConfig.dashboard ? 1 : 10;
+                        defaultConfig.insetPaddingObject.top = appConfig.dashboard ? 3 : 10;
                     }
                     else {
                         defaultConfig.items = [getDefaultChartTitle(store)];
@@ -3550,7 +3610,7 @@
                             },
                             markerConfig: {
                                 type: 'circle',
-                                radius: ns.dashboard ? 3 : 4
+                                radius: appConfig.dashboard ? 3 : 4
                             },
                             tips: getDefaultTips(),
                             title: seriesTitles[i]
@@ -3732,10 +3792,10 @@
                         store: store,
                         series: series,
                         insetPaddingObject: {
-                            top: ns.dashboard ? 15 : 40,
-                            right: ns.dashboard ? 2 : 30,
-                            bottom: ns.dashboard ? 13: 30,
-                            left: ns.dashboard ? 7 : 30
+                            top: appConfig.dashboard ? 15 : 40,
+                            right: appConfig.dashboard ? 2 : 30,
+                            bottom: appConfig.dashboard ? 13: 30,
+                            left: appConfig.dashboard ? 7 : 30
                         }
                     });
 
@@ -3864,10 +3924,10 @@
                     chart = getDefaultChart({
                         axes: [axis],
                         series: [series],
-                        width: ns.app.centerRegion.getWidth(),
-                        height: ns.app.centerRegion.getHeight() * 0.6,
+                        width: app.getCenterRegionWidth(),
+                        height: app.getCenterRegionHeight() * 0.6,
                         store: store,
-                        insetPadding: ns.dashboard ? 50 : 100,
+                        insetPadding: appConfig.dashboard ? 50 : 100,
                         theme: null,
                         //animate: {
                             //easing: 'elasticIn',
@@ -3889,8 +3949,8 @@
 
                     chart.setChartSize = function() {
 						//this.animate = false;
-                        this.setWidth(ns.app.centerRegion.getWidth());
-                        this.setHeight(ns.app.centerRegion.getHeight() * 0.6);
+                        this.setWidth(app.getCenterRegionWidth());
+                        this.setHeight(app.getCenterRegionHeight() * 0.6);
                         //this.animate = true;
                     };
 
@@ -3902,7 +3962,7 @@
 
                             if (title) {
                                 var titleWidth = Ext.isIE ? title.el.dom.scrollWidth : title.el.getWidth(),
-                                    titleX = titleWidth ? (ns.app.centerRegion.getWidth() / 2) - (titleWidth / 2) : titleXFallback;
+                                    titleX = titleWidth ? (app.getCenterRegionWidth() / 2) - (titleWidth / 2) : titleXFallback;
                                 title.setAttributes({
                                     x: titleX
                                 }, true);
@@ -3910,7 +3970,7 @@
 
                             if (subTitle) {
                                 var subTitleWidth = Ext.isIE ? subTitle.el.dom.scrollWidth : subTitle.el.getWidth(),
-                                    subTitleX = subTitleWidth ? (ns.app.centerRegion.getWidth() / 2) - (subTitleWidth / 2) : titleXFallback;
+                                    subTitleX = subTitleWidth ? (app.getCenterRegionWidth() / 2) - (subTitleWidth / 2) : titleXFallback;
                                 subTitle.setAttributes({
                                     x: subTitleX
                                 }, true);
@@ -3949,15 +4009,18 @@
 		}());
 
 		// alert
-        ns.alert = web.message.alert;
-
-		ns.conf = conf;
-		ns.api = api;
-		ns.support = support;
-		ns.service = service;
-		ns.web = web;
-
-		return ns;
+		webAlert = web.message.alert;
+
+		return {
+            init: init,
+            conf: conf,
+            api: api,
+            support: support,
+            service: service,
+            web: web,
+            app: app,
+            webAlert: webAlert
+        };
     };
 
     // PLUGIN
@@ -3985,7 +4048,8 @@
 		var isInit = false,
 			requests = [],
 			callbacks = 0,
-            type = config.plugin && config.crossDomain ? 'jsonp' : 'json',
+            type = 'json',
+            ajax,
 			fn;
 
         init.contextPath = config.url;
@@ -4002,6 +4066,15 @@
 			}
 		};
 
+        ajax = function(requestConfig, authConfig) {
+            if (authConfig.crossDomain && Ext.isString(authConfig.username) && Ext.isString(authConfig.password)) {
+                requestConfig.headers = Ext.isObject(authConfig.headers) ? authConfig.headers : {};
+                requestConfig.headers['Authorization'] = 'Basic ' + btoa(authConfig.username + ':' + authConfig.password);
+            }
+
+            Ext.Ajax.request(requestConfig);
+        };
+
         // user-account
         requests.push({
             url: init.contextPath + '/api/me/user-account.' + type,
@@ -4074,17 +4147,13 @@
 		});
 
 		for (var i = 0; i < requests.length; i++) {
-            if (type === 'jsonp') {
-                Ext.data.JsonP.request(requests[i]);
-            }
-            else {
-                Ext.Ajax.request(requests[i]);
-            }
+            ajax(requests[i], config);
 		}
 	};
 
-	applyCss = function() {
-        var css = '';
+	applyCss = function(config) {
+        var css = '',
+            errorUrl = config.dashboard ? init.contextPath + '/dhis-web-commons/javascripts/plugin/images/error_m.png' : '//dhis2-cdn.org/v220/plugin/images/error_m.png';
 
         // tooltip
         css += '.dv-chart-tips { border-radius: 2px; padding: 2px 3px 0; border: 0 none; background-color: #000; opacity: 0.9 } \n';
@@ -4100,6 +4169,10 @@
         // alert
         css += '.ns-plugin-alert { width: 90%; padding: 5%; color: #777 } \n';
 
+        css += '.x-window-body { font-size: 13px; } \n';
+        css += '.ns-window-title-messagebox { padding-left: 16px; background-position-y: 1px; } \n';
+        css += '.ns-window-title-messagebox.error { background-image: url("' + errorUrl + '"); } \n';
+
         Ext.util.CSS.createStyleSheet(css);
     };
 
@@ -4130,14 +4203,14 @@
 			return true;
 		};
 
-        extendInstance = function(ns) {
+        extendInstance = function(ns, appConfig) {
             var init = ns.core.init,
 				api = ns.core.api,
                 conf = ns.core.conf,
 				support = ns.core.support,
 				service = ns.core.service,
 				web = ns.core.web,
-                type = ns.plugin && ns.crossDomain ? 'jsonp' : 'json',
+                type = 'json',
                 headerMap = {
                     json: 'application/json',
                     jsonp: 'application/javascript'
@@ -4148,6 +4221,19 @@
                 },
                 el = Ext.get(config.el);
 
+			init.el = config.el;
+
+			// ns
+            ns.plugin = appConfig.plugin;
+            ns.dashboard = appConfig.dashboard;
+            ns.crossDomain = appConfig.crossDomain;
+            ns.skipMask = appConfig.skipMask;
+            ns.skipFade = appConfig.skipFade;
+            ns.el = appConfig.el;
+            ns.username = appConfig.username;
+            ns.password = appConfig.password;
+            ns.ajax = support.connection.ajax;
+
 			// message
 			web.message = web.message || {};
 
@@ -4354,17 +4440,6 @@
                     }
                 }
 			};
-
-            // ns
-            ns.plugin = init.plugin;
-            ns.dashboard = init.dashboard;
-            ns.crossDomain = init.crossDomain;
-            ns.skipMask = init.skipMask;
-            ns.skipFade = init.skipFade;
-
-            ns.alert = web.message.alert;
-
-			init.el = config.el;
         };
 
 		createViewport = function() {
@@ -4404,25 +4479,29 @@
 				return;
 			}
 
+            appConfig = {
+                plugin: true,
+                dashboard: Ext.isBoolean(config.dashboard) ? config.dashboard : false,
+                crossDomain: Ext.isBoolean(config.crossDomain) ? config.crossDomain : true,
+                skipMask: Ext.isBoolean(config.skipMask) ? config.skipMask : false,
+                skipFade: Ext.isBoolean(config.skipFade) ? config.skipFade : false,
+                el: Ext.isString(config.el) ? config.el : null,
+                username: Ext.isString(config.username) ? config.username : null,
+                password: Ext.isString(config.password) ? config.password : null
+            };
+
             // css
-			applyCss();
-
-            // config
-            init.plugin = true;
-            init.dashboard = Ext.isBoolean(config.dashboard) ? config.dashboard : false;
-            init.crossDomain = Ext.isBoolean(config.crossDomain) ? config.crossDomain : true;
-            init.skipMask = Ext.isBoolean(config.skipMask) ? config.skipMask : false;
-            init.skipFade = Ext.isBoolean(config.skipFade) ? config.skipFade : false;
-
-            // init
-            ns.init = init;
-            DV.instances.push(ns);
-			ns.core = DV.getCore(ns);
-			extendInstance(ns);
+			applyCss(config);
+
+            // core
+			ns.core = DV.getCore(init, appConfig);
+			extendInstance(ns, appConfig);
 
 			ns.app.viewport = createViewport();
 			ns.app.centerRegion = ns.app.viewport.centerRegion;
 
+            DV.instances.push(ns);
+
             if (el) {
                 el.setViewportWidth = function(width) {
                     ns.app.centerRegion.setWidth(width);