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 +219 -21 3.10.143.11.10 View file →
@@ -7,11 +7,12 @@
7 7 /* global vizHaveSettingsChanged */
8 8
9 9 (function ($) {
10 10 $(window).on('load', function(){
11 - // scroll to the selected chart type.
12 - if($('label.type-label.type-label-selected').length > 0) {
13 - $('label.type-label.type-label-selected')[0].scrollIntoView();
11 + let chart_select = $('#chart-select');
12 + if(chart_select.length > 0){
13 + // scroll to the selected chart type.
14 + $('#chart-select')[0].scrollIntoView();
14 15 }
15 16 });
16 17
17 18 $(document).ready(function () {
@@ -144,9 +145,9 @@
144 145 $('#cancel-button').click(function () {
145 146 $('#cancel-form').submit();
146 147 });
147 148
148 - init_type_vs_library();
149 + init_available_chart_list();
149 150
150 151 $('.viz-abort').on('click', function(e){
151 152 e.preventDefault();
152 153 window.parent.postMessage('visualizer:mediaframe:close', '*');
@@ -153,27 +154,122 @@
153 154 });
154 155
155 156 }
156 157
157 - function init_type_vs_library() {
158 - var $data = $('select.viz-select-library').attr('data-type-vs-library');
159 - if(typeof $data === 'undefined' || $data.length === 0){
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 ) {
160 166 return;
161 167 }
162 - var $typeVsLibrary = JSON.parse( $('select.viz-select-library').attr('data-type-vs-library') );
163 - // disable all unsupported libraries for the chart type.
164 - $('input.type-radio').on('click', function(){
165 - enable_libraries_for($(this).val(), $typeVsLibrary);
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 + });
166 206 });
167 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 +
168 261 enable_libraries_for($('input.type-radio:checked').val(), $typeVsLibrary);
169 262 }
170 263
171 264 function enable_libraries_for($type, $typeVsLibrary) {
172 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>');
173 268 var $libs = $typeVsLibrary[$type];
174 269 $.each($libs, function( i, $lib ) {
175 270 $('select.viz-select-library option[value="' + $lib + '"]').removeClass('disabled').removeAttr('disabled');
271 + $('select.viz-select-library option[value="' + $lib + '"] .premium-label').remove();
176 272 });
177 273 $('select.viz-select-library').val( $('select.viz-select-library option:not(.disabled)').val() );
178 274 }
179 275
@@ -181,9 +277,9 @@
181 277 $('.visualizer-permission').chosen({
182 278 width : '50%',
183 279 search_contains : true
184 280 });
185 -
281 +
186 282 $('.visualizer-permission-type').each(function(x, y){
187 283 var type = $(y).attr('data-visualizer-permission-type');
188 284 var child = $('.visualizer-permission-' + type + '-specific');
189 285 if($(y).val() === 'all'){
@@ -190,9 +286,9 @@
190 286 child.next('div.chosen-container').hide();
191 287 return;
192 288 }
193 289 });
194 -
290 +
195 291 $('.visualizer-permission-type').on('change', function(evt, params) {
196 292 var type = $(this).attr('data-visualizer-permission-type');
197 293 var child = $('.visualizer-permission-' + type + '-specific');
198 294 child.empty();
@@ -235,9 +331,9 @@
235 331 lineWrapping: true,
236 332 dragDrop: false,
237 333 matchBrackets: true,
238 334 autoCloseBrackets: true,
239 - extraKeys: {"Ctrl-Space": "autocomplete"},
335 + extraKeys: {"Shift-Space": "autocomplete"},
240 336 hintOptions: { tables: table_columns }
241 337 });
242 338
243 339 // force refresh so that the query shows on first time load. Otherwise you have to click on the editor for it to show.
@@ -245,9 +341,9 @@
245 341 cm.refresh();
246 342 });
247 343
248 344 cm.focus();
249 -
345 +
250 346 // update text area.
251 347 cm.on('inputRead', function(x, y){
252 348 cm.save();
253 349 });
@@ -256,9 +352,9 @@
256 352 // from the editor. Let's force this.
257 353 $('body').on('visualizer:db:query:update', function(event, data){
258 354 cm.save();
259 355 });
260 -
356 +
261 357 // clear the editor.
262 358 $('body').on('visualizer:db:query:setvalue', function(event, data){
263 359 cm.setValue(data.value);
264 360 cm.clearHistory();
@@ -287,9 +383,9 @@
287 383 $('body').trigger('visualizer:db:query:update', {});
288 384 if($('.visualizer-db-query').val() === ''){
289 385 return;
290 386 }
291 -
387 +
292 388 start_ajax($('#visualizer-db-query'));
293 389 $('.db-wizard-results').empty();
294 390 $('.db-wizard-error').empty();
295 391 $.ajax({
@@ -326,9 +422,9 @@
326 422 filter_button.attr( 'data-current', 'chart' );
327 423 $( '#canvas' ).css("z-index", "1").show();
328 424 });
329 425
330 - $('#content').css('width', 'calc(100% - 300px)');
426 + $('#content').css('width', 'calc(100% - 350px)');
331 427 if( $(this).attr( 'data-current' ) === 'chart'){
332 428 $(this).val( $(this).attr( 'data-t-filter' ) );
333 429 $(this).html( $(this).attr( 'data-t-filter' ) );
334 430 $(this).attr( 'data-current', 'filter' );
@@ -375,9 +471,9 @@
375 471 heightStyle: 'content',
376 472 active: false,
377 473 collapsible: true
378 474 });
379 -
475 +
380 476 // open the accordions by default if they are indicated with the 'open' class.
381 477 $('.visualizer-json-subform .viz-substep.open').each(function(i, e){
382 478 $('.visualizer-json-subform').accordion( "option", "active", i );
383 479 });
@@ -596,9 +692,9 @@
596 692 };
597 693
598 694 // show column visibility button only when more than 6 columns are found (including the Label column)
599 695 if($(element + ' table.viz-editor-table thead tr th').length > 6){
600 - $.extend( settings, {
696 + $.extend( settings, {
601 697 dom: 'Bt',
602 698 buttons: [
603 699 {
604 700 extend: 'colvis',
@@ -679,5 +775,107 @@
679 775 });
680 776
681 777 return $(this);
682 778 };
683 -})(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 +}