PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.5.4
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.5.4
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
wp-optimize / js / wpoadmin.js

wpoadmin.js in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 4.5.4, at js/wpoadmin.js

2,497 lines 76.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 jQuery(function ($) {
2 WP_Optimize = WP_Optimize();
3 if ('undefined' != typeof WP_Optimize_Cache) WP_Optimize_Cache = WP_Optimize_Cache();
4 if ('undefined' != typeof wp_optimize.minify) WP_Optimize_Minify = wp_optimize.minify.init();
5 });
6
7 (function($) {
8 /*
9 * Form errors store
10 */
11 var errors = [];
12 $.fn.form_errors = function() {
13 return this;
14 }
15 $.fn.form_errors.add = function(type, message) {
16 if (false !== this.has_error((type))) return;
17 errors.push({type: type, message: message});
18 };
19 $.fn.form_errors.remove = function(type) {
20 var found_error = this.has_error(type);
21 if (found_error !== false) {
22 errors.splice(found_error, 1);
23 }
24 };
25 $.fn.form_errors.has_error = function(type) {
26 var has_error = false;
27 $.each(errors, function(index, error) {
28 console.log(index, error)
29 if (type == error.type) {
30 has_error = index;
31 }
32 }.bind(this));
33 return has_error;
34 };
35 $.fn.form_errors.has_errors = function() {
36 return errors.length > 0;
37 }
38 })(jQuery);
39
40 /**
41 * Main WP_Optimize - Function for sending communications.
42 */
43 var WP_Optimize = function () {
44 var $ = jQuery;
45 var debug_level = 0;
46 var queue = new Updraft_Queue();
47 var block_ui = wp_optimize.block_ui;
48 var send_command = wp_optimize.send_command;
49 var optimization_force = false;
50 var optimization_logged_warnings = false;
51 var force_single_table_optimization = false;
52 var heartbeat = WP_Optimize_Heartbeat();
53
54 /*
55 * Enable select all checkbox for optimizations list.
56 */
57 define_select_all_checkbox($('#select_all_optimizations'), $('#optimizations_list .optimization_checkbox'));
58
59 /**
60 * Either display normally, or grey-out, the scheduling options, depending on whether any schedule has been selected.
61 *
62 * @return {string}
63 */
64 function enable_or_disable_schedule_options() {
65 if ($('#enable-schedule').length) {
66 var schedule_enabled = $('#enable-schedule').is(':checked');
67 if (schedule_enabled) {
68 $('#wp-optimize-auto-options').css('opacity', '1');
69 } else {
70 $('#wp-optimize-auto-options').css('opacity', '0.5')
71 }
72 }
73 }
74
75 enable_or_disable_schedule_options();
76
77 $('#enable-schedule').on('change', function () {
78 enable_or_disable_schedule_options();
79 });
80
81 /*
82 * Triggered when the database tabs are loaded.
83 */
84
85 $(document).on('wpo_database_tabs_loaded', function() {
86 /*
87 * Setup table events and tablesorter
88 */
89
90 var elTable = document.getElementById('wpoptimize_table_list');
91
92 if (null === elTable) return;
93
94 enhanceSortableAccessibility([elTable]);
95
96 document.getElementById('wpoptimize_table_list_filter').addEventListener('input', function () {
97 var filter = this.value.toLowerCase();
98 var regex = new RegExp(filter, 'i');
99 var tbody = elTable.querySelector('tbody');
100 var tfoot = elTable.querySelector('tfoot');
101 var rows = tbody.getElementsByTagName('tr');
102 var hidden = 0;
103
104 for (var i = 0; i < rows.length; i++) {
105 var cell = rows[i].getElementsByTagName('td')[1];
106 if (cell) {
107 var value = cell.getAttribute('data-tablename');
108 if (regex.test(value)) {
109 rows[i].style.display = "";
110 } else {
111 rows[i].style.display = "none";
112 hidden++;
113 }
114 }
115 }
116
117 tfoot.style.display = hidden > 0 ? "none" : "";
118
119 var tables_not_found = document.getElementById('wpoptimize_table_list_tables_not_found');
120
121 // Check if rows are visible
122 if (hidden === rows.length) {
123 tables_not_found.style.display = 'block';
124 } else {
125 tables_not_found.style.display = 'none';
126 }
127
128 });
129
130 /*
131 * Setup force optimization checkboxes and associated events
132 */
133
134 var optimization_force_checkbox = $('#innodb_force_optimize');
135 var optimization_row = optimization_force_checkbox.closest('tr');
136 var single_table_optimization_force = $('#innodb_force_optimize_single');
137
138 optimization_force_checkbox.on('change', function() {
139 $('button, input[type="checkbox"]', optimization_row).each(function() {
140 optimization_force = optimization_force_checkbox.is(':checked');
141 var btn = $(this);
142 if (btn.data('disabled')) {
143 if (optimization_force) {
144 btn.prop('disabled', false);
145 } else {
146 btn.prop('disabled', true);
147 }
148 }
149 });
150 });
151
152 // Handle force optimization checkbox on table list tab.
153 single_table_optimization_force.on('change', function() {
154 force_single_table_optimization = $(this).is(':checked');
155 update_single_table_optimization_buttons(force_single_table_optimization);
156 });
157
158 // Set initial value
159 force_single_table_optimization = single_table_optimization_force.is(':checked');
160 optimization_force = optimization_force_checkbox.is(':checked');
161
162 // Update single table optimization buttons state on load.
163 update_single_table_optimization_buttons(force_single_table_optimization);
164
165 // Attach warning events
166 add_warning_for_delete_post_meta_action();
167 add_warning_for_delete_orphaned_relationship_data_action();
168
169 });
170
171 /**
172 * Temporarily show a dashboard notice, and then remove it. The HTML will be prepended to the .wrap.wp-optimize-wrap element.
173 *
174 * @param {String} html_contents HTML to display.
175 * @param {String} where CSS selector of where to prepend the HTML to.
176 * @param {Number} [delay=15] The number of seconds to wait before removing the message.
177 *
178 * @return {string}
179 */
180 function temporarily_display_notice(html_contents, where, delay) {
181 where = ('undefined' === typeof where) ? '#wp-optimize-wrap' : where;
182 delay = ('undefined' === typeof delay) ? 15 : delay;
183 $(html_contents).hide().prependTo(where).slideDown('fast').delay(delay * 1000).slideUp('fast', function () {
184 $(this).remove();
185 });
186 }
187
188 /**
189 * Send a request to disable or enable comments or trackbacks
190 *
191 * @param {string} type - either "comments" or "trackbacks"
192 * @param {boolean} enable - whether to enable, or, to disable
193 *
194 * @return {string}
195 */
196 function enable_or_disable_feature(type, enable) {
197 var data = {
198 type: type,
199 enable: enable ? 1 : 0
200 };
201
202 $('#' + type + '_spinner').show();
203
204 send_command('enable_or_disable_feature', data, function (resp) {
205 $('#' + type + '_spinner').hide();
206
207 if (resp && resp.hasOwnProperty('output')) {
208 for (var i = 0, len = resp.output.length; i < len; i++) {
209 var new_html = '<div class="updated"><p>' + resp.output[i] + '</p></div>';
210 temporarily_display_notice(new_html, '#' + type + '_notice');
211 }
212 }
213 if (resp && resp.hasOwnProperty('messages')) {
214 $('#' + type + '_actionmsg').html(resp.messages.join(' - '));
215 }
216 });
217 }
218
219 $('#wp-optimize-disable-enable-trackbacks-enable').on('click', function () {
220 enable_or_disable_feature('trackbacks', true);
221 });
222
223 $('#wp-optimize-disable-enable-trackbacks-disable').on('click', function () {
224 enable_or_disable_feature('trackbacks', false);
225 });
226
227 $('#wp-optimize-disable-enable-comments-enable').on('click', function () {
228 enable_or_disable_feature('comments', true);
229 });
230
231 $('#wp-optimize-disable-enable-comments-disable').on('click', function () {
232 enable_or_disable_feature('comments', false);
233 });
234
235 // Main menu
236 $('.wpo-pages-menu').on('click', 'a', function(e) {
237 e.preventDefault();
238 if (!$(this).is('.active')) {
239 $('.wpo-pages-menu a.active').removeClass('active');
240 $('.wpo-page.active').removeClass('active');
241 $(this).addClass('active');
242 $('.wpo-page[data-whichpage="' + $(this).data('menuslug') + '"]').addClass('active');
243 window.scroll(0, 0);
244
245 // Trigger a global event when changing page
246 $('#wp-optimize-wrap').trigger('page-change', { page: $(this).data('menuslug') });
247 }
248
249 // Close the menu on mobile
250 $('#wp-optimize-nav-page-menu').trigger('click');
251
252 });
253
254 $('#wp-optimize-wrap').on('page-change', function(e, params) {
255 // Trigger the global tab change events when changing page
256 var active_tab = $('.wpo-page[data-whichpage='+params.page+']').find('.nav-tab-wrapper .nav-tab-active');
257 $('#wp-optimize-wrap').trigger('tab-change', { page: params.page, tab: active_tab.data('tab') });
258 $('#wp-optimize-wrap').trigger('tab-change/'+params.page+'/'+active_tab.data('tab'), { content: $('#' + active_tab.attr('id') + '-contents')});
259 });
260
261 // set a time out, as needs to be done once the rest is loaded
262 setTimeout(function() {
263 // Trigger page-change event on load
264 $('#wp-optimize-wrap').trigger('page-change', { page: $('.wpo-pages-menu a.active').data('menuslug') });
265 }, 500);
266
267 // Tabs menu
268 $('.nav-tab-wrapper .nav-tab').on('click', function (e) {
269 e.preventDefault();
270
271 var clicked_tab_id = $(this).attr('id'),
272 container = $(this).closest('.nav-tab-wrapper');
273
274 if (!clicked_tab_id) { return; }
275
276 toggle_mobile_menu(false);
277 // Mobile menu TABS toggle
278 if ($(this).is('[id^="wp-optimize-nav-tab-menu-"]')) {
279 toggle_mobile_menu(true);
280 return;
281 }
282
283 container.find('.nav-tab:not(#wp-optimize-nav-tab-' + clicked_tab_id + ')').removeClass('nav-tab-active');
284
285 $(this).addClass('nav-tab-active');
286 $(this).closest('.wpo-page').find('.wp-optimize-nav-tab-contents').hide();
287 $('#' + clicked_tab_id + '-contents').show();
288
289 // Trigger global events on tab change
290 $('#wp-optimize-wrap').trigger('tab-change', { page: $(this).data('page'), tab: $(this).data('tab') });
291 $('#wp-optimize-wrap').trigger('tab-change/'+$(this).data('page')+'/'+$(this).data('tab'), { content: $('#' + clicked_tab_id + '-contents')});
292
293 });
294
295 // Mobile menu toggle
296 $('#wp-optimize-nav-page-menu').on('click', function(e) {
297 e.preventDefault();
298 $(this).toggleClass('opened');
299 });
300
301 /*
302 * Setup a simple cross-pages/tabs navigation.
303 *
304 * Basic example: <button class="js--wpo-goto" data-page="wpo_minify" data-tab="status">Go to the minify page, status tab</button>
305 */
306 $('#wp-optimize-wrap').on('click', '.js--wpo-goto', function(e) {
307 e.preventDefault();
308 // get the page and tab
309 var page = $(this).data('page');
310 var tab = $(this).data('tab');
311 if (page) {
312 // Trigger a page change
313 $('.wpo-pages-menu a[data-menuslug="' + page + '"]').trigger('click');
314 }
315 if (tab) {
316 // Change tab change
317 $('.wpo-page.active .nav-tab-wrapper a[data-tab="' + tab + '"]').trigger('click');
318 }
319 });
320
321 /**
322 * Toggle Mobile menu
323 *
324 * @param {bool} open
325 *
326 * @return {void}
327 */
328 function toggle_mobile_menu(open) {
329 if (open) {
330 $('#wp-optimize-wrap').addClass('wpo-mobile-menu-opened');
331 } else {
332 $('#wp-optimize-wrap').removeClass('wpo-mobile-menu-opened');
333 }
334 }
335
336 var database_tabs_loading = false;
337 var database_tabs_loaded = false;
338 // When showing the tables tab
339 $('#wp-optimize-wrap').on('tab-change/WP-Optimize/tables', function(e) {
340 get_database_tabs();
341 });
342
343 // When showing the optimizations tab
344 $('#wp-optimize-wrap').on('tab-change/WP-Optimize/optimize', function(event, data) {
345 get_database_tabs();
346 });
347
348
349 // When showing the settings tab
350 $('#wp-optimize-wrap').on('tab-change/wpo_settings/settings', function(event, data) {
351 // If the innodb_force_optimize--container is present, fetch the required data.
352 // We load the database tabs together, as they need the same processing.
353 if (data.content.find('.innodb_force_optimize--container').length) get_database_tabs();
354 WPO_Status_Report();
355 });
356
357 /**
358 * Get the data for the database tabs. We get them at the same time, as they both need the same time consuming requests.
359 */
360 function get_database_tabs() {
361 if (database_tabs_loading || database_tabs_loaded) return;
362 var container = $('.wpo-page[data-whichpage=WP-Optimize]');
363 var shade = container.find('.wpo_shade');
364 shade.removeClass('hidden');
365 database_tabs_loading = true;
366 send_command('get_database_tabs', {}, function(response) {
367 // Set the status to true, to prevent loading again.
368 database_tabs_loaded = true;
369
370 // Update the optimizations tab
371 if (response.hasOwnProperty('optimizations')) {
372 container.find('.wp-optimize-optimizations-table-placeholder').replaceWith(response.optimizations);
373 }
374
375 // Update the optimizations tables list
376 update_tables_list(response);
377
378 $(document).trigger('wpo_database_tabs_loaded');
379
380 }).always(function() {
381 database_tabs_loading = false;
382 shade.addClass('hidden');
383 });
384 }
385
386 /**
387 * Gathers the settings from the settings tab and return in selected format.
388 *
389 * @param {string} output_format optional param 'object' or 'string'.
390 *
391 * @return (string) - serialized settings.
392 */
393 function gather_settings(output_format) {
394 var form_data = '',
395 output_format = ('undefined' === typeof output_format) ? 'string' : output_format,
396 $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]");
397
398 if ('object' == output_format) {
399 form_data = $form_elements.serializeJSON({useIntKeysAsArrayIndex: true});
400 } else {
401 // Excluding the unnecessary 'action' input avoids triggering a very misconceived mod_security rule seen on one user's site.
402 form_data = $form_elements.serialize();
403
404 // Include unchecked checkboxes. user filter to only include unchecked boxes.
405 $.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]')
406 .filter(function (idx) {
407 return $(this).prop('checked') == false
408 }),
409 function (idx, el) {
410 // Attach matched element names to the form_data with chosen value.
411 var empty_val = '0';
412 form_data += '&' + $(el).attr('name') + '=' + empty_val;
413 }
414 );
415 }
416
417 return form_data;
418 }
419
420 /**
421 * Runs after all queued commands done and sends optimizations_done command
422 *
423 * @return {string}
424 */
425 function process_done() {
426 send_command('optimizations_done', {}, function () {});
427 // Reset the warning flag
428 optimization_logged_warnings = false;
429 }
430
431 /**
432 * Processes the queue
433 *
434 * @return void
435 */
436 function process_queue() {
437 if (!queue.get_lock()) {
438 if (debug_level > 0) {
439 console.log("WP-Optimize: process_queue(): queue is currently locked - exiting");
440 }
441 return;
442 }
443
444 if (debug_level > 0) {
445 console.log("WP-Optimize: process_queue(): got queue lock");
446 }
447
448 var id = queue.peek();
449 var blog_id = 0;
450 var sites_container = $("#wpo_all_sites");
451 var active_site = sites_container.data('active_site');
452
453 // Check to see if an object has been returned.
454 if (typeof id == 'object') {
455 data = id;
456 id = id.optimization_id;
457 blog_id = data.blog_id;
458
459 if ("undefined" == typeof active_site) {
460 sites_container.data('active_site', blog_id);
461 do_site_ui_update(blog_id, 0);
462 } else if (active_site != blog_id) {
463 var prev_blog_id = active_site;
464 sites_container.data('active_site', blog_id);
465 do_site_ui_update(blog_id, prev_blog_id);
466 }
467
468 } else {
469 data = {};
470 }
471
472 if ('undefined' === typeof id) {
473 if (debug_level > 0) console.log("WP-Optimize: process_queue(): queue is apparently empty - exiting");
474 queue.unlock();
475 var prev_blog_id = sites_container.data('active_site');
476 do_site_ui_update(0, prev_blog_id);
477 process_done();
478 return;
479 }
480
481 if (debug_level > 0) console.log("WP-Optimize: process_queue(): processing item: " + id);
482
483 queue.dequeue();
484
485 $(document).trigger(['do_optimization_', id, '_start'].join(''));
486
487 if ('optimizetables' === id) {
488 // Display the table name being optimized
489 $('#optimization_info_' + id).html(wpoptimize.optimizing_table + ' ' + data.optimization_table);
490
491 // Set extra options for the request
492 var timeout = parseInt(wpoptimize.table_optimization_timeout) ? parseInt(wpoptimize.table_optimization_timeout) : 120000;
493 var request_options = {
494 timeout: timeout,
495 error: function(error, type) {
496 optimization_logged_warnings = true;
497 if ('timeout' === type) {
498 console.warn('The request to optimize the table ' + data.optimization_table + ' timed out after ' + (timeout / 1000) + ' seconds');
499 } else {
500 console.warn('There was an error when running the optimization "' + id + '".', type, error, data);
501 }
502 if (queue.is_empty()) {
503 var blog_id = sites_container.data('active_site');
504 do_site_ui_update(blog_id, 0);
505 $('#optimization_spinner_' + id).hide();
506 $('#optimization_checkbox_' + id).show();
507 $('.optimization_button_' + id).prop('disabled', false);
508 $('#optimization_info_' + id).html(wpoptimize.optimization_complete + ' ' + wpoptimize.with_warnings);
509 }
510
511 setTimeout(function () {
512 queue.unlock(); process_queue();
513 }, 500);
514 }
515 }
516 } else {
517 var request_options = {};
518 }
519
520 send_command('do_optimization', { optimization_id: id, data: data }, function (response) {
521 $('#optimization_spinner_' + id).hide();
522 $('#optimization_checkbox_' + id).show();
523 $('.optimization_button_' + id).prop('disabled', false);
524
525 $(document).trigger(['do_optimization_', id, '_done'].join(''), response);
526
527 if (response) {
528 var total_output = '';
529 for (var i = 0, len = response.errors.length; i < len; i++) {
530 total_output += '<span class="error">' + response.errors[i] + '</span><br>';
531 }
532 for (var i = 0, len = response.messages.length; i < len; i++) {
533 total_output += response.errors[i] + '<br>';
534 }
535 for (var i = 0, len = response.result.output.length; i < len; i++) {
536 total_output += response.result.output[i] + '<br>';
537 }
538 $('#optimization_info_' + id).html(total_output);
539 if (response.hasOwnProperty('status_box_contents')) {
540 $('#wp_optimize_status_box').css('opacity', '1').find('.inside').html(response.status_box_contents);
541 }
542 if (response.hasOwnProperty('table_list')) {
543 $('#wpoptimize_table_list tbody').html($(response.table_list).find('tbody').html());
544 }
545 if (response.hasOwnProperty('total_size')) {
546 $('#optimize_current_db_size').html(response.total_size);
547 }
548
549 if ('optimizetables' === id) {
550 // Status check for optimizing tables.
551 const optimizetables_id = "optimizetables";
552 if (queue.contains_id(optimizetables_id)) {
553 $('#optimization_checkbox_' + optimizetables_id).hide();
554 $('#optimization_spinner_' + optimizetables_id).show();
555 $('.optimization_button_' + optimizetables_id).prop('disabled', true);
556 } else {
557 $('#optimization_checkbox_' + optimizetables_id).show();
558 $('#optimization_spinner_' + optimizetables_id).hide();
559 $('.optimization_button_' + optimizetables_id).prop('disabled', false);
560 $('#optimization_info_' + optimizetables_id).html(wpoptimize.optimization_complete + (optimization_logged_warnings ? (' ' + wpoptimize.with_warnings) : ''));
561 }
562 }
563
564 // check if we need update unapproved comments count.
565 if (response.result.meta && response.result.meta.hasOwnProperty('awaiting_mod')) {
566 var awaiting_mod = response.result.meta.awaiting_mod;
567 if (awaiting_mod > 0) {
568 $('#adminmenu .awaiting-mod .pending-count').remove(awaiting_mod);
569 } else {
570 // if there is no unapproved comments then remove bullet.
571 $('#adminmenu .awaiting-mod').remove();
572 }
573 }
574 }
575 setTimeout(function () {
576 queue.unlock(); process_queue();
577 }, 500);
578 }, true, request_options);
579 }
580
581 /**
582 * Update UI of sites list based on which site is currently being optimizated
583 *
584 * @param {Number} blog_id - current site id being optimized
585 * @param {Number} prev_blog_id - previous site id
586 *
587 * @return void
588 */
589 function do_site_ui_update(blog_id, prev_blog_id) {
590 if (0 != prev_blog_id) {
591 $("#site-" + prev_blog_id).show();
592 $("#optimization_spinner_site-" + prev_blog_id).hide();
593 }
594 $("#site-" + blog_id).hide();
595 $("#optimization_spinner_site-" + blog_id).show();
596 }
597
598 /**
599 * Runs a specified optimization, displaying the progress and results in the optimization's row
600 *
601 * @param {string} id - The optimization ID
602 *
603 * @return void
604 */
605 function do_optimization(id) {
606 var $optimization_row = $('#wp-optimize-nav-tab-contents-optimize .wp-optimize-settings-' + id);
607
608 if (!$optimization_row) {
609 console.log("do_optimization: row corresponding to this optimization (" + id + ") not found");
610 }
611
612 // check if there any additional inputs checkboxes.
613 var additional_data = {},
614 additional_data_length = 0;
615
616 $('input[type="checkbox"]', $('#optimization_info_' + id)).each(function() {
617 var checkbox = $(this);
618
619 if (checkbox.is(':checked')) {
620 additional_data[checkbox.attr('name')] = checkbox.val();
621 additional_data_length++;
622 }
623 });
624
625 // don't run optimization if optimization active.
626 if (true == $('.optimization_button_' + id).prop('disabled')) return;
627
628 var no_queue_actions_added = false;
629
630 // Check if it is DB optimize.
631 if ('optimizetables' == id) {
632 var optimization_tables = $('#wpoptimize_table_list #the-list tr'),
633 filter_by_blog_id = $('#wpo_sitelist_moreoptions').length > 0 && $('#wpo_sitelist_moreoptions').is(':visible'),
634 selected_sites = [];
635
636 // Get list of selected sites.
637 if (filter_by_blog_id) {
638 selected_sites = $('#wpo_sitelist_moreoptions input[type="checkbox"]:checked').map(function() {
639 return parseInt($(this).val());
640 }).get();
641 }
642
643 no_queue_actions_added = true;
644
645 // Check if there are any tables to be optimized.
646 $(optimization_tables).each(function (index) {
647 // Get information from each td.
648 var $table_information = $(this).find('td');
649
650 // Get table type information.
651 var table_type = $(this).data('type');
652 var table = $(this).data('tablename');
653 var optimizable = $(this).data('optimizable');
654 var blog_id = $(this).data('blog_id') ? parseInt($(this).data('blog_id')) : 1;
655 var in_selected_sites = true;
656
657
658 // Check if table is in the list of selected sites (multisite mode).
659 if (filter_by_blog_id && -1 == selected_sites.indexOf(blog_id)) {
660 in_selected_sites = false;
661 }
662
663 // Make sure the table isnt blank.
664 if ('' != table && in_selected_sites) {
665 // Check if table is optimizable or optimization forced by user.
666 if (1 == parseInt(optimizable) || optimization_force) {
667 var data = {
668 optimization_id: id,
669 blog_id: blog_id,
670 optimization_table: table,
671 optimization_table_type: table_type,
672 optimization_force: optimization_force
673 };
674
675 queue.enqueue(data);
676
677 no_queue_actions_added = false;
678 }
679 }
680 });
681 } else {
682 // check if additional data passed for optimization.
683 data = {
684 optimization_id: id
685 };
686
687 if (additional_data_length > 0) {
688 for (var i in additional_data) {
689 if (!additional_data.hasOwnProperty(i)) continue;
690 data[i] = additional_data[i];
691 }
692 }
693
694 queue.enqueue(data);
695 }
696
697 // if new actions was not added in tasks queue then we don't process queue.
698 if (no_queue_actions_added) return;
699
700 $('#optimization_checkbox_' + id).hide();
701 $('#optimization_spinner_' + id).show();
702 $('.optimization_button_' + id).prop('disabled', true);
703
704 $('#optimization_info_' + id).html('...');
705
706 process_queue();
707 }
708
709
710 /**
711 * Run action and save selected sites list options.
712 *
713 * @param {function} action - action to do after save.
714 *
715 * @return void
716 */
717 function save_sites_list_and_do_action(action) {
718 // if multisite mode then save sites list before action.
719 if ($('#wpo_settings_sites_list').length) {
720 // save wpo-sites settings.
721 send_command('save_site_settings', {'wpo-sites': get_selected_sites_list()}, function () {
722 // do action.
723 if (action) action();
724 });
725 } else {
726 // do action.
727 if (action) action();
728 }
729 }
730
731 /**
732 * Returns list of selected sites list.
733 *
734 * @return {Array}
735 */
736 function get_selected_sites_list() {
737 var wpo_sites = [];
738
739 $('#wpo_settings_sites_list input[type="checkbox"]').each(function () {
740 var checkbox = $(this);
741 if (checkbox.is(':checked')) {
742 wpo_sites.push(checkbox.attr('value'));
743 }
744 });
745
746 return wpo_sites;
747 }
748
749 /*
750 * Run single optimization click.
751 */
752 $('#wp-optimize-nav-tab-WP-Optimize-optimize-contents').on('click', 'button.wp-optimize-settings-optimization-run-button', function () {
753 var optimization_id = $(this).closest('.wp-optimize-settings').data('optimization_id');
754 if (!optimization_id) {
755 console.log("Optimization ID corresponding to pressed button not found");
756 return;
757 }
758 // if run button disabled then don't run this optimization.
759 if (true == $('.optimization_button_' + optimization_id).prop('disabled')) return;
760 // disable run button before save sites list.
761 $('.optimization_button_' + optimization_id).prop('disabled', true);
762
763 save_sites_list_and_do_action(function() {
764 $('.optimization_button_' + optimization_id).prop('disabled', false);
765 do_optimization(optimization_id);
766 });
767 });
768
769 /*
770 * Run all optimizations click.
771 */
772 $('#wp-optimize-nav-tab-WP-Optimize-optimize-contents #wp-optimize').on('click', function (e) {
773 e.preventDefault();
774
775 if (null == tmpl_wpo_grouped_warnings_tpl) {
776 tmpl_wpo_grouped_warnings_tpl = $('#tmpl-wpo-grouped-warnings').html().toString();
777 }
778
779 user_confirm_destructive_actions(function() {
780 return function(run_btn) {
781 // disable run button to avoid double click.
782 $(run_btn).prop('disabled', true);
783 save_sites_list_and_do_action(function() {
784 $(run_btn).prop('disabled', false);
785 run_optimizations();
786 });
787 };
788 }(this));
789 });
790
791 var tmpl_wpo_grouped_warnings_tpl = null;
792
793 /**
794 * Prepare the stack of optimizations that the user will need to actively confirm using the popup
795 * Then show them in sequence
796 */
797 function user_confirm_destructive_actions(callback) {
798 var optimizations = $('#optimizations_list .optimization_checkbox:checked');
799
800 var confirmations_stack = [];
801
802 optimizations.filter(function(i, optim) {
803 var optimization_id = optim.id.replace('optimization_checkbox_', '');
804 var destructive_action_popup = $('#tmpl-wpo-' + optimization_id);
805 return 0 < destructive_action_popup.length;
806 }).each(function(i, maybe_confirm) {
807 var optimization_id = maybe_confirm.id.replace('optimization_checkbox_', '');
808 if (should_user_confirm_action(optimization_id)) {
809 confirmations_stack.push(optimization_id);
810 }
811 });
812
813 user_confirm_destructive_actions_grouped(confirmations_stack, callback);
814 }
815
816 /**
817 * Show confirmation popups for user to accept, in sequence. When done, trigger callback
818 */
819 function user_confirm_destructive_actions_grouped(confirmations_stack, callback) {
820 if (0 < confirmations_stack.length) {
821 var warning_messages = [];
822 confirmations_stack.forEach(function(optimization_id) {
823 var str = $($('#tmpl-wpo-' + optimization_id).html()).children('p').html();
824 warning_messages.push(str);
825 });
826
827 wp_optimize.modal.open(
828 Object.assign(get_destructive_actions_confirm_popup('grouped-warnings'), {
829 cancel: function() {
830 // Nothing will be done
831 },
832 confirm: function() {
833 this.close();
834 callback();
835 },
836 content: function() {
837 return tmpl_wpo_grouped_warnings_tpl.replace('[[warning_messages]]', "<ul><li>" + warning_messages.join("</li><li>") + "</li></ul>");
838 }
839 }
840 ));
841 } else {
842 // No confirmations needed
843 callback();
844 }
845 }
846
847 /**
848 * Sent command to run selected optimizations and auto backup if selected
849 *
850 * @return void
851 */
852 function run_optimizations() {
853 var auto_backup = false;
854
855 if ($('#enable-auto-backup').is(":checked")) {
856 auto_backup = true;
857 }
858
859 // Save the click option.
860 save_auto_backup_options();
861
862 // Only run the backup if tick box is checked.
863 if (auto_backup == true) {
864 take_a_backup_with_updraftplus(run_optimization);
865 } else {
866 // Run optimizations.
867 run_optimization();
868 }
869 }
870
871 /**
872 * Take a backup with UpdraftPlus if possible.
873 *
874 * @param {Function} callback
875 * @param {String} file_entities
876 *
877 * @return void
878 */
879 function take_a_backup_with_updraftplus(callback, file_entities) {
880 // Set default for file_entities to empty string
881 if ('undefined' == typeof file_entities) file_entities = '';
882 var exclude_files = file_entities ? 0 : 1;
883
884 if (typeof updraft_backupnow_inpage_go === 'function') {
885 updraft_backupnow_inpage_go(function () {
886 // Close the backup dialogue.
887 $('#updraft-backupnow-inpage-modal').dialog('close');
888
889 if (callback) callback();
890
891 }, file_entities, 'autobackup', 0, exclude_files, 0, wpoptimize.automatic_backup_before_optimizations);
892 } else {
893 if (callback) callback();
894 }
895 }
896
897 /**
898 * Save all auto backup options.
899 *
900 * @return void
901 */
902 function save_auto_backup_options() {
903 var options = gather_settings('object');
904 options['auto_backup'] = $('#enable-auto-backup').is(":checked");
905
906 send_command('save_auto_backup_option', options);
907 }
908
909 // Show/hide sites list for multi-site settings.
910 var wpo_settings_sites_list = $('#wpo_settings_sites_list'),
911 wpo_settings_sites_list_ul = wpo_settings_sites_list.find('ul').first(),
912 wpo_settings_sites_list_items = $('input[type="checkbox"]', wpo_settings_sites_list_ul),
913 wpo_settings_all_sites_checkbox = wpo_settings_sites_list.find('#wpo_all_sites'),
914 wpo_sitelist_show_moreoptions_link = $('#wpo_sitelist_show_moreoptions'),
915 wpo_sitelist_moreoptions_div = $('#wpo_sitelist_moreoptions'),
916
917 wpo_settings_sites_list_cron = $('#wpo_settings_sites_list_cron'),
918 wpo_settings_sites_list_cron_ul = wpo_settings_sites_list_cron.find('ul').first(),
919 wpo_settings_sites_list_cron_items = $('input[type="checkbox"]', wpo_settings_sites_list_cron_ul),
920 wpo_settings_all_sites_cron_checkbox = wpo_settings_sites_list_cron.find('#wpo_all_sites_cron'),
921 wpo_sitelist_show_moreoptions_cron_link = $('#wpo_sitelist_show_moreoptions_cron'),
922 wpo_sitelist_moreoptions_cron_div = $('#wpo_sitelist_moreoptions_cron');
923
924 // sites list for manual run.
925 define_moreoptions_settings(
926 wpo_sitelist_show_moreoptions_link,
927 wpo_sitelist_moreoptions_div,
928 wpo_settings_all_sites_checkbox,
929 wpo_settings_sites_list_items
930 );
931
932 var debounceTimer;
933
934 $([wpo_settings_all_sites_checkbox, wpo_settings_sites_list_items]).each(function() {
935 $(this).on('change', function() {
936 clearTimeout(debounceTimer);
937 debounceTimer = setTimeout(function() {
938 update_optimizations_info();
939 }, 1000);
940 });
941 });
942
943 // sites list for cron run.
944 define_moreoptions_settings(
945 wpo_sitelist_show_moreoptions_cron_link,
946 wpo_sitelist_moreoptions_cron_div,
947 wpo_settings_all_sites_cron_checkbox,
948 wpo_settings_sites_list_cron_items
949 );
950
951 /**
952 * Attach event handlers for more options list showed by clicking on show_moreoptions_link.
953 *
954 * @param show_moreoptions_link
955 * @param more_options_div
956 * @param all_items_checkbox
957 * @param items_list
958 *
959 * @return boolean
960 */
961 function define_moreoptions_settings(show_moreoptions_link, more_options_div, all_items_checkbox, items_list) {
962 // toggle show options on click.
963 show_moreoptions_link.on('click', function () {
964 if (!more_options_div.hasClass('wpo_always_visible')) more_options_div.toggleClass('wpo_hidden');
965 return false;
966 });
967
968 // if "all items" checked/unchecked then check/uncheck items in the list.
969 define_select_all_checkbox(all_items_checkbox, items_list);
970 }
971
972 /**
973 * Defines "select all" check box, where all_items_checkbox is a select all check box jQuery object
974 * and items_list is a list of checkboxes assigned with all_items_checkbox.
975 *
976 * @param {Object} all_items_checkbox
977 * @param {Object} items_list
978 *
979 * @return void
980 */
981 function define_select_all_checkbox(all_items_checkbox, items_list) {
982 // if "all items" checked/unchecked then check/uncheck items in the list.
983 all_items_checkbox.on('change', function () {
984 if (all_items_checkbox.is(':checked')) {
985 items_list.prop('checked', true);
986 } else {
987 items_list.prop('checked', false);
988 }
989
990 update_wpo_all_items_checkbox_state(all_items_checkbox, items_list);
991 });
992
993 items_list.on('change', function () {
994 update_wpo_all_items_checkbox_state(all_items_checkbox, items_list);
995 });
996
997 update_wpo_all_items_checkbox_state(all_items_checkbox, items_list);
998
999 }
1000
1001 /**
1002 * Update state of "all items" checkbox depends on state all items in the list.
1003 *
1004 * @param all_items_checkbox
1005 * @param all_items
1006 *
1007 * @return void
1008 */
1009 function update_wpo_all_items_checkbox_state(all_items_checkbox, all_items) {
1010 var all_items_count = 0, checked_items_count = 0;
1011
1012 all_items.each(function () {
1013 if ($(this).is(':checked')) {
1014 checked_items_count++;
1015 }
1016 all_items_count++;
1017 });
1018
1019 // update label text if need.
1020 if (all_items_checkbox.next().is('label') && all_items_checkbox.next().data('label')) {
1021 var label = all_items_checkbox.next(),
1022 label_mask = label.data('label');
1023
1024 if (all_items_count == checked_items_count) {
1025 label.text(label_mask);
1026 } else {
1027 label.text(label_mask.replace('all', [checked_items_count, ' of ', all_items_count].join('')));
1028 }
1029 }
1030
1031 if (all_items_count == checked_items_count) {
1032 all_items_checkbox.prop('checked', true);
1033 } else {
1034 all_items_checkbox.prop('checked', false);
1035 }
1036 }
1037
1038 /**
1039 * Running the optimizations for the selected options
1040 *
1041 * @return {[type]} optimizations
1042 */
1043 function run_optimization() {
1044 var optimizations = $('#optimizations_list .optimization_checkbox:checked').toArray();
1045
1046 var sorted_optimizations = optimizations.sort(function (a, b) {
1047 var aOrder = $(a).closest('.wp-optimize-settings').data('optimization_run_sort_order');
1048 var bOrder = $(b).closest('.wp-optimize-settings').data('optimization_run_sort_order');
1049 return aOrder - bOrder; // Ascending order - so all other optimizations will run before optimizetables
1050 });
1051
1052 var optimization_options = {};
1053
1054 sorted_optimizations.forEach(function (element) {
1055 var optimization_id = $(element).closest('.wp-optimize-settings').data('optimization_id');
1056 if (!optimization_id) {
1057 console.log("Optimization ID corresponding to pressed button not found");
1058 return;
1059 }
1060 // An empty object - in future, options may be implemented.
1061 optimization_options[optimization_id] = { active: 1 };
1062 do_optimization(optimization_id);
1063 });
1064
1065 send_command('save_manual_run_optimization_options', optimization_options);
1066 }
1067
1068 /**
1069 * Uptate the tables list
1070 *
1071 * @param {object} response
1072 */
1073 function update_tables_list(response) {
1074 if (response.hasOwnProperty('table_list')) {
1075 var resort = true,
1076 // add a callback, as desired
1077 callback = function(table) {
1078 $('#wpoptimize_table_list tbody').css('opacity', '1');
1079 };
1080
1081 // update body with new content.
1082 $("#wpoptimize_table_list tbody").remove();
1083 $("#wpoptimize_table_list tfoot").remove();
1084 $("#wpoptimize_table_list thead").after(response.table_list);
1085
1086 $("#wpoptimize_table_list").trigger("updateAll", [resort, callback]);
1087 }
1088
1089 if (response.hasOwnProperty('total_size')) {
1090 $('#optimize_current_db_size').html(response.total_size);
1091 }
1092
1093 if (response.hasOwnProperty('show_innodb_force_optimize')) {
1094 $('.innodb_force_optimize--container').toggleClass('hidden', !response.show_innodb_force_optimize);
1095 }
1096
1097 change_actions_column_visibility();
1098 update_single_table_optimization_buttons(force_single_table_optimization);
1099 }
1100
1101 $('#wp_optimize_table_list_refresh').on('click', function (e) {
1102 e.preventDefault();
1103 var shade = $(this).closest('.wpo-tab-postbox').find('.wpo_shade');
1104 shade.removeClass('hidden');
1105 $('#wpoptimize_table_list tbody').css('opacity', '0.5');
1106 send_command('get_table_list', {refresh_plugin_json: true}, update_tables_list).always(function() {
1107 shade.addClass('hidden');
1108 });
1109 });
1110
1111 $('#wpo-404-detector-form').on('click', '#wpo-404-clear-logs', function (e) {
1112 e.preventDefault();
1113 block_ui(wpoptimize.please_wait);
1114 send_command('truncate_404_logs', {}, function (resp) {
1115 if (resp && resp.hasOwnProperty('success') && resp.success) {
1116 $('#wpo_404_detector_results').html('');
1117 }
1118 if (resp && resp.hasOwnProperty('message') && resp.message) {
1119 block_ui(resp.message, {}, 3000);
1120 }
1121 }).fail(function() {
1122 block_ui(wpoptimize.something_wrong_try_again, {}, 3000);
1123 });
1124 });
1125
1126
1127 $('#database_settings_form, #settings_form, #wpo-404-detector-form').on('click', '.wpo-save-settings', function (e) {
1128 e.preventDefault();
1129 var form = $(this).closest('form');
1130 var spinner = form.find('.wpo-saving-settings');
1131 var form_data = gather_settings();
1132
1133 form.trigger('wpo-saving-form-data');
1134
1135 if (form.form_errors.has_errors()) return;
1136
1137 spinner.show();
1138 block_ui(wpoptimize.saving);
1139
1140 // when optimizations list in the document - send information about selected optimizations.
1141 if ($('#optimizations_list').length) {
1142 $('#optimizations_list .optimization_checkbox:checked').each(function() {
1143 var optimization_id = $(this).closest('.wp-optimize-settings').data('optimization_id');
1144 if (optimization_id) {
1145 form_data += '&optimization-options['+optimization_id+'][active]=1';
1146 }
1147 });
1148 }
1149
1150 if ($('#purge_cache_permissions').length) {
1151 if (!$('#purge_cache_permissions').val()) {
1152 form_data += '&purge_cache_permissions[]';
1153 }
1154 }
1155
1156 send_command('save_settings', form_data, function (resp) {
1157 spinner.closest('div').find('.save-done').show().delay(5000).fadeOut();
1158
1159 if (resp && resp.hasOwnProperty('save_results') && resp.save_results && resp.save_results.hasOwnProperty('errors')) {
1160 for (var i = 0, len = resp.save_results.errors.length; i < len; i++) {
1161 var new_html = '<div class="error">' + resp.errors[i] + '</div>';
1162 temporarily_display_notice(new_html, '#wp-optimize-settings-save-results');
1163 }
1164 }
1165 if (resp && resp.hasOwnProperty('status_box_contents')) {
1166 $(resp.status_box_contents).each(function(index, el) {
1167 if ($(el).is('#wp_optimize_status_box')) {
1168 $('#wp_optimize_status_box').replaceWith($(el));
1169 }
1170 });
1171 }
1172
1173 if (resp && resp.hasOwnProperty('optimizations_table')) {
1174 $('#optimizations_list').replaceWith(resp.optimizations_table);
1175 }
1176
1177 if (resp && resp.hasOwnProperty('settings_auto_cleanup_contents')) {
1178 $('#wpo_auto_cleanup').replaceWith(resp.settings_auto_cleanup_contents);
1179 }
1180
1181 if (resp && resp.hasOwnProperty('logging_settings_contents')) {
1182 $('#wpo_logging_settings').replaceWith(resp.logging_settings_contents);
1183 }
1184
1185 // switch for visibility (performance tab).
1186 var $wpo_404_detector_btn = $('#wpo_404_detector');
1187 $wpo_404_detector_btn.prop('checked', !$wpo_404_detector_btn.prop('checked'));
1188 var $wpo_404_detector_results = $('#wpo_404_detector_results');
1189 $wpo_404_detector_results.css('display', $wpo_404_detector_btn.prop('checked') ? 'block' : 'none');
1190
1191 // Need to refresh the page if enable-admin-menu tick state has changed.
1192 if (resp.save_results.refresh) {
1193 location.reload();
1194 }
1195 }).always(function() {
1196 spinner.hide();
1197 $.unblockUI();
1198 });
1199 });
1200
1201 $('#database_settings_form').on('click', '.wpo_save_event', function() {
1202 setTimeout(function(){
1203 $('#wp-optimize-save-database-settings').trigger('click');
1204 }, 500);
1205 });
1206
1207 $('#settings_form').on('click', '.wpo_save_logging', function() {
1208 setTimeout(function(){
1209 $('#wp-optimize-save-main-settings').trigger('click');
1210 }, 500);
1211 });
1212
1213 /*
1214 * Handle Wipe Settings click.
1215 */
1216 $('#settings_form').on('click', '.wpo-wipe-settings', function() {
1217 var spinner = $(this).parent().find('.wpo_spinner');
1218
1219 spinner.show();
1220
1221 send_command('wipe_settings', {}, function() {
1222 spinner.next().removeClass('display-none').delay(5000).fadeOut();
1223 alert(wpoptimize.settings_have_been_deleted_successfully);
1224 location.replace(wpoptimize.settings_page_url);
1225 }).always(function() {
1226 spinner.hide();
1227 });
1228
1229 });
1230
1231 $('#wp-optimize-wrap').on('click', '#wp_optimize_status_box_refresh', function (e) {
1232 e.preventDefault();
1233 $('#wp_optimize_status_box').css('opacity', '0.5');
1234 send_command('get_status_box_contents', null, function (resp) {
1235 $('#wp_optimize_status_box').css('opacity', '1');
1236 $(resp).each(function(index, el) {
1237 if ($(el).is('#wp_optimize_status_box')) {
1238 $('#wp_optimize_status_box').replaceWith($(el));
1239 }
1240 });
1241
1242 });
1243 });
1244
1245 /**
1246 * Run single table optimization. Handle click on Optimize button.
1247 *
1248 * @param {Object} btn jQuery object clicked Optimize button
1249 *
1250 * @return {void}
1251 */
1252 function run_single_table_optimization(btn) {
1253 var spinner = btn.next(),
1254 action_done_icon = spinner.next(),
1255 table_name = btn.data('table'),
1256 table_type = btn.data('type'),
1257 data = {
1258 optimization_id: 'optimizetables',
1259 optimization_table: table_name,
1260 optimization_table_type: table_type
1261 };
1262 btn.hide();
1263 // if checked force button then send force value.
1264 if (force_single_table_optimization) {
1265 data['optimization_force'] = true;
1266 }
1267
1268 spinner.removeClass('visibility-hidden');
1269
1270 send_command('do_optimization', { optimization_id: 'optimizetables', data: data }, function (response) {
1271 if (response.result.meta.error) {
1272 btn.closest('tr').html('<td colspan="8" class="no-table"><p>' + response.result.meta.message + '</p></td>');
1273 setTimeout(function() {
1274 $('#wp_optimize_table_list_refresh').trigger('click');
1275 }, 2000);
1276 } else {
1277 if (response.result.meta.tableinfo) {
1278 var row = btn.closest('tr'),
1279 meta = response.result.meta,
1280 tableinfo = meta.tableinfo;
1281
1282 update_single_table_information(row, tableinfo);
1283
1284 // update total overhead.
1285 $('#wpoptimize_table_list > tbody:last th:eq(6)').html(['<span style="color:', meta.overhead > 0 ? '#0000FF' : '#004600', '">', meta.overhead_formatted,'</span>'].join(''));
1286 }
1287 }
1288
1289 btn.prop('disabled', false);
1290 spinner.addClass('visibility-hidden');
1291 action_done_icon.show().removeClass('visibility-hidden').delay(2500).fadeOut('fast', function() {
1292 btn.show();
1293 action_done_icon.show().addClass('visibility-hidden');
1294 });
1295 });
1296 }
1297
1298 /**
1299 * Update information about single table in the database tables list.
1300 *
1301 * @param {Object} row jQuery object for TR html tag.
1302 * @param {Object} tableinfo
1303 *
1304 * @return {void}
1305 */
1306 function update_single_table_information(row, tableinfo) {
1307 // update table information in row.
1308 $('td:eq(2)', row).text(tableinfo.rows);
1309 $('td:eq(3)', row).text(tableinfo.data_size);
1310 $('td:eq(4)', row).text(tableinfo.index_size);
1311 $('td:eq(5)', row).text(tableinfo.type);
1312
1313 if (tableinfo.is_optimizable) {
1314 $('td:eq(6)', row).html(['<span style="color:', tableinfo.overhead > 0 ? '#0000FF' : '#004600', '">', tableinfo.overhead,'</span>'].join(''));
1315 } else {
1316 $('td:eq(6)', row).html('<span color="#0000FF">-</span>');
1317 }
1318
1319 }
1320
1321 /**
1322 * Update single table optimization buttons state depends on force_optimization value.
1323 *
1324 * @param {boolean} force_optimization See if we need to force optimization
1325 *
1326 * @return {void}
1327 */
1328 function update_single_table_optimization_buttons(force_optimization) {
1329 $('.run-single-table-optimization').each(function() {
1330 var btn = $(this);
1331
1332 if (btn.data('disabled')) {
1333 if (force_optimization) {
1334 btn.prop('disabled', false);
1335 } else {
1336 btn.prop('disabled', true);
1337 }
1338 }
1339 });
1340 }
1341
1342 /**
1343 * Returns true if single site mode or multisite and at least one site selected;
1344 *
1345 * @return {boolean}
1346 */
1347 function is_sites_selected() {
1348 return (0 == wpo_settings_sites_list.length || 0 != $('input[type="checkbox"]:checked', wpo_settings_sites_list).length);
1349 }
1350
1351 /**
1352 * Update optimizations info texts.
1353 *
1354 * @param {Object} response object returned by command get_optimizations_info.
1355 *
1356 * @return {void}
1357 */
1358 function update_optimizations_info_view(response) {
1359 var i, dom_id, info;
1360
1361 // @codingStandardsIgnoreLine
1362 if (!response) return;
1363
1364 for (i in response) {
1365 if (!response.hasOwnProperty(i)) continue;
1366
1367 dom_id = ['#wp-optimize-settings-', response[i].dom_id].join('');
1368 info = response[i].info ? response[i].info : '';
1369
1370 $(dom_id + ' .wp-optimize-settings-optimization-info').html(info);
1371 }
1372 }
1373
1374 var get_optimizations_info_cache = {};
1375
1376 /**
1377 * Send command for get optimizations info and update view.
1378 *
1379 * @return {void}
1380 */
1381 function update_optimizations_info() {
1382 var cache_key = ['', get_selected_sites_list().join('_')].join('');
1383
1384 // if information saved in cache show it.
1385 if (get_optimizations_info_cache.hasOwnProperty(cache_key)) {
1386 update_optimizations_info_view(get_optimizations_info_cache[cache_key]);
1387 } else {
1388 // else send command update cache and update view.
1389 send_command('get_optimizations_info', {'wpo-sites':get_selected_sites_list()}, function(response) {
1390 // @codingStandardsIgnoreLine
1391 if (!response) return;
1392 get_optimizations_info_cache[cache_key] = response;
1393 update_optimizations_info_view(response);
1394 });
1395 }
1396 }
1397
1398 /*
1399 * Check if settings file selected for import.
1400 */
1401 $('#wpo_import_settings_btn').on('click', function(e) {
1402 var file_input = $('#wpo_import_settings_file'),
1403 filename = file_input.val(),
1404 wpo_import_file_file = file_input[0].files[0],
1405 wpo_import_file_reader = new FileReader();
1406
1407 $('#wpo_import_settings_btn').prop('disabled', true);
1408
1409 if (!/\.json$/.test(filename)) {
1410 e.preventDefault();
1411 $('#wpo_import_settings_btn').prop('disabled', false);
1412 $('#wpo_import_error_message').text(wpoptimize.please_select_settings_file).slideDown();
1413 return false;
1414 }
1415
1416 wpo_import_file_reader.onload = function() {
1417 import_settings(this.result);
1418 };
1419
1420 wpo_import_file_reader.readAsText(wpo_import_file_file);
1421
1422 return false;
1423 });
1424
1425 /**
1426 * Send import settings command.
1427 *
1428 * @param {string} settings encoded settings in json string.
1429 *
1430 * @return {void}
1431 */
1432 function import_settings(settings) {
1433 var loader = $('#wpo_import_spinner'),
1434 success_message = $('#wpo_import_success_message'),
1435 error_message = $('#wpo_import_error_message');
1436
1437 loader.show();
1438 send_command('import_settings', {'settings': settings}, function(response) {
1439 loader.hide();
1440 if (response && response.errors && response.errors.length) {
1441 error_message.text(response.errors.join('<br>'));
1442 error_message.slideDown();
1443 } else if (response && response.messages && response.messages.length) {
1444 success_message.text(response.messages.join('<br>'));
1445 success_message.slideDown();
1446 setTimeout(function() {
1447 window.location.reload();
1448 }, 500);
1449 }
1450
1451 $('#wpo_import_settings_btn').prop('disabled', false);
1452 });
1453 }
1454
1455 /*
1456 * Hide file validation message on change file field value.
1457 */
1458 $('#wpo_import_settings_file').on('change', function() {
1459 $('#wpo_import_error_message').slideUp();
1460 });
1461
1462 /*
1463 * Save settings to hidden form field, used for export.
1464 */
1465 $('#wpo_export_settings_btn').on('click', function(e) {
1466 wpo_download_json_file(gather_settings('object'));
1467 return false;
1468 });
1469
1470 /**
1471 * Force download json file with posted data.
1472 *
1473 * @param {Object} data data to put in a file.
1474 * @param {string} filename
1475 *
1476 * @return {void}
1477 */
1478 function wpo_download_json_file(data ,filename) {
1479 // Attach this data to an anchor on page
1480 var link = document.body.appendChild(document.createElement('a')),
1481 date = new Date(),
1482 year = date.getFullYear(),
1483 month = date.getMonth() < 10 ? ['0', date.getMonth()].join('') : date.getMonth(),
1484 day = date.getDay() < 10 ? ['0', date.getDay()].join('') : date.getDay();
1485
1486 filename = filename ? filename : ['wpo-settings-',year,'-',month,'-',day,'.json'].join('');
1487
1488 link.setAttribute('download', filename);
1489 link.setAttribute('style', "display:none;");
1490 link.setAttribute('href', 'data:text/json' + ';charset=UTF-8,' + encodeURIComponent(JSON.stringify(data)));
1491 link.click();
1492 }
1493
1494 /**
1495 * Make ajax request to get optimization info.
1496 *
1497 * @param {Object} optimization_info_container - jquery object obtimization info container.
1498 * @param {string} optimization_id - optimization id.
1499 * @param {Object} params - custom params posted to optimization get info.
1500 *
1501 * @return void
1502 */
1503 var optimization_get_info = function(optimization_info_container, optimization_id, params) {
1504 return send_command('get_optimization_info', {optimization_id: optimization_id, data: params}, function(resp) {
1505 var meta = (resp && resp.result && resp.result.meta) ? resp.result.meta : {},
1506 message = (resp && resp.result && resp.result.output) ? resp.result.output.join('<br>') : '...';
1507
1508 // trigger event about optimization get info in process.
1509 $(document).trigger(['optimization_get_info_', optimization_id].join(''), [message, meta]);
1510 // update status message in optimizations list.
1511 optimization_info_container.html(message);
1512
1513 if (!meta.finished) {
1514 setTimeout(function() {
1515 var xhr = optimization_get_info(optimization_info_container, optimization_id, meta);
1516 $(document).trigger(['optimization_get_info_xhr_', optimization_id].join(''), [xhr, meta]);
1517 }, 1);
1518 } else {
1519 // trigger event about optimization get info action done.
1520 $(document).trigger(['optimization_get_info_', optimization_id, '_done'].join(''), resp);
1521 }
1522 });
1523 };
1524
1525 // attach event handlers after database tables template loaded.
1526 // Handle single optimization click.
1527 $('#wpoptimize_table_list').on('click', '.run-single-table-optimization', function () {
1528 var take_backup_checkbox = $('#enable-auto-backup-1'),
1529 button = $(this);
1530
1531 // check if backup checkbox is checked for db tables
1532 if (take_backup_checkbox.is(':checked')) {
1533 take_a_backup_with_updraftplus(
1534 function () {
1535 run_single_table_optimization(button);
1536 }
1537 );
1538 } else {
1539 run_single_table_optimization(button);
1540 }
1541 });
1542
1543 // Handle repair table click
1544 $('#wpoptimize_table_list').on('click', '.run-single-table-repair', function () {
1545 var btn = $(this),
1546 spinner = btn.next(),
1547 action_done_icon = spinner.next(),
1548 table_name = btn.data('table'),
1549 data = {
1550 optimization_id: 'repairtables',
1551 optimization_table: table_name
1552 };
1553
1554 spinner.removeClass('visibility-hidden');
1555
1556 send_command('do_optimization', {optimization_id: 'repairtables', data: data}, function (response) {
1557 if (response.result.meta.success) {
1558 var row = btn.closest('tr'),
1559 tableinfo = response.result.meta.tableinfo;
1560
1561 btn.prop('disabled', false);
1562 spinner.addClass('visibility-hidden');
1563 action_done_icon.show().removeClass('visibility-hidden');
1564
1565 update_single_table_information(row, tableinfo);
1566
1567 // keep visible results from previous operation for one second and show optimize button if possible.
1568 setTimeout(function () {
1569 var parent_td = btn.closest('td'),
1570 btn_wrap = btn.closest('.wpo_button_wrap');
1571
1572 // remove Repair button and show Optimize button.
1573 btn_wrap.fadeOut('fast', function () {
1574 btn_wrap.closest('.wpo_button_wrap').remove();
1575
1576 // if table type is supported for optimization then show OPTIMIZE button.
1577 if (tableinfo.is_type_supported) {
1578 $('.wpo_button_wrap', parent_td).removeClass('wpo_hidden');
1579 }
1580 });
1581
1582 change_actions_column_visibility();
1583 }, 1000);
1584 } else {
1585 btn.prop('disabled', false);
1586 spinner.addClass('visibility-hidden');
1587 alert(wpoptimize.table_was_not_repaired.replace('%s', table_name));
1588 }
1589 });
1590 });
1591
1592 // Handle convert table click
1593 $('#wpoptimize_table_list').on('click', '.toinnodb', function () {
1594 convert_single_db_table($(this));
1595 });
1596
1597 var table_to_remove_btn;
1598
1599 // Handle delete table click
1600 $('#wpoptimize_table_list').on('click', '.run-single-table-delete', function () {
1601 table_to_remove_btn = $(this);
1602 var take_backup_checkbox = $('#enable-auto-backup-1');
1603 if ('' == wpoptimize.user_always_ignores_table_deletion_warning || '1' !== wpoptimize.user_always_ignores_table_deletion_warning) {
1604 wp_optimize.modal.open({
1605 className: 'wpo-confirm',
1606 events: {
1607 'click .wpo-modal--bg': 'close',
1608 'click .delete-table': 'deleteTable',
1609 'change #confirm_deletion_without_backup': 'changeConfirm',
1610 'change #confirm_table_deletion': 'changeConfirm'
1611 },
1612 content: function() {
1613 var content_template = wp.template('wpo-table-delete');
1614 // Get the plugins list
1615 var plugins_list = table_to_remove_btn.closest('tr').find('.table-plugins').html();
1616 return content_template({
1617 no_backup: !take_backup_checkbox.is(':checked'),
1618 plugins_list: plugins_list,
1619 table_name: table_to_remove_btn.data('table')
1620 });
1621 },
1622 changeConfirm: function() {
1623 var enable_button = true;
1624 var backup_input = this.$('#confirm_deletion_without_backup');
1625 var confirm_input = this.$('#confirm_table_deletion');
1626 if (backup_input.length && !backup_input.is(':checked')) {
1627 enable_button = false;
1628 }
1629 if (!confirm_input.is(':checked')) {
1630 enable_button = false;
1631 }
1632 this.$('.delete-table').prop('disabled', !enable_button);
1633 },
1634 deleteTable: function() {
1635 // check if user ignore table warning
1636 var ignores_table_deletion_warning_checkbox = this.$('#ignores_table_deletion_warning');
1637 if (ignores_table_deletion_warning_checkbox.is(':checked')) {
1638 send_command('user_ignores_table_deletion_warning', {}, function(response) {
1639 if (response.success) {
1640 wpoptimize.user_always_ignores_table_deletion_warning = '1';
1641 }
1642 });
1643 }
1644 // check if backup checkbox is checked for db tables
1645 if (take_backup_checkbox.is(':checked')) {
1646 take_a_backup_with_updraftplus(remove_single_db_table);
1647 } else {
1648 remove_single_db_table();
1649 }
1650 this.close();
1651
1652 }
1653 });
1654 } else {
1655 // check if backup checkbox is checked for db tables
1656 if (take_backup_checkbox.is(':checked')) {
1657 take_a_backup_with_updraftplus(remove_single_db_table);
1658 } else {
1659 remove_single_db_table();
1660 }
1661 }
1662 });
1663
1664 /**
1665 * Send ajax command to convert single table to InnoDB.
1666 *
1667 * @param {Object} btn jQuery object of clicked "Convert to InnoDB" button.
1668 *
1669 * @return void
1670 */
1671 function convert_single_db_table(table_to_convert_btn) {
1672 var spinner = table_to_convert_btn.next(),
1673 action_done_icon = spinner.next(),
1674 table_name = table_to_convert_btn.data('table'),
1675 data = {
1676 optimization_id: 'orphanedtables',
1677 optimization_table: table_name,
1678 optimization_action: 'toinnodb'
1679 };
1680
1681 spinner.removeClass('visibility-hidden');
1682
1683 send_command('do_optimization', { optimization_id: 'orphanedtables', data: data }, function (response) {
1684 if (response.result.meta.error) {
1685 table_to_convert_btn.closest('tr').html('<td colspan="8" class="no-table"><p>' + response.result.meta.message + '</p></td>');
1686 setTimeout(function() {
1687 $('#wp_optimize_table_list_refresh').trigger('click');
1688 }, 2000);
1689 return;
1690 }
1691 if (response.result.meta.success) {
1692 var row = table_to_convert_btn.closest('tr');
1693
1694 action_done_icon.show().removeClass('visibility-hidden');
1695
1696 // remove convert to Innodb button.
1697 row.find(".toinnodb").remove();
1698
1699
1700 setTimeout(function() {
1701 action_done_icon.fadeOut('slow', function() {
1702 row.find("[data-colname='Type']").text("InnoDB");
1703 });
1704 }, 500);
1705 } else {
1706 var message = wpoptimize.table_was_not_converted.replace('%s', table_name);
1707
1708 if (response.result.meta.message) {
1709 message += '(' + response.result.meta.message + ')';
1710 }
1711
1712 alert(message);
1713 }
1714 }).always(function() {
1715 table_to_convert_btn.prop('disabled', false);
1716 spinner.addClass('visibility-hidden');
1717 });
1718 }
1719
1720
1721
1722 /**
1723 * Send ajax command to remove single database table.
1724 *
1725 * @param {Object} btn jQuery object of clicked "Remove" button.
1726 *
1727 * @return void
1728 */
1729 function remove_single_db_table() {
1730 var spinner = table_to_remove_btn.next(),
1731 action_done_icon = spinner.next(),
1732 table_name = table_to_remove_btn.data('table'),
1733 data = {
1734 optimization_id: 'orphanedtables',
1735 optimization_table: table_name
1736 };
1737
1738 spinner.removeClass('visibility-hidden');
1739
1740 send_command('do_optimization', { optimization_id: 'orphanedtables', data: data }, function (response) {
1741 if (response.result.meta.success) {
1742 var row = table_to_remove_btn.closest('tr');
1743
1744 action_done_icon.show().removeClass('visibility-hidden');
1745
1746 // remove row for deleted table.
1747 setTimeout(function() {
1748 row.fadeOut('slow', function() {
1749 row.remove();
1750
1751 change_actions_column_visibility();
1752 });
1753 }, 500);
1754 } else {
1755 var message = wpoptimize.table_was_not_deleted.replace('%s', table_name);
1756
1757 if (response.result.meta.message) {
1758 message += '(' + response.result.meta.message + ')';
1759 }
1760
1761 alert(message);
1762 }
1763 }).always(function() {
1764 table_to_remove_btn.prop('disabled', false);
1765 spinner.addClass('visibility-hidden');
1766 });
1767 }
1768
1769 change_actions_column_visibility();
1770
1771 /**
1772 * Show or hide actions column if need.
1773 *
1774 * @return void
1775 */
1776 function change_actions_column_visibility() {
1777 var table = $('#wpoptimize_table_list'),
1778 hideLastColumn = true;
1779
1780 // check if any button exists in the actions column.
1781 $('tr', table).each(function() {
1782 var row = $(this);
1783
1784 if ($('button', row).length > 0) {
1785 hideLastColumn = false;
1786 return false;
1787 }
1788 });
1789
1790 // hide or show last column
1791 $('tr', table).each(function() {
1792 var row = $(this);
1793
1794 if (hideLastColumn) {
1795 $('td:last, th:last', row).hide();
1796 } else {
1797 $('td:last, th:last', row).show();
1798 }
1799 });
1800 }
1801
1802 /*
1803 * Validate general settings (loggers).
1804 */
1805 $('#wp-optimize-general-settings').on('wpo-saving-form-data', function() {
1806 var valid = true;
1807 var $form = $(this);
1808
1809 $('.wpo_logger_addition_option, .wpo_logger_type').each(function() {
1810 if (!validate_field($(this), true)) {
1811 valid = false;
1812 $(this).addClass('wpo_error_field');
1813 } else {
1814 $(this).removeClass('wpo_error_field');
1815 }
1816 });
1817
1818 if (!valid) {
1819 $form.form_errors.add('missing-fields', '');
1820 $('#wp-optimize-settings-save-results')
1821 .show()
1822 .addClass('wpo_alert_notice')
1823 .text(wpoptimize.fill_all_settings_fields)
1824 .delay(5000)
1825 .fadeOut(3000, function() {
1826 $(this).removeClass('wpo_alert_notice');
1827 });
1828 } else {
1829 $form.form_errors.remove('missing-fields');
1830 $('#wp-optimize-logger-settings .save_settings_reminder').slideUp();
1831 }
1832
1833 });
1834
1835 /**
1836 * Validate import field with data-validate attribute.
1837 *
1838 * @param {object} field jquery element
1839 * @param {boolean} required
1840 *
1841 * @return {boolean}
1842 */
1843 function validate_field(field, required) {
1844 var value = field.val(),
1845 validate = field.data('validate');
1846
1847 if (!validate && required) {
1848 return ('' != value.trim());
1849 }
1850
1851 if (validate && !required && '' == value.trim()) {
1852 return true;
1853 }
1854
1855 var valid = true;
1856
1857 switch (validate) {
1858 case 'email':
1859 var regex = /\S+@\S+\.\S+/,
1860 emails = value.split(","),
1861 email = '';
1862
1863 for (var i = 0; i < emails.length; i++) {
1864 email = emails[i].trim();
1865
1866 if ('' == email || !regex.test(email)) {
1867 valid = false;
1868 }
1869 }
1870 break;
1871
1872 case 'url':
1873 // https://gist.github.com/dperini/729294
1874 // @codingStandardsIgnoreLine
1875 var regex = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
1876
1877 valid = regex.test(value);
1878 break;
1879 }
1880
1881 return valid;
1882 }
1883
1884 /**
1885 * Send check_overdue_crons command and output warning if need.
1886 */
1887 setTimeout(function() {
1888 send_command('check_overdue_crons', null, function (resp) {
1889 if (resp && resp.hasOwnProperty('m')) {
1890 $('#wpo_settings_warnings').append(resp.m);
1891 }
1892 });
1893 }, 11000);
1894
1895 /**
1896 * Hide introduction notice
1897 */
1898 $('.wpo-introduction-notice .notice-dismiss, .wpo-introduction-notice .close').on('click', function(e) {
1899 $('.wpo-introduction-notice').remove();
1900 send_command('dismiss_install_or_update_notice', null, function (resp) {
1901 if (resp && resp.hasOwnProperty('error')) {
1902 // there was an error.
1903 console.log('There was an error dismissing the install or update notice (dismiss_install_or_update_notice)', resp);
1904 }
1905 });
1906 });
1907
1908 $('#wpo-settings-export').on('click', export_settings);
1909
1910 $('#wpo-settings-import').on('click', function(e) {
1911 e.preventDefault();
1912
1913 block_ui(wpoptimize.importing);
1914
1915 var wpo_import_file_input = document.getElementById('import_settings');
1916 if (0 === wpo_import_file_input.files.length) {
1917 alert(wpoptimize.import_select_file);
1918 $.unblockUI();
1919 return;
1920 }
1921 read_settings_json_file(wpo_import_file_input.files[0]);
1922 });
1923
1924 /**
1925 * Pack WPO settings into a single object
1926 *
1927 * @return {object}
1928 */
1929 function build_settings() {
1930 var date_now = new Date();
1931
1932 return {
1933 epoch_date: date_now.getTime(),
1934 local_date: date_now.toLocaleString(),
1935 network_site_url: wpoptimize.network_site_url,
1936 data: {
1937 cache_settings: wp_optimize.cache_settings(),
1938 minify_settings: wp_optimize.minify_settings(),
1939 smush_settings: wp_optimize.smush_settings(),
1940 database_settings: gather_settings('string')
1941 }
1942 };
1943 }
1944
1945 /**
1946 * Export plugin settings as a JSON file
1947 *
1948 * @param {object} e - Event object
1949 *
1950 * @return {void}
1951 */
1952 function export_settings(e) {
1953 e.preventDefault();
1954
1955 form_data = JSON.stringify(build_settings());
1956
1957 // Attach this data to an anchor on page
1958 var link = document.body.appendChild(document.createElement('a'));
1959 link.setAttribute('download', wpoptimize.export_settings_file_name);
1960 link.setAttribute('style', "display:none;");
1961 link.setAttribute('href', 'data:text/json' + ';charset=UTF-8,' + encodeURIComponent(form_data));
1962 link.click();
1963 }
1964
1965 /**
1966 * Read json settings file and import it
1967 *
1968 * @param {Blob} file - Settings file
1969 *
1970 * @return {void}
1971 */
1972 function read_settings_json_file(file) {
1973 var file_reader = new FileReader();
1974 file_reader.onload = function() {
1975 import_settings(this.result);
1976 };
1977 file_reader.readAsText(file);
1978 }
1979
1980 /**
1981 * Import json data and save it as plugin settings in database
1982 *
1983 * @param {json} json_data
1984 *
1985 * @return {void}
1986 */
1987 function import_settings(json_data) {
1988 var parsed;
1989 try {
1990 parsed = wpo_parse_json(json_data);
1991 } catch (e) {
1992 $.unblockUI();
1993 jQuery('#import_settings').val('');
1994 console.log(json_data);
1995 console.log(e);
1996 alert(wpoptimize.import_invalid_json_file);
1997 return;
1998 }
1999 if (window.confirm(wpoptimize.importing_data_from + ' ' + parsed['network_site_url'] + "\n" + wpoptimize.exported_on + ' ' + parsed['local_date'] + "\n" + wpoptimize.continue_import)) {
2000 // GET the settings back to the AJAX handler
2001 var stringified = JSON.stringify(parsed['data']);
2002 send_command('import_settings', {
2003 settings: stringified
2004 }, function(response) {
2005 $.unblockUI();
2006 if (response && response.errors) {
2007 alert(response.errors.join('<br />'));
2008 } else if (response && response.success) {
2009 alert(response.message);
2010 setTimeout(function() {
2011 window.location.reload();
2012 }, 200);
2013 }
2014 });
2015 } else {
2016 $.unblockUI();
2017 }
2018 }
2019
2020 /**
2021 * Define popup for each optimization action that needs confirmation from user
2022 */
2023 function get_destructive_actions_confirm_popup(action) {
2024 var popups = destructive_actions_confirm_popup = {
2025 postmeta: {
2026 className: 'wpo-confirm',
2027 events: {
2028 'click .wpo-modal--bg': 'close',
2029 'click #confirm_post_meta_deletion': 'deleteConfirm',
2030 'click .cancel': 'cancel',
2031 'click #confirm-post-meta-delete-action': 'confirm'
2032 },
2033 content: function() {
2034 var content_template = wp.template('wpo-postmeta');
2035 return content_template({});
2036 },
2037 deleteConfirm: function() {
2038 var enable_button = $('#confirm_post_meta_deletion').is(':checked');
2039 $('.delete-post-meta').prop('disabled', !enable_button);
2040 }
2041 },
2042 orphandata: {
2043 className: 'wpo-confirm',
2044 events: {
2045 'click .wpo-modal--bg': 'close',
2046 'click #confirm_orphaned_relationship_data_deletion': 'deleteConfirm',
2047 'click .cancel': 'cancel',
2048 'click #confirm-orphaned-relationship-data-delete-action': 'confirm'
2049 },
2050 content: function() {
2051 var content_template = wp.template('wpo-orphandata');
2052 return content_template({});
2053 },
2054 deleteConfirm: function() {
2055 var enable_button = $('#confirm_orphaned_relationship_data_deletion').is(':checked');
2056 $('.delete-orphaned-relationship-data').prop('disabled', !enable_button);
2057 }
2058 },
2059 "grouped-warnings": {
2060 className: 'wpo-confirm',
2061 events: {
2062 'click .wpo-modal--bg': 'close',
2063 'click #confirm_grouped_warnings_data_deletion': 'deleteConfirm',
2064 'click .cancel': 'cancel',
2065 'click #confirm-grouped-warnings-data-delete-action': 'confirm'
2066 },
2067 deleteConfirm: function() {
2068 var enable_button = $('#confirm_grouped_warnings_data_deletion').is(':checked');
2069 $('.delete-grouped-warnings-data').prop('disabled', !enable_button);
2070 }
2071 }
2072 }
2073
2074 return popups[action];
2075 }
2076
2077 /**
2078 * Attach click event to postmeta checkbox
2079 */
2080 function add_warning_for_delete_post_meta_action() {
2081 $('#optimization_button_postmeta_big').on('click', function (evt) {
2082 return function(this_button) {
2083 var remove_post_meta_checkbox = $('#optimization_checkbox_postmeta');
2084
2085 if (should_user_confirm_action('postmeta')) {
2086 wp_optimize.modal.open(
2087 Object.assign(get_destructive_actions_confirm_popup('postmeta'), {
2088 cancel: function() {
2089 $(remove_post_meta_checkbox).prop('checked', false);
2090 },
2091 confirm: function() {
2092 maybe_dismiss_destructive_actions();
2093 this.close();
2094
2095 $(this_button).prop('bypass-confirm-box', true);
2096 $(this_button).trigger('click');
2097
2098 }
2099 }
2100 ));
2101
2102 evt.preventDefault();
2103 return false;
2104 } else {
2105 $(this_button).prop('bypass-confirm-box', false);
2106 return true;
2107 }
2108 }(this);
2109 });
2110 }
2111
2112 /**
2113 * Check if dismiss future confirms checkbox is visible and selected, then save option in DB
2114 */
2115 function maybe_dismiss_destructive_actions() {
2116 var ignores_orphaned_relationship_data_delete_warning_checkbox = $('#ignores_orphaned_relationship_data_deletion_warning');
2117 if (ignores_orphaned_relationship_data_delete_warning_checkbox.is(':visible') && ignores_orphaned_relationship_data_delete_warning_checkbox.is(':checked')) {
2118 send_command('user_ignores_orphaned_relationship_data_deletion_warning', {}, function(response) {
2119 if (response.success) {
2120 wpoptimize.user_always_ignores_orphaned_relationship_data_deletion_warning = '1';
2121 }
2122 });
2123 }
2124
2125 var ignores_post_meta_deletion_warning_checkbox = $('#ignores_post_meta_deletion_warning');
2126 if (ignores_post_meta_deletion_warning_checkbox.is(':visible') && ignores_post_meta_deletion_warning_checkbox.is(':checked')) {
2127 send_command('user_ignores_post_meta_deletion_warning', {}, function(response) {
2128 if (response.success) {
2129 wpoptimize.user_always_ignores_post_meta_deletion_warning = '1';
2130 }
2131 });
2132 }
2133 }
2134
2135 /**
2136 * Check if user dismissed confirms, or should they see the confirm popup
2137 */
2138 function should_user_confirm_action(action) {
2139 if ('orphandata' == action) {
2140 var bypass_confirm = $('#optimization_button_orphandata_big').prop('bypass-confirm-box') == true;
2141
2142 return !bypass_confirm && ('' == wpoptimize.user_always_ignores_orphaned_relationship_data_deletion_warning || '1' !== wpoptimize.user_always_ignores_orphaned_relationship_data_deletion_warning);
2143 } else if ('postmeta' == action) {
2144 var bypass_confirm = $('#optimization_button_postmeta_big').prop('bypass-confirm-box') == true;
2145
2146 return !bypass_confirm && ('' == wpoptimize.user_always_ignores_post_meta_deletion_warning || '1' !== wpoptimize.user_always_ignores_post_meta_deletion_warning);
2147 }
2148 }
2149
2150 /**
2151 * Attach click event to orphandata optimization checkbox
2152 */
2153 function add_warning_for_delete_orphaned_relationship_data_action() {
2154 $('#optimization_button_orphandata_big').on('click', function (evt) {
2155 return function(this_button) {
2156 var remove_orphaned_relationship_data_checkbox = $('#optimization_checkbox_orphandata');
2157
2158 if (should_user_confirm_action('orphandata')) {
2159 wp_optimize.modal.open(
2160 Object.assign(get_destructive_actions_confirm_popup('orphandata'), {
2161 cancel: function() {
2162 $(remove_orphaned_relationship_data_checkbox).prop('checked', false);
2163 },
2164 confirm: function() {
2165 maybe_dismiss_destructive_actions();
2166
2167 this.close();
2168
2169 $(this_button).prop('bypass-confirm-box', true);
2170 $(this_button).trigger('click');
2171 }
2172 }
2173 ));
2174
2175 evt.preventDefault();
2176 return false;
2177 } else {
2178 $(this_button).prop('bypass-confirm-box', false);
2179 return true;
2180 }
2181 }(this);
2182 });
2183 }
2184
2185 // Attach heartbeat API events
2186 heartbeat.setup();
2187
2188 return {
2189 send_command: send_command,
2190 optimization_get_info: optimization_get_info,
2191 take_a_backup_with_updraftplus: take_a_backup_with_updraftplus,
2192 save_auto_backup_options: save_auto_backup_options,
2193 build_settings: build_settings
2194 }
2195 }; // END function WP_Optimize()
2196
2197 jQuery(function ($) {
2198 /**
2199 * Show additional options section if optimization enabled
2200 *
2201 * @param {string} checkbox Logger settings jQuery checkbox object.
2202 *
2203 * @return {void}
2204 */
2205 function show_hide_additional_logger_options($checkbox) {
2206 var additional_section_id = ['#', $checkbox.data('additional')].join('');
2207
2208 if ($checkbox.is(':checked')) {
2209 $(additional_section_id).show();
2210 } else {
2211 $(additional_section_id).hide();
2212 }
2213 }
2214
2215 // Add events handler for each logger.
2216 $('.wp-optimize-logging-settings').each(function () {
2217 var $checkbox = $(this);
2218 show_hide_additional_logger_options($checkbox);
2219 $checkbox.on('change', function () {
2220 show_hide_additional_logger_options($checkbox);
2221 });
2222 });
2223
2224 var add_logging_btn = $('#settings_form');
2225
2226 /**
2227 * Handle add logging destination click.
2228 */
2229 add_logging_btn.on('click', '#wpo_add_logger_link', function(e) {
2230 e.preventDefault();
2231 $('#wp-optimize-logger-settings .save_settings_reminder').after(get_add_logging_form_html());
2232
2233 filter_select_destinations($('.wpo_logger_type').first());
2234 });
2235
2236 /**
2237 * Handle logging destination select change.
2238 */
2239 $('#wp-optimize-general-settings').on('change', '.wpo_logger_type', function() {
2240 var select = $(this),
2241 logger_id = select.val(),
2242 options_container = select.parent().find('.wpo_additional_logger_options');
2243
2244 options_container.html(get_logging_additional_options_html(logger_id));
2245
2246 if (select.val()) {
2247 show_logging_save_settings_reminder();
2248 }
2249 });
2250
2251 /**
2252 * Show save settings reminder for logging settings.
2253 *
2254 * @return {void}
2255 */
2256 function show_logging_save_settings_reminder() {
2257 var reminder = $('#wp-optimize-logger-settings .save_settings_reminder');
2258
2259 if (!reminder.is(':visible')) {
2260 reminder.slideDown('normal');
2261 }
2262 }
2263
2264 /**
2265 * Handle edit logger click.
2266 */
2267 $('#settings_form').on('click', '.wpo_logging_actions_row .wpo_edit_logger', function() {
2268
2269 var link = $(this),
2270 container = link.closest('.wpo_logging_row');
2271
2272 $('.wpo_additional_logger_options', container).removeClass('wpo_hidden');
2273 $('.wpo_logging_options_row', container).hide();
2274 $('.wpo_logging_status_row', container).hide();
2275 /*link.hide();
2276 link.next('.wpo_delete_logger').hide();*/
2277 link.parent('.wpo_logging_actions_row').hide();
2278 $(container).children('.wpo_logging_edit_row').show();
2279
2280 return false;
2281 });
2282
2283 /**
2284 * Handle cancel logger click.
2285 */
2286 $('#settings_form').on('click', '.wpo_logging_edit_row .wpo_cancel_logging', function() {
2287
2288 var cancel_btn = $(this),
2289 container = cancel_btn.closest('.wpo_logging_row');
2290
2291 $(container).children('.wpo_logging_edit_row').hide();
2292 $(container).children('.wpo_logging_options_row').show();
2293 $(container).children('.wpo_logging_status_row').show();
2294 $(container).children('.wpo_logging_actions_row').show();
2295 $(container).children('.wpo_additional_logger_options').addClass('wpo_hidden');
2296
2297 return false;
2298 });
2299
2300 $('#wp-optimize-logger-settings').on('change', '.wpo_logger_addition_option', function() {
2301 show_logging_save_settings_reminder();
2302 });
2303
2304 /**
2305 * Handle change of active/inactive status and update hidden field value.
2306 */
2307 $('#settings_form').on('change', '.wpo_logger_active_checkbox', function() {
2308 var checkbox = $(this),
2309 hidden_input = checkbox.closest('label').find('input[type="hidden"]');
2310
2311 hidden_input.val(checkbox.is(':checked') ? '1' : '0');
2312 });
2313
2314 /**
2315 * Handle delete logger destination click.
2316 */
2317 $('#wp-optimize-general-settings').on('click', '.wpo_delete_logger', function() {
2318
2319 if (!confirm(wpoptimize.are_you_sure_you_want_to_remove_logging_destination)) {
2320 return false;
2321 }
2322
2323 var btn = $(this);
2324 btn.closest('.wpo_logging_row, .wpo_add_logger_form').remove();
2325 filter_all_select_destinations();
2326
2327 if (0 == $('#wp-optimize-logging-options .wpo_logging_row').length) {
2328 $('#wp-optimize-logging-options').hide();
2329 }
2330
2331 setTimeout(function(){
2332 $('#wp-optimize-save-main-settings').trigger('click');
2333 }, 500);
2334
2335 return false;
2336 });
2337
2338 /**
2339 * Filter all selects with logger destinations, called after some destination deleted.
2340 *
2341 * @return {void}
2342 */
2343 function filter_all_select_destinations() {
2344 $('.wpo_logger_type').each(function() {
2345 filter_select_destinations($(this));
2346 });
2347 }
2348
2349 /**
2350 * Filter certain select options depending on currently selected values.
2351 *
2352 * @param {object} select
2353 *
2354 * @return {void}
2355 */
2356 function filter_select_destinations(select) {
2357 var i,
2358 destination,
2359 current_destinations = get_current_destinations();
2360
2361 for (i in current_destinations) {
2362 destination = current_destinations[i];
2363 if (wpoptimize.loggers_classes_info[destination].allow_multiple) {
2364 $('option[value="'+destination+'"]', select).show();
2365 } else {
2366 $('option[value="'+destination+'"]', select).hide();
2367 }
2368 }
2369 }
2370
2371 /**
2372 * Returns currently selected loggers destinations.
2373 *
2374 * @return {Array}
2375 */
2376 function get_current_destinations() {
2377 var destinations = [];
2378
2379 $('.wpo_logging_row, .wpo_logger_type').each(function() {
2380 var destination = $(this).is('select') ? $(this).val() : $(this).data('id');
2381
2382 if (destination) destinations.push(destination);
2383 });
2384
2385 return destinations;
2386 }
2387
2388 /**
2389 * Return add logging form.
2390 *
2391 * @return {string}
2392 */
2393 function get_add_logging_form_html() {
2394 var i,
2395 select_options = [
2396 '<option value="">' + wpoptimize.select_destination + '</option>'
2397 ];
2398
2399 for (i in wpoptimize.loggers_classes_info) {
2400 if (!wpoptimize.loggers_classes_info.hasOwnProperty(i)) continue;
2401
2402 if (!wpoptimize.loggers_classes_info[i].available) continue;
2403
2404 select_options.push(['<option value="',i,'">',wpoptimize.loggers_classes_info[i].description,'</option>'].join(''));
2405 }
2406
2407 return [
2408 '<div class="wpo_add_logger_form">',
2409 '<select class="wpo_logger_type" name="wpo-logger-type[]">',
2410 select_options.join(''),
2411 '</select>',
2412 '<div class="wpo_logging_edit_row" style="display:block;"><span class="wpo_delete_logger button button-secondary" title="'+wpoptimize.cancel+'">'+wpoptimize.cancel+'</span>',
2413 '<span class="wpo_save_logging button button-primary" title="'+wpoptimize.add+'">'+wpoptimize.add+'</span></div>',
2414 '<div class="wpo_additional_logger_options"></div>',
2415 '</div>'
2416 ].join('');
2417 }
2418
2419 /**
2420 * Returns logging options html.
2421 *
2422 * @param {string} logger_id
2423 *
2424 * @return {string}
2425 */
2426 function get_logging_additional_options_html(logger_id) {
2427 if (!wpoptimize.loggers_classes_info[logger_id].options) return '';
2428
2429 var i,
2430 options = wpoptimize.loggers_classes_info[logger_id].options,
2431 options_list = [],
2432 placeholder = '',
2433 validate = '';
2434
2435 for (i in options) {
2436 if (!options.hasOwnProperty(i)) continue;
2437
2438 if (Array.isArray(options[i])) {
2439 placeholder = options[i][0].trim();
2440 validate = options[i][1].trim();
2441 } else {
2442 placeholder = options[i].trim();
2443 validate = '';
2444 }
2445
2446 options_list.push([
2447 '<input class="wpo_logger_addition_option" type="text" name="wpo-logger-options[',i,'][]" value="" ',
2448 'placeholder="',placeholder,'" ',('' !== validate ? 'data-validate="'+validate+'"' : ''), '/>'
2449 ].join(''));
2450 }
2451
2452 // Add hidden field for active/inactive value.
2453 options_list.push('<input type="hidden" name="wpo-logger-options[active][]" value="1" />');
2454
2455 return options_list.join('');
2456 }
2457
2458 /**
2459 * Layout - Adds `is-scrolled` class to the body element when scrolled.
2460 */
2461 var is_scrolled = false;
2462 $(window).on('scroll', function(e) {
2463 window.requestAnimationFrame(function() {
2464 var threshold = $('.wpo-main-header').length ? $('.wpo-main-header')[0].offsetTop : 0;
2465 if ((window.pageYOffset > threshold - 20) != is_scrolled) {
2466 is_scrolled = !is_scrolled;
2467 $('body').toggleClass('is-scrolled', is_scrolled);
2468 }
2469 });
2470 });
2471
2472 // Opens the video preview / info popup
2473 $('.wpo-info__trigger').on('click', function(e) {
2474 e.preventDefault();
2475 var $container = $(this).closest('.wpo-info');
2476 $container.toggleClass('opened');
2477 });
2478
2479 // Embed videos when clicking the vimeo links
2480 $('.wpo-video-preview a').on('click', function(e) {
2481 var video_url = $(this).data('embed');
2482 if (video_url) {
2483 e.preventDefault();
2484 var $iframe = $('<iframe width="356" height="200" allowfullscreen webkitallowfullscreen mozallowfullscreen>').attr('src', video_url);
2485 $iframe.insertAfter($(this));
2486 $(this).remove();
2487 $iframe.focus();
2488 }
2489 });
2490
2491 // Show/hide Enable the caching menu in the admin bar on cache/minify status change
2492 $(document).on('wp-optimize/cache/toggle-status wp-optimize/minify/toggle-status', function() {
2493 var minify_or_cache_enabled = $('#wpo_min_enable_minify').prop('checked') || $('#enable_page_caching').prop('checked');
2494 $('#enable_cache_in_admin_bar_option').toggleClass('wpo_hidden', !minify_or_cache_enabled);
2495 });
2496 });
2497