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

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