PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.11.10
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.11.10
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/frame.js +589 -56 3.1.13.11.10 View file →
@@ -1,29 +1,61 @@
1 1 /* global prompt */
2 2 /* global visualizer */
3 3 /* global alert */
4 +/* global confirm */
4 5 /* global ajaxurl */
5 6 /* global CodeMirror */
7 +/* global vizHaveSettingsChanged */
6 8
7 9 (function ($) {
8 - $(window).load(function(){
9 - // scroll to the selected chart type.
10 - if($('label.type-label.type-label-selected').length > 0) {
11 - $('label.type-label.type-label-selected')[0].scrollIntoView();
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();
12 15 }
13 16 });
14 17
15 18 $(document).ready(function () {
16 - // open the correct source tab.
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.
17 42 var source = $('#visualizer-chart-id').attr('data-chart-source');
18 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();
19 46
20 47 init_permissions();
21 48
22 49 if(typeof visualizer !== 'undefined' && visualizer.is_pro) {
23 50 init_db_import();
51 + init_filter_import();
24 52 }
25 53
54 + init_json_import();
55 +
56 + init_editor_table();
57 +
26 58 // update the manual configuation link to point to the correct chart type.
27 59 var type = $('#visualizer-chart-id').attr('data-chart-type');
28 60 var chart_type_in_api_link = type + 'chart';
29 61 switch (type) {
@@ -42,22 +74,10 @@
42 74 $('.type-label-selected').removeClass('type-label-selected');
43 75 $(this).parent().addClass('type-label-selected');
44 76 });
45 77
46 - $('#vz-chart-settings h2').click(function () {
47 - $("#vz-chart-source").hide();
48 - $("#vz-chart-permissions").removeClass('open').addClass('bottom-fixed');
49 - $(this).parent().removeClass('bottom-fixed').addClass('open');
50 - $("#vz-chart-permissions .viz-group-header").hide();
51 - return false;
52 - });
53 - $('#vz-chart-settings .customize-section-back').click(function () {
54 - $("#vz-chart-source").show();
55 - $(this).parent().parent().removeClass('open').addClass('bottom-fixed');
56 -
57 - return false;
58 - });
59 - $('.viz-group-title').click(function () {
78 + // collapse other open sections of this group
79 + $(document).on('click', '.viz-group-title', function () {
60 80 var parent = $(this).parent();
61 81
62 82 if (parent.hasClass('open')) {
63 83 parent.removeClass('open');
@@ -64,14 +84,32 @@
64 84 } else {
65 85 parent.parent().find('.viz-group.open').removeClass('open');
66 86 parent.addClass('open');
67 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');
68 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 +
69 107 $('#view-remote-file').click(function () {
70 - var url = $(this).parent().find('#remote-data').val();
108 + var url = $(this).parent().find('#vz-schedule-url').val();
71 109
72 110 if (url !== '') {
73 - if (/^([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)) {
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)) {
74 112 if (url.substr(url.length - 8) === '/pubhtml') {
75 113 url = url.substring(0, url.length - 8) + '/export?format=csv';
76 114 }
77 115
@@ -90,17 +128,17 @@
90 128 $(this).parent().submit();
91 129 }
92 130 });
93 131
94 - $('#thehole').load(function () {
132 + $( window ).on( 'load', function() {
95 133 $('#canvas').unlock();
96 - });
134 + } );
97 135
98 - $('.viz-section-title').click(function () {
136 + $(document).on('click', '.viz-section-title', function () {
99 137 $(this).toggleClass('open').parent().find('.viz-section-items').toggle();
100 138 });
101 139
102 - $('.more-info').click(function () {
140 + $(document).on('click', '.more-info', function () {
103 141 $(this).parent().find('.viz-section-description:first').toggle();
104 142 return false;
105 143 });
106 144
@@ -107,45 +145,141 @@
107 145 $('#cancel-button').click(function () {
108 146 $('#cancel-form').submit();
109 147 });
110 148
111 - });
149 + init_available_chart_list();
112 150
113 - function init_permissions(){
114 - $('#vz-chart-permissions h2').click(function () {
115 - $("#vz-chart-source").hide();
116 - $("#vz-chart-permissions .viz-group-header").show();
117 - $("#vz-chart-settings").removeClass('open').addClass('bottom-fixed');
151 + $('.viz-abort').on('click', function(e){
152 + e.preventDefault();
153 + window.parent.postMessage('visualizer:mediaframe:close', '*');
154 + });
118 155
119 - $('#settings-button').click(function(e) {
120 - e.preventDefault();
121 - $('#permissions-form').submit();
122 - $('#settings-form').submit();
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 + }
123 205 });
206 + });
124 207
125 - $(this).parent().removeClass('bottom-fixed').addClass('open');
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 + });
126 214
127 - return false;
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 + }
128 259 });
129 - $('#vz-chart-permissions .customize-section-back').click(function () {
130 - $("#vz-chart-source").show();
131 260
132 - $("#vz-chart-permissions .viz-group-header").hide();
133 - $('#settings-button').click(function(e) {
134 - e.preventDefault();
135 - $('#settings-form').submit();
136 - });
261 + enable_libraries_for($('input.type-radio:checked').val(), $typeVsLibrary);
262 + }
137 263
138 - $(this).parent().parent().removeClass('open').addClass('bottom-fixed');
139 -
140 - return false;
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();
141 272 });
273 + $('select.viz-select-library').val( $('select.viz-select-library option:not(.disabled)').val() );
274 + }
142 275
276 + function init_permissions(){
143 277 $('.visualizer-permission').chosen({
144 278 width : '50%',
145 279 search_contains : true
146 280 });
147 -
281 +
148 282 $('.visualizer-permission-type').each(function(x, y){
149 283 var type = $(y).attr('data-visualizer-permission-type');
150 284 var child = $('.visualizer-permission-' + type + '-specific');
151 285 if($(y).val() === 'all'){
@@ -152,9 +286,9 @@
152 286 child.next('div.chosen-container').hide();
153 287 return;
154 288 }
155 289 });
156 -
290 +
157 291 $('.visualizer-permission-type').on('change', function(evt, params) {
158 292 var type = $(this).attr('data-visualizer-permission-type');
159 293 var child = $('.visualizer-permission-' + type + '-specific');
160 294 child.empty();
@@ -197,9 +331,9 @@
197 331 lineWrapping: true,
198 332 dragDrop: false,
199 333 matchBrackets: true,
200 334 autoCloseBrackets: true,
201 - extraKeys: {"Ctrl-Space": "autocomplete"},
335 + extraKeys: {"Shift-Space": "autocomplete"},
202 336 hintOptions: { tables: table_columns }
203 337 });
204 338
205 339 // force refresh so that the query shows on first time load. Otherwise you have to click on the editor for it to show.
@@ -207,9 +341,9 @@
207 341 cm.refresh();
208 342 });
209 343
210 344 cm.focus();
211 -
345 +
212 346 // update text area.
213 347 cm.on('inputRead', function(x, y){
214 348 cm.save();
215 349 });
@@ -218,10 +352,28 @@
218 352 // from the editor. Let's force this.
219 353 $('body').on('visualizer:db:query:update', function(event, data){
220 354 cm.save();
221 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 + });
222 368 }
223 369
370 + function init_filter_import() {
371 + $( '#db-filter-save-button' ).on( 'click', function(){
372 + $('#vz-filter-wizard').submit();
373 + });
374 + }
375 +
224 376 function init_db_import(){
225 377 $( '#visualizer-db-query' ).css("z-index", "-1").hide();
226 378
227 379 init_db_import_component();
@@ -231,9 +383,9 @@
231 383 $('body').trigger('visualizer:db:query:update', {});
232 384 if($('.visualizer-db-query').val() === ''){
233 385 return;
234 386 }
235 -
387 +
236 388 start_ajax($('#visualizer-db-query'));
237 389 $('.db-wizard-results').empty();
238 390 $('.db-wizard-error').empty();
239 391 $.ajax({
@@ -260,9 +412,19 @@
260 412 });
261 413 });
262 414
263 415 $( '#db-chart-button' ).on( 'click', function(){
264 - $('#content').css('width', 'calc(100% - 300px)');
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)');
265 427 if( $(this).attr( 'data-current' ) === 'chart'){
266 428 $(this).val( $(this).attr( 'data-t-filter' ) );
267 429 $(this).html( $(this).attr( 'data-t-filter' ) );
268 430 $(this).attr( 'data-current', 'filter' );
@@ -282,13 +444,282 @@
282 444 }
283 445 } );
284 446
285 447 $( '#db-chart-save-button' ).on( 'click', function(){
286 - $('#viz-db-wizard-params').val($('#db-query-form').serialize());
287 - $('#vz-db-wizard').submit();
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 + }
288 455 });
289 456 }
290 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 +
291 722 function start_ajax(element){
292 723 element.lock();
293 724 }
294 725
@@ -344,5 +775,107 @@
344 775 });
345 776
346 777 return $(this);
347 778 };
348 -})(jQuery);
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 +}