PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.6.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.6.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 3.8.0 All 110 releases
wp-optimize / js / wpoadmin.js

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

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