PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.7.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
← All changes | js/wpoadmin.js +676 -149 3.4.2 → 4.7.0 View file →
@@ -43,19 +43,44 @@
43 43 var WP_Optimize = function () {
44 44 var $ = jQuery;
45 45 var debug_level = 0;
46 46 var queue = new Updraft_Queue();
47 + var block_ui = wp_optimize.block_ui;
47 48 var send_command = wp_optimize.send_command;
48 49 var optimization_force = false;
49 50 var optimization_logged_warnings = false;
50 51 var force_single_table_optimization = false;
51 52 var heartbeat = WP_Optimize_Heartbeat();
52 -
53 +
54 + // Dashboard refresh button
55 + $(document).on('click', '#wpo-dashboard-refresh', function(e) {
56 + e.preventDefault();
57 + var $btn = $(this);
58 + var $icon = $btn.find('.dashicons');
59 + $btn.prop('disabled', true);
60 + $icon.addClass('wpo-spinning');
61 + send_command('refresh_dashboard', {}, function(resp) {
62 + if (resp && resp.success) {
63 + if (resp.top_row) {
64 + $('.wpo-top-row').html(resp.top_row);
65 + }
66 + if (resp.mod_grid) {
67 + $('.wpo-mod-grid').html(resp.mod_grid);
68 + }
69 + }
70 + }).fail(function() {
71 + block_ui(wpoptimize.something_wrong_try_again, {}, 3000);
72 + }).always(function() {
73 + $btn.prop('disabled', false);
74 + $icon.removeClass('wpo-spinning');
75 + });
76 + });
77 +
53 78 /*
54 79 * Enable select all checkbox for optimizations list.
55 80 */
56 81 define_select_all_checkbox($('#select_all_optimizations'), $('#optimizations_list .optimization_checkbox'));
57 -
82 +
58 83 /**
59 84 * Either display normally, or grey-out, the scheduling options, depending on whether any schedule has been selected.
60 85 *
61 86 * @return {string}
@@ -76,28 +101,8 @@
76 101 $('#enable-schedule').on('change', function () {
77 102 enable_or_disable_schedule_options();
78 103 });
79 104
80 - // table sorter library.
81 - // This calls the tablesorter library in order to sort the table information correctly.
82 - // There is a fix below on line 172 to apply applyWidgets on load to avoid display hidden for tabs.
83 - // add parser through the tablesorter addParser method
84 - $.tablesorter.addParser({
85 - // set a unique id
86 - id: 'sizes',
87 - is: function(s) {
88 - // return false so this parser is not auto detected
89 - return false;
90 - },
91 - format: function(cell_content, table, cell) {
92 - var val = $(cell).data('raw_value');
93 - if (!val) val = 0;
94 - return parseInt(val);
95 - },
96 - // set type, either numeric or text
97 - type: 'numeric'
98 - });
99 -
100 105 /*
101 106 * Triggered when the database tabs are loaded.
102 107 */
103 108
@@ -105,52 +110,46 @@
105 110 /*
106 111 * Setup table events and tablesorter
107 112 */
108 113
109 - var table_list_filter = $('#wpoptimize_table_list_filter'),
110 - table_list = $('#wpoptimize_table_list'),
111 - table_footer_line = $('#wpoptimize_table_list tbody:last'),
112 - tables_not_found = $('#wpoptimize_table_list_tables_not_found');
114 + var elTable = document.getElementById('wpoptimize_table_list');
113 115
114 - table_list.tablesorter({
115 - theme: 'default',
116 - widgets: ['zebra', 'rows', 'filter'],
117 - cssInfoBlock: "tablesorter-no-sort",
118 - // This option is to specify with columns will be disabled for sorting
119 - headers: {
120 - 2: {sorter: 'digit'},
121 - 3: {sorter: 'sizes'},
122 - 4: {sorter: 'sizes'},
123 - // For Column Action
124 - 7: {sorter: false }
125 - },
126 - widgetOptions: {
127 - // filter_anyMatch replaced! Instead use the filter_external option
128 - // Set to use a jQuery selector (or jQuery object) pointing to the
129 - // external filter (column specific or any match)
130 - filter_external: table_list_filter,
131 - // add a default type search to the second table column
132 - filter_defaultFilter: { 2 : '~{query}' }
116 + if (null === elTable) return;
117 +
118 + enhanceSortableAccessibility([elTable]);
119 +
120 + document.getElementById('wpoptimize_table_list_filter').addEventListener('input', function () {
121 + var filter = this.value.toLowerCase();
122 + var regex = new RegExp(filter, 'i');
123 + var tbody = elTable.querySelector('tbody');
124 + var tfoot = elTable.querySelector('tfoot');
125 + var rows = tbody.getElementsByTagName('tr');
126 + var hidden = 0;
127 +
128 + for (var i = 0; i < rows.length; i++) {
129 + var cell = rows[i].getElementsByTagName('td')[1];
130 + if (cell) {
131 + var value = cell.getAttribute('data-tablename');
132 + if (regex.test(value)) {
133 + rows[i].style.display = "";
134 + } else {
135 + rows[i].style.display = "none";
136 + hidden++;
137 + }
138 + }
133 139 }
134 - });
135 140
136 - /*
137 - * After tables filtered check if we need show table footer and No tables message.
138 - */
139 - table_list.on('filterEnd', function() {
140 - var search_value = table_list_filter.val().trim();
141 -
142 - if ('' == search_value) {
143 - table_footer_line.show();
141 + if (tfoot) tfoot.style.display = hidden > 0 ? "none" : "";
142 +
143 + var tables_not_found = document.getElementById('wpoptimize_table_list_tables_not_found');
144 +
145 + // Check if rows are visible
146 + if (hidden === rows.length) {
147 + tables_not_found.style.display = 'block';
144 148 } else {
145 - table_footer_line.hide();
149 + tables_not_found.style.display = 'none';
146 150 }
147 -
148 - if (0 == $('#the-list tr:visible', table_list).length) {
149 - tables_not_found.show();
150 - } else {
151 - tables_not_found.hide();
152 - }
151 +
153 152 });
154 153
155 154 /*
156 155 * Setup force optimization checkboxes and associated events
@@ -186,8 +185,12 @@
186 185
187 186 // Update single table optimization buttons state on load.
188 187 update_single_table_optimization_buttons(force_single_table_optimization);
189 188
189 + // Attach warning events
190 + add_warning_for_delete_post_meta_action();
191 + add_warning_for_delete_orphaned_relationship_data_action();
192 +
190 193 });
191 194
192 195 /**
193 196 * Temporarily show a dashboard notice, and then remove it. The HTML will be prepended to the .wrap.wp-optimize-wrap element.
@@ -276,8 +279,10 @@
276 279 // Trigger the global tab change events when changing page
277 280 var active_tab = $('.wpo-page[data-whichpage='+params.page+']').find('.nav-tab-wrapper .nav-tab-active');
278 281 $('#wp-optimize-wrap').trigger('tab-change', { page: params.page, tab: active_tab.data('tab') });
279 282 $('#wp-optimize-wrap').trigger('tab-change/'+params.page+'/'+active_tab.data('tab'), { content: $('#' + active_tab.attr('id') + '-contents')});
283 +
284 + maybe_show_too_many_tables_popup(active_tab.attr('data-tab'));
280 285 });
281 286
282 287 // set a time out, as needs to be done once the rest is loaded
283 288 setTimeout(function() {
@@ -295,9 +300,9 @@
295 300 if (!clicked_tab_id) { return; }
296 301
297 302 toggle_mobile_menu(false);
298 303 // Mobile menu TABS toggle
299 - if ($(this).is('[role="toggle-menu"]')) {
304 + if ($(this).is('[id^="wp-optimize-nav-tab-menu-"]')) {
300 305 toggle_mobile_menu(true);
301 306 return;
302 307 }
303 308
@@ -356,22 +361,24 @@
356 361
357 362 var database_tabs_loading = false;
358 363 var database_tabs_loaded = false;
359 364 // When showing the tables tab
360 - $('#wp-optimize-wrap').on('tab-change/WP-Optimize/tables', function(e) {
365 + $('#wp-optimize-wrap').on('tab-change/wpo_database/tables', function(e) {
361 366 get_database_tabs();
362 367 });
363 368
364 369 // When showing the optimizations tab
365 - $('#wp-optimize-wrap').on('tab-change/WP-Optimize/optimize', function(event, data) {
370 + $('#wp-optimize-wrap').on('tab-change/wpo_database/optimize', function(event, data) {
366 371 get_database_tabs();
367 372 });
368 373
374 +
369 375 // When showing the settings tab
370 376 $('#wp-optimize-wrap').on('tab-change/wpo_settings/settings', function(event, data) {
371 377 // If the innodb_force_optimize--container is present, fetch the required data.
372 378 // We load the database tabs together, as they need the same processing.
373 379 if (data.content.find('.innodb_force_optimize--container').length) get_database_tabs();
380 + WPO_Status_Report();
374 381 });
375 382
376 383 /**
377 384 * Get the data for the database tabs. We get them at the same time, as they both need the same time consuming requests.
@@ -377,9 +384,9 @@
377 384 * Get the data for the database tabs. We get them at the same time, as they both need the same time consuming requests.
378 385 */
379 386 function get_database_tabs() {
380 387 if (database_tabs_loading || database_tabs_loaded) return;
381 - var container = $('.wpo-page[data-whichpage=WP-Optimize]');
388 + var container = $('.wpo-page[data-whichpage=wpo_database]');
382 389 var shade = container.find('.wpo_shade');
383 390 shade.removeClass('hidden');
384 391 database_tabs_loading = true;
385 392 send_command('get_database_tabs', {}, function(response) {
@@ -385,16 +392,71 @@
385 392 send_command('get_database_tabs', {}, function(response) {
386 393 // Set the status to true, to prevent loading again.
387 394 database_tabs_loaded = true;
388 395
389 - // Updtate the optimizations tab
396 + // Update the optimizations tab
390 397 if (response.hasOwnProperty('optimizations')) {
391 398 container.find('.wp-optimize-optimizations-table-placeholder').replaceWith(response.optimizations);
392 399 }
393 400
394 - // Updtate the optimizations tables list
395 - update_tables_list(response);
401 + // If the batch table scan hasn't finished yet, trigger the loading popup so it
402 + // runs automatically. The popup will reload the page once the scan completes.
403 + if (true === response.scan_pending) {
404 + // Add a scan-first notice beneath the disabled "Optimize database tables" info.
405 + var $optimizeDbInfo = $('#optimization_info_optimizetables');
406 + if ($optimizeDbInfo.length) {
407 + $optimizeDbInfo.append(
408 + '<br><span class="wpo-scan-pending-notice">' +
409 + wpoptimize.db_tables_scan_pending_optimize + ' ' +
410 + '<a href="#" id="wpo-optimizations-tab-scan-link">' + wpoptimize.db_tables_scan_button + '</a>' +
411 + '</span>'
412 + );
413 + $('#wpo-optimizations-tab-scan-link').on('click', function(e) {
414 + e.preventDefault();
415 + var scanBtn = document.getElementById('wpo-load-tables-in-batches');
416 + if (scanBtn) scanBtn.click();
417 + });
418 + }
396 419
420 + // Replace the spinner placeholder in the tables tab with a scan-first notice.
421 + $('#wpoptimize_table_list tbody').html(
422 + '<tr>' +
423 + '<td></td>' +
424 + '<td colspan="6" style="text-align:center;padding:1em;">' +
425 + wpoptimize.db_tables_scan_pending_list + ' ' +
426 + '<a href="#" id="wpo-tables-tab-scan-link">' + wpoptimize.db_tables_scan_button + '</a>' +
427 + '</td>' +
428 + '<td></td>' +
429 + '</tr>'
430 + );
431 + $('#wpo-tables-tab-scan-link').on('click', function(e) {
432 + e.preventDefault();
433 + var scanBtn = document.getElementById('wpo-load-tables-in-batches');
434 + if (scanBtn) scanBtn.click();
435 + });
436 +
437 + var scanBtn = document.getElementById('wpo-load-tables-in-batches');
438 + if (scanBtn) {
439 + // If the onboarding wizard modal is currently open in the DOM, wait for it
440 + // to close before auto-clicking — otherwise the thickbox would stack on top.
441 + var onboardingRoot = document.getElementById('onboarding-modal-root');
442 + if (onboardingRoot && onboardingRoot.querySelector('[data-state="open"]')) {
443 + var scanObserver = new MutationObserver(function(mutations, obs) {
444 + if (!onboardingRoot.querySelector('[data-state="open"]')) {
445 + obs.disconnect();
446 + scanBtn.click();
447 + }
448 + });
449 + scanObserver.observe(onboardingRoot, { childList: true, subtree: true, attributes: true, attributeFilter: ['data-state'] });
450 + } else {
451 + scanBtn.click();
452 + }
453 + }
454 + } else {
455 + // Update the optimizations tables list
456 + update_tables_list(response);
457 + }
458 +
397 459 $(document).trigger('wpo_database_tabs_loaded');
398 460
399 461 }).always(function() {
400 462 database_tabs_loading = false;
@@ -411,18 +473,18 @@
411 473 */
412 474 function gather_settings(output_format) {
413 475 var form_data = '',
414 476 output_format = ('undefined' === typeof output_format) ? 'string' : output_format,
415 - $form_elements = $("#wp-optimize-database-settings form input[name!='action'], #wp-optimize-database-settings form select, #wp-optimize-database-settings form textarea, #wp-optimize-general-settings form input[name!='action'], #wp-optimize-general-settings form textarea, #wp-optimize-general-settings form select, #wp-optimize-nav-tab-contents-optimize input[type='checkbox'], .wp-optimize-nav-tab-contents input[name^='enable-auto-backup-']");
477 + $form_elements = $("#wp-optimize-database-settings form input[name!='action'], #wp-optimize-database-settings form select, #wp-optimize-database-settings form textarea, #wp-optimize-general-settings form input[name!='action'], #wp-optimize-general-settings form textarea, #wp-optimize-general-settings form select, #wp-optimize-nav-tab-contents-optimize input[type='checkbox'], .wp-optimize-nav-tab-contents input[name^='enable-auto-backup-'], #wpo-404-detector-form input[type=checkbox]");
416 478
417 479 if ('object' == output_format) {
418 480 form_data = $form_elements.serializeJSON({useIntKeysAsArrayIndex: true});
419 481 } else {
420 - // Excluding the unnecessary 'action' input avoids triggering a very mis-conceived mod_security rule seen on one user's site.
482 + // Excluding the unnecessary 'action' input avoids triggering a very misconceived mod_security rule seen on one user's site.
421 483 form_data = $form_elements.serialize();
422 484
423 485 // Include unchecked checkboxes. user filter to only include unchecked boxes.
424 - $.each($('#wp-optimize-database-settings form input[type=checkbox], #wp-optimize-general-settings form input[type=checkbox], .wp-optimize-nav-tab-contents input[name^="enable-auto-backup-"]')
486 + $.each($('#wp-optimize-database-settings form input[type=checkbox], #wp-optimize-general-settings form input[type=checkbox], .wp-optimize-nav-tab-contents input[name^="enable-auto-backup-"], #wpo-404-detector-form input[type=checkbox]')
425 487 .filter(function (idx) {
426 488 return $(this).prop('checked') == false
427 489 }),
428 490 function (idx, el) {
@@ -564,19 +626,21 @@
564 626 if (response.hasOwnProperty('total_size')) {
565 627 $('#optimize_current_db_size').html(response.total_size);
566 628 }
567 629
568 - // Status check for optimizing tables.
569 - const optimizetables_id = "optimizetables";
570 - if (queue.contains_id(optimizetables_id)) {
571 - $('#optimization_checkbox_' + optimizetables_id).hide();
572 - $('#optimization_spinner_' + optimizetables_id).show();
573 - $('.optimization_button_' + optimizetables_id).prop('disabled', true);
574 - } else {
575 - $('#optimization_checkbox_' + optimizetables_id).show();
576 - $('#optimization_spinner_' + optimizetables_id).hide();
577 - $('.optimization_button_' + optimizetables_id).prop('disabled', false);
578 - $('#optimization_info_' + optimizetables_id).html(wpoptimize.optimization_complete + (optimization_logged_warnings ? (' ' + wpoptimize.with_warnings) : ''));
630 + if ('optimizetables' === id) {
631 + // Status check for optimizing tables.
632 + const optimizetables_id = "optimizetables";
633 + if (queue.contains_id(optimizetables_id)) {
634 + $('#optimization_checkbox_' + optimizetables_id).hide();
635 + $('#optimization_spinner_' + optimizetables_id).show();
636 + $('.optimization_button_' + optimizetables_id).prop('disabled', true);
637 + } else {
638 + $('#optimization_checkbox_' + optimizetables_id).show();
639 + $('#optimization_spinner_' + optimizetables_id).hide();
640 + $('.optimization_button_' + optimizetables_id).prop('disabled', false);
641 + $('#optimization_info_' + optimizetables_id).html(wpoptimize.optimization_complete + (optimization_logged_warnings ? (' ' + wpoptimize.with_warnings) : ''));
642 + }
579 643 }
580 644
581 645 // check if we need update unapproved comments count.
582 646 if (response.result.meta && response.result.meta.hasOwnProperty('awaiting_mod')) {
@@ -765,9 +829,9 @@
765 829
766 830 /*
767 831 * Run single optimization click.
768 832 */
769 - $('#wp-optimize-nav-tab-WP-Optimize-optimize-contents').on('click', 'button.wp-optimize-settings-optimization-run-button', function () {
833 + $('#wp-optimize-nav-tab-wpo_database-optimize-contents').on('click', 'button.wp-optimize-settings-optimization-run-button', function () {
770 834 var optimization_id = $(this).closest('.wp-optimize-settings').data('optimization_id');
771 835 if (!optimization_id) {
772 836 console.log("Optimization ID corresponding to pressed button not found");
773 837 return;
@@ -785,22 +849,247 @@
785 849
786 850 /*
787 851 * Run all optimizations click.
788 852 */
789 - $('#wp-optimize-nav-tab-WP-Optimize-optimize-contents').on('click', '#wp-optimize', function (e) {
790 - var run_btn = $(this);
853 + $('#wp-optimize-nav-tab-wpo_database-optimize-contents #wp-optimize').on('click', function (e) {
854 + e.preventDefault();
855 +
856 + if (null == tmpl_wpo_grouped_warnings_tpl) {
857 + tmpl_wpo_grouped_warnings_tpl = $('#tmpl-wpo-grouped-warnings').html().toString();
858 + }
791 859
792 - e.preventDefault();
860 + user_confirm_destructive_actions(function() {
861 + return function(run_btn) {
862 + // disable run button to avoid double click.
863 + $(run_btn).prop('disabled', true);
864 + save_sites_list_and_do_action(function() {
865 + $(run_btn).prop('disabled', false);
866 + run_optimizations();
867 + });
868 + };
869 + }(this));
870 + });
793 871
794 - // disable run button to avoid double click.
795 - run_btn.prop('disabled', true);
796 - save_sites_list_and_do_action(function() {
797 - run_btn.prop('disabled', false);
798 - run_optimizations();
872 + var tmpl_wpo_grouped_warnings_tpl = null;
873 +
874 + /**
875 + * Prepare the stack of optimizations that the user will need to actively confirm using the popup
876 + * Then show them in sequence
877 + */
878 + function user_confirm_destructive_actions(callback) {
879 + var optimizations = $('#optimizations_list .optimization_checkbox:checked');
880 +
881 + var confirmations_stack = [];
882 +
883 + optimizations.filter(function(i, optim) {
884 + var optimization_id = optim.id.replace('optimization_checkbox_', '');
885 + var destructive_action_popup = $('#tmpl-wpo-' + optimization_id);
886 + return 0 < destructive_action_popup.length;
887 + }).each(function(i, maybe_confirm) {
888 + var optimization_id = maybe_confirm.id.replace('optimization_checkbox_', '');
889 + if (should_user_confirm_action(optimization_id)) {
890 + confirmations_stack.push(optimization_id);
891 + }
799 892 });
800 - });
893 +
894 + user_confirm_destructive_actions_grouped(confirmations_stack, callback);
895 + }
801 896
802 897 /**
898 + * Show confirmation popups for user to accept, in sequence. When done, trigger callback
899 + */
900 + function user_confirm_destructive_actions_grouped(confirmations_stack, callback) {
901 + if (0 < confirmations_stack.length) {
902 + var warning_messages = [];
903 + confirmations_stack.forEach(function(optimization_id) {
904 + var str = $($('#tmpl-wpo-' + optimization_id).html()).children('p').html();
905 + warning_messages.push(str);
906 + });
907 +
908 + wp_optimize.modal.open(
909 + Object.assign(get_destructive_actions_confirm_popup('grouped-warnings'), {
910 + cancel: function() {
911 + // Nothing will be done
912 + },
913 + confirm: function() {
914 + this.close();
915 + callback();
916 + },
917 + content: function() {
918 + return tmpl_wpo_grouped_warnings_tpl.replace('[[warning_messages]]', "<ul><li>" + warning_messages.join("</li><li>") + "</li></ul>");
919 + }
920 + }
921 + ));
922 + } else {
923 + // No confirmations needed
924 + callback();
925 + }
926 + }
927 +
928 + /**
929 + * Pad a string to the left
930 + *
931 + * @param {string} string The string we want to pad
932 + * @param {string} pad Padding character
933 + * @param {int} length Padding length
934 + * @returns string
935 + */
936 + function str_pad_left(string, pad, length) {
937 + return (new Array(length + 1).join(pad) + string).slice(-length);
938 + }
939 +
940 + /**
941 + * Shared state for the "load database tables in batches" feature
942 + *
943 + * @var {object}
944 + */
945 + var wpoDBTableInfo = {
946 + progressText: [],
947 + startTime: null,
948 + updateTimeout: null,
949 + inProgress: false
950 + };
951 +
952 + /**
953 + * Call AJAX command to load table statuses in batches
954 + *
955 + * @param {int} offset Query offset
956 + * @param {bool} start_clean True when this is the first time the function is called
957 + * @param {function} callback Self referenced callback, recursively calls itself until the work is done
958 + * @returns void
959 + */
960 + function load_tables_in_batches(offset, start_clean, callback) {
961 + var e = $("#wpo-load-tables-in-batches-progress");
962 + var limit = parseInt(wpoptimize.high_table_count_threshold);
963 + var start = offset + 1;
964 + var end = offset + limit;
965 +
966 + var progress_text = wpoptimize.loading_tables_in_batches.replace('%1$s', start).replace('%2$s', end);
967 +
968 + if (start_clean || (-1 == wpoDBTableInfo.progressText.indexOf(progress_text))) {
969 + wpoDBTableInfo.progressText.push(progress_text);
970 + e.append($("<div>" + progress_text + "...</div>"));
971 + }
972 +
973 + if (5 < e.children().length) {
974 + e.children()[0].remove();
975 + }
976 +
977 + var spinner = '<img class="wpo-v-middle" height=16 src="'+wpoptimize.spinner_src+'">';
978 + var time_left_container = $('#wpo-load-tables-eta');
979 + if (true == start_clean) {
980 + time_left_container.html(spinner);
981 + }
982 +
983 + send_command('load_tables_in_batches', {offset: offset}, function(result) {
984 + var now = new Date();
985 +
986 + var time_left = 1 <= result.done ? parseInt(((now - wpoDBTableInfo.startTime) / 1000) / result.done * (result.total - result.done)) : 600;
987 + var minutesNum = Math.floor(time_left / 60);
988 + var minutes = str_pad_left(minutesNum, '0', 2);
989 + var seconds = str_pad_left(time_left - minutesNum * 60, '0', 2);
990 +
991 + time_left_container.html(wpoptimize.time_left.replace('%s', '<span id="wpo-load-tables-time-left" rel="' + time_left + '">' + minutes + ':' + seconds + '</span>') + ' ' + spinner);
992 +
993 + if (null != wpoDBTableInfo.updateTimeout) {
994 + clearTimeout(wpoDBTableInfo.updateTimeout);
995 + }
996 +
997 + if (true == result.continue) {
998 + wpoDBTableInfo.updateTimeout = setTimeout(load_tables_update_time_left, 1000);
999 +
1000 + callback(result.done, false, callback);
1001 + } else {
1002 + e.html(wpoptimize.done_reloading + '...');
1003 + time_left_container.html('');
1004 + clearTimeout(wpoDBTableInfo.updateTimeout);
1005 + location.reload();
1006 + }
1007 + }).fail(function() {
1008 + if (null != wpoDBTableInfo.updateTimeout) {
1009 + clearTimeout(wpoDBTableInfo.updateTimeout);
1010 + }
1011 + time_left_container.html('');
1012 + e.append($("<div>" + wpoptimize.something_wrong_try_again + "</div>"));
1013 +
1014 + wpoDBTableInfo.inProgress = false;
1015 + $('#wpo-load-tables-in-batches-button').prop('disabled', false);
1016 + });
1017 + }
1018 +
1019 + /**
1020 + * While AJAX operation runs in background, update time left every second in front-end
1021 + *
1022 + * @returns void
1023 + */
1024 + function load_tables_update_time_left() {
1025 + var time_left_container = $('#wpo-load-tables-time-left');
1026 + var current_time_left = Math.max(0, parseInt(time_left_container.attr('rel')) - 1);
1027 +
1028 + var minutesNum = Math.floor(current_time_left / 60);
1029 + var minutes = str_pad_left(minutesNum, '0', 2);
1030 + var seconds = str_pad_left(current_time_left - minutesNum * 60, '0', 2);
1031 +
1032 + time_left_container.html(minutes + ':' + seconds);
1033 + time_left_container.attr('rel', current_time_left);
1034 +
1035 + wpoDBTableInfo.updateTimeout = setTimeout(load_tables_update_time_left, 1000);
1036 + }
1037 +
1038 + /**
1039 + * Check if we need to show the table load popup and show it
1040 + * Skips auto-opening while the onboarding wizard is active.
1041 + *
1042 + * @param {string} active_tab Only show popup when active_tab='optimize'
1043 + * @returns void
1044 + */
1045 + function maybe_show_too_many_tables_popup(active_tab) {
1046 +
1047 + var $modal = $('#wpo-too-many-tables-popup');
1048 +
1049 + function openTooManyTablesModal(autoShown) {
1050 + // Move the modal to <body> so it isn't hidden by a display:none tab wrapper.
1051 + if (!$modal.parent().is('body')) {
1052 + $('body').append($modal);
1053 + }
1054 + $modal.show();
1055 + $('body').addClass('wpo-modal-is-opened');
1056 + var $closeBtn = $modal.find('.wpo-too-many-tables-close');
1057 + var $bg = $modal.find('.wpo-modal--bg');
1058 + $closeBtn.off('click.wpoModal');
1059 + $bg.off('click.wpoModal');
1060 + if (autoShown) {
1061 + $closeBtn.on('click.wpoModal', function() { location.href = 'plugins.php'; });
1062 + } else {
1063 + $closeBtn.add($bg).on('click.wpoModal', function() {
1064 + $modal.hide();
1065 + $('body').removeClass('wpo-modal-is-opened');
1066 + });
1067 + }
1068 + }
1069 +
1070 + if ('optimize' === active_tab && 'undefined' !== typeof wpo_too_many_tables && true === wpo_too_many_tables && 'undefined' !== typeof wpo_onboarding_active && true !== wpo_onboarding_active) {
1071 + $(document).ready(function() { openTooManyTablesModal(true); });
1072 + }
1073 +
1074 + $('#wpo-load-tables-in-batches').off('click.wpoLoadTablesModal').on('click.wpoLoadTablesModal', function() {
1075 + openTooManyTablesModal(false);
1076 + });
1077 +
1078 + $('#wpo-load-tables-in-batches-button').off('click.wpoLoadTablesInBatches').on('click.wpoLoadTablesInBatches', function() {
1079 + if (wpoDBTableInfo.inProgress) return;
1080 +
1081 + wpoDBTableInfo.inProgress = true;
1082 + $(this).prop('disabled', true);
1083 + wpoDBTableInfo.startTime = new Date();
1084 +
1085 + load_tables_in_batches(wpo_table_scan_offset, true, function() {
1086 + load_tables_in_batches.apply({}, arguments);
1087 + });
1088 + });
1089 + }
1090 +
1091 + /**
803 1092 * Sent command to run selected optimizations and auto backup if selected
804 1093 *
805 1094 * @return void
806 1095 */
@@ -883,16 +1172,15 @@
883 1172 wpo_settings_all_sites_checkbox,
884 1173 wpo_settings_sites_list_items
885 1174 );
886 1175
887 - var sites_list_clicked_count = 0;
1176 + var debounceTimer;
888 1177
889 1178 $([wpo_settings_all_sites_checkbox, wpo_settings_sites_list_items]).each(function() {
890 1179 $(this).on('change', function() {
891 - sites_list_clicked_count++;
892 - setTimeout(function() {
893 - sites_list_clicked_count--;
894 - if (sites_list_clicked_count == 0) update_optimizations_info();
1180 + clearTimeout(debounceTimer);
1181 + debounceTimer = setTimeout(function() {
1182 + update_optimizations_info();
895 1183 }, 1000);
896 1184 });
897 1185 });
898 1186
@@ -996,27 +1284,20 @@
996 1284 *
997 1285 * @return {[type]} optimizations
998 1286 */
999 1287 function run_optimization() {
1000 - $optimizations = $('#optimizations_list .optimization_checkbox:checked');
1288 + var optimizations = $('#optimizations_list .optimization_checkbox:checked').toArray();
1001 1289
1002 - $optimizations.sort(function (a, b) {
1003 - // Convert to IDs.
1004 - a = $(a).closest('.wp-optimize-settings').data('optimization_run_sort_order');
1005 - b = $(b).closest('.wp-optimize-settings').data('optimization_run_sort_order');
1006 - if (a > b) {
1007 - return 1;
1008 - } else if (a < b) {
1009 - return -1;
1010 - } else {
1011 - return 0;
1012 - }
1290 + var sorted_optimizations = optimizations.sort(function (a, b) {
1291 + var aOrder = $(a).closest('.wp-optimize-settings').data('optimization_run_sort_order');
1292 + var bOrder = $(b).closest('.wp-optimize-settings').data('optimization_run_sort_order');
1293 + return aOrder - bOrder; // Ascending order - so all other optimizations will run before optimizetables
1013 1294 });
1014 1295
1015 1296 var optimization_options = {};
1016 1297
1017 - $optimizations.each(function (index) {
1018 - var optimization_id = $(this).closest('.wp-optimize-settings').data('optimization_id');
1298 + sorted_optimizations.forEach(function (element) {
1299 + var optimization_id = $(element).closest('.wp-optimize-settings').data('optimization_id');
1019 1300 if (!optimization_id) {
1020 1301 console.log("Optimization ID corresponding to pressed button not found");
1021 1302 return;
1022 1303 }
@@ -1042,8 +1323,9 @@
1042 1323 };
1043 1324
1044 1325 // update body with new content.
1045 1326 $("#wpoptimize_table_list tbody").remove();
1327 + $("#wpoptimize_table_list tfoot").remove();
1046 1328 $("#wpoptimize_table_list thead").after(response.table_list);
1047 1329
1048 1330 $("#wpoptimize_table_list").trigger("updateAll", [resort, callback]);
1049 1331 }
@@ -1061,8 +1343,14 @@
1061 1343 }
1062 1344
1063 1345 $('#wp_optimize_table_list_refresh').on('click', function (e) {
1064 1346 e.preventDefault();
1347 + // Tables are not available until the batch scan completes — open the scan popup instead.
1348 + if (true === wpo_too_many_tables) {
1349 + var scanBtn = document.getElementById('wpo-load-tables-in-batches');
1350 + if (scanBtn) scanBtn.click();
1351 + return;
1352 + }
1065 1353 var shade = $(this).closest('.wpo-tab-postbox').find('.wpo_shade');
1066 1354 shade.removeClass('hidden');
1067 1355 $('#wpoptimize_table_list tbody').css('opacity', '0.5');
1068 1356 send_command('get_table_list', {refresh_plugin_json: true}, update_tables_list).always(function() {
@@ -1069,10 +1357,26 @@
1069 1357 shade.addClass('hidden');
1070 1358 });
1071 1359 });
1072 1360
1073 - $('#database_settings_form, #settings_form').on('click', '.wpo-save-settings', function (e) {
1361 + $('#wpo-404-detector-form').on('click', '#wpo-404-clear-logs', function (e) {
1074 1362 e.preventDefault();
1363 + block_ui(wpoptimize.please_wait);
1364 + send_command('truncate_404_logs', {}, function (resp) {
1365 + if (resp && resp.hasOwnProperty('success') && resp.success) {
1366 + $('#wpo_404_detector_results').html('');
1367 + }
1368 + if (resp && resp.hasOwnProperty('message') && resp.message) {
1369 + block_ui(resp.message, {}, 3000);
1370 + }
1371 + }).fail(function() {
1372 + block_ui(wpoptimize.something_wrong_try_again, {}, 3000);
1373 + });
1374 + });
1375 +
1376 +
1377 + $('#database_settings_form, #settings_form, #wpo-404-detector-form').on('click', '.wpo-save-settings', function (e) {
1378 + e.preventDefault();
1075 1379 var form = $(this).closest('form');
1076 1380 var spinner = form.find('.wpo-saving-settings');
1077 1381 var form_data = gather_settings();
1078 1382
@@ -1080,9 +1384,9 @@
1080 1384
1081 1385 if (form.form_errors.has_errors()) return;
1082 1386
1083 1387 spinner.show();
1084 - $.blockUI();
1388 + block_ui(wpoptimize.saving);
1085 1389
1086 1390 // when optimizations list in the document - send information about selected optimizations.
1087 1391 if ($('#optimizations_list').length) {
1088 1392 $('#optimizations_list .optimization_checkbox:checked').each(function() {
@@ -1121,8 +1425,9 @@
1121 1425 }
1122 1426
1123 1427 if (resp && resp.hasOwnProperty('settings_auto_cleanup_contents')) {
1124 1428 $('#wpo_auto_cleanup').replaceWith(resp.settings_auto_cleanup_contents);
1429 + WPO_Select2();
1125 1430 }
1126 1431
1127 1432 if (resp && resp.hasOwnProperty('logging_settings_contents')) {
1128 1433 $('#wpo_logging_settings').replaceWith(resp.logging_settings_contents);
@@ -1127,8 +1432,14 @@
1127 1432 if (resp && resp.hasOwnProperty('logging_settings_contents')) {
1128 1433 $('#wpo_logging_settings').replaceWith(resp.logging_settings_contents);
1129 1434 }
1130 1435
1436 + // switch for visibility (performance tab).
1437 + var $wpo_404_detector_btn = $('#wpo_404_detector');
1438 + $wpo_404_detector_btn.prop('checked', !$wpo_404_detector_btn.prop('checked'));
1439 + var $wpo_404_detector_results = $('#wpo_404_detector_results');
1440 + $wpo_404_detector_results.css('display', $wpo_404_detector_btn.prop('checked') ? 'block' : 'none');
1441 +
1131 1442 // Need to refresh the page if enable-admin-menu tick state has changed.
1132 1443 if (resp.save_results.refresh) {
1133 1444 location.reload();
1134 1445 }
@@ -1229,8 +1540,9 @@
1229 1540 btn.prop('disabled', false);
1230 1541 spinner.addClass('visibility-hidden');
1231 1542 action_done_icon.show().removeClass('visibility-hidden').delay(2500).fadeOut('fast', function() {
1232 1543 btn.show();
1544 + action_done_icon.show().addClass('visibility-hidden');
1233 1545 });
1234 1546 });
1235 1547 }
1236 1548
@@ -1303,9 +1615,9 @@
1303 1615 for (i in response) {
1304 1616 if (!response.hasOwnProperty(i)) continue;
1305 1617
1306 1618 dom_id = ['#wp-optimize-settings-', response[i].dom_id].join('');
1307 - info = response[i].info ? response[i].info.join('<br>') : '';
1619 + info = response[i].info ? response[i].info : '';
1308 1620
1309 1621 $(dom_id + ' .wp-optimize-settings-optimization-info').html(info);
1310 1622 }
1311 1623 }
@@ -1538,9 +1850,9 @@
1538 1850 // Handle delete table click
1539 1851 $('#wpoptimize_table_list').on('click', '.run-single-table-delete', function () {
1540 1852 table_to_remove_btn = $(this);
1541 1853 var take_backup_checkbox = $('#enable-auto-backup-1');
1542 - if ('' == wpoptimize.user_always_ignores_table_delete_warning || '1' !== wpoptimize.user_always_ignores_table_delete_warning) {
1854 + if ('' == wpoptimize.user_always_ignores_table_deletion_warning || '1' !== wpoptimize.user_always_ignores_table_deletion_warning) {
1543 1855 wp_optimize.modal.open({
1544 1856 className: 'wpo-confirm',
1545 1857 events: {
1546 1858 'click .wpo-modal--bg': 'close',
@@ -1571,13 +1883,13 @@
1571 1883 this.$('.delete-table').prop('disabled', !enable_button);
1572 1884 },
1573 1885 deleteTable: function() {
1574 1886 // check if user ignore table warning
1575 - var ignores_table_detele_warning_checkbox = this.$('#ignores_table_delete_warning');
1576 - if (ignores_table_detele_warning_checkbox.is(':checked')) {
1577 - send_command('user_ignores_table_delete_warning', {}, function(response) {
1887 + var ignores_table_deletion_warning_checkbox = this.$('#ignores_table_deletion_warning');
1888 + if (ignores_table_deletion_warning_checkbox.is(':checked')) {
1889 + send_command('user_ignores_table_deletion_warning', {}, function(response) {
1578 1890 if (response.success) {
1579 - wpoptimize.user_always_ignores_table_delete_warning = '1';
1891 + wpoptimize.user_always_ignores_table_deletion_warning = '1';
1580 1892 }
1581 1893 });
1582 1894 }
1583 1895 // check if backup checkbox is checked for db tables
@@ -1658,9 +1970,9 @@
1658 1970
1659 1971
1660 1972
1661 1973 /**
1662 - * Send ajax commant to remove single database table.
1974 + * Send ajax command to remove single database table.
1663 1975 *
1664 1976 * @param {Object} btn jQuery object of clicked "Remove" button.
1665 1977 *
1666 1978 * @return void
@@ -1833,9 +2145,9 @@
1833 2145
1834 2146 /**
1835 2147 * Hide introduction notice
1836 2148 */
1837 - $('.wpo-introduction-notice .notice-dismiss, .wpo-introduction-notice .close').on('click', function(e) {
2149 + $('#wp-optimize-wrap').on('click', '.wpo-introduction-notice .notice-dismiss, .wpo-introduction-notice .close', function(e) {
1838 2150 $('.wpo-introduction-notice').remove();
1839 2151 send_command('dismiss_install_or_update_notice', null, function (resp) {
1840 2152 if (resp && resp.hasOwnProperty('error')) {
1841 2153 // there was an error.
@@ -1848,9 +2160,9 @@
1848 2160
1849 2161 $('#wpo-settings-import').on('click', function(e) {
1850 2162 e.preventDefault();
1851 2163
1852 - block_ui();
2164 + block_ui(wpoptimize.importing);
1853 2165
1854 2166 var wpo_import_file_input = document.getElementById('import_settings');
1855 2167 if (0 === wpo_import_file_input.files.length) {
1856 2168 alert(wpoptimize.import_select_file);
@@ -1860,21 +2172,26 @@
1860 2172 read_settings_json_file(wpo_import_file_input.files[0]);
1861 2173 });
1862 2174
1863 2175 /**
1864 - * Blocks UI
2176 + * Pack WPO settings into a single object
2177 + *
2178 + * @return {object}
1865 2179 */
1866 - function block_ui() {
1867 - $.blockUI({
1868 - css: {
1869 - width: '300px',
1870 - border: 'none',
1871 - 'border-radius': '10px',
1872 - left: 'calc(50% - 150px)',
1873 - padding: '20px'
1874 - },
1875 - message: '<div style="margin: 8px; font-size:150%;" class="updraft_saving_popup"><img src="'+wpoptimize.spinner_src+'" height="80" width="80" style="padding-bottom:10px;"><br>'+wpoptimize.importing+'</div>'
1876 - });
2180 + function build_settings() {
2181 + var date_now = new Date();
2182 +
2183 + return {
2184 + epoch_date: date_now.getTime(),
2185 + local_date: date_now.toLocaleString(),
2186 + network_site_url: wpoptimize.network_site_url,
2187 + data: {
2188 + cache_settings: wp_optimize.cache_settings(),
2189 + minify_settings: wp_optimize.minify_settings(),
2190 + smush_settings: wp_optimize.smush_settings(),
2191 + database_settings: gather_settings('string')
2192 + }
2193 + };
1877 2194 }
1878 2195
1879 2196 /**
1880 2197 * Export plugin settings as a JSON file
@@ -1885,22 +2202,10 @@
1885 2202 */
1886 2203 function export_settings(e) {
1887 2204 e.preventDefault();
1888 2205
1889 - var date_now = new Date();
2206 + form_data = JSON.stringify(build_settings());
1890 2207
1891 - form_data = JSON.stringify({
1892 - epoch_date: date_now.getTime(),
1893 - local_date: date_now.toLocaleString(),
1894 - network_site_url: wpoptimize.network_site_url,
1895 - data: {
1896 - cache_settings: wp_optimize.cache_settings(),
1897 - minify_settings: wp_optimize.minify_settings(),
1898 - smush_settings: wp_optimize.smush_settings(),
1899 - database_settings: gather_settings('string')
1900 - }
1901 - });
1902 -
1903 2208 // Attach this data to an anchor on page
1904 2209 var link = document.body.appendChild(document.createElement('a'));
1905 2210 link.setAttribute('download', wpoptimize.export_settings_file_name);
1906 2211 link.setAttribute('style', "display:none;");
@@ -1962,8 +2267,173 @@
1962 2267 $.unblockUI();
1963 2268 }
1964 2269 }
1965 2270
2271 + /**
2272 + * Define popup for each optimization action that needs confirmation from user
2273 + */
2274 + function get_destructive_actions_confirm_popup(action) {
2275 + var popups = destructive_actions_confirm_popup = {
2276 + postmeta: {
2277 + className: 'wpo-confirm',
2278 + events: {
2279 + 'click .wpo-modal--bg': 'close',
2280 + 'click #confirm_post_meta_deletion': 'deleteConfirm',
2281 + 'click .cancel': 'cancel',
2282 + 'click #confirm-post-meta-delete-action': 'confirm'
2283 + },
2284 + content: function() {
2285 + var content_template = wp.template('wpo-postmeta');
2286 + return content_template({});
2287 + },
2288 + deleteConfirm: function() {
2289 + var enable_button = $('#confirm_post_meta_deletion').is(':checked');
2290 + $('.delete-post-meta').prop('disabled', !enable_button);
2291 + }
2292 + },
2293 + orphandata: {
2294 + className: 'wpo-confirm',
2295 + events: {
2296 + 'click .wpo-modal--bg': 'close',
2297 + 'click #confirm_orphaned_relationship_data_deletion': 'deleteConfirm',
2298 + 'click .cancel': 'cancel',
2299 + 'click #confirm-orphaned-relationship-data-delete-action': 'confirm'
2300 + },
2301 + content: function() {
2302 + var content_template = wp.template('wpo-orphandata');
2303 + return content_template({});
2304 + },
2305 + deleteConfirm: function() {
2306 + var enable_button = $('#confirm_orphaned_relationship_data_deletion').is(':checked');
2307 + $('.delete-orphaned-relationship-data').prop('disabled', !enable_button);
2308 + }
2309 + },
2310 + "grouped-warnings": {
2311 + className: 'wpo-confirm',
2312 + events: {
2313 + 'click .wpo-modal--bg': 'close',
2314 + 'click #confirm_grouped_warnings_data_deletion': 'deleteConfirm',
2315 + 'click .cancel': 'cancel',
2316 + 'click #confirm-grouped-warnings-data-delete-action': 'confirm'
2317 + },
2318 + deleteConfirm: function() {
2319 + var enable_button = $('#confirm_grouped_warnings_data_deletion').is(':checked');
2320 + $('.delete-grouped-warnings-data').prop('disabled', !enable_button);
2321 + }
2322 + }
2323 + }
2324 +
2325 + return popups[action];
2326 + }
2327 +
2328 + /**
2329 + * Attach click event to postmeta checkbox
2330 + */
2331 + function add_warning_for_delete_post_meta_action() {
2332 + $('#optimization_button_postmeta_big').on('click', function (evt) {
2333 + return function(this_button) {
2334 + var remove_post_meta_checkbox = $('#optimization_checkbox_postmeta');
2335 +
2336 + if (should_user_confirm_action('postmeta')) {
2337 + wp_optimize.modal.open(
2338 + Object.assign(get_destructive_actions_confirm_popup('postmeta'), {
2339 + cancel: function() {
2340 + $(remove_post_meta_checkbox).prop('checked', false);
2341 + },
2342 + confirm: function() {
2343 + maybe_dismiss_destructive_actions();
2344 + this.close();
2345 +
2346 + $(this_button).prop('bypass-confirm-box', true);
2347 + $(this_button).trigger('click');
2348 +
2349 + }
2350 + }
2351 + ));
2352 +
2353 + evt.preventDefault();
2354 + return false;
2355 + } else {
2356 + $(this_button).prop('bypass-confirm-box', false);
2357 + return true;
2358 + }
2359 + }(this);
2360 + });
2361 + }
2362 +
2363 + /**
2364 + * Check if dismiss future confirms checkbox is visible and selected, then save option in DB
2365 + */
2366 + function maybe_dismiss_destructive_actions() {
2367 + var ignores_orphaned_relationship_data_delete_warning_checkbox = $('#ignores_orphaned_relationship_data_deletion_warning');
2368 + if (ignores_orphaned_relationship_data_delete_warning_checkbox.is(':visible') && ignores_orphaned_relationship_data_delete_warning_checkbox.is(':checked')) {
2369 + send_command('user_ignores_orphaned_relationship_data_deletion_warning', {}, function(response) {
2370 + if (response.success) {
2371 + wpoptimize.user_always_ignores_orphaned_relationship_data_deletion_warning = '1';
2372 + }
2373 + });
2374 + }
2375 +
2376 + var ignores_post_meta_deletion_warning_checkbox = $('#ignores_post_meta_deletion_warning');
2377 + if (ignores_post_meta_deletion_warning_checkbox.is(':visible') && ignores_post_meta_deletion_warning_checkbox.is(':checked')) {
2378 + send_command('user_ignores_post_meta_deletion_warning', {}, function(response) {
2379 + if (response.success) {
2380 + wpoptimize.user_always_ignores_post_meta_deletion_warning = '1';
2381 + }
2382 + });
2383 + }
2384 + }
2385 +
2386 + /**
2387 + * Check if user dismissed confirms, or should they see the confirm popup
2388 + */
2389 + function should_user_confirm_action(action) {
2390 + if ('orphandata' == action) {
2391 + var bypass_confirm = $('#optimization_button_orphandata_big').prop('bypass-confirm-box') == true;
2392 +
2393 + return !bypass_confirm && ('' == wpoptimize.user_always_ignores_orphaned_relationship_data_deletion_warning || '1' !== wpoptimize.user_always_ignores_orphaned_relationship_data_deletion_warning);
2394 + } else if ('postmeta' == action) {
2395 + var bypass_confirm = $('#optimization_button_postmeta_big').prop('bypass-confirm-box') == true;
2396 +
2397 + return !bypass_confirm && ('' == wpoptimize.user_always_ignores_post_meta_deletion_warning || '1' !== wpoptimize.user_always_ignores_post_meta_deletion_warning);
2398 + }
2399 + }
2400 +
2401 + /**
2402 + * Attach click event to orphandata optimization checkbox
2403 + */
2404 + function add_warning_for_delete_orphaned_relationship_data_action() {
2405 + $('#optimization_button_orphandata_big').on('click', function (evt) {
2406 + return function(this_button) {
2407 + var remove_orphaned_relationship_data_checkbox = $('#optimization_checkbox_orphandata');
2408 +
2409 + if (should_user_confirm_action('orphandata')) {
2410 + wp_optimize.modal.open(
2411 + Object.assign(get_destructive_actions_confirm_popup('orphandata'), {
2412 + cancel: function() {
2413 + $(remove_orphaned_relationship_data_checkbox).prop('checked', false);
2414 + },
2415 + confirm: function() {
2416 + maybe_dismiss_destructive_actions();
2417 +
2418 + this.close();
2419 +
2420 + $(this_button).prop('bypass-confirm-box', true);
2421 + $(this_button).trigger('click');
2422 + }
2423 + }
2424 + ));
2425 +
2426 + evt.preventDefault();
2427 + return false;
2428 + } else {
2429 + $(this_button).prop('bypass-confirm-box', false);
2430 + return true;
2431 + }
2432 + }(this);
2433 + });
2434 + }
2435 +
1966 2436 // Attach heartbeat API events
1967 2437 heartbeat.setup();
1968 2438
1969 2439 return {
@@ -1969,13 +2439,62 @@
1969 2439 return {
1970 2440 send_command: send_command,
1971 2441 optimization_get_info: optimization_get_info,
1972 2442 take_a_backup_with_updraftplus: take_a_backup_with_updraftplus,
1973 - save_auto_backup_options: save_auto_backup_options
2443 + save_auto_backup_options: save_auto_backup_options,
2444 + build_settings: build_settings
1974 2445 }
1975 2446 }; // END function WP_Optimize()
1976 2447
2448 +/**
2449 + * Init Select2 Library
2450 + */
2451 +var WPO_Select2 = function () {
2452 + if ('function' === typeof jQuery.fn.select2) {
2453 + jQuery(".wpo-select2").not('.select2-hidden-accessible').select2();
2454 + }
2455 +}
2456 +
2457 +/**
2458 + * Init Tooltip Library
2459 + */
2460 +var WPO_Tooltip = function () {
2461 + if ('function' === typeof jQuery.fn.tooltip) {
2462 + jQuery(".wpo-tooltip").tooltip({
2463 + items: "[data-tooltip]",
2464 + content: function() {
2465 + return jQuery('<span>').text(jQuery(this).attr("data-tooltip"));
2466 + },
2467 + position: {
2468 + my: "center bottom",
2469 + at: "center top",
2470 + collision: "flipfit"
2471 + },
2472 + open: function(event, ui) {
2473 + jQuery(".wpo-tooltip").not(this).tooltip("close");
2474 + }
2475 + });
2476 +
2477 + // New: explicit outside-tap/click close, since jQuery UI has no touch equivalent of mouseleave/focusout
2478 + jQuery(document).on("touchstart click", function(e) {
2479 + if (!jQuery(e.target).closest("[data-tooltip], .ui-tooltip").length) {
2480 + jQuery(".wpo-tooltip").each(function() {
2481 + var $el = jQuery(this);
2482 + if ($el.data("ui-tooltip")) {
2483 + $el.tooltip("close");
2484 + }
2485 + });
2486 + }
2487 + });
2488 + }
2489 +}
2490 +
1977 2491 jQuery(function ($) {
2492 +
2493 + WPO_Tooltip();
2494 +
2495 + WPO_Select2();
2496 +
1978 2497 /**
1979 2498 * Show additional options section if optimization enabled
1980 2499 *
1981 2500 * @param {string} checkbox Logger settings jQuery checkbox object.
@@ -2010,8 +2529,10 @@
2010 2529 e.preventDefault();
2011 2530 $('#wp-optimize-logger-settings .save_settings_reminder').after(get_add_logging_form_html());
2012 2531
2013 2532 filter_select_destinations($('.wpo_logger_type').first());
2533 +
2534 + WPO_Select2();
2014 2535 });
2015 2536
2016 2537 /**
2017 2538 * Handle logging destination select change.
@@ -2185,9 +2706,9 @@
2185 2706 }
2186 2707
2187 2708 return [
2188 2709 '<div class="wpo_add_logger_form">',
2189 - '<select class="wpo_logger_type" name="wpo-logger-type[]">',
2710 + '<select class="wpo_logger_type wpo-select2" name="wpo-logger-type[]">',
2190 2711 select_options.join(''),
2191 2712 '</select>',
2192 2713 '<div class="wpo_logging_edit_row" style="display:block;"><span class="wpo_delete_logger button button-secondary" title="'+wpoptimize.cancel+'">'+wpoptimize.cancel+'</span>',
2193 2714 '<span class="wpo_save_logging button button-primary" title="'+wpoptimize.add+'">'+wpoptimize.add+'</span></div>',
@@ -2265,6 +2786,12 @@
2265 2786 $iframe.insertAfter($(this));
2266 2787 $(this).remove();
2267 2788 $iframe.focus();
2268 2789 }
2790 + });
2791 +
2792 + // Show/hide Enable the caching menu in the admin bar on cache/minify status change
2793 + $(document).on('wp-optimize/cache/toggle-status wp-optimize/minify/toggle-status', function() {
2794 + var minify_or_cache_enabled = $('#wpo_min_enable_minify').prop('checked') || $('#enable_page_caching').prop('checked');
2795 + $('#enable_cache_in_admin_bar_option').toggleClass('wpo_hidden', !minify_or_cache_enabled);
2269 2796 });
2270 2797 });