PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.21
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.21
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 / wposmush.js

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

1,317 lines 40.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 jQuery(function($) {
2 WP_Optimize_Smush = WP_Optimize_Smush();
3 });
4
5 var WP_Optimize_Smush = function() {
6
7 var $ = jQuery;
8
9 /**
10 * Variables for smushing.
11 */
12 var smush_nav_tab = $('#wp-optimize-images-nav-tab-smush'),
13 smush_images_grid = $('#wpo_smush_images_grid'),
14 smush_images_optimization_message = $('#smush_info_images'),
15 smush_images_pending_tasks_container = $('#wpo_smush_images_pending_tasks_container'),
16 smush_images_pending_tasks_btn = $('#wpo_smush_images_pending_tasks_button'),
17 smush_images_save_options_btn = $('.wpo-fieldgroup #wpo_smush_images_save_options_button'),
18 smush_images_refresh_btn = $('#wpo_smush_images_refresh'),
19 smush_images_select_all_btn = $('#wpo_smush_images_select_all'),
20 smush_images_select_none_btn = $('#wpo_smush_images_select_none'),
21 smush_images_stats_clear_btn = $('#wpo_smush_clear_stats_btn'),
22 smush_selected_images_btn = $('#wpo_smush_images_btn'),
23 smush_mark_as_compressed_btn = $('#wpo_smush_mark_as_compressed'),
24 smush_single_image_btn = $('.wpo_smush_single_image .button'),
25 smush_single_restore_btn = $('.wpo_restore_single_image .button'),
26 convert_to_webp_btn = $('.wpo_smush.column-wpo_smush .convert-to-webp');
27 smush_mark_all_as_uncompressed_btn = $('#wpo_smush_mark_all_as_uncompressed_btn'),
28 restore_all_compressed_images_btn = $('#wpo_smush_restore_all_compressed_images_btn'),
29 smush_view_logs_btn = $('.wpo_smush_get_logs'),
30 smush_delete_backup_images_btn = $('#wpo_smush_delete_backup_btn'),
31 compression_server_select = $('.compression_server'),
32 reset_webp_serving_method_btn = $('#wpo_reset_webp_serving_method'),
33 smush_images_tab_loaded = false,
34 smush_service_features = [],
35 smush_total_seconds = 0,
36 smush_timer_locked = false,
37 smush_timer_handle = 0,
38 smush_image_list = [],
39 smush_completed = false,
40 smush_mark_all_as_uncompressed = false,
41 smush_affected_images = {},
42 pending_tasks_cancel_btn = $('#wpo_smush_images_pending_tasks_cancel_button'),
43 uncompressed_images_sites_select = $('#wpo_uncompressed_images_sites_select');
44
45 /**
46 * Handle Image Selection
47 */
48
49 smush_images_grid.on('click', '.thumbnail', function (e) {
50 $(this).closest('input[type="checkbox"]').prop('checked', true);
51 });
52
53
54 /**
55 * Handle Shift Ctrl keys state.
56 */
57 var ctrl_shift_on_image_held = false;
58
59
60 smush_images_grid.on('mousedown', '.thumbnail', function (e) {
61 ctrl_shift_on_image_held = e.shiftKey || e.ctrlKey;
62 });
63
64 smush_images_grid.on('mouseup', '.thumbnail', function (e) {
65 ctrl_shift_on_image_held = e.shiftKey || e.ctrlKey;
66 });
67
68 // Resets server rewrite capability
69 reset_webp_serving_method_btn.on('click', function(e) {
70 e.preventDefault();
71 smush_manager_send_command('reset_webp_serving_method', {}, function(resp) {
72 if (!resp.success) {
73 console.log('[Failed] WebP server capability detection');
74 } else {
75 $('#wpo_reset_webp_serving_method_done').show().delay(3000).fadeOut();
76 }
77 });
78 });
79
80 /**
81 * Checks if smush is active and loads images if yes - image tabs change.
82 */
83 $('#wp-optimize-nav-tab-wrapper__wpo_images .nav-tab').on('click', function() {
84 if ($(this).is('#wp-optimize-nav-tab-wpo_images-smush')) {
85 get_info_from_smush_manager();
86 }
87 });
88
89 /**
90 * Checks if smush is active and loads images if yes - main menu change.
91 */
92 $('#wp-optimize-wrap').on('page-change', function(e, params) {
93 if ('wpo_images' == params.page) {
94 if ($('#wp-optimize-nav-tab-wrapper__wpo_images .nav-tab-active').is('#wp-optimize-nav-tab-wpo_images-smush')) {
95 get_info_from_smush_manager();
96 }
97 }
98 });
99
100 if ($('#smush-metabox').length > 0) {
101 update_view_available_options();
102 }
103
104
105 var lastclick = null;
106 smush_images_grid.on('click' , '.wpo_smush_image' , function(e) {
107 var grid_input = $('#wpo_smush_images_grid input[type="checkbox"]');
108 var input = $(this).find('.wpo_smush_image__input');
109 var input_val = (!(input.prop('checked')));
110 if (!lastclick) {
111 $(this).find('.wpo_smush_image__input').prop('checked',input_val);
112 lastclick = input;
113 }
114 if (true === ctrl_shift_on_image_held) {
115 var start = grid_input.index(input);
116 var end = grid_input.index(lastclick);
117 if (start === end) {
118 grid_input.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', input_val);
119 } else {
120 if (true === lastclick.prop('checked')) {
121 grid_input.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', input_val);
122 }
123 }
124 }
125 lastclick = input;
126 update_smush_action_buttons_state();
127 });
128
129 /**
130 * Disable smush actions buttons if no images selected.
131 */
132 function update_smush_action_buttons_state() {
133 var state = (0 == $('input[type="checkbox"]:checked', smush_images_grid).length);
134
135 smush_selected_images_btn.prop('disabled', state);
136 smush_mark_as_compressed_btn.prop('disabled', state);
137 }
138
139 update_smush_action_buttons_state();
140
141 /**
142 * Handles change of smush service provider
143 */
144 compression_server_select.on('change', function(e) {
145 update_view_available_options();
146 save_options();
147 });
148
149 /**
150 * Process bulk smush
151 */
152 smush_selected_images_btn.off().on('click', function() {
153
154 if (0 == $('#wpo_smush_images_grid input[type="checkbox"]:checked').length) {
155 $('#smush-information-modal .smush-information').text(wposmush.please_select_images)
156 update_view_modal_message($('#smush-information-modal'), $.unblockUI);
157 return;
158 }
159
160 $('#smush-information-modal .smush-information').text(wposmush.server_check);
161 update_view_modal_message($('#smush-information-modal'));
162
163 data = { 'server': $("input[name='compression_server']:checked").val() };
164 smush_manager_send_command('check_server_status', data, function(resp) {
165 if (resp.online) {
166 bulk_smush_selected_images();
167 } else {
168 if (resp.error) {
169 error_message = resp.error + '<br>' + wposmush.server_error
170 $('#smush-information-modal .smush-information').html(error_message);
171 } else {
172 $('#smush-information-modal .smush-information').text(wposmush.server_error);
173 }
174 update_view_modal_message($('#smush-information-modal'), $.unblockUI);
175 }
176 });
177 });
178
179 /**
180 * Mark as compressed
181 */
182 smush_mark_as_compressed_btn.off().on('click', function() {
183 if (0 == $('#wpo_smush_images_grid input[type="checkbox"]:checked').length) {
184 $('#smush-information-modal .smush-information').text(wposmush.please_select_compressed_images)
185 update_view_modal_message($('#smush-information-modal'), $.unblockUI);
186 return;
187 }
188
189 var selected_images = [],
190 image;
191
192 $('#wpo_smush_images_grid input:checked').each(function() {
193 image = {
194 'attachment_id':$(this).val(),
195 'blog_id': $(this).data('blog')
196 };
197 selected_images.push(image);
198 });
199
200 update_view_modal_message(wposmush.please_updating_images_info);
201
202 smush_manager_send_command('mark_as_compressed', {selected_images: selected_images}, function(response) {
203 $('#smush-information-modal .smush-information').text(response.summary);
204 update_view_modal_message($('#smush-information-modal'), $.unblockUI);
205 // refresh images list.
206 get_info_from_smush_manager();
207 });
208 });
209
210 /**
211 * Handle "Mark all images as uncompressed" click.
212 */
213 smush_mark_all_as_uncompressed_btn.on('click', function() {
214 if (!confirm(wposmush.mark_all_images_uncompressed)) return;
215
216 var restore_backup = confirm(wposmush.restore_images_from_backup);
217
218 update_view_modal_message($('#smush-information-modal-cancel-btn'));
219 $('#smush-information-modal-cancel-btn .smush-information').text(wposmush.please_wait);
220
221 smush_mark_all_as_uncompressed = true;
222 run_mark_all_as_uncompressed(restore_backup);
223 });
224
225 /**
226 * Handle "Restore all compressed images" click.
227 */
228 restore_all_compressed_images_btn.on('click', function() {
229 if (!confirm(wposmush.restore_all_compressed_images)) return;
230
231 update_view_modal_message($('#smush-information-modal-cancel-btn'));
232 $('#smush-information-modal-cancel-btn .smush-information').text(wposmush.please_wait);
233
234 smush_mark_all_as_uncompressed = true;
235 run_mark_all_as_uncompressed(true, true);
236 });
237
238 /**
239 * Handle "Cancel" button click for mark all images as uncompressed process
240 */
241 $('#smush-information-modal-cancel-btn input[type="button"]').on('click', function() {
242 smush_mark_all_as_uncompressed = false;
243 get_info_from_smush_manager();
244 $.unblockUI();
245 });
246
247 /**
248 * Send command for mark all compressed images as uncompressed.
249 *
250 * @param {bool} restore_backup if set to true then images will restored from backup if possible.
251 */
252 function run_mark_all_as_uncompressed(restore_backup, delete_only_backups_meta) {
253 if (!smush_mark_all_as_uncompressed) return;
254
255 var info = $('#smush-information-modal-cancel-btn .smush-information');
256 smush_manager_send_command('mark_all_as_uncompressed',
257 {
258 restore_backup: restore_backup ? 1 : 0,
259 delete_only_backups_meta: delete_only_backups_meta ? 1 : 0
260 },
261 function(resp) {
262 // if cancel button pressed then exit
263 if (!smush_mark_all_as_uncompressed) return;
264
265 // if we get an error then show it
266 if (resp.hasOwnProperty('error')) {
267 update_view_modal_message($('#smush-information-modal'), $.unblockUI);
268 $('#smush-information-modal .smush-information').text(resp.error);
269 get_info_from_smush_manager();
270 return;
271 }
272
273 // if completed then refresh uncompressed images list and show final message.
274 if (resp.completed) {
275 update_view_modal_message($('#smush-information-modal'), $.unblockUI);
276 $('#smush-information-modal .smush-information').text(resp.message);
277 get_info_from_smush_manager();
278 } else {
279 info.text(resp.message);
280 run_mark_all_as_uncompressed(restore_backup);
281 }
282 }
283 );
284 }
285
286 /**
287 * Refresh image list
288 */
289 smush_images_refresh_btn.off().on('click', function() {
290 get_info_from_smush_manager();
291 });
292
293 /**
294 * Bind select all / select none controls
295 */
296 smush_images_select_all_btn.off().on('click', function() {
297 $('#wpo_smush_images_grid input[type="checkbox"]').prop("checked", true);
298 lastclick = null;
299 update_smush_action_buttons_state();
300 });
301
302
303 /**
304 * Bind select all / select none controls
305 */
306 smush_images_select_none_btn.off().on('click', function() {
307 $('#wpo_smush_images_grid input[type="checkbox"]').prop("checked", false);
308 lastclick = null;
309 update_smush_action_buttons_state();
310 });
311
312 /**
313 * Displays logs in a modal
314 */
315 smush_view_logs_btn.off().on('click', function() {
316 $("#log-panel").text("Please wait, fetching logs.");
317 smush_manager_send_command('get_smush_logs', {}, function(resp) {
318 $.blockUI({
319 message: $("#smush-log-modal"),
320 onOverlayClick: $.unblockUI(),
321 css: {
322 width: '80%',
323 height: '80%',
324 top: '15%',
325 left: '15%'
326 }
327 });
328 $("#log-panel").html("<pre>" + resp + "</pre>");
329 download_link = ajaxurl + "?action=updraft_smush_ajax&subaction=get_smush_logs&nonce=" + wposmush.smush_ajax_nonce;
330 $("#smush-log-modal a").attr('href', download_link);
331 }, false);
332 });
333
334 /**
335 * Handle delete all backup images button click.
336 */
337 smush_delete_backup_images_btn.on('click', function() {
338
339 if (!confirm(wposmush.delete_image_backup_confirm)) return;
340 smush_delete_backup_images_btn.prop('disabled', true);
341 var spinner = $('#wpo_smush_delete_backup_spinner'),
342 done = $('#wpo_smush_delete_backup_done');
343
344 spinner.show();
345
346 smush_manager_send_command('clean_all_backup_images', {}, function() {
347 spinner.hide();
348 smush_delete_backup_images_btn.prop('disabled', false);
349 done.css('display', 'inline-block').delay(3000).fadeOut();
350 });
351 });
352
353 /**
354 * Saves options
355 */
356 smush_images_save_options_btn.off().on('click', function(e) {
357 save_options();
358 });
359
360 /**
361 * Binds clear stats button
362 */
363 smush_images_stats_clear_btn.off().on('click', function(e) {
364 $('#wpo_smush_images_clear_stats_spinner').show().delay(3000).fadeOut();
365
366 smush_manager_send_command('clear_smush_stats', {}, function(resp) {
367 $('#wpo_smush_images_clear_stats_spinner').hide();
368 $('#wpo_smush_images_clear_stats_done').show().delay(3000).fadeOut();
369 });
370 });
371
372 /**
373 * Binds pending tasks button
374 */
375 smush_images_pending_tasks_btn.off().on('click', function(e) {
376 $('#smush-information-modal .smush-information').text(wposmush.server_check);
377 update_view_modal_message($('#smush-information-modal'), $.unblockUI);
378 data = { 'server': $("input[name='compression_server']:checked").val() };
379 smush_manager_send_command('check_server_status', data, function(resp) {
380 if (resp.online) {
381 update_view_bulk_smush_start();
382 smush_manager_send_command('process_pending_images', {}, function(resp) {
383 handle_response_from_smush_manager(resp, update_view_bulk_smush_progress);
384 });
385 } else {
386 if (resp.error) {
387 error_message = resp.error + '<br>' + wposmush.server_error
388 $('#smush-information-modal .smush-information').html(error_message);
389 } else {
390 $('#smush-information-modal .smush-information').text(wposmush.server_error);
391 }
392 update_view_modal_message($('#smush-information-modal'), $.unblockUI);
393 }
394 });
395
396 });
397
398
399 /**
400 * Binds smush cancel button
401 */
402 $('body').on('click', '#wpo_smush_images_pending_tasks_cancel_button', function(e) {
403
404 if (wpoptimize.cancel === pending_tasks_cancel_btn.val()) {
405 pending_tasks_cancel_btn.val(wpoptimize.cancelling);
406 pending_tasks_cancel_btn.prop('disabled', true);
407 }
408 smush_manager_send_command('clear_pending_images', {}, function(resp) {
409 $.unblockUI();
410 if (resp.status) {
411 get_info_from_smush_manager();
412 reset_view_bulk_smush();
413 } else {
414 console.log('Cancelling pending images apparently failed.', resp);
415 }
416 pending_tasks_cancel_btn.val(wpoptimize.cancel);
417 pending_tasks_cancel_btn.prop('disabled', false);
418 });
419 });
420
421 /**
422 * Single image compression
423 */
424 $('body').on('click', '.wpo_smush_single_image .button', function() {
425
426 image = {
427 'attachment_id':$(this).data('id'),
428 'blog_id': $(this).data('blog')
429 };
430
431 if ($('#enable_custom_compression').is(":checked")) {
432 image_quality = $('#custom_compression_slider').val();
433 } else {
434 // The '60' here has to be kept in sync with WP_Optimize::admin_page_wpo_images_smush()
435 image_quality = $('#enable_lossy_compression').is(":checked") ? 60 : 92;
436 }
437 lossy_compression = image_quality < 92 ? true : false;
438
439 smush_options = {
440 'compression_server': $("input[name='compression_server_" + image.attachment_id + "']:checked").val(),
441 'image_quality': image_quality,
442 'lossy_compression': lossy_compression,
443 'back_up_original': $('#smush_backup_' + image.attachment_id).is(":checked"),
444 'preserve_exif': $('#smush_exif_' + image.attachment_id).is(":checked")
445 }
446
447 data = { 'server': $("input[name='compression_server_" + $(this).attr('id').substring(15) + "']:checked").val() };
448 update_view_modal_message(wposmush.server_check);
449 smush_manager_send_command('check_server_status', data, function(resp) {
450 if (resp.online) {
451 smush_selected_image(image, smush_options);
452 } else {
453 if (resp.error) {
454 error_message = resp.error + '<br>' + wposmush.server_error
455
456 update_view_modal_message(error_message, $.unblockUI);
457 } else {
458 update_view_modal_message(wposmush.server_error, $.unblockUI);
459 }
460 }
461 });
462 });
463
464 /**
465 * Single image restore
466 */
467 $('body').on('click', '.wpo_restore_single_image .button', function() {
468 var clicked_image = $(this);
469 blog_id = clicked_image.data('blog');
470 image_id = clicked_image.data('id');
471
472 if (!image_id || !blog_id) return;
473 restore_selected_image(blog_id, image_id);
474 });
475
476 /**
477 * Mark as compressed
478 */
479 $('body').on('click', '.wpo_smush_mark_single_image .button', function() {
480 var image = {
481 'attachment_id':$(this).data('id'),
482 'blog_id': $(this).data('blog')
483 },
484 wrapper = $(this).closest('#smush-metabox-inside-wrapper');
485
486 update_view_modal_message(wposmush.please_updating_images_info);
487
488 smush_manager_send_command('mark_as_compressed', {selected_images: [ image ]}, function(response) {
489 $('#smush-information-modal .smush-information').text(response.summary);
490 update_view_modal_message($('#smush-information-modal'), $.unblockUI);
491
492 if (response.status) {
493 $('.wpo_smush_single_image', wrapper).hide();
494 $('.wpo-toggle-advanced-options', wrapper).removeClass('opened');
495 $('.wpo_smush_mark_single_image', wrapper).hide();
496 $('.wpo_smush_unmark_single_image', wrapper).show();
497 $('.wpo_restore_single_image', wrapper).show();
498 $('#smush_info', wrapper).text(response.info);
499 }
500 });
501 });
502
503 /**
504 * Unmark as uncompressed
505 */
506 $('body').on('click', '.wpo_smush_unmark_single_image .button', function() {
507 var image = {
508 'attachment_id':$(this).data('id'),
509 'blog_id': $(this).data('blog')
510 },
511 wrapper = $(this).closest('#smush-metabox-inside-wrapper');
512
513 update_view_modal_message(wposmush.please_updating_images_info);
514
515 smush_manager_send_command('mark_as_compressed', {selected_images: [ image ], unmark: true}, function(response) {
516 $('#smush-information-modal .smush-information').text(response.summary);
517 update_view_modal_message($('#smush-information-modal'), $.unblockUI);
518
519 if (response.status) {
520 $('.wpo_smush_single_image', wrapper).show();
521 $('.wpo_smush_mark_single_image', wrapper).show();
522 $('.wpo_smush_unmark_single_image', wrapper).hide();
523 $('.wpo_restore_single_image', wrapper).hide();
524 $('#smush_info', wrapper).text('');
525 }
526 });
527 });
528
529 $('body').on('click', '#wpo_smush_details .wpo-collapsible', toggle_smush_details);
530 $('body').on('click', '.column-wpo_smush .wpo-collapsible', toggle_smush_details);
531
532 function toggle_smush_details() {
533 $(this).toggleClass('opened');
534 if ($(this).hasClass('opened')) {
535 $(this).text(wposmush.less);
536 } else {
537 $(this).text(wposmush.more);
538 }
539 }
540
541 $('body').on('click', '#smush-log-modal .close, #smush-information-modal .information-modal-close', function() {
542 $.unblockUI();
543 });
544
545 $('body').on('click', '.wpo_smush_stats_cta_btn, .wpo_smush_get_logs, #smush-complete-summary .close', function() {
546 $.unblockUI();
547 get_info_from_smush_manager();
548 setTimeout(reset_view_bulk_smush, 500);
549 });
550
551 $('body').on('click', '.wpo-toggle-advanced-options', function(e) {
552 e.preventDefault();
553 $(this).toggleClass('opened');
554 });
555
556 $('.wpo-fieldgroup .autosmush input, .wpo-fieldgroup .compression_level, .wpo-fieldgroup .image_options, #smush-show-metabox, #enable_webp_conversion').on('change', function(e) {
557 save_options();
558 });
559
560 $('body').on('change', '.smush-options.compression_level', function() {
561 if ($('#enable_custom_compression').is(':checked')) {
562 $('.smush-options.custom_compression').show();
563 } else {
564 $('.smush-options.custom_compression').hide();
565 }
566 });
567
568 $('body').on('change', '.smush-advanced input[type="radio"]', function() {
569 update_view_available_options();
570 });
571
572 convert_to_webp_btn.on('click', function(e){
573 e.preventDefault();
574 var $link = $(this);
575 data = {
576 'attachment_id': $(this).data('attachment-id')
577 };
578 update_view_modal_message(wposmush.converting_to_webp);
579 smush_manager_send_command('convert_to_webp_format', data, function(response) {
580 if (response.error) {
581 update_view_modal_message(response.error, $.unblockUI);
582 setTimeout(function() {
583 $.unblockUI();
584 }, 2000);
585 } else {
586 update_view_modal_message(response.success, $.unblockUI);
587 setTimeout(function() {
588 $.unblockUI();
589 }, 2000);
590 $link.next().remove();
591 $link.remove();
592 }
593 });
594 });
595
596 /**
597 * Load and show information about uncompressed images.
598 *
599 * @param {Boolean} use_cache Use the request cache
600 *
601 * @return void
602 */
603 function get_info_from_smush_manager(use_cache) {
604
605 var use_cache = (typeof use_cache === 'undefined') ? true : use_cache;
606 var data = { 'use_cache': use_cache };
607
608 smush_images_optimization_message.html('...');
609 smush_images_pending_tasks_container.hide();
610
611 disable_image_optimization_controls(true);
612
613 smush_manager_send_command('get_ui_update', data, function(resp) {
614 handle_response_from_smush_manager(resp, update_view_show_uncompressed_images);
615 update_view_available_options();
616 disable_image_optimization_controls(false);
617 update_smush_action_buttons_state();
618 });
619 }
620
621
622 /**
623 * Get selected images and make an ajax request to compress them.
624 *
625 * @return void
626 */
627 function bulk_smush_selected_images() {
628
629 $('#wpo_smush_images_grid input:checked').each(function() {
630 image = {
631 'attachment_id':$(this).val(),
632 'blog_id': $(this).data('blog')
633 };
634 smush_image_list.push(image);
635 });
636
637 data = {
638 optimization_id: 'smush',
639 selected_images: smush_image_list,
640 smush_options: {
641 'compression_server': $("input[name='compression_server']:checked").val(),
642 'image_quality': $('#image_quality').val(),
643 'lossy_compression': $('#smush-lossy-compression').is(":checked"),
644 'back_up_original': $('#smush-backup-original').is(":checked"),
645 'preserve_exif': $('#smush-preserve-exif').is(":checked")
646 }
647 }
648
649 update_view_bulk_smush_start();
650 smush_manager_send_command('process_bulk_smush', data);
651 }
652
653 /**
654 * Save options in the DB
655 *
656 * @return void
657 */
658 function save_options() {
659 // only save when changing the options on the wpo dashboard.
660 if (!$('#wp-optimize-wrap').length) return;
661
662 $('#wpo_smush_images_save_options_spinner').show().delay(3000).fadeOut();
663
664 var smush_options = get_smush_options();
665
666 smush_manager_send_command('update_smush_options', smush_options, function(resp) {
667 $('#wpo_smush_images_save_options_spinner').hide();
668 if (resp.hasOwnProperty('saved') && resp.saved) {
669 $('#wpo_smush_images_save_options_done').show().delay(3000).fadeOut();
670 smush_images_save_options_btn.hide();
671 } else {
672 $('#wpo_smush_images_save_options_fail').show().delay(3000).fadeOut();
673 smush_images_save_options_btn.show();
674 }
675 });
676 }
677
678 /**
679 * A timer to run for the duration of the bulk smush operation.
680 *
681 * @return void
682 */
683 function smush_timer() {
684 smush_timer_locked = true;
685 smush_total_seconds++;
686 seconds = (smush_total_seconds % 60) + '' < 10 ? '0' + (smush_total_seconds % 60) : (smush_total_seconds % 60);
687 minutes = parseInt(smush_total_seconds / 60) + '' < 10 ? '0' + parseInt(smush_total_seconds / 60) : parseInt(smush_total_seconds / 60);
688
689 $('#smush_stats_timer').text(minutes + ":" + seconds);
690 trigger_events(smush_total_seconds);
691 }
692
693 /**
694 * A timer to run for the duration of the bulk smush operation.
695 *
696 * @param {Number} time_elapsed - time in seconds
697 *
698 * @return void
699 */
700 function trigger_events(time_elapsed) {
701
702 if (0 == time_elapsed % 3) {
703 update_smush_stats();
704 }
705
706 if (0 == time_elapsed % 60) {
707 smush_manager_send_command('process_pending_images', {}, function(resp) {
708 handle_response_from_smush_manager(resp, update_view_bulk_smush_progress);
709 });
710 }
711 }
712
713 /**
714 * Updates the UI with stats
715 *
716 * @param {Boolean} use_cache Use the request cache
717 *
718 * @return void
719 */
720 function update_smush_stats(use_cache) {
721
722 var use_cache = (typeof use_cache === 'undefined') ? true : use_cache;
723
724 data = {
725 update_ui: true,
726 use_cache: false
727 }
728
729 smush_manager_send_command('get_ui_update', data, function(resp) {
730 handle_response_from_smush_manager(resp, update_view_bulk_smush_progress);
731 });
732 }
733
734 /**
735 * Update images optimization tab view with data returned from images optimization.
736 *
737 * @param {Object} data - meta data returned from task manager
738 *
739 * @return void
740 */
741 function update_view_show_uncompressed_images(data) {
742 smush_images_grid.html('');
743
744 if (!data || !data.hasOwnProperty('unsmushed_images')) return;
745
746 var unsmushed_images = data.unsmushed_images,
747 pending_tasks = data.pending_tasks,
748 blog_id = 0;
749
750 if (0 == unsmushed_images.length && 0 == pending_tasks) {
751 smush_images_grid.text(wposmush.all_images_compressed).wrapInner("<div class='wpo-fieldgroup'> </div>");
752 }
753
754 if (0 != pending_tasks) {
755 smush_images_pending_tasks_container.show().find('.red').text(data.pending);
756 }
757
758 if (1 === data.is_multisite) {
759 blog_id = uncompressed_images_sites_select.find(":selected").val();
760 add_unsmushed_images_to_grid(blog_id, data);
761 } else {
762 for (blog_id in data.unsmushed_images) {
763 add_unsmushed_images_to_grid(blog_id, data);
764 }
765 }
766 }
767
768 function sort_unsmushed_images(a, b) {
769 return a.id - b.id;
770 }
771
772 function add_unsmushed_images_to_grid(blog_id, data) {
773 // Used to have upload.php?item= on multisite (using data.is_multisite), and no suffix
774 var admin_url_pre_id = 'post.php?post=',
775 admin_url_post_id = '&action=edit',
776 admin_url = data.admin_urls[blog_id],
777 unsmushed_images = data.unsmushed_images[blog_id];
778
779 if ('undefined' !== typeof unsmushed_images) {
780 unsmushed_images.sort(sort_unsmushed_images);
781 }
782
783 for (i in unsmushed_images) {
784 if (!unsmushed_images.hasOwnProperty(i)) continue;
785 var image = unsmushed_images[i];
786 add_image_to_grid(image, blog_id, admin_url + admin_url_pre_id + image.id + admin_url_post_id);
787 }
788 }
789
790 uncompressed_images_sites_select.on('change', function() {
791 get_info_from_smush_manager();
792 });
793
794 /**
795 * Updates the view when bulk smush starts
796 *
797 * @return void
798 */
799 function update_view_bulk_smush_start() {
800 if (smush_timer_locked) return;
801 update_view_modal_message($('#wpo_smush_images_information_container'));
802
803 service = $('.compression_server input[type="radio"]:checked + label small').text();
804 $('#wpo_smush_images_information_server').html(service);
805
806 // Clear stats
807 $('#smush_stats_pending_images').html("...");
808 $('#smush_stats_completed_images').html("...");
809 $('#smush_stats_bytes_saved').html("...");
810 $('#smush_stats_percent_saved').html("...");
811 $('#smush_stats_timer').html("...");
812
813 smush_timer_handle = window.setInterval(smush_timer, 1000);
814 disable_image_optimization_controls(true);
815 }
816
817 /**
818 * Updates the view with progress related stats
819 *
820 * @param {Object} resp - response from smush manager.
821 *
822 * @return void
823 */
824 function update_view_bulk_smush_progress(resp) {
825
826 // Update stats
827 $('#smush_stats_pending_images').html(resp.pending_tasks);
828 $('#smush_stats_completed_images').html(resp.completed_task_count);
829 $('#smush_stats_bytes_saved').html(resp.bytes_saved);
830 $('#smush_stats_percent_saved').html(resp.percent_saved);
831
832 // Show summary and close the modal
833 if (true == resp.smush_complete) {
834 // Force a delay here to avoid stale data
835 setTimeout(update_view_bulk_smush_complete, 1500);
836 }
837 }
838
839 /**
840 * Updates the view when bulk smush completes
841 *
842 * @return void
843 */
844 function update_view_bulk_smush_complete() {
845
846 data = {
847 update_ui: true,
848 use_cache: false,
849 image_list: smush_image_list
850 }
851
852 smush_manager_send_command('get_ui_update', data, function(resp) {
853
854 summary = resp.session_stats;
855
856 if (0 != resp.completed_task_count) {
857 summary += '<hr>' + resp.summary;
858 }
859
860 show_smush_summary(summary);
861 });
862 }
863
864 /**
865 * Displays a modal with compression data
866 *
867 * @param {string} summary - stats and info
868 *
869 * @return void
870 */
871 function show_smush_summary(summary) {
872
873 if (smush_completed) return;
874
875 $('#summary-message').html(summary);
876 reset_view_bulk_smush();
877 update_view_modal_message($('#smush-complete-summary'));
878 smush_completed = true;
879 }
880
881 /**
882 * Updates the view when bulk smush completes
883 *
884 * @return void
885 */
886 function reset_view_bulk_smush() {
887 // Reset timer and locks
888 smush_total_seconds = 0;
889 smush_timer_locked = false;
890 smush_completed = false;
891 smush_image_list = [];
892 window.clearInterval(smush_timer_handle);
893 disable_image_optimization_controls(false);
894 }
895
896 /**
897 * Append the image to the grid
898 *
899 * @param {Object} image - image data returned from smush manager
900 * @param {int} blog_id - The blog id the image
901 * @param {String} admin_url - The URL to link to for viewing the image
902 *
903 * @return void
904 */
905 function add_image_to_grid(image, blog_id, admin_url) {
906
907 var dom_id = ['wpo_smush_', blog_id, '_', image.id].join('');
908
909 image_html = '<div class="wpo_smush_image" data-filesize="'+image.filesize+'">';
910 image_html += '<a class="button" href="'+admin_url+'" target="_blank"> ' + wposmush.view_image + ' </a>';
911 image_html += '<input id="' + dom_id + '" type="checkbox" data-blog="'+blog_id+ '" class="wpo_smush_image__input" value="'+image.id+'">';
912 image_html += '<label for="' + dom_id + '"></a>';
913 image_html += '<div class="thumbnail">';
914 image_html += '<img class="lazyload" src="'+image.thumb_url+'">';
915 image_html += '</div></label></div>';
916
917 smush_images_grid.append(image_html);
918 }
919
920 /**
921 * Updates UI based on service provider selected
922 *
923 * @param {Object} features - image data returned from smush manager
924 *
925 * @return void
926 */
927 function update_view_available_options() {
928 features = wposmush.features;
929 service = $("input[name^='compression_server']:checked").val();
930
931 for (feature in features[service]) {
932 $('.' + feature).prop('disabled', !features[service][feature]);
933 }
934
935 $('.wpo_smush_image').each(function() {
936 if ($(this).data('filesize') > wposmush.features[service]["max_filesize"]) {
937 $(this).hide();
938 } else {
939 $(this).show();
940 }
941 })
942 }
943
944 /**
945 * Disable smush controls (buttons, checkboxes) in bulk mode
946 *
947 * @param {boolean} disable - if true then disable controls, false - enable.
948 *
949 * @return void
950 */
951 function disable_image_optimization_controls(disable) {
952 $.each([
953 smush_selected_images_btn,
954 smush_images_select_all_btn,
955 smush_images_select_none_btn,
956 smush_images_save_options_btn,
957 smush_images_refresh_btn,
958 smush_images_pending_tasks_btn,
959 smush_mark_as_compressed_btn,
960 ], function(i, el) {
961 el.prop('disabled', disable);
962 });
963
964 if (disable) {
965 $('#wpo_smush_images_refresh').hide();
966 $('.wpo_smush_images_loader').show();
967 } else {
968 $('#wpo_smush_images_refresh').show();
969 $('.wpo_smush_images_loader').hide();
970 }
971 }
972
973 /**
974 * Gets selected image and make an ajax request to compress it.
975 *
976 * @param {Object} selected_image - { attachment_id: ..., blog_id: ... }
977 * @param {Array} smush_options - The options to use
978 *
979 * @return void
980 */
981 function smush_selected_image(selected_image, smush_options) {
982
983 // if no selected images then exit.
984 if (0 == selected_image.length) return;
985
986 data = {
987 selected_image: selected_image,
988 smush_options: smush_options
989 }
990
991 update_view_modal_message(wposmush.compress_single_image_dialog);
992 smush_manager_send_command('compress_single_image', data, function(resp) {
993 handle_response_from_smush_manager(resp, update_view_single_image_complete);
994 });
995 }
996
997 /**
998 * Get selected image and make an ajax request to compress it.
999 *
1000 * @param {Number} blog_id - The blog id
1001 * @param {Number} selected_image - The image id
1002 *
1003 * @return void
1004 */
1005 function restore_selected_image(blog_id, selected_image) {
1006
1007 // if no selected images then exit.
1008 if (0 == selected_image.length) return;
1009
1010 update_view_modal_message(wposmush.please_wait, $.unblockUI);
1011 var data = { 'blog_id': blog_id, 'selected_image': selected_image };
1012 smush_manager_send_command('restore_single_image', data, function(resp) {
1013 handle_response_from_smush_manager(resp, update_view_single_image_complete);
1014 });
1015 }
1016
1017 /**
1018 * Updates the view once a single image is compressed or restored.
1019 *
1020 * @param {Object} resp - response from smush manager.
1021 *
1022 * @return void
1023 */
1024 function update_view_single_image_complete(resp) {
1025
1026 if (resp.hasOwnProperty('success') && resp.success) {
1027 $(".smush-information").text(resp.summary);
1028 update_view_modal_message($("#smush-information-modal"), $.unblockUI);
1029
1030 $('.wpo-toggle-advanced-options.wpo_smush_single_image').removeClass('opened');
1031
1032 update_view_singe_image_compress(resp.operation, resp.summary, resp.restore_possible, resp);
1033
1034 // here we store data from the the response
1035 // this information will be used to show correct UI elements
1036 // when smush metabox will shown again without reloading main page
1037 var blog_id = resp.blog_id || resp.options.blog_id,
1038 image_id = resp.image || resp.options.attachment_id;
1039
1040 if (!smush_affected_images.hasOwnProperty(blog_id)) smush_affected_images[blog_id] = {};
1041 if (!smush_affected_images[blog_id].hasOwnProperty(image_id)) smush_affected_images[blog_id][image_id] = {};
1042
1043 if ('compress' == resp.operation) {
1044 smush_affected_images[blog_id][image_id] = {
1045 operation: resp.operation,
1046 summary: resp.summary,
1047 restore_possible: resp.restore_possible
1048 }
1049 } else {
1050 smush_affected_images[blog_id][image_id] = {
1051 operation: resp.operation
1052 }
1053 }
1054 } else {
1055 $(".smush-information").text(resp.error_message);
1056 update_view_modal_message($("#smush-information-modal"), $.unblockUI);
1057 }
1058 }
1059
1060 /**
1061 * Update metabox view depending on a command response.
1062 *
1063 * @param {string} operation
1064 * @param {string} summary
1065 * @param {boolean} restore_possible
1066 * @param {object} smush_image_data
1067 */
1068 function update_view_singe_image_compress(operation, summary, restore_possible, smush_image_data) {
1069 var wrapper = $("#smush_info").closest('#smush-metabox-inside-wrapper');
1070
1071 if ('compress' == operation) {
1072 $(".wpo_smush_single_image").hide();
1073 $(".wpo_restore_single_image").show();
1074
1075 if (smush_image_data && smush_image_data.hasOwnProperty('sizes-info')) {
1076 $("#smush_info").text(summary);
1077 $("#wpo_smush_details").html(smush_image_data['sizes-info']);
1078 } else {
1079 $("#smush_info").text(summary);
1080 $("#wpo_smush_details").text('').hide();
1081 }
1082
1083 $('.wpo_smush_mark_single_image').hide();
1084
1085 if (restore_possible) {
1086 $(".restore_possible").show();
1087 } else {
1088 $(".restore_possible").hide();
1089 }
1090 } else {
1091 $(".wpo_smush_single_image").show();
1092 $(".wpo_restore_single_image").hide();
1093
1094 $('.wpo_smush_mark_single_image').show();
1095 $('.wpo_smush_unmark_single_image', wrapper).hide();
1096 }
1097 }
1098
1099 /**
1100 * Handle smush metabox load event. This handler is used to restore correct smush metabox view.
1101 */
1102 $(document).on('admin-metabox-smush-loaded', function() {
1103 var image_data = $('.wpo_restore_single_image input[type="button"]').first().data();
1104
1105 if (!image_data) return;
1106
1107 if (smush_affected_images.hasOwnProperty(image_data.blog) && smush_affected_images[image_data.blog].hasOwnProperty(image_data.id)) {
1108 var smush_image_data = smush_affected_images[image_data.blog][image_data.id];
1109
1110 if ('compress' == smush_image_data.operation) {
1111 update_view_singe_image_compress(smush_image_data.operation, smush_image_data.summary, smush_image_data.restore_possible, smush_image_data);
1112 } else {
1113 update_view_singe_image_compress(smush_image_data.operation);
1114 }
1115 }
1116 });
1117
1118 /**
1119 * Display a modal message
1120 *
1121 * @param {string} message The message or element to display
1122 * @param {Function} callback Called when the overlay is clicked
1123 *
1124 * @return void
1125 */
1126 function update_view_modal_message(message, callback) {
1127
1128 $.blockUI({
1129 message: message,
1130 onOverlayClick: callback,
1131 baseZ: 160001,
1132 css: {
1133 width: '400px',
1134 padding: '20px',
1135 cursor: 'pointer'
1136 }
1137 });
1138 }
1139
1140 /**
1141 * Check returned response from the smush manager and call update view callback.
1142 *
1143 * @param {Object} resp - response from smush manager.
1144 * @param {Function} update_view_callback - callback function to update view.
1145 *
1146 * @return void
1147 */
1148 function handle_response_from_smush_manager(resp, update_view_callback) {
1149 if (resp && resp.hasOwnProperty('status') && resp.status) {
1150 if (update_view_callback) update_view_callback(resp);
1151 } else {
1152 alert(wposmush.error_unexpected_response);
1153 console.log(resp);
1154 }
1155 }
1156
1157 /**
1158 * Send an action to the task manager via admin-ajax.php.
1159 *
1160 * @param {string} action The action to send
1161 * @param {[type]} data Data to send
1162 * @param {Function} callback Will be called with the results
1163 * @param {boolean} json_parse JSON parse the results
1164 *
1165 * @return {JSON}
1166 */
1167 function smush_manager_send_command(action, data, callback, json_parse) {
1168
1169 json_parse = ('undefined' === typeof json_parse) ? true : json_parse;
1170 data = $.isEmptyObject(data) ? {'use_cache' : false} : data;
1171
1172 var ajax_data = {
1173 action: 'updraft_smush_ajax',
1174 subaction: action,
1175 nonce: wposmush.smush_ajax_nonce,
1176 data: data
1177 };
1178
1179 var ajax_opts = {
1180 type: 'POST',
1181 url: ajaxurl,
1182 data: ajax_data,
1183 success: function(response) {
1184
1185 if (json_parse) {
1186 try {
1187 var resp = wpo_parse_json(response);
1188 } catch (e) {
1189 console.log("smush_manager_send_command JSON parse error");
1190 console.log(e);
1191 console.log(response);
1192 alert(wposmush.error_unexpected_response);
1193 }
1194 if ('undefined' !== typeof callback) callback(resp);
1195 } else {
1196 if ('undefined' !== typeof callback) callback(response);
1197 }
1198 },
1199 error: function(response, status, error_code) {
1200 console.log("smush_manager_send_command AJAX parse error: "+status+" ("+error_code+")");
1201 if ('undefined' !== typeof callback) {
1202 callback(response);
1203 } else {
1204 console.log(response);
1205 alert(wposmush.error_unexpected_response);
1206 }
1207 },
1208 dataType: 'text'
1209
1210 }
1211
1212 $.ajax(ajax_opts);
1213
1214 };
1215
1216 // Gather smush options
1217 var get_smush_options = function() {
1218 var image_quality = '';
1219 if ($('#enable_custom_compression').is(":checked")) {
1220 image_quality = $('#custom_compression_slider').val();
1221 } else {
1222 // The '90' here has to be kept in sync with WP_Optimize::admin_page_wpo_images_smush()
1223 image_quality = $('#enable_lossy_compression').is(":checked") ? 60 : 92;
1224 }
1225 var lossy_compression = image_quality < 92 ? true : false;
1226
1227 return {
1228 'compression_server': $("input[name='compression_server']:checked").val(),
1229 'image_quality': image_quality,
1230 'lossy_compression': lossy_compression,
1231 'back_up_original': $('#smush-backup-original').is(":checked"),
1232 'back_up_delete_after': $('#smush-backup-delete').is(":checked"),
1233 'back_up_delete_after_days': $('#smush-backup-delete-days').val(),
1234 'preserve_exif': $('#smush-preserve-exif').is(":checked"),
1235 'autosmush': $('#smush-automatically').is(":checked"),
1236 'show_smush_metabox': $('#smush-show-metabox').is(":checked"),
1237 'webp_conversion': $('#enable_webp_conversion').is(":checked")
1238 };
1239 }
1240 wp_optimize.smush_settings = get_smush_options;
1241 } // END WP_Optimize_Smush
1242
1243 /**
1244 * Parse JSON string, including automatically detecting unwanted extra input and skipping it
1245 *
1246 * @param {string|object} json_mix_str - JSON string which need to parse and convert to object
1247 *
1248 * @throws SyntaxError|String (including passing on what JSON.parse may throw) if a parsing error occurs.
1249 *
1250 * @return mixed parsed JSON object. Will only return if parsing is successful (otherwise, will throw)
1251 */
1252 function wpo_parse_json(json_mix_str) {
1253 // When using wp_send_json to return the value, the format is already parsed.
1254 if ('object' === typeof json_mix_str) return json_mix_str;
1255
1256 // Just try it - i.e. the 'default' case where things work (which can include extra whitespace/line-feeds, and simple strings, etc.).
1257 try {
1258 var result = JSON.parse(json_mix_str);
1259 return result;
1260 } catch (e) {
1261 console.log("WPO: Exception when trying to parse JSON (1) - will attempt to fix/re-parse");
1262 console.log(json_mix_str);
1263 }
1264
1265 var json_start_pos = json_mix_str.indexOf('{');
1266 var json_last_pos = json_mix_str.lastIndexOf('}');
1267
1268 // Case where some php notice may be added after or before json string
1269 if (json_start_pos > -1 && json_last_pos > -1) {
1270 var json_str = json_mix_str.slice(json_start_pos, json_last_pos + 1);
1271 try {
1272 var parsed = JSON.parse(json_str);
1273 return parsed;
1274 } catch (e) {
1275 console.log("WPO: Exception when trying to parse JSON (2) - will attempt to fix/re-parse based upon bracket counting");
1276
1277 var cursor = json_start_pos;
1278 var open_count = 0;
1279 var last_character = '';
1280 var inside_string = false;
1281
1282 // Don't mistake this for a real JSON parser. Its aim is to improve the odds in real-world cases seen, not to arrive at universal perfection.
1283 while ((open_count > 0 || cursor == json_start_pos) && cursor <= json_last_pos) {
1284
1285 var current_character = json_mix_str.charAt(cursor);
1286
1287 if (!inside_string && '{' == current_character) {
1288 open_count++;
1289 } else if (!inside_string && '}' == current_character) {
1290 open_count--;
1291 } else if ('"' == current_character && '\\' != last_character) {
1292 inside_string = inside_string ? false : true;
1293 }
1294
1295 last_character = current_character;
1296 cursor++;
1297 }
1298
1299 console.log("Started at cursor="+json_start_pos+", ended at cursor="+cursor+" with result following:");
1300 console.log(json_mix_str.substring(json_start_pos, cursor));
1301
1302 try {
1303 var parsed = JSON.parse(json_mix_str.substring(json_start_pos, cursor));
1304 // console.log('WPO: JSON re-parse successful');
1305 return parsed;
1306 } catch (e) {
1307 // Throw it again, so that our function works just like JSON.parse() in its behaviour.
1308 throw e;
1309 }
1310
1311 }
1312 }
1313
1314 throw "WPO: could not parse the JSON";
1315
1316 }
1317