PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.4
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.4
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.4, at js/render-google.js

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