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

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