PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.11.7
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.11.7
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 / frame.js

frame.js in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.11.7, at js/frame.js

882 lines 35.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global prompt */
2 /* global visualizer */
3 /* global alert */
4 /* global confirm */
5 /* global ajaxurl */
6 /* global CodeMirror */
7 /* global vizHaveSettingsChanged */
8
9 (function ($) {
10 $(window).on('load', function(){
11 let chart_select = $('#chart-select');
12 if(chart_select.length > 0){
13 // scroll to the selected chart type.
14 $('#chart-select')[0].scrollIntoView();
15 }
16 });
17
18 $(document).ready(function () {
19 onReady();
20 });
21
22 function initTabs(){
23 $( "#sidebar" ).lock();
24 $( "#viz-tabs" ).tabs({
25 create: function( event, ui ) {
26 $(this).addClass('done');
27 $( "#sidebar" ).unlock();
28 },
29 beforeActivate: function( event, ui ) {
30 // if settings have changed in tab #2 and tab #1 is being activated, warn the user.
31 if(vizHaveSettingsChanged() && ui.newTab.find( 'a' ).attr( 'id' ).includes('viz-tab-basic')){
32 return confirm(visualizer.l10n.save_settings);
33 }
34 }
35 });
36 }
37
38 function onReady() {
39 initTabs();
40
41 // open the correct source tab/sub-tab.
42 var source = $('#visualizer-chart-id').attr('data-chart-source');
43 $('li.viz-group.' + source).addClass('open');
44 $('li.viz-group.' + source + ' span.viz-section-title.' + source).addClass('open');
45 $('li.viz-group.' + source + ' span.viz-section-title.' + source + '.open').parent().find('div.viz-section-items').show();
46
47 init_permissions();
48
49 if(typeof visualizer !== 'undefined' && visualizer.is_pro) {
50 init_db_import();
51 init_filter_import();
52 }
53
54 init_json_import();
55
56 init_editor_table();
57
58 // update the manual configuation link to point to the correct chart type.
59 var type = $('#visualizer-chart-id').attr('data-chart-type');
60 var chart_type_in_api_link = type + 'chart';
61 switch (type) {
62 case "gauge":
63 case "table":
64 case "timeline":
65 chart_type_in_api_link = type;
66 break;
67 }
68
69 if($('span.viz-gvlink').length > 0) {
70 $('span.viz-gvlink').html($('span.viz-gvlink').html().replace('?', chart_type_in_api_link));
71 }
72
73 $('.type-radio').change(function () {
74 $('.type-label-selected').removeClass('type-label-selected');
75 $(this).parent().addClass('type-label-selected');
76 });
77
78 // collapse other open sections of this group
79 $(document).on('click', '.viz-group-title', function () {
80 var parent = $(this).parent();
81
82 if (parent.hasClass('open')) {
83 parent.removeClass('open');
84 } else {
85 parent.parent().find('.viz-group.open').removeClass('open');
86 parent.addClass('open');
87 }
88
89 /*
90 * if the user wants to perform an action and click that tab to change the source
91 * and the chart is no longer showing because that particular LHS screen is showing
92 * e.g. create parameters, import json, db query box etc.
93 * we need to make sure we cancel the current process WITHOUT saving
94 * and then show the chart as it was
95 * let's close the LHS window and show the chart that is hidden
96 */
97 $('body').trigger('visualizer:change:action');
98 });
99
100 // collapse other open subsections of this section
101 $(document).on('click', '.viz-section-title', function () {
102 var grandparent = $(this).parent().parent();
103 grandparent.find('.viz-section-title.open ~ .viz-section-items').hide();
104 grandparent.find('.viz-section-title.open').removeClass('open');
105 });
106
107 $('#view-remote-file').click(function () {
108 var url = $(this).parent().find('#vz-schedule-url').val();
109
110 if (url !== '') {
111 if (url.indexOf('localhost') !== -1 || /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(url)) {
112 if (url.substr(url.length - 8) === '/pubhtml') {
113 url = url.substring(0, url.length - 8) + '/export?format=csv';
114 }
115
116 $('#canvas').lock();
117 $(this).parent().submit();
118 } else {
119 alert(visualizer.l10n.invalid_source);
120 }
121 }
122 });
123
124 $('#vz-import-file').click(function (e) {
125 e.preventDefault();
126 if ($.trim($(this).parent().find("#csv-file").val()) !== '') {
127 $('#canvas').lock();
128 $(this).parent().submit();
129 }
130 });
131
132 $( window ).on( 'load', function() {
133 $('#canvas').unlock();
134 } );
135
136 $(document).on('click', '.viz-section-title', function () {
137 $(this).toggleClass('open').parent().find('.viz-section-items').toggle();
138 });
139
140 $(document).on('click', '.more-info', function () {
141 $(this).parent().find('.viz-section-description:first').toggle();
142 return false;
143 });
144
145 $('#cancel-button').click(function () {
146 $('#cancel-form').submit();
147 });
148
149 init_available_chart_list();
150
151 $('.viz-abort').on('click', function(e){
152 e.preventDefault();
153 window.parent.postMessage('visualizer:mediaframe:close', '*');
154 });
155
156 }
157
158 /**
159 * Initialize/Update the available chart list based on their supported renderer libraries.
160 *
161 * @returns {void}
162 */
163 function init_available_chart_list() {
164 const rendererSelect = document.querySelector('select.viz-select-library');
165 if ( ! rendererSelect ) {
166 return;
167 }
168
169 const rendererTypesMappingData = rendererSelect?.getAttribute('data-type-vs-library');
170 if( ! rendererTypesMappingData ) {
171 return;
172 }
173
174 /** @type {Record<string, ('GoogleCharts' | 'ChartJS' | 'DataTable')[]>} */
175 const rendererTypesMapping = JSON.parse( rendererTypesMappingData );
176
177 document.querySelectorAll('input.type-radio').forEach( chartTypeRadio => {
178
179 // Init the lib based on the default selected chart type.
180 if ( chartTypeRadio.checked ) {
181 const chartType = chartTypeRadio.value;
182 if ( ! chartType ) {
183 return;
184 }
185
186 const selectedRenderer = rendererSelect.value;
187 if ( ! rendererTypesMapping[chartType]?.includes( selectedRenderer ) ) {
188 disable_renderer_select_placeholder();
189 rendererSelect.value = rendererTypesMapping[chartType][0]
190 }
191 }
192
193 chartTypeRadio.addEventListener('click', (event) => {
194 // Check if the chart type is supported by the selected renderer. If not, select the first supported renderer.
195 const chartType = event.target.value;
196 if ( ! chartType ) {
197 return;
198 }
199
200 const selectedRenderer = rendererSelect.value;
201 if ( ! rendererTypesMapping[chartType]?.includes( selectedRenderer ) ) {
202 disable_renderer_select_placeholder();
203 rendererSelect.value = rendererTypesMapping[chartType][0]
204 }
205 });
206 });
207
208 // Update the chart list on user interaction.
209 rendererSelect.addEventListener('change', (event) => {
210 disable_renderer_select_placeholder();
211 toggle_renderer_type( event.target.value );
212 toggle_chart_types_by_render( event.target.value );
213 });
214
215 }
216
217 /**
218 * Disable the placeholder option in the renderer select.
219 */
220 function disable_renderer_select_placeholder() {
221 const placeholderOption = document.querySelector('#library-select-placeholder');
222 if ( placeholderOption && placeholderOption.disabled === false ) {
223 placeholderOption.disabled = true;
224 }
225 }
226
227 /**
228 * Toggle the renderer type class based on the given renderer type.
229 *
230 * The class is used to style the chart type picker based on the given renderer library.
231 *
232 * @param {('GoogleCharts' | 'ChartJS' | 'DataTable')} rendererType The renderer type to toggle the class.
233 */
234 function toggle_renderer_type( rendererType ) {
235 const typePicker = document.querySelector('#type-picker');
236 if ( ! typePicker ) {
237 return;
238 }
239
240 typePicker.classList.remove('lib-GoogleCharts', 'lib-ChartJS', 'lib-DataTable');
241 typePicker.classList.add(`lib-${rendererType}`);
242 }
243
244 /**
245 * Toggle chart types based on the given renderer type.
246 *
247 * @param {('GoogleCharts' | 'ChartJS' | 'DataTable')} rendererType The renderer type to filter the chart types.
248 */
249 function toggle_chart_types_by_render( rendererType ) {
250 document.querySelectorAll('.type-box').forEach( typeBox => {
251 const hasLib = typeBox.classList.contains(`type-lib-${rendererType}`);
252 typeBox.classList.toggle('viz-hidden', ! hasLib );
253
254 // Reset unavailable chart type selection.
255 const chartOption = typeBox.querySelector('input[type="radio"]');
256 if ( ! hasLib && chartOption?.checked ) {
257 chartOption.checked = false;
258 }
259 });
260
261 enable_libraries_for($('input.type-radio:checked').val(), $typeVsLibrary);
262 }
263
264 function enable_libraries_for($type, $typeVsLibrary) {
265 $('select.viz-select-library option').addClass('disabled').attr('disabled', 'disabled');
266 $('select.viz-select-library option .premium-label').remove();
267 $('select.viz-select-library option').append('<span class="premium-label"> (PREMIUM)</span>');
268 var $libs = $typeVsLibrary[$type];
269 $.each($libs, function( i, $lib ) {
270 $('select.viz-select-library option[value="' + $lib + '"]').removeClass('disabled').removeAttr('disabled');
271 $('select.viz-select-library option[value="' + $lib + '"] .premium-label').remove();
272 });
273 $('select.viz-select-library').val( $('select.viz-select-library option:not(.disabled)').val() );
274 }
275
276 function init_permissions(){
277 $('.visualizer-permission').chosen({
278 width : '50%',
279 search_contains : true
280 });
281
282 $('.visualizer-permission-type').each(function(x, y){
283 var type = $(y).attr('data-visualizer-permission-type');
284 var child = $('.visualizer-permission-' + type + '-specific');
285 if($(y).val() === 'all'){
286 child.next('div.chosen-container').hide();
287 return;
288 }
289 });
290
291 $('.visualizer-permission-type').on('change', function(evt, params) {
292 var type = $(this).attr('data-visualizer-permission-type');
293 var child = $('.visualizer-permission-' + type + '-specific');
294 child.empty();
295 if(params.selected === 'all'){
296 child.next('div.chosen-container').hide();
297 return;
298 } else {
299 child.next('div.chosen-container').show();
300 }
301 child.append('<option value="">' + visualizer.l10n['loading'] + '</option>').trigger('chosen:updated');
302 $.ajax({
303 url : visualizer.ajax['url'],
304 method : 'post',
305 data : {
306 'action' : visualizer.ajax['actions']['permissions'],
307 'nonce' : visualizer.ajax['nonces']['permissions'],
308 'type' : params.selected
309 },
310 success : function(d, textStatus, XMLHttpRequest){
311 if(d.success) {
312 child.empty();
313 $.each(d.data, function(k, v){
314 child.append('<option value="' + k + '">' + v + '</option>');
315 });
316 child.trigger('chosen:updated');
317 }
318 }
319 });
320 });
321 }
322
323 // https://codemirror.net/
324 function init_db_import_component(){
325 var table_columns = visualizer.db_query.tables;
326 var code_mirror = wp.CodeMirror || CodeMirror;
327 var cm = code_mirror.fromTextArea($('.visualizer-db-query').get(0), {
328 value: $('.visualizer-db-query').val(),
329 autofocus: true,
330 mode: 'text/x-mysql',
331 lineWrapping: true,
332 dragDrop: false,
333 matchBrackets: true,
334 autoCloseBrackets: true,
335 extraKeys: {"Shift-Space": "autocomplete"},
336 hintOptions: { tables: table_columns }
337 });
338
339 // force refresh so that the query shows on first time load. Otherwise you have to click on the editor for it to show.
340 $('body').on('visualizer:db:query:focus', function(event, data){
341 cm.refresh();
342 });
343
344 cm.focus();
345
346 // update text area.
347 cm.on('inputRead', function(x, y){
348 cm.save();
349 });
350
351 // backspace and delete do not register so the text box does not get empty if the entire query is deleted
352 // from the editor. Let's force this.
353 $('body').on('visualizer:db:query:update', function(event, data){
354 cm.save();
355 });
356
357 // clear the editor.
358 $('body').on('visualizer:db:query:setvalue', function(event, data){
359 cm.setValue(data.value);
360 cm.clearHistory();
361 cm.refresh();
362 });
363
364 // set an option at runtime?
365 $('body').on('visualizer:db:query:changeoption', function(event, data){
366 cm.setOption(data.name, data.value);
367 });
368 }
369
370 function init_filter_import() {
371 $( '#db-filter-save-button' ).on( 'click', function(){
372 $('#vz-filter-wizard').submit();
373 });
374 }
375
376 function init_db_import(){
377 $( '#visualizer-db-query' ).css("z-index", "-1").hide();
378
379 init_db_import_component();
380
381 $('#visualizer-query-fetch').on('click', function(e){
382
383 $('body').trigger('visualizer:db:query:update', {});
384 if($('.visualizer-db-query').val() === ''){
385 return;
386 }
387
388 start_ajax($('#visualizer-db-query'));
389 $('.db-wizard-results').empty();
390 $('.db-wizard-error').empty();
391 $.ajax({
392 url : ajaxurl,
393 method : 'post',
394 data : {
395 'action' : visualizer.ajax['actions']['db_get_data'],
396 'security' : visualizer.ajax['nonces']['db_get_data'],
397 'params' : $('#db-query-form').serialize()
398 },
399 success : function(data){
400 if(data.success){
401 $('.db-wizard-results').html(data.data.table);
402 $('#results').DataTable({
403 "paging": false
404 });
405 }else{
406 $('.db-wizard-error').html(data.data.msg);
407 }
408 },
409 complete: function(){
410 end_ajax($('#visualizer-db-query'));
411 }
412 });
413 });
414
415 $( '#db-chart-button' ).on( 'click', function(){
416
417 $('body').off('visualizer:change:action').on('visualizer:change:action', function(e){
418 var filter_button = $( '#db-chart-button' );
419 $( '#visualizer-db-query' ).css("z-index", "-1").hide();
420 filter_button.val( filter_button.attr( 'data-t-chart' ) );
421 filter_button.html( filter_button.attr( 'data-t-chart' ) );
422 filter_button.attr( 'data-current', 'chart' );
423 $( '#canvas' ).css("z-index", "1").show();
424 });
425
426 $('#content').css('width', 'calc(100% - 350px)');
427 if( $(this).attr( 'data-current' ) === 'chart'){
428 $(this).val( $(this).attr( 'data-t-filter' ) );
429 $(this).html( $(this).attr( 'data-t-filter' ) );
430 $(this).attr( 'data-current', 'filter' );
431 $( '.visualizer-editor-lhs' ).hide();
432 $( '#visualizer-db-query' ).css("z-index", "9999").show();
433 $('body').trigger('visualizer:db:query:focus', {});
434 $( '#canvas' ).hide();
435 }else{
436 var filter_button = $(this);
437 $( '#visualizer-db-query' ).css("z-index", "-1").hide();
438 $('#canvas').lock();
439 filter_button.val( filter_button.attr( 'data-t-chart' ) );
440 filter_button.html( filter_button.attr( 'data-t-chart' ) );
441 filter_button.attr( 'data-current', 'chart' );
442 $( '#canvas' ).css("z-index", "1").show();
443 $( '#db-chart-save-button' ).trigger('click');
444 }
445 } );
446
447 $( '#db-chart-save-button' ).on( 'click', function(){
448 // submit only if a query has been provided.
449 if($('#db-query-form .visualizer-db-query').val().length > 0){
450 $('#viz-db-wizard-params').val($('#db-query-form').serialize());
451 $('#vz-db-wizard').submit();
452 }else{
453 $('#canvas').unlock();
454 }
455 });
456 }
457
458 function init_json_import(){
459 if(typeof visualizer === 'undefined'){
460 return;
461 }
462
463 var regex = new RegExp(visualizer.json_tag_separator, 'g');
464
465 $( '#visualizer-json-screen' ).css("z-index", "-1").hide();
466 $('.visualizer-json-form').accordion({
467 heightStyle: 'content',
468 active: 0
469 });
470 $('.visualizer-json-subform').accordion({
471 heightStyle: 'content',
472 active: false,
473 collapsible: true
474 });
475
476 // open the accordions by default if they are indicated with the 'open' class.
477 $('.visualizer-json-subform .viz-substep.open').each(function(i, e){
478 $('.visualizer-json-subform').accordion( "option", "active", i );
479 });
480
481 // toggle between chart and create/modify parameters
482 $( '#json-chart-button, #woo-chart-button' ).on( 'click', function(){
483
484 $('body').off('visualizer:change:action').on('visualizer:change:action', function(e){
485 var filter_button = $( '#json-chart-button, #woo-chart-button' );
486 $( '#visualizer-json-screen' ).css("z-index", "-1").hide();
487 filter_button.val( filter_button.attr( 'data-t-chart' ) );
488 filter_button.html( filter_button.attr( 'data-t-chart' ) );
489 filter_button.attr( 'data-current', 'chart' );
490 $( '#canvas' ).css("z-index", "1").show();
491 $( '#vz-import-woo-report' ).find( 'select, input' ).removeAttr( 'disabled' );
492 });
493
494 if ( 'json-chart-button' === $( this ).attr( 'id' ) ) {
495 $( '#vz-import-woo-report' ).find( 'select, input' ).attr( 'disabled', true );
496 } else {
497 $( '#vz-import-woo-report' ).find( 'select, input' ).removeAttr( 'disabled' );
498 }
499 $('#content').css('width', 'calc(100% - 100px)');
500 if( $(this).attr( 'data-current' ) === 'chart'){
501 // toggle from chart to LHS form
502 $(this).val( $(this).attr( 'data-t-filter' ) );
503 $(this).html( $(this).attr( 'data-t-filter' ) );
504 $(this).attr( 'data-current', 'filter' );
505 $( '.visualizer-editor-lhs' ).hide();
506 $( '#visualizer-json-screen' ).css("z-index", "9999").show();
507 if ( 'woo-chart-button' === $( this ).attr( 'id' ) && '' !== $( '#vz-woo-source:visible' ).val() ) {
508 $( '#vz-import-json-url' ).val( visualizer.rest_base + $( '#vz-woo-source' ).val() ).attr( 'readonly', true );
509 } else {
510 if ( 'undefined' !== $( '#vz-import-json-url' ).attr( 'readonly' ) ) {
511 $( '#vz-import-json-url' ).val( '' ).removeAttr( 'readonly' ).removeAttr( 'value' );
512 $('#json-endpoint-form')[0].reset();
513 $('.visualizer-json-form h3.viz-step:not(.step1)').addClass('ui-state-disabled');
514 }
515 }
516 $( '#canvas' ).hide();
517 }else{
518 // toggle from LHS form to chart
519 $( '#json-conclude-form' ).trigger('submit');
520 }
521 } );
522
523 $('body').on('visualizer:json:form:submit', function() {
524 var filter_button = $( '#json-chart-button, #woo-chart-button' );
525 $( '#visualizer-json-screen' ).css("z-index", "-1").hide();
526 $('#canvas').lock();
527 filter_button.val( filter_button.attr( 'data-t-chart' ) );
528 filter_button.html( filter_button.attr( 'data-t-chart' ) );
529 filter_button.attr( 'data-current', 'chart' );
530 end_ajax( $( '#visualizer-json-screen' ) );
531 $( '#canvas' ).removeClass('visualizer-chart-loaded').css("z-index", "1").show();
532 });
533
534
535 // fetch the roots for the provided endpoint
536 $( '#visualizer-json-fetch' ).on( 'click', function(e){
537 e.preventDefault();
538 $('.visualizer-json-form').accordion( 'option', 'active', 0 );
539 $('.visualizer-json-form h3.viz-step:not(.step1)').addClass('ui-state-disabled');
540 $('.json-table').html('');
541 start_ajax( $( '#visualizer-json-screen' ) );
542 $.ajax({
543 url : ajaxurl,
544 method : 'post',
545 data : {
546 'action' : visualizer.ajax['actions']['json_get_roots'],
547 'security' : visualizer.ajax['nonces']['json_get_roots'],
548 'params' : $('#json-endpoint-form').serialize()
549 },
550 success : function(data){
551 if(data.success){
552 $('#vz-import-json-root').empty();
553 $.each(data.data.roots, function(i, name){
554 $('#vz-import-json-root').append('<option value="' + name + '">' + name.replace(regex, visualizer.json_tag_separator_view) + '</option>');
555 });
556 $('#json-root-form').fadeIn('medium');
557 json_accordion_activate(1, true);
558 }else{
559 alert(data.data.msg);
560 }
561 },
562 complete: function(){
563 end_ajax($('#visualizer-json-screen'));
564 }
565 });
566 });
567
568 // fetch the data for the chosen root
569 $( '#visualizer-json-parse' ).on( 'click', function(e){
570 e.preventDefault();
571 $('.visualizer-json-form h3.viz-step:not(.step1):not(.step2)').addClass('ui-state-disabled');
572 $('.json-table').html('');
573 start_ajax( $( '#visualizer-json-screen' ) );
574 $.ajax({
575 url : ajaxurl,
576 method : 'post',
577 data : {
578 'action' : visualizer.ajax['actions']['json_get_data'],
579 'security' : visualizer.ajax['nonces']['json_get_data'],
580 'params' : $('#json-root-form, #json-endpoint-form').serialize()
581 },
582 success : function(data){
583 if(data.success){
584 $('#vz-import-json-paging option:not(.static)').remove();
585 if(data.data.paging.length > 0){
586 var $template = $('#vz-import-json-paging').attr('data-template');
587 $.each(data.data.paging, function(i, name){
588 var display = name.replace(regex, visualizer.json_tag_separator_view);
589 display = $template.replace('?', display);
590 $('#vz-import-json-paging').append('<option value="' + name + '">' + display + '</option>');
591 });
592 $('.json-pagination').show();
593 }
594 $('#json-conclude-form .json-table').html(data.data.table);
595
596 var $table = create_editor_table( '#json-conclude-form' );
597
598 json_accordion_activate(3, true);
599 json_accordion_activate(2, false);
600 $table.columns.adjust().draw();
601 }else{
602 alert(data.data.msg);
603 }
604 },
605 complete: function(){
606 end_ajax($('#visualizer-json-screen'));
607 }
608 });
609 });
610
611 // when the data is set and the chart is updated, toggle the screen so that the chart is shown
612 $('#json-conclude-form').on( 'submit', function(e){
613 // at least one column has to be selected as non-excluded.
614 var count_selected = 0;
615 $('select.viz-select-data-type').each(function(i, element){
616 if($(element).prop('selectedIndex') > 0){
617 count_selected++;
618 }
619 });
620 if(count_selected === 0){
621 alert(visualizer.l10n.select_columns);
622 return false;
623 }
624
625 // populate the form elements that are in the other tabs.
626 $('#json-conclude-form-helper .json-form-element, #json-endpoint-form .json-form-element, #json-root-form .json-form-element, #vz-import-json .json-form-element, #vz-import-woo-report .json-form-element:not(:disabled)').each(function(x, y){
627 $('#json-conclude-form').append('<input type="hidden" name="' + y.name + '" value="' + y.value + '">');
628 });
629
630 $('body').trigger('visualizer:json:form:submit');
631 });
632
633 // update the schedule
634 $('#json-chart-save-button, #woo-chart-save-button').on('click', function(e){
635 e.preventDefault();
636 $('#canvas').lock();
637 var btnID = jQuery( this ).attr( 'id' );
638 $.ajax({
639 url : ajaxurl,
640 method : 'post',
641 data : {
642 'action' : visualizer.ajax['actions']['json_set_schedule'],
643 'security' : visualizer.ajax['nonces']['json_set_schedule'],
644 'chart' : $('#vz-json-time, #vz-woo-time').attr('data-chart'),
645 'time' : $('#vz-json-time, #vz-woo-time').val(),
646 'is_woocommerce_report': 'woo-chart-save-button' === btnID,
647 },
648 success : function(data){
649 // do nothing.
650 },
651 complete: function(){
652 $('#canvas').unlock();
653 }
654 });
655 });
656
657 // Select WooCommerce report endpoint.
658 $( '#vz-woo-source' ).on( 'click', function( e ) {
659 // Trigger change action.
660 $( 'body' ).trigger( 'visualizer:change:action' );
661
662 if ( '' !== $( this ).val() ) {
663 $( '#woo-chart-button, #woo-chart-save-button' ).removeAttr( 'disabled' );
664 } else {
665 $( '#woo-chart-button, #woo-chart-save-button' ).attr( 'disabled', true );
666 }
667 } );
668
669 }
670
671 function init_editor_table() {
672 $('body').on('visualizer:db:editor:table:init', function(event, data){
673 var $table = create_editor_table('.viz-table-editor', data.config);
674 $('body').on('visualizer:db:editor:table:redraw', function(event, data){
675 $table.draw();
676 });
677 });
678 }
679
680 function create_editor_table(element, config) {
681 var settings = {
682 paging: false,
683 searching: false,
684 ordering: false,
685 select: false,
686 scrollX: "100%",
687 scrollY: "400px",
688 info: false,
689 colReorder: {
690 fixedColumnsLeft: 1
691 }
692 };
693
694 // show column visibility button only when more than 6 columns are found (including the Label column)
695 if($(element + ' table.viz-editor-table thead tr th').length > 6){
696 $.extend( settings, {
697 dom: 'Bt',
698 buttons: [
699 {
700 extend: 'colvis',
701 columns: ':gt(0)',
702 collectionLayout: 'four-column'
703 }
704 ]
705 } );
706 }
707 if(config){
708 $.extend( settings, config );
709 }
710
711 var $table = $(element + ' .viz-editor-table').DataTable(settings);
712 return $table;
713 }
714
715 function json_accordion_activate($step, $activate){
716 $('.visualizer-json-form h3.viz-step.step' + ( $step + 1 )).removeClass('ui-state-disabled');
717 if($activate){
718 $('.visualizer-json-form').accordion( 'option', 'active', $step );
719 }
720 }
721
722 function start_ajax(element){
723 element.lock();
724 }
725
726 function end_ajax(element){
727 element.unlock();
728 }
729
730 })(jQuery);
731
732 (function ($) {
733 $.fn.lock = function () {
734 $(this).each(function () {
735 var $this = $(this);
736 var position = $this.css('position');
737
738 if (!position) {
739 position = 'static';
740 }
741
742 switch (position) {
743 case 'absolute':
744 case 'relative':
745 break;
746 default:
747 $this.css('position', 'relative');
748 break;
749 }
750 $this.data('position', position);
751
752 var width = $this.width(),
753 height = $this.height();
754
755 var locker = $('<div class="locker"></div>');
756 locker.width(width).height(height);
757
758 var loader = $('<div class="locker-loader"></div>');
759 loader.width(width).height(height);
760
761 locker.append(loader);
762 $this.append(locker);
763 $(window).resize(function () {
764 $this.find('.locker,.locker-loader').width($this.width()).height($this.height());
765 });
766 });
767
768 return $(this);
769 };
770
771 $.fn.unlock = function () {
772 $(this).each(function () {
773 $(this).find('.locker').remove();
774 $(this).css('position', $(this).data('position'));
775 });
776
777 return $(this);
778 };
779
780 // Telemetry
781 function getChartID() {
782 const urlParams = new URLSearchParams(window.location.search);
783 return urlParams.get('chart') ?? '';
784 }
785
786 const groupId = getChartID();
787
788 const chartTypes = document.querySelector('#viz-types-form')
789 if( chartTypes ) {
790 document.querySelector('.push-right[type=submit]')?.addEventListener('click', async function (event) {
791 if ( typeof window.tiTrk !== 'undefined' ) {
792 event.preventDefault();
793 try {
794 const formData = new FormData(document.querySelector('#viz-types-form'));
795 const savedData = Object.fromEntries(formData);
796
797 tiTrk?.with('visualizer')?.add({
798 feature: 'chart-create',
799 featureComponent: 'saved-data',
800 featureData: {
801 type: savedData?.['type'],
802 library: savedData?.['chart-library']
803 },
804 groupId
805 });
806
807 // Do not make the user to wait too long for the event to be uploaded.
808 const timer = new Promise((resolve) => setTimeout(resolve, 500));
809 await Promise.race([timer, tiTrk?.uploadEvents()]);
810 } catch (e) {
811 console.warn(e);
812 }
813 $('#viz-types-form').submit();
814 }
815 });
816 }
817
818 [
819 {
820 selector: '#editor-button',
821 featureComponent: 'source-manual-data'
822 },
823 {
824 selector: '#vz-import-file',
825 featureComponent: 'source-import-csv-file'
826 },
827 {
828 selector: '#vz-save-schedule',
829 featureComponent: 'source-import-csv-remote'
830 },
831 {
832 selector: '#visualizer-json-fetch',
833 featureComponent: 'source-import-json-remote'
834 },
835 {
836 selector: '#existing-chart',
837 featureComponent: 'source-import-chart'
838 },
839 {
840 selector: '#filter-chart-button',
841 featureComponent: 'source-import-wordpress',
842 },
843 {
844 selector: '#woo-chart-button',
845 featureComponent: 'source-import-woocommerce'
846 },
847 {
848 selector: '#db-chart-button',
849 featureComponent: 'source-import-database'
850 }
851 ].forEach(({ selector, featureComponent }) => {
852 document.querySelector(selector)?.addEventListener('click', function () {
853 window?.tiTrk?.with('visualizer')?.set('used-source',{
854 feature: 'chart-edit-used-source',
855 featureComponent,
856 groupId
857 });
858 });
859 });
860 })(jQuery);
861
862
863 document.querySelector('#viz-copy-shortcode')?.addEventListener('click', function() {
864 var copyText = document.querySelector('#viz-shortcode')?.value;
865 if ( !copyText ) {
866 return;
867 }
868
869 navigator.clipboard.writeText(copyText);
870 alert(visualizer.l10n.copied);
871 });
872
873 // Connect Chart Backend Title Info Panel with the field from the settings form.
874 const interactiveBackendTitleField = document.querySelector( '#viz-backend-name' );
875 const backendTitleSave = document.querySelector( '#settings-form input[name="backend-title"]' );
876
877 if ( interactiveBackendTitleField && backendTitleSave ) {
878 interactiveBackendTitleField.addEventListener('input', function() {
879 backendTitleSave.value = this.value;
880 });
881 }
882