PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.5
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.5
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 3.10.4 All 148 releases
visualizer / js / render-google.js

render-google.js in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.4.5, at js/render-google.js

490 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global google */
2 /* global visualizer */
3 /* global console */
4
5 // this will store the images for each chart rendered.
6 var __visualizer_chart_images = [];
7
8 (function($) {
9 var gv;
10 var all_charts, objects;
11 // so that we know which charts belong to our library.
12 var rendered_charts = [];
13
14 function renderChart(id) {
15 var chart = all_charts[id];
16 var hasAnnotation = false;
17 if(id !== 'canvas' && typeof chart.series !== 'undefined' && typeof chart.settings.series !== 'undefined'){
18 hasAnnotation = chart.series.length - chart.settings.series.length > 1;
19 }
20 // re-render the chart only if it doesn't have annotations and it is on the front-end
21 // this is to prevent the chart from showing "All series on a given axis must be of the same data type" during resize.
22 if(hasAnnotation){
23 return;
24 }
25 renderSpecificChart(id, all_charts[id]);
26 }
27
28 function renderSpecificChart(id, chart) {
29 var render, container, series, data, table, settings, i, j, row, date, axis, property, format, formatter;
30
31 if(chart.library !== 'google'){
32 return;
33 }
34 rendered_charts[id] = 'yes';
35
36 series = chart.series;
37 data = chart.data;
38 settings = chart.settings;
39
40 container = document.getElementById(id);
41 if (container == null) {
42 return;
43 }
44 table = new gv.DataTable({cols: series});
45
46 render = objects[id] || null;
47 if (!render) {
48 switch (chart.type) {
49 case "tabular":
50 render = "Table";
51 break;
52 case "gauge":
53 case "table":
54 case "timeline":
55 render = chart.type.charAt(0).toUpperCase() + chart.type.slice(1);
56 break;
57 default:
58 render = chart.type.charAt(0).toUpperCase() + chart.type.slice(1) + 'Chart';
59 break;
60 }
61
62 render = new gv[render](container);
63 }
64
65 if (settings['animation'] && parseInt(settings['animation']['startup']) === 1)
66 {
67 settings['animation']['startup'] = true;
68 settings['animation']['duration'] = parseInt(settings['animation']['duration']);
69 }
70
71 // mark roles for series that have specified a role
72 // and then remove them from future processing
73 // and also adjust the indices of the series array so that
74 // the ones with a role are ignored
75 // e.g. if there are 6 columns (0-5) out of which 1, 3 and 5 are annotations
76 // the final series will only include 0, 2, 4 (reindexed as 0, 1, 2)
77 if (settings.series) {
78 var adjusted_series = [];
79 for (i = 0; i < settings.series.length; i++) {
80 if (!series[i + 1] || typeof settings.series[i] === 'undefined') {
81 continue;
82 }
83 if(typeof settings.series[i].role !== 'undefined'){
84 table.setColumnProperty(i + 1, 'role', settings.series[i].role);
85 if(settings.series[i].role === '') {
86 adjusted_series.push(settings.series[i]);
87 }
88 }
89 }
90 if(adjusted_series.length > 0){
91 settings.series = adjusted_series;
92 }
93 }
94
95 if ( settings['explorer_enabled'] && settings['explorer_enabled'] == 'true' ) { // jshint ignore:line
96 var $explorer = {};
97 $explorer['keepInBounds'] = true;
98
99 if ( settings['explorer_actions'] ) {
100 $explorer['actions'] = settings['explorer_actions'];
101 }
102 settings['explorer'] = $explorer;
103 }
104
105 switch (chart.type) {
106 case 'pie':
107 if (settings.slices) {
108 for (i in settings.slices) {
109 if (settings.slices[i]['color'] === '') {
110 delete settings.slices[i]['color'];
111 }
112 }
113 }
114 break;
115 case 'line':
116 case 'bar':
117 case 'column':
118 case 'area':
119 case 'scatter':
120 case 'candlestick':
121 if (settings.series) {
122 for (i in settings.series) {
123 if (settings.series[i]['color'] === '') {
124 delete settings.series[i]['color'];
125 }
126 }
127 }
128
129 if (settings.series && settings.legend && settings.legend.position === "left")
130 {
131 settings.targetAxisIndex = 1;
132 }
133 break;
134 case 'geo':
135 if (settings.region !== undefined && settings.region.replace(/^\s+|\s+$/g, '') === '') {
136 settings['region'] = 'world';
137 }
138 break;
139 case 'table':
140 case 'tabular':
141 if (parseInt(settings['pagination']) !== 1)
142 {
143 delete settings['pageSize'];
144 }
145 break;
146 case 'gauge':
147 break;
148 case 'bubble':
149 settings.sortBubblesBySize = settings.sortBubblesBySize ? settings.sortBubblesBySize == 1 : false; // jshint ignore:line
150 break;
151 case 'timeline':
152 settings['timeline'] = [];
153 settings['timeline']['groupByRowLabel'] = settings['groupByRowLabel'] ? true : false;
154 settings['timeline']['colorByRowLabel'] = settings['colorByRowLabel'] ? true : false;
155 settings['timeline']['showRowLabels'] = settings['showRowLabels'] ? true : false;
156 if(settings['singleColor'] !== '') {
157 settings['timeline']['singleColor'] = settings['singleColor'];
158 }
159 break;
160 case 'combo':
161 if (settings.series) {
162 for (i in settings.series) {
163 if (settings.series[i]['type'] === '') {
164 delete settings.series[i]['type'];
165 }
166 if (settings.series[i]['color'] === '') {
167 delete settings.series[i]['color'];
168 }
169 }
170 }
171
172 if (settings.series && settings.legend && settings.legend.position === "left")
173 {
174 settings.targetAxisIndex = 1;
175 }
176 break;
177 default:
178 return;
179 }
180
181 if (series[0] && (series[0].type === 'date' || series[0].type === 'datetime' || series[0].type === 'timeofday')) {
182 axis = false;
183 switch (chart.type) {
184 case 'line':
185 case 'area':
186 case 'scatter':
187 case 'candlestick':
188 case 'column':
189 case 'combo':
190 axis = settings.hAxis;
191 break;
192 case 'bar':
193 axis = settings.vAxis;
194 break;
195 }
196
197 if (axis) {
198 for (property in axis.viewWindow) {
199 date = new Date(axis.viewWindow[property]);
200 if (Object.prototype.toString.call(date) === "[object Date]") {
201 if (!isNaN(date.getTime())) {
202 axis.viewWindow[property] = date;
203 continue;
204 }
205 }
206
207 delete axis.viewWindow[property];
208 }
209 }
210 }
211
212 if(settings.hAxis){
213 if(settings.hAxis.textStyle && settings.hAxis.textStyle !== ''){
214 if(typeof(settings.hAxis.textStyle) === "string") {
215 settings.hAxis.textStyle = {color: settings.hAxis.textStyle};
216 }
217 }
218 }
219
220 if(settings.vAxis){
221 if(settings.vAxis.textStyle && settings.vAxis.textStyle !== ''){
222 if(typeof(settings.vAxis.textStyle) === "string") {
223 settings.vAxis.textStyle = {color: settings.vAxis.textStyle};
224 }
225 }
226 }
227
228 for (i = 0; i < data.length; i++) {
229 row = [];
230 for (j = 0; j < series.length; j++) {
231 switch(series[j].type) {
232 case 'string':
233 if(data[i][j] === ''){
234 data[i][j] = null;
235 }
236 break;
237 case 'boolean':
238 if (typeof data[i][j] === 'string'){
239 data[i][j] = data[i][j] === 'true';
240 }
241 break;
242 case 'date':
243 // fall-through.
244 case 'datetime':
245 date = new Date(data[i][j]);
246 data[i][j] = null;
247 if (Object.prototype.toString.call(date) === "[object Date]") {
248 if (!isNaN(date.getTime())) {
249 data[i][j] = date;
250 }
251 }
252 break;
253 }
254 row.push(data[i][j]);
255 }
256 table.addRow(row);
257 }
258
259 if (settings.series) {
260 switch(chart.type){
261 case 'table':
262 for(i in settings.series){
263 i = parseInt(i);
264 if (!series[i + 1]) {
265 continue;
266 }
267 format_data(id, table, series[i + 1].type, settings.series[i].format, i + 1);
268 }
269 break;
270 default:
271 for (i = 0; i < settings.series.length; i++) {
272 if (!series[i + 1] || typeof settings.series[i] === 'undefined') {
273 continue;
274 }
275 format_data(id, table, series[i + 1].type, settings.series[i].format, i + 1);
276 }
277 break;
278 }
279 } else if (chart.type === 'pie' && settings.format && settings.format !== '') {
280 format_data(id, table, 'number', settings.format, 1);
281 }
282
283 if(settings.hAxis && series[0]) {
284 format_data(id, table, series[0].type, settings.hAxis.format, 0);
285 }
286
287 override(settings);
288
289 gv.events.addListener(render, 'ready', function () {
290 var arr = id.split('-');
291 __visualizer_chart_images[ arr[0] + '-' + arr[1] ] = '';
292 try{
293 var img = render.getImageURI();
294 __visualizer_chart_images[ arr[0] + '-' + arr[1] ] = img;
295 $('body').trigger('visualizer:render:chart', {id: arr[1], image: img});
296 }catch(error){
297 console.warn('render.getImageURI not defined for ' + arr[0] + '-' + arr[1]);
298 }
299 });
300
301 $('body').trigger('visualizer:chart:settings:extend', {id: id, chart: chart, settings: settings, data: table});
302
303 render.draw(table, settings);
304 }
305
306 function format_data(id, table, type, format, index) {
307 if (!format || format === '') {
308 return;
309 }
310
311 var formatter = null;
312 switch (type) {
313 case 'number':
314 formatter = new gv.NumberFormat({pattern: format});
315 break;
316 case 'date':
317 case 'datetime':
318 case 'timeofday':
319 formatter = new gv.DateFormat({pattern: format});
320 break;
321 }
322
323 if (formatter) {
324 formatter.format(table, index);
325 }
326
327 var arr = id.split('-');
328 $('body').trigger('visualizer:format:chart', {id: parseInt(arr[1]), data: table, column: index});
329
330 }
331
332 function override(settings) {
333 if (settings.manual) {
334 try{
335 var options = JSON.parse(settings.manual);
336 $.extend(settings, options);
337 delete settings.manual;
338 }catch(error){
339 console.error("Error while adding manual configuration override " + settings.manual);
340 }
341 }
342 }
343
344 function render() {
345 for (var id in (all_charts || {})) {
346 renderChart(id);
347 }
348 }
349
350 var resizeTimeout;
351
352 $(document).ready(function() {
353 $(window).resize(function() {
354 clearTimeout(resizeTimeout);
355 resizeTimeout = setTimeout(render, 100);
356 });
357
358 resizeHiddenContainers(true);
359 });
360
361 $(window).on('load', function(){
362 resizeHiddenContainers(true);
363 });
364
365 function resizeHiddenContainers(everytime){
366 $(".visualizer-front").parents().each(function(){
367 if(!$(this).is(":visible") && !$(this).hasClass("visualizer-hidden-container")){
368 $(this).addClass("visualizer-hidden-container");
369 }
370 });
371
372 var mutateObserver = new MutationObserver(function(records) {
373 records.forEach(function(record) {
374 if(record.attributeName === "style" || record.attributeName === "class"){
375 var element = $(record.target);
376 var displayStyle = window.getComputedStyle(element[0]).getPropertyValue("display");
377 if(element.hasClass("visualizer-hidden-container-resized") || displayStyle === "none") { return ; }
378 element.find(".visualizer-front").resize();
379 if(!everytime) {
380 element.addClass("visualizer-hidden-container-resized");
381 }
382 }
383 });
384 });
385
386 $('.visualizer-hidden-container').each(function(){
387 mutateObserver.observe($(this)[0], {attributes: true});
388 });
389 }
390
391 $('body').on('visualizer:render:chart:start', function(event, v){
392 var $chart_types = ['corechart', 'geochart', 'gauge', 'table', 'timeline'];
393 if(v.is_front == true){ // jshint ignore:line
394 // check what all chart types to load.
395 $chart_types = [];
396 $.each(v.charts, function(i, c){
397 var $type = c.type;
398 switch($type){
399 case 'bar':
400 case 'column':
401 case 'line':
402 case 'area':
403 case 'stepped area':
404 case 'bubble':
405 case 'pie':
406 case 'donut':
407 case 'combo':
408 case 'candlestick':
409 case 'histogram':
410 case 'scatter':
411 case 'bubble':
412 $type = 'corechart';
413 break;
414 case 'geo':
415 $type = 'geochart';
416 break;
417 case 'tabular':
418 case 'table':
419 $type = 'table';
420 break;
421 case 'dataTable':
422 case 'polarArea':
423 case 'radar':
424 $type = null;
425 break;
426 }
427 if($type != null){
428 $chart_types.push($type);
429 }
430 });
431 }
432
433 objects = {};
434 google.charts.load("current", {packages: $chart_types, mapsApiKey: v.map_api_key, 'language' : v.language});
435 google.charts.setOnLoadCallback(function() {
436 gv = google.visualization;
437 all_charts = v.charts;
438 if(v.is_front == true && typeof v.id !== 'undefined'){ // jshint ignore:line
439 renderChart(v.id);
440 } else {
441 render();
442 }
443 });
444 });
445
446 $('body').on('visualizer:render:specificchart:start', function(event, v){
447 objects = {};
448 gv = google.visualization;
449 renderSpecificChart(v.id, v.chart);
450 });
451
452 $('body').on('visualizer:render:currentchart:update', function(event, v){
453 renderChart('canvas');
454 });
455
456 // front end actions
457 // 'image' is also called from the library
458 $('body').on('visualizer:action:specificchart', function(event, v){
459 var id = v.id;
460 if(typeof rendered_charts[id] === 'undefined'){
461 return;
462 }
463 var arr = id.split('-');
464 var img = __visualizer_chart_images[ arr[0] + '-' + arr[1] ];
465 switch(v.action){
466 case 'print':
467 // for charts that have no rendered image defined, we print the data instead.
468 var html = v.data;
469 if(img !== ''){
470 html = "<html><body><img src='" + img + "' /></body></html>";
471 }
472 $('body').trigger('visualizer:action:specificchart:defaultprint', {data: html});
473 break;
474 case 'image':
475 if(img !== ''){
476 var $a = $("<a>"); // jshint ignore:line
477 $a.attr("href", img);
478 $("body").append($a);
479 $a.attr("download", v.dataObj.name);
480 $a[0].click();
481 $a.remove();
482 }else{
483 console.warn("No image generated");
484 }
485 break;
486 }
487 });
488
489 })(jQuery);
490