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

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