← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 6953: (DV plugin) Show data, trend line, hide legend, hide subtitle, target line, base line options add...

 

Merge authors:
  Jan Henrik Øverland (janhenrik-overland)
------------------------------------------------------------
revno: 6953 [merge]
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2012-05-16 00:49:25 +0200
message:
  (DV plugin) Show data, trend line, hide legend, hide subtitle, target line, base line options added + Merged with table plugin.
removed:
  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/css/chart.css
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/table.js
added:
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/css/plugin.css
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/plugin.js
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/plugin.css
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/plugin.js
modified:
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/app.js
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/index.html


--
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
=== removed 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	2012-05-12 13:36:32 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/chart.js	1970-01-01 00:00:00 +0000
@@ -1,776 +0,0 @@
-DHIS = {};
-DHIS.conf = {
-    finals: {
-        ajax: {
-            data_get: 'api/chartValues.jsonp',
-            favorite_get: 'api/charts/'
-        },        
-        dimension: {
-            data: {
-                value: 'data',
-                rawvalue: 'Data'
-            },
-            indicator: {
-                value: 'indicator',
-                rawvalue: 'Indicator'
-            },
-            dataelement: {
-                value: 'dataelement',
-                rawvalue: 'Data element'
-            },
-            period: {
-                value: 'period',
-                rawvalue: 'Period'
-            },
-            organisationunit: {
-                value: 'organisationunit',
-                rawvalue: 'Organisation unit'
-            }
-        },
-        chart: {
-            x: 'x',
-            series: 'series',
-            category: 'category',
-            filter: 'filter',
-            column: 'column',
-            stackedcolumn: 'stackedcolumn',
-            bar: 'bar',
-            stackedbar: 'stackedbar',
-            line: 'line',
-            area: 'area',
-            pie: 'pie',
-            orgUnitIsParent: 'orgUnitIsParent'
-        }
-    }
-};
-
-Ext.onReady( function() {
-	
-    DHIS.initialize = function() {
-        DHIS.store.column = DHIS.store.defaultChartStore;
-        DHIS.store.stackedcolumn = DHIS.store.defaultChartStore;
-        DHIS.store.stackedbar = DHIS.store.bar;
-        DHIS.store.line = DHIS.store.defaultChartStore;
-        DHIS.store.area = DHIS.store.defaultChartStore;
-        DHIS.store.pie = DHIS.store.defaultChartStore;
-        
-        DHIS.getChart = DHIS.exe.addToQueue;
-        DHIS.destroyChart = DHIS.exe.destroy;
-    };
-    
-    DHIS.projects = {};
-    
-    DHIS.util = {
-        dimension: {
-            indicator: {
-                getIdsFromObjects: function(indicators) {
-                    var a = []
-                    for (var i = 0; i < indicators.length; i++) {
-                        a.push(indicators[i].id);
-                    }
-                    return a;
-                }
-            },
-            dataelement: {
-                getIdsFromObjects: function(dataelements) {
-                    var a = []
-                    for (var i = 0; i < dataelements.length; i++) {
-                        a.push(dataelements[i].id);
-                    }
-                    return a;
-                }
-            },
-            data: {
-                getUrl: function(isFilter) {
-                    var a = [];
-                    Ext.Array.each(DHIS.state.state.conf.indicators, function(r) {
-                        a.push('indicatorIds=' + r);
-                    });
-                    Ext.Array.each(DHIS.state.state.conf.dataelements, function(r) {
-                        a.push('dataElementIds=' + r);
-                    });
-                    return (isFilter && a.length > 1) ? a.slice(0,1) : a;
-                }
-            },
-            period: {
-                getUrl: function(isFilter) {
-                    var a = [];
-                    Ext.Array.each(DHIS.state.state.conf.periods, function(r) {
-						a.push(r + '=true')
-                    });
-                    return (isFilter && a.length > 1) ? a.slice(0,1) : a;
-                },
-                getRelativesFromObject: function(obj) {
-                    var a = [];
-                    for (var k in obj) {
-                        if (obj[k]) {
-                            a.push(k);
-                        }
-                    }
-                    return a;
-                }
-            },
-            organisationunit: {
-                getUrl: function(isFilter) {
-                    var a = [];
-                    Ext.Array.each(DHIS.state.state.conf.organisationunits, function(r) {
-						a.push('organisationUnitIds=' + r)
-                    });
-                    return (isFilter && a.length > 1) ? a.slice(0,1) : a;
-                },
-                getIdsFromObjects: function(organisationunits) {
-                    var a = []
-                    for (var i = 0; i < organisationunits.length; i++) {
-                        a.push(organisationunits[i].id);
-                    }
-                    return a;
-                }
-            }
-        },
-        chart: {
-            getLegend: function(len) {
-                len = len ? len : 1;
-                return {
-                    position: len > 5 ? 'right' : 'top',
-                    labelFont: '11px arial',
-                    boxStroke: '#ffffff',
-                    boxStrokeWidth: 0,
-                    padding: 0
-                };
-            },
-            getGrid: function() {
-                return {
-                    opacity: 1,
-                    fill: '#f1f1f1',
-                    stroke: '#aaa',
-                    'stroke-width': 0.2
-                };
-            },
-            getTitle: function() {
-                return {
-                    type: 'text',
-                    text: DHIS.state.state.filter.names[0],
-                    font: 'bold 13px arial',
-                    fill: '#222',
-                    width: 300,
-                    height: 20,
-                    x: 28,
-                    y: 16
-                };
-            },
-            getTips: function() {
-                return {
-                    trackMouse: true,
-                    style: 'border-width:2px; background-color:#eee',
-                    renderer: function(r, item) {
-						this.update('<span style="font-size:21px">' + '' + item.value[1] + '</span>');
-                    }
-                };
-            },
-            setMask: function(str) {
-                if (DHIS.mask) {
-                    DHIS.mask.hide();
-                }
-                DHIS.mask = new Ext.LoadMask(DHIS.chart.chart, {msg: str});
-                DHIS.mask.show();
-            },
-            label: {
-                getCategoryLabel: function() {
-                    return {
-                        font: '11px arial',
-                        rotate: {
-                            degrees: 320
-                        }
-                    };
-                },
-                getNumericLabel: function(values) {
-                    return {
-                        font: '11px arial',
-                        renderer: Ext.util.Format.numberRenderer(DHIS.util.number.getChartAxisFormatRenderer(values))
-                    };
-                }
-            },
-            bar: {
-                getCategoryLabel: function() {
-                    return {
-                        font: '11px arial'
-                    };
-                }
-            },
-            line: {
-                getSeriesArray: function(project) {
-                    var a = [];
-                    for (var i = 0; i < project.store.left.length; i++) {
-                        a.push({
-                            type: 'line',
-                            axis: 'left',
-                            xField: project.store.bottom,
-                            yField: project.store.left[i],
-							style: {
-								opacity: 0.8,
-								lineWidth: 3
-							},
-							tips: DHIS.util.chart.getTips()
-                        });
-                    }
-                    return a;
-                }
-            },
-            pie: {
-                getTitle: function(title, subtitle) {
-                    return [
-                        {
-                            type: 'text',
-                            text: title,
-                            font: 'bold 13px arial',
-                            fill: '#222',
-                            width: 300,
-                            height: 20,
-                            x: 28,
-                            y: 16
-                        },
-                        {
-                            type: 'text',
-                            text: subtitle,
-                            font: 'bold 11px arial',
-                            fill: '#777',
-                            width: 300,
-                            height: 20,
-                            x: 28,
-                            y: 36
-                        }
-                    ];                        
-                },
-                getTips: function(left) {
-                    return {
-                        trackMouse: true,
-						style: 'border-width:2px; background-color:#eee',
-                        renderer: function(item) {
-							this.update('<span style="font-size:14px">' + item.data.x + '<br/><b>' + item.data[left] + '</b></span>');
-                        }
-                    };
-                }
-            }
-        },
-        number: {
-            isInteger: function(n) {
-                var str = new String(n);
-                if (str.indexOf('.') > -1) {
-                    var d = str.substr(str.indexOf('.') + 1);
-                    return (d.length === 1 && d == '0');
-                }
-                return false;
-            },
-            allValuesAreIntegers: function(values) {
-                for (var i = 0; i < values.length; i++) {
-                    if (!this.isInteger(values[i].v)) {
-                        return false;
-                    }
-                }
-                return true;
-            },
-            getChartAxisFormatRenderer: function(values) {
-                return this.allValuesAreIntegers(values) ? '0' : '0.0';
-            }
-        },
-        string: {
-            getEncodedString: function(text) {
-                return text.replace(/[^a-zA-Z 0-9(){}<>_!+;:?*&%#-]+/g,'');
-            },
-            extendUrl: function(url) {
-                if (url.charAt(url.length-1) !== '/') {
-                    url += '/';
-                }
-                return url;
-            },
-            appendUrlIfTrue: function(url, param, expression) {
-            	if (expression && expression == true) {
-            		url = Ext.String.urlAppend(url, param + '=true');
-            	}
-            	return url;            	
-            }
-        },
-        value: {
-            jsonfy: function(r) {                
-                var object = {
-                    values: [],
-                    periods: r.p,
-                    datanames: [],
-                    organisationunitnames: []
-                };
-                for (var i = 0; i < r.v.length; i++) {
-                    var obj = {};
-                    obj.v = r.v[i][0];
-                    obj[DHIS.conf.finals.dimension.data.value] = r.v[i][1];
-                    obj[DHIS.conf.finals.dimension.period.value] = r.v[i][2];
-                    obj[DHIS.conf.finals.dimension.organisationunit.value] = r.v[i][3];
-                    object.values.push(obj);
-                }
-                for (var j = 0; j < r.d.length; j++) {
-					object.datanames.push(DHIS.util.string.getEncodedString(r.d[j]));
-				}
-                for (var k = 0; k < r.o.length; k++) {
-					object.organisationunitnames.push(DHIS.util.string.getEncodedString(r.o[k]));
-				}
-                return object;
-            }
-        }
-    };
-    
-    DHIS.store = {
-        getChartStore: function(project) {
-            this[project.state.type](project);
-        },
-        defaultChartStore: function(project) {
-            var keys = [];
-            
-            Ext.Array.each(project.data, function(item) {
-                keys = Ext.Array.merge(keys, Ext.Object.getKeys(item));
-            });
-            
-            project.store = Ext.create('Ext.data.Store', {
-                fields: keys,
-                data: project.data
-            });
-            project.store.bottom = [DHIS.conf.finals.chart.x];
-            project.store.left = keys.slice(0);
-            for (var i = 0; i < project.store.left.length; i++) {
-                if (project.store.left[i] === DHIS.conf.finals.chart.x) {
-                    project.store.left.splice(i, 1);
-                }
-            }
-            
-			DHIS.chart.getChart(project);
-        },
-        bar: function(project) {
-            var properties = Ext.Object.getKeys(project.data[0]);
-            project.store = Ext.create('Ext.data.Store', {
-                fields: properties,
-                data: project.data
-            });
-            project.store.left = properties.slice(0, 1);
-            project.store.bottom = properties.slice(1, properties.length);
-            
-			DHIS.chart.getChart(project);
-        }
-    };
-    
-    DHIS.state = {
-        state: null,
-        getState: function(conf) {
-            var project = {
-                state: {
-                    conf: null,
-                    type: null,
-                    series: {
-                        dimension: null,
-                        names: []
-                    },
-                    category: {
-                        dimension: null,
-                        names: []
-                    },
-                    filter: {
-                        dimension: null,
-                        names: []
-                    }
-                }
-            };
-            
-            var defaultConf = {
-                type: 'column',
-                stacked: false,
-                indicators: [],
-                periods: ['last12Months'],
-                organisationunits: [],
-                series: 'data',
-                category: 'period',
-                filter: 'organisationunit',
-                el: '',
-                legendPosition: false,
-                orgUnitIsParent: false,
-                skipAnimation: false,
-                url: ''
-            };
-            
-            project.state.conf = Ext.applyIf(conf, defaultConf);
-            project.state.conf.type = project.state.conf.type.toLowerCase();
-            project.state.conf.series = project.state.conf.series.toLowerCase();
-            project.state.conf.category = project.state.conf.category.toLowerCase();
-            project.state.conf.filter = project.state.conf.filter.toLowerCase();
-            
-            project.state.conf[project.state.conf.series] = DHIS.conf.finals.chart.series;
-            project.state.conf[project.state.conf.category] = DHIS.conf.finals.chart.category;
-            project.state.conf[project.state.conf.filter] = DHIS.conf.finals.chart.filter;
-            
-            project.state.type = project.state.conf.type;
-            project.state.series.dimension = project.state.conf.series;
-            project.state.category.dimension = project.state.conf.category;
-            project.state.filter.dimension = project.state.conf.filter;
-            project.state.orgUnitIsParent = project.state.conf.orgUnitIsParent;
-            
-            DHIS.state.state = project.state;
-            
-			DHIS.value.getValues(project);
-        },
-        setState: function(conf) {
-            if (conf.uid) {
-                Ext.data.JsonP.request({
-                    url: conf.url + DHIS.conf.finals.ajax.favorite_get + conf.uid + '.jsonp',
-                    disableCaching: false,
-                    scope: this,
-                    success: function(r) {
-                        if (!r) {
-                            alert('Invalid uid');
-                            return;
-                        }
-                        
-                        conf.type = r.type.toLowerCase();
-                        conf.periods = DHIS.util.dimension.period.getRelativesFromObject(r.relativePeriods);
-                        conf.organisationunits = DHIS.util.dimension.organisationunit.getIdsFromObjects(r.organisationUnits);
-                        conf.series = r.series.toLowerCase();
-                        conf.category = r.category.toLowerCase();
-                        conf.filter = r.filter.toLowerCase();
-                        conf.legendPosition = conf.legendPosition || false;
-                        
-                        if (r.indicators) {
-                            conf.indicators = DHIS.util.dimension.indicator.getIdsFromObjects(r.indicators);
-                        }
-                        if (r.dataElements) {
-                            conf.dataelements = DHIS.util.dimension.dataelement.getIdsFromObjects(r.dataElements);
-                        }
-                        
-                        this.getState(conf);                        
-                    }
-                });
-            }
-        },
-        storage: {}
-    };
-    
-    DHIS.value = {
-        getValues: function(project) {
-            var params = [];                
-            params = params.concat(DHIS.util.dimension[project.state.series.dimension].getUrl());
-            params = params.concat(DHIS.util.dimension[project.state.category.dimension].getUrl());
-            params = params.concat(DHIS.util.dimension[project.state.filter.dimension].getUrl(true));
-                        
-            var baseUrl = DHIS.util.string.extendUrl(project.state.conf.url) + DHIS.conf.finals.ajax.data_get;
-            baseUrl = DHIS.util.string.appendUrlIfTrue(baseUrl, DHIS.conf.finals.chart.orgUnitIsParent, project.state.orgUnitIsParent);
-            
-            Ext.Array.each(params, function(item) {
-                baseUrl = Ext.String.urlAppend(baseUrl, item);
-            });
-            
-            Ext.data.JsonP.request({
-                url: baseUrl,
-                disableCaching: false,
-                success: function(r) {
-                    var json = DHIS.util.value.jsonfy(r);
-                    project.values = json.values;
-                    
-                    if (!project.values.length) {
-                        alert('No data values');
-                        return;
-                    }
-                    
-                    for (var i = 0; i < project.values.length; i++) {
-                        project.values[i][DHIS.conf.finals.dimension.data.value] = DHIS.util.string.getEncodedString(project.values[i][DHIS.conf.finals.dimension.data.value]);
-                        project.values[i][DHIS.conf.finals.dimension.period.value] = DHIS.util.string.getEncodedString(project.values[i][DHIS.conf.finals.dimension.period.value]);
-                        project.values[i][DHIS.conf.finals.dimension.organisationunit.value] = DHIS.util.string.getEncodedString(project.values[i][DHIS.conf.finals.dimension.organisationunit.value]);
-                    }
-                    
-                    project.state[project.state.conf.data].names = json.datanames;
-                    project.state[project.state.conf.organisationunit].names = json.organisationunitnames;
-                    Ext.Array.each(project.values, function(item) {						
-                        Ext.Array.include(project.state[project.state.conf.period].names, DHIS.util.string.getEncodedString(item[project.state[project.state.conf.period].dimension]));
-                        item.v = parseFloat(item.v);
-                    });
-                    
-                    for (var k in project.state.conf) {
-                        if (project.state.conf[k] == 'period') {
-                            project.state[k].names = json.periods;
-                        }
-                    }
-                    
-                    DHIS.state.state = project.state;
-                    
-					DHIS.chart.getData(project);
-                }
-            });
-        }
-    };
-    
-    DHIS.chart = {
-        getData: function(project) {
-            project.data = [];
-			
-            Ext.Array.each(project.state.category.names, function(item) {
-                var obj = {};
-                obj[DHIS.conf.finals.chart.x] = item;
-                project.data.push(obj);
-            });
-            
-            Ext.Array.each(project.data, function(item) {
-                for (var i = 0; i < project.state.series.names.length; i++) {
-                    item[project.state.series.names[i]] = 0;
-                }
-            });
-            
-            Ext.Array.each(project.data, function(item) {
-                for (var i = 0; i < project.state.series.names.length; i++) {
-                    for (var j = 0; j < project.values.length; j++) {
-                        if (project.values[j][project.state.category.dimension] === item[DHIS.conf.finals.chart.x] && project.values[j][project.state.series.dimension] === project.state.series.names[i]) {
-                            item[project.values[j][project.state.series.dimension]] = project.values[j].v;
-                            break;
-                        }
-                    }
-                }
-            });
-                
-			DHIS.store.getChartStore(project);
-        },
-        el: null,
-        getChart: function(project) {
-            this.el = Ext.get(project.state.conf.el);
-            this[project.state.type](project);
-            DHIS.exe.execute();
-        },
-        column: function(project, isStacked) {			
-            project.chart = Ext.create('Ext.chart.Chart', {
-				renderTo: project.state.conf.el,
-                width: project.state.conf.width || this.el.getWidth(),
-                height: project.state.conf.height || this.el.getHeight(),
-                animate: !project.state.conf.skipAnimation,
-                store: project.store,
-                items: DHIS.util.chart.getTitle(),
-                legend: DHIS.util.chart.getLegend(project.store.left.length),
-                axes: [
-                    {
-                        type: 'Numeric',
-                        position: 'left',
-                        minimum: 0,
-                        fields: project.store.left,
-                        label: DHIS.util.chart.label.getNumericLabel(project.values),
-                        grid: {
-                            even: DHIS.util.chart.getGrid()
-                        }
-                    },
-                    {
-                        type: 'Category',
-                        position: 'bottom',
-                        fields: project.store.bottom,
-                        label: DHIS.util.chart.label.getCategoryLabel()
-                    }
-                ],
-                series: [
-                    {
-                        type: 'column',
-                        axis: 'left',
-                        xField: project.store.bottom,
-                        yField: project.store.left,
-                        stacked: isStacked,
-						style: {
-							opacity: 0.8,
-							stroke: '#333'
-						},
-						tips: DHIS.util.chart.getTips()
-                    }
-                ]
-            });
-            
-            DHIS.projects[project.state.conf.el] = project;
-        },
-        stackedcolumn: function(project) {
-            this.column(project, true);
-        },
-        bar: function(project, isStacked) {
-            project.chart = Ext.create('Ext.chart.Chart', {
-				renderTo: project.state.conf.el,
-                width: project.state.conf.width || this.el.getWidth(),
-                height: project.state.conf.height || this.el.getHeight(),
-                animate: !project.state.conf.skipAnimation,
-                store: project.store,
-                items: DHIS.util.chart.getTitle(),
-                legend: DHIS.util.chart.getLegend(project.store.bottom.length),
-                axes: [
-                    {
-                        type: 'Category',
-                        position: 'left',
-                        fields: project.store.left,
-                        label: DHIS.util.chart.bar.getCategoryLabel()
-                    },
-                    {
-                        type: 'Numeric',
-                        position: 'bottom',
-                        minimum: 0,
-                        fields: project.store.bottom,
-                        label: DHIS.util.chart.label.getNumericLabel(project.values),
-                        grid: {
-                            even: DHIS.util.chart.getGrid()
-                        }
-                    }
-                ],
-                series: [
-                    {
-                        type: 'bar',
-                        axis: 'bottom',
-                        xField: project.store.left,
-                        yField: project.store.bottom,
-                        stacked: isStacked,
-						style: {
-							opacity: 0.8,
-							stroke: '#333'
-						},
-						tips: DHIS.util.chart.getTips()
-                    }
-                ]
-            });
-            
-            DHIS.projects[project.state.conf.el] = project;
-        },
-        stackedbar: function(project) {
-            this.bar(project, true);
-        },
-        line: function(project) {
-            project.chart = Ext.create('Ext.chart.Chart', {
-				renderTo: project.state.conf.el,
-                width: project.state.conf.width || this.el.getWidth(),
-                height: project.state.conf.height || this.el.getHeight(),
-                animate: !project.state.conf.skipAnimation,
-                store: project.store,
-                items: DHIS.util.chart.getTitle(),
-                legend: DHIS.util.chart.getLegend(project.store.left.length),
-                axes: [
-                    {
-                        type: 'Numeric',
-                        position: 'left',
-                        minimum: 0,
-                        fields: project.store.left,
-                        label: DHIS.util.chart.label.getNumericLabel(project.values),
-                        grid: {
-                            even: DHIS.util.chart.getGrid()
-                        }
-                    },
-                    {
-                        type: 'Category',
-                        position: 'bottom',
-                        fields: project.store.bottom,
-                        label: DHIS.util.chart.label.getCategoryLabel()
-                    }
-                ],
-                series: DHIS.util.chart.line.getSeriesArray(project)
-            });
-            
-            DHIS.projects[project.state.conf.el] = project;
-        },
-        area: function(project) {
-            project.chart = Ext.create('Ext.chart.Chart', {
-				renderTo: project.state.conf.el,
-                width: project.state.conf.width || this.el.getWidth(),
-                height: project.state.conf.height || this.el.getHeight(),
-                animate: !project.state.conf.skipAnimation,
-                store: project.store,
-                items: DHIS.util.chart.getTitle(),
-                legend: DHIS.util.chart.getLegend(project.store.left.length),
-                axes: [
-                    {
-                        type: 'Numeric',
-                        position: 'left',
-                        minimum: 0,
-                        fields: project.store.left,
-                        label: DHIS.util.chart.label.getNumericLabel(project.values),
-                        grid: {
-                            even: DHIS.util.chart.getGrid()
-                        }
-                    },
-                    {
-                        type: 'Category',
-                        position: 'bottom',
-                        fields: project.store.bottom,
-                        label: DHIS.util.chart.label.getCategoryLabel()
-                    }
-                ],
-                series: [{
-                    type: 'area',
-                    axis: 'left',
-                    xField: project.store.bottom[0],
-                    yField: project.store.left,
-					style: {
-						opacity: 0.65,
-						stroke: '#555'
-					}
-                }]
-            });
-            
-            DHIS.projects[project.state.conf.el] = project;
-        },
-        pie: function(project) {
-            project.chart = Ext.create('Ext.chart.Chart', {
-				renderTo: project.state.conf.el,
-                width: project.state.conf.width || this.el.getWidth(),
-                height: project.state.conf.height || this.el.getHeight(),
-                animate: !project.state.conf.skipAnimation,
-                shadow: true,
-                store: project.store,
-                insetPadding: 60,
-                items: DHIS.util.chart.pie.getTitle(project.state.filter.names[0], project.store.left[0]),
-                legend: DHIS.util.chart.getLegend(project.state.category.names.length),
-                series: [{
-                    type: 'pie',
-                    field: project.store.left[0],
-                    showInLegend: true,
-                    label: {
-                        field: project.store.bottom[0]
-                    },
-                    highlight: {
-                        segment: {
-                            margin: 10
-                        }
-                    },
-                    style: {
-                        opacity: 0.9,
-						stroke: '#555'
-                    },
-                    tips: DHIS.util.chart.pie.getTips(project.store.left[0])
-                }]
-            });
-            
-            DHIS.projects[project.state.conf.el] = project;
-        }
-    };
-    
-    DHIS.exe = {
-        allow: true,
-        queue: [],
-        addToQueue: function(conf) {
-            DHIS.exe.queue.push(conf);
-            if (DHIS.exe.allow) {
-                DHIS.exe.allow = false;
-                DHIS.exe.execute();
-            }
-        },
-        execute: function() {
-            if (this.queue.length) {
-                var conf = this.queue.shift();
-                this.destroy(conf.el);
-                if (conf.uid) {
-                    DHIS.state.setState(conf);
-                }
-                else {
-                    DHIS.state.getState(conf);
-                }
-            }
-            else {
-				DHIS.exe.allow = true;
-			}
-		},
-		destroy: function(el) {
-			if (DHIS.projects[el]) {
-				DHIS.projects[el].chart.destroy();
-			}
-		}
-    };
-    
-    DHIS.initialize();
-});

=== removed file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/css/chart.css'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/css/chart.css	2012-05-09 11:53:21 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/css/chart.css	1970-01-01 00:00:00 +0000
@@ -1,28 +0,0 @@
-.x-border-box,.x-border-box *{box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-webkit-box-sizing:border-box}
-.x-unselectable,.x-surface tspan{user-select:none;-o-user-select:none;-ms-user-select:none;-moz-user-select:0;-webkit-user-select:none;cursor:default}
-.x-css-shadow{position:absolute;-moz-border-radius:5px;-webkit-border-radius:5px 5px;-o-border-radius:5px 5px;-ms-border-radius:5px 5px;-khtml-border-radius:5px 5px;border-radius:5px 5px}
-.x-tip{position:absolute;overflow:visible;-moz-border-radius:3px;-webkit-border-radius:3px;-o-border-radius:3px;-ms-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;background-color:#ccc;border-color:#868686;border-style:solid;border-width:1px;padding:2px}
-.x-hide-visibility,.x-ie6 .x-masked select,.x-ie6.x-body-masked select{visibility:hidden!important}
-.x-layer{position:absolute;overflow:hidden;zoom:1}
-.x-tip-anchor{position:absolute;overflow:hidden;height:0;width:0;zoom:1;border-color:#868686;border-style:solid;border-width:5px}
-.x-border-box .x-tip-anchor{width:10px;height:10px}
-.x-tip-header,.x-tip-body,.x-form-invalid-tip-body{color:#444;font-size:11px;font-weight:400}
-.x-tip-anchor-top{border-top-color:transparent;border-left-color:transparent;border-right-color:transparent;_border-top-color:#FFC0CB;_border-left-color:#FFC0CB;_border-right-color:#FFC0CB;_filter:chroma(color=pink)}
-.x-tip-body,.x-form-invalid-tip-body{overflow:hidden;position:relative;padding:3px}
-.x-item-disabled,.x-item-disabled *,.x-tab-default-disabled *,.x-splitter-collapsed{cursor:default}
-.x-html:before,.x-html:after{white-space:pre-line}
-.x-btn *,.x-trigger-noedit,.x-tab *{cursor:hand}
-.x-surface{-moz-box-orient:vertical;vertical-align:auto;display:inline}
-.x-item-disabled,.x-splitter-active .x-collapse-el{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=30);opacity:.3}
-.x-masked-relative,.x-btn button,.x-btn a,.x-opera .x-menu-item-link,.x-window .x-window-wrap,.x-tab button,.x-tab a,.x-fit-item{position:relative}
-.x-inline-children > *{display:inline-block!important}
-.x-btn-split,.x-column-header-over .x-column-header-trigger,.x-column-header-open .x-column-header-trigger,.x-html html,.x-html address,.x-html blockquote,.x-html body,.x-html dd,.x-html div,.x-html dl,.x-html dt,.x-html fieldset,.x-html form,.x-html frame,.x-html frameset,.x-html h1,.x-html h2,.x-html h3,.x-html h4,.x-html h5,.x-html h6,.x-html noframes,.x-html ol,.x-html p,.x-html ul,.x-html center,.x-html dir,.x-html hr,.x-html menu,.x-html pre{display:block}
-.x-frame-shadow *{overflow:hidden;border:0;clear:none;zoom:1;margin:0;padding:0}
-.x-mask{z-index:100;position:absolute;top:0;left:0;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=50);opacity:.5;width:100%;height:100%;zoom:1;background:#ccc}
-.x-ie6 .x-item-disabled,.x-ie6 .x-btn-disabled span,.x-ie7 .x-btn-disabled span,.x-ie7 .x-btn-disabled,.x-ie8 .x-btn-disabled{filter:none}
-.x-color-picker em span{cursor:pointer;display:block;height:10px;width:10px;line-height:10px}
-.x-ie .x-fieldset-noborder legend span{position:absolute;left:16px}
-.x-grid-tree-loading span{font-style:italic;color:#444}
-table.x-datepicker-inner .x-datepicker-selected span{font-weight:700}
-.x-btn-disabled span,.x-menu-item-disabled,.x-ie .x-menu-item-disabled .x-menu-item-icon{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=50);opacity:.5}
-table.x-datepicker-inner th span{display:block;padding-right:7px}

=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/css/plugin.css'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/css/plugin.css	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/css/plugin.css	2012-05-15 22:35:45 +0000
@@ -0,0 +1,31 @@
+.x-border-box,.x-border-box *{box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-webkit-box-sizing:border-box}
+.x-unselectable,.x-surface tspan{user-select:none;-o-user-select:none;-ms-user-select:none;-moz-user-select:0;-webkit-user-select:none;cursor:default}
+.x-css-shadow{position:absolute;-moz-border-radius:5px;-webkit-border-radius:5px 5px;-o-border-radius:5px 5px;-ms-border-radius:5px 5px;-khtml-border-radius:5px 5px;border-radius:5px 5px}
+.x-tip{position:absolute;overflow:visible;-moz-border-radius:3px;-webkit-border-radius:3px;-o-border-radius:3px;-ms-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;background-color:#ccc;border-color:#868686;border-style:solid;border-width:1px;padding:2px}
+.x-hide-visibility,.x-ie6 .x-masked select,.x-ie6.x-body-masked select{visibility:hidden!important}
+.x-layer{position:absolute;overflow:hidden;zoom:1}
+.x-tip-anchor{position:absolute;overflow:hidden;height:0;width:0;zoom:1;border-color:#868686;border-style:solid;border-width:5px}
+.x-border-box .x-tip-anchor{width:10px;height:10px}
+.x-tip-header,.x-tip-body,.x-form-invalid-tip-body{color:#444;font-size:11px;font-weight:400}
+.x-tip-anchor-top{border-top-color:transparent;border-left-color:transparent;border-right-color:transparent;_border-top-color:#FFC0CB;_border-left-color:#FFC0CB;_border-right-color:#FFC0CB;_filter:chroma(color=pink)}
+.x-tip-body,.x-form-invalid-tip-body{overflow:hidden;position:relative;padding:3px}
+.x-item-disabled,.x-item-disabled *,.x-tab-default-disabled *,.x-splitter-collapsed{cursor:default}
+.x-html:before,.x-html:after{white-space:pre-line}
+.x-btn *,.x-trigger-noedit,.x-tab *{cursor:hand}
+.x-surface{-moz-box-orient:vertical;vertical-align:auto;display:inline}
+.x-item-disabled,.x-splitter-active .x-collapse-el{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=30);opacity:.3}
+.x-masked-relative,.x-btn button,.x-btn a,.x-opera .x-menu-item-link,.x-window .x-window-wrap,.x-tab button,.x-tab a,.x-fit-item{position:relative}
+.x-inline-children > *{display:inline-block!important}
+.x-btn-split,.x-column-header-over .x-column-header-trigger,.x-column-header-open .x-column-header-trigger,.x-html html,.x-html address,.x-html blockquote,.x-html body,.x-html dd,.x-html div,.x-html dl,.x-html dt,.x-html fieldset,.x-html form,.x-html frame,.x-html frameset,.x-html h1,.x-html h2,.x-html h3,.x-html h4,.x-html h5,.x-html h6,.x-html noframes,.x-html ol,.x-html p,.x-html ul,.x-html center,.x-html dir,.x-html hr,.x-html menu,.x-html pre{display:block}
+.x-frame-shadow *{overflow:hidden;border:0;clear:none;zoom:1;margin:0;padding:0}
+.x-mask{z-index:100;position:absolute;top:0;left:0;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=50);opacity:.5;width:100%;height:100%;zoom:1;background:#ccc}
+.x-ie6 .x-item-disabled,.x-ie6 .x-btn-disabled span,.x-ie7 .x-btn-disabled span,.x-ie7 .x-btn-disabled,.x-ie8 .x-btn-disabled{filter:none}
+.x-color-picker em span{cursor:pointer;display:block;height:10px;width:10px;line-height:10px}
+.x-ie .x-fieldset-noborder legend span{position:absolute;left:16px}
+.x-grid-tree-loading span{font-style:italic;color:#444}
+table.x-datepicker-inner .x-datepicker-selected span{font-weight:700}
+.x-btn-disabled span,.x-menu-item-disabled,.x-ie .x-menu-item-disabled .x-menu-item-icon{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=50);opacity:.5}
+table.x-datepicker-inner th span{display:block;padding-right:7px}
+.dv-chart-tips, .dv-chart-tips-pie {border-width:2px;background-color:#eee;padding:2px 4px 0;}
+.dv-chart-tips .x-tip-body {font-size:22px;font-family:arial,sans-serif,ubuntu,consolas}
+.dv-chart-tips-pie .x-tip-body {font-size:17px;font-family:arial,sans-serif,ubuntu,consolas}

=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/plugin.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/plugin.js	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/plugin.js	2012-05-15 22:43:36 +0000
@@ -0,0 +1,1228 @@
+DHIS = {
+	chart: {},
+	table: {}
+};
+
+/* CHART */
+
+DHIS.chart.conf = {
+    finals: {
+        ajax: {
+            data_get: 'api/chartValues.jsonp',
+            favorite_get: 'api/charts/'
+        },        
+        dimension: {
+            data: {
+                value: 'data',
+                rawvalue: 'Data'
+            },
+            indicator: {
+                value: 'indicator',
+                rawvalue: 'Indicator'
+            },
+            dataelement: {
+                value: 'dataelement',
+                rawvalue: 'Data element'
+            },
+            period: {
+                value: 'period',
+                rawvalue: 'Period'
+            },
+            organisationunit: {
+                value: 'organisationunit',
+                rawvalue: 'Organisation unit'
+            }
+        },
+        chart: {
+            x: 'x',
+            series: 'series',
+            category: 'category',
+            filter: 'filter',
+            column: 'column',
+            stackedcolumn: 'stackedcolumn',
+            bar: 'bar',
+            stackedbar: 'stackedbar',
+            line: 'line',
+            area: 'area',
+            pie: 'pie',
+            orgUnitIsParent: 'orgUnitIsParent'
+        },
+        data: {
+			domain: 'domain_',
+			targetline: 'targetline_',
+			baseline: 'baseline_',
+			trendline: 'trendline_'
+		},
+    },
+    chart: {
+        style: {
+            inset: 30,
+            font: 'arial,sans-serif,ubuntu,consolas'
+        },
+        theme: {
+            dv1: ['#94ae0a', '#0b3b68', '#a61120', '#ff8809', '#7c7474', '#a61187', '#ffd13e', '#24ad9a', '#a66111', '#414141', '#4500c4', '#1d5700']
+        }
+    }
+};
+
+Ext.onReady( function() {
+	
+    DHIS.chart.initialize = function() {
+        DHIS.chart.store.column = DHIS.chart.store.defaultChartStore;
+        DHIS.chart.store.stackedcolumn = DHIS.chart.store.defaultChartStore;
+        DHIS.chart.store.stackedbar = DHIS.chart.store.bar;
+        DHIS.chart.store.line = DHIS.chart.store.defaultChartStore;
+        DHIS.chart.store.area = DHIS.chart.store.defaultChartStore;
+        DHIS.chart.store.pie = DHIS.chart.store.defaultChartStore;
+        
+        DHIS.getChart = DHIS.chart.exe.addToQueue;
+        DHIS.destroyChart = DHIS.chart.exe.destroy;
+    };
+    
+    DHIS.chart.projects = {};
+    
+    DHIS.chart.plugin = {
+		SimpleRegression: function SimpleRegression() {
+			var sumX = 0;
+			var sumY = 0;
+			var sumXX = 0;
+			var sumXY = 0;
+			var n = 0;
+			var xbar = 0;
+			var ybar = 0;
+			
+			this.addData = function(x, y) {
+				if ( n == 0 ) {
+					xbar = x;
+					ybar = y;
+				}
+				else {
+					var dx = x - xbar;
+					var dy = y - ybar;
+					sumXX += dx * dx * n / ( n + 1 );
+					sumXY += dx * dy * n / ( n + 1 );
+					xbar += dx / ( n + 1 );
+					ybar += dy / ( n + 1 );
+				}
+				
+				sumX += x;
+				sumY += y;
+				n++;
+			};
+			
+			this.predict = function( x ) {
+				var b1 = this.getSlope();				
+				return this.getIntercept( b1 ) + b1 * x;
+			};
+			
+			this.getSlope = function() {
+				if ( n < 2 ) {
+					return Number.NaN;
+				}				
+				return sumXY / sumXX;
+			};
+			
+			this.getIntercept = function( slope ) {
+				return ( sumY - slope * sumX ) / n;
+			};
+		}
+	};
+    
+    DHIS.chart.util = {
+        dimension: {
+            indicator: {
+                getIdsFromObjects: function(indicators) {
+                    var a = []
+                    for (var i = 0; i < indicators.length; i++) {
+                        a.push(indicators[i].id);
+                    }
+                    return a;
+                }
+            },
+            dataelement: {
+                getIdsFromObjects: function(dataelements) {
+                    var a = []
+                    for (var i = 0; i < dataelements.length; i++) {
+                        a.push(dataelements[i].id);
+                    }
+                    return a;
+                }
+            },
+            data: {
+                getUrl: function(isFilter) {
+                    var a = [];
+                    Ext.Array.each(DHIS.chart.state.state.conf.indicators, function(r) {
+                        a.push('indicatorIds=' + r);
+                    });
+                    Ext.Array.each(DHIS.chart.state.state.conf.dataelements, function(r) {
+                        a.push('dataElementIds=' + r);
+                    });
+                    return (isFilter && a.length > 1) ? a.slice(0,1) : a;
+                }
+            },
+            period: {
+                getUrl: function(isFilter) {
+                    var a = [];
+                    Ext.Array.each(DHIS.chart.state.state.conf.periods, function(r) {
+						a.push(r + '=true')
+                    });
+                    return (isFilter && a.length > 1) ? a.slice(0,1) : a;
+                },
+                getRelativesFromObject: function(obj) {
+                    var a = [];
+                    for (var k in obj) {
+                        if (obj[k]) {
+                            a.push(k);
+                        }
+                    }
+                    return a;
+                }
+            },
+            organisationunit: {
+                getUrl: function(isFilter) {
+                    var a = [];
+                    Ext.Array.each(DHIS.chart.state.state.conf.organisationunits, function(r) {
+						a.push('organisationUnitIds=' + r)
+                    });
+                    return (isFilter && a.length > 1) ? a.slice(0,1) : a;
+                },
+                getIdsFromObjects: function(organisationunits) {
+                    var a = []
+                    for (var i = 0; i < organisationunits.length; i++) {
+                        a.push(organisationunits[i].id);
+                    }
+                    return a;
+                }
+            }
+        },
+        chart: {
+			def: {
+				getChart: function(project, axes, series, elWidth, elHeight) {
+					return Ext.create('Ext.chart.Chart', {
+						renderTo: project.state.conf.el,
+						animate: true,
+						store: project.store,
+						insetPadding: DHIS.chart.conf.chart.style.inset,						
+						items: project.state.conf.hideSubtitle ? false : DHIS.chart.util.chart.def.getTitle(project),
+						legend: project.state.conf.hideLegend ? false : DHIS.chart.util.chart.def.getLegend(project.store.range.length),
+						width: project.state.conf.width || elWidth,
+						height: project.state.conf.height || elHeight,
+						axes: axes,
+						series: series,
+						theme: project.state.conf.el
+					});
+				},
+				getLegend: function(len) {
+					len = len ? len : 1;
+					return {
+						position: len > 5 ? 'right' : 'top',
+						labelFont: '11px ' + DHIS.chart.conf.chart.style.font,
+						boxStroke: '#ffffff',
+						boxStrokeWidth: 0,
+						padding: 0
+					};
+				},
+				getTitle: function(project) {
+					return {
+						type: 'text',
+						text: project.state.filter.names[0],
+						font: 'bold 13px ' + DHIS.chart.conf.chart.style.font,
+						fill: '#222',
+						width: 300,
+						height: 20,
+						x: 28,
+						y: 16
+					};
+				},
+				getGrid: function() {
+					return {
+						opacity: 1,
+						fill: '#f1f1f1',
+						stroke: '#aaa',
+						'stroke-width': 0.2
+					};
+				},
+				setMask: function(str) {
+					if (DHIS.chart.mask) {
+						DHIS.chart.mask.hide();
+					}
+					DHIS.chart.mask = new Ext.LoadMask(DHIS.chart.chart.chart, {msg: str});
+					DHIS.chart.mask.show();
+				},
+				label: {
+					getCategory: function() {
+						return {
+							font: '11px ' + DHIS.chart.conf.chart.style.font,
+							rotate: {
+								degrees: 320
+							}
+						};
+					},
+					getNumeric: function(values) {
+						return {
+							font: '11px ' + DHIS.chart.conf.chart.style.font,
+							renderer: Ext.util.Format.numberRenderer(DHIS.chart.util.number.getChartAxisFormatRenderer(values))
+						};
+					}
+				},
+				axis: {
+					getNumeric: function(project, isStacked) {
+						return {
+							type: 'Numeric',
+							position: 'left',
+							title: project.state.conf.rangeAxisLabel || false,
+							labelTitle: {
+								font: '17px ' + DHIS.chart.conf.chart.style.font
+							},
+							minimum: 0,
+							fields: isStacked ? project.state.series.names : project.store.range,
+							label: DHIS.chart.util.chart.def.label.getNumeric(project.values),
+							grid: {
+								odd: {
+									opacity: 1,
+									fill: '#fefefe',
+									stroke: '#aaa',
+									'stroke-width': 0.1
+								},									
+								even: {
+									opacity: 1,
+									fill: '#f1f1f1',
+									stroke: '#aaa',
+									'stroke-width': 0.1
+								}
+							}
+						};
+					},
+					getCategory: function(project) {
+						return {
+							type: 'Category',
+							position: 'bottom',
+							title: project.state.conf.domainAxisLabel || false,
+							labelTitle: {
+								font: '17px ' + DHIS.chart.conf.chart.style.font
+							},
+							fields: DHIS.chart.conf.finals.data.domain,
+							label: DHIS.chart.util.chart.def.label.getCategory()
+						};
+					}
+				},
+				series: {
+					getTips: function() {
+						return {
+							trackMouse: true,
+							cls: 'dv-chart-tips',
+							renderer: function(r, item) {
+								this.update('' + item.value[1]);
+							}
+						};
+					},
+					getTargetLine: function(project) {
+						var title = project.state.conf.targetLineLabel || 'Target';
+						title += ' (' + project.state.conf.targetLineValue + ')';
+						return {
+							type: 'line',
+							axis: 'left',
+							xField: DHIS.chart.conf.finals.data.domain,
+							yField: DHIS.chart.conf.finals.data.targetline,
+							style: {
+								opacity: 1,
+								lineWidth: 3,
+								stroke: '#041423'
+							},
+							markerConfig: {
+								type: 'circle',
+								radius: 0
+							},
+							title: title
+						};
+					},
+					getBaseLine: function(project) {
+						var title = project.state.conf.baseLineLabel || 'Base';
+						title += ' (' + project.state.conf.baseLineValue + ')';
+						return {
+							type: 'line',
+							axis: 'left',
+							xField: DHIS.chart.conf.finals.data.domain,
+							yField: DHIS.chart.conf.finals.data.baseline,
+							style: {
+								opacity: 1,
+								lineWidth: 3,
+								stroke: '#041423'
+							},
+							markerConfig: {
+								type: 'circle',
+								radius: 0
+							},
+							title: title
+						};
+					},
+					getTrendLineArray: function(project) {						
+						var a = [];
+						for (var i = 0; i < project.trendline.length; i++) {
+							a.push({
+								type: 'line',
+								axis: 'left',
+								xField: DHIS.chart.conf.finals.data.domain,
+								yField: project.trendline[i].key,
+								style: {
+									opacity: 0.8,
+									lineWidth: 3
+								},
+								markerConfig: {
+									type: 'circle',
+									radius: 4
+								},
+								tips: DHIS.chart.util.chart.def.series.getTips(),
+								title: project.trendline[i].name
+							});
+						}
+						return a;
+					},
+					setTheme: function(project) {
+						var colors = DHIS.chart.conf.chart.theme.dv1.slice(0, project.state.series.names.length);
+						if (project.state.conf.targetLineValue || project.state.conf.baseLineValue) {
+							colors.push('#051a2e');
+						}					
+						if (project.state.conf.targetLineValue) {
+							colors.push('#051a2e');
+						}					
+						if (project.state.conf.baseLineValue) {
+							colors.push('#051a2e');
+						}
+						Ext.chart.theme[project.state.conf.el] = Ext.extend(Ext.chart.theme.Base, {
+							constructor: function(config) {
+								Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
+									seriesThemes: colors,
+									colors: colors
+								}, config));
+							}
+						});
+					}
+				}
+			},
+            bar: {
+				label: {
+					getCategory: function() {
+						return {
+							font: '11px ' + DHIS.chart.conf.chart.style.font
+						};
+					}
+				},
+				axis: {
+					getNumeric: function(project) {
+						var num = DHIS.chart.util.chart.def.axis.getNumeric(project);
+						num.position = 'bottom';
+						return num;
+					},
+					getCategory: function(project) {
+						var cat = DHIS.chart.util.chart.def.axis.getCategory(project);
+						cat.position = 'left';
+						cat.label = DHIS.chart.util.chart.bar.label.getCategory();
+						return cat;
+					}
+				},
+                series: {
+					getTips: function() {
+						return {
+							trackMouse: true,
+							cls: 'dv-chart-tips',
+							renderer: function(si, item) {
+								this.update('' + item.value[0]);
+							}
+						};
+					},
+					getTargetLine: function(project) {
+						var line = DHIS.chart.util.chart.def.series.getTargetLine(project);
+						line.axis = 'bottom';
+						line.xField = DHIS.chart.conf.finals.data.targetline;
+						line.yField = DHIS.chart.conf.finals.data.domain;
+						return line;
+					},
+					getBaseLine: function(project) {
+						var line = DHIS.chart.util.chart.def.series.getBaseLine(project);
+						line.axis = 'bottom';
+						line.xField = DHIS.chart.conf.finals.data.baseline;
+						line.yField = DHIS.chart.conf.finals.data.domain;
+						return line;
+					},
+					getTrendLineArray: function(project) {
+						var a = [];
+						for (var i = 0; i < project.trendline.length; i++) {
+							a.push({
+								type: 'line',
+								axis: 'bottom',
+								xField: project.trendline[i].key,
+								yField: DHIS.chart.conf.finals.data.domain,
+								style: {
+									opacity: 0.8,
+									lineWidth: 3
+								},
+								markerConfig: {
+									type: 'circle',
+									radius: 4
+								},
+								tips: DHIS.chart.util.chart.bar.series.getTips(),
+								title: project.trendline[i].name
+							});
+						}
+						return a;
+					}
+				}
+            },
+            line: {
+				series: {
+					getArray: function(project) {
+						var a = [];
+						for (var i = 0; i < project.state.series.names.length; i++) {
+							a.push({
+								type: 'line',
+								axis: 'left',
+								xField: DHIS.chart.conf.finals.data.domain,
+								yField: project.state.series.names[i],
+								style: {
+									opacity: 0.8,
+									lineWidth: 3
+								},
+								markerConfig: {
+									type: 'circle',
+									radius: 4
+								},
+								tips: DHIS.chart.util.chart.def.series.getTips()
+							});
+						}
+						return a;
+					},
+					setTheme: function(project) {
+						var colors = DHIS.chart.conf.chart.theme.dv1.slice(0, project.state.series.names.length);
+						if (project.state.conf.trendLine) {
+							colors = colors.concat(colors);
+						}
+						if (project.state.conf.targetLineValue) {
+							colors.push('#051a2e');
+						}
+						if (project.state.conf.baseLineValue) {
+							colors.push('#051a2e');
+						}
+						Ext.chart.theme[project.state.conf.el] = Ext.extend(Ext.chart.theme.Base, {
+							constructor: function(config) {
+								Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
+									seriesThemes: colors,
+									colors: colors
+								}, config));
+							}
+						});
+					}
+                }
+            },
+            pie: {
+                getTitle: function(title, subtitle) {
+                    return [
+                        {
+                            type: 'text',
+                            text: title,
+                            font: 'bold 13px arial',
+                            fill: '#222',
+                            width: 300,
+                            height: 20,
+                            x: 28,
+                            y: 16
+                        },
+                        {
+                            type: 'text',
+                            text: subtitle,
+                            font: 'bold 11px arial',
+                            fill: '#777',
+                            width: 300,
+                            height: 20,
+                            x: 28,
+                            y: 36
+                        }
+                    ];                        
+                },
+                series: {
+					getTips: function(project) {
+						return {
+							trackMouse: true,
+							cls: 'dv-chart-tips-pie',
+							renderer: function(item) {
+								this.update(item.data[DHIS.chart.conf.finals.data.domain] + '<br/><b>' + item.data[project.state.series.names[0]] + '</b>');
+							}
+						};
+					},
+					setTheme: function(project) {
+						var colors = DHIS.chart.conf.chart.theme.dv1.slice(0, project.state.category.names.length);
+						Ext.chart.theme[project.state.conf.el] = Ext.extend(Ext.chart.theme.Base, {
+							constructor: function(config) {
+								Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
+									seriesThemes: colors,
+									colors: colors
+								}, config));
+							}
+						});
+					}
+				}
+            }
+        },
+        number: {
+            isInteger: function(n) {
+                var str = new String(n);
+                if (str.indexOf('.') > -1) {
+                    var d = str.substr(str.indexOf('.') + 1);
+                    return (d.length === 1 && d == '0');
+                }
+                return false;
+            },
+            allValuesAreIntegers: function(values) {
+                for (var i = 0; i < values.length; i++) {
+                    if (!this.isInteger(values[i].v)) {
+                        return false;
+                    }
+                }
+                return true;
+            },
+            getChartAxisFormatRenderer: function(values) {
+                return this.allValuesAreIntegers(values) ? '0' : '0.0';
+            }
+        },
+        string: {
+            getEncodedString: function(text) {
+                return text.replace(/[^a-zA-Z 0-9(){}<>_!+;:?*&%#-]+/g,'');
+            },
+            extendUrl: function(url) {
+                if (url.charAt(url.length-1) !== '/') {
+                    url += '/';
+                }
+                return url;
+            },
+            appendUrlIfTrue: function(url, param, expression) {
+            	if (expression && expression == true) {
+            		url = Ext.String.urlAppend(url, param + '=true');
+            	}
+            	return url;            	
+            }
+        },
+        value: {
+            jsonfy: function(r) {                
+                var object = {
+                    values: [],
+                    periods: r.p,
+                    datanames: [],
+                    organisationunitnames: []
+                };
+                for (var i = 0; i < r.v.length; i++) {
+                    var obj = {};
+                    obj.v = r.v[i][0];
+                    obj[DHIS.chart.conf.finals.dimension.data.value] = r.v[i][1];
+                    obj[DHIS.chart.conf.finals.dimension.period.value] = r.v[i][2];
+                    obj[DHIS.chart.conf.finals.dimension.organisationunit.value] = r.v[i][3];
+                    object.values.push(obj);
+                }
+                for (var j = 0; j < r.d.length; j++) {
+					object.datanames.push(DHIS.chart.util.string.getEncodedString(r.d[j]));
+				}
+                for (var k = 0; k < r.o.length; k++) {
+					object.organisationunitnames.push(DHIS.chart.util.string.getEncodedString(r.o[k]));
+				}
+                return object;
+            }
+        }
+    };
+    
+    DHIS.chart.store = {
+        getChartStore: function(project) {
+            var keys = [];            
+            Ext.Array.each(project.data, function(item) {
+                keys = Ext.Array.merge(keys, Ext.Object.getKeys(item));
+            });            
+            project.store = Ext.create('Ext.data.Store', {
+                fields: keys,
+                data: project.data
+            });
+            project.store.range = keys.slice(0);
+            for (var i = 0; i < project.store.range.length; i++) {
+                if (project.store.range[i] === DHIS.chart.conf.finals.data.domain) {
+                    project.store.range.splice(i, 1);
+                }
+            }
+            
+			DHIS.chart.chart.getChart(project);
+        }
+    };
+    
+    DHIS.chart.state = {
+        state: null,
+        getState: function(conf) {
+            var project = {
+                state: {
+                    conf: null,
+                    type: null,
+                    series: {
+                        dimension: null,
+                        names: []
+                    },
+                    category: {
+                        dimension: null,
+                        names: []
+                    },
+                    filter: {
+                        dimension: null,
+                        names: []
+                    }
+                }
+            };
+            
+            var defaultConf = {
+                type: 'column',
+                stacked: false,
+                indicators: [],
+                periods: ['last12Months'],
+                organisationunits: [],
+                series: 'data',
+                category: 'period',
+                filter: 'organisationunit',
+                el: '',
+                legendPosition: false,
+                orgUnitIsParent: false,
+                showData: false,
+                trendLine: false,
+                hideLegend: false,
+                hideSubtitle: false,
+                targetLineValue: null,
+                targetLineLabel: null,
+                baseLineValue: null,
+                baseLineLabel: null,                
+                url: ''
+            };
+            
+            project.state.conf = Ext.applyIf(conf, defaultConf);
+            project.state.conf.type = project.state.conf.type.toLowerCase();
+            project.state.conf.series = project.state.conf.series.toLowerCase();
+            project.state.conf.category = project.state.conf.category.toLowerCase();
+            project.state.conf.filter = project.state.conf.filter.toLowerCase();
+            
+            project.state.conf[project.state.conf.series] = DHIS.chart.conf.finals.chart.series;
+            project.state.conf[project.state.conf.category] = DHIS.chart.conf.finals.chart.category;
+            project.state.conf[project.state.conf.filter] = DHIS.chart.conf.finals.chart.filter;
+            
+            project.state.type = project.state.conf.type;
+            project.state.series.dimension = project.state.conf.series;
+            project.state.category.dimension = project.state.conf.category;
+            project.state.filter.dimension = project.state.conf.filter;
+            
+            DHIS.chart.state.state = project.state;
+            
+			DHIS.chart.value.getValues(project);
+        },
+        setState: function(conf) {
+            if (conf.uid) {
+                Ext.data.JsonP.request({
+                    url: conf.url + DHIS.chart.conf.finals.ajax.favorite_get + conf.uid + '.jsonp',
+                    scope: this,
+                    success: function(r) {
+                        if (!r) {
+                            alert('Invalid uid');
+                            return;
+                        }
+                        
+                        conf.type = r.type.toLowerCase();
+                        conf.periods = DHIS.chart.util.dimension.period.getRelativesFromObject(r.relativePeriods);
+                        conf.organisationunits = DHIS.chart.util.dimension.organisationunit.getIdsFromObjects(r.organisationUnits);
+                        conf.series = r.series.toLowerCase();
+                        conf.category = r.category.toLowerCase();
+                        conf.filter = r.filter.toLowerCase();
+                        conf.legendPosition = conf.legendPosition || false;
+                        
+                        if (r.indicators) {
+                            conf.indicators = DHIS.chart.util.dimension.indicator.getIdsFromObjects(r.indicators);
+                        }
+                        if (r.dataElements) {
+                            conf.dataelements = DHIS.chart.util.dimension.dataelement.getIdsFromObjects(r.dataElements);
+                        }
+                        
+                        this.getState(conf);                        
+                    }
+                });
+            }
+        }
+    };
+    
+    DHIS.chart.value = {
+        getValues: function(project) {
+            var params = [];                
+            params = params.concat(DHIS.chart.util.dimension[project.state.series.dimension].getUrl());
+            params = params.concat(DHIS.chart.util.dimension[project.state.category.dimension].getUrl());
+            params = params.concat(DHIS.chart.util.dimension[project.state.filter.dimension].getUrl(true));
+                        
+            var baseUrl = DHIS.chart.util.string.extendUrl(project.state.conf.url) + DHIS.chart.conf.finals.ajax.data_get;
+            baseUrl = DHIS.chart.util.string.appendUrlIfTrue(baseUrl, DHIS.chart.conf.finals.chart.orgUnitIsParent, project.state.orgUnitIsParent);
+            
+            Ext.Array.each(params, function(item) {
+                baseUrl = Ext.String.urlAppend(baseUrl, item);
+            });
+            
+            Ext.data.JsonP.request({
+                url: baseUrl,
+                disableCaching: false,
+                success: function(r) {
+                    var json = DHIS.chart.util.value.jsonfy(r);
+                    project.values = json.values;
+                    
+                    if (!project.values.length) {
+                        alert('No data values');
+                        return;
+                    }
+                    
+                    for (var i = 0; i < project.values.length; i++) {
+                        project.values[i][DHIS.chart.conf.finals.dimension.data.value] = DHIS.chart.util.string.getEncodedString(project.values[i][DHIS.chart.conf.finals.dimension.data.value]);
+                        project.values[i][DHIS.chart.conf.finals.dimension.period.value] = DHIS.chart.util.string.getEncodedString(project.values[i][DHIS.chart.conf.finals.dimension.period.value]);
+                        project.values[i][DHIS.chart.conf.finals.dimension.organisationunit.value] = DHIS.chart.util.string.getEncodedString(project.values[i][DHIS.chart.conf.finals.dimension.organisationunit.value]);
+                    }
+                    
+                    project.state[project.state.conf.data].names = json.datanames;
+                    project.state[project.state.conf.organisationunit].names = json.organisationunitnames;
+                    Ext.Array.each(project.values, function(item) {						
+                        Ext.Array.include(project.state[project.state.conf.period].names, DHIS.chart.util.string.getEncodedString(item[project.state[project.state.conf.period].dimension]));
+                        item.v = parseFloat(item.v);
+                    });
+                    
+                    for (var k in project.state.conf) {
+                        if (project.state.conf[k] == 'period') {
+                            project.state[k].names = json.periods;
+                        }
+                    }
+                    
+                    DHIS.chart.state.state = project.state;
+					DHIS.chart.chart.getData(project);
+                }
+            });
+        }
+    };
+    
+    DHIS.chart.chart = {
+        getData: function(project) {
+            project.data = [];
+			
+            Ext.Array.each(project.state.category.names, function(item) {
+                var obj = {};
+                obj[DHIS.chart.conf.finals.data.domain] = item;
+                project.data.push(obj);
+            });
+            
+            Ext.Array.each(project.data, function(item) {
+                for (var i = 0; i < project.state.series.names.length; i++) {
+                    item[project.state.series.names[i]] = 0;
+                }
+            });
+            
+            Ext.Array.each(project.data, function(item) {
+                for (var i = 0; i < project.state.series.names.length; i++) {
+                    for (var j = 0; j < project.values.length; j++) {
+                        if (project.values[j][project.state.category.dimension] === item[DHIS.chart.conf.finals.data.domain] && project.values[j][project.state.series.dimension] === project.state.series.names[i]) {
+                            item[project.values[j][project.state.series.dimension]] = project.values[j].v;
+                            break;
+                        }
+                    }
+                }
+            });
+            
+			if (project.state.conf.trendLine) {
+				project.trendline = [];
+				for (var i = 0; i < project.state.series.names.length; i++) {
+					var s = project.state.series.names[i],
+						reg = new DHIS.chart.plugin.SimpleRegression();
+					for (var j = 0; j < project.data.length; j++) {
+						reg.addData(j, project.data[j][s]);
+					}
+					var key = DHIS.chart.conf.finals.data.trendline + s;
+					for (var j = 0; j < project.data.length; j++) {
+						var n = reg.predict(j);
+						project.data[j][key] = parseFloat(reg.predict(j).toFixed(1));
+					}
+					project.trendline.push({
+						key: key,
+						name: 'Trend (' + s + ')'
+					});
+				}
+			}
+
+			if (project.state.conf.targetLineValue) {
+				Ext.Array.each(project.data, function(item) {
+					item[DHIS.chart.conf.finals.data.targetline] = project.state.conf.targetLineValue;
+				});
+			}
+
+			if (project.state.conf.baseLineValue) {
+				Ext.Array.each(project.data, function(item) {
+					item[DHIS.chart.conf.finals.data.baseline] = project.state.conf.baseLineValue;
+				});
+			}
+                
+			DHIS.chart.store.getChartStore(project);
+        },
+        el: null,
+        getChart: function(project) {
+            this.el = Ext.get(project.state.conf.el);
+            this[project.state.type](project);
+            DHIS.chart.exe.execute();
+        },
+        column: function(project, isStacked) {
+			var series = [];
+			if (project.state.conf.trendLine) {
+				var a = DHIS.chart.util.chart.def.series.getTrendLineArray(project);
+				for (var i = 0; i < a.length; i++) {
+					series.push(a[i]);
+				}
+			}
+			var main = {
+				type: 'column',
+				axis: 'left',
+				xField: DHIS.chart.conf.finals.data.domain,
+				yField: project.state.series.names,
+				stacked: isStacked,
+				style: {
+					opacity: 0.8,
+					stroke: '#333'
+				},
+				tips: DHIS.chart.util.chart.def.series.getTips()
+			};
+			if (project.state.conf.showData) {
+				main.label = {display: 'outside', field: project.state.series.names};
+			}
+			series.push(main);
+			if (project.state.conf.targetLineValue) {
+				series.push(DHIS.chart.util.chart.def.series.getTargetLine(project));
+			}
+			if (project.state.conf.baseLineValue) {
+				series.push(DHIS.chart.util.chart.def.series.getBaseLine(project));
+			}
+			
+			var axes = [];
+			var numeric = DHIS.chart.util.chart.def.axis.getNumeric(project, isStacked);
+			axes.push(numeric);
+			axes.push(DHIS.chart.util.chart.def.axis.getCategory(project));
+			
+			DHIS.chart.util.chart.def.series.setTheme(project);
+			project.chart = DHIS.chart.util.chart.def.getChart(project, axes, series, this.el.getWidth(), this.el.getHeight());
+			
+            DHIS.chart.projects[project.state.conf.el] = project;
+        },
+        stackedcolumn: function(project) {
+            this.column(project, true);
+        },
+        bar: function(project, isStacked) {
+			var series = [];
+			if (project.state.conf.trendLine) {
+				var a = DHIS.chart.util.chart.bar.series.getTrendLineArray(project);
+				for (var i = 0; i < a.length; i++) {
+					series.push(a[i]);
+				}
+			}
+			var main = {
+				type: 'bar',
+				axis: 'bottom',
+				xField: DHIS.chart.conf.finals.data.domain,
+				yField: project.state.series.names,
+				stacked: isStacked,
+				style: {
+					opacity: 0.8,
+					stroke: '#333'
+				},
+				tips: DHIS.chart.util.chart.def.series.getTips()
+			};
+			if (project.state.conf.showData) {
+				main.label = {display: 'outside', field: project.state.series.names};
+			}
+			series.push(main);
+			if (project.state.conf.targetLineValue) {
+				series.push(DHIS.chart.util.chart.bar.series.getTargetLine(project));
+			}
+			if (project.state.conf.baseLineValue) {
+				series.push(DHIS.chart.util.chart.bar.series.getBaseLine(project));
+			}
+			
+			var axes = [];
+			var numeric = DHIS.chart.util.chart.bar.axis.getNumeric(project, isStacked);
+			axes.push(numeric);
+			axes.push(DHIS.chart.util.chart.bar.axis.getCategory(project));
+			
+			DHIS.chart.util.chart.def.series.setTheme(project);
+			project.chart = DHIS.chart.util.chart.def.getChart(project, axes, series, this.el.getWidth(), this.el.getHeight());
+			
+            DHIS.chart.projects[project.state.conf.el] = project;
+        },
+        stackedbar: function(project) {
+            this.bar(project, true);
+        },
+        line: function(project) {
+			var series = [];
+			if (project.state.conf.trendLine) {
+				var a = DHIS.chart.util.chart.def.series.getTrendLineArray(project);
+				for (var i = 0; i < a.length; i++) {
+					series.push(a[i]);
+				}
+			}	
+			series = series.concat(DHIS.chart.util.chart.line.series.getArray(project));
+			
+			if (project.state.conf.targetLineValue) {
+				series.push(DHIS.chart.util.chart.def.series.getTargetLine(project));
+			}
+			if (project.state.conf.baseLineValue) {
+				series.push(DHIS.chart.util.chart.def.series.getBaseLine(project));
+			}
+			
+			var axes = [];
+			var numeric = DHIS.chart.util.chart.def.axis.getNumeric(project);
+			axes.push(numeric);
+			axes.push(DHIS.chart.util.chart.def.axis.getCategory(project));
+			
+			DHIS.chart.util.chart.line.series.setTheme(project);
+			project.chart = DHIS.chart.util.chart.def.getChart(project, axes, series, this.el.getWidth(), this.el.getHeight());
+            
+            DHIS.chart.projects[project.state.conf.el] = project;
+        },
+        area: function(project) {
+			var series = [];
+			series.push({
+				type: 'area',
+				axis: 'left',
+				xField: DHIS.chart.conf.finals.data.domain,
+				yField: project.state.series.names,
+				style: {
+					opacity: 0.65,
+					stroke: '#555'
+				}
+			});
+			
+			var axes = [];
+			var numeric = DHIS.chart.util.chart.def.axis.getNumeric(project);
+			axes.push(numeric);
+			axes.push(DHIS.chart.util.chart.def.axis.getCategory(project));
+			
+			DHIS.chart.util.chart.line.series.setTheme(project);
+			project.chart = DHIS.chart.util.chart.def.getChart(project, axes, series, this.el.getWidth(), this.el.getHeight());
+            
+            DHIS.chart.projects[project.state.conf.el] = project;
+        },
+        pie: function(project) {
+			DHIS.chart.util.chart.pie.series.setTheme(project);
+            project.chart = Ext.create('Ext.chart.Chart', {
+				renderTo: project.state.conf.el,
+                width: project.state.conf.width || this.el.getWidth(),
+                height: project.state.conf.height || this.el.getHeight(),
+                animate: true,
+                shadow: true,
+                store: project.store,
+                insetPadding: 60,
+                items: project.state.conf.hideSubtitle ? false : DHIS.chart.util.chart.pie.getTitle(project.state.filter.names[0], project.store.range[0]),
+                legend: project.state.conf.hideLegend ? false : DHIS.chart.util.chart.def.getLegend(project.state.category.names.length),
+                series: [{
+                    type: 'pie',
+                    field: project.state.series.names[0],
+                    showInLegend: true,
+                    label: {
+                        field: DHIS.chart.conf.finals.data.domain
+                    },
+                    highlight: {
+                        segment: {
+                            margin: 10
+                        }
+                    },
+                    style: {
+                        opacity: 0.9,
+						stroke: '#555'
+                    },
+                    tips: DHIS.chart.util.chart.pie.series.getTips(project)
+                }],
+                theme: project.state.conf.el
+            });
+            
+            DHIS.chart.projects[project.state.conf.el] = project;
+        }
+    };
+    
+    DHIS.chart.exe = {
+        allow: true,
+        queue: [],
+        addToQueue: function(conf) {
+            DHIS.chart.exe.queue.push(conf);
+            if (DHIS.chart.exe.allow) {
+                DHIS.chart.exe.allow = false;
+                DHIS.chart.exe.execute();
+            }
+        },
+        execute: function() {
+            if (this.queue.length) {
+                var conf = this.queue.shift();
+                this.destroy(conf.el);
+                if (conf.uid) {
+                    DHIS.chart.state.setState(conf);
+                }
+                else {
+                    DHIS.chart.state.getState(conf);
+                }
+            }
+            else {
+				DHIS.chart.exe.allow = true;
+			}
+		},
+		destroy: function(el) {
+			if (DHIS.chart.projects[el]) {
+				DHIS.chart.projects[el].chart.destroy();
+			}
+		}
+    };
+    
+    DHIS.chart.initialize();
+});
+
+/* TABLE */
+
+DHIS.table.finals = {
+	dataGet: 'api/reportTables/data.jsonp?minimal=true',
+	data: 'data',
+	periods: 'periods',
+	orgunits: 'orgunits',
+	crosstab: 'crosstab',            
+	orgUnitIsParent: 'orgUnitIsParent',
+	defaultConf: {
+		indicators: [],
+		dataelements: [],
+		datasets: [],
+		periods: ['last12Months'],
+		orgunits: [],
+		crosstab: ['data'],
+		orgUnitIsParent: false,
+		useExtGrid: false,
+		el: '',
+		url: ''
+	}
+};
+
+DHIS.table.tables = []; /* element id -> grid panel */
+
+DHIS.table.utils = {
+    appendUrlIfTrue: function(url, param, expression) {
+    	if (expression && expression == true) {
+    		url = Ext.String.urlAppend(url, param + '=true');
+    	}
+    	return url;            	
+    },
+    destroy: function(el) {
+    	if (DHIS.table.tables[el]) {
+    		DHIS.table.tables[el].destroy();
+    	}
+    },
+    getDataUrl: function(conf) {
+		var url = conf.url + DHIS.table.finals.dataGet;
+		
+		Ext.Array.each(conf.indicators, function(item) {
+			url = Ext.String.urlAppend(url, 'in=' + item);
+		});
+		Ext.Array.each(conf.dataelements, function(item) {
+			url = Ext.String.urlAppend(url, 'de=' + item);
+		});
+		Ext.Array.each(conf.datasets, function(item) {
+			url = Ext.String.urlAppend(url, 'ds=' + item);
+		});
+		Ext.Array.each(conf.periods, function(item) {
+			url = Ext.String.urlAppend(url, item + '=true');
+		});
+		Ext.Array.each(conf.orgunits, function(item) {
+			url = Ext.String.urlAppend(url, 'ou=' + item);
+		});
+		Ext.Array.each(conf.crosstab, function(item) {
+			url = Ext.String.urlAppend(url, 'crosstab=' + item);
+		});
+		url = DHIS.table.utils.appendUrlIfTrue(url, DHIS.table.finals.orgUnitIsParent, conf.orgUnitIsParent);
+		return url;
+	}
+};
+
+DHIS.table.grid = {
+	getHeaderArray: function(data) {
+		var headers = [];
+		Ext.Array.each(data.headers, function(header, index) {
+			headers.push(header.name);
+		});
+		return headers;
+	},
+	getColumnArray: function(data) {
+		var columns = [];
+		Ext.Array.each(data.headers, function(header, index) {
+			columns.push({text: header.name, dataIndex: header.name});
+		});
+		return columns;
+	},
+	getStore: function(data) {
+		var store = Ext.create('Ext.data.ArrayStore', {
+			fields: DHIS.table.grid.getHeaderArray(data),
+			data: data.rows
+		});
+		return store;
+	},
+	render: function(conf) {
+		DHIS.table.utils.destroy(conf.el);
+		Ext.data.JsonP.request({
+			url: DHIS.table.utils.getDataUrl(conf),
+			disableCaching: false,
+			success: function(data) {
+				DHIS.table.tables[conf.el] = Ext.create('Ext.grid.Panel', {
+					store: DHIS.table.grid.getStore(data),
+					columns: DHIS.table.grid.getColumnArray(data),
+					renderTo: conf.el
+				});
+			}
+		});
+	}
+};
+
+DHIS.table.plain = {
+	getMarkup: function(data) {
+		var html = '<table><tr>';
+		var classMap = []; /* Col index -> class markup */
+		
+		Ext.Array.each(data.headers, function(header, index) {
+			var clazz = !header.meta ? ' class=\"val\"' : '';	
+			classMap[index] = clazz;
+			html += '<th' + clazz + '>' + header.name + '<\/th>';	
+		});
+		
+		html += '<\/tr>';
+		
+		Ext.Array.each(data.rows, function(row) {
+			html += '<tr>';
+			Ext.Array.each(row, function(field, index) {
+				var clazz = classMap[index];				
+				html += '<td' + clazz + '>' + field + '<\/td>';
+			});
+			html += '<\/tr>';
+		});
+		
+		html += '<\/table>';
+		return html;
+	},	
+	render: function(conf) {
+		Ext.data.JsonP.request({
+			url: DHIS.table.utils.getDataUrl(conf),
+			disableCaching: false,
+			success: function(data) {
+				var html = DHIS.table.plain.getMarkup(data);
+				Ext.get(conf.el).update(html);
+			}
+		});
+	}
+};
+
+DHIS.table.impl = {
+	render: function(conf) {
+		conf = Ext.applyIf(conf, DHIS.table.finals.defaultConf);
+		if ( conf.useExtGrid ) {
+			DHIS.table.grid.render(conf);
+		}
+		else {
+			DHIS.table.plain.render(conf);
+		}
+	}
+}
+
+DHIS.getTable = DHIS.table.impl.render;

=== removed file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/table.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/table.js	2012-05-15 21:24:12 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/plugin/table.js	1970-01-01 00:00:00 +0000
@@ -1,151 +0,0 @@
-DHIS.table = {};
-
-DHIS.table.finals = {
-	dataGet: 'api/reportTables/data.jsonp?minimal=true',
-	data: 'data',
-	periods: 'periods',
-	orgunits: 'orgunits',
-	crosstab: 'crosstab',            
-	orgUnitIsParent: 'orgUnitIsParent',
-	defaultConf: {
-		indicators: [],
-		dataelements: [],
-		datasets: [],
-		periods: ['last12Months'],
-		orgunits: [],
-		crosstab: ['data'],
-		orgUnitIsParent: false,
-		useExtGrid: false,
-		el: '',
-		url: ''
-	}
-};
-
-DHIS.table.tables = []; // element id -> grid panel
-
-DHIS.table.utils = {
-    appendUrlIfTrue: function(url, param, expression) {
-    	if (expression && expression == true) {
-    		url = Ext.String.urlAppend(url, param + '=true');
-    	}
-    	return url;            	
-    },
-    destroy: function(el) {
-    	if (DHIS.table.tables[el]) {
-    		DHIS.table.tables[el].destroy();
-    	}
-    },
-    getDataUrl: function(conf) {
-		var url = conf.url + DHIS.table.finals.dataGet;
-		
-		Ext.Array.each(conf.indicators, function(item) {
-			url = Ext.String.urlAppend(url, 'in=' + item);
-		});
-		Ext.Array.each(conf.dataelements, function(item) {
-			url = Ext.String.urlAppend(url, 'de=' + item);
-		});
-		Ext.Array.each(conf.datasets, function(item) {
-			url = Ext.String.urlAppend(url, 'ds=' + item);
-		});
-		Ext.Array.each(conf.periods, function(item) {
-			url = Ext.String.urlAppend(url, item + '=true');
-		});
-		Ext.Array.each(conf.orgunits, function(item) {
-			url = Ext.String.urlAppend(url, 'ou=' + item);
-		});
-		Ext.Array.each(conf.crosstab, function(item) {
-			url = Ext.String.urlAppend(url, 'crosstab=' + item);
-		});
-		url = DHIS.table.utils.appendUrlIfTrue(url, DHIS.table.finals.orgUnitIsParent, conf.orgUnitIsParent);
-		return url;
-	}
-};
-
-DHIS.table.grid = {
-	getHeaderArray: function(data) {
-		var headers = [];
-		Ext.Array.each(data.headers, function(header, index) {
-			headers.push(header.name);
-		});
-		return headers;
-	},
-	getColumnArray: function(data) {
-		var columns = [];
-		Ext.Array.each(data.headers, function(header, index) {
-			columns.push({text: header.name, dataIndex: header.name});
-		});
-		return columns;
-	},
-	getStore: function(data) {
-		var store = Ext.create('Ext.data.ArrayStore', {
-			fields: DHIS.table.grid.getHeaderArray(data),
-			data: data.rows
-		});
-		return store;
-	},
-	render: function(conf) {
-		DHIS.table.utils.destroy(conf.el);
-		Ext.data.JsonP.request({
-			url: DHIS.table.utils.getDataUrl(conf),
-			disableCaching: false,
-			success: function(data) {
-				DHIS.table.tables[conf.el] = Ext.create('Ext.grid.Panel', {
-					store: DHIS.table.grid.getStore(data),
-					columns: DHIS.table.grid.getColumnArray(data),
-					renderTo: conf.el
-				});
-			}
-		});
-	}
-};
-
-DHIS.table.plain = {
-	getMarkup: function(data) {
-		var html = '<table><tr>';
-		var classMap = []; // Col index -> class markup
-		
-		Ext.Array.each(data.headers, function(header, index) {
-			var clazz = !header.meta ? ' class=\"val\"' : '';	
-			classMap[index] = clazz;
-			html += '<th' + clazz + '>' + header.name + '<\/th>';	
-		});
-		
-		html += '<\/tr>';
-		
-		Ext.Array.each(data.rows, function(row) {
-			html += '<tr>';
-			Ext.Array.each(row, function(field, index) {
-				var clazz = classMap[index];				
-				html += '<td' + clazz + '>' + field + '<\/td>';
-			});
-			html += '<\/tr>';
-		});
-		
-		html += '<\/table>';
-		return html;
-	},	
-	render: function(conf) {
-		Ext.data.JsonP.request({
-			url: DHIS.table.utils.getDataUrl(conf),
-			disableCaching: false,
-			success: function(data) {
-				var html = DHIS.table.plain.getMarkup(data);
-				Ext.get(conf.el).update(html);
-			}
-		});
-	}
-};
-
-DHIS.table.impl = {
-	render: function(conf) {
-		conf = Ext.applyIf(conf, DHIS.table.finals.defaultConf);
-		if ( conf.useExtGrid ) {
-			DHIS.table.grid.render(conf);
-		}
-		else {
-			DHIS.table.plain.render(conf);
-		}
-	}
-}
-
-DHIS.getTable = DHIS.table.impl.render;

=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/app.js'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/app.js	2012-05-14 08:14:47 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/app.js	2012-05-15 22:32:35 +0000
@@ -246,7 +246,6 @@
 Ext.require('Ext.ux.form.MultiSelect');
 
 Ext.onReady( function() {
-    Ext.override(Ext.form.FieldSet,{setExpanded:function(a){var b=this,c=b.checkboxCmp,d=b.toggleCmp,e;a=!!a;if(c){c.setValue(a)}if(d){d.setType(a?"up":"down")}if(a){e="expand";b.removeCls(b.baseCls+"-collapsed")}else{e="collapse";b.addCls(b.baseCls+"-collapsed")}b.collapsed=!a;b.doComponentLayout();b.fireEvent(e,b);return b}});
     Ext.QuickTips.init();
     document.body.oncontextmenu = function(){return false;}; 
     
@@ -254,7 +253,7 @@
         url: DV.conf.finals.ajax.path_visualizer + DV.conf.finals.ajax.initialize,
         success: function(r) {
             
-    DV.init = DV.conf.init.ajax.jsonfy(r);    
+    DV.init = DV.conf.init.ajax.jsonfy(r);
     DV.init.initialize = function() {
 		DV.c = DV.chart.model;
         DV.util.combobox.filter.category();
@@ -1052,7 +1051,10 @@
 						}
 						if (DV.c.targetlinevalue) {
 							colors.push('#051a2e');
-						}						
+						}
+						if (DV.c.baselinevalue) {
+							colors.push('#051a2e');
+						}
 						Ext.chart.theme.dv1 = Ext.extend(Ext.chart.theme.Base, {
 							constructor: function(config) {
 								Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
@@ -1200,7 +1202,7 @@
             },
             allValuesAreIntegers: function(values) {
                 for (var i = 0; i < values.length; i++) {
-                    if (!this.isInteger(values[i].v)) {
+                    if (!this.isInteger(values[i].value)) {
                         return false;
                     }
                 }
@@ -1511,7 +1513,7 @@
     };
     
     DV.state = {
-        setChart: function(exe, id) {
+		setChart: function(exe, id) {
 			DV.chart.reset();
 			
 			if (id) {
@@ -1576,7 +1578,7 @@
                         DV.c.baselinelabel = f.baseLineLabel ? f.baseLineLabel : null;
                         
                         if (exe) {
-							this.expandChart(exe, id);
+							this.extendChart(exe, id);
 						}
 					}
 				});
@@ -1595,11 +1597,11 @@
 				this.setOptions();
                         
 				if (exe) {
-					this.expandChart(exe);
+					this.extendChart(exe);
 				}
 			}
 		},
-		expandChart: function(exe, id) {
+		extendChart: function(exe, id) {
 			DV.chart.warnings = [];
 			
 			if (!this.validation.dimensions()) {
@@ -1674,7 +1676,7 @@
             DV.c.baselinevalue = parseFloat(DV.cmp.favorite.baselinevalue.getValue());
             DV.c.baselinelabel = DV.cmp.favorite.baselinelabel.getValue();
 		},
-        getParams: function() {
+		getParams: function() {
             var p = {};
             p.type = DV.c.type.toUpperCase();
             p.series = DV.c.dimension.series.toUpperCase();
@@ -1778,7 +1780,7 @@
 				DV.cmp.dimension.organisationunit.panel.groupsets.setValue(DV.store.isloaded ? DV.conf.finals.cmd.none : DV.i18n.none);
 			}
 		},
-        validation: {
+		validation: {
 			dimensions: function() {
 				if (!DV.c.dimension.series || !DV.c.dimension.category || !DV.c.dimension.filter) {
 					DV.util.notification.error(DV.i18n.et_invalid_dimension_setup, DV.i18n.em_invalid_dimension_setup);
@@ -1922,7 +1924,7 @@
 				return true;
 			}
 		}
-    };
+	};
     
     DV.value = {
         values: [],

=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/index.html'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/index.html	2012-05-15 20:21:11 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/index.html	2012-05-15 22:32:35 +0000
@@ -1,20 +1,19 @@
 <html>
 <head>
     <link rel="stylesheet" type="text/css" href="../../../dhis-web-commons/javascripts/ext/resources/css/ext-all-gray.css" />
+    <link rel="stylesheet" type="text/css" href="../../../dhis-web-commons/javascripts/plugin/css/plugin.css" />
+    
     <script type="text/javascript" src="../../../dhis-web-commons/javascripts/ext/ext-all.js"></script>
-    <script type="text/javascript" src="../../../dhis-web-commons/javascripts/plugin/chart.js"></script>
-    <script type="text/javascript" src="../../../dhis-web-commons/javascripts/plugin/table.js"></script>
+    <script type="text/javascript" src="../../../dhis-web-commons/javascripts/plugin/plugin.js"></script>
     
     <style type="text/css">
 		body {font-family: sans-serif; margin: 0 0 0 60px;}
 		
 		h1 {font-size: 20px; margin: 20px 0;}
 		
-		#chart1 {width: 900px; height: 400px; border: 2px solid #d1d1d1; margin-bottom: 100px; border-radius: 3px;}
-
-		#chart2 {width: 1000px; height: 400px; border: 2px solid #d1d1d1; margin-bottom: 100px;  border-radius: 3px;}
+		#chart1, #chart2, #table1, #table2 {width: 1000px; margin-bottom: 50px;}
 		
-		#table1, #table2 {width: 1000px;}
+		#chart1, #chart2 {height: 400px; border: 2px solid #d1d1d1; border-radius: 3px;}
 		
 		table {border-collapse: collapse;}
 		
@@ -35,12 +34,20 @@
 			
 			DHIS.getChart({
 				type: 'stackedcolumn',
-				indicators: ['Uvn6LCg7dVU', 'OdiHJayrsKo'],
-				periods: 'thisYear',
-				category: 'organisationunit',
-				filter: 'period',
+				indicators: ['Uvn6LCg7dVU'],
+				periods: 'last12Months',
+				category: 'period',
+				filter: 'organisationunit',
 				organisationunits: ['ImspTQPwCqd'],
-				orgUnitIsParent: true,
+				orgUnitIsParent: false,
+				showData: true,
+				trendLine: true,
+				hideLegend: false,
+				hideSubtitle: false,
+				targetLineValue: 80,
+				targetLineLabel: null,				
+				baseLineValue: 20,
+				baseLineLabel: null,	
 				el: 'chart2',
 				url: url
 			});
@@ -79,21 +86,30 @@
 	dataelements        [integer]                           (Required*) Data element uids. Required if no indicators are provided.
 	periods             [string]        'last12Months'      (Optional) Relative period names.
 	organisationunits   [integer]                           (Required) Organisation unit uids.
-	series              string          'data'              (Optional) Series: 'data', 'period' or 'organisationunit'
-	category            string          'period'            (Optional) Category: 'indicator', 'dataelement', 'period' or 'organisationunit'
-	filter              string          'organisationunit'  (Optional) Filter: 'indicator', 'dataelement', 'period' or 'organisationunit'
+	series              string          'data'              (Optional) Series: 'data', 'period' or 'organisationunit'.
+	category            string          'period'            (Optional) Category: 'indicator', 'dataelement', 'period' or 'organisationunit'.
+	filter              string          'organisationunit'  (Optional) Filter: 'indicator', 'dataelement', 'period' or 'organisationunit'.
+	orgUnitIsParent		boolean			false				(Optional) If true, the children of the provided orgunit are displayed.
+	showData			boolean			false				(Optional) If true, the exact data are displayed on the chart.
+	trendLine			boolean			false				(Optional) If true, trend line(s) are added.
+	hideLegend			boolean			false				(Optional) If true, the legend is not visible.
+	hideSubtitle		boolean			false				(Optional) If true, the subtitle is not visible.
+	targetLineValue		integer								(Optional) The value of the target line.
+	targetLineLabel		string								(Optional) The legend name of the target line. Requires targetLineValue, otherwise ignored.
+	baseLineValue		integer								(Optional) The value of the base line.
+	baseLineLabel		string								(Optional) The legend name of the base line. Requires baseLineValue, otherwise ignored.
+	legendPosition      string          'top'               (Optional) Positions: 'top', 'right', 'bottom' or 'left'.
 	el                  string                              (Required) The element id to render the chart.
 	width               integer         <el width>          (Optional) Chart width. Default is the element width.
 	height              integer         <el height>         (Optional) Chart height. Default is the element height.
-	legendPosition      string          'top'               (Optional) Positions: 'top', 'right', 'bottom' or 'left'
 	url                 string                              (Required) The base url of the DHIS instance.
 	-->
 </head>
 
 <body>
-	<h1>My chart 1</h1>
+    <h1>My chart 1</h1>
 	<div id="chart1"></div>
-    
+	
     <h1>My chart 2</h1>
 	<div id="chart2"></div>
 	

=== added file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/plugin.css'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/plugin.css	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/plugin.css	2012-05-15 21:40:46 +0000
@@ -0,0 +1,31 @@
+.x-border-box,.x-border-box *{box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-webkit-box-sizing:border-box}
+.x-unselectable,.x-surface tspan{user-select:none;-o-user-select:none;-ms-user-select:none;-moz-user-select:0;-webkit-user-select:none;cursor:default}
+.x-css-shadow{position:absolute;-moz-border-radius:5px;-webkit-border-radius:5px 5px;-o-border-radius:5px 5px;-ms-border-radius:5px 5px;-khtml-border-radius:5px 5px;border-radius:5px 5px}
+.x-tip{position:absolute;overflow:visible;-moz-border-radius:3px;-webkit-border-radius:3px;-o-border-radius:3px;-ms-border-radius:3px;-khtml-border-radius:3px;border-radius:3px;background-color:#ccc;border-color:#868686;border-style:solid;border-width:1px;padding:2px}
+.x-hide-visibility,.x-ie6 .x-masked select,.x-ie6.x-body-masked select{visibility:hidden!important}
+.x-layer{position:absolute;overflow:hidden;zoom:1}
+.x-tip-anchor{position:absolute;overflow:hidden;height:0;width:0;zoom:1;border-color:#868686;border-style:solid;border-width:5px}
+.x-border-box .x-tip-anchor{width:10px;height:10px}
+.x-tip-header,.x-tip-body,.x-form-invalid-tip-body{color:#444;font-size:11px;font-weight:400}
+.x-tip-anchor-top{border-top-color:transparent;border-left-color:transparent;border-right-color:transparent;_border-top-color:#FFC0CB;_border-left-color:#FFC0CB;_border-right-color:#FFC0CB;_filter:chroma(color=pink)}
+.x-tip-body,.x-form-invalid-tip-body{overflow:hidden;position:relative;padding:3px}
+.x-item-disabled,.x-item-disabled *,.x-tab-default-disabled *,.x-splitter-collapsed{cursor:default}
+.x-html:before,.x-html:after{white-space:pre-line}
+.x-btn *,.x-trigger-noedit,.x-tab *{cursor:hand}
+.x-surface{-moz-box-orient:vertical;vertical-align:auto;display:inline}
+.x-item-disabled,.x-splitter-active .x-collapse-el{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=30);opacity:.3}
+.x-masked-relative,.x-btn button,.x-btn a,.x-opera .x-menu-item-link,.x-window .x-window-wrap,.x-tab button,.x-tab a,.x-fit-item{position:relative}
+.x-inline-children > *{display:inline-block!important}
+.x-btn-split,.x-column-header-over .x-column-header-trigger,.x-column-header-open .x-column-header-trigger,.x-html html,.x-html address,.x-html blockquote,.x-html body,.x-html dd,.x-html div,.x-html dl,.x-html dt,.x-html fieldset,.x-html form,.x-html frame,.x-html frameset,.x-html h1,.x-html h2,.x-html h3,.x-html h4,.x-html h5,.x-html h6,.x-html noframes,.x-html ol,.x-html p,.x-html ul,.x-html center,.x-html dir,.x-html hr,.x-html menu,.x-html pre{display:block}
+.x-frame-shadow *{overflow:hidden;border:0;clear:none;zoom:1;margin:0;padding:0}
+.x-mask{z-index:100;position:absolute;top:0;left:0;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=50);opacity:.5;width:100%;height:100%;zoom:1;background:#ccc}
+.x-ie6 .x-item-disabled,.x-ie6 .x-btn-disabled span,.x-ie7 .x-btn-disabled span,.x-ie7 .x-btn-disabled,.x-ie8 .x-btn-disabled{filter:none}
+.x-color-picker em span{cursor:pointer;display:block;height:10px;width:10px;line-height:10px}
+.x-ie .x-fieldset-noborder legend span{position:absolute;left:16px}
+.x-grid-tree-loading span{font-style:italic;color:#444}
+table.x-datepicker-inner .x-datepicker-selected span{font-weight:700}
+.x-btn-disabled span,.x-menu-item-disabled,.x-ie .x-menu-item-disabled .x-menu-item-icon{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=50);opacity:.5}
+table.x-datepicker-inner th span{display:block;padding-right:7px}
+.dv-chart-tips, .dv-chart-tips-pie {border-width:2px;background-color:#eee;padding:2px 4px 0;}
+.dv-chart-tips .x-tip-body {font-size:22px;font-family:arial,sans-serif,ubuntu,consolas}
+.dv-chart-tips-pie .x-tip-body {font-size:17px;font-family:arial,sans-serif,ubuntu,consolas}

=== added file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/plugin.js'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/plugin.js	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/plugin/plugin.js	2012-05-15 22:43:36 +0000
@@ -0,0 +1,1228 @@
+DHIS = {
+	chart: {},
+	table: {}
+};
+
+/* CHART */
+
+DHIS.chart.conf = {
+    finals: {
+        ajax: {
+            data_get: 'api/chartValues.jsonp',
+            favorite_get: 'api/charts/'
+        },        
+        dimension: {
+            data: {
+                value: 'data',
+                rawvalue: 'Data'
+            },
+            indicator: {
+                value: 'indicator',
+                rawvalue: 'Indicator'
+            },
+            dataelement: {
+                value: 'dataelement',
+                rawvalue: 'Data element'
+            },
+            period: {
+                value: 'period',
+                rawvalue: 'Period'
+            },
+            organisationunit: {
+                value: 'organisationunit',
+                rawvalue: 'Organisation unit'
+            }
+        },
+        chart: {
+            x: 'x',
+            series: 'series',
+            category: 'category',
+            filter: 'filter',
+            column: 'column',
+            stackedcolumn: 'stackedcolumn',
+            bar: 'bar',
+            stackedbar: 'stackedbar',
+            line: 'line',
+            area: 'area',
+            pie: 'pie',
+            orgUnitIsParent: 'orgUnitIsParent'
+        },
+        data: {
+			domain: 'domain_',
+			targetline: 'targetline_',
+			baseline: 'baseline_',
+			trendline: 'trendline_'
+		},
+    },
+    chart: {
+        style: {
+            inset: 30,
+            font: 'arial,sans-serif,ubuntu,consolas'
+        },
+        theme: {
+            dv1: ['#94ae0a', '#0b3b68', '#a61120', '#ff8809', '#7c7474', '#a61187', '#ffd13e', '#24ad9a', '#a66111', '#414141', '#4500c4', '#1d5700']
+        }
+    }
+};
+
+Ext.onReady( function() {
+	
+    DHIS.chart.initialize = function() {
+        DHIS.chart.store.column = DHIS.chart.store.defaultChartStore;
+        DHIS.chart.store.stackedcolumn = DHIS.chart.store.defaultChartStore;
+        DHIS.chart.store.stackedbar = DHIS.chart.store.bar;
+        DHIS.chart.store.line = DHIS.chart.store.defaultChartStore;
+        DHIS.chart.store.area = DHIS.chart.store.defaultChartStore;
+        DHIS.chart.store.pie = DHIS.chart.store.defaultChartStore;
+        
+        DHIS.getChart = DHIS.chart.exe.addToQueue;
+        DHIS.destroyChart = DHIS.chart.exe.destroy;
+    };
+    
+    DHIS.chart.projects = {};
+    
+    DHIS.chart.plugin = {
+		SimpleRegression: function SimpleRegression() {
+			var sumX = 0;
+			var sumY = 0;
+			var sumXX = 0;
+			var sumXY = 0;
+			var n = 0;
+			var xbar = 0;
+			var ybar = 0;
+			
+			this.addData = function(x, y) {
+				if ( n == 0 ) {
+					xbar = x;
+					ybar = y;
+				}
+				else {
+					var dx = x - xbar;
+					var dy = y - ybar;
+					sumXX += dx * dx * n / ( n + 1 );
+					sumXY += dx * dy * n / ( n + 1 );
+					xbar += dx / ( n + 1 );
+					ybar += dy / ( n + 1 );
+				}
+				
+				sumX += x;
+				sumY += y;
+				n++;
+			};
+			
+			this.predict = function( x ) {
+				var b1 = this.getSlope();				
+				return this.getIntercept( b1 ) + b1 * x;
+			};
+			
+			this.getSlope = function() {
+				if ( n < 2 ) {
+					return Number.NaN;
+				}				
+				return sumXY / sumXX;
+			};
+			
+			this.getIntercept = function( slope ) {
+				return ( sumY - slope * sumX ) / n;
+			};
+		}
+	};
+    
+    DHIS.chart.util = {
+        dimension: {
+            indicator: {
+                getIdsFromObjects: function(indicators) {
+                    var a = []
+                    for (var i = 0; i < indicators.length; i++) {
+                        a.push(indicators[i].id);
+                    }
+                    return a;
+                }
+            },
+            dataelement: {
+                getIdsFromObjects: function(dataelements) {
+                    var a = []
+                    for (var i = 0; i < dataelements.length; i++) {
+                        a.push(dataelements[i].id);
+                    }
+                    return a;
+                }
+            },
+            data: {
+                getUrl: function(isFilter) {
+                    var a = [];
+                    Ext.Array.each(DHIS.chart.state.state.conf.indicators, function(r) {
+                        a.push('indicatorIds=' + r);
+                    });
+                    Ext.Array.each(DHIS.chart.state.state.conf.dataelements, function(r) {
+                        a.push('dataElementIds=' + r);
+                    });
+                    return (isFilter && a.length > 1) ? a.slice(0,1) : a;
+                }
+            },
+            period: {
+                getUrl: function(isFilter) {
+                    var a = [];
+                    Ext.Array.each(DHIS.chart.state.state.conf.periods, function(r) {
+						a.push(r + '=true')
+                    });
+                    return (isFilter && a.length > 1) ? a.slice(0,1) : a;
+                },
+                getRelativesFromObject: function(obj) {
+                    var a = [];
+                    for (var k in obj) {
+                        if (obj[k]) {
+                            a.push(k);
+                        }
+                    }
+                    return a;
+                }
+            },
+            organisationunit: {
+                getUrl: function(isFilter) {
+                    var a = [];
+                    Ext.Array.each(DHIS.chart.state.state.conf.organisationunits, function(r) {
+						a.push('organisationUnitIds=' + r)
+                    });
+                    return (isFilter && a.length > 1) ? a.slice(0,1) : a;
+                },
+                getIdsFromObjects: function(organisationunits) {
+                    var a = []
+                    for (var i = 0; i < organisationunits.length; i++) {
+                        a.push(organisationunits[i].id);
+                    }
+                    return a;
+                }
+            }
+        },
+        chart: {
+			def: {
+				getChart: function(project, axes, series, elWidth, elHeight) {
+					return Ext.create('Ext.chart.Chart', {
+						renderTo: project.state.conf.el,
+						animate: true,
+						store: project.store,
+						insetPadding: DHIS.chart.conf.chart.style.inset,						
+						items: project.state.conf.hideSubtitle ? false : DHIS.chart.util.chart.def.getTitle(project),
+						legend: project.state.conf.hideLegend ? false : DHIS.chart.util.chart.def.getLegend(project.store.range.length),
+						width: project.state.conf.width || elWidth,
+						height: project.state.conf.height || elHeight,
+						axes: axes,
+						series: series,
+						theme: project.state.conf.el
+					});
+				},
+				getLegend: function(len) {
+					len = len ? len : 1;
+					return {
+						position: len > 5 ? 'right' : 'top',
+						labelFont: '11px ' + DHIS.chart.conf.chart.style.font,
+						boxStroke: '#ffffff',
+						boxStrokeWidth: 0,
+						padding: 0
+					};
+				},
+				getTitle: function(project) {
+					return {
+						type: 'text',
+						text: project.state.filter.names[0],
+						font: 'bold 13px ' + DHIS.chart.conf.chart.style.font,
+						fill: '#222',
+						width: 300,
+						height: 20,
+						x: 28,
+						y: 16
+					};
+				},
+				getGrid: function() {
+					return {
+						opacity: 1,
+						fill: '#f1f1f1',
+						stroke: '#aaa',
+						'stroke-width': 0.2
+					};
+				},
+				setMask: function(str) {
+					if (DHIS.chart.mask) {
+						DHIS.chart.mask.hide();
+					}
+					DHIS.chart.mask = new Ext.LoadMask(DHIS.chart.chart.chart, {msg: str});
+					DHIS.chart.mask.show();
+				},
+				label: {
+					getCategory: function() {
+						return {
+							font: '11px ' + DHIS.chart.conf.chart.style.font,
+							rotate: {
+								degrees: 320
+							}
+						};
+					},
+					getNumeric: function(values) {
+						return {
+							font: '11px ' + DHIS.chart.conf.chart.style.font,
+							renderer: Ext.util.Format.numberRenderer(DHIS.chart.util.number.getChartAxisFormatRenderer(values))
+						};
+					}
+				},
+				axis: {
+					getNumeric: function(project, isStacked) {
+						return {
+							type: 'Numeric',
+							position: 'left',
+							title: project.state.conf.rangeAxisLabel || false,
+							labelTitle: {
+								font: '17px ' + DHIS.chart.conf.chart.style.font
+							},
+							minimum: 0,
+							fields: isStacked ? project.state.series.names : project.store.range,
+							label: DHIS.chart.util.chart.def.label.getNumeric(project.values),
+							grid: {
+								odd: {
+									opacity: 1,
+									fill: '#fefefe',
+									stroke: '#aaa',
+									'stroke-width': 0.1
+								},									
+								even: {
+									opacity: 1,
+									fill: '#f1f1f1',
+									stroke: '#aaa',
+									'stroke-width': 0.1
+								}
+							}
+						};
+					},
+					getCategory: function(project) {
+						return {
+							type: 'Category',
+							position: 'bottom',
+							title: project.state.conf.domainAxisLabel || false,
+							labelTitle: {
+								font: '17px ' + DHIS.chart.conf.chart.style.font
+							},
+							fields: DHIS.chart.conf.finals.data.domain,
+							label: DHIS.chart.util.chart.def.label.getCategory()
+						};
+					}
+				},
+				series: {
+					getTips: function() {
+						return {
+							trackMouse: true,
+							cls: 'dv-chart-tips',
+							renderer: function(r, item) {
+								this.update('' + item.value[1]);
+							}
+						};
+					},
+					getTargetLine: function(project) {
+						var title = project.state.conf.targetLineLabel || 'Target';
+						title += ' (' + project.state.conf.targetLineValue + ')';
+						return {
+							type: 'line',
+							axis: 'left',
+							xField: DHIS.chart.conf.finals.data.domain,
+							yField: DHIS.chart.conf.finals.data.targetline,
+							style: {
+								opacity: 1,
+								lineWidth: 3,
+								stroke: '#041423'
+							},
+							markerConfig: {
+								type: 'circle',
+								radius: 0
+							},
+							title: title
+						};
+					},
+					getBaseLine: function(project) {
+						var title = project.state.conf.baseLineLabel || 'Base';
+						title += ' (' + project.state.conf.baseLineValue + ')';
+						return {
+							type: 'line',
+							axis: 'left',
+							xField: DHIS.chart.conf.finals.data.domain,
+							yField: DHIS.chart.conf.finals.data.baseline,
+							style: {
+								opacity: 1,
+								lineWidth: 3,
+								stroke: '#041423'
+							},
+							markerConfig: {
+								type: 'circle',
+								radius: 0
+							},
+							title: title
+						};
+					},
+					getTrendLineArray: function(project) {						
+						var a = [];
+						for (var i = 0; i < project.trendline.length; i++) {
+							a.push({
+								type: 'line',
+								axis: 'left',
+								xField: DHIS.chart.conf.finals.data.domain,
+								yField: project.trendline[i].key,
+								style: {
+									opacity: 0.8,
+									lineWidth: 3
+								},
+								markerConfig: {
+									type: 'circle',
+									radius: 4
+								},
+								tips: DHIS.chart.util.chart.def.series.getTips(),
+								title: project.trendline[i].name
+							});
+						}
+						return a;
+					},
+					setTheme: function(project) {
+						var colors = DHIS.chart.conf.chart.theme.dv1.slice(0, project.state.series.names.length);
+						if (project.state.conf.targetLineValue || project.state.conf.baseLineValue) {
+							colors.push('#051a2e');
+						}					
+						if (project.state.conf.targetLineValue) {
+							colors.push('#051a2e');
+						}					
+						if (project.state.conf.baseLineValue) {
+							colors.push('#051a2e');
+						}
+						Ext.chart.theme[project.state.conf.el] = Ext.extend(Ext.chart.theme.Base, {
+							constructor: function(config) {
+								Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
+									seriesThemes: colors,
+									colors: colors
+								}, config));
+							}
+						});
+					}
+				}
+			},
+            bar: {
+				label: {
+					getCategory: function() {
+						return {
+							font: '11px ' + DHIS.chart.conf.chart.style.font
+						};
+					}
+				},
+				axis: {
+					getNumeric: function(project) {
+						var num = DHIS.chart.util.chart.def.axis.getNumeric(project);
+						num.position = 'bottom';
+						return num;
+					},
+					getCategory: function(project) {
+						var cat = DHIS.chart.util.chart.def.axis.getCategory(project);
+						cat.position = 'left';
+						cat.label = DHIS.chart.util.chart.bar.label.getCategory();
+						return cat;
+					}
+				},
+                series: {
+					getTips: function() {
+						return {
+							trackMouse: true,
+							cls: 'dv-chart-tips',
+							renderer: function(si, item) {
+								this.update('' + item.value[0]);
+							}
+						};
+					},
+					getTargetLine: function(project) {
+						var line = DHIS.chart.util.chart.def.series.getTargetLine(project);
+						line.axis = 'bottom';
+						line.xField = DHIS.chart.conf.finals.data.targetline;
+						line.yField = DHIS.chart.conf.finals.data.domain;
+						return line;
+					},
+					getBaseLine: function(project) {
+						var line = DHIS.chart.util.chart.def.series.getBaseLine(project);
+						line.axis = 'bottom';
+						line.xField = DHIS.chart.conf.finals.data.baseline;
+						line.yField = DHIS.chart.conf.finals.data.domain;
+						return line;
+					},
+					getTrendLineArray: function(project) {
+						var a = [];
+						for (var i = 0; i < project.trendline.length; i++) {
+							a.push({
+								type: 'line',
+								axis: 'bottom',
+								xField: project.trendline[i].key,
+								yField: DHIS.chart.conf.finals.data.domain,
+								style: {
+									opacity: 0.8,
+									lineWidth: 3
+								},
+								markerConfig: {
+									type: 'circle',
+									radius: 4
+								},
+								tips: DHIS.chart.util.chart.bar.series.getTips(),
+								title: project.trendline[i].name
+							});
+						}
+						return a;
+					}
+				}
+            },
+            line: {
+				series: {
+					getArray: function(project) {
+						var a = [];
+						for (var i = 0; i < project.state.series.names.length; i++) {
+							a.push({
+								type: 'line',
+								axis: 'left',
+								xField: DHIS.chart.conf.finals.data.domain,
+								yField: project.state.series.names[i],
+								style: {
+									opacity: 0.8,
+									lineWidth: 3
+								},
+								markerConfig: {
+									type: 'circle',
+									radius: 4
+								},
+								tips: DHIS.chart.util.chart.def.series.getTips()
+							});
+						}
+						return a;
+					},
+					setTheme: function(project) {
+						var colors = DHIS.chart.conf.chart.theme.dv1.slice(0, project.state.series.names.length);
+						if (project.state.conf.trendLine) {
+							colors = colors.concat(colors);
+						}
+						if (project.state.conf.targetLineValue) {
+							colors.push('#051a2e');
+						}
+						if (project.state.conf.baseLineValue) {
+							colors.push('#051a2e');
+						}
+						Ext.chart.theme[project.state.conf.el] = Ext.extend(Ext.chart.theme.Base, {
+							constructor: function(config) {
+								Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
+									seriesThemes: colors,
+									colors: colors
+								}, config));
+							}
+						});
+					}
+                }
+            },
+            pie: {
+                getTitle: function(title, subtitle) {
+                    return [
+                        {
+                            type: 'text',
+                            text: title,
+                            font: 'bold 13px arial',
+                            fill: '#222',
+                            width: 300,
+                            height: 20,
+                            x: 28,
+                            y: 16
+                        },
+                        {
+                            type: 'text',
+                            text: subtitle,
+                            font: 'bold 11px arial',
+                            fill: '#777',
+                            width: 300,
+                            height: 20,
+                            x: 28,
+                            y: 36
+                        }
+                    ];                        
+                },
+                series: {
+					getTips: function(project) {
+						return {
+							trackMouse: true,
+							cls: 'dv-chart-tips-pie',
+							renderer: function(item) {
+								this.update(item.data[DHIS.chart.conf.finals.data.domain] + '<br/><b>' + item.data[project.state.series.names[0]] + '</b>');
+							}
+						};
+					},
+					setTheme: function(project) {
+						var colors = DHIS.chart.conf.chart.theme.dv1.slice(0, project.state.category.names.length);
+						Ext.chart.theme[project.state.conf.el] = Ext.extend(Ext.chart.theme.Base, {
+							constructor: function(config) {
+								Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
+									seriesThemes: colors,
+									colors: colors
+								}, config));
+							}
+						});
+					}
+				}
+            }
+        },
+        number: {
+            isInteger: function(n) {
+                var str = new String(n);
+                if (str.indexOf('.') > -1) {
+                    var d = str.substr(str.indexOf('.') + 1);
+                    return (d.length === 1 && d == '0');
+                }
+                return false;
+            },
+            allValuesAreIntegers: function(values) {
+                for (var i = 0; i < values.length; i++) {
+                    if (!this.isInteger(values[i].v)) {
+                        return false;
+                    }
+                }
+                return true;
+            },
+            getChartAxisFormatRenderer: function(values) {
+                return this.allValuesAreIntegers(values) ? '0' : '0.0';
+            }
+        },
+        string: {
+            getEncodedString: function(text) {
+                return text.replace(/[^a-zA-Z 0-9(){}<>_!+;:?*&%#-]+/g,'');
+            },
+            extendUrl: function(url) {
+                if (url.charAt(url.length-1) !== '/') {
+                    url += '/';
+                }
+                return url;
+            },
+            appendUrlIfTrue: function(url, param, expression) {
+            	if (expression && expression == true) {
+            		url = Ext.String.urlAppend(url, param + '=true');
+            	}
+            	return url;            	
+            }
+        },
+        value: {
+            jsonfy: function(r) {                
+                var object = {
+                    values: [],
+                    periods: r.p,
+                    datanames: [],
+                    organisationunitnames: []
+                };
+                for (var i = 0; i < r.v.length; i++) {
+                    var obj = {};
+                    obj.v = r.v[i][0];
+                    obj[DHIS.chart.conf.finals.dimension.data.value] = r.v[i][1];
+                    obj[DHIS.chart.conf.finals.dimension.period.value] = r.v[i][2];
+                    obj[DHIS.chart.conf.finals.dimension.organisationunit.value] = r.v[i][3];
+                    object.values.push(obj);
+                }
+                for (var j = 0; j < r.d.length; j++) {
+					object.datanames.push(DHIS.chart.util.string.getEncodedString(r.d[j]));
+				}
+                for (var k = 0; k < r.o.length; k++) {
+					object.organisationunitnames.push(DHIS.chart.util.string.getEncodedString(r.o[k]));
+				}
+                return object;
+            }
+        }
+    };
+    
+    DHIS.chart.store = {
+        getChartStore: function(project) {
+            var keys = [];            
+            Ext.Array.each(project.data, function(item) {
+                keys = Ext.Array.merge(keys, Ext.Object.getKeys(item));
+            });            
+            project.store = Ext.create('Ext.data.Store', {
+                fields: keys,
+                data: project.data
+            });
+            project.store.range = keys.slice(0);
+            for (var i = 0; i < project.store.range.length; i++) {
+                if (project.store.range[i] === DHIS.chart.conf.finals.data.domain) {
+                    project.store.range.splice(i, 1);
+                }
+            }
+            
+			DHIS.chart.chart.getChart(project);
+        }
+    };
+    
+    DHIS.chart.state = {
+        state: null,
+        getState: function(conf) {
+            var project = {
+                state: {
+                    conf: null,
+                    type: null,
+                    series: {
+                        dimension: null,
+                        names: []
+                    },
+                    category: {
+                        dimension: null,
+                        names: []
+                    },
+                    filter: {
+                        dimension: null,
+                        names: []
+                    }
+                }
+            };
+            
+            var defaultConf = {
+                type: 'column',
+                stacked: false,
+                indicators: [],
+                periods: ['last12Months'],
+                organisationunits: [],
+                series: 'data',
+                category: 'period',
+                filter: 'organisationunit',
+                el: '',
+                legendPosition: false,
+                orgUnitIsParent: false,
+                showData: false,
+                trendLine: false,
+                hideLegend: false,
+                hideSubtitle: false,
+                targetLineValue: null,
+                targetLineLabel: null,
+                baseLineValue: null,
+                baseLineLabel: null,                
+                url: ''
+            };
+            
+            project.state.conf = Ext.applyIf(conf, defaultConf);
+            project.state.conf.type = project.state.conf.type.toLowerCase();
+            project.state.conf.series = project.state.conf.series.toLowerCase();
+            project.state.conf.category = project.state.conf.category.toLowerCase();
+            project.state.conf.filter = project.state.conf.filter.toLowerCase();
+            
+            project.state.conf[project.state.conf.series] = DHIS.chart.conf.finals.chart.series;
+            project.state.conf[project.state.conf.category] = DHIS.chart.conf.finals.chart.category;
+            project.state.conf[project.state.conf.filter] = DHIS.chart.conf.finals.chart.filter;
+            
+            project.state.type = project.state.conf.type;
+            project.state.series.dimension = project.state.conf.series;
+            project.state.category.dimension = project.state.conf.category;
+            project.state.filter.dimension = project.state.conf.filter;
+            
+            DHIS.chart.state.state = project.state;
+            
+			DHIS.chart.value.getValues(project);
+        },
+        setState: function(conf) {
+            if (conf.uid) {
+                Ext.data.JsonP.request({
+                    url: conf.url + DHIS.chart.conf.finals.ajax.favorite_get + conf.uid + '.jsonp',
+                    scope: this,
+                    success: function(r) {
+                        if (!r) {
+                            alert('Invalid uid');
+                            return;
+                        }
+                        
+                        conf.type = r.type.toLowerCase();
+                        conf.periods = DHIS.chart.util.dimension.period.getRelativesFromObject(r.relativePeriods);
+                        conf.organisationunits = DHIS.chart.util.dimension.organisationunit.getIdsFromObjects(r.organisationUnits);
+                        conf.series = r.series.toLowerCase();
+                        conf.category = r.category.toLowerCase();
+                        conf.filter = r.filter.toLowerCase();
+                        conf.legendPosition = conf.legendPosition || false;
+                        
+                        if (r.indicators) {
+                            conf.indicators = DHIS.chart.util.dimension.indicator.getIdsFromObjects(r.indicators);
+                        }
+                        if (r.dataElements) {
+                            conf.dataelements = DHIS.chart.util.dimension.dataelement.getIdsFromObjects(r.dataElements);
+                        }
+                        
+                        this.getState(conf);                        
+                    }
+                });
+            }
+        }
+    };
+    
+    DHIS.chart.value = {
+        getValues: function(project) {
+            var params = [];                
+            params = params.concat(DHIS.chart.util.dimension[project.state.series.dimension].getUrl());
+            params = params.concat(DHIS.chart.util.dimension[project.state.category.dimension].getUrl());
+            params = params.concat(DHIS.chart.util.dimension[project.state.filter.dimension].getUrl(true));
+                        
+            var baseUrl = DHIS.chart.util.string.extendUrl(project.state.conf.url) + DHIS.chart.conf.finals.ajax.data_get;
+            baseUrl = DHIS.chart.util.string.appendUrlIfTrue(baseUrl, DHIS.chart.conf.finals.chart.orgUnitIsParent, project.state.orgUnitIsParent);
+            
+            Ext.Array.each(params, function(item) {
+                baseUrl = Ext.String.urlAppend(baseUrl, item);
+            });
+            
+            Ext.data.JsonP.request({
+                url: baseUrl,
+                disableCaching: false,
+                success: function(r) {
+                    var json = DHIS.chart.util.value.jsonfy(r);
+                    project.values = json.values;
+                    
+                    if (!project.values.length) {
+                        alert('No data values');
+                        return;
+                    }
+                    
+                    for (var i = 0; i < project.values.length; i++) {
+                        project.values[i][DHIS.chart.conf.finals.dimension.data.value] = DHIS.chart.util.string.getEncodedString(project.values[i][DHIS.chart.conf.finals.dimension.data.value]);
+                        project.values[i][DHIS.chart.conf.finals.dimension.period.value] = DHIS.chart.util.string.getEncodedString(project.values[i][DHIS.chart.conf.finals.dimension.period.value]);
+                        project.values[i][DHIS.chart.conf.finals.dimension.organisationunit.value] = DHIS.chart.util.string.getEncodedString(project.values[i][DHIS.chart.conf.finals.dimension.organisationunit.value]);
+                    }
+                    
+                    project.state[project.state.conf.data].names = json.datanames;
+                    project.state[project.state.conf.organisationunit].names = json.organisationunitnames;
+                    Ext.Array.each(project.values, function(item) {						
+                        Ext.Array.include(project.state[project.state.conf.period].names, DHIS.chart.util.string.getEncodedString(item[project.state[project.state.conf.period].dimension]));
+                        item.v = parseFloat(item.v);
+                    });
+                    
+                    for (var k in project.state.conf) {
+                        if (project.state.conf[k] == 'period') {
+                            project.state[k].names = json.periods;
+                        }
+                    }
+                    
+                    DHIS.chart.state.state = project.state;
+					DHIS.chart.chart.getData(project);
+                }
+            });
+        }
+    };
+    
+    DHIS.chart.chart = {
+        getData: function(project) {
+            project.data = [];
+			
+            Ext.Array.each(project.state.category.names, function(item) {
+                var obj = {};
+                obj[DHIS.chart.conf.finals.data.domain] = item;
+                project.data.push(obj);
+            });
+            
+            Ext.Array.each(project.data, function(item) {
+                for (var i = 0; i < project.state.series.names.length; i++) {
+                    item[project.state.series.names[i]] = 0;
+                }
+            });
+            
+            Ext.Array.each(project.data, function(item) {
+                for (var i = 0; i < project.state.series.names.length; i++) {
+                    for (var j = 0; j < project.values.length; j++) {
+                        if (project.values[j][project.state.category.dimension] === item[DHIS.chart.conf.finals.data.domain] && project.values[j][project.state.series.dimension] === project.state.series.names[i]) {
+                            item[project.values[j][project.state.series.dimension]] = project.values[j].v;
+                            break;
+                        }
+                    }
+                }
+            });
+            
+			if (project.state.conf.trendLine) {
+				project.trendline = [];
+				for (var i = 0; i < project.state.series.names.length; i++) {
+					var s = project.state.series.names[i],
+						reg = new DHIS.chart.plugin.SimpleRegression();
+					for (var j = 0; j < project.data.length; j++) {
+						reg.addData(j, project.data[j][s]);
+					}
+					var key = DHIS.chart.conf.finals.data.trendline + s;
+					for (var j = 0; j < project.data.length; j++) {
+						var n = reg.predict(j);
+						project.data[j][key] = parseFloat(reg.predict(j).toFixed(1));
+					}
+					project.trendline.push({
+						key: key,
+						name: 'Trend (' + s + ')'
+					});
+				}
+			}
+
+			if (project.state.conf.targetLineValue) {
+				Ext.Array.each(project.data, function(item) {
+					item[DHIS.chart.conf.finals.data.targetline] = project.state.conf.targetLineValue;
+				});
+			}
+
+			if (project.state.conf.baseLineValue) {
+				Ext.Array.each(project.data, function(item) {
+					item[DHIS.chart.conf.finals.data.baseline] = project.state.conf.baseLineValue;
+				});
+			}
+                
+			DHIS.chart.store.getChartStore(project);
+        },
+        el: null,
+        getChart: function(project) {
+            this.el = Ext.get(project.state.conf.el);
+            this[project.state.type](project);
+            DHIS.chart.exe.execute();
+        },
+        column: function(project, isStacked) {
+			var series = [];
+			if (project.state.conf.trendLine) {
+				var a = DHIS.chart.util.chart.def.series.getTrendLineArray(project);
+				for (var i = 0; i < a.length; i++) {
+					series.push(a[i]);
+				}
+			}
+			var main = {
+				type: 'column',
+				axis: 'left',
+				xField: DHIS.chart.conf.finals.data.domain,
+				yField: project.state.series.names,
+				stacked: isStacked,
+				style: {
+					opacity: 0.8,
+					stroke: '#333'
+				},
+				tips: DHIS.chart.util.chart.def.series.getTips()
+			};
+			if (project.state.conf.showData) {
+				main.label = {display: 'outside', field: project.state.series.names};
+			}
+			series.push(main);
+			if (project.state.conf.targetLineValue) {
+				series.push(DHIS.chart.util.chart.def.series.getTargetLine(project));
+			}
+			if (project.state.conf.baseLineValue) {
+				series.push(DHIS.chart.util.chart.def.series.getBaseLine(project));
+			}
+			
+			var axes = [];
+			var numeric = DHIS.chart.util.chart.def.axis.getNumeric(project, isStacked);
+			axes.push(numeric);
+			axes.push(DHIS.chart.util.chart.def.axis.getCategory(project));
+			
+			DHIS.chart.util.chart.def.series.setTheme(project);
+			project.chart = DHIS.chart.util.chart.def.getChart(project, axes, series, this.el.getWidth(), this.el.getHeight());
+			
+            DHIS.chart.projects[project.state.conf.el] = project;
+        },
+        stackedcolumn: function(project) {
+            this.column(project, true);
+        },
+        bar: function(project, isStacked) {
+			var series = [];
+			if (project.state.conf.trendLine) {
+				var a = DHIS.chart.util.chart.bar.series.getTrendLineArray(project);
+				for (var i = 0; i < a.length; i++) {
+					series.push(a[i]);
+				}
+			}
+			var main = {
+				type: 'bar',
+				axis: 'bottom',
+				xField: DHIS.chart.conf.finals.data.domain,
+				yField: project.state.series.names,
+				stacked: isStacked,
+				style: {
+					opacity: 0.8,
+					stroke: '#333'
+				},
+				tips: DHIS.chart.util.chart.def.series.getTips()
+			};
+			if (project.state.conf.showData) {
+				main.label = {display: 'outside', field: project.state.series.names};
+			}
+			series.push(main);
+			if (project.state.conf.targetLineValue) {
+				series.push(DHIS.chart.util.chart.bar.series.getTargetLine(project));
+			}
+			if (project.state.conf.baseLineValue) {
+				series.push(DHIS.chart.util.chart.bar.series.getBaseLine(project));
+			}
+			
+			var axes = [];
+			var numeric = DHIS.chart.util.chart.bar.axis.getNumeric(project, isStacked);
+			axes.push(numeric);
+			axes.push(DHIS.chart.util.chart.bar.axis.getCategory(project));
+			
+			DHIS.chart.util.chart.def.series.setTheme(project);
+			project.chart = DHIS.chart.util.chart.def.getChart(project, axes, series, this.el.getWidth(), this.el.getHeight());
+			
+            DHIS.chart.projects[project.state.conf.el] = project;
+        },
+        stackedbar: function(project) {
+            this.bar(project, true);
+        },
+        line: function(project) {
+			var series = [];
+			if (project.state.conf.trendLine) {
+				var a = DHIS.chart.util.chart.def.series.getTrendLineArray(project);
+				for (var i = 0; i < a.length; i++) {
+					series.push(a[i]);
+				}
+			}	
+			series = series.concat(DHIS.chart.util.chart.line.series.getArray(project));
+			
+			if (project.state.conf.targetLineValue) {
+				series.push(DHIS.chart.util.chart.def.series.getTargetLine(project));
+			}
+			if (project.state.conf.baseLineValue) {
+				series.push(DHIS.chart.util.chart.def.series.getBaseLine(project));
+			}
+			
+			var axes = [];
+			var numeric = DHIS.chart.util.chart.def.axis.getNumeric(project);
+			axes.push(numeric);
+			axes.push(DHIS.chart.util.chart.def.axis.getCategory(project));
+			
+			DHIS.chart.util.chart.line.series.setTheme(project);
+			project.chart = DHIS.chart.util.chart.def.getChart(project, axes, series, this.el.getWidth(), this.el.getHeight());
+            
+            DHIS.chart.projects[project.state.conf.el] = project;
+        },
+        area: function(project) {
+			var series = [];
+			series.push({
+				type: 'area',
+				axis: 'left',
+				xField: DHIS.chart.conf.finals.data.domain,
+				yField: project.state.series.names,
+				style: {
+					opacity: 0.65,
+					stroke: '#555'
+				}
+			});
+			
+			var axes = [];
+			var numeric = DHIS.chart.util.chart.def.axis.getNumeric(project);
+			axes.push(numeric);
+			axes.push(DHIS.chart.util.chart.def.axis.getCategory(project));
+			
+			DHIS.chart.util.chart.line.series.setTheme(project);
+			project.chart = DHIS.chart.util.chart.def.getChart(project, axes, series, this.el.getWidth(), this.el.getHeight());
+            
+            DHIS.chart.projects[project.state.conf.el] = project;
+        },
+        pie: function(project) {
+			DHIS.chart.util.chart.pie.series.setTheme(project);
+            project.chart = Ext.create('Ext.chart.Chart', {
+				renderTo: project.state.conf.el,
+                width: project.state.conf.width || this.el.getWidth(),
+                height: project.state.conf.height || this.el.getHeight(),
+                animate: true,
+                shadow: true,
+                store: project.store,
+                insetPadding: 60,
+                items: project.state.conf.hideSubtitle ? false : DHIS.chart.util.chart.pie.getTitle(project.state.filter.names[0], project.store.range[0]),
+                legend: project.state.conf.hideLegend ? false : DHIS.chart.util.chart.def.getLegend(project.state.category.names.length),
+                series: [{
+                    type: 'pie',
+                    field: project.state.series.names[0],
+                    showInLegend: true,
+                    label: {
+                        field: DHIS.chart.conf.finals.data.domain
+                    },
+                    highlight: {
+                        segment: {
+                            margin: 10
+                        }
+                    },
+                    style: {
+                        opacity: 0.9,
+						stroke: '#555'
+                    },
+                    tips: DHIS.chart.util.chart.pie.series.getTips(project)
+                }],
+                theme: project.state.conf.el
+            });
+            
+            DHIS.chart.projects[project.state.conf.el] = project;
+        }
+    };
+    
+    DHIS.chart.exe = {
+        allow: true,
+        queue: [],
+        addToQueue: function(conf) {
+            DHIS.chart.exe.queue.push(conf);
+            if (DHIS.chart.exe.allow) {
+                DHIS.chart.exe.allow = false;
+                DHIS.chart.exe.execute();
+            }
+        },
+        execute: function() {
+            if (this.queue.length) {
+                var conf = this.queue.shift();
+                this.destroy(conf.el);
+                if (conf.uid) {
+                    DHIS.chart.state.setState(conf);
+                }
+                else {
+                    DHIS.chart.state.getState(conf);
+                }
+            }
+            else {
+				DHIS.chart.exe.allow = true;
+			}
+		},
+		destroy: function(el) {
+			if (DHIS.chart.projects[el]) {
+				DHIS.chart.projects[el].chart.destroy();
+			}
+		}
+    };
+    
+    DHIS.chart.initialize();
+});
+
+/* TABLE */
+
+DHIS.table.finals = {
+	dataGet: 'api/reportTables/data.jsonp?minimal=true',
+	data: 'data',
+	periods: 'periods',
+	orgunits: 'orgunits',
+	crosstab: 'crosstab',            
+	orgUnitIsParent: 'orgUnitIsParent',
+	defaultConf: {
+		indicators: [],
+		dataelements: [],
+		datasets: [],
+		periods: ['last12Months'],
+		orgunits: [],
+		crosstab: ['data'],
+		orgUnitIsParent: false,
+		useExtGrid: false,
+		el: '',
+		url: ''
+	}
+};
+
+DHIS.table.tables = []; /* element id -> grid panel */
+
+DHIS.table.utils = {
+    appendUrlIfTrue: function(url, param, expression) {
+    	if (expression && expression == true) {
+    		url = Ext.String.urlAppend(url, param + '=true');
+    	}
+    	return url;            	
+    },
+    destroy: function(el) {
+    	if (DHIS.table.tables[el]) {
+    		DHIS.table.tables[el].destroy();
+    	}
+    },
+    getDataUrl: function(conf) {
+		var url = conf.url + DHIS.table.finals.dataGet;
+		
+		Ext.Array.each(conf.indicators, function(item) {
+			url = Ext.String.urlAppend(url, 'in=' + item);
+		});
+		Ext.Array.each(conf.dataelements, function(item) {
+			url = Ext.String.urlAppend(url, 'de=' + item);
+		});
+		Ext.Array.each(conf.datasets, function(item) {
+			url = Ext.String.urlAppend(url, 'ds=' + item);
+		});
+		Ext.Array.each(conf.periods, function(item) {
+			url = Ext.String.urlAppend(url, item + '=true');
+		});
+		Ext.Array.each(conf.orgunits, function(item) {
+			url = Ext.String.urlAppend(url, 'ou=' + item);
+		});
+		Ext.Array.each(conf.crosstab, function(item) {
+			url = Ext.String.urlAppend(url, 'crosstab=' + item);
+		});
+		url = DHIS.table.utils.appendUrlIfTrue(url, DHIS.table.finals.orgUnitIsParent, conf.orgUnitIsParent);
+		return url;
+	}
+};
+
+DHIS.table.grid = {
+	getHeaderArray: function(data) {
+		var headers = [];
+		Ext.Array.each(data.headers, function(header, index) {
+			headers.push(header.name);
+		});
+		return headers;
+	},
+	getColumnArray: function(data) {
+		var columns = [];
+		Ext.Array.each(data.headers, function(header, index) {
+			columns.push({text: header.name, dataIndex: header.name});
+		});
+		return columns;
+	},
+	getStore: function(data) {
+		var store = Ext.create('Ext.data.ArrayStore', {
+			fields: DHIS.table.grid.getHeaderArray(data),
+			data: data.rows
+		});
+		return store;
+	},
+	render: function(conf) {
+		DHIS.table.utils.destroy(conf.el);
+		Ext.data.JsonP.request({
+			url: DHIS.table.utils.getDataUrl(conf),
+			disableCaching: false,
+			success: function(data) {
+				DHIS.table.tables[conf.el] = Ext.create('Ext.grid.Panel', {
+					store: DHIS.table.grid.getStore(data),
+					columns: DHIS.table.grid.getColumnArray(data),
+					renderTo: conf.el
+				});
+			}
+		});
+	}
+};
+
+DHIS.table.plain = {
+	getMarkup: function(data) {
+		var html = '<table><tr>';
+		var classMap = []; /* Col index -> class markup */
+		
+		Ext.Array.each(data.headers, function(header, index) {
+			var clazz = !header.meta ? ' class=\"val\"' : '';	
+			classMap[index] = clazz;
+			html += '<th' + clazz + '>' + header.name + '<\/th>';	
+		});
+		
+		html += '<\/tr>';
+		
+		Ext.Array.each(data.rows, function(row) {
+			html += '<tr>';
+			Ext.Array.each(row, function(field, index) {
+				var clazz = classMap[index];				
+				html += '<td' + clazz + '>' + field + '<\/td>';
+			});
+			html += '<\/tr>';
+		});
+		
+		html += '<\/table>';
+		return html;
+	},	
+	render: function(conf) {
+		Ext.data.JsonP.request({
+			url: DHIS.table.utils.getDataUrl(conf),
+			disableCaching: false,
+			success: function(data) {
+				var html = DHIS.table.plain.getMarkup(data);
+				Ext.get(conf.el).update(html);
+			}
+		});
+	}
+};
+
+DHIS.table.impl = {
+	render: function(conf) {
+		conf = Ext.applyIf(conf, DHIS.table.finals.defaultConf);
+		if ( conf.useExtGrid ) {
+			DHIS.table.grid.render(conf);
+		}
+		else {
+			DHIS.table.plain.render(conf);
+		}
+	}
+}
+
+DHIS.getTable = DHIS.table.impl.render;