PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.4.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.4.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / js / wpoadmin.js

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

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