tbl_chart.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /* vim: set expandtab sw=4 ts=4 sts=4: */
  2. var chart_data = {};
  3. var temp_chart_title;
  4. var currentChart = null;
  5. var currentSettings = null;
  6. /**
  7. * Unbind all event handlers before tearing down a page
  8. */
  9. AJAX.registerTeardown('tbl_chart.js', function() {
  10. $('input[name="chartType"]').unbind('click');
  11. $('input[name="barStacked"]').unbind('click');
  12. $('input[name="chartTitle"]').unbind('focus').unbind('keyup').unbind('blur');
  13. $('select[name="chartXAxis"]').unbind('change');
  14. $('select[name="chartSeries"]').unbind('change');
  15. $('input[name="xaxis_label"]').unbind('keyup');
  16. $('input[name="yaxis_label"]').unbind('keyup');
  17. $('#resizer').unbind('resizestop');
  18. });
  19. AJAX.registerOnload('tbl_chart.js', function() {
  20. // from jQuery UI
  21. $('#resizer').resizable({
  22. minHeight: 240,
  23. minWidth: 300
  24. })
  25. .width($('#div_view_options').width() - 50);
  26. $('#resizer').bind('resizestop', function(event, ui) {
  27. // make room so that the handle will still appear
  28. $('#querychart').height($('#resizer').height() * 0.96);
  29. $('#querychart').width($('#resizer').width() * 0.96);
  30. currentChart.redraw({
  31. resetAxes : true
  32. });
  33. });
  34. currentSettings = {
  35. type : 'line',
  36. width : $('#resizer').width() - 20,
  37. height : $('#resizer').height() - 20,
  38. xaxisLabel : $('input[name="xaxis_label"]').val(),
  39. yaxisLabel : $('input[name="yaxis_label"]').val(),
  40. title : $('input[name="chartTitle"]').val(),
  41. stackSeries : false,
  42. mainAxis : parseInt($('select[name="chartXAxis"]').val()),
  43. selectedSeries : getSelectedSeries()
  44. };
  45. // handle chart type changes
  46. $('input[name="chartType"]').click(function() {
  47. currentSettings.type = $(this).val();
  48. drawChart();
  49. if ($(this).val() == 'bar' || $(this).val() == 'column'
  50. || $(this).val() == 'line' || $(this).val() == 'area'
  51. || $(this).val() == 'timeline' || $(this).val() == 'spline') {
  52. $('span.barStacked').show();
  53. } else {
  54. $('span.barStacked').hide();
  55. }
  56. });
  57. // handle stacking for bar, column and area charts
  58. $('input[name="barStacked"]').click(function() {
  59. if (this.checked) {
  60. $.extend(true, currentSettings, {stackSeries : true});
  61. } else {
  62. $.extend(true, currentSettings, {stackSeries : false});
  63. }
  64. drawChart();
  65. });
  66. // handle changes in chart title
  67. $('input[name="chartTitle"]').focus(function() {
  68. temp_chart_title = $(this).val();
  69. }).keyup(function() {
  70. var title = $(this).val();
  71. if (title.length == 0) {
  72. title = ' ';
  73. }
  74. currentSettings.title = $('input[name="chartTitle"]').val();
  75. drawChart();
  76. }).blur(function() {
  77. if ($(this).val() != temp_chart_title) {
  78. drawChart();
  79. }
  80. });
  81. var dateTimeCols = [];
  82. var vals = $('input[name="dateTimeCols"]').val().split(' ');
  83. $.each(vals, function(i, v) {
  84. dateTimeCols.push(parseInt(v));
  85. });
  86. // handle changing the x-axis
  87. $('select[name="chartXAxis"]').change(function() {
  88. currentSettings.mainAxis = parseInt($(this).val());
  89. if (dateTimeCols.indexOf(currentSettings.mainAxis) != -1) {
  90. $('span.span_timeline').show();
  91. } else {
  92. $('span.span_timeline').hide();
  93. if (currentSettings.type == 'timeline') {
  94. $('input#radio_line').prop('checked', true);
  95. currentSettings.type = 'line';
  96. }
  97. }
  98. var xaxis_title = $(this).children('option:selected').text();
  99. $('input[name="xaxis_label"]').val(xaxis_title);
  100. currentSettings.xaxisLabel = xaxis_title;
  101. drawChart();
  102. });
  103. // handle changing the selected data series
  104. $('select[name="chartSeries"]').change(function() {
  105. currentSettings.selectedSeries = getSelectedSeries();
  106. var yaxis_title;
  107. if (currentSettings.selectedSeries.length == 1) {
  108. $('span.span_pie').show();
  109. yaxis_title = $(this).children('option:selected').text();
  110. } else {
  111. $('span.span_pie').hide();
  112. if (currentSettings.type == 'pie') {
  113. $('input#radio_line').prop('checked', true);
  114. currentSettings.type = 'line';
  115. }
  116. yaxis_title = PMA_messages['strYValues'];
  117. }
  118. $('input[name="yaxis_label"]').val(yaxis_title);
  119. currentSettings.yaxisLabel = yaxis_title;
  120. drawChart();
  121. });
  122. // handle manual changes to the chart axis labels
  123. $('input[name="xaxis_label"]').keyup(function() {
  124. currentSettings.xaxisLabel = $(this).val();
  125. drawChart();
  126. });
  127. $('input[name="yaxis_label"]').keyup(function() {
  128. currentSettings.yaxisLabel = $(this).val();
  129. drawChart();
  130. });
  131. $("#tblchartform").submit();
  132. });
  133. /**
  134. * Ajax Event handler for 'Go' button click
  135. *
  136. */
  137. $("#tblchartform").live('submit', function(event) {
  138. if (!checkFormElementInRange(this, 'session_max_rows', PMA_messages['strNotValidRowNumber'], 1)
  139. || !checkFormElementInRange(this, 'pos', PMA_messages['strNotValidRowNumber'], 0 - 1)) {
  140. return false;
  141. }
  142. var $form = $(this);
  143. if (!checkSqlQuery($form[0])) {
  144. return false;
  145. }
  146. // remove any div containing a previous error message
  147. $('.error').remove();
  148. var $msgbox = PMA_ajaxShowMessage();
  149. PMA_prepareForAjaxRequest($form);
  150. $.post($form.attr('action'), $form.serialize(), function(data) {
  151. if (data.success == true) {
  152. $('.success').fadeOut();
  153. if (typeof data.chartData != 'undefined') {
  154. chart_data = jQuery.parseJSON(data.chartData);
  155. drawChart();
  156. $('div#querychart').height($('div#resizer').height() * 0.96);
  157. $('div#querychart').width($('div#resizer').width() * 0.96);
  158. currentChart.redraw({
  159. resetAxes : true
  160. });
  161. $('#querychart').show();
  162. }
  163. } else {
  164. PMA_ajaxRemoveMessage($msgbox);
  165. PMA_ajaxShowMessage(data.error, false);
  166. chart_data = null;
  167. drawChart();
  168. }
  169. PMA_ajaxRemoveMessage($msgbox);
  170. }, "json"); // end $.post()
  171. return false;
  172. }); // end
  173. function drawChart() {
  174. currentSettings.width = $('#resizer').width() - 20;
  175. currentSettings.height = $('#resizer').height() - 20;
  176. // todo: a better way using .redraw() ?
  177. if (currentChart != null) {
  178. currentChart.destroy();
  179. }
  180. var columnNames = [];
  181. $('select[name="chartXAxis"] option').each(function() {
  182. columnNames.push(escapeHtml($(this).text()));
  183. });
  184. try {
  185. currentChart = PMA_queryChart(chart_data, columnNames, currentSettings);
  186. } catch(err) {
  187. PMA_ajaxShowMessage(err.message, false);
  188. }
  189. }
  190. function getSelectedSeries() {
  191. var val = $('select[name="chartSeries"]').val() || [];
  192. var ret = [];
  193. $.each(val, function(i, v) {
  194. ret.push(parseInt(v));
  195. });
  196. return ret;
  197. }
  198. function extractDate(dateString) {
  199. var matches, match;
  200. var dateTimeRegExp = /[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/;
  201. var dateRegExp = /[0-9]{4}-[0-9]{2}-[0-9]{2}/;
  202. matches = dateTimeRegExp.exec(dateString);
  203. if (matches != null && matches.length > 0) {
  204. match = matches[0];
  205. return new Date(match.substr(0, 4), match.substr(5, 2), match.substr(8, 2), match.substr(11, 2), match.substr(14, 2), match.substr(17, 2));
  206. } else {
  207. matches = dateRegExp.exec(dateString);
  208. if (matches != null && matches.length > 0) {
  209. match = matches[0];
  210. return new Date(match.substr(0, 4), match.substr(5, 2), match.substr(8, 2));
  211. }
  212. }
  213. return null;
  214. }
  215. function PMA_queryChart(data, columnNames, settings) {
  216. if ($('#querychart').length == 0) {
  217. return;
  218. }
  219. var jqPlotSettings = {
  220. title : {
  221. text : settings.title,
  222. escapeHtml: true
  223. },
  224. grid : {
  225. drawBorder : false,
  226. shadow : false,
  227. background : 'rgba(0,0,0,0)'
  228. },
  229. legend : {
  230. show : true,
  231. placement : 'outsideGrid',
  232. location : 'e'
  233. },
  234. axes : {
  235. xaxis : {
  236. label : escapeHtml(settings.xaxisLabel)
  237. },
  238. yaxis : {
  239. label : settings.yaxisLabel
  240. }
  241. },
  242. stackSeries : settings.stackSeries,
  243. highlighter: {
  244. show: true,
  245. showTooltip: true,
  246. tooltipAxes: 'xy'
  247. }
  248. };
  249. // create the chart
  250. var factory = new JQPlotChartFactory();
  251. var chart = factory.createChart(settings.type, "querychart");
  252. // create the data table and add columns
  253. var dataTable = new DataTable();
  254. if (settings.type == 'timeline') {
  255. dataTable.addColumn(ColumnType.DATE, columnNames[settings.mainAxis]);
  256. } else {
  257. dataTable.addColumn(ColumnType.STRING, columnNames[settings.mainAxis]);
  258. }
  259. $.each(settings.selectedSeries, function(index, element) {
  260. dataTable.addColumn(ColumnType.NUMBER, columnNames[element]);
  261. });
  262. // set data to the data table
  263. var columnsToExtract = [ settings.mainAxis ];
  264. $.each(settings.selectedSeries, function(index, element) {
  265. columnsToExtract.push(element);
  266. });
  267. var values = [], newRow, row, col;
  268. for ( var i = 0; i < data.length; i++) {
  269. row = data[i];
  270. newRow = [];
  271. for ( var j = 0; j < columnsToExtract.length; j++) {
  272. col = columnNames[columnsToExtract[j]];
  273. if (j == 0) {
  274. if (settings.type == 'timeline') { // first column is date type
  275. newRow.push(extractDate(row[col]));
  276. } else { // first column is string type
  277. newRow.push(row[col]);
  278. }
  279. } else { // subsequent columns are of type, number
  280. newRow.push(parseFloat(row[col]));
  281. }
  282. }
  283. values.push(newRow);
  284. }
  285. dataTable.setData(values);
  286. // draw the chart and return the chart object
  287. chart.draw(dataTable, jqPlotSettings);
  288. return chart;
  289. }