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

1,270 lines 38.8 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 var smush_options = get_smush_options();
639
640 smush_manager_send_command('update_smush_options', smush_options, function(resp) {
641 $('#wpo_smush_images_save_options_spinner').hide();
642 if (resp.hasOwnProperty('saved') && resp.saved) {
643 $('#wpo_smush_images_save_options_done').show().delay(3000).fadeOut();
644 smush_images_save_options_btn.hide();
645 } else {
646 $('#wpo_smush_images_save_options_fail').show().delay(3000).fadeOut();
647 smush_images_save_options_btn.show();
648 }
649 });
650 }
651
652 /**
653 * A timer to run for the duration of the bulk smush operation.
654 *
655 * @return void
656 */
657 function smush_timer() {
658 smush_timer_locked = true;
659 smush_total_seconds++;
660 seconds = (smush_total_seconds % 60) + '' < 10 ? '0' + (smush_total_seconds % 60) : (smush_total_seconds % 60);
661 minutes = parseInt(smush_total_seconds / 60) + '' < 10 ? '0' + parseInt(smush_total_seconds / 60) : parseInt(smush_total_seconds / 60);
662
663 $('#smush_stats_timer').text(minutes + ":" + seconds);
664 trigger_events(smush_total_seconds);
665 }
666
667 /**
668 * A timer to run for the duration of the bulk smush operation.
669 *
670 * @param {Number} time_elapsed - time in seconds
671 *
672 * @return void
673 */
674 function trigger_events(time_elapsed) {
675
676 if (0 == time_elapsed % 3) {
677 update_smush_stats();
678 }
679
680 if (0 == time_elapsed % 60) {
681 smush_manager_send_command('process_pending_images', {}, function(resp) {
682 handle_response_from_smush_manager(resp, update_view_bulk_smush_progress);
683 });
684 }
685 }
686
687 /**
688 * Updates the UI with stats
689 *
690 * @param {Boolean} use_cache Use the request cache
691 *
692 * @return void
693 */
694 function update_smush_stats(use_cache) {
695
696 var use_cache = (typeof use_cache === 'undefined') ? true : use_cache;
697
698 data = {
699 update_ui: true,
700 use_cache: false
701 }
702
703 smush_manager_send_command('get_ui_update', data, function(resp) {
704 handle_response_from_smush_manager(resp, update_view_bulk_smush_progress);
705 });
706 }
707
708 /**
709 * Update images optimization tab view with data returned from images optimization.
710 *
711 * @param {Object} data - meta data returned from task manager
712 *
713 * @return void
714 */
715 function update_view_show_uncompressed_images(data) {
716 smush_images_grid.html('');
717
718 if (!data || !data.hasOwnProperty('unsmushed_images')) return;
719
720 var unsmushed_images = data.unsmushed_images;
721 var pending_tasks = data.pending_tasks;
722
723 if (0 == data.unsmushed_images.length && 0 == data.pending_tasks) {
724 smush_images_grid.text(wposmush.all_images_compressed).wrapInner("<div class='wpo-fieldgroup'> </div>");
725 }
726
727 if (0 != data.pending_tasks) {
728 smush_images_pending_tasks_container.show().find('.red').text(data.pending);
729 }
730
731 // Used to have upload.php?item= on multisite (using data.is_multisite), and no suffix
732 var admin_url_pre_id = 'post.php?post=';
733 var admin_url_post_id = '&action=edit';
734
735 for (blog_id in data.unsmushed_images) {
736 data.unsmushed_images[blog_id].sort(function(a, b) {
737 return a.id - b.id;
738 });
739 for (i in data.unsmushed_images[blog_id]) {
740 if (!data.unsmushed_images[blog_id].hasOwnProperty(i)) continue;
741 image = data.unsmushed_images[blog_id][i];
742 add_image_to_grid(image, blog_id, data.admin_urls[blog_id] + admin_url_pre_id + image.id + admin_url_post_id);
743 }
744 }
745 }
746
747 /**
748 * Updates the view when bulk smush starts
749 *
750 * @return void
751 */
752 function update_view_bulk_smush_start() {
753 if (smush_timer_locked) return;
754 update_view_modal_message($('#wpo_smush_images_information_container'));
755
756 service = $('.compression_server input[type="radio"]:checked + label small').text();
757 $('#wpo_smush_images_information_server').html(service);
758
759 // Clear stats
760 $('#smush_stats_pending_images').html("...");
761 $('#smush_stats_completed_images').html("...");
762 $('#smush_stats_bytes_saved').html("...");
763 $('#smush_stats_percent_saved').html("...");
764 $('#smush_stats_timer').html("...");
765
766 smush_timer_handle = window.setInterval(smush_timer, 1000);
767 disable_image_optimization_controls(true);
768 }
769
770 /**
771 * Updates the view with progress related stats
772 *
773 * @param {Object} resp - response from smush manager.
774 *
775 * @return void
776 */
777 function update_view_bulk_smush_progress(resp) {
778
779 // Update stats
780 $('#smush_stats_pending_images').html(resp.pending_tasks);
781 $('#smush_stats_completed_images').html(resp.completed_task_count);
782 $('#smush_stats_bytes_saved').html(resp.bytes_saved);
783 $('#smush_stats_percent_saved').html(resp.percent_saved);
784
785 // Show summary and close the modal
786 if (true == resp.smush_complete) {
787 // Force a delay here to avoid stale data
788 setTimeout(update_view_bulk_smush_complete, 1500);
789 }
790 }
791
792 /**
793 * Updates the view when bulk smush completes
794 *
795 * @return void
796 */
797 function update_view_bulk_smush_complete() {
798
799 data = {
800 update_ui: true,
801 use_cache: false,
802 image_list: smush_image_list
803 }
804
805 smush_manager_send_command('get_ui_update', data, function(resp) {
806
807 summary = resp.session_stats;
808
809 if (0 != resp.completed_task_count) {
810 summary += '<hr>' + resp.summary;
811 }
812
813 show_smush_summary(summary);
814 });
815 }
816
817 /**
818 * Displays a modal with compression data
819 *
820 * @param {string} summary - stats and info
821 *
822 * @return void
823 */
824 function show_smush_summary(summary) {
825
826 if (smush_completed) return;
827
828 $('#summary-message').html(summary);
829 reset_view_bulk_smush();
830 update_view_modal_message($('#smush-complete-summary'));
831 smush_completed = true;
832 }
833
834 /**
835 * Updates the view when bulk smush completes
836 *
837 * @return void
838 */
839 function reset_view_bulk_smush() {
840 // Reset timer and locks
841 smush_total_seconds = 0;
842 smush_timer_locked = false;
843 smush_completed = false;
844 smush_image_list = [];
845 window.clearInterval(smush_timer_handle);
846 disable_image_optimization_controls(false);
847 }
848
849 /**
850 * Append the image to the grid
851 *
852 * @param {Object} image - image data returned from smush manager
853 * @param {int} blog_id - The blog id the image
854 * @param {String} admin_url - The URL to link to for viewing the image
855 *
856 * @return void
857 */
858 function add_image_to_grid(image, blog_id, admin_url) {
859
860 var dom_id = ['wpo_smush_', blog_id, '_', image.id].join('');
861
862 image_html = '<div class="wpo_smush_image" data-filesize="'+image.filesize+'">';
863 image_html += '<a class="button" href="'+admin_url+'" target="_blank"> ' + wposmush.view_image + ' </a>';
864 image_html += '<input id="' + dom_id + '" type="checkbox" data-blog="'+blog_id+ '" class="wpo_smush_image__input" value="'+image.id+'">';
865 image_html += '<label for="' + dom_id + '"></a>';
866 image_html += '<div class="thumbnail">';
867 image_html += '<img class="lazyload" src="'+image.thumb_url+'">';
868 image_html += '</div></label></div>';
869
870 smush_images_grid.append(image_html);
871 }
872
873 /**
874 * Updates UI based on service provider selected
875 *
876 * @param {Object} features - image data returned from smush manager
877 *
878 * @return void
879 */
880 function update_view_available_options() {
881 features = wposmush.features;
882 service = $("input[name^='compression_server']:checked").val();
883
884 for (feature in features[service]) {
885 $('.' + feature).prop('disabled', !features[service][feature]);
886 }
887
888 $('.wpo_smush_image').each(function() {
889 if ($(this).data('filesize') > wposmush.features[service]["max_filesize"]) {
890 $(this).hide();
891 } else {
892 $(this).show();
893 }
894 })
895 }
896
897 /**
898 * Disable smush controls (buttons, checkboxes) in bulk mode
899 *
900 * @param {boolean} disable - if true then disable controls, false - enable.
901 *
902 * @return void
903 */
904 function disable_image_optimization_controls(disable) {
905 $.each([
906 smush_selected_images_btn,
907 smush_images_select_all_btn,
908 smush_images_select_none_btn,
909 smush_images_save_options_btn,
910 smush_images_refresh_btn,
911 smush_images_pending_tasks_btn,
912 smush_mark_as_compressed_btn,
913 ], function(i, el) {
914 el.prop('disabled', disable);
915 });
916
917 if (disable) {
918 $('#wpo_smush_images_refresh').hide();
919 $('.wpo_smush_images_loader').show();
920 } else {
921 $('#wpo_smush_images_refresh').show();
922 $('.wpo_smush_images_loader').hide();
923 }
924 }
925
926 /**
927 * Gets selected image and make an ajax request to compress it.
928 *
929 * @param {Object} selected_image - { attachment_id: ..., blog_id: ... }
930 * @param {Array} smush_options - The options to use
931 *
932 * @return void
933 */
934 function smush_selected_image(selected_image, smush_options) {
935
936 // if no selected images then exit.
937 if (0 == selected_image.length) return;
938
939 data = {
940 selected_image: selected_image,
941 smush_options: smush_options
942 }
943
944 update_view_modal_message(wposmush.compress_single_image_dialog);
945 smush_manager_send_command('compress_single_image', data, function(resp) {
946 handle_response_from_smush_manager(resp, update_view_single_image_complete);
947 });
948 }
949
950 /**
951 * Get selected image and make an ajax request to compress it.
952 *
953 * @param {Number} blog_id - The blog id
954 * @param {Number} selected_image - The image id
955 *
956 * @return void
957 */
958 function restore_selected_image(blog_id, selected_image) {
959
960 // if no selected images then exit.
961 if (0 == selected_image.length) return;
962
963 update_view_modal_message(wposmush.please_wait, $.unblockUI);
964 var data = { 'blog_id': blog_id, 'selected_image': selected_image };
965 smush_manager_send_command('restore_single_image', data, function(resp) {
966 handle_response_from_smush_manager(resp, update_view_single_image_complete);
967 });
968 }
969
970 /**
971 * Updates the view once a single image is compressed or restored.
972 *
973 * @param {Object} resp - response from smush manager.
974 *
975 * @return void
976 */
977 function update_view_single_image_complete(resp) {
978
979 if (resp.hasOwnProperty('success') && resp.success) {
980 $(".smush-information").text(resp.summary);
981 update_view_modal_message($("#smush-information-modal"), $.unblockUI);
982
983 $('.wpo-toggle-advanced-options.wpo_smush_single_image').removeClass('opened');
984
985 update_view_singe_image_compress(resp.operation, resp.summary, resp.restore_possible, resp);
986
987 // here we store data from the the response
988 // this information will be used to show correct UI elements
989 // when smush metabox will shown again without reloading main page
990 var blog_id = resp.blog_id || resp.options.blog_id,
991 image_id = resp.image || resp.options.attachment_id;
992
993 if (!smush_affected_images.hasOwnProperty(blog_id)) smush_affected_images[blog_id] = {};
994 if (!smush_affected_images[blog_id].hasOwnProperty(image_id)) smush_affected_images[blog_id][image_id] = {};
995
996 if ('compress' == resp.operation) {
997 smush_affected_images[blog_id][image_id] = {
998 operation: resp.operation,
999 summary: resp.summary,
1000 restore_possible: resp.restore_possible
1001 }
1002 } else {
1003 smush_affected_images[blog_id][image_id] = {
1004 operation: resp.operation
1005 }
1006 }
1007 } else {
1008 $(".smush-information").text(resp.error_message);
1009 update_view_modal_message($("#smush-information-modal"), $.unblockUI);
1010 }
1011 }
1012
1013 /**
1014 * Update metabox view depending on a command response.
1015 *
1016 * @param {string} operation
1017 * @param {string} summary
1018 * @param {boolean} restore_possible
1019 * @param {object} smush_image_data
1020 */
1021 function update_view_singe_image_compress(operation, summary, restore_possible, smush_image_data) {
1022 var wrapper = $("#smush_info").closest('#smush-metabox-inside-wrapper');
1023
1024 if ('compress' == operation) {
1025 $(".wpo_smush_single_image").hide();
1026 $(".wpo_restore_single_image").show();
1027
1028 if (smush_image_data && smush_image_data.hasOwnProperty('sizes-info')) {
1029 $("#smush_info").text(summary);
1030 $("#wpo_smush_details").html(smush_image_data['sizes-info']);
1031 } else {
1032 $("#smush_info").text(summary);
1033 $("#wpo_smush_details").text('').hide();
1034 }
1035
1036 $('.wpo_smush_mark_single_image').hide();
1037
1038 if (restore_possible) {
1039 $(".restore_possible").show();
1040 } else {
1041 $(".restore_possible").hide();
1042 }
1043 } else {
1044 $(".wpo_smush_single_image").show();
1045 $(".wpo_restore_single_image").hide();
1046
1047 $('.wpo_smush_mark_single_image').show();
1048 $('.wpo_smush_unmark_single_image', wrapper).hide();
1049 }
1050 }
1051
1052 /**
1053 * Handle smush metabox load event. This handler is used to restore correct smush metabox view.
1054 */
1055 $(document).on('admin-metabox-smush-loaded', function() {
1056 var image_data = $('.wpo_restore_single_image input[type="button"]').first().data();
1057
1058 if (!image_data) return;
1059
1060 if (smush_affected_images.hasOwnProperty(image_data.blog) && smush_affected_images[image_data.blog].hasOwnProperty(image_data.id)) {
1061 var smush_image_data = smush_affected_images[image_data.blog][image_data.id];
1062
1063 if ('compress' == smush_image_data.operation) {
1064 update_view_singe_image_compress(smush_image_data.operation, smush_image_data.summary, smush_image_data.restore_possible, smush_image_data);
1065 } else {
1066 update_view_singe_image_compress(smush_image_data.operation);
1067 }
1068 }
1069 });
1070
1071 /**
1072 * Display a modal message
1073 *
1074 * @param {string} message The message or element to display
1075 * @param {Function} callback Called when the overlay is clicked
1076 *
1077 * @return void
1078 */
1079 function update_view_modal_message(message, callback) {
1080
1081 $.blockUI({
1082 message: message,
1083 onOverlayClick: callback,
1084 baseZ: 160001,
1085 css: {
1086 width: '400px',
1087 padding: '20px',
1088 cursor: 'pointer'
1089 }
1090 });
1091 }
1092
1093 /**
1094 * Check returned response from the smush manager and call update view callback.
1095 *
1096 * @param {Object} resp - response from smush manager.
1097 * @param {Function} update_view_callback - callback function to update view.
1098 *
1099 * @return void
1100 */
1101 function handle_response_from_smush_manager(resp, update_view_callback) {
1102 if (resp && resp.hasOwnProperty('status') && resp.status) {
1103 if (update_view_callback) update_view_callback(resp);
1104 } else {
1105 alert(wposmush.error_unexpected_response);
1106 console.log(resp);
1107 }
1108 }
1109
1110 /**
1111 * Send an action to the task manager via admin-ajax.php.
1112 *
1113 * @param {string} action The action to send
1114 * @param {[type]} data Data to send
1115 * @param {Function} callback Will be called with the results
1116 * @param {boolean} json_parse JSON parse the results
1117 *
1118 * @return {JSON}
1119 */
1120 function smush_manager_send_command(action, data, callback, json_parse) {
1121
1122 json_parse = ('undefined' === typeof json_parse) ? true : json_parse;
1123 data = $.isEmptyObject(data) ? {'use_cache' : false} : data;
1124
1125 var ajax_data = {
1126 action: 'updraft_smush_ajax',
1127 subaction: action,
1128 nonce: wposmush.smush_ajax_nonce,
1129 data: data
1130 };
1131
1132 var ajax_opts = {
1133 type: 'POST',
1134 url: ajaxurl,
1135 data: ajax_data,
1136 success: function(response) {
1137
1138 if (json_parse) {
1139 try {
1140 var resp = wpo_parse_json(response);
1141 } catch (e) {
1142 console.log("smush_manager_send_command JSON parse error");
1143 console.log(e);
1144 console.log(response);
1145 alert(wposmush.error_unexpected_response);
1146 }
1147 if ('undefined' !== typeof callback) callback(resp);
1148 } else {
1149 if ('undefined' !== typeof callback) callback(response);
1150 }
1151 },
1152 error: function(response, status, error_code) {
1153 console.log("smush_manager_send_command AJAX parse error: "+status+" ("+error_code+")");
1154 if ('undefined' !== typeof callback) {
1155 callback(response);
1156 } else {
1157 console.log(response);
1158 alert(wposmush.error_unexpected_response);
1159 }
1160 },
1161 dataType: 'text'
1162
1163 }
1164
1165 $.ajax(ajax_opts);
1166
1167 };
1168
1169 // Gather smush options
1170 var get_smush_options = function() {
1171 var image_quality = '';
1172 if ($('#enable_custom_compression').is(":checked")) {
1173 image_quality = $('#custom_compression_slider').val();
1174 } else {
1175 // The '90' here has to be kept in sync with WP_Optimize::admin_page_wpo_images_smush()
1176 image_quality = $('#enable_lossy_compression').is(":checked") ? 60 : 100;
1177 }
1178 var lossy_compression = image_quality < 100 ? true : false;
1179
1180 return {
1181 'compression_server': $("input[name='compression_server']:checked").val(),
1182 'image_quality': image_quality,
1183 'lossy_compression': lossy_compression,
1184 'back_up_original': $('#smush-backup-original').is(":checked"),
1185 'back_up_delete_after': $('#smush-backup-delete').is(":checked"),
1186 'back_up_delete_after_days': $('#smush-backup-delete-days').val(),
1187 'preserve_exif': $('#smush-preserve-exif').is(":checked"),
1188 'autosmush': $('#smush-automatically').is(":checked"),
1189 'show_smush_metabox': $('#smush-show-metabox').is(":checked"),
1190 'webp_conversion': $('#enable_webp_conversion').is(":checked")
1191 };
1192 }
1193 wp_optimize.smush_settings = get_smush_options;
1194 } // END WP_Optimize_Smush
1195
1196 /**
1197 * Parse JSON string, including automatically detecting unwanted extra input and skipping it
1198 *
1199 * @param {string|object} json_mix_str - JSON string which need to parse and convert to object
1200 *
1201 * @throws SyntaxError|String (including passing on what JSON.parse may throw) if a parsing error occurs.
1202 *
1203 * @return mixed parsed JSON object. Will only return if parsing is successful (otherwise, will throw)
1204 */
1205 function wpo_parse_json(json_mix_str) {
1206 // When using wp_send_json to return the value, the format is already parsed.
1207 if ('object' === typeof json_mix_str) return json_mix_str;
1208
1209 // Just try it - i.e. the 'default' case where things work (which can include extra whitespace/line-feeds, and simple strings, etc.).
1210 try {
1211 var result = JSON.parse(json_mix_str);
1212 return result;
1213 } catch (e) {
1214 console.log("WPO: Exception when trying to parse JSON (1) - will attempt to fix/re-parse");
1215 console.log(json_mix_str);
1216 }
1217
1218 var json_start_pos = json_mix_str.indexOf('{');
1219 var json_last_pos = json_mix_str.lastIndexOf('}');
1220
1221 // Case where some php notice may be added after or before json string
1222 if (json_start_pos > -1 && json_last_pos > -1) {
1223 var json_str = json_mix_str.slice(json_start_pos, json_last_pos + 1);
1224 try {
1225 var parsed = JSON.parse(json_str);
1226 return parsed;
1227 } catch (e) {
1228 console.log("WPO: Exception when trying to parse JSON (2) - will attempt to fix/re-parse based upon bracket counting");
1229
1230 var cursor = json_start_pos;
1231 var open_count = 0;
1232 var last_character = '';
1233 var inside_string = false;
1234
1235 // 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.
1236 while ((open_count > 0 || cursor == json_start_pos) && cursor <= json_last_pos) {
1237
1238 var current_character = json_mix_str.charAt(cursor);
1239
1240 if (!inside_string && '{' == current_character) {
1241 open_count++;
1242 } else if (!inside_string && '}' == current_character) {
1243 open_count--;
1244 } else if ('"' == current_character && '\\' != last_character) {
1245 inside_string = inside_string ? false : true;
1246 }
1247
1248 last_character = current_character;
1249 cursor++;
1250 }
1251
1252 console.log("Started at cursor="+json_start_pos+", ended at cursor="+cursor+" with result following:");
1253 console.log(json_mix_str.substring(json_start_pos, cursor));
1254
1255 try {
1256 var parsed = JSON.parse(json_mix_str.substring(json_start_pos, cursor));
1257 // console.log('WPO: JSON re-parse successful');
1258 return parsed;
1259 } catch (e) {
1260 // Throw it again, so that our function works just like JSON.parse() in its behaviour.
1261 throw e;
1262 }
1263
1264 }
1265 }
1266
1267 throw "WPO: could not parse the JSON";
1268
1269 }
1270