Translated using Weblate (Tatar)
[phpmyadmin.git] / js / tbl_chart.js
blob33cdab78ddc1120681662f4dabdfd64cdd434e37
1 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 var chart_data = {};
4 var temp_chart_title;
6 var currentChart = null;
7 var currentSettings = null;
9 var dateTimeCols = [];
10 var numericCols = [];
12 function extractDate(dateString) {
13     var matches, match;
14     var dateTimeRegExp = /[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/;
15     var dateRegExp = /[0-9]{4}-[0-9]{2}-[0-9]{2}/;
17     matches = dateTimeRegExp.exec(dateString);
18     if (matches !== null && matches.length > 0) {
19         match = matches[0];
20         return new Date(match.substr(0, 4), parseInt(match.substr(5, 2), 10) - 1, match.substr(8, 2), match.substr(11, 2), match.substr(14, 2), match.substr(17, 2));
21     } else {
22         matches = dateRegExp.exec(dateString);
23         if (matches !== null && matches.length > 0) {
24             match = matches[0];
25             return new Date(match.substr(0, 4), parseInt(match.substr(5, 2), 10) - 1, match.substr(8, 2));
26         }
27     }
28     return null;
31 function PMA_queryChart(data, columnNames, settings) {
32     if ($('#querychart').length === 0) {
33         return;
34     }
36     var plotSettings = {
37         title : {
38             text : settings.title,
39             escapeHtml: true
40         },
41         grid : {
42             drawBorder : false,
43             shadow : false,
44             background : 'rgba(0,0,0,0)'
45         },
46         legend : {
47             show : true,
48             placement : 'outsideGrid',
49             location : 'e'
50         },
51         axes : {
52             xaxis : {
53                 label : escapeHtml(settings.xaxisLabel)
54             },
55             yaxis : {
56                 label : settings.yaxisLabel
57             }
58         },
59         stackSeries : settings.stackSeries
60     };
62     // create the chart
63     var factory = new JQPlotChartFactory();
64     var chart = factory.createChart(settings.type, "querychart");
66     // create the data table and add columns
67     var dataTable = new DataTable();
68     if (settings.type == 'timeline') {
69         dataTable.addColumn(ColumnType.DATE, columnNames[settings.mainAxis]);
70     } else if (settings.type == 'scatter') {
71         dataTable.addColumn(ColumnType.NUMBER, columnNames[settings.mainAxis]);
72     } else {
73         dataTable.addColumn(ColumnType.STRING, columnNames[settings.mainAxis]);
74     }
76     var i;
77     if (settings.seriesColumn === null) {
78         $.each(settings.selectedSeries, function (index, element) {
79             dataTable.addColumn(ColumnType.NUMBER, columnNames[element]);
80         });
82         // set data to the data table
83         var columnsToExtract = [ settings.mainAxis ];
84         $.each(settings.selectedSeries, function (index, element) {
85             columnsToExtract.push(element);
86         });
87         var values = [], newRow, row, col;
88         for (i = 0; i < data.length; i++) {
89             row = data[i];
90             newRow = [];
91             for (var j = 0; j < columnsToExtract.length; j++) {
92                 col = columnNames[columnsToExtract[j]];
93                 if (j === 0) {
94                     if (settings.type == 'timeline') { // first column is date type
95                         newRow.push(extractDate(row[col]));
96                     } else if (settings.type == 'scatter') {
97                         newRow.push(parseFloat(row[col]));
98                     } else { // first column is string type
99                         newRow.push(row[col]);
100                     }
101                 } else { // subsequent columns are of type, number
102                     newRow.push(parseFloat(row[col]));
103                 }
104             }
105             values.push(newRow);
106         }
107         dataTable.setData(values);
108     } else {
109         var seriesNames = {}, seriesNumber = 1;
110         var seriesColumnName = columnNames[settings.seriesColumn];
111         for (i = 0; i < data.length; i++) {
112             if (! seriesNames[data[i][seriesColumnName]]) {
113                 seriesNames[data[i][seriesColumnName]] = seriesNumber;
114                 seriesNumber++;
115             }
116         }
118         $.each(seriesNames, function (seriesName, seriesNumber) {
119             dataTable.addColumn(ColumnType.NUMBER, seriesName);
120         });
122         var valueMap = {}, xValue, value;
123         var mainAxisName = columnNames[settings.mainAxis];
124         var valueColumnName = columnNames[settings.valueColumn];
125         for (i = 0; i < data.length; i++) {
126             xValue = data[i][mainAxisName];
127             value = valueMap[xValue];
128             if (! value) {
129                 value = [xValue];
130                 valueMap[xValue] = value;
131             }
132             seriesNumber = seriesNames[data[i][seriesColumnName]];
133             value[seriesNumber] = parseFloat(data[i][valueColumnName]);
134         }
136         var values = [];
137         $.each(valueMap, function(index, value) {
138             values.push(value);
139         });
140         dataTable.setData(values);
141     }
143     // draw the chart and return the chart object
144     chart.draw(dataTable, plotSettings);
145     return chart;
148 function drawChart() {
149     currentSettings.width = $('#resizer').width() - 20;
150     currentSettings.height = $('#resizer').height() - 20;
152     // TODO: a better way using .redraw() ?
153     if (currentChart !== null) {
154         currentChart.destroy();
155     }
157     var columnNames = [];
158     $('select[name="chartXAxis"] option').each(function () {
159         columnNames.push($(this).text());
160     });
161     try {
162         currentChart = PMA_queryChart(chart_data, columnNames, currentSettings);
163         if (currentChart != null) {
164             $('#saveChart').attr('href', currentChart.toImageString());
165         }
166     } catch (err) {
167         PMA_ajaxShowMessage(err.message, false);
168     }
171 function getSelectedSeries() {
172     var val = $('select[name="chartSeries"]').val() || [];
173     var ret = [];
174     $.each(val, function (i, v) {
175         ret.push(parseInt(v, 10));
176     });
177     return ret;
180 function onXAxisChange() {
181     var $xAxisSelect = $('select[name="chartXAxis"]');
182     currentSettings.mainAxis = parseInt($xAxisSelect.val(), 10);
183     if (dateTimeCols.indexOf(currentSettings.mainAxis) != -1) {
184         $('span.span_timeline').show();
185     } else {
186         $('span.span_timeline').hide();
187         if (currentSettings.type == 'timeline') {
188             $('input#radio_line').prop('checked', true);
189             currentSettings.type = 'line';
190         }
191     }
192     if (numericCols.indexOf(currentSettings.mainAxis) != -1) {
193         $('span.span_scatter').show();
194     } else {
195         $('span.span_scatter').hide();
196         if (currentSettings.type == 'scatter') {
197             $('input#radio_line').prop('checked', true);
198             currentSettings.type = 'line';
199         }
200     }
201     var xaxis_title = $xAxisSelect.children('option:selected').text();
202     $('input[name="xaxis_label"]').val(xaxis_title);
203     currentSettings.xaxisLabel = xaxis_title;
206 function onDataSeriesChange() {
207     var $seriesSelect = $('select[name="chartSeries"]');
208     currentSettings.selectedSeries = getSelectedSeries();
209     var yaxis_title;
210     if (currentSettings.selectedSeries.length == 1) {
211         $('span.span_pie').show();
212         yaxis_title = $seriesSelect.children('option:selected').text();
213     } else {
214         $('span.span_pie').hide();
215         if (currentSettings.type == 'pie') {
216             $('input#radio_line').prop('checked', true);
217             currentSettings.type = 'line';
218         }
219         yaxis_title = PMA_messages.strYValues;
220     }
221     $('input[name="yaxis_label"]').val(yaxis_title);
222     currentSettings.yaxisLabel = yaxis_title;
226  * Unbind all event handlers before tearing down a page
227  */
228 AJAX.registerTeardown('tbl_chart.js', function () {
229     $('input[name="chartType"]').unbind('click');
230     $('input[name="barStacked"]').unbind('click');
231     $('input[name="chkAlternative"]').unbind('click');
232     $('input[name="chartTitle"]').unbind('focus').unbind('keyup').unbind('blur');
233     $('select[name="chartXAxis"]').unbind('change');
234     $('select[name="chartSeries"]').unbind('change');
235     $('select[name="chartSeriesColumn"]').unbind('change');
236     $('select[name="chartValueColumn"]').unbind('change');
237     $('input[name="xaxis_label"]').unbind('keyup');
238     $('input[name="yaxis_label"]').unbind('keyup');
239     $('#resizer').unbind('resizestop');
240     $('#tblchartform').unbind('submit');
243 AJAX.registerOnload('tbl_chart.js', function () {
245     // handle manual resize
246     $('#resizer').bind('resizestop', function (event, ui) {
247         // make room so that the handle will still appear
248         $('#querychart').height($('#resizer').height() * 0.96);
249         $('#querychart').width($('#resizer').width() * 0.96);
250         if (currentChart !== null) {
251             currentChart.redraw({
252                 resetAxes : true
253             });
254         }
255     });
257     // handle chart type changes
258     $('input[name="chartType"]').click(function () {
259         var type = currentSettings.type = $(this).val();
260         if (type == 'bar' || type == 'column' || type == 'area') {
261             $('span.barStacked').show();
262         } else {
263             $('input[name="barStacked"]').prop('checked', false);
264             $.extend(true, currentSettings, {stackSeries : false});
265             $('span.barStacked').hide();
266         }
267         drawChart();
268     });
270     // handle chosing alternative data format
271     $('input[name="chkAlternative"]').click(function () {
272         var $seriesColumn = $('select[name="chartSeriesColumn"]');
273         var $valueColumn  = $('select[name="chartValueColumn"]');
274         var $chartSeries  = $('select[name="chartSeries"]');
275         if ($(this).is(':checked')) {
276             $seriesColumn.prop('disabled', false);
277             $valueColumn.prop('disabled', false);
278             $chartSeries.prop('disabled', true);
279             currentSettings.seriesColumn = parseInt($seriesColumn.val(), 10);
280             currentSettings.valueColumn = parseInt($valueColumn.val(), 10);
281         } else {
282             $seriesColumn.prop('disabled', true);
283             $valueColumn.prop('disabled', true);
284             $chartSeries.prop('disabled', false);
285             currentSettings.seriesColumn = null;
286             currentSettings.valueColumn = null;
287         }
288         drawChart();
289     });
291     // handle stacking for bar, column and area charts
292     $('input[name="barStacked"]').click(function () {
293         if ($(this).is(':checked')) {
294             $.extend(true, currentSettings, {stackSeries : true});
295         } else {
296             $.extend(true, currentSettings, {stackSeries : false});
297         }
298         drawChart();
299     });
301     // handle changes in chart title
302     $('input[name="chartTitle"]')
303     .focus(function () {
304         temp_chart_title = $(this).val();
305     })
306     .keyup(function () {
307         var title = $(this).val();
308         if (title.length === 0) {
309             title = ' ';
310         }
311         currentSettings.title = $('input[name="chartTitle"]').val();
312         drawChart();
313     })
314     .blur(function () {
315         if ($(this).val() != temp_chart_title) {
316             drawChart();
317         }
318     });
320     // handle changing the x-axis
321     $('select[name="chartXAxis"]').change(function () {
322         onXAxisChange();
323         drawChart();
324     });
326     // handle changing the selected data series
327     $('select[name="chartSeries"]').change(function () {
328         onDataSeriesChange();
329         drawChart();
330     });
332     // handle changing the series column
333     $('select[name="chartSeriesColumn"]').change(function () {
334         currentSettings.seriesColumn = parseInt($(this).val(), 10);
335         drawChart();
336     });
338     // handle changing the value column
339     $('select[name="chartValueColumn"]').change(function () {
340         currentSettings.valueColumn = parseInt($(this).val(), 10);
341         drawChart();
342     });
344     // handle manual changes to the chart x-axis labels
345     $('input[name="xaxis_label"]').keyup(function () {
346         currentSettings.xaxisLabel = $(this).val();
347         drawChart();
348     });
350     // handle manual changes to the chart y-axis labels
351     $('input[name="yaxis_label"]').keyup(function () {
352         currentSettings.yaxisLabel = $(this).val();
353         drawChart();
354     });
356     // handler for ajax form submission
357     $('#tblchartform').submit(function (event) {
359         var $form = $(this);
360         if (codemirror_editor) {
361             $form[0].elements.sql_query.value = codemirror_editor.getValue();
362         }
363         if (!checkSqlQuery($form[0])) {
364             return false;
365         }
367         var $msgbox = PMA_ajaxShowMessage();
368         PMA_prepareForAjaxRequest($form);
369         $.post($form.attr('action'), $form.serialize(), function (data) {
370             if (typeof data !== 'undefined' &&
371                     data.success === true &&
372                     typeof data.chartData !== 'undefined') {
373                 chart_data = jQuery.parseJSON(data.chartData);
374                 drawChart();
375                 PMA_ajaxRemoveMessage($msgbox);
376             } else {
377                 PMA_ajaxShowMessage(data.error, false);
378             }
379         }, "json"); // end $.post()
381         return false;
382     });
384     // from jQuery UI
385     $('#resizer').resizable({
386         minHeight: 240,
387         minWidth: 300
388     })
389     .width($('#div_view_options').width() - 50)
390     .trigger('resizestop');
392     currentSettings = {
393         type : 'line',
394         width : $('#resizer').width() - 20,
395         height : $('#resizer').height() - 20,
396         xaxisLabel : $('input[name="xaxis_label"]').val(),
397         yaxisLabel : $('input[name="yaxis_label"]').val(),
398         title : $('input[name="chartTitle"]').val(),
399         stackSeries : false,
400         mainAxis : parseInt($('select[name="chartXAxis"]').val(), 10),
401         selectedSeries : getSelectedSeries(),
402         seriesColumn : null
403     };
405     var vals = $('input[name="dateTimeCols"]').val().split(' ');
406     $.each(vals, function (i, v) {
407         dateTimeCols.push(parseInt(v, 10));
408     });
410     vals = $('input[name="numericCols"]').val().split(' ');
411     $.each(vals, function (i, v) {
412         numericCols.push(parseInt(v, 10));
413     });
415     onXAxisChange();
416     onDataSeriesChange();
418     $("#tblchartform").submit();