PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 1.4.3
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v1.4.3
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / assets / js / jquery.twentytwenty.js

jquery.twentytwenty.js in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 1.4.3, at assets/js/jquery.twentytwenty.js

551 lines 20.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function(window, $, undefined){
2
3 $.fn.twentytwenty = function(options, callback) {
4 var options = $.extend({
5 handlePosition : 0.5,
6 orientation : 'horizontal',
7 labelBefore : 'Before',
8 labelAfter : 'After'
9 }
10 , options);
11 return this.each(function() {
12
13 var sliderPct = options.handlePosition,
14 $container = $(this),
15 sliderOrientation = options.orientation,
16 beforeDirection = (sliderOrientation === 'vertical') ? 'down' : 'left',
17 afterDirection = (sliderOrientation === 'vertical') ? 'up' : 'right',
18 $beforeImg = $container.find('img:first'),
19 $afterImg = $container.find('img:last');
20
21
22 $container.wrap('<div class="twentytwenty-wrapper twentytwenty-' + sliderOrientation + '"></div>');
23 $container.append('<div class="twentytwenty-overlay"></div>');
24 $container.append('<div class="twentytwenty-handle"></div>');
25
26 var $slider = $container.find('.twentytwenty-handle');
27
28 $slider.append('<span class="twentytwenty-' + beforeDirection + '-arrow"></span>');
29 $slider.append('<span class="twentytwenty-' + afterDirection + '-arrow"></span>');
30 $container.addClass('twentytwenty-container');
31 $beforeImg.addClass('twentytwenty-before');
32 $afterImg.addClass('twentytwenty-after');
33
34 var $overlay = $container.find('.twentytwenty-overlay');
35
36 $overlay.append('<div class="twentytwenty-labels twentytwenty-before-label"><span class="twentytwenty-label-content">' + options.labelBefore + '</span></div>');
37 $overlay.append('<div class="twentytwenty-labels twentytwenty-after-label"><span class="twentytwenty-label-content">' + options.labelAfter + '</span></div>');
38
39
40 // some usefull function and vars declarations
41
42 var calcOffset = function(dimensionPct) {
43 var w = $beforeImg.width();
44 var h = $beforeImg.height();
45 return {
46 w: w+"px",
47 h: h+"px",
48 cw: (dimensionPct*w)+"px",
49 ch: (dimensionPct*h)+"px"
50 };
51 },
52
53 adjustContainer = function( offset ) {
54 // make it dynamic, in case "before" image change
55 var $beforeImg = $container.find('.twentytwenty-before');
56
57 if ( sliderOrientation === 'vertical' ) {
58 $beforeImg.css( 'clip', 'rect(0,' + offset.w + ',' + offset.ch + ',0)' );
59 }
60 else {
61 $beforeImg.css( 'clip', 'rect(0,' + offset.cw + ',' + offset.h + ',0)' );
62 }
63 $container.css( 'height', offset.h );
64
65 if ( typeof callback === 'function' ) {
66 callback();
67 }
68 },
69 adjustSlider = function( pct ) {
70 var offset = calcOffset(pct);
71 $slider.css( ( sliderOrientation === 'vertical' ) ? 'top' : 'left', ( sliderOrientation === 'vertical' ) ? offset.ch : offset.cw );
72 adjustContainer( offset );
73 },
74 offsetX = 0,
75 offsetY = 0,
76 imgWidth = 0,
77 imgHeight = 0;
78
79 $(window).on('resize.twentytwenty', function(e) {
80 adjustSlider( sliderPct );
81 });
82
83 $slider.on('movestart', function(e) {
84 if ( ( ( e.distX > e.distY && e.distX < -e.distY ) || ( e.distX < e.distY && e.distX > -e.distY ) ) && sliderOrientation !== 'vertical' ) {
85 e.preventDefault();
86 }
87 else if ( ( ( e.distX < e.distY && e.distX < -e.distY ) || ( e.distX > e.distY && e.distX > -e.distY ) ) && sliderOrientation === 'vertical' ) {
88 e.preventDefault();
89 }
90 $container.addClass('active');
91 offsetX = $container.offset().left;
92 offsetY = $container.offset().top;
93 imgWidth = $beforeImg.width();
94 imgHeight = $beforeImg.height();
95 });
96
97 $slider.on('moveend', function(e) {
98 $container.removeClass('active');
99 });
100
101 $slider.on('move', function(e) {
102 if ( $container.hasClass('active') ) {
103
104 sliderPct = ( sliderOrientation === 'vertical' ) ? ( e.pageY-offsetY )/imgHeight : ( e.pageX-offsetX )/imgWidth;
105
106 if ( sliderPct < 0 ) {
107 sliderPct = 0;
108 }
109 if ( sliderPct > 1 ) {
110 sliderPct = 1;
111 }
112 adjustSlider( sliderPct );
113 }
114 });
115
116 $container.find('img').on('mousedown', function(event) {
117 event.preventDefault();
118 });
119
120 $(window).trigger('resize.twentytwenty');
121 });
122 };
123
124 })(window, jQuery);
125
126 /**
127 * Twentytwenty Imagify Init
128 */
129 (function($, window, document, undefined){
130
131 /*
132 * Mini chart
133 *
134 * @param {element} canvas
135 */
136 var draw_me_a_chart = function ( canvas ) {
137 canvas.each(function(){
138 var the_value = parseInt( $(this).closest('.imagify-chart').next('.imagify-chart-value').text() ),
139 overviewData = [
140 {
141 value: the_value,
142 color: '#00B3D3'
143 },
144 {
145 value: 100 - the_value,
146 color: '#D8D8D8'
147 }
148 ],
149 overviewDoughnut = new Chart( $(this)[0].getContext('2d')).Doughnut(overviewData, {
150 segmentStrokeColor : '#2A2E3C',
151 segmentStrokeWidth : 1,
152 animateRotate : true,
153 percentageInnerCutout: 60,
154 tooltipEvents : []
155 });
156 });
157 };
158
159 /**
160 * Dynamic modal
161 *
162 * @param {object} Parameters to build modal with datas
163 */
164 var imagify_twenty_modal = function( options ) {
165
166 var defaults = {
167 width: 0, //px
168 height: 0, //px
169 original_url: '', //url
170 optimized_url: '', //url
171 original_size: 0, //mb
172 optimized_size: 0, // mb
173 saving: 0, //percent
174 modal_append_to: $('body'), // jQuery element
175 trigger: $('[data-target="imagify-visual-comparison"]'), // jQuery element (button, link) with data-target="modal_id"
176 modal_id: 'imagify-visual-comparison', // should be dynamic if multiple modals
177 },
178 settings = $.extend({}, defaults, options);
179
180 if ( settings.width === 0 || settings.height === 0 || settings.original_url === ''|| settings.optimized_url === '' || settings.original_size === 0 || settings.optimized_size === 0 || settings.saving === 0 ) {
181 return 'error';
182 }
183
184 // create modal box
185 settings.modal_append_to.append(''
186 + '<div id="' + settings.modal_id + '" class="imagify-modal imagify-visual-comparison" aria-hidden="true">'
187 + '<div class="imagify-modal-content loading">'
188 + '<div class="twentytwenty-container">'
189 + '<img class="imagify-img-before" alt="" width="' + settings.width + '" height="' + settings.height + '">'
190 + '<img class="imagify-img-after" alt="" width="' + settings.width + '" height="' + settings.height + '">'
191 + '</div>'
192 + '<div class="imagify-comparison-levels">'
193 + '<div class="imagify-c-level imagify-level-original go-left">'
194 + '<p class="imagify-c-level-row">'
195 + '<span class="label">' + imagifyTTT.labels.filesize + '</span>'
196 + '<span class="value level">' + settings.original_size + '</span>'
197 + '</p>'
198 + '</div>'
199 + '<div class="imagify-c-level imagify-level-optimized go-right">'
200 + '<p class="imagify-c-level-row">'
201 + '<span class="label">' + imagifyTTT.labels.filesize + '</span>'
202 + '<span class="value level">' + settings.optimized_size + '</span>'
203 + '</p>'
204 + '<p class="imagify-c-level-row">'
205 + '<span class="label">' + imagifyTTT.labels.saving + '</span>'
206 + '<span class="value"><span class="imagify-chart"><span class="imagify-chart-container"><canvas id="imagify-consumption-chart-normal" width="15" height="15"></canvas></span></span><span class="imagify-chart-value">' + settings.saving + '</span>%</span>'
207 + '</p>'
208 +'</div>'
209 + '</div>'
210 + '<button class="close-btn absolute" type="button"><i aria-hidden="true" class="dashicons dashicons-no-alt"></i><span class="screen-reader-text">' + imagifyTTT.labels.close + '</span></button>'
211 + '</div>'
212 + '</div>'
213 );
214
215 settings.trigger.on('click.imagify', function(){
216
217 var $modal = $( $(this).data('target') ),
218 imgs_loaded = 0;
219
220 $modal.find('.imagify-modal-content').css({
221 'width' : ($(window).outerWidth()*0.95) + 'px',
222 'max-width' : settings.width
223 });
224
225 // load before img
226 $modal.find('.imagify-img-before').on('load', function(){
227 imgs_loaded++;
228 }).attr('src', settings.original_url);
229
230 // load after img
231 $modal.find('.imagify-img-after').on('load', function(){
232 imgs_loaded++;
233 }).attr('src', settings.optimized_url);
234
235 var $tt = $modal.find('.twentytwenty-container'),
236 check_load = setInterval( function(){
237
238 if ( imgs_loaded === 2 ) {
239 $tt.twentytwenty({
240 handlePosition: 0.3,
241 orientation: 'horizontal',
242 labelBefore: imagifyTTT.labels.original_l,
243 labelAfter: imagifyTTT.labels.optimized_l
244 }, function(){
245
246 var windowH = $(window).height(),
247 ttH = $modal.find('.twentytwenty-container').height(),
248 ttTop = $modal.find('.twentytwenty-wrapper').position().top;
249
250 if ( ! $tt.closest('.imagify-modal-content').hasClass('loaded') ) {
251 $tt.closest('.imagify-modal-content').removeClass('loading').addClass('loaded');
252 draw_me_a_chart( $modal.find('.imagify-level-optimized').find('.imagify-chart').find('canvas') );
253 }
254
255 // check if image height is to big
256 if ( windowH < ttH && ! $modal.hasClass('modal-is-too-high') ) {
257 $modal.addClass('modal-is-too-high');
258
259 var $handle = $modal.find('.twentytwenty-handle'),
260 $labels = $modal.find('.twentytwenty-label-content'),
261 $datas = $modal.find('.imagify-comparison-levels'),
262 datasH = $datas.outerHeight(),
263 handle_pos = ( windowH - ttTop - $handle.height() ) / 2,
264 labels_pos = ( windowH - ttTop * 3 - datasH );
265
266 $handle.css({
267 top: handle_pos
268 });
269 $labels.css({
270 top: labels_pos,
271 bottom: 'auto'
272 });
273 $modal.find('.twentytwenty-wrapper').css({
274 paddingBottom: datasH
275 });
276
277 $modal.find('.imagify-modal-content').on('scroll.imagify', function(){
278 $handle.css({
279 top: handle_pos + $(this).scrollTop()
280 });
281 $labels.css({
282 top: labels_pos + $(this).scrollTop()
283 });
284 $datas.css({
285 bottom: - ( $(this).scrollTop() )
286 });
287 });
288 }
289
290 });
291 clearInterval( check_load );
292 check_load = null;
293 return 'done';
294 }
295 }, 75 );
296
297 return false;
298 });
299 }; // imagify_twenty_modal( options );
300
301
302 /**
303 * The complexe visual comparison
304 */
305 $('.imagify-visual-comparison-btn').on('click', function(){
306
307 if ( $('.twentytwenty-wrapper').length === 1) {
308 return;
309 }
310
311 $( $(this).data('target') ).find('.imagify-modal-content').css('width', ($(window).outerWidth()*0.95) + 'px');
312
313 if ( $('.twentytwenty-container').length > 0 && $(window).outerWidth() > 800 ) {
314
315 var $tt = $('.twentytwenty-container'),
316 imgs_loaded = 0,
317 loader = $tt.data('loader'),
318 label_original = $tt.data('label-original'),
319 label_normal = $tt.data('label-normal'),
320 label_aggressive = $tt.data('label-aggressive'),
321 label_ultra = $tt.data('label-ultra'),
322
323 original_label = $tt.data('original-label').replace(/\*\*/, '<strong>').replace(/\*\*/, '</strong>'),
324 original_alt = $tt.data('original-alt'),
325 original_src = $tt.data('original-img'),
326 original_dim = $tt.data('original-dim').split('x'),
327
328 normal_label = $tt.data('normal-label').replace(/\*\*/, '<strong>').replace(/\*\*/, '</strong>'),
329 normal_alt = $tt.data('normal-alt'),
330 normal_src = $tt.data('normal-img'),
331 normal_dim = $tt.data('normal-dim').split('x'),
332
333 aggressive_label = $tt.data('aggressive-label').replace(/\*\*/, '<strong>').replace(/\*\*/, '</strong>'),
334 aggressive_alt = $tt.data('aggressive-alt'),
335 aggressive_src = $tt.data('aggressive-img'),
336 aggressive_dim = $tt.data('aggressive-dim').split('x'),
337
338 ultra_label = $tt.data('ultra-label').replace(/\*\*/, '<strong>').replace(/\*\*/, '</strong>'),
339 ultra_alt = $tt.data('ultra-alt'),
340 ultra_src = $tt.data('ultra-img'),
341 ultra_dim = $tt.data('ultra-dim').split('x'),
342
343 tt_before_buttons = '<span class="twentytwenty-duo-buttons twentytwenty-duo-left">' +
344 '<button type="button" class="imagify-comparison-original selected" data-img="original">' + label_original + '</button>' +
345 '<button type="button" class="imagify-comparison-normal" data-img="normal">' + label_normal + '</button>' +
346 '<button type="button" class="imagify-comparison-aggressive" data-img="aggressive">' + label_aggressive + '</button>' +
347 '</span>',
348 tt_after_buttons = '<span class="twentytwenty-duo-buttons twentytwenty-duo-right">' +
349 '<button type="button" class="imagify-comparison-normal" data-img="normal">' + label_normal + '</button>' +
350 '<button type="button" class="imagify-comparison-aggressive" data-img="aggressive">' + label_aggressive + '</button>' +
351 '<button type="button" class="imagify-comparison-ultra selected" data-img="ultra">' + label_ultra + '</button>' +
352 '</span>';
353
354 // loader
355 $tt.before('<img class="loader" src="' + loader + '" alt="Loading…" width="64" height="64">')
356
357 // add switchers button only if needed
358 // should be more locally integrate...
359 var duo_buttons = ( $('.twentytwenty-left-buttons').lenght ) ? tt_before_buttons + tt_after_buttons : '';
360 // should be more locally integrate...
361 $('.twentytwenty-left-buttons').append(tt_before_buttons);
362 $('.twentytwenty-right-buttons').append(tt_after_buttons);
363
364 // add images to 50/50 area
365 $tt.closest('.imagify-modal-content').addClass('loading').find('.twentytwenty-container').append(
366 '<img class="img-original" alt="' + original_alt + '" width="' + original_dim[0] + '" height="' + original_dim[1] + '">' +
367 '<img class="img-normal" alt="' + normal_alt + '" width="' + normal_dim[0] + '" height="' + normal_dim[1] + '">' +
368 '<img class="img-aggressive" alt="' + aggressive_alt + '" width="' + aggressive_dim[0] + '" height="' + aggressive_dim[1] + '">' +
369 '<img class="img-ultra" alt="' + ultra_alt + '" width="' + ultra_dim[0] + '" height="' + ultra_dim[1] + '">' +
370 duo_buttons
371 );
372
373 // load image original
374 $('.img-original').on('load', function(){
375 imgs_loaded++;
376 }).attr('src', original_src);
377
378 // load image normal
379 $('.img-normal').on('load', function(){
380 imgs_loaded++;
381 }).attr('src', normal_src);
382
383 // load image aggressive
384 $('.img-aggressive').on('load', function(){
385 imgs_loaded++;
386 }).attr('src', aggressive_src);
387
388 // load image ultra
389 $('.img-ultra').on('load', function(){
390 imgs_loaded++;
391 }).attr('src', ultra_src);
392
393 var twenty_me = setInterval(function(){
394 if ( imgs_loaded === 4 ) {
395 $tt.twentytwenty({
396 handlePosition: 0.6,
397 orientation: 'horizontal',
398 labelBefore: original_label,
399 labelAfter: ultra_label
400 }, function(){
401 // fires on initialisation & each time the handle is moving
402 if ( ! $tt.closest('.imagify-modal-content').hasClass('loaded') ) {
403 $tt.closest('.imagify-modal-content').removeClass('loading').addClass('loaded');
404 draw_me_a_chart( $('.imagify-level-ultra').find('.imagify-chart').find('canvas') );
405 }
406 });
407 clearInterval( twenty_me );
408 twenty_me = null;
409 }
410 }, 75);
411
412 // on click on button choices
413
414 $('.imagify-comparison-title').on('click', '.twentytwenty-duo-buttons button:not(.selected)', function(e){
415
416 e.stopPropagation();
417
418 var $_this = $(this),
419 $container = $_this.closest('.imagify-comparison-title').nextAll('.twentytwenty-wrapper').find('.twentytwenty-container'),
420 side = $_this.closest('.twentytwenty-duo-buttons').hasClass('twentytwenty-duo-left') ? 'left' : 'right',
421 $other_side = side === 'left' ? $_this.closest('.imagify-comparison-title').find('.twentytwenty-duo-right') : $_this.closest('.imagify-comparison-title').find('.twentytwenty-duo-left'),
422 $duo = $_this.closest('.twentytwenty-duo-buttons').find('button'),
423 $img_before = $container.find('.twentytwenty-before'),
424 $img_after = $container.find('.twentytwenty-after'),
425 image = $_this.data('img');
426
427 // button coloration
428 $duo.removeClass('selected');
429 $_this.addClass('selected');
430
431 // other side action (to not compare same images)
432 if ( $other_side.find('.selected').data('img') === image ) {
433 $other_side.find('button:not(.selected)').eq(0).trigger('click');
434 }
435
436 // left buttons
437 if ( side === 'left' ) {
438 var clip_styles = $img_before.css('clip');
439 $img_before.attr('style', '');
440 $img_before.removeClass('twentytwenty-before');
441 $container.find( '.img-' + image ).addClass('twentytwenty-before').css('clip', clip_styles);
442 $('.twentytwenty-before-label').find('.twentytwenty-label-content').text( $container.data( image + '-label' ) );
443 $('.imagify-c-level.go-left').attr('aria-hidden', 'true').removeClass('go-left go-right');
444 $('.imagify-level-' + image).attr('aria-hidden', 'false').addClass('go-left');
445 }
446
447 // right buttons
448 if ( side === 'right' ) {
449 $img_after.removeClass('twentytwenty-after')
450 $container.find( '.img-' + image ).addClass('twentytwenty-after');
451 $('.twentytwenty-after-label').find('.twentytwenty-label-content').text( $container.data( image + '-label' ) );
452 $('.imagify-c-level.go-right').attr('aria-hidden', 'true').removeClass('go-left go-right');
453 $('.imagify-level-' + image).attr('aria-hidden', 'false').addClass('go-right');
454 }
455
456 draw_me_a_chart( $('.imagify-level-' + image).find('.imagify-chart').find('canvas') );
457
458 return false;
459
460 });
461 }
462
463 });
464
465
466 /**
467 * Imagify comparison inside Media post visualization
468 */
469 if ( $('.post-php').find('.wp_attachment_image').find('.thumbnail').length > 0 ) {
470
471 var $ori_parent = $('.post-php').find('.wp_attachment_image'),
472 $thumbnail = $ori_parent.find('.thumbnail'),
473 thumb = { src: $thumbnail.prop('src'), width: $thumbnail.width(), height: $thumbnail.height() },
474 ori_source = { src: $('#imagify-full-original').val(), size: $('#imagify-full-original-size').val() },
475 $optimize_btn = $('#misc-publishing-actions').find('.misc-pub-imagify').find('.button-primary'),
476 width_limit = 360;
477
478 // if shown image > 360, use twentytwenty
479 if ( thumb.width > width_limit && $('#imagify-full-original').length > 0 && $('#imagify-full-original').val() !== '' ) {
480
481 var imgs_loaded = 0,
482 filesize = $('.misc-pub-filesize').find('strong').text(),
483 saving = $('.imagify-data-item').find('.imagify-chart-value').text();
484
485 // create button to trigger
486 $('[id^="imgedit-open-btn-"]').before('<button type="button" class="imagify-button-primary button-primary imagify-modal-trigger" data-target="#imagify-visual-comparison" id="imagify-start-comparison">' + imagifyTTT.labels.compare + '</button>')
487
488 // Modal and trigger event creation
489 var is_modalified = imagify_twenty_modal({
490 width: thumb.width,
491 height: thumb.height,
492 original_url: ori_source.src,
493 optimized_url: thumb.src,
494 original_size: ori_source.size,
495 optimized_size: filesize,
496 saving: saving,
497 modal_append_to: $ori_parent,
498 trigger: $('#imagify-start-comparison'),
499 modal_id: 'imagify-visual-comparison'
500 });
501 }
502 // else put images next to next
503 else if ( thumb.width < width_limit && $('#imagify-full-original').length > 0 && $('#imagify-full-original').val() !== '' ) {
504
505 }
506 // if image has no backup
507 else if ( $('#imagify-full-original').length > 0 && $('#imagify-full-original').val() === '' ) {
508 // do nothing ?
509 }
510 // in case image is not optimized
511 else {
512 $('[id^="imgedit-open-btn-"]').before('<span class="spinner imagify-hidden"></span><a class="imagify-button-primary button-primary imagify-optimize-trigger" id="imagify-optimize-trigger" href="' + $optimize_btn.attr('href') + '">' + imagifyTTT.labels.optimize + '</a>');
513
514 $('#imagify-optimize-trigger').on('click', function(){
515 $(this).prev('.spinner').removeClass('imagify-hidden').addClass('is-active');
516 });
517 }
518
519 }
520
521 /**
522 * Comparison images in attachments list page (upload.php)
523 */
524 if ( $('.upload-php').find('.imagify-compare-images').length > 0 ) {
525
526 $('.imagify-compare-images').each(function(){
527
528 var $_this = $(this),
529 id = $_this.data('id'),
530 $datas = $_this.closest('#post-' + id ).find('.column-imagify_optimized_file'),
531
532 // Modal and trigger event creation
533 is_modalified = imagify_twenty_modal({
534 width: $_this.data('full-width'),
535 height: $_this.data('full-height'),
536 original_url: $_this.data('backup-src'),
537 optimized_url: $_this.data('full-src'),
538 original_size: $datas.find('.original').text(),
539 optimized_size: $datas.find('.imagify-data-item').find('.big').text(),
540 saving: $datas.find('.imagify-chart-value').text(),
541 modal_append_to: $_this.closest('.column-primary'),
542 trigger: $_this,
543 modal_id: 'imagify-comparison-' + id
544 });
545
546 });
547
548 }
549
550 })(jQuery, window, document);
551