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 +313 -12 4.5.4 → 4.7.0 View file →
@@ -49,14 +49,38 @@
49 49 var optimization_force = false;
50 50 var optimization_logged_warnings = false;
51 51 var force_single_table_optimization = false;
52 52 var heartbeat = WP_Optimize_Heartbeat();
53 -
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 +
54 78 /*
55 79 * Enable select all checkbox for optimizations list.
56 80 */
57 81 define_select_all_checkbox($('#select_all_optimizations'), $('#optimizations_list .optimization_checkbox'));
58 -
82 +
59 83 /**
60 84 * Either display normally, or grey-out, the scheduling options, depending on whether any schedule has been selected.
61 85 *
62 86 * @return {string}
@@ -113,9 +137,9 @@
113 137 }
114 138 }
115 139 }
116 140
117 - tfoot.style.display = hidden > 0 ? "none" : "";
141 + if (tfoot) tfoot.style.display = hidden > 0 ? "none" : "";
118 142
119 143 var tables_not_found = document.getElementById('wpoptimize_table_list_tables_not_found');
120 144
121 145 // Check if rows are visible
@@ -255,8 +279,10 @@
255 279 // Trigger the global tab change events when changing page
256 280 var active_tab = $('.wpo-page[data-whichpage='+params.page+']').find('.nav-tab-wrapper .nav-tab-active');
257 281 $('#wp-optimize-wrap').trigger('tab-change', { page: params.page, tab: active_tab.data('tab') });
258 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'));
259 285 });
260 286
261 287 // set a time out, as needs to be done once the rest is loaded
262 288 setTimeout(function() {
@@ -335,14 +361,14 @@
335 361
336 362 var database_tabs_loading = false;
337 363 var database_tabs_loaded = false;
338 364 // When showing the tables tab
339 - $('#wp-optimize-wrap').on('tab-change/WP-Optimize/tables', function(e) {
365 + $('#wp-optimize-wrap').on('tab-change/wpo_database/tables', function(e) {
340 366 get_database_tabs();
341 367 });
342 368
343 369 // When showing the optimizations tab
344 - $('#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) {
345 371 get_database_tabs();
346 372 });
347 373
348 374
@@ -358,9 +384,9 @@
358 384 * Get the data for the database tabs. We get them at the same time, as they both need the same time consuming requests.
359 385 */
360 386 function get_database_tabs() {
361 387 if (database_tabs_loading || database_tabs_loaded) return;
362 - var container = $('.wpo-page[data-whichpage=WP-Optimize]');
388 + var container = $('.wpo-page[data-whichpage=wpo_database]');
363 389 var shade = container.find('.wpo_shade');
364 390 shade.removeClass('hidden');
365 391 database_tabs_loading = true;
366 392 send_command('get_database_tabs', {}, function(response) {
@@ -371,11 +397,66 @@
371 397 if (response.hasOwnProperty('optimizations')) {
372 398 container.find('.wp-optimize-optimizations-table-placeholder').replaceWith(response.optimizations);
373 399 }
374 400
375 - // Update the optimizations tables list
376 - 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 + }
377 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 +
378 459 $(document).trigger('wpo_database_tabs_loaded');
379 460
380 461 }).always(function() {
381 462 database_tabs_loading = false;
@@ -748,9 +829,9 @@
748 829
749 830 /*
750 831 * Run single optimization click.
751 832 */
752 - $('#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 () {
753 834 var optimization_id = $(this).closest('.wp-optimize-settings').data('optimization_id');
754 835 if (!optimization_id) {
755 836 console.log("Optimization ID corresponding to pressed button not found");
756 837 return;
@@ -768,9 +849,9 @@
768 849
769 850 /*
770 851 * Run all optimizations click.
771 852 */
772 - $('#wp-optimize-nav-tab-WP-Optimize-optimize-contents #wp-optimize').on('click', function (e) {
853 + $('#wp-optimize-nav-tab-wpo_database-optimize-contents #wp-optimize').on('click', function (e) {
773 854 e.preventDefault();
774 855
775 856 if (null == tmpl_wpo_grouped_warnings_tpl) {
776 857 tmpl_wpo_grouped_warnings_tpl = $('#tmpl-wpo-grouped-warnings').html().toString();
@@ -844,8 +925,171 @@
844 925 }
845 926 }
846 927
847 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 + /**
848 1092 * Sent command to run selected optimizations and auto backup if selected
849 1093 *
850 1094 * @return void
851 1095 */
@@ -1099,8 +1343,14 @@
1099 1343 }
1100 1344
1101 1345 $('#wp_optimize_table_list_refresh').on('click', function (e) {
1102 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 + }
1103 1353 var shade = $(this).closest('.wpo-tab-postbox').find('.wpo_shade');
1104 1354 shade.removeClass('hidden');
1105 1355 $('#wpoptimize_table_list tbody').css('opacity', '0.5');
1106 1356 send_command('get_table_list', {refresh_plugin_json: true}, update_tables_list).always(function() {
@@ -1175,8 +1425,9 @@
1175 1425 }
1176 1426
1177 1427 if (resp && resp.hasOwnProperty('settings_auto_cleanup_contents')) {
1178 1428 $('#wpo_auto_cleanup').replaceWith(resp.settings_auto_cleanup_contents);
1429 + WPO_Select2();
1179 1430 }
1180 1431
1181 1432 if (resp && resp.hasOwnProperty('logging_settings_contents')) {
1182 1433 $('#wpo_logging_settings').replaceWith(resp.logging_settings_contents);
@@ -1894,9 +2145,9 @@
1894 2145
1895 2146 /**
1896 2147 * Hide introduction notice
1897 2148 */
1898 - $('.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) {
1899 2150 $('.wpo-introduction-notice').remove();
1900 2151 send_command('dismiss_install_or_update_notice', null, function (resp) {
1901 2152 if (resp && resp.hasOwnProperty('error')) {
1902 2153 // there was an error.
@@ -2193,9 +2444,57 @@
2193 2444 build_settings: build_settings
2194 2445 }
2195 2446 }; // END function WP_Optimize()
2196 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 +
2197 2491 jQuery(function ($) {
2492 +
2493 + WPO_Tooltip();
2494 +
2495 + WPO_Select2();
2496 +
2198 2497 /**
2199 2498 * Show additional options section if optimization enabled
2200 2499 *
2201 2500 * @param {string} checkbox Logger settings jQuery checkbox object.
@@ -2230,8 +2529,10 @@
2230 2529 e.preventDefault();
2231 2530 $('#wp-optimize-logger-settings .save_settings_reminder').after(get_add_logging_form_html());
2232 2531
2233 2532 filter_select_destinations($('.wpo_logger_type').first());
2533 +
2534 + WPO_Select2();
2234 2535 });
2235 2536
2236 2537 /**
2237 2538 * Handle logging destination select change.
@@ -2405,9 +2706,9 @@
2405 2706 }
2406 2707
2407 2708 return [
2408 2709 '<div class="wpo_add_logger_form">',
2409 - '<select class="wpo_logger_type" name="wpo-logger-type[]">',
2710 + '<select class="wpo_logger_type wpo-select2" name="wpo-logger-type[]">',
2410 2711 select_options.join(''),
2411 2712 '</select>',
2412 2713 '<div class="wpo_logging_edit_row" style="display:block;"><span class="wpo_delete_logger button button-secondary" title="'+wpoptimize.cancel+'">'+wpoptimize.cancel+'</span>',
2413 2714 '<span class="wpo_save_logging button button-primary" title="'+wpoptimize.add+'">'+wpoptimize.add+'</span></div>',