~halvdanhg/dhis2/message-fixes

« back to all changes in this revision

Viewing changes to dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/plugin/chart.js

  • Committer: Halvdan Hoem Grelland
  • Date: 2015-01-12 12:29:11 UTC
  • mfrom: (17924.2.17 dhis2)
  • Revision ID: halvdanhg@gmail.com-20150112122911-1xg4pwmjblq30cbg
mwt

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Ext.onReady(function() {
 
2
 
 
3
        // SIMPLE REGRESSION
 
4
        function SimpleRegression()
 
5
        {
 
6
                var sumX = 0; // Sum of x values
 
7
                var sumY = 0; // Sum of y values
 
8
                var sumXX = 0; // Total variation in x
 
9
                var sumXY = 0; // Sum of products
 
10
                var n = 0; // Number of observations
 
11
                var xbar = 0; // Mean of accumulated x values, used in updating formulas
 
12
                var ybar = 0; // Mean of accumulated y values, used in updating formulas
 
13
 
 
14
                this.addData = function( x, y )
 
15
                {
 
16
                        if ( n == 0 )
 
17
                        {
 
18
                                xbar = x;
 
19
                                ybar = y;
 
20
                        }
 
21
                        else
 
22
                        {
 
23
                                var dx = x - xbar;
 
24
                                var dy = y - ybar;
 
25
                                sumXX += dx * dx * n / ( n + 1 );
 
26
                                sumXY += dx * dy * n / ( n + 1 );
 
27
                                xbar += dx / ( n + 1 );
 
28
                                ybar += dy / ( n + 1 );
 
29
                        }
 
30
 
 
31
                        sumX += x;
 
32
                        sumY += y;
 
33
                        n++;
 
34
                };
 
35
 
 
36
                this.predict = function( x )
 
37
                {
 
38
                        var b1 = this.getSlope();
 
39
 
 
40
                        return this.getIntercept( b1 ) + b1 * x;
 
41
                };
 
42
 
 
43
                this.getSlope = function()
 
44
                {
 
45
                        if ( n < 2 )
 
46
                        {
 
47
                                return Number.NaN;
 
48
                        }
 
49
 
 
50
                        return sumXY / sumXX;
 
51
                };
 
52
 
 
53
                this.getIntercept = function( slope )
 
54
                {
 
55
                        return ( sumY - slope * sumX ) / n;
 
56
                };
 
57
        }
 
58
 
 
59
        // CORE
 
60
 
 
61
        // ext config
 
62
        Ext.Ajax.method = 'GET';
 
63
 
 
64
    Ext.isIE = function() {
 
65
        return /trident/.test(Ext.userAgent);
 
66
    }();
 
67
 
 
68
        // namespace
 
69
        DV = {};
 
70
 
 
71
        DV.instances = [];
 
72
        DV.i18n = {};
 
73
        DV.isDebug = false;
 
74
        DV.isSessionStorage = ('sessionStorage' in window && window['sessionStorage'] !== null);
 
75
 
 
76
        DV.getCore = function(init) {
 
77
        var conf = {},
 
78
            api = {},
 
79
            support = {},
 
80
            service = {},
 
81
            web = {},
 
82
            dimConf;
 
83
 
 
84
                // conf
 
85
        (function() {
 
86
            conf.finals = {
 
87
                ajax: {
 
88
                                        path_module: '/dhis-web-visualizer/',
 
89
                                        path_api: '/api/',
 
90
                                        path_commons: '/dhis-web-commons-ajax-json/',
 
91
                    data_get: 'chartValues.json',
 
92
                    indicator_get: 'indicatorGroups/',
 
93
                    indicator_getall: 'indicators.json?paging=false&links=false',
 
94
                    indicatorgroup_get: 'indicatorGroups.json?paging=false&links=false',
 
95
                    dataelement_get: 'dataElementGroups/',
 
96
                    dataelement_getall: 'dataElements.json?domainType=aggregate&paging=false&links=false',
 
97
                    dataelementgroup_get: 'dataElementGroups.json?paging=false&links=false',
 
98
                    dataset_get: 'dataSets.json?paging=false&links=false'
 
99
                },
 
100
                dimension: {
 
101
                    data: {
 
102
                        value: 'data',
 
103
                        name: DV.i18n.data,
 
104
                        dimensionName: 'dx',
 
105
                        objectName: 'dx'
 
106
                    },
 
107
                    indicator: {
 
108
                        value: 'indicator',
 
109
                        name: DV.i18n.indicator,
 
110
                        dimensionName: 'dx',
 
111
                        objectName: 'in'
 
112
                    },
 
113
                    dataElement: {
 
114
                        value: 'dataelement',
 
115
                        name: DV.i18n.data_element,
 
116
                        dimensionName: 'dx',
 
117
                        objectName: 'de'
 
118
                    },
 
119
                    operand: {
 
120
                        value: 'operand',
 
121
                        name: 'Operand',
 
122
                        dimensionName: 'dx',
 
123
                        objectName: 'dc'
 
124
                    },
 
125
                    dataSet: {
 
126
                        value: 'dataset',
 
127
                        name: DV.i18n.dataset,
 
128
                        dimensionName: 'dx',
 
129
                        objectName: 'ds'
 
130
                    },
 
131
                    category: {
 
132
                        name: DV.i18n.assigned_categories,
 
133
                        dimensionName: 'co',
 
134
                        objectName: 'co',
 
135
                    },
 
136
                    period: {
 
137
                        value: 'period',
 
138
                        name: DV.i18n.period,
 
139
                        dimensionName: 'pe',
 
140
                        objectName: 'pe',
 
141
                    },
 
142
                    fixedPeriod: {
 
143
                        value: 'periods'
 
144
                    },
 
145
                    relativePeriod: {
 
146
                        value: 'relativePeriods'
 
147
                    },
 
148
                    organisationUnit: {
 
149
                        value: 'organisationUnits',
 
150
                        name: DV.i18n.organisation_units,
 
151
                        dimensionName: 'ou',
 
152
                        objectName: 'ou',
 
153
                    },
 
154
                    dimension: {
 
155
                        value: 'dimension'
 
156
                        //objectName: 'di'
 
157
                    },
 
158
                    value: {
 
159
                        value: 'value'
 
160
                    }
 
161
                },
 
162
                chart: {
 
163
                    series: 'series',
 
164
                    category: 'category',
 
165
                    filter: 'filter',
 
166
                    column: 'column',
 
167
                    stackedcolumn: 'stackedcolumn',
 
168
                    bar: 'bar',
 
169
                    stackedbar: 'stackedbar',
 
170
                    line: 'line',
 
171
                    area: 'area',
 
172
                    pie: 'pie',
 
173
                    radar: 'radar',
 
174
                    gauge: 'gauge'
 
175
                },
 
176
                data: {
 
177
                    domain: 'domain_',
 
178
                    targetLine: 'targetline_',
 
179
                    baseLine: 'baseline_',
 
180
                    trendLine: 'trendline_'
 
181
                },
 
182
                image: {
 
183
                    png: 'png',
 
184
                    pdf: 'pdf'
 
185
                },
 
186
                cmd: {
 
187
                    init: 'init_',
 
188
                    none: 'none_',
 
189
                    urlparam: 'id'
 
190
                },
 
191
                root: {
 
192
                    id: 'root'
 
193
                }
 
194
            };
 
195
 
 
196
            dimConf = conf.finals.dimension;
 
197
 
 
198
            dimConf.objectNameMap = {};
 
199
            dimConf.objectNameMap[dimConf.data.objectName] = dimConf.data;
 
200
            dimConf.objectNameMap[dimConf.indicator.objectName] = dimConf.indicator;
 
201
            dimConf.objectNameMap[dimConf.dataElement.objectName] = dimConf.dataElement;
 
202
            dimConf.objectNameMap[dimConf.operand.objectName] = dimConf.operand;
 
203
            dimConf.objectNameMap[dimConf.dataSet.objectName] = dimConf.dataSet;
 
204
            dimConf.objectNameMap[dimConf.category.objectName] = dimConf.category;
 
205
            dimConf.objectNameMap[dimConf.period.objectName] = dimConf.period;
 
206
            dimConf.objectNameMap[dimConf.organisationUnit.objectName] = dimConf.organisationUnit;
 
207
            dimConf.objectNameMap[dimConf.dimension.objectName] = dimConf.dimension;
 
208
 
 
209
                        conf.period = {
 
210
                                periodTypes: [
 
211
                                        {id: 'Daily', name: DV.i18n.daily},
 
212
                                        {id: 'Weekly', name: DV.i18n.weekly},
 
213
                                        {id: 'Monthly', name: DV.i18n.monthly},
 
214
                                        {id: 'BiMonthly', name: DV.i18n.bimonthly},
 
215
                                        {id: 'Quarterly', name: DV.i18n.quarterly},
 
216
                                        {id: 'SixMonthly', name: DV.i18n.sixmonthly},
 
217
                                        {id: 'SixMonthlyApril', name: DV.i18n.sixmonthly_april},
 
218
                                        {id: 'Yearly', name: DV.i18n.yearly},
 
219
                                        {id: 'FinancialOct', name: DV.i18n.financial_oct},
 
220
                                        {id: 'FinancialJuly', name: DV.i18n.financial_july},
 
221
                                        {id: 'FinancialApril', name: DV.i18n.financial_april}
 
222
                                ]
 
223
                        };
 
224
 
 
225
            conf.layout = {
 
226
                west_width: 424,
 
227
                west_fieldset_width: 418,
 
228
                west_width_padding: 2,
 
229
                west_fill: 2,
 
230
                west_fill_accordion_indicator: 56,
 
231
                west_fill_accordion_dataelement: 59,
 
232
                west_fill_accordion_dataset: 31,
 
233
                west_fill_accordion_period: 284,
 
234
                west_fill_accordion_organisationunit: 58,
 
235
                west_maxheight_accordion_indicator: 350,
 
236
                west_maxheight_accordion_dataelement: 350,
 
237
                west_maxheight_accordion_dataset: 350,
 
238
                west_maxheight_accordion_period: 513,
 
239
                west_maxheight_accordion_organisationunit: 500,
 
240
                west_maxheight_accordion_group: 350,
 
241
                west_scrollbarheight_accordion_indicator: 300,
 
242
                west_scrollbarheight_accordion_dataelement: 300,
 
243
                west_scrollbarheight_accordion_dataset: 300,
 
244
                west_scrollbarheight_accordion_period: 450,
 
245
                west_scrollbarheight_accordion_organisationunit: 450,
 
246
                west_scrollbarheight_accordion_group: 300,
 
247
                east_tbar_height: 31,
 
248
                east_gridcolumn_height: 30,
 
249
                form_label_width: 55,
 
250
                window_favorite_ypos: 100,
 
251
                window_confirm_width: 250,
 
252
                window_share_width: 500,
 
253
                grid_favorite_width: 420,
 
254
                grid_row_height: 27,
 
255
                treepanel_minheight: 135,
 
256
                treepanel_maxheight: 400,
 
257
                treepanel_fill_default: 310,
 
258
                treepanel_toolbar_menu_width_group: 140,
 
259
                treepanel_toolbar_menu_width_level: 120,
 
260
                multiselect_minheight: 100,
 
261
                multiselect_maxheight: 250,
 
262
                multiselect_fill_default: 345,
 
263
                multiselect_fill_reportingrates: 315
 
264
            };
 
265
 
 
266
            conf.chart = {
 
267
                style: {
 
268
                    inset: 30,
 
269
                    fontFamily: 'Arial,Sans-serif,Roboto,Helvetica,Consolas'
 
270
                },
 
271
                theme: {
 
272
                    dv1: ['#94ae0a', '#1d5991', '#a61120', '#ff8809', '#7c7474', '#a61187', '#ffd13e', '#24ad9a', '#a66111', '#414141', '#4500c4', '#1d5700']
 
273
                }
 
274
            };
 
275
 
 
276
            conf.status = {
 
277
                icon: {
 
278
                    error: 'error_s.png',
 
279
                    warning: 'warning.png',
 
280
                    ok: 'ok.png'
 
281
                }
 
282
            };
 
283
 
 
284
            conf.url = {
 
285
                analysisFields: [
 
286
                    '*',
 
287
                    'program[id,name]',
 
288
                    'programStage[id,name]',
 
289
                    'columns[dimension,filter,items[id,' + init.namePropertyUrl + ']]',
 
290
                    'rows[dimension,filter,items[id,' + init.namePropertyUrl + ']]',
 
291
                    'filters[dimension,filter,items[id,' + init.namePropertyUrl + ']]',
 
292
                    '!lastUpdated',
 
293
                    '!href',
 
294
                    '!created',
 
295
                    '!publicAccess',
 
296
                    '!rewindRelativePeriods',
 
297
                    '!userOrganisationUnit',
 
298
                    '!userOrganisationUnitChildren',
 
299
                    '!userOrganisationUnitGrandChildren',
 
300
                    '!externalAccess',
 
301
                    '!access',
 
302
                    '!relativePeriods',
 
303
                    '!columnDimensions',
 
304
                    '!rowDimensions',
 
305
                    '!filterDimensions',
 
306
                    '!user',
 
307
                    '!organisationUnitGroups',
 
308
                    '!itemOrganisationUnitGroups',
 
309
                    '!userGroupAccesses',
 
310
                    '!indicators',
 
311
                    '!dataElements',
 
312
                    '!dataElementOperands',
 
313
                    '!dataElementGroups',
 
314
                    '!dataSets',
 
315
                    '!periods',
 
316
                    '!organisationUnitLevels',
 
317
                    '!organisationUnits'
 
318
                ]
 
319
            };
 
320
        }());
 
321
 
 
322
        // api
 
323
        (function() {
 
324
            api.layout = {};
 
325
 
 
326
                        api.layout.Record = function(config) {
 
327
                                var config = Ext.clone(config);
 
328
 
 
329
                                // id: string
 
330
 
 
331
                                return function() {
 
332
                                        if (!Ext.isObject(config)) {
 
333
                                                console.log('Record: config is not an object: ' + config);
 
334
                                                return;
 
335
                                        }
 
336
 
 
337
                                        if (!Ext.isString(config.id)) {
 
338
                                                alert('Record: id is not text: ' + config);
 
339
                                                return;
 
340
                                        }
 
341
 
 
342
                                        config.id = config.id.replace('.', '#');
 
343
 
 
344
                                        return config;
 
345
                                }();
 
346
                        };
 
347
 
 
348
            api.layout.Dimension = function(config) {
 
349
                                var config = Ext.clone(config);
 
350
 
 
351
                                // dimension: string
 
352
 
 
353
                                // items: [Record]
 
354
 
 
355
                                return function() {
 
356
                                        if (!Ext.isObject(config)) {
 
357
                                                console.log('Dimension: config is not an object: ' + config);
 
358
                                                return;
 
359
                                        }
 
360
 
 
361
                                        if (!Ext.isString(config.dimension)) {
 
362
                                                console.log('Dimension: name is not a string: ' + config);
 
363
                                                return;
 
364
                                        }
 
365
 
 
366
                                        if (config.dimension !== conf.finals.dimension.category.objectName) {
 
367
                                                var records = [];
 
368
 
 
369
                                                if (!Ext.isArray(config.items)) {
 
370
                                                        console.log('Dimension: items is not an array: ' + config);
 
371
                                                        return;
 
372
                                                }
 
373
 
 
374
                                                for (var i = 0; i < config.items.length; i++) {
 
375
                                                        records.push(api.layout.Record(config.items[i]));
 
376
                                                }
 
377
 
 
378
                                                config.items = Ext.Array.clean(records);
 
379
 
 
380
                                                if (!config.items.length) {
 
381
                                                        console.log('Dimension: has no valid items: ' + config);
 
382
                                                        return;
 
383
                                                }
 
384
                                        }
 
385
 
 
386
                                        return config;
 
387
                                }();
 
388
                        };
 
389
 
 
390
            api.layout.Layout = function(config, applyConfig) {
 
391
                                var config = Ext.clone(config),
 
392
                                        layout = {},
 
393
                                        getValidatedDimensionArray,
 
394
                                        validateSpecialCases;
 
395
 
 
396
                // type: string ('column') - 'column', 'stackedcolumn', 'bar', 'stackedbar', 'line', 'area', 'pie'
 
397
 
 
398
                // columns: [Dimension]
 
399
 
 
400
                // rows: [Dimension]
 
401
 
 
402
                // filters: [Dimension]
 
403
 
 
404
                // showTrendLine: boolean (false)
 
405
 
 
406
                // targetLineValue: number
 
407
 
 
408
                // targetLineTitle: string
 
409
 
 
410
                // baseLineValue: number
 
411
 
 
412
                // baseLineTitle: string
 
413
 
 
414
                // sortOrder: number
 
415
 
 
416
                // rangeAxisMaxValue: number
 
417
 
 
418
                // rangeAxisMinValue: number
 
419
 
 
420
                // rangeAxisSteps: number
 
421
 
 
422
                // rangeAxisDecimals: number
 
423
 
 
424
                // showValues: boolean (true)
 
425
 
 
426
                // hideEmptyRows: boolean (false)
 
427
 
 
428
                // hideLegend: boolean (false)
 
429
 
 
430
                // hideTitle: boolean (false)
 
431
 
 
432
                // domainAxisTitle: string
 
433
 
 
434
                // rangeAxisTitle: string
 
435
 
 
436
                // userOrganisationUnit: boolean (false)
 
437
 
 
438
                // userOrganisationUnitChildren: boolean (false)
 
439
 
 
440
                // parentGraphMap: object
 
441
 
 
442
                getValidatedDimensionArray = function(dimensionArray) {
 
443
                                        var dimensionArray = Ext.clone(dimensionArray);
 
444
 
 
445
                                        if (!(dimensionArray && Ext.isArray(dimensionArray) && dimensionArray.length)) {
 
446
                                                return;
 
447
                                        }
 
448
 
 
449
                                        for (var i = 0; i < dimensionArray.length; i++) {
 
450
                                                dimensionArray[i] = api.layout.Dimension(dimensionArray[i]);
 
451
                                        }
 
452
 
 
453
                                        dimensionArray = Ext.Array.clean(dimensionArray);
 
454
 
 
455
                                        return dimensionArray.length ? dimensionArray : null;
 
456
                                };
 
457
 
 
458
                                analytical2layout = function(analytical) {
 
459
                                        var layoutConfig = Ext.clone(analytical),
 
460
                                                co = dimConf.category.objectName;
 
461
 
 
462
                                        analytical = Ext.clone(analytical);
 
463
 
 
464
                                        layoutConfig.columns = [];
 
465
                                        layoutConfig.rows = [];
 
466
                                        layoutConfig.filters = layoutConfig.filters || [];
 
467
 
 
468
                                        // Series
 
469
                                        if (Ext.isArray(analytical.columns) && analytical.columns.length) {
 
470
                                                analytical.columns.reverse();
 
471
 
 
472
                                                for (var i = 0, dim; i < analytical.columns.length; i++) {
 
473
                                                        dim = analytical.columns[i];
 
474
 
 
475
                                                        if (dim.dimension === co) {
 
476
                                                                continue;
 
477
                                                        }
 
478
 
 
479
                                                        if (!layoutConfig.columns.length) {
 
480
                                                                layoutConfig.columns.push(dim);
 
481
                                                        }
 
482
                                                        else {
 
483
 
 
484
                                                                // indicators cannot be set as filter
 
485
                                                                if (dim.dimension === dimConf.indicator.objectName) {
 
486
                                                                        layoutConfig.filters.push(layoutConfig.columns.pop());
 
487
                                                                        layoutConfig.columns = [dim];
 
488
                                                                }
 
489
                                                                else {
 
490
                                                                        layoutConfig.filters.push(dim);
 
491
                                                                }
 
492
                                                        }
 
493
                                                }
 
494
                                        }
 
495
 
 
496
                                        // Rows
 
497
                                        if (Ext.isArray(analytical.rows) && analytical.rows.length) {
 
498
                                                analytical.rows.reverse();
 
499
 
 
500
                                                for (var i = 0, dim; i < analytical.rows.length; i++) {
 
501
                                                        dim = analytical.rows[i];
 
502
 
 
503
                                                        if (dim.dimension === co) {
 
504
                                                                continue;
 
505
                                                        }
 
506
 
 
507
                                                        if (!layoutConfig.rows.length) {
 
508
                                                                layoutConfig.rows.push(dim);
 
509
                                                        }
 
510
                                                        else {
 
511
 
 
512
                                                                // indicators cannot be set as filter
 
513
                                                                if (dim.dimension === dimConf.indicator.objectName) {
 
514
                                                                        layoutConfig.filters.push(layoutConfig.rows.pop());
 
515
                                                                        layoutConfig.rows = [dim];
 
516
                                                                }
 
517
                                                                else {
 
518
                                                                        layoutConfig.filters.push(dim);
 
519
                                                                }
 
520
                                                        }
 
521
                                                }
 
522
                                        }
 
523
 
 
524
                                        return layoutConfig;
 
525
                                };
 
526
 
 
527
                                validateSpecialCases = function() {
 
528
                                        var dimConf = conf.finals.dimension,
 
529
                                                dimensions,
 
530
                                                objectNameDimensionMap = {};
 
531
 
 
532
                                        if (!layout) {
 
533
                                                return;
 
534
                                        }
 
535
 
 
536
                                        dimensions = Ext.Array.clean([].concat(layout.columns || [], layout.rows || [], layout.filters || []));
 
537
 
 
538
                                        for (var i = 0; i < dimensions.length; i++) {
 
539
                                                objectNameDimensionMap[dimensions[i].dimension] = dimensions[i];
 
540
                                        }
 
541
 
 
542
                                        if (layout.filters && layout.filters.length) {
 
543
                                                for (var i = 0; i < layout.filters.length; i++) {
 
544
 
 
545
                                                        // Indicators as filter
 
546
                                                        if (layout.filters[i].dimension === dimConf.indicator.objectName) {
 
547
                                                                web.message.alert(DV.i18n.indicators_cannot_be_specified_as_filter || 'Indicators cannot be specified as filter');
 
548
                                                                return;
 
549
                                                        }
 
550
 
 
551
                                                        // Categories as filter
 
552
                                                        if (layout.filters[i].dimension === dimConf.category.objectName) {
 
553
                                                                web.message.alert(DV.i18n.categories_cannot_be_specified_as_filter || 'Categories cannot be specified as filter');
 
554
                                                                return;
 
555
                                                        }
 
556
 
 
557
                                                        // Data sets as filter
 
558
                                                        if (layout.filters[i].dimension === dimConf.dataSet.objectName) {
 
559
                                                                web.message.alert(DV.i18n.data_sets_cannot_be_specified_as_filter || 'Data sets cannot be specified as filter');
 
560
                                                                return;
 
561
                                                        }
 
562
                                                }
 
563
                                        }
 
564
 
 
565
                                        // dc and in
 
566
                                        if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.indicator.objectName]) {
 
567
                                                web.message.alert('Indicators and detailed data elements cannot be specified together');
 
568
                                                return;
 
569
                                        }
 
570
 
 
571
                                        // dc and de
 
572
                                        if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.dataElement.objectName]) {
 
573
                                                web.message.alert('Detailed data elements and totals cannot be specified together');
 
574
                                                return;
 
575
                                        }
 
576
 
 
577
                                        // dc and ds
 
578
                                        if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.dataSet.objectName]) {
 
579
                                                web.message.alert('Data sets and detailed data elements cannot be specified together');
 
580
                                                return;
 
581
                                        }
 
582
 
 
583
                                        // dc and co
 
584
                                        if (objectNameDimensionMap[dimConf.operand.objectName] && objectNameDimensionMap[dimConf.category.objectName]) {
 
585
                                                web.message.alert('Categories and detailed data elements cannot be specified together');
 
586
                                                return;
 
587
                                        }
 
588
 
 
589
                                        return true;
 
590
                                };
 
591
 
 
592
                return function() {
 
593
                    var objectNames = [],
 
594
                                                dimConf = conf.finals.dimension;
 
595
 
 
596
                                        // config must be an object
 
597
                                        if (!(config && Ext.isObject(config))) {
 
598
                                                alert('Layout: config is not an object (' + init.el + ')');
 
599
                                                return;
 
600
                                        }
 
601
 
 
602
                    config.columns = getValidatedDimensionArray(config.columns);
 
603
                    config.rows = getValidatedDimensionArray(config.rows);
 
604
                    config.filters = getValidatedDimensionArray(config.filters);
 
605
 
 
606
                                        // at least one dimension specified as column and row
 
607
                                        if (!config.columns) {
 
608
                                                alert('No series items selected');
 
609
                                                return;
 
610
                                        }
 
611
 
 
612
                                        if (!config.rows) {
 
613
                                                alert('No category items selected');
 
614
                                                return;
 
615
                                        }
 
616
 
 
617
                                        // get object names
 
618
                                        for (var i = 0, dims = Ext.Array.clean([].concat(config.columns || [], config.rows || [], config.filters || [])); i < dims.length; i++) {
 
619
 
 
620
                                                // Object names
 
621
                                                if (api.layout.Dimension(dims[i])) {
 
622
                                                        objectNames.push(dims[i].dimension);
 
623
                                                }
 
624
                                        }
 
625
 
 
626
                                        // at least one period
 
627
                                        if (!Ext.Array.contains(objectNames, dimConf.period.objectName)) {
 
628
                                                alert('At least one period must be specified as series, category or filter');
 
629
                                                return;
 
630
                                        }
 
631
 
 
632
                                        // favorite
 
633
                                        if (config.id) {
 
634
                                                layout.id = config.id;
 
635
                                        }
 
636
 
 
637
                                        if (config.name) {
 
638
                                                layout.name = config.name;
 
639
                                        }
 
640
 
 
641
                                        // analytical2layout
 
642
                                        //config = analytical2layout(config);
 
643
 
 
644
                    // layout
 
645
                    layout.type = Ext.isString(config.type) ? config.type.toLowerCase() : conf.finals.chart.column;
 
646
 
 
647
                    layout.columns = config.columns;
 
648
                    layout.rows = config.rows;
 
649
                    layout.filters = config.filters;
 
650
 
 
651
                    // properties
 
652
                    layout.showValues = Ext.isBoolean(config.showData) ? config.showData : (Ext.isBoolean(config.showValues) ? config.showValues : true);
 
653
                    layout.hideEmptyRows = Ext.isBoolean(config.hideEmptyRows) ? config.hideEmptyRows : (Ext.isBoolean(config.hideEmptyRows) ? config.hideEmptyRows : true);
 
654
                    layout.showTrendLine = Ext.isBoolean(config.regression) ? config.regression : (Ext.isBoolean(config.showTrendLine) ? config.showTrendLine : false);
 
655
                    layout.targetLineValue = Ext.isNumber(config.targetLineValue) ? config.targetLineValue : null;
 
656
                    layout.targetLineTitle = Ext.isString(config.targetLineLabel) && !Ext.isEmpty(config.targetLineLabel) ? config.targetLineLabel :
 
657
                        (Ext.isString(config.targetLineTitle) && !Ext.isEmpty(config.targetLineTitle) ? config.targetLineTitle : null);
 
658
                    layout.baseLineValue = Ext.isNumber(config.baseLineValue) ? config.baseLineValue : null;
 
659
                    layout.baseLineTitle = Ext.isString(config.baseLineLabel) && !Ext.isEmpty(config.baseLineLabel) ? config.baseLineLabel :
 
660
                        (Ext.isString(config.baseLineTitle) && !Ext.isEmpty(config.baseLineTitle) ? config.baseLineTitle : null);
 
661
                    layout.sortOrder = Ext.isNumber(config.sortOrder) ? config.sortOrder : 0;
 
662
 
 
663
                                        layout.rangeAxisMaxValue = Ext.isNumber(config.rangeAxisMaxValue) ? config.rangeAxisMaxValue : null;
 
664
                                        layout.rangeAxisMinValue = Ext.isNumber(config.rangeAxisMinValue) ? config.rangeAxisMinValue : null;
 
665
                                        layout.rangeAxisSteps = Ext.isNumber(config.rangeAxisSteps) ? config.rangeAxisSteps : null;
 
666
                                        layout.rangeAxisDecimals = Ext.isNumber(config.rangeAxisDecimals) ? config.rangeAxisDecimals : null;
 
667
                                        layout.rangeAxisTitle = Ext.isString(config.rangeAxisLabel) && !Ext.isEmpty(config.rangeAxisLabel) ? config.rangeAxisLabel :
 
668
                        (Ext.isString(config.rangeAxisTitle) && !Ext.isEmpty(config.rangeAxisTitle) ? config.rangeAxisTitle : null);
 
669
                                        layout.domainAxisTitle = Ext.isString(config.domainAxisLabel) && !Ext.isEmpty(config.domainAxisLabel) ? config.domainAxisLabel :
 
670
                        (Ext.isString(config.domainAxisTitle) && !Ext.isEmpty(config.domainAxisTitle) ? config.domainAxisTitle : null);
 
671
 
 
672
                    layout.hideLegend = Ext.isBoolean(config.hideLegend) ? config.hideLegend : false;
 
673
                    layout.hideTitle = Ext.isBoolean(config.hideTitle) ? config.hideTitle : false;
 
674
                    layout.title = Ext.isString(config.title) &&  !Ext.isEmpty(config.title) ? config.title : null;
 
675
 
 
676
                    layout.parentGraphMap = Ext.isObject(config.parentGraphMap) ? config.parentGraphMap : null;
 
677
 
 
678
                    // style
 
679
                    if (Ext.isObject(config.domainAxisStyle)) {
 
680
                        layout.domainAxisStyle = config.domainAxisStyle;
 
681
                    }
 
682
 
 
683
                    if (Ext.isObject(config.rangeAxisStyle)) {
 
684
                        layout.rangeAxisStyle = config.rangeAxisStyle;
 
685
                    }
 
686
 
 
687
                    if (Ext.isObject(config.legendStyle)) {
 
688
                        layout.legendStyle = config.legendStyle;
 
689
                    }
 
690
 
 
691
                    if (Ext.isObject(config.seriesStyle)) {
 
692
                        layout.seriesStyle = config.seriesStyle;
 
693
                    }
 
694
 
 
695
                                        if (!validateSpecialCases()) {
 
696
                                                return;
 
697
                                        }
 
698
 
 
699
                                        return Ext.apply(layout, applyConfig);
 
700
                }();
 
701
            };
 
702
 
 
703
            api.response = {};
 
704
 
 
705
            api.response.Header = function(config) {
 
706
                                var config = Ext.clone(config);
 
707
 
 
708
                                // name: string
 
709
 
 
710
                                // meta: boolean
 
711
 
 
712
                                return function() {
 
713
                                        if (!Ext.isObject(config)) {
 
714
                                                console.log('Header: config is not an object: ' + config);
 
715
                                                return;
 
716
                                        }
 
717
 
 
718
                                        if (!Ext.isString(config.name)) {
 
719
                                                console.log('Header: name is not a string: ' + config);
 
720
                                                return;
 
721
                                        }
 
722
 
 
723
                                        if (!Ext.isBoolean(config.meta)) {
 
724
                                                console.log('Header: meta is not boolean: ' + config);
 
725
                                                return;
 
726
                                        }
 
727
 
 
728
                                        return config;
 
729
                                }();
 
730
                        };
 
731
 
 
732
            api.response.Response = function(config) {
 
733
                                var config = Ext.clone(config);
 
734
 
 
735
                                // headers: [Header]
 
736
 
 
737
                                return function() {
 
738
                                        if (!(config && Ext.isObject(config))) {
 
739
                                                console.log('Response: config is not an object');
 
740
                                                return;
 
741
                                        }
 
742
 
 
743
                                        if (!(config.headers && Ext.isArray(config.headers))) {
 
744
                                                console.log('Response: headers is not an array');
 
745
                                                return;
 
746
                                        }
 
747
 
 
748
                                        for (var i = 0, header; i < config.headers.length; i++) {
 
749
                                                config.headers[i] = api.response.Header(config.headers[i]);
 
750
                                        }
 
751
 
 
752
                                        config.headers = Ext.Array.clean(config.headers);
 
753
 
 
754
                                        if (!config.headers.length) {
 
755
                                                console.log('Response: no valid headers');
 
756
                                                return;
 
757
                                        }
 
758
 
 
759
                                        if (!(Ext.isArray(config.rows) && config.rows.length > 0)) {
 
760
                        if (!DV.plugin) {
 
761
                            alert('No values found');
 
762
                        }
 
763
                        return;
 
764
                                        }
 
765
 
 
766
                                        if (config.headers.length !== config.rows[0].length) {
 
767
                                                console.log('Response: headers.length !== rows[0].length');
 
768
                                        }
 
769
 
 
770
                                        return config;
 
771
                                }();
 
772
                        };
 
773
        }());
 
774
 
 
775
                // support
 
776
                (function() {
 
777
 
 
778
                        // prototype
 
779
                        support.prototype = {};
 
780
 
 
781
                                // array
 
782
                        support.prototype.array = {};
 
783
 
 
784
                        support.prototype.array.getLength = function(array, suppressWarning) {
 
785
                                if (!Ext.isArray(array)) {
 
786
                                        if (!suppressWarning) {
 
787
                                                console.log('support.prototype.array.getLength: not an array');
 
788
                                        }
 
789
 
 
790
                                        return null;
 
791
                                }
 
792
 
 
793
                                return array.length;
 
794
                        };
 
795
 
 
796
                        support.prototype.array.sort = function(array, direction, key) {
 
797
                                // accepts [number], [string], [{prop: number}], [{prop: string}]
 
798
 
 
799
                                if (!support.prototype.array.getLength(array)) {
 
800
                                        return;
 
801
                                }
 
802
 
 
803
                                key = key || 'name';
 
804
 
 
805
                                array.sort( function(a, b) {
 
806
 
 
807
                                        // if object, get the property values
 
808
                                        if (Ext.isObject(a) && Ext.isObject(b) && key) {
 
809
                                                a = a[key];
 
810
                                                b = b[key];
 
811
                                        }
 
812
 
 
813
                                        // string
 
814
                                        if (Ext.isString(a) && Ext.isString(b)) {
 
815
                                                a = a.toLowerCase();
 
816
                                                b = b.toLowerCase();
 
817
 
 
818
                                                if (direction === 'DESC') {
 
819
                                                        return a < b ? 1 : (a > b ? -1 : 0);
 
820
                                                }
 
821
                                                else {
 
822
                                                        return a < b ? -1 : (a > b ? 1 : 0);
 
823
                                                }
 
824
                                        }
 
825
 
 
826
                                        // number
 
827
                                        else if (Ext.isNumber(a) && Ext.isNumber(b)) {
 
828
                                                return direction === 'DESC' ? b - a : a - b;
 
829
                                        }
 
830
 
 
831
                                        return 0;
 
832
                                });
 
833
 
 
834
                                return array;
 
835
                        };
 
836
 
 
837
                                // object
 
838
                        support.prototype.object = {};
 
839
 
 
840
                        support.prototype.object.getLength = function(object, suppressWarning) {
 
841
                                if (!Ext.isObject(object)) {
 
842
                                        if (!suppressWarning) {
 
843
                                                console.log('support.prototype.object.getLength: not an object');
 
844
                                        }
 
845
 
 
846
                                        return null;
 
847
                                }
 
848
 
 
849
                                var size = 0;
 
850
 
 
851
                                for (var key in object) {
 
852
                                        if (object.hasOwnProperty(key)) {
 
853
                                                size++;
 
854
                                        }
 
855
                                }
 
856
 
 
857
                                return size;
 
858
                        };
 
859
 
 
860
                        support.prototype.object.hasObject = function(object, property, value) {
 
861
                                if (!support.prototype.object.getLength(object)) {
 
862
                                        return null;
 
863
                                }
 
864
 
 
865
                                for (var key in object) {
 
866
                                        var record = object[key];
 
867
 
 
868
                                        if (object.hasOwnProperty(key) && record[property] === value) {
 
869
                                                return true;
 
870
                                        }
 
871
                                }
 
872
 
 
873
                                return null;
 
874
                        };
 
875
 
 
876
                                // str
 
877
                        support.prototype.str = {};
 
878
 
 
879
                        support.prototype.str.replaceAll = function(variable, find, replace) {
 
880
                if (Ext.isString(variable)) {
 
881
                    variable = variable.split(find).join(replace);
 
882
                }
 
883
                else if (Ext.isArray(variable)) {
 
884
                    for (var i = 0; i < variable.length; i++) {
 
885
                        variable[i] = variable[i].split(find).join(replace);
 
886
                    }
 
887
                }
 
888
 
 
889
                return variable;
 
890
                        };
 
891
                }());
 
892
 
 
893
                // service
 
894
                (function() {
 
895
 
 
896
                        // layout
 
897
                        service.layout = {};
 
898
 
 
899
                        service.layout.cleanDimensionArray = function(dimensionArray) {
 
900
                                if (!support.prototype.array.getLength(dimensionArray)) {
 
901
                                        return null;
 
902
                                }
 
903
 
 
904
                                var array = [];
 
905
 
 
906
                                for (var i = 0; i < dimensionArray.length; i++) {
 
907
                                        array.push(api.layout.Dimension(dimensionArray[i]));
 
908
                                }
 
909
 
 
910
                                array = Ext.Array.clean(array);
 
911
 
 
912
                                return array.length ? array : null;
 
913
                        };
 
914
 
 
915
                        service.layout.sortDimensionArray = function(dimensionArray, key) {
 
916
                                if (!support.prototype.array.getLength(dimensionArray, true)) {
 
917
                                        return null;
 
918
                                }
 
919
 
 
920
                                // Clean dimension array
 
921
                                dimensionArray = service.layout.cleanDimensionArray(dimensionArray);
 
922
 
 
923
                                if (!dimensionArray) {
 
924
                                        console.log('service.layout.sortDimensionArray: no valid dimensions');
 
925
                                        return null;
 
926
                                }
 
927
 
 
928
                                key = key || 'dimensionName';
 
929
 
 
930
                                // Dimension order
 
931
                                Ext.Array.sort(dimensionArray, function(a,b) {
 
932
                                        if (a[key] < b[key]) {
 
933
                                                return -1;
 
934
                                        }
 
935
                                        if (a[key] > b[key]) {
 
936
                                                return 1;
 
937
                                        }
 
938
                                        return 0;
 
939
                                });
 
940
 
 
941
                                // Sort object items, ids
 
942
                                for (var i = 0, items; i < dimensionArray.length; i++) {
 
943
                                        support.prototype.array.sort(dimensionArray[i].items, 'ASC', 'id');
 
944
 
 
945
                                        if (support.prototype.array.getLength(dimensionArray[i].ids)) {
 
946
                                                support.prototype.array.sort(dimensionArray[i].ids);
 
947
                                        }
 
948
                                }
 
949
 
 
950
                                return dimensionArray;
 
951
                        };
 
952
 
 
953
                        service.layout.getObjectNameDimensionMapFromDimensionArray = function(dimensionArray) {
 
954
                                var map = {};
 
955
 
 
956
                                if (!support.prototype.array.getLength(dimensionArray)) {
 
957
                                        return null;
 
958
                                }
 
959
 
 
960
                                for (var i = 0, dimension; i < dimensionArray.length; i++) {
 
961
                                        dimension = api.layout.Dimension(dimensionArray[i]);
 
962
 
 
963
                                        if (dimension) {
 
964
                                                map[dimension.dimension] = dimension;
 
965
                                        }
 
966
                                }
 
967
 
 
968
                                return support.prototype.object.getLength(map) ? map : null;
 
969
                        };
 
970
 
 
971
                        service.layout.getObjectNameDimensionItemsMapFromDimensionArray = function(dimensionArray) {
 
972
                                var map = {};
 
973
 
 
974
                                if (!support.prototype.array.getLength(dimensionArray)) {
 
975
                                        return null;
 
976
                                }
 
977
 
 
978
                                for (var i = 0, dimension; i < dimensionArray.length; i++) {
 
979
                                        dimension = api.layout.Dimension(dimensionArray[i]);
 
980
 
 
981
                                        if (dimension) {
 
982
                                                map[dimension.dimension] = dimension.items;
 
983
                                        }
 
984
                                }
 
985
 
 
986
                                return support.prototype.object.getLength(map) ? map : null;
 
987
                        };
 
988
 
 
989
                        service.layout.getExtendedLayout = function(layout) {
 
990
                                var layout = Ext.clone(layout),
 
991
                                        xLayout;
 
992
 
 
993
                                xLayout = {
 
994
                                        columns: [],
 
995
                                        rows: [],
 
996
                                        filters: [],
 
997
 
 
998
                                        columnObjectNames: [],
 
999
                                        columnDimensionNames: [],
 
1000
                                        rowObjectNames: [],
 
1001
                                        rowDimensionNames: [],
 
1002
 
 
1003
                                        // axis
 
1004
                                        axisDimensions: [],
 
1005
                                        axisObjectNames: [],
 
1006
                                        axisDimensionNames: [],
 
1007
 
 
1008
                                                // for param string
 
1009
                                        sortedAxisDimensionNames: [],
 
1010
 
 
1011
                                        // Filter
 
1012
                                        filterDimensions: [],
 
1013
                                        filterObjectNames: [],
 
1014
                                        filterDimensionNames: [],
 
1015
 
 
1016
                                                // for param string
 
1017
                                        sortedFilterDimensions: [],
 
1018
 
 
1019
                                        // all
 
1020
                                        dimensions: [],
 
1021
                                        objectNames: [],
 
1022
                                        dimensionNames: [],
 
1023
 
 
1024
                                        // oject name maps
 
1025
                                        objectNameDimensionsMap: {},
 
1026
                                        objectNameItemsMap: {},
 
1027
                                        objectNameIdsMap: {},
 
1028
 
 
1029
                                        // dimension name maps
 
1030
                                        dimensionNameDimensionsMap: {},
 
1031
                                        dimensionNameItemsMap: {},
 
1032
                                        dimensionNameIdsMap: {},
 
1033
 
 
1034
                                                // for param string
 
1035
                                        dimensionNameSortedIdsMap: {}
 
1036
 
 
1037
                                        // sort table by column
 
1038
                                        //sortableIdObjects: []
 
1039
                                };
 
1040
 
 
1041
                                Ext.applyIf(xLayout, layout);
 
1042
 
 
1043
                                // columns, rows, filters
 
1044
                                if (layout.columns) {
 
1045
                    //layout.columns = support.prototype.array.uniqueByProperty(layout.columns, 'dimension');
 
1046
 
 
1047
                                        for (var i = 0, dim, items, xDim; i < layout.columns.length; i++) {
 
1048
                                                dim = layout.columns[i];
 
1049
                                                items = dim.items;
 
1050
                                                xDim = {};
 
1051
 
 
1052
                                                xDim.dimension = dim.dimension;
 
1053
                                                xDim.objectName = dim.dimension;
 
1054
                                                xDim.dimensionName = dimConf.objectNameMap.hasOwnProperty(dim.dimension) ? dimConf.objectNameMap[dim.dimension].dimensionName || dim.dimension : dim.dimension;
 
1055
 
 
1056
                                                xDim.items = [];
 
1057
                                                xDim.ids = [];
 
1058
 
 
1059
                                                if (items) {
 
1060
                                                        xDim.items = items;
 
1061
 
 
1062
                                                        for (var j = 0; j < items.length; j++) {
 
1063
                                                                xDim.ids.push(items[j].id);
 
1064
                                                        }
 
1065
                                                }
 
1066
 
 
1067
                                                xLayout.columns.push(xDim);
 
1068
 
 
1069
                                                xLayout.columnObjectNames.push(xDim.objectName);
 
1070
                                                xLayout.columnDimensionNames.push(xDim.dimensionName);
 
1071
 
 
1072
                                                xLayout.axisDimensions.push(xDim);
 
1073
                                                xLayout.axisObjectNames.push(xDim.objectName);
 
1074
                                                xLayout.axisDimensionNames.push(dimConf.objectNameMap.hasOwnProperty(xDim.objectName) ? dimConf.objectNameMap[xDim.objectName].dimensionName || xDim.objectName : xDim.objectName);
 
1075
 
 
1076
                                                xLayout.objectNameDimensionsMap[xDim.objectName] = xDim;
 
1077
                                                xLayout.objectNameItemsMap[xDim.objectName] = xDim.items;
 
1078
                                                xLayout.objectNameIdsMap[xDim.objectName] = xDim.ids;
 
1079
                                        }
 
1080
                                }
 
1081
 
 
1082
                                if (layout.rows) {
 
1083
                    //layout.rows = support.prototype.array.uniqueByProperty(layout.rows, 'dimension');
 
1084
 
 
1085
                                        for (var i = 0, dim, items, xDim; i < layout.rows.length; i++) {
 
1086
                                                dim = Ext.clone(layout.rows[i]);
 
1087
                                                items = dim.items;
 
1088
                                                xDim = {};
 
1089
 
 
1090
                                                xDim.dimension = dim.dimension;
 
1091
                                                xDim.objectName = dim.dimension;
 
1092
                                                xDim.dimensionName = dimConf.objectNameMap.hasOwnProperty(dim.dimension) ? dimConf.objectNameMap[dim.dimension].dimensionName || dim.dimension : dim.dimension;
 
1093
 
 
1094
                                                xDim.items = [];
 
1095
                                                xDim.ids = [];
 
1096
 
 
1097
                                                if (items) {
 
1098
                                                        xDim.items = items;
 
1099
 
 
1100
                                                        for (var j = 0; j < items.length; j++) {
 
1101
                                                                xDim.ids.push(items[j].id);
 
1102
                                                        }
 
1103
                                                }
 
1104
 
 
1105
                                                xLayout.rows.push(xDim);
 
1106
 
 
1107
                                                xLayout.rowObjectNames.push(xDim.objectName);
 
1108
                                                xLayout.rowDimensionNames.push(xDim.dimensionName);
 
1109
 
 
1110
                                                xLayout.axisDimensions.push(xDim);
 
1111
                                                xLayout.axisObjectNames.push(xDim.objectName);
 
1112
                                                xLayout.axisDimensionNames.push(dimConf.objectNameMap.hasOwnProperty(xDim.objectName) ? dimConf.objectNameMap[xDim.objectName].dimensionName || xDim.objectName : xDim.objectName);
 
1113
 
 
1114
                                                xLayout.objectNameDimensionsMap[xDim.objectName] = xDim;
 
1115
                                                xLayout.objectNameItemsMap[xDim.objectName] = xDim.items;
 
1116
                                                xLayout.objectNameIdsMap[xDim.objectName] = xDim.ids;
 
1117
                                        }
 
1118
                                }
 
1119
 
 
1120
                                if (layout.filters) {
 
1121
                    //layout.filters = support.prototype.array.uniqueByProperty(layout.filters, 'dimension');
 
1122
 
 
1123
                                        for (var i = 0, dim, items, xDim; i < layout.filters.length; i++) {
 
1124
                                                dim = layout.filters[i];
 
1125
                                                items = dim.items;
 
1126
                                                xDim = {};
 
1127
 
 
1128
                                                xDim.dimension = dim.dimension;
 
1129
                                                xDim.objectName = dim.dimension;
 
1130
                                                xDim.dimensionName = dimConf.objectNameMap.hasOwnProperty(dim.dimension) ? dimConf.objectNameMap[dim.dimension].dimensionName || dim.dimension : dim.dimension;
 
1131
 
 
1132
                                                xDim.items = [];
 
1133
                                                xDim.ids = [];
 
1134
 
 
1135
                                                if (items) {
 
1136
                                                        xDim.items = items;
 
1137
 
 
1138
                                                        for (var j = 0; j < items.length; j++) {
 
1139
                                                                xDim.ids.push(items[j].id);
 
1140
                                                        }
 
1141
                                                }
 
1142
 
 
1143
                                                xLayout.filters.push(xDim);
 
1144
 
 
1145
                                                xLayout.filterDimensions.push(xDim);
 
1146
                                                xLayout.filterObjectNames.push(xDim.objectName);
 
1147
                                                xLayout.filterDimensionNames.push(dimConf.objectNameMap.hasOwnProperty(xDim.objectName) ? dimConf.objectNameMap[xDim.objectName].dimensionName || xDim.objectName : xDim.objectName);
 
1148
 
 
1149
                                                xLayout.objectNameDimensionsMap[xDim.objectName] = xDim;
 
1150
                                                xLayout.objectNameItemsMap[xDim.objectName] = xDim.items;
 
1151
                                                xLayout.objectNameIdsMap[xDim.objectName] = xDim.ids;
 
1152
                                        }
 
1153
                                }
 
1154
 
 
1155
                                // legend set
 
1156
                                xLayout.legendSet = layout.legendSet ? init.idLegendSetMap[layout.legendSet.id] : null;
 
1157
 
 
1158
                                if (layout.legendSet && layout.legendSet.mapLegends) {
 
1159
                                        xLayout.legendSet = init.idLegendSetMap[layout.legendSet.id];
 
1160
                                        support.prototype.array.sort(xLayout.legendSet.mapLegends, 'ASC', 'startValue');
 
1161
                                }
 
1162
 
 
1163
                                // unique dimension names
 
1164
                                xLayout.axisDimensionNames = Ext.Array.unique(xLayout.axisDimensionNames);
 
1165
                                xLayout.filterDimensionNames = Ext.Array.unique(xLayout.filterDimensionNames);
 
1166
 
 
1167
                                xLayout.columnDimensionNames = Ext.Array.unique(xLayout.columnDimensionNames);
 
1168
                                xLayout.rowDimensionNames = Ext.Array.unique(xLayout.rowDimensionNames);
 
1169
                                xLayout.filterDimensionNames = Ext.Array.unique(xLayout.filterDimensionNames);
 
1170
 
 
1171
                                        // for param string
 
1172
                                xLayout.sortedAxisDimensionNames = Ext.clone(xLayout.axisDimensionNames).sort();
 
1173
                                xLayout.sortedFilterDimensions = service.layout.sortDimensionArray(Ext.clone(xLayout.filterDimensions));
 
1174
 
 
1175
                                // all
 
1176
                                xLayout.dimensions = [].concat(xLayout.axisDimensions, xLayout.filterDimensions);
 
1177
                                xLayout.objectNames = [].concat(xLayout.axisObjectNames, xLayout.filterObjectNames);
 
1178
                                xLayout.dimensionNames = [].concat(xLayout.axisDimensionNames, xLayout.filterDimensionNames);
 
1179
 
 
1180
                                // dimension name maps
 
1181
                                for (var i = 0, dimName; i < xLayout.dimensionNames.length; i++) {
 
1182
                                        dimName = xLayout.dimensionNames[i];
 
1183
 
 
1184
                                        xLayout.dimensionNameDimensionsMap[dimName] = [];
 
1185
                                        xLayout.dimensionNameItemsMap[dimName] = [];
 
1186
                                        xLayout.dimensionNameIdsMap[dimName] = [];
 
1187
                                }
 
1188
 
 
1189
                                for (var i = 0, xDim; i < xLayout.dimensions.length; i++) {
 
1190
                                        xDim = xLayout.dimensions[i];
 
1191
 
 
1192
                                        xLayout.dimensionNameDimensionsMap[xDim.dimensionName].push(xDim);
 
1193
                                        xLayout.dimensionNameItemsMap[xDim.dimensionName] = xLayout.dimensionNameItemsMap[xDim.dimensionName].concat(xDim.items);
 
1194
                                        xLayout.dimensionNameIdsMap[xDim.dimensionName] = xLayout.dimensionNameIdsMap[xDim.dimensionName].concat(xDim.ids);
 
1195
                                }
 
1196
 
 
1197
                                        // for param string
 
1198
                                for (var key in xLayout.dimensionNameIdsMap) {
 
1199
                                        if (xLayout.dimensionNameIdsMap.hasOwnProperty(key)) {
 
1200
                                                xLayout.dimensionNameSortedIdsMap[key] = Ext.clone(xLayout.dimensionNameIdsMap[key]).sort();
 
1201
                                        }
 
1202
                                }
 
1203
 
 
1204
                                // Uuid
 
1205
                                xLayout.tableUuid = init.el + '_' + Ext.data.IdGenerator.get('uuid').generate();
 
1206
 
 
1207
                                return xLayout;
 
1208
                        };
 
1209
 
 
1210
                        service.layout.getSyncronizedXLayout = function(xLayout, response) {
 
1211
                                var dimensions = Ext.Array.clean([].concat(xLayout.columns || [], xLayout.rows || [], xLayout.filters || [])),
 
1212
                                        xOuDimension = xLayout.objectNameDimensionsMap[dimConf.organisationUnit.objectName],
 
1213
                                        isUserOrgunit = xOuDimension && Ext.Array.contains(xOuDimension.ids, 'USER_ORGUNIT'),
 
1214
                                        isUserOrgunitChildren = xOuDimension && Ext.Array.contains(xOuDimension.ids, 'USER_ORGUNIT_CHILDREN'),
 
1215
                                        isUserOrgunitGrandChildren = xOuDimension && Ext.Array.contains(xOuDimension.ids, 'USER_ORGUNIT_GRANDCHILDREN'),
 
1216
                                        isLevel = function() {
 
1217
                                                if (xOuDimension && Ext.isArray(xOuDimension.ids)) {
 
1218
                                                        for (var i = 0; i < xOuDimension.ids.length; i++) {
 
1219
                                                                if (xOuDimension.ids[i].substr(0,5) === 'LEVEL') {
 
1220
                                                                        return true;
 
1221
                                                                }
 
1222
                                                        }
 
1223
                                                }
 
1224
 
 
1225
                                                return false;
 
1226
                                        }(),
 
1227
                                        isGroup = function() {
 
1228
                                                if (xOuDimension && Ext.isArray(xOuDimension.ids)) {
 
1229
                                                        for (var i = 0; i < xOuDimension.ids.length; i++) {
 
1230
                                                                if (xOuDimension.ids[i].substr(0,8) === 'OU_GROUP') {
 
1231
                                                                        return true;
 
1232
                                                                }
 
1233
                                                        }
 
1234
                                                }
 
1235
 
 
1236
                                                return false;
 
1237
                                        }(),
 
1238
                                        ou = dimConf.organisationUnit.objectName,
 
1239
                                        layout;
 
1240
 
 
1241
                                // Set items from init/metaData/xLayout
 
1242
                                for (var i = 0, dim, metaDataDim, items; i < dimensions.length; i++) {
 
1243
                                        dim = dimensions[i];
 
1244
                                        dim.items = [];
 
1245
                                        metaDataDim = response.metaData[dim.objectName];
 
1246
 
 
1247
                                        // If ou and children
 
1248
                                        if (dim.dimensionName === ou) {
 
1249
                                                if (isUserOrgunit || isUserOrgunitChildren || isUserOrgunitGrandChildren) {
 
1250
                                                        var userOu,
 
1251
                                                                userOuc,
 
1252
                                                                userOugc;
 
1253
 
 
1254
                                                        if (init.user && isUserOrgunit) {
 
1255
                                                                userOu = [];
 
1256
 
 
1257
                                                                for (var j = 0; j < init.user.ou.length; j++) {
 
1258
                                                                        userOu.push({
 
1259
                                                                                id: init.user.ou[j],
 
1260
                                                                                name: response.metaData.names[init.user.ou[j]]
 
1261
                                                                        });
 
1262
                                                                }
 
1263
                                                        }
 
1264
                                                        if (init.user && init.user.ouc && isUserOrgunitChildren) {
 
1265
                                                                userOuc = [];
 
1266
 
 
1267
                                                                for (var j = 0; j < init.user.ouc.length; j++) {
 
1268
                                                                        userOuc.push({
 
1269
                                                                                id: init.user.ouc[j],
 
1270
                                                                                name: response.metaData.names[init.user.ouc[j]]
 
1271
                                                                        });
 
1272
                                                                }
 
1273
 
 
1274
                                                                support.prototype.array.sort(userOuc);
 
1275
                                                        }
 
1276
                                                        if (init.user && init.user.ouc && isUserOrgunitGrandChildren) {
 
1277
                                                                var userOuOuc = [].concat(init.user.ou, init.user.ouc),
 
1278
                                                                        responseOu = response.metaData[ou];
 
1279
 
 
1280
                                                                userOugc = [];
 
1281
 
 
1282
                                                                for (var j = 0, id; j < responseOu.length; j++) {
 
1283
                                                                        id = responseOu[j];
 
1284
 
 
1285
                                                                        if (!Ext.Array.contains(userOuOuc, id)) {
 
1286
                                                                                userOugc.push({
 
1287
                                                                                        id: id,
 
1288
                                                                                        name: response.metaData.names[id]
 
1289
                                                                                });
 
1290
                                                                        }
 
1291
                                                                }
 
1292
 
 
1293
                                                                support.prototype.array.sort(userOugc);
 
1294
                                                        }
 
1295
 
 
1296
                                                        dim.items = [].concat(userOu || [], userOuc || [], userOugc || []);
 
1297
                                                }
 
1298
                                                else if (isLevel || isGroup) {
 
1299
                                                                for (var j = 0, responseOu = response.metaData[ou], id; j < responseOu.length; j++) {
 
1300
                                                                        id = responseOu[j];
 
1301
 
 
1302
                                                                        dim.items.push({
 
1303
                                                                                id: id,
 
1304
                                                                                name: response.metaData.names[id]
 
1305
                                                                        });
 
1306
                                                                }
 
1307
 
 
1308
                                                                support.prototype.array.sort(dim.items);
 
1309
                                                        }
 
1310
                                                        else {
 
1311
                                                                dim.items = Ext.clone(xLayout.dimensionNameItemsMap[dim.dimensionName]);
 
1312
                                                        }
 
1313
                                        }
 
1314
                                        else {
 
1315
                                                // Items: get ids from metadata -> items
 
1316
                                                if (Ext.isArray(metaDataDim) && metaDataDim.length) {
 
1317
                                                        var ids = Ext.clone(response.metaData[dim.dimensionName]);
 
1318
                                                        for (var j = 0; j < ids.length; j++) {
 
1319
                                                                dim.items.push({
 
1320
                                                                        id: ids[j],
 
1321
                                                                        name: response.metaData.names[ids[j]]
 
1322
                                                                });
 
1323
                                                        }
 
1324
                                                }
 
1325
                                                // Items: get items from xLayout
 
1326
                                                else {
 
1327
                                                        dim.items = Ext.clone(xLayout.objectNameItemsMap[dim.objectName]);
 
1328
                                                }
 
1329
                                        }
 
1330
                                }
 
1331
 
 
1332
                                // Re-layout
 
1333
                                layout = api.layout.Layout(xLayout);
 
1334
 
 
1335
                                if (layout) {
 
1336
                                        dimensions = Ext.Array.clean([].concat(layout.columns || [], layout.rows || [], layout.filters || []));
 
1337
 
 
1338
                                        for (var i = 0, idNameMap = response.metaData.names, dimItems; i < dimensions.length; i++) {
 
1339
                                                dimItems = dimensions[i].items;
 
1340
 
 
1341
                                                if (Ext.isArray(dimItems) && dimItems.length) {
 
1342
                                                        for (var j = 0, item; j < dimItems.length; j++) {
 
1343
                                                                item = dimItems[j];
 
1344
 
 
1345
                                                                if (Ext.isObject(item) && Ext.isString(idNameMap[item.id]) && !Ext.isString(item.name)) {
 
1346
                                                                        item.name = idNameMap[item.id] || '';
 
1347
                                                                }
 
1348
                                                        }
 
1349
                                                }
 
1350
                                        }
 
1351
 
 
1352
                                        return service.layout.getExtendedLayout(layout);
 
1353
                                }
 
1354
 
 
1355
                                return null;
 
1356
                        };
 
1357
 
 
1358
                        service.layout.layout2plugin = function(layout, el) {
 
1359
                                var layout = Ext.clone(layout),
 
1360
                                        dimensions = Ext.Array.clean([].concat(layout.columns || [], layout.rows || [], layout.filters || []));
 
1361
 
 
1362
                                layout.url = init.contextPath;
 
1363
 
 
1364
                                if (el) {
 
1365
                                        layout.el = el;
 
1366
                                }
 
1367
 
 
1368
                                if (Ext.isString(layout.id)) {
 
1369
                                        return {id: layout.id};
 
1370
                                }
 
1371
 
 
1372
                                for (var i = 0, dimension, item; i < dimensions.length; i++) {
 
1373
                                        dimension = dimensions[i];
 
1374
 
 
1375
                                        delete dimension.id;
 
1376
                                        delete dimension.ids;
 
1377
                                        delete dimension.type;
 
1378
                                        delete dimension.dimensionName;
 
1379
                                        delete dimension.objectName;
 
1380
 
 
1381
                                        for (var j = 0, item; j < dimension.items.length; j++) {
 
1382
                                                item = dimension.items[j];
 
1383
 
 
1384
                                                delete item.name;
 
1385
                                                delete item.code;
 
1386
                                                delete item.created;
 
1387
                                                delete item.lastUpdated;
 
1388
                                                delete item.value;
 
1389
                                        }
 
1390
                                }
 
1391
 
 
1392
                                if (!layout.hideEmptyRows) {
 
1393
                                        delete layout.hideEmptyRows;
 
1394
                                }
 
1395
 
 
1396
                                if (!layout.showTrendLine) {
 
1397
                                        delete layout.showTrendLine;
 
1398
                                }
 
1399
 
 
1400
                                if (!layout.targetLineValue) {
 
1401
                                        delete layout.targetLineValue;
 
1402
                                }
 
1403
 
 
1404
                                if (!layout.targetLineTitle) {
 
1405
                                        delete layout.targetLineTitle;
 
1406
                                }
 
1407
 
 
1408
                                if (!layout.baseLineValue) {
 
1409
                                        delete layout.baseLineValue;
 
1410
                                }
 
1411
 
 
1412
                                if (!layout.baseLineTitle) {
 
1413
                                        delete layout.baseLineTitle;
 
1414
                                }
 
1415
 
 
1416
                                if (!layout.hideLegend) {
 
1417
                                        delete layout.hideLegend;
 
1418
                                }
 
1419
 
 
1420
                                if (!layout.hideTitle) {
 
1421
                                        delete layout.hideTitle;
 
1422
                                }
 
1423
 
 
1424
                                if (!layout.title) {
 
1425
                                        delete layout.title;
 
1426
                                }
 
1427
 
 
1428
                                if (!layout.domainAxisTitle) {
 
1429
                                        delete layout.domainAxisTitle;
 
1430
                                }
 
1431
 
 
1432
                                if (!layout.rangeAxisTitle) {
 
1433
                                        delete layout.rangeAxisTitle;
 
1434
                                }
 
1435
 
 
1436
                                if (!layout.rangeAxisMaxValue) {
 
1437
                                        delete layout.rangeAxisMaxValue;
 
1438
                                }
 
1439
 
 
1440
                                if (!layout.rangeAxisMinValue) {
 
1441
                                        delete layout.rangeAxisMinValue;
 
1442
                                }
 
1443
 
 
1444
                                if (!layout.rangeAxisSteps) {
 
1445
                                        delete layout.rangeAxisSteps;
 
1446
                                }
 
1447
 
 
1448
                                if (!layout.rangeAxisDecimals) {
 
1449
                                        delete layout.rangeAxisDecimals;
 
1450
                                }
 
1451
 
 
1452
                if (!layout.sorting) {
 
1453
                    delete layout.sorting;
 
1454
                }
 
1455
 
 
1456
                                if (!layout.legend) {
 
1457
                                        delete layout.legend;
 
1458
                                }
 
1459
 
 
1460
                // default true
 
1461
 
 
1462
                                if (layout.showValues) {
 
1463
                                        delete layout.showValues;
 
1464
                                }
 
1465
 
 
1466
                                delete layout.parentGraphMap;
 
1467
                                delete layout.reportingPeriod;
 
1468
                                delete layout.organisationUnit;
 
1469
                                delete layout.parentOrganisationUnit;
 
1470
                                delete layout.regression;
 
1471
                                delete layout.cumulative;
 
1472
                                delete layout.topLimit;
 
1473
 
 
1474
                                return layout;
 
1475
                        };
 
1476
 
 
1477
                        service.layout.analytical2layout = function(analytical) {
 
1478
                                var layoutConfig = Ext.clone(analytical),
 
1479
                                        co = dimConf.category.objectName;
 
1480
 
 
1481
                                analytical = Ext.clone(analytical);
 
1482
 
 
1483
                                layoutConfig.columns = [];
 
1484
                                layoutConfig.rows = [];
 
1485
                                layoutConfig.filters = layoutConfig.filters || [];
 
1486
 
 
1487
                                // Series
 
1488
                                if (Ext.isArray(analytical.columns) && analytical.columns.length) {
 
1489
                                        analytical.columns.reverse();
 
1490
 
 
1491
                                        for (var i = 0, dim; i < analytical.columns.length; i++) {
 
1492
                                                dim = analytical.columns[i];
 
1493
 
 
1494
                                                if (dim.dimension === co) {
 
1495
                                                        continue;
 
1496
                                                }
 
1497
 
 
1498
                                                if (!layoutConfig.columns.length) {
 
1499
                                                        layoutConfig.columns.push(dim);
 
1500
                                                }
 
1501
                                                else {
 
1502
 
 
1503
                                                        // indicators cannot be set as filter
 
1504
                                                        if (dim.dimension === dimConf.indicator.objectName) {
 
1505
                                                                layoutConfig.filters.push(layoutConfig.columns.pop());
 
1506
                                                                layoutConfig.columns = [dim];
 
1507
                                                        }
 
1508
                                                        else {
 
1509
                                                                layoutConfig.filters.push(dim);
 
1510
                                                        }
 
1511
                                                }
 
1512
                                        }
 
1513
                                }
 
1514
 
 
1515
                                // Rows
 
1516
                                if (Ext.isArray(analytical.rows) && analytical.rows.length) {
 
1517
                                        analytical.rows.reverse();
 
1518
 
 
1519
                                        for (var i = 0, dim; i < analytical.rows.length; i++) {
 
1520
                                                dim = analytical.rows[i];
 
1521
 
 
1522
                                                if (dim.dimension === co) {
 
1523
                                                        continue;
 
1524
                                                }
 
1525
 
 
1526
                                                if (!layoutConfig.rows.length) {
 
1527
                                                        layoutConfig.rows.push(dim);
 
1528
                                                }
 
1529
                                                else {
 
1530
 
 
1531
                                                        // indicators cannot be set as filter
 
1532
                                                        if (dim.dimension === dimConf.indicator.objectName) {
 
1533
                                                                layoutConfig.filters.push(layoutConfig.rows.pop());
 
1534
                                                                layoutConfig.rows = [dim];
 
1535
                                                        }
 
1536
                                                        else {
 
1537
                                                                layoutConfig.filters.push(dim);
 
1538
                                                        }
 
1539
                                                }
 
1540
                                        }
 
1541
                                }
 
1542
 
 
1543
                                return layoutConfig;
 
1544
                        };
 
1545
 
 
1546
                        // response
 
1547
                        service.response = {};
 
1548
 
 
1549
                        service.response.getExtendedResponse = function(xLayout, response) {
 
1550
                                var ids = [];
 
1551
 
 
1552
                                response.nameHeaderMap = {};
 
1553
                                response.idValueMap = {};
 
1554
 
 
1555
                                // extend headers
 
1556
                                (function() {
 
1557
 
 
1558
                                        // extend headers: index, ids, size
 
1559
                                        for (var i = 0, header; i < response.headers.length; i++) {
 
1560
                                                header = response.headers[i];
 
1561
 
 
1562
                                                // index
 
1563
                                                header.index = i;
 
1564
 
 
1565
                                                if (header.meta) {
 
1566
 
 
1567
                                                        // ids
 
1568
                                                        header.ids = Ext.clone(xLayout.dimensionNameIdsMap[header.name]) || [];
 
1569
 
 
1570
                                                        // size
 
1571
                                                        header.size = header.ids.length;
 
1572
 
 
1573
                                                        // collect ids, used by extendMetaData
 
1574
                                                        ids = ids.concat(header.ids);
 
1575
                                                }
 
1576
                                        }
 
1577
 
 
1578
                                        // nameHeaderMap (headerName: header)
 
1579
                                        for (var i = 0, header; i < response.headers.length; i++) {
 
1580
                                                header = response.headers[i];
 
1581
 
 
1582
                                                response.nameHeaderMap[header.name] = header;
 
1583
                                        }
 
1584
                                }());
 
1585
 
 
1586
                                // extend metadata
 
1587
                                (function() {
 
1588
                                        for (var i = 0, id, splitId ; i < ids.length; i++) {
 
1589
                                                id = ids[i];
 
1590
 
 
1591
                                                if (id.indexOf('#') !== -1) {
 
1592
                                                        splitId = id.split('#');
 
1593
                                                        response.metaData.names[id] = response.metaData.names[splitId[0]] + ' ' + response.metaData.names[splitId[1]];
 
1594
                                                }
 
1595
                                        }
 
1596
                                }());
 
1597
 
 
1598
                                // create value id map
 
1599
                                (function() {
 
1600
                                        var valueHeaderIndex = response.nameHeaderMap[conf.finals.dimension.value.value].index,
 
1601
                                                coHeader = response.nameHeaderMap[conf.finals.dimension.category.dimensionName],
 
1602
                                                dx = dimConf.data.dimensionName,
 
1603
                                                co = dimConf.category.dimensionName,
 
1604
                                                axisDimensionNames = xLayout.axisDimensionNames,
 
1605
                                                idIndexOrder = [];
 
1606
 
 
1607
                                        // idIndexOrder
 
1608
                                        for (var i = 0; i < axisDimensionNames.length; i++) {
 
1609
                                                idIndexOrder.push(response.nameHeaderMap[axisDimensionNames[i]].index);
 
1610
 
 
1611
                                                // If co exists in response and is not added in layout, add co after dx
 
1612
                                                if (coHeader && !Ext.Array.contains(axisDimensionNames, co) && axisDimensionNames[i] === dx) {
 
1613
                                                        idIndexOrder.push(coHeader.index);
 
1614
                                                }
 
1615
                                        }
 
1616
 
 
1617
                                        // idValueMap
 
1618
                                        for (var i = 0, row, id; i < response.rows.length; i++) {
 
1619
                                                row = response.rows[i];
 
1620
                                                id = '';
 
1621
 
 
1622
                                                for (var j = 0; j < idIndexOrder.length; j++) {
 
1623
                                                        id += row[idIndexOrder[j]];
 
1624
                                                }
 
1625
 
 
1626
                                                response.idValueMap[id] = row[valueHeaderIndex];
 
1627
                                        }
 
1628
                                }());
 
1629
 
 
1630
                                return response;
 
1631
                        };
 
1632
 
 
1633
            // legend set
 
1634
            service.mapLegend = {};
 
1635
 
 
1636
            service.mapLegend.getColorByValue = function(legendSet, value) {
 
1637
                var color;
 
1638
 
 
1639
                if (!(legendSet && value)) {
 
1640
                    return;
 
1641
                }
 
1642
 
 
1643
                for (var i = 0, legend; i < legendSet.mapLegends.length; i++) {
 
1644
                    legend = legendSet.mapLegends[i];
 
1645
 
 
1646
                    if (value >= parseFloat(legend.startValue) && value < parseFloat(legend.endValue)) {
 
1647
                        return legend.color;
 
1648
                    }
 
1649
                }
 
1650
 
 
1651
                return;
 
1652
            };
 
1653
                }());
 
1654
 
 
1655
                // web
 
1656
                (function() {
 
1657
 
 
1658
                        // mask
 
1659
                        web.mask = {};
 
1660
 
 
1661
                        web.mask.show = function(component, message) {
 
1662
                if (init.skipMask) {
 
1663
                    return;
 
1664
                }
 
1665
 
 
1666
                                if (!Ext.isObject(component)) {
 
1667
                                        console.log('support.gui.mask.show: component not an object');
 
1668
                                        return null;
 
1669
                                }
 
1670
 
 
1671
                                message = message || 'Loading..';
 
1672
 
 
1673
                                if (component.mask) {
 
1674
                                        component.mask.destroy();
 
1675
                                        component.mask = null;
 
1676
                                }
 
1677
 
 
1678
                                component.mask = new Ext.create('Ext.LoadMask', component, {
 
1679
                                        shadow: false,
 
1680
                                        message: message,
 
1681
                                        style: 'box-shadow:0',
 
1682
                                        bodyStyle: 'box-shadow:0'
 
1683
                                });
 
1684
 
 
1685
                                component.mask.show();
 
1686
                        };
 
1687
 
 
1688
                        web.mask.hide = function(component) {
 
1689
                if (init.skipMask) {
 
1690
                    return;
 
1691
                }
 
1692
 
 
1693
                                if (!Ext.isObject(component)) {
 
1694
                                        console.log('support.gui.mask.hide: component not an object');
 
1695
                                        return null;
 
1696
                                }
 
1697
 
 
1698
                                if (component.mask) {
 
1699
                                        component.mask.destroy();
 
1700
                                        component.mask = null;
 
1701
                                }
 
1702
                        };
 
1703
 
 
1704
                        // message
 
1705
                        web.message = {};
 
1706
 
 
1707
                        web.message.alert = function(message) {
 
1708
                                console.log(message);
 
1709
                        };
 
1710
 
 
1711
                        // analytics
 
1712
                        web.analytics = {};
 
1713
 
 
1714
                        web.analytics.getParamString = function(xLayout, isSorted) {
 
1715
                var axisDimensionNames = isSorted ? xLayout.sortedAxisDimensionNames : xLayout.axisDimensionNames,
 
1716
                    filterDimensions = isSorted ? xLayout.sortedFilterDimensions : xLayout.filterDimensions,
 
1717
                    dimensionNameIdsMap = isSorted ? xLayout.dimensionNameSortedIdsMap : xLayout.dimensionNameIdsMap,
 
1718
                    paramString = '?',
 
1719
                    addCategoryDimension = false,
 
1720
                    map = xLayout.dimensionNameItemsMap,
 
1721
                    dx = dimConf.indicator.dimensionName;
 
1722
 
 
1723
                for (var i = 0, dimName, items; i < axisDimensionNames.length; i++) {
 
1724
                    dimName = axisDimensionNames[i];
 
1725
 
 
1726
                    paramString += 'dimension=' + dimName;
 
1727
 
 
1728
                    items = Ext.clone(dimensionNameIdsMap[dimName]);
 
1729
 
 
1730
                    if (dimName === dx) {
 
1731
                        for (var j = 0, index; j < items.length; j++) {
 
1732
                            index = items[j].indexOf('#');
 
1733
 
 
1734
                            if (index > 0) {
 
1735
                                addCategoryDimension = true;
 
1736
                                items[j] = items[j].substr(0, index);
 
1737
                            }
 
1738
                        }
 
1739
 
 
1740
                        items = Ext.Array.unique(items);
 
1741
                    }
 
1742
 
 
1743
                    if (dimName !== dimConf.category.dimensionName) {
 
1744
                        paramString += ':' + items.join(';');
 
1745
                    }
 
1746
 
 
1747
                    if (i < (axisDimensionNames.length - 1)) {
 
1748
                        paramString += '&';
 
1749
                    }
 
1750
                }
 
1751
 
 
1752
                if (addCategoryDimension) {
 
1753
                    paramString += '&dimension=' + conf.finals.dimension.category.dimensionName;
 
1754
                }
 
1755
 
 
1756
                if (Ext.isArray(filterDimensions) && filterDimensions.length) {
 
1757
                    for (var i = 0, dim; i < filterDimensions.length; i++) {
 
1758
                        dim = filterDimensions[i];
 
1759
 
 
1760
                        paramString += '&filter=' + dim.dimensionName + ':' + dim.ids.join(';');
 
1761
                    }
 
1762
                }
 
1763
 
 
1764
                // display property
 
1765
                paramString += '&displayProperty=' + init.userAccount.settings.keyAnalysisDisplayProperty.toUpperCase();
 
1766
 
 
1767
                return paramString;
 
1768
            };
 
1769
 
 
1770
                        web.analytics.validateUrl = function(url) {
 
1771
                                var msg;
 
1772
 
 
1773
                if (Ext.isIE) {
 
1774
                    msg = 'Too many items selected (url has ' + url.length + ' characters). Internet Explorer accepts maximum 2048 characters.';
 
1775
                }
 
1776
                else {
 
1777
                                        var len = url.length > 8000 ? '8000' : (url.length > 4000 ? '4000' : '2000');
 
1778
                                        msg = 'Too many items selected (url has ' + url.length + ' characters). Please reduce to less than ' + len + ' characters.';
 
1779
                }
 
1780
 
 
1781
                msg += '\n\n' + 'Hint: A good way to reduce the number of items is to use relative periods and level/group organisation unit selection modes.';
 
1782
 
 
1783
                alert(msg);
 
1784
                        };
 
1785
 
 
1786
                        // chart
 
1787
                        web.chart = {};
 
1788
 
 
1789
                        web.chart.createChart = function(ns, legendSet) {
 
1790
                var xLayout = ns.app.xLayout,
 
1791
                    xResponse = ns.app.xResponse,
 
1792
                    columnIds = xLayout.columnDimensionNames[0] ? xLayout.dimensionNameIdsMap[xLayout.columnDimensionNames[0]] : [],
 
1793
                    failSafeColumnIds = [],
 
1794
                    failSafeColumnIdMap = {},
 
1795
                    createFailSafeIds = function() {
 
1796
                        for (var i = 0, uuid; i < columnIds.length; i++) {
 
1797
                            uuid = Ext.data.IdGenerator.get('uuid').generate();
 
1798
 
 
1799
                            failSafeColumnIds.push(uuid);
 
1800
                            failSafeColumnIdMap[uuid] = columnIds[i];
 
1801
 
 
1802
                            xResponse.metaData.names[uuid] = xResponse.metaData.names[columnIds[i]];
 
1803
                        }
 
1804
                    }(),
 
1805
 
 
1806
                    // row ids
 
1807
                    rowIds = xLayout.rowDimensionNames[0] ? xLayout.dimensionNameIdsMap[xLayout.rowDimensionNames[0]] : [],
 
1808
 
 
1809
                    // filter ids
 
1810
                    filterIds = function() {
 
1811
                        var ids = [];
 
1812
 
 
1813
                        if (xLayout.filters) {
 
1814
                            for (var i = 0; i < xLayout.filters.length; i++) {
 
1815
                                ids = ids.concat(xLayout.filters[i].ids || []);
 
1816
                            }
 
1817
                        }
 
1818
 
 
1819
                        return ids;
 
1820
                    }(),
 
1821
 
 
1822
                    // totals
 
1823
                    dataTotalKey = Ext.data.IdGenerator.get('uuid').generate(),
 
1824
                    addDataTotals = function(data, ids) {
 
1825
                        for (var i = 0, obj, total; i < data.length; i++) {
 
1826
                            obj = data[i];
 
1827
                            total = 0;
 
1828
 
 
1829
                            for (var j = 0; j < ids.length; j++) {
 
1830
                                total += parseFloat(obj[ids[j]]);
 
1831
                                obj[dataTotalKey] = total;
 
1832
                            }
 
1833
                        }
 
1834
                    },
 
1835
 
 
1836
                                        getSyncronizedXLayout,
 
1837
                    getExtendedResponse,
 
1838
                    validateUrl,
 
1839
 
 
1840
                    getDefaultStore,
 
1841
                    getDefaultNumericAxis,
 
1842
                    getDefaultCategoryAxis,
 
1843
                    getDefaultSeriesTitle,
 
1844
                    getDefaultSeries,
 
1845
                    getDefaultTrendLines,
 
1846
                    getDefaultTargetLine,
 
1847
                    getDefaultBaseLine,
 
1848
                    getDefaultTips,
 
1849
                    setDefaultTheme,
 
1850
                    getDefaultLegend,
 
1851
                    getDefaultChartTitle,
 
1852
                    getDefaultChartSizeHandler,
 
1853
                    getDefaultChartTitlePositionHandler,
 
1854
                    getDefaultChart,
 
1855
 
 
1856
                    generator = {};
 
1857
 
 
1858
                getDefaultStore = function(isStacked) {
 
1859
                    var data = [],
 
1860
                        trendLineFields = [],
 
1861
                        targetLineFields = [],
 
1862
                        baseLineFields = [],
 
1863
                        store;
 
1864
 
 
1865
                    // data
 
1866
                    for (var i = 0, obj, category, rowValues, isEmpty; i < rowIds.length; i++) {
 
1867
                        obj = {};
 
1868
                        category = rowIds[i];
 
1869
                        rowValues = [];
 
1870
                        isEmpty = false;
 
1871
 
 
1872
                        obj[conf.finals.data.domain] = xResponse.metaData.names[category];
 
1873
 
 
1874
                        for (var j = 0, id, value; j < columnIds.length; j++) {
 
1875
                            id = support.prototype.str.replaceAll(columnIds[j], '#', '') + support.prototype.str.replaceAll(rowIds[i], '#', '');
 
1876
                            value = xResponse.idValueMap[id];
 
1877
                            rowValues.push(value);
 
1878
 
 
1879
                            obj[failSafeColumnIds[j]] = value ? parseFloat(value) : '0.0';
 
1880
                        }
 
1881
 
 
1882
                        isEmpty = !(Ext.Array.clean(rowValues).length);
 
1883
 
 
1884
                        if (!(isEmpty && xLayout.hideEmptyRows)) {
 
1885
                            data.push(obj);
 
1886
                        }
 
1887
                    }
 
1888
 
 
1889
                    // stacked
 
1890
                    if (isStacked) {
 
1891
                        addDataTotals(data, failSafeColumnIds);
 
1892
                    }
 
1893
 
 
1894
                    // sort order
 
1895
                    if (xLayout.sortOrder) {
 
1896
                        var sortingKey = isStacked ? dataTotalKey : failSafeColumnIds[0];
 
1897
 
 
1898
                        support.prototype.array.sort(data, xLayout.sortOrder === -1 ? 'ASC' : 'DESC', sortingKey);
 
1899
                    }
 
1900
 
 
1901
                    // trend lines
 
1902
                    if (xLayout.showTrendLine) {
 
1903
                        var regression,
 
1904
                            regressionKey;
 
1905
 
 
1906
                        if (isStacked) {
 
1907
                            regression = new SimpleRegression();
 
1908
                            regressionKey = conf.finals.data.trendLine + dataTotalKey;
 
1909
 
 
1910
                            for (var i = 0, value; i < data.length; i++) {
 
1911
                                value = data[i][dataTotalKey];
 
1912
                                regression.addData(i, parseFloat(value));
 
1913
                            }
 
1914
 
 
1915
                            for (var i = 0; i < data.length; i++) {
 
1916
                                data[i][regressionKey] = parseFloat(regression.predict(i).toFixed(1));
 
1917
                            }
 
1918
 
 
1919
                            trendLineFields.push(regressionKey);
 
1920
                            xResponse.metaData.names[regressionKey] = DV.i18n.trend + ' (Total)';
 
1921
                        }
 
1922
                        else {
 
1923
                            for (var i = 0; i < failSafeColumnIds.length; i++) {
 
1924
                                regression = new SimpleRegression();
 
1925
                                regressionKey = conf.finals.data.trendLine + failSafeColumnIds[i];
 
1926
 
 
1927
                                for (var j = 0, value; j < data.length; j++) {
 
1928
                                    value = data[j][failSafeColumnIds[i]];
 
1929
                                    regression.addData(j, parseFloat(value));
 
1930
                                }
 
1931
 
 
1932
                                for (var j = 0; j < data.length; j++) {
 
1933
                                    data[j][regressionKey] = parseFloat(regression.predict(j).toFixed(1));
 
1934
                                }
 
1935
 
 
1936
                                trendLineFields.push(regressionKey);
 
1937
                                xResponse.metaData.names[regressionKey] = DV.i18n.trend + ' (' + xResponse.metaData.names[failSafeColumnIds[i]] + ')';
 
1938
                            }
 
1939
                        }
 
1940
                    }
 
1941
 
 
1942
                    // target line
 
1943
                    if (Ext.isNumber(xLayout.targetLineValue) || Ext.isNumber(parseFloat(xLayout.targetLineValue))) {
 
1944
                        for (var i = 0; i < data.length; i++) {
 
1945
                            data[i][conf.finals.data.targetLine] = parseFloat(xLayout.targetLineValue);
 
1946
                        }
 
1947
 
 
1948
                        targetLineFields.push(conf.finals.data.targetLine);
 
1949
                    }
 
1950
 
 
1951
                    // base line
 
1952
                    if (Ext.isNumber(xLayout.baseLineValue) || Ext.isNumber(parseFloat(xLayout.baseLineValue))) {
 
1953
                        for (var i = 0; i < data.length; i++) {
 
1954
                            data[i][conf.finals.data.baseLine] = parseFloat(xLayout.baseLineValue);
 
1955
                        }
 
1956
 
 
1957
                        baseLineFields.push(conf.finals.data.baseLine);
 
1958
                    }
 
1959
 
 
1960
                    store = Ext.create('Ext.data.Store', {
 
1961
                        fields: function() {
 
1962
                            var fields = Ext.clone(failSafeColumnIds);
 
1963
                            fields.push(conf.finals.data.domain);
 
1964
                            fields = fields.concat(trendLineFields, targetLineFields, baseLineFields);
 
1965
 
 
1966
                            return fields;
 
1967
                        }(),
 
1968
                        data: data
 
1969
                    });
 
1970
 
 
1971
                    store.rangeFields = failSafeColumnIds;
 
1972
                    store.domainFields = [conf.finals.data.domain];
 
1973
                    store.trendLineFields = trendLineFields;
 
1974
                    store.targetLineFields = targetLineFields;
 
1975
                    store.baseLineFields = baseLineFields;
 
1976
                    store.numericFields = [].concat(store.rangeFields, store.trendLineFields, store.targetLineFields, store.baseLineFields);
 
1977
 
 
1978
                    store.getMaximum = function() {
 
1979
                        var maximums = [];
 
1980
 
 
1981
                        for (var i = 0; i < store.numericFields.length; i++) {
 
1982
                            maximums.push(store.max(store.numericFields[i]));
 
1983
                        }
 
1984
 
 
1985
                        return Ext.Array.max(maximums);
 
1986
                    };
 
1987
 
 
1988
                    store.getMinimum = function() {
 
1989
                        var minimums = [];
 
1990
 
 
1991
                        for (var i = 0; i < store.numericFields.length; i++) {
 
1992
                            minimums.push(store.min(store.numericFields[i]));
 
1993
                        }
 
1994
 
 
1995
                        return Ext.Array.min(minimums);
 
1996
                    };
 
1997
 
 
1998
                    store.getMaximumSum = function() {
 
1999
                        var sums = [],
 
2000
                            recordSum = 0;
 
2001
 
 
2002
                        store.each(function(record) {
 
2003
                            recordSum = 0;
 
2004
 
 
2005
                            for (var i = 0; i < store.rangeFields.length; i++) {
 
2006
                                recordSum += record.data[store.rangeFields[i]];
 
2007
                            }
 
2008
 
 
2009
                            sums.push(recordSum);
 
2010
                        });
 
2011
 
 
2012
                        return Ext.Array.max(sums);
 
2013
                    };
 
2014
 
 
2015
                    store.hasDecimals = function() {
 
2016
                        var records = store.getRange();
 
2017
 
 
2018
                        for (var i = 0; i < records.length; i++) {
 
2019
                            for (var j = 0, value; j < store.rangeFields.length; j++) {
 
2020
                                value = records[i].data[store.rangeFields[j]];
 
2021
 
 
2022
                                if (Ext.isNumber(value) && (value % 1)) {
 
2023
                                    return true;
 
2024
                                }
 
2025
                            }
 
2026
                        }
 
2027
 
 
2028
                        return false;
 
2029
                    };
 
2030
 
 
2031
                    store.getNumberOfDecimals = function() {
 
2032
                        var records = store.getRange(),
 
2033
                            values = [];
 
2034
 
 
2035
                        for (var i = 0; i < records.length; i++) {
 
2036
                            for (var j = 0, value; j < store.rangeFields.length; j++) {
 
2037
                                value = records[i].data[store.rangeFields[j]];
 
2038
 
 
2039
                                if (Ext.isNumber(value) && (value % 1)) {
 
2040
                                    value = value.toString();
 
2041
 
 
2042
                                    values.push(value.length - value.indexOf('.') - 1);
 
2043
                                }
 
2044
                            }
 
2045
                        }
 
2046
 
 
2047
                        return Ext.Array.max(values);
 
2048
                    };
 
2049
 
 
2050
                    if (DV.isDebug) {
 
2051
                        console.log("data", data);
 
2052
                        console.log("rangeFields", store.rangeFields);
 
2053
                        console.log("domainFields", store.domainFields);
 
2054
                        console.log("trendLineFields", store.trendLineFields);
 
2055
                        console.log("targetLineFields", store.targetLineFields);
 
2056
                        console.log("baseLineFields", store.baseLineFields);
 
2057
                    }
 
2058
 
 
2059
                    return store;
 
2060
                };
 
2061
 
 
2062
                getDefaultNumericAxis = function(store) {
 
2063
                    var labelFont = 'normal 11px ' + conf.chart.style.fontFamily,
 
2064
                        labelColor = 'black',
 
2065
                        labelRotation = 0,
 
2066
                        titleFont = 'bold 12px ' + conf.chart.style.fontFamily,
 
2067
                        titleColor = 'black',
 
2068
 
 
2069
                        typeConf = conf.finals.chart,
 
2070
                        minimum = store.getMinimum(),
 
2071
                        maximum,
 
2072
                        numberOfDecimals,
 
2073
                        axis;
 
2074
 
 
2075
                    getRenderer = function(numberOfDecimals) {
 
2076
                        var renderer = '0.';
 
2077
 
 
2078
                        for (var i = 0; i < numberOfDecimals; i++) {
 
2079
                            renderer += '0';
 
2080
                        }
 
2081
 
 
2082
                        return renderer;
 
2083
                    };
 
2084
 
 
2085
                    // set maximum if stacked + extra line
 
2086
                    if ((xLayout.type === typeConf.stackedcolumn || xLayout.type === typeConf.stackedbar) &&
 
2087
                        (xLayout.showTrendLine || xLayout.targetLineValue || xLayout.baseLineValue)) {
 
2088
                        var a = [store.getMaximum(), store.getMaximumSum()];
 
2089
                        maximum = Math.ceil(Ext.Array.max(a) * 1.1);
 
2090
                        maximum = Math.floor(maximum / 10) * 10;
 
2091
                    }
 
2092
 
 
2093
                    // renderer
 
2094
                    numberOfDecimals = store.getNumberOfDecimals();
 
2095
                    renderer = !!numberOfDecimals && (store.getMaximum() < 20) ? getRenderer(numberOfDecimals) : '0,0';
 
2096
 
 
2097
                    axis = {
 
2098
                        type: 'Numeric',
 
2099
                        position: 'left',
 
2100
                        fields: store.numericFields,
 
2101
                        minimum: minimum < 0 ? minimum : 0,
 
2102
                        label: {
 
2103
                            renderer: Ext.util.Format.numberRenderer(renderer),
 
2104
                            style: {},
 
2105
                            rotate: {}
 
2106
                        },
 
2107
                        labelTitle: {},
 
2108
                        grid: {
 
2109
                            odd: {
 
2110
                                opacity: 1,
 
2111
                                stroke: '#000',
 
2112
                                'stroke-width': 0.03
 
2113
                            },
 
2114
                            even: {
 
2115
                                opacity: 1,
 
2116
                                stroke: '#000',
 
2117
                                'stroke-width': 0.03
 
2118
                            }
 
2119
                        }
 
2120
                    };
 
2121
 
 
2122
                    if (maximum) {
 
2123
                        axis.maximum = maximum;
 
2124
                    }
 
2125
 
 
2126
                    if (xLayout.rangeAxisMaxValue) {
 
2127
                                                axis.maximum = xLayout.rangeAxisMaxValue;
 
2128
                                        }
 
2129
 
 
2130
                    if (xLayout.rangeAxisMinValue) {
 
2131
                                                axis.minimum = xLayout.rangeAxisMinValue;
 
2132
                                        }
 
2133
 
 
2134
                                        if (xLayout.rangeAxisSteps) {
 
2135
                                                axis.majorTickSteps = xLayout.rangeAxisSteps - 1;
 
2136
                                        }
 
2137
 
 
2138
                                        if (xLayout.rangeAxisDecimals) {
 
2139
                                                axis.label.renderer = Ext.util.Format.numberRenderer(getRenderer(xLayout.rangeAxisDecimals));
 
2140
                                        }
 
2141
 
 
2142
                    if (xLayout.rangeAxisTitle) {
 
2143
                        axis.title = xLayout.rangeAxisTitle;
 
2144
                    }
 
2145
 
 
2146
                    // style
 
2147
                    if (Ext.isObject(xLayout.rangeAxisStyle)) {
 
2148
                        var style = xLayout.rangeAxisStyle;
 
2149
 
 
2150
                        // label
 
2151
                        labelColor = style.labelColor || labelColor;
 
2152
 
 
2153
                        if (style.labelFont) {
 
2154
                            labelFont = style.labelFont;
 
2155
                        }
 
2156
                        else {
 
2157
                            labelFont = style.labelFontWeight ? style.labelFontWeight + ' ' : 'normal ';
 
2158
                            labelFont += style.labelFontSize ? parseFloat(style.labelFontSize) + 'px ' : '11px ';
 
2159
                            labelFont +=  style.labelFontFamily ? style.labelFontFamily : conf.chart.style.fontFamily;
 
2160
                        }
 
2161
 
 
2162
                        // rotation
 
2163
                        if (Ext.isNumber(parseFloat(style.labelRotation))) {
 
2164
                            labelRotation = 360 - parseFloat(style.labelRotation);
 
2165
                        }
 
2166
 
 
2167
                        // title
 
2168
                        titleColor = style.titleColor || titleColor;
 
2169
 
 
2170
                        if (style.titleFont) {
 
2171
                            titleFont = style.titleFont;
 
2172
                        }
 
2173
                        else {
 
2174
                            titleFont = style.titleFontWeight ? style.titleFontWeight + ' ' : 'bold ';
 
2175
                            titleFont += style.titleFontSize ? parseFloat(style.titleFontSize) + 'px ' : '12px ';
 
2176
                            titleFont +=  style.titleFontFamily ? style.titleFontFamily : conf.chart.style.fontFamily;
 
2177
                        }
 
2178
                    }
 
2179
 
 
2180
                    axis.label.style.fill = labelColor;
 
2181
                    axis.label.style.font = labelFont;
 
2182
                    axis.label.rotate.degrees = labelRotation;
 
2183
 
 
2184
                    axis.labelTitle.fill = titleColor;
 
2185
                    axis.labelTitle.font = titleFont;
 
2186
 
 
2187
                    return axis;
 
2188
                };
 
2189
 
 
2190
                getDefaultCategoryAxis = function(store) {
 
2191
                    var labelFont = 'normal 11px ' + conf.chart.style.fontFamily,
 
2192
                        labelColor = 'black',
 
2193
                        labelRotation = 315,
 
2194
                        titleFont = 'bold 12px ' + conf.chart.style.fontFamily,
 
2195
                        titleColor = 'black',
 
2196
 
 
2197
                        axis = {
 
2198
                            type: 'Category',
 
2199
                            position: 'bottom',
 
2200
                            fields: store.domainFields,
 
2201
                            label: {
 
2202
                                rotate: {},
 
2203
                                style: {}
 
2204
                            },
 
2205
                            labelTitle: {}
 
2206
                        };
 
2207
 
 
2208
                    if (xLayout.domainAxisTitle) {
 
2209
                        axis.title = xLayout.domainAxisTitle;
 
2210
                    }
 
2211
 
 
2212
                    // style
 
2213
                    if (Ext.isObject(xLayout.domainAxisStyle)) {
 
2214
                        var style = xLayout.domainAxisStyle;
 
2215
 
 
2216
                        // label
 
2217
                        labelColor = style.labelColor || labelColor;
 
2218
 
 
2219
                        if (style.labelFont) {
 
2220
                            labelFont = style.labelFont;
 
2221
                        }
 
2222
                        else {
 
2223
                            labelFont = style.labelFontWeight ? style.labelFontWeight + ' ' : 'normal ';
 
2224
                            labelFont += style.labelFontSize ? parseFloat(style.labelFontSize) + 'px ' : '11px ';
 
2225
                            labelFont +=  style.labelFontFamily ? style.labelFontFamily : conf.chart.style.fontFamily;
 
2226
                        }
 
2227
 
 
2228
                        // rotation
 
2229
                        if (Ext.isNumber(parseFloat(style.labelRotation))) {
 
2230
                            labelRotation = 360 - parseFloat(style.labelRotation);
 
2231
                        }
 
2232
 
 
2233
                        // title
 
2234
                        titleColor = style.titleColor || titleColor;
 
2235
 
 
2236
                        if (style.titleFont) {
 
2237
                            titleFont = style.titleFont;
 
2238
                        }
 
2239
                        else {
 
2240
                            titleFont = style.titleFontWeight ? style.titleFontWeight + ' ' : 'bold ';
 
2241
                            titleFont += style.titleFontSize ? parseFloat(style.titleFontSize) + 'px ' : '12px ';
 
2242
                            titleFont +=  style.titleFontFamily ? style.titleFontFamily : conf.chart.style.fontFamily;
 
2243
                        }
 
2244
                    }
 
2245
 
 
2246
                    axis.label.style.fill = labelColor;
 
2247
                    axis.label.style.font = labelFont;
 
2248
                    axis.label.rotate.degrees = labelRotation;
 
2249
 
 
2250
                    axis.labelTitle.fill = titleColor;
 
2251
                    axis.labelTitle.font = titleFont;
 
2252
 
 
2253
                    return axis;
 
2254
                };
 
2255
 
 
2256
                getDefaultSeriesTitle = function(store) {
 
2257
                    var a = [];
 
2258
 
 
2259
                    if (Ext.isObject(xLayout.legendStyle) && Ext.isArray(xLayout.legendStyle.labelNames)) {
 
2260
                        return xLayout.legendStyle.labelNames;
 
2261
                    }
 
2262
                    else {
 
2263
                        for (var i = 0, id, name, mxl, ids; i < store.rangeFields.length; i++) {
 
2264
                            id = failSafeColumnIdMap[store.rangeFields[i]];
 
2265
                            name = xResponse.metaData.names[id];
 
2266
 
 
2267
                            if (Ext.isString(name) && Ext.isObject(xLayout.legendStyle) && Ext.isNumber(xLayout.legendStyle.labelMaxLength)) {
 
2268
                                var mxl = parseInt(xLayout.legendStyle.labelMaxLength);
 
2269
 
 
2270
                                name = name.length > mxl ? name.substr(0, mxl) + '..' : name;
 
2271
                            }
 
2272
 
 
2273
                            a.push(name);
 
2274
                        }
 
2275
                    }
 
2276
 
 
2277
                    return a;
 
2278
                                };
 
2279
 
 
2280
                getDefaultSeries = function(store) {
 
2281
                    var main = {
 
2282
                        type: 'column',
 
2283
                        axis: 'left',
 
2284
                        xField: store.domainFields,
 
2285
                        yField: store.rangeFields,
 
2286
                        style: {
 
2287
                            opacity: 0.8,
 
2288
                            lineWidth: 3
 
2289
                        },
 
2290
                        markerConfig: {
 
2291
                            type: 'circle',
 
2292
                            radius: 4
 
2293
                        },
 
2294
                        tips: getDefaultTips(),
 
2295
                        title: getDefaultSeriesTitle(store)
 
2296
                    };
 
2297
 
 
2298
                    if (xLayout.showValues) {
 
2299
                        var labelFont = conf.chart.style.fontFamily,
 
2300
                            labelColor = 'black';
 
2301
 
 
2302
                        if (Ext.isObject(xLayout.seriesStyle)) {
 
2303
                            var style = xLayout.seriesStyle;
 
2304
 
 
2305
                            // label
 
2306
                            labelColor = style.labelColor || labelColor;
 
2307
 
 
2308
                            if (style.labelFont) {
 
2309
                                labelFont = style.labelFont;
 
2310
                            }
 
2311
                            else {
 
2312
                                labelFont = style.labelFontWeight ? style.labelFontWeight + ' ' : 'normal ';
 
2313
                                labelFont += style.labelFontSize ? parseFloat(style.labelFontSize) + 'px ' : '11px ';
 
2314
                                labelFont +=  style.labelFontFamily ? style.labelFontFamily : conf.chart.style.fontFamily;
 
2315
                            }
 
2316
                        }
 
2317
 
 
2318
                        main.label = {
 
2319
                            display: 'outside',
 
2320
                            'text-anchor': 'middle',
 
2321
                            field: store.rangeFields,
 
2322
                            font: labelFont,
 
2323
                            fill: labelColor,
 
2324
                            renderer: function(n) {
 
2325
                                return n === '0.0' ? '' : n;
 
2326
                            }
 
2327
                        };
 
2328
                    }
 
2329
 
 
2330
                    return main;
 
2331
                };
 
2332
 
 
2333
                getDefaultTrendLines = function(store, isStacked) {
 
2334
                    var a = [];
 
2335
 
 
2336
                    for (var i = 0, strokeColor; i < store.trendLineFields.length; i++) {
 
2337
                        strokeColor = isStacked ? '#000' : conf.chart.theme.dv1[i];
 
2338
 
 
2339
                        a.push({
 
2340
                            type: 'line',
 
2341
                            axis: 'left',
 
2342
                            xField: store.domainFields,
 
2343
                            yField: store.trendLineFields[i],
 
2344
                            style: {
 
2345
                                opacity: 0.8,
 
2346
                                lineWidth: 2,
 
2347
                                'stroke-dasharray': 14,
 
2348
                                stroke: strokeColor
 
2349
                            },
 
2350
                            markerConfig: {
 
2351
                                type: 'circle',
 
2352
                                radius: 0,
 
2353
                                fill: strokeColor
 
2354
                            },
 
2355
                            title: function() {
 
2356
                                var title = xResponse.metaData.names[store.trendLineFields[i]],
 
2357
                                    ls = xLayout.legendStyle;
 
2358
                                return ls && Ext.isNumber(ls.labelMaxLength) ? title.substr(0, ls.labelMaxLength) + '..' : title;
 
2359
                            }()
 
2360
                        });
 
2361
                    }
 
2362
 
 
2363
                    return a;
 
2364
                };
 
2365
 
 
2366
                getDefaultTargetLine = function(store) {
 
2367
                    return {
 
2368
                        type: 'line',
 
2369
                        axis: 'left',
 
2370
                        xField: store.domainFields,
 
2371
                        yField: store.targetLineFields,
 
2372
                        style: {
 
2373
                            opacity: 1,
 
2374
                            lineWidth: 1,
 
2375
                            'stroke-width': 1,
 
2376
                            stroke: '#000'
 
2377
                        },
 
2378
                        showMarkers: false,
 
2379
                        title: function() {
 
2380
                            var title = (Ext.isString(xLayout.targetLineTitle) ? xLayout.targetLineTitle : DV.i18n.target) + ' (' + xLayout.targetLineValue + ')',
 
2381
                                ls = xLayout.legendStyle;
 
2382
                            return ls && Ext.isNumber(ls.labelMaxLength) ? title.substr(0, ls.labelMaxLength) + '..' : title;
 
2383
                        }()
 
2384
                    };
 
2385
                };
 
2386
 
 
2387
                getDefaultBaseLine = function(store) {
 
2388
                    return {
 
2389
                        type: 'line',
 
2390
                        axis: 'left',
 
2391
                        xField: store.domainFields,
 
2392
                        yField: store.baseLineFields,
 
2393
                        style: {
 
2394
                            opacity: 1,
 
2395
                            lineWidth: 1,
 
2396
                            'stroke-width': 1,
 
2397
                            stroke: '#000'
 
2398
                        },
 
2399
                        showMarkers: false,
 
2400
                        title: function() {
 
2401
                            var title = (Ext.isString(xLayout.baseLineTitle) ? xLayout.baseLineTitle : DV.i18n.base) + ' (' + xLayout.baseLineValue + ')',
 
2402
                                ls = xLayout.legendStyle;
 
2403
                            return ls && Ext.isNumber(ls.labelMaxLength) ? title.substr(0, ls.labelMaxLength) + '..' : title;
 
2404
                        }()
 
2405
                    };
 
2406
                };
 
2407
 
 
2408
                getDefaultTips = function() {
 
2409
                    return {
 
2410
                        trackMouse: true,
 
2411
                        cls: 'dv-chart-tips',
 
2412
                        renderer: function(si, item) {
 
2413
                            if (item.value) {
 
2414
                                var value = item.value[1] === '0.0' ? '-' : item.value[1];
 
2415
                                this.update('<div style="text-align:center"><div style="font-size:17px; font-weight:bold">' + value + '</div><div style="font-size:10px">' + si.data[conf.finals.data.domain] + '</div></div>');
 
2416
                            }
 
2417
                        }
 
2418
                    };
 
2419
                };
 
2420
 
 
2421
                setDefaultTheme = function(store) {
 
2422
                    var colors = conf.chart.theme.dv1.slice(0, store.rangeFields.length);
 
2423
 
 
2424
                    Ext.chart.theme.dv1 = Ext.extend(Ext.chart.theme.Base, {
 
2425
                        constructor: function(config) {
 
2426
                            Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
 
2427
                                seriesThemes: colors,
 
2428
                                colors: colors
 
2429
                            }, config));
 
2430
                        }
 
2431
                    });
 
2432
                };
 
2433
 
 
2434
                getDefaultLegend = function(store, chartConfig) {
 
2435
                    var itemLength = 30,
 
2436
                        charLength = 6,
 
2437
                        numberOfItems = 0,
 
2438
                        numberOfChars = 0,
 
2439
                        str = '',
 
2440
                        width,
 
2441
                        isVertical = false,
 
2442
                        labelFont = '11px ' + conf.chart.style.fontFamily,
 
2443
                        position = 'top',
 
2444
                        padding = 0,
 
2445
                        positions = ['top', 'right', 'bottom', 'left'],
 
2446
                        series = chartConfig.series;
 
2447
 
 
2448
                    if (xLayout.type === conf.finals.chart.pie) {
 
2449
                        numberOfItems = store.getCount();
 
2450
                        store.each(function(r) {
 
2451
                            str += r.data[store.domainFields[0]];
 
2452
                        });
 
2453
                    }
 
2454
                    else {
 
2455
                        for (var i = 0, title; i < series.length; i++) {
 
2456
                            title = series[i].title;
 
2457
 
 
2458
                            if (Ext.isString(title)) {
 
2459
                                numberOfItems += 1;
 
2460
                                numberOfChars += title.length;
 
2461
                            }
 
2462
                            else if (Ext.isArray(title)) {
 
2463
                                numberOfItems += title.length;
 
2464
                                numberOfChars += title.toString().split(',').join('').length;
 
2465
                            }
 
2466
                        }
 
2467
                    }
 
2468
 
 
2469
                    width = (numberOfItems * itemLength) + (numberOfChars * charLength);
 
2470
 
 
2471
                    if (width > ns.app.centerRegion.getWidth() - 10) {
 
2472
                        isVertical = true;
 
2473
                        position = 'right';
 
2474
                    }
 
2475
 
 
2476
                    // style
 
2477
                    if (Ext.isObject(xLayout.legendStyle)) {
 
2478
                        var style = xLayout.legendStyle;
 
2479
 
 
2480
                        if (Ext.Array.contains(positions, style.position)) {
 
2481
                            position = style.position;
 
2482
                        }
 
2483
 
 
2484
                        if (style.labelFont) {
 
2485
                            labelFont = style.labelFont;
 
2486
                        }
 
2487
                        else {
 
2488
                            labelFont = style.labelFontWeight ? style.labelFontWeight + ' ' : 'normal ';
 
2489
                            labelFont += style.labelFontSize ? parseFloat(style.labelFontSize) + 'px ' : '11px ';
 
2490
                            labelFont +=  style.labelFontFamily ? style.labelFontFamily : conf.chart.style.fontFamily;
 
2491
                        }
 
2492
                    }
 
2493
 
 
2494
                    // padding
 
2495
                    if (position === 'right') {
 
2496
                        padding = 5;
 
2497
                    }
 
2498
 
 
2499
                    return Ext.create('Ext.chart.Legend', {
 
2500
                        position: position,
 
2501
                        isVertical: isVertical,
 
2502
                        labelFont: labelFont,
 
2503
                        boxStroke: '#ffffff',
 
2504
                        boxStrokeWidth: 0,
 
2505
                        padding: padding
 
2506
                    });
 
2507
                };
 
2508
 
 
2509
                getDefaultChartTitle = function(store) {
 
2510
                    var ids = [],
 
2511
                        text = '',
 
2512
                        titleFont,
 
2513
                        titleColor,
 
2514
                        isPie = xLayout.type === conf.finals.chart.pie,
 
2515
                        isGauge = xLayout.type === conf.finals.chart.gauge;
 
2516
 
 
2517
                    if (isPie) {
 
2518
                        ids.push(columnIds[0]);
 
2519
                    }
 
2520
                    else if (isGauge) {
 
2521
                        ids.push(columnIds[0], rowIds[0]);
 
2522
                    }
 
2523
 
 
2524
                    ids = Ext.Array.clean(ids.concat(filterIds || []));
 
2525
 
 
2526
                    if (Ext.isArray(ids) && ids.length) {
 
2527
                        for (var i = 0; i < ids.length; i++) {
 
2528
                            text += xResponse.metaData.names[ids[i]];
 
2529
                            text += i < ids.length - 1 ? ', ' : '';
 
2530
                        }
 
2531
                    }
 
2532
 
 
2533
                    if (xLayout.title) {
 
2534
                        text = xLayout.title;
 
2535
                    }
 
2536
 
 
2537
                    fontSize = (ns.app.centerRegion.getWidth() / text.length) < 11.6 ? 12 : 17;
 
2538
                    titleFont = 'normal ' + fontSize + 'px ' + conf.chart.style.fontFamily;
 
2539
                    titleColor = 'black';
 
2540
 
 
2541
                    // legend
 
2542
                    if (Ext.isObject(xLayout.legendStyle)) {
 
2543
                        var style = xLayout.legendStyle;
 
2544
 
 
2545
                        titleColor = style.titleColor || titleColor;
 
2546
 
 
2547
                        if (style.titleFont) {
 
2548
                            titleFont = style.titleFont;
 
2549
                        }
 
2550
                        else {
 
2551
                            titleFont = style.titleFontWeight ? style.titleFontWeight + ' ' : 'normal ';
 
2552
                            titleFont += style.titleFontSize ? parseFloat(style.titleFontSize) + 'px ' : (fontSize + 'px ');
 
2553
                            titleFont +=  style.titleFontFamily ? style.titleFontFamily : conf.chart.style.fontFamily;
 
2554
                        }
 
2555
                    }
 
2556
 
 
2557
                    return Ext.create('Ext.draw.Sprite', {
 
2558
                        type: 'text',
 
2559
                        text: text,
 
2560
                        font: titleFont,
 
2561
                        fill: titleColor,
 
2562
                        height: 20,
 
2563
                        y: ns.dashboard ? 11 : 20
 
2564
                    });
 
2565
                };
 
2566
 
 
2567
                getDefaultChartSizeHandler = function() {
 
2568
                    return function() {
 
2569
                                                //this.animate = false;
 
2570
                        this.setWidth(ns.app.centerRegion.getWidth() - 15);
 
2571
                        this.setHeight(ns.app.centerRegion.getHeight() - 40);
 
2572
                        //this.animate = true;
 
2573
                    };
 
2574
                };
 
2575
 
 
2576
                getDefaultChartTitlePositionHandler = function() {
 
2577
                    return function() {
 
2578
                        if (this.items) {
 
2579
                            var title = this.items[0],
 
2580
                                titleWidth = Ext.isIE ? title.el.dom.scrollWidth : title.el.getWidth(),
 
2581
                                titleXFallback = 10,
 
2582
                                legend = this.legend,
 
2583
                                legendCenterX,
 
2584
                                titleX;
 
2585
 
 
2586
                            if (this.legend.position === 'top') {
 
2587
                                legendCenterX = legend.x + (legend.width / 2);
 
2588
                                titleX = titleWidth ? legendCenterX - (titleWidth / 2) : titleXFallback;
 
2589
                            }
 
2590
                            else {
 
2591
                                var legendWidth = legend ? legend.width : 0;
 
2592
                                titleX = titleWidth ? (this.width / 2) - (titleWidth / 2) : titleXFallback;
 
2593
                            }
 
2594
 
 
2595
                            title.setAttributes({
 
2596
                                x: titleX
 
2597
                            }, true);
 
2598
                        }
 
2599
                    };
 
2600
                };
 
2601
 
 
2602
                getDefaultChart = function(config) {
 
2603
                    var chart,
 
2604
                        store = config.store || {},
 
2605
                        defaultConfig = {
 
2606
                            //animate: true,
 
2607
                            animate: false,
 
2608
                            shadow: false,
 
2609
                            insetPadding: ns.dashboard ? 23 : 35,
 
2610
                            width: ns.app.centerRegion.getWidth() - 15,
 
2611
                            height: ns.app.centerRegion.getHeight() - 40,
 
2612
                            theme: 'dv1'
 
2613
                        };
 
2614
 
 
2615
                    // legend
 
2616
                    if (!xLayout.hideLegend) {
 
2617
                        defaultConfig.legend = getDefaultLegend(store, config);
 
2618
 
 
2619
                        if (defaultConfig.legend.position === 'right') {
 
2620
                            defaultConfig.insetPadding = ns.dashboard ? 32 : 40;
 
2621
                        }
 
2622
                    }
 
2623
 
 
2624
                    // title
 
2625
                    if (!xLayout.hideTitle) {
 
2626
                        defaultConfig.items = [getDefaultChartTitle(store)];
 
2627
                    }
 
2628
                    else {
 
2629
                        defaultConfig.insetPadding = 10;
 
2630
                    }
 
2631
 
 
2632
                    Ext.apply(defaultConfig, config);
 
2633
 
 
2634
                    chart = Ext.create('Ext.chart.Chart', defaultConfig);
 
2635
 
 
2636
                    chart.setChartSize = getDefaultChartSizeHandler();
 
2637
                    chart.setTitlePosition = getDefaultChartTitlePositionHandler();
 
2638
 
 
2639
                    chart.onViewportResize = function() {
 
2640
                        chart.setChartSize();
 
2641
                        chart.redraw();
 
2642
                        chart.setTitlePosition();
 
2643
                    };
 
2644
 
 
2645
                    chart.on('afterrender', function() {
 
2646
                        chart.setTitlePosition();
 
2647
                    });
 
2648
 
 
2649
                    return chart;
 
2650
                };
 
2651
 
 
2652
                generator.column = function(isStacked) {
 
2653
                    var store = getDefaultStore(isStacked),
 
2654
                        numericAxis = getDefaultNumericAxis(store),
 
2655
                        categoryAxis = getDefaultCategoryAxis(store),
 
2656
                        axes = [numericAxis, categoryAxis],
 
2657
                        series = [getDefaultSeries(store)];
 
2658
 
 
2659
                    // options
 
2660
                    if (xLayout.showTrendLine) {
 
2661
                        series = series.concat(getDefaultTrendLines(store, isStacked));
 
2662
                    }
 
2663
 
 
2664
                    if (xLayout.targetLineValue) {
 
2665
                        series.push(getDefaultTargetLine(store));
 
2666
                    }
 
2667
 
 
2668
                    if (xLayout.baseLineValue) {
 
2669
                        series.push(getDefaultBaseLine(store));
 
2670
                    }
 
2671
 
 
2672
                    // theme
 
2673
                    setDefaultTheme(store, isStacked);
 
2674
 
 
2675
                    return getDefaultChart({
 
2676
                        store: store,
 
2677
                        axes: axes,
 
2678
                        series: series
 
2679
                    });
 
2680
                };
 
2681
 
 
2682
                generator.stackedcolumn = function() {
 
2683
                    var chart = this.column(true);
 
2684
 
 
2685
                    for (var i = 0, item; i < chart.series.items.length; i++) {
 
2686
                        item = chart.series.items[i];
 
2687
 
 
2688
                        if (item.type === conf.finals.chart.column) {
 
2689
                            item.stacked = true;
 
2690
                        }
 
2691
                    }
 
2692
 
 
2693
                    return chart;
 
2694
                };
 
2695
 
 
2696
                generator.bar = function(isStacked) {
 
2697
                    var store = getDefaultStore(isStacked),
 
2698
                        numericAxis = getDefaultNumericAxis(store),
 
2699
                        categoryAxis = getDefaultCategoryAxis(store),
 
2700
                        axes,
 
2701
                        series = getDefaultSeries(store),
 
2702
                        trendLines,
 
2703
                        targetLine,
 
2704
                        baseLine,
 
2705
                        chart;
 
2706
 
 
2707
                    // Axes
 
2708
                    numericAxis.position = 'bottom';
 
2709
                    categoryAxis.position = 'left';
 
2710
                    categoryAxis.label.rotate.degrees = 360;
 
2711
                    axes = [numericAxis, categoryAxis];
 
2712
 
 
2713
                    // Series
 
2714
                    series.type = 'bar';
 
2715
                    series.axis = 'bottom';
 
2716
 
 
2717
                    // Options
 
2718
                    if (xLayout.showValues) {
 
2719
                        series.label = {
 
2720
                            display: 'outside',
 
2721
                            'text-anchor': 'middle',
 
2722
                            field: store.rangeFields
 
2723
                        };
 
2724
                    }
 
2725
 
 
2726
                    series = [series];
 
2727
 
 
2728
                    if (xLayout.showTrendLine) {
 
2729
                        trendLines = getDefaultTrendLines(store, isStacked);
 
2730
 
 
2731
                        for (var i = 0; i < trendLines.length; i++) {
 
2732
                            trendLines[i].axis = 'bottom';
 
2733
                            trendLines[i].xField = store.trendLineFields[i];
 
2734
                            trendLines[i].yField = store.domainFields;
 
2735
                        }
 
2736
 
 
2737
                        series = series.concat(trendLines);
 
2738
                    }
 
2739
 
 
2740
                    if (xLayout.targetLineValue) {
 
2741
                        targetLine = getDefaultTargetLine(store);
 
2742
                        targetLine.axis = 'bottom';
 
2743
                        targetLine.xField = store.targetLineFields;
 
2744
                        targetLine.yField = store.domainFields;
 
2745
 
 
2746
                        series.push(targetLine);
 
2747
                    }
 
2748
 
 
2749
                    if (xLayout.baseLineValue) {
 
2750
                        baseLine = getDefaultBaseLine(store);
 
2751
                        baseLine.axis = 'bottom';
 
2752
                        baseLine.xField = store.baseLineFields;
 
2753
                        baseLine.yField = store.domainFields;
 
2754
 
 
2755
                        series.push(baseLine);
 
2756
                    }
 
2757
 
 
2758
                    // Theme
 
2759
                    setDefaultTheme(store);
 
2760
 
 
2761
                    return getDefaultChart({
 
2762
                        store: store,
 
2763
                        axes: axes,
 
2764
                        series: series
 
2765
                    });
 
2766
                };
 
2767
 
 
2768
                generator.stackedbar = function() {
 
2769
                    var chart = this.bar(true);
 
2770
 
 
2771
                    for (var i = 0, item; i < chart.series.items.length; i++) {
 
2772
                        item = chart.series.items[i];
 
2773
 
 
2774
                        if (item.type === conf.finals.chart.bar) {
 
2775
                            item.stacked = true;
 
2776
                        }
 
2777
                    }
 
2778
 
 
2779
                    return chart;
 
2780
                };
 
2781
 
 
2782
                generator.line = function() {
 
2783
                    var store = getDefaultStore(),
 
2784
                        numericAxis = getDefaultNumericAxis(store),
 
2785
                        categoryAxis = getDefaultCategoryAxis(store),
 
2786
                        axes = [numericAxis, categoryAxis],
 
2787
                        series = [],
 
2788
                        colors = conf.chart.theme.dv1.slice(0, store.rangeFields.length),
 
2789
                        seriesTitles = getDefaultSeriesTitle(store);
 
2790
 
 
2791
                    // Series
 
2792
                    for (var i = 0, line; i < store.rangeFields.length; i++) {
 
2793
                        line = {
 
2794
                            type: 'line',
 
2795
                            axis: 'left',
 
2796
                            xField: store.domainFields,
 
2797
                            yField: store.rangeFields[i],
 
2798
                            style: {
 
2799
                                opacity: 0.8,
 
2800
                                lineWidth: 3
 
2801
                            },
 
2802
                            markerConfig: {
 
2803
                                type: 'circle',
 
2804
                                radius: ns.dashboard ? 3 : 4
 
2805
                            },
 
2806
                            tips: getDefaultTips(),
 
2807
                            title: seriesTitles[i]
 
2808
                        };
 
2809
 
 
2810
                        //if (xLayout.showValues) {
 
2811
                            //line.label = {
 
2812
                                //display: 'over',
 
2813
                                //field: store.rangeFields[i]
 
2814
                            //};
 
2815
                        //}
 
2816
 
 
2817
                        series.push(line);
 
2818
                    }
 
2819
 
 
2820
                    // Options, theme colors
 
2821
                    if (xLayout.showTrendLine) {
 
2822
                        series = getDefaultTrendLines(store).concat(series);
 
2823
 
 
2824
                        colors = colors.concat(colors);
 
2825
                    }
 
2826
 
 
2827
                    if (xLayout.targetLineValue) {
 
2828
                        series.push(getDefaultTargetLine(store));
 
2829
 
 
2830
                        colors.push('#051a2e');
 
2831
                    }
 
2832
 
 
2833
                    if (xLayout.baseLineValue) {
 
2834
                        series.push(getDefaultBaseLine(store));
 
2835
 
 
2836
                        colors.push('#051a2e');
 
2837
                    }
 
2838
 
 
2839
                    // Theme
 
2840
                    Ext.chart.theme.dv1 = Ext.extend(Ext.chart.theme.Base, {
 
2841
                        constructor: function(config) {
 
2842
                            Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
 
2843
                                seriesThemes: colors,
 
2844
                                colors: colors
 
2845
                            }, config));
 
2846
                        }
 
2847
                    });
 
2848
 
 
2849
                    return getDefaultChart({
 
2850
                        store: store,
 
2851
                        axes: axes,
 
2852
                        series: series
 
2853
                    });
 
2854
                };
 
2855
 
 
2856
                generator.area = function() {
 
2857
 
 
2858
                    // NB, always true for area charts as extjs area charts cannot handle nulls
 
2859
                    xLayout.hideEmptyRows = true;
 
2860
 
 
2861
                    var store = getDefaultStore(true),
 
2862
                        numericAxis = getDefaultNumericAxis(store),
 
2863
                        categoryAxis = getDefaultCategoryAxis(store),
 
2864
                        axes = [numericAxis, categoryAxis],
 
2865
                        series = getDefaultSeries(store);
 
2866
 
 
2867
                    series.type = 'area';
 
2868
                    series.style.opacity = 0.7;
 
2869
                    series.style.lineWidth = 0;
 
2870
                    delete series.label;
 
2871
                    delete series.tips;
 
2872
                    series = [series];
 
2873
 
 
2874
                    // Options
 
2875
                    if (xLayout.showTrendLine) {
 
2876
                        series = series.concat(getDefaultTrendLines(store, true));
 
2877
                    }
 
2878
 
 
2879
                    if (xLayout.targetLineValue) {
 
2880
                        series.push(getDefaultTargetLine(store));
 
2881
                    }
 
2882
 
 
2883
                    if (xLayout.baseLineValue) {
 
2884
                        series.push(getDefaultBaseLine(store));
 
2885
                    }
 
2886
 
 
2887
                    // Theme
 
2888
                    setDefaultTheme(store);
 
2889
 
 
2890
                    return getDefaultChart({
 
2891
                        store: store,
 
2892
                        axes: axes,
 
2893
                        series: series
 
2894
                    });
 
2895
                };
 
2896
 
 
2897
                generator.pie = function() {
 
2898
                    var store = getDefaultStore(),
 
2899
                        series,
 
2900
                        colors,
 
2901
                        chart,
 
2902
                        label = {
 
2903
                            field: conf.finals.data.domain
 
2904
                        };
 
2905
 
 
2906
                    // Label
 
2907
                    if (xLayout.showValues) {
 
2908
                        var labelFont = conf.chart.style.fontFamily,
 
2909
                            labelColor;
 
2910
 
 
2911
                        if (Ext.isObject(xLayout.seriesStyle)) {
 
2912
                            var style = xLayout.seriesStyle;
 
2913
 
 
2914
                            // color
 
2915
                            labelColor = style.labelColor || labelColor;
 
2916
 
 
2917
                            if (style.labelFont) {
 
2918
                                labelFont = style.labelFont;
 
2919
                            }
 
2920
                            else {
 
2921
                                labelFont = style.labelFontWeight ? style.labelFontWeight + ' ' : 'normal ';
 
2922
                                labelFont += style.labelFontSize ? parseFloat(style.labelFontSize) + 'px ' : '11px ';
 
2923
                                labelFont +=  style.labelFontFamily ? style.labelFontFamily : conf.chart.style.fontFamily;
 
2924
                            }
 
2925
                        }
 
2926
 
 
2927
                        label.display = 'middle';
 
2928
                        label.contrast = !labelColor;
 
2929
                        label.font = labelFont;
 
2930
                        label.fill = labelColor;
 
2931
                        label.renderer = function(value) {
 
2932
                            var record = store.getAt(store.findExact(conf.finals.data.domain, value));
 
2933
                            return record.data[store.rangeFields[0]];
 
2934
                        };
 
2935
                    }
 
2936
 
 
2937
                    // Series
 
2938
                    series = [{
 
2939
                        type: 'pie',
 
2940
                        field: store.rangeFields[0],
 
2941
                        donut: 5,
 
2942
                        showInLegend: true,
 
2943
                        highlight: {
 
2944
                            segment: {
 
2945
                                margin: 5
 
2946
                            }
 
2947
                        },
 
2948
                        label: label,
 
2949
                        style: {
 
2950
                            opacity: 0.8,
 
2951
                            stroke: '#555'
 
2952
                        },
 
2953
                        tips: {
 
2954
                            trackMouse: true,
 
2955
                            cls: 'dv-chart-tips',
 
2956
                            renderer: function(item) {
 
2957
                                this.update('<div style="text-align:center"><div style="font-size:17px; font-weight:bold">' + item.data[store.rangeFields[0]] + '</div><div style="font-size:10px">' + item.data[conf.finals.data.domain] + '</div></div>');
 
2958
                            }
 
2959
                        },
 
2960
                        shadowAttributes: false
 
2961
                    }];
 
2962
 
 
2963
                    // Theme
 
2964
                    colors = conf.chart.theme.dv1.slice(0, xResponse.nameHeaderMap[xLayout.rowDimensionNames[0]].ids.length);
 
2965
 
 
2966
                    Ext.chart.theme.dv1 = Ext.extend(Ext.chart.theme.Base, {
 
2967
                        constructor: function(config) {
 
2968
                            Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
 
2969
                                seriesThemes: colors,
 
2970
                                colors: colors
 
2971
                            }, config));
 
2972
                        }
 
2973
                    });
 
2974
 
 
2975
                    // Chart
 
2976
                    chart = getDefaultChart({
 
2977
                        store: store,
 
2978
                        series: series
 
2979
                    });
 
2980
 
 
2981
                    //chart.legend.position = 'right';
 
2982
                    //chart.legend.isVertical = true;
 
2983
                    chart.insetPadding = ns.dashboard ? 25 : 40;
 
2984
 
 
2985
                    return chart;
 
2986
                };
 
2987
 
 
2988
                generator.radar = function() {
 
2989
                    var store = getDefaultStore(),
 
2990
                        axes = [],
 
2991
                        series = [],
 
2992
                        seriesTitles = getDefaultSeriesTitle(store),
 
2993
                        chart;
 
2994
 
 
2995
                    // axes
 
2996
                    axes.push({
 
2997
                        type: 'Radial',
 
2998
                        position: 'radial',
 
2999
                        label: {
 
3000
                            display: true
 
3001
                        }
 
3002
                    });
 
3003
 
 
3004
                    // series
 
3005
                    for (var i = 0, obj; i < store.rangeFields.length; i++) {
 
3006
                        obj = {
 
3007
                            showInLegend: true,
 
3008
                            type: 'radar',
 
3009
                            xField: store.domainFields,
 
3010
                            yField: store.rangeFields[i],
 
3011
                            style: {
 
3012
                                opacity: 0.5
 
3013
                            },
 
3014
                            tips: getDefaultTips(),
 
3015
                            title: seriesTitles[i]
 
3016
                        };
 
3017
 
 
3018
                        if (xLayout.showValues) {
 
3019
                            obj.label = {
 
3020
                                display: 'over',
 
3021
                                field: store.rangeFields[i]
 
3022
                            };
 
3023
                        }
 
3024
 
 
3025
                        series.push(obj);
 
3026
                    }
 
3027
 
 
3028
                    chart = getDefaultChart({
 
3029
                        store: store,
 
3030
                        axes: axes,
 
3031
                        series: series,
 
3032
                        theme: 'Category2'
 
3033
                    });
 
3034
 
 
3035
                    chart.insetPadding = ns.dashboard ? 32 : 40;
 
3036
 
 
3037
                    chart.height = ns.app.centerRegion.getHeight() - 80;
 
3038
 
 
3039
                    chart.setChartSize = function() {
 
3040
                        //this.animate = false;
 
3041
                        this.setWidth(ns.app.centerRegion.getWidth());
 
3042
                        this.setHeight(ns.app.centerRegion.getHeight() - 80);
 
3043
                        //this.animate = true;
 
3044
                    };
 
3045
 
 
3046
                    return chart;
 
3047
                };
 
3048
 
 
3049
                generator.gauge = function() {
 
3050
                    var valueColor = '#aaa',
 
3051
                        store,
 
3052
                        axis,
 
3053
                        series,
 
3054
                        legend,
 
3055
                        config,
 
3056
                        chart;
 
3057
 
 
3058
                    // overwrite items
 
3059
                    columnIds = [columnIds[0]];
 
3060
                    failSafeColumnIds = [failSafeColumnIds[0]];
 
3061
                    rowIds = [rowIds[0]];
 
3062
 
 
3063
                    // store
 
3064
                    store = getDefaultStore();
 
3065
 
 
3066
                    // axis
 
3067
                    axis = {
 
3068
                        type: 'gauge',
 
3069
                        position: 'gauge',
 
3070
                        minimum: 0,
 
3071
                        maximum: 100,
 
3072
                        steps: 10,
 
3073
                        margin: -7
 
3074
                    };
 
3075
 
 
3076
                    // series, legendset
 
3077
                    if (legendSet) {
 
3078
                        valueColor = service.mapLegend.getColorByValue(legendSet, store.getRange()[0].data[failSafeColumnIds[0]]) || valueColor;
 
3079
                    }
 
3080
 
 
3081
                    series = {
 
3082
                        type: 'gauge',
 
3083
                        field: store.rangeFields[0],
 
3084
                        //donut: 5,
 
3085
                        colorSet: [valueColor, '#ddd']
 
3086
                    };
 
3087
 
 
3088
                    chart = getDefaultChart({
 
3089
                        axes: [axis],
 
3090
                        series: [series],
 
3091
                        width: ns.app.centerRegion.getWidth(),
 
3092
                        height: ns.app.centerRegion.getHeight() * 0.6,
 
3093
                        store: store,
 
3094
                        insetPadding: ns.dashboard ? 50 : 100,
 
3095
                        theme: null,
 
3096
                        //animate: {
 
3097
                            //easing: 'elasticIn',
 
3098
                            //duration: 1000
 
3099
                        //}
 
3100
                        animate: false
 
3101
                    });
 
3102
 
 
3103
                    if (xLayout.showValues) {
 
3104
                        chart.items.push(Ext.create('Ext.draw.Sprite', {
 
3105
                            type: 'text',
 
3106
                            text: store.getRange()[0].data[failSafeColumnIds[0]],
 
3107
                            font: 'normal 26px ' + conf.chart.style.fontFamily,
 
3108
                            fill: '#111',
 
3109
                            height: 40,
 
3110
                            y:  60
 
3111
                        }));
 
3112
                    }
 
3113
 
 
3114
                    chart.setChartSize = function() {
 
3115
                                                //this.animate = false;
 
3116
                        this.setWidth(ns.app.centerRegion.getWidth());
 
3117
                        this.setHeight(ns.app.centerRegion.getHeight() * 0.6);
 
3118
                        //this.animate = true;
 
3119
                    };
 
3120
 
 
3121
                    chart.setTitlePosition = function() {
 
3122
                        if (this.items) {
 
3123
                            var title = this.items[0],
 
3124
                                subTitle = this.items[1],
 
3125
                                titleXFallback = 10;
 
3126
 
 
3127
                            if (title) {
 
3128
                                var titleWidth = Ext.isIE ? title.el.dom.scrollWidth : title.el.getWidth(),
 
3129
                                    titleX = titleWidth ? (ns.app.centerRegion.getWidth() / 2) - (titleWidth / 2) : titleXFallback;
 
3130
                                title.setAttributes({
 
3131
                                    x: titleX
 
3132
                                }, true);
 
3133
                            }
 
3134
 
 
3135
                            if (subTitle) {
 
3136
                                var subTitleWidth = Ext.isIE ? subTitle.el.dom.scrollWidth : subTitle.el.getWidth(),
 
3137
                                    subTitleX = subTitleWidth ? (ns.app.centerRegion.getWidth() / 2) - (subTitleWidth / 2) : titleXFallback;
 
3138
                                subTitle.setAttributes({
 
3139
                                    x: subTitleX
 
3140
                                }, true);
 
3141
                            }
 
3142
                        }
 
3143
                    };
 
3144
 
 
3145
                    return chart;
 
3146
                };
 
3147
 
 
3148
                // initialize
 
3149
                return generator[xLayout.type]();
 
3150
            };
 
3151
 
 
3152
        }());
 
3153
 
 
3154
                // extend init
 
3155
                (function() {
 
3156
 
 
3157
                        // sort and extend dynamic dimensions
 
3158
                        if (Ext.isArray(init.dimensions)) {
 
3159
                                support.prototype.array.sort(init.dimensions);
 
3160
 
 
3161
                                for (var i = 0, dim; i < init.dimensions.length; i++) {
 
3162
                                        dim = init.dimensions[i];
 
3163
                                        dim.dimensionName = dim.id;
 
3164
                                        dim.objectName = conf.finals.dimension.dimension.objectName;
 
3165
                                        conf.finals.dimension.objectNameMap[dim.id] = dim;
 
3166
                                }
 
3167
                        }
 
3168
 
 
3169
                        // sort ouc
 
3170
                        if (init.user && init.user.ouc) {
 
3171
                                support.prototype.array.sort(init.user.ouc);
 
3172
                        }
 
3173
                }());
 
3174
 
 
3175
                // instance
 
3176
                return {
 
3177
                        conf: conf,
 
3178
                        api: api,
 
3179
                        support: support,
 
3180
                        service: service,
 
3181
                        web: web,
 
3182
                        init: init
 
3183
                };
 
3184
    };
 
3185
 
 
3186
    // PLUGIN
 
3187
 
 
3188
        // i18n
 
3189
        DV.i18n = {
 
3190
                target: 'Target',
 
3191
                base: 'Base',
 
3192
                trend: 'Trend'
 
3193
        };
 
3194
 
 
3195
    DV.plugin = {};
 
3196
 
 
3197
        var init = {
 
3198
                        user: {}
 
3199
                },
 
3200
                configs = [],
 
3201
                isInitStarted = false,
 
3202
                isInitComplete = false,
 
3203
                getInit,
 
3204
                applyCss,
 
3205
                execute;
 
3206
 
 
3207
        getInit = function(config) {
 
3208
                var isInit = false,
 
3209
                        requests = [],
 
3210
                        callbacks = 0,
 
3211
            type = config.plugin && config.crossDomain ? 'jsonp' : 'json',
 
3212
                        fn;
 
3213
 
 
3214
        init.contextPath = config.url;
 
3215
 
 
3216
                fn = function() {
 
3217
                        if (++callbacks === requests.length) {
 
3218
                                isInitComplete = true;
 
3219
 
 
3220
                                for (var i = 0; i < configs.length; i++) {
 
3221
                                        execute(configs[i]);
 
3222
                                }
 
3223
 
 
3224
                                configs = [];
 
3225
                        }
 
3226
                };
 
3227
 
 
3228
        // user-account
 
3229
        requests.push({
 
3230
            url: init.contextPath + '/api/me/user-account.' + type,
 
3231
            disableCaching: false,
 
3232
            success: function(r) {
 
3233
                init.userAccount = r.responseText ? Ext.decode(r.responseText) : r;
 
3234
 
 
3235
                // init
 
3236
                var defaultKeyUiLocale = 'en',
 
3237
                    defaultKeyAnalysisDisplayProperty = 'name',
 
3238
                    namePropertyUrl,
 
3239
                    contextPath,
 
3240
                    keyUiLocale;
 
3241
 
 
3242
                init.userAccount.settings.keyUiLocale = init.userAccount.settings.keyUiLocale || defaultKeyUiLocale;
 
3243
                init.userAccount.settings.keyAnalysisDisplayProperty = init.userAccount.settings.keyAnalysisDisplayProperty || defaultKeyAnalysisDisplayProperty;
 
3244
 
 
3245
                // local vars
 
3246
                contextPath = init.contextPath;
 
3247
                keyUiLocale = init.userAccount.settings.keyUiLocale;
 
3248
                keyAnalysisDisplayProperty = init.userAccount.settings.keyAnalysisDisplayProperty;
 
3249
                namePropertyUrl = keyAnalysisDisplayProperty === defaultKeyAnalysisDisplayProperty ? keyAnalysisDisplayProperty : keyAnalysisDisplayProperty + '|rename(' + defaultKeyAnalysisDisplayProperty + ')';
 
3250
 
 
3251
                init.namePropertyUrl = namePropertyUrl;
 
3252
 
 
3253
                fn();
 
3254
            }
 
3255
        });
 
3256
 
 
3257
        // user orgunit
 
3258
                requests.push({
 
3259
                        url: init.contextPath + '/api/organisationUnits.' + type + '?userOnly=true&fields=id,name,children[id,name]&paging=false',
 
3260
            disableCaching: false,
 
3261
                        success: function(r) {
 
3262
                                var organisationUnits = (r.responseText ? Ext.decode(r.responseText).organisationUnits : r) || [],
 
3263
                    ou = [],
 
3264
                    ouc = [];
 
3265
 
 
3266
                if (organisationUnits.length) {
 
3267
                    for (var i = 0, org; i < organisationUnits.length; i++) {
 
3268
                        org = organisationUnits[i];
 
3269
 
 
3270
                        ou.push(org.id);
 
3271
 
 
3272
                        if (org.children) {
 
3273
                            ouc = Ext.Array.clean(ouc.concat(Ext.Array.pluck(org.children, 'id') || []));
 
3274
                        }
 
3275
                    }
 
3276
 
 
3277
                    init.user = {
 
3278
                        ou: ou,
 
3279
                        ouc: ouc
 
3280
                    }
 
3281
                }
 
3282
                else {
 
3283
                    alert('User is not assigned to any organisation units');
 
3284
                }
 
3285
 
 
3286
                fn();
 
3287
                        }
 
3288
                });
 
3289
 
 
3290
                requests.push({
 
3291
                        url: init.contextPath + '/api/dimensions.' + type + '?fields=id,name&paging=false',
 
3292
            disableCaching: false,
 
3293
                        success: function(r) {
 
3294
                                init.dimensions = r.responseText ? Ext.decode(r.responseText).dimensions : r.dimensions;
 
3295
                                fn();
 
3296
                        }
 
3297
                });
 
3298
 
 
3299
                for (var i = 0; i < requests.length; i++) {
 
3300
            if (type === 'jsonp') {
 
3301
                Ext.data.JsonP.request(requests[i]);
 
3302
            }
 
3303
            else {
 
3304
                Ext.Ajax.request(requests[i]);
 
3305
            }
 
3306
                }
 
3307
        };
 
3308
 
 
3309
        applyCss = function() {
 
3310
 
 
3311
        // chart tips css
 
3312
        var css = '.dv-chart-tips { border-radius: 2px; padding: 0px 3px 1px; border: 2px solid #000; background-color: #000; } \n';
 
3313
        css += '.dv-chart-tips .x-tip-body { background-color: #000; font-size: 13px; font-weight: normal; color: #fff; -webkit-text-stroke: 0; } \n';
 
3314
        css += '.dv-chart-tips .x-tip-body div { font-family: arial,sans-serif,ubuntu,consolas !important; } \n';
 
3315
 
 
3316
        // load mask css
 
3317
        css += '.x-mask-msg { padding: 0; border: 0 none; background-image: none; background-color: transparent; } \n';
 
3318
        css += '.x-mask-msg div { background-position: 11px center; } \n';
 
3319
        css += '.x-mask-msg .x-mask-loading { border: 0 none; \n background-color: #000; color: #fff; border-radius: 2px; padding: 12px 14px 12px 30px; opacity: 0.65; } \n';
 
3320
        css += '.x-mask { opacity: 0; } \n';
 
3321
 
 
3322
        Ext.util.CSS.createStyleSheet(css);
 
3323
    };
 
3324
 
 
3325
        execute = function(config) {
 
3326
                var validateConfig,
 
3327
            extendInstance,
 
3328
                        createViewport,
 
3329
                        initialize,
 
3330
                        ns = {
 
3331
                                core: {},
 
3332
                                app: {}
 
3333
                        };
 
3334
 
 
3335
                validateConfig = function(config) {
 
3336
                        if (!Ext.isObject(config)) {
 
3337
                                console.log('Chart configuration is not an object');
 
3338
                                return;
 
3339
                        }
 
3340
 
 
3341
                        if (!Ext.isString(config.el)) {
 
3342
                                console.log('No element id provided');
 
3343
                                return;
 
3344
                        }
 
3345
 
 
3346
                        config.id = config.id || config.uid;
 
3347
 
 
3348
                        return true;
 
3349
                };
 
3350
 
 
3351
        extendInstance = function(ns) {
 
3352
            var init = ns.core.init,
 
3353
                                api = ns.core.api,
 
3354
                conf = ns.core.conf,
 
3355
                                support = ns.core.support,
 
3356
                                service = ns.core.service,
 
3357
                                web = ns.core.web,
 
3358
                type = ns.plugin && ns.crossDomain ? 'jsonp' : 'json',
 
3359
                headerMap = {
 
3360
                    json: 'application/json',
 
3361
                    jsonp: 'application/javascript'
 
3362
                },
 
3363
                headers = {
 
3364
                    'Content-Type': headerMap[type],
 
3365
                    'Accepts': headerMap[type]
 
3366
                };
 
3367
 
 
3368
            ns.plugin = init.plugin;
 
3369
            ns.dashboard = init.dashboard;
 
3370
            ns.crossDomain = init.crossDomain;
 
3371
            ns.skipMask = init.skipMask;
 
3372
            ns.skipFade = init.skipFade;
 
3373
 
 
3374
                        init.el = config.el;
 
3375
 
 
3376
            if (!ns.skipFade && init.el && Ext.get(init.el)) {
 
3377
                Ext.get(init.el).setStyle('opacity', 0);
 
3378
            }
 
3379
 
 
3380
                        web.chart = web.chart || {};
 
3381
 
 
3382
            web.chart.loadChart = function(obj) {
 
3383
                var success,
 
3384
                    failure,
 
3385
                    config = {};
 
3386
 
 
3387
                if (!(obj && obj.id)) {
 
3388
                    console.log('Error, no chart id');
 
3389
                    return;
 
3390
                }
 
3391
 
 
3392
                success = function(r) {
 
3393
                    var layout = api.layout.Layout((r.responseText ? Ext.decode(r.responseText) : r), obj);
 
3394
 
 
3395
                    if (layout) {
 
3396
                        web.chart.getData(layout, true);
 
3397
                    }
 
3398
                };
 
3399
 
 
3400
                failure = function(r) {
 
3401
                    console.log(obj.id, (r.responseText ? Ext.decode(r.responseText) : r));
 
3402
                };
 
3403
 
 
3404
                config.url = init.contextPath + '/api/charts/' + obj.id + '.' + type + '?fields=' + conf.url.analysisFields.join(',');
 
3405
                config.disableCaching = false;
 
3406
                config.headers = headers;
 
3407
                config.success = success;
 
3408
                config.failure = failure;
 
3409
 
 
3410
                if (type === 'jsonp') {
 
3411
                    Ext.data.JsonP.request(config);
 
3412
                }
 
3413
                else {
 
3414
                    Ext.Ajax.request(config);
 
3415
                }
 
3416
                        };
 
3417
 
 
3418
                        web.chart.getData = function(layout, isUpdateGui) {
 
3419
                                var xLayout,
 
3420
                                        paramString,
 
3421
                    success,
 
3422
                    failure,
 
3423
                    config = {};
 
3424
 
 
3425
                                if (!layout) {
 
3426
                                        return;
 
3427
                                }
 
3428
 
 
3429
                                xLayout = service.layout.getExtendedLayout(layout);
 
3430
                                paramString = web.analytics.getParamString(xLayout, true);
 
3431
 
 
3432
                                // mask
 
3433
                if (!ns.skipMask) {
 
3434
                    web.mask.show(ns.app.centerRegion);
 
3435
                }
 
3436
 
 
3437
                success = function(r) {
 
3438
                    var response = api.response.Response((r.responseText ? Ext.decode(r.responseText) : r));
 
3439
 
 
3440
                    if (!response) {
 
3441
                        web.mask.hide(ns.app.centerRegion);
 
3442
                        return;
 
3443
                    }
 
3444
 
 
3445
                    // sync xLayout with response
 
3446
                    xLayout = service.layout.getSyncronizedXLayout(xLayout, response);
 
3447
 
 
3448
                    if (!xLayout) {
 
3449
                        web.mask.hide(ns.app.centerRegion);
 
3450
                        return;
 
3451
                    }
 
3452
 
 
3453
                    ns.app.paramString = paramString;
 
3454
 
 
3455
                    web.chart.getChart(layout, xLayout, response, isUpdateGui);
 
3456
                };
 
3457
 
 
3458
                failure = function(r) {
 
3459
                    if (!ns.skipMask) {
 
3460
                        web.mask.hide(ns.app.centerRegion);
 
3461
                    }
 
3462
                };
 
3463
 
 
3464
                config.url = init.contextPath + '/api/analytics.' + type + paramString;
 
3465
                config.disableCaching = false;
 
3466
                config.timeout = 60000;
 
3467
                config.headers = headers;
 
3468
                config.success = success;
 
3469
                config.failure = failure;
 
3470
 
 
3471
                if (type === 'jsonp') {
 
3472
                    Ext.data.JsonP.request(config);
 
3473
                }
 
3474
                else {
 
3475
                    Ext.Ajax.request(config);
 
3476
                }
 
3477
                        };
 
3478
 
 
3479
                        web.chart.getChart = function(layout, xLayout, response, isUpdateGui) {
 
3480
                                var xResponse,
 
3481
                                        xColAxis,
 
3482
                                        xRowAxis,
 
3483
                                        config;
 
3484
 
 
3485
                                if (!xLayout) {
 
3486
                                        xLayout = service.layout.getExtendedLayout(layout);
 
3487
                                }
 
3488
 
 
3489
                                // extend response
 
3490
                                xResponse = service.response.getExtendedResponse(xLayout, response);
 
3491
 
 
3492
                                // references
 
3493
                                ns.app.layout = layout;
 
3494
                                ns.app.xLayout = xLayout;
 
3495
                                ns.app.response = response;
 
3496
                                ns.app.xResponse = xResponse;
 
3497
 
 
3498
                if (DV.isDebug) {
 
3499
                    console.log('layout', ns.app.layout);
 
3500
                    console.log('xLayout', ns.app.xLayout);
 
3501
                    console.log('response', ns.app.response);
 
3502
                    console.log('xResponse', ns.app.xResponse);
 
3503
                }
 
3504
 
 
3505
                                // create chart
 
3506
                                ns.app.chart = ns.core.web.chart.createChart(ns);
 
3507
 
 
3508
                // fade
 
3509
                if (!ns.skipFade && ns.core.init.el && Ext.get(ns.core.init.el)) {
 
3510
                    ns.app.chart.on('afterrender', function() {
 
3511
                        Ext.defer( function() {
 
3512
                            Ext.get(ns.core.init.el).fadeIn({
 
3513
                                duration: 400
 
3514
                            });
 
3515
                        }, 300 );
 
3516
                    });
 
3517
                }
 
3518
 
 
3519
                                // update viewport
 
3520
                                ns.app.centerRegion.removeAll();
 
3521
                                ns.app.centerRegion.add(ns.app.chart);
 
3522
 
 
3523
                if (!ns.skipMask) {
 
3524
                    web.mask.hide(ns.app.centerRegion);
 
3525
                }
 
3526
                        };
 
3527
                };
 
3528
 
 
3529
                createViewport = function() {
 
3530
                        var el = Ext.get(ns.core.init.el),
 
3531
                                setFavorite,
 
3532
                                centerRegion,
 
3533
                width,
 
3534
                height;
 
3535
 
 
3536
            if (!ns.skipFade && el && Ext.get(el)) {
 
3537
                                var elBorderW = parseInt(el.getStyle('border-left-width')) + parseInt(el.getStyle('border-right-width')),
 
3538
                    elBorderH = parseInt(el.getStyle('border-top-width')) + parseInt(el.getStyle('border-bottom-width')),
 
3539
                    elPaddingW = parseInt(el.getStyle('padding-left')) + parseInt(el.getStyle('padding-right')),
 
3540
                    elPaddingH = parseInt(el.getStyle('padding-top')) + parseInt(el.getStyle('padding-bottom'));
 
3541
 
 
3542
                                width = el.getWidth() - elBorderW - elPaddingW,
 
3543
                                height = el.getHeight() - elBorderH - elPaddingH;
 
3544
            }
 
3545
 
 
3546
                        centerRegion = Ext.create('Ext.panel.Panel', {
 
3547
                                renderTo: el,
 
3548
                                bodyStyle: 'border: 0 none',
 
3549
                                width: config.width || width || '100%',
 
3550
                                height: config.height || height || '50%',
 
3551
                                layout: 'fit'
 
3552
                        });
 
3553
 
 
3554
                        return {
 
3555
                                centerRegion: centerRegion
 
3556
                        };
 
3557
                };
 
3558
 
 
3559
                initialize = function() {
 
3560
                        if (!validateConfig(config)) {
 
3561
                                return;
 
3562
                        }
 
3563
 
 
3564
                        applyCss();
 
3565
 
 
3566
            init.plugin = true;
 
3567
            init.dashboard = Ext.isBoolean(config.dashboard) ? config.dashboard : false;
 
3568
            init.crossDomain = Ext.isBoolean(config.crossDomain) ? config.crossDomain : true;
 
3569
            init.skipMask = Ext.isBoolean(config.skipMask) ? config.skipMask : false;
 
3570
            init.skipFade = Ext.isBoolean(config.skipFade) ? config.skipFade : false;
 
3571
 
 
3572
                        ns.core = DV.getCore(Ext.clone(init));
 
3573
                        extendInstance(ns);
 
3574
 
 
3575
                        ns.app.viewport = createViewport();
 
3576
                        ns.app.centerRegion = ns.app.viewport.centerRegion;
 
3577
 
 
3578
                        if (config && config.id) {
 
3579
                                ns.core.web.chart.loadChart(config);
 
3580
                        }
 
3581
                        else {
 
3582
                                layout = ns.core.api.layout.Layout(config);
 
3583
 
 
3584
                                if (!layout) {
 
3585
                                        return;
 
3586
                                }
 
3587
 
 
3588
                                ns.core.web.chart.getData(layout);
 
3589
                        }
 
3590
                }();
 
3591
        };
 
3592
 
 
3593
        DV.plugin.getChart = function(config) {
 
3594
                if (Ext.isString(config.url) && config.url.split('').pop() === '/') {
 
3595
                        config.url = config.url.substr(0, config.url.length - 1);
 
3596
                }
 
3597
 
 
3598
                if (isInitComplete) {
 
3599
                        execute(config);
 
3600
                }
 
3601
                else {
 
3602
                        configs.push(config);
 
3603
 
 
3604
                        if (!isInitStarted) {
 
3605
                                isInitStarted = true;
 
3606
                                getInit(config);
 
3607
                        }
 
3608
                }
 
3609
        };
 
3610
 
 
3611
        DHIS = Ext.isObject(window['DHIS']) ? DHIS : {};
 
3612
        DHIS.getChart = DV.plugin.getChart;
 
3613
});