PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 4.0.8
Visualizer – Tables & Charts Manager with Built-in AI Generator v4.0.8
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
← All changes | js/render-google.js +51 -32 3.10.144.0.8 View file →
@@ -25,19 +25,28 @@
25 25 if ( ! chart ) {
26 26 return;
27 27 }
28 28
29 + if ( chart.library && chart.library !== 'google' && chart.library !== 'GoogleCharts' ) {
30 + return;
31 + }
32 +
29 33 // re-render the chart only if it doesn't have annotations and it is on the front-end
30 34 // this is to prevent the chart from showing "All series on a given axis must be of the same data type" during resize.
31 35 // remember, some charts do not support annotations so they should not be included in this.
32 36 var no_annotation_charts = ['tabular', 'timeline', 'gauge', 'geo', 'bubble', 'candlestick'];
33 37 if ( undefined !== chart.settings && undefined !== chart.settings.series && undefined === chart.settings.series.length ) {
34 - var chartSeries = [];
35 - var chartSeriesValue = Object.values( chart.settings.series );
36 - $.each( Object.keys( chart.settings.series ), function( index, element ) {
37 - chartSeries[element] = chartSeriesValue[index];
38 - } );
39 - chart.settings.series = chartSeries;
38 + var seriesKeys = Object.keys( chart.settings.series );
39 + // Only convert when keys are numeric indices (PHP JSON-encoded array).
40 + // String keys (e.g. named series from manual config) must be left as-is.
41 + if ( seriesKeys.every( function( k ) { return ! isNaN( k ); } ) ) {
42 + var chartSeries = [];
43 + var chartSeriesValue = Object.values( chart.settings.series );
44 + $.each( seriesKeys, function( index, element ) {
45 + chartSeries[ element ] = chartSeriesValue[ index ];
46 + } );
47 + chart.settings.series = chartSeries;
48 + }
40 49 }
41 50 if(id !== 'canvas' && typeof chart.series !== 'undefined' && typeof chart.settings.series !== 'undefined' && ! no_annotation_charts.includes(chart.type) ) {
42 51 hasAnnotation = chart.series.length - chart.settings.series.length > 1;
43 52 }
@@ -351,21 +360,16 @@
351 360 format_data(id, table, series[i + 1].type, settings.series[i].format, i + 1);
352 361 }
353 362 break;
354 363 default:
355 - for (i = 0; i < settings.series.length; i++) {
356 - if (!series[i + 1] || typeof settings.series[i] === 'undefined') {
357 - continue;
358 - }
359 - var seriesIndexToUse = i + 1;
360 -
361 - // if an annotation "swallowed" a series, use the following one.
362 - if(series_annotations.includes(i)){
363 - seriesIndexToUse++;
364 - }
365 - if ( series[seriesIndexToUse] ) {
366 - format_data(id, table, series[seriesIndexToUse].type, settings.series[i].format, seriesIndexToUse);
367 - }
364 + // Single-pass: walk columns, skip annotation/helper roles, apply formats in order.
365 + var k = 0; // index into settings.series (visible series)
366 + for (var c = 1; c < series.length && k < settings.series.length; c++) { // skip label at 0
367 + if (table.getColumnProperty(c, 'role')) continue; // helper/annotation column
368 + var s = settings.series[k++];
369 + if (!s || !s.format) continue;
370 + if (!series[c]) continue;
371 + format_data(id, table, series[c].type, s.format, c);
368 372 }
369 373 break;
370 374 }
371 375 } else if (chart.type === 'pie' && settings.format && settings.format !== '') {
@@ -448,21 +452,32 @@
448 452 return;
449 453 }
450 454
451 455 var formatter = null;
452 - switch (type) {
453 - case 'number':
454 - formatter = new gv.NumberFormat({pattern: format});
455 - break;
456 - case 'date':
457 - case 'datetime':
458 - case 'timeofday':
459 - formatter = new gv.DateFormat({pattern: format});
460 - break;
461 - }
456 + var $formatInput = $('input.control-text[name*="[format]"]').filter(function() {
457 + return $(this).val() === format;
458 + });
459 + try {
460 + switch (type) {
461 + case 'number':
462 + formatter = new gv.NumberFormat({pattern: format});
463 + break;
464 + case 'date':
465 + case 'datetime':
466 + case 'timeofday':
467 + formatter = new gv.DateFormat({pattern: format});
468 + break;
469 + }
462 470
463 - if (formatter) {
464 - formatter.format(table, index);
471 + if (formatter) {
472 + formatter.format(table, index);
473 + $formatInput.nextAll('.visualizer-format-error').remove();
474 + }
475 + } catch (e) {
476 + if ($formatInput.length) {
477 + $formatInput.nextAll('.visualizer-format-error').remove();
478 + $('<p class="visualizer-format-error" style="color:#cc0000;margin:4px 0 0"></p>').text(visualizer.l10n.invalid_format).insertAfter($formatInput);
479 + }
465 480 }
466 481
467 482 var arr = id.split('-');
468 483 $('body').trigger('visualizer:format:chart', {id: parseInt(arr[1]), data: table, column: index});
@@ -548,8 +563,12 @@
548 563 if(v.is_front == true){ // jshint ignore:line
549 564 // check what all chart types to load.
550 565 $chart_types = [];
551 566 $.each(v.charts, function(i, c){
567 + // Only consider charts rendered by Google Charts.
568 + if ( c.library && c.library !== 'google' && c.library !== 'GoogleCharts' ) {
569 + return;
570 + }
552 571 var $type = c.type;
553 572 switch($type){
554 573 case 'bar':
555 574 case 'column':
@@ -578,9 +597,9 @@
578 597 case 'radar':
579 598 $type = null;
580 599 break;
581 600 }
582 - if($type != null){
601 + if($type != null && $type !== ''){
583 602 $chart_types.push($type);
584 603 }
585 604 });
586 605 }