1/** 2 * ALB Shortcode Image Difference frontend and preview iframe 3 * 4 * @added by guenter 5 * @since 5.5 6 */ 7"use strict"; 8 9// global namespace 10var avia_js_shortcodes = avia_js_shortcodes || {}; 11var aviaJS = aviaJS || {}; 12 13(function() 14{ 15 if( ! avia_js_shortcodes.aviaImageDiff ) 16 { 17 class scAviaImageDiff 18 { 19 container = null; // container element 20 id = ''; 21 divider = 'vertical'; // 'vertical' | 'horizontal' 22 handle = null; 23 settings = {}; 24 wrapperDiv = [] 25 btnOverlay = []; 26 btnBefore = []; 27 btnAfter = []; 28 imgBefore = []; 29 imgAfter = []; 30 imgDimension = {}; 31 mouseCapture = false; 32 touchCapture = false; 33 touchMoved = false; 34 downScreenX = 0; 35 downScreenY = 0; 36 downClientX = 0; 37 downClientY = 0; 38 downHandlePos = 0; 39 preview = false; 40 41 constructor( container ) 42 { 43 this.container = container; 44 this.container.scAviaImageDiff = this; 45 this.id = container.getAttribute('id'); 46 47 this.handle = container.getElementsByClassName( 'av-image-diff-handle' ); 48 if( ! this.handle.length ) 49 { 50 return; 51 } 52 53 this.handle = this.handle[0]; 54 55 this.init(); 56 } 57 58 init() 59 { 60 this.settings = JSON.parse( this.container.dataset.image_diff ); 61 this.wrapperDiv = this.container.getElementsByClassName( 'av-image-diff-wrapper' ); 62 this.btnOverlay = this.container.getElementsByClassName( 'av-image-diff-overlay' ); 63 this.btnBefore = this.btnOverlay[0].getElementsByClassName( 'label-before' ); 64 this.btnAfter = this.btnOverlay[0].getElementsByClassName( 'label-after' ); 65 this.imgBefore = this.container.getElementsByClassName( 'av-img-before' ); 66 this.imgAfter = this.container.getElementsByClassName( 'av-img-after' ); 67 68 if( ! this.imgBefore.length || ! this.imgAfter.length ) 69 { 70 this.hideHandlerDOM(); 71 return; 72 } 73 74 if( this.container.classList.contains( 'av-handle-horizontal' ) ) 75 { 76 this.divider = 'horizontal'; 77 } 78 79 this.preview = document.getElementById( 'av-admin-preview' ) != null; 80 81 this.bindEvents(); 82 this.initialPositionHandler(); 83 } 84 85 hideHandlerDOM() 86 { 87 this.handle.style.display = 'none'; 88 89 if( this.btnOverlay.length ) 90 { 91 this.btnOverlay[0].style.display = 'none'; 92 } 93 } 94 95 initialPositionHandler() 96 { 97 let start = ( 'undefined' == typeof this.settings.drag_start ) ? 50 : parseInt( this.settings.drag_start ); 98 if( isNaN( start ) ) 99 { 100 start = 50; 101 } 102 103 let offset = 0; 104 105 this.imgDimension = this.imgBefore[0].getBoundingClientRect(); 106 107 if( this.divider == 'horizontal' ) 108 { 109 offset = this.imgDimension.height * ( start / 100.0 ); 110 } 111 else 112 { 113 offset = this.imgDimension.width * ( start / 100.0 ); 114 } 115 116 this.container.classList.add( 'av-initialise' ); 117 118 this.adjustDividerFrame( offset ); 119 120 let obj = this; 121 122 setTimeout( function() 123 { 124 obj.container.classList.remove( 'av-initialise' ); 125 }, 700 ); 126 } 127 128 adjustDividerFrame( offset ) 129 { 130 const overhead = 5; 131 132 this.container.classList.remove( 'av-handler-at-before', 'av-handler-at-after'); 133 134 offset = Math.round( offset ); 135 136 if( offset <= 0 ) 137 { 138 offset = 0; 139 this.container.classList.add( 'av-handler-at-before' ); 140 } 141 142 if( this.divider == 'horizontal' ) 143 { 144 if( offset >= ( this.imgDimension.height + overhead ) ) 145 { 146 offset = Math.round( this.imgDimension.height + overhead ); 147 this.container.classList.add( 'av-handler-at-after' ); 148 } 149 150 let bottom = this.imgDimension.height - offset; 151 152 this.handle.style.top = offset + 'px'; 153 this.imgBefore[0].style['clip-path'] = 'inset( 0 0 ' + bottom + 'px 0 )'; 154 this.imgAfter[0].style['clip-path'] = 'inset( ' + offset + 'px 0 0 0 )'; 155 } 156 else 157 { 158 if( offset >= ( this.imgDimension.width + overhead ) ) 159 { 160 offset = Math.round( this.imgDimension.width + overhead ); 161 this.container.classList.add( 'av-handler-at-after' ); 162 } 163 164 let right = this.imgDimension.width - offset; 165 166 this.handle.style.left = offset + 'px'; 167 this.imgBefore[0].style['clip-path'] = 'inset( 0 ' + right + 'px 0 0 )'; 168 this.imgAfter[0].style['clip-path'] = 'inset( 0 0 0 ' + offset + 'px )'; 169 } 170 } 171 172 bindEvents() 173 { 174 // jQuery event hack -> see lottie_animation.js 175 this.container.onavia_start_animation = ( e ) => 176 { 177 const opt = { 178 'bubbles': true, 179 'cancelable': true 180 }; 181 182 const event = new CustomEvent( 'avia_start_animation', opt );
183 this.container.dispatchEvent( event ); 184 }; 185 186 this.container.addEventListener( 'avia_start_animation', this.onAviaStartAnimation.bind( this ) ); 187 188 189 this.handle.addEventListener( 'click', this.onHandleClick.bind( this ) ); 190 this.handle.addEventListener( 'mousedown', this.onMouseDown.bind( this ) ); 191 192 if( this.wrapperDiv.length > 0 ) 193 { 194 this.wrapperDiv[0].addEventListener( 'click', this.onClickWrapper.bind( this ) ); 195 this.wrapperDiv[0].addEventListener( 'touchstart', this.onTouchStart.bind( this ) ); 196 } 197 198 if( this.btnBefore.length > 0 ) 199 { 200 this.btnBefore[0].addEventListener( 'click', this.onClickBtnBefore.bind( this ) ); 201 } 202 203 if( this.btnAfter.length > 0 ) 204 { 205 this.btnAfter[0].addEventListener( 'click', this.onClickBtnAfter.bind( this ) ); 206 } 207 208 window.addEventListener( 'mousemove', this.onMouseMove.bind( this ) ); 209 window.addEventListener( 'mouseup', this.onMouseUp.bind( this ) ); 210 window.addEventListener( 'touchmove', this.onTouchMove.bind( this ) ); 211 window.addEventListener( 'touchend', this.onTouchEnd.bind( this ) ); 212 window.addEventListener( 'resize', aviaJS.aviaJSHelpers.debounce( this.onResize.bind( this ), 200 ) ); 213 214 if( this.preview ) 215 { 216 this.container.addEventListener( 'animationend', this.onAnimationEnd.bind( this ) ); 217 } 218 } 219 220 onAviaStartAnimation( event ) 221 { 222 if( this.container.classList.contains( 'avia_animation_finished' ) ) 223 { 224 return; 225 } 226 227 if( this.preview ) 228 { 229 // modal preview does not have waypoint script - simulate it 230 this.container.classList.add( 'avia_start_animation', 'avia_animation_finished' ); 231 } 232 233 if( 'undefined' != typeof event ) 234 { 235 this.container.classList.add( 'avia_animation_finished', 'avia_start_delayed_animation' ); 236 } 237 } 238 239 onAnimationEnd( event ) 240 { 241 if( ! this.preview ) 242 { 243 return; 244 } 245 246 this.initialPositionHandler(); 247 } 248 249 onMouseDown( event ) 250 { 251 if( this.touchCapture ) 252 { 253 return; 254 } 255 256 event.preventDefault(); 257 event.stopPropagation(); 258 259 this.mouseCapture = true; 260 this.container.classList.add( 'av-active-drag' ); 261 262 this.downScreenX = event.screenX; 263 this.downScreenY = event.screenY; 264 265 if( this.divider == 'horizontal' ) 266 { 267 this.downHandlePos = this.handle.style.top; 268 } 269 else 270 { 271 this.downHandlePos = this.handle.style.left; 272 } 273 274 this.downHandlePos = parseInt( this.downHandlePos.replace( 'px', '' ) ); 275 } 276 277 onMouseMove( event ) 278 { 279 if( ! this.mouseCapture ) 280 { 281 return; 282 } 283 284 event.preventDefault(); 285 event.stopPropagation(); 286 287 let newPos = 0, 288 diff = 0; 289 290 if( this.divider == 'horizontal' ) 291 { 292 diff = event.screenY - this.downScreenY; 293 } 294 else 295 { 296 diff = event.screenX - this.downScreenX; 297 } 298 299 if( Math.abs( diff ) < 5 ) 300 { 301 return; 302 } 303 304 newPos = this.downHandlePos + diff; 305 306 this.adjustDividerFrame( newPos ); 307 } 308 309 onMouseUp( event ) 310 { 311 if( ! this.mouseCapture ) 312 { 313 return; 314 } 315 316 event.preventDefault(); 317 event.stopPropagation(); 318 319 this.mouseCapture = false; 320 this.container.classList.remove( 'av-active-drag' ); 321 } 322 323 onTouchStart( event ) 324 { 325 if( this.mouseCapture ) 326 { 327 return; 328 } 329 330 if( ! event.touches.length ) 331 { 332 return; 333 } 334 335 event.preventDefault(); 336 event.stopPropagation(); 337 338 if( event.explicitOriginalTarget ) 339 { 340 // pass click event to button when visible !!! 341 if( event.explicitOriginalTarget.classList.contains( 'av-img-diff-label' ) ) 342 { 343 let opacity = window.getComputedStyle( event.explicitOriginalTarget ).getPropertyValue( 'opacity' ); 344 345 if( opacity > 0 ) 346 { 347 event.explicitOriginalTarget.dispatchEvent( new MouseEvent( 'click' ) ); 348 return; 349 } 350 } 351 } 352 353 this.touchCapture = true; 354 this.container.classList.add( 'av-active-drag' ); 355 356 this.downScreenX = event.touches[0].screenX; 357 this.downScreenY = event.touches[0].screenY; 358 this.downClientX = event.touches[0].clientX; 359 this.downClientY = event.touches[0].clientY; 360 361 if( this.divider == 'horizontal' ) 362 { 363 this.downHandlePos = this.handle.style.top; 364 } 365 else 366 { 367 this.downHandlePos = this.handle.style.left; 368 } 369 370 this.downHandlePos = parseInt( this.downHandlePos.replace( 'px', '' ) ); 371 } 372 373 onTouchMove( event ) 374 { 375 if( ! this.touchCapture ) 376 { 377 return; 378 } 379 380 event.preventDefault(); 381 event.stopPropagation(); 382 383 let newPos = 0, 384 diff = 0; 385 386 if( this.divider == 'horizontal' ) 387 { 388 diff = event.touches[0].screenY - this.downScreenY; 389 } 390 else 391 { 392 diff = event.touches[0].screenX - this.downScreenX; 393 } 394 395 if( Math.abs( diff ) < 5 ) 396 { 397 return; 398 } 399 400 newPos = this.downHandlePos + diff; 401 402 this.adjustDividerFrame( newPos ); 403 this.touchMoved = true; 404 } 405 406 onTouchEnd( event ) 407 { 408 if( ! this.touchCapture ) 409 { 410 return; 411 } 412 413 if( ! this.touchMoved ) 414 { 415 let newPos = 0, 416 maxCheck = 0, 417 rect = this.wrapperDiv[0].getBoundingClientRect(); 418 419 if( this.divider == 'horizontal' ) 420 { 421 newPos = this.downClientY - rect.top; 422 maxCheck = rect.height; 423 } 424 else 425 { 426 newPos = this.downClientX - rect.left; 427 maxCheck = rect.width; 428 } 429 430 if( newPos < 0 ) 431 { 432 newPos = 0; 433 } 434 else if( newPos > maxCheck ) 435 { 436 newPos = maxCheck; 437 } 438 439 this.adjustDividerFrame( newPos ); 440 } 441 442 event.preventDefault(); 443 event.stopPropagation(); 444 445 this.touchCapture = false;
446 this.touchMoved = false; 447 this.container.classList.remove( 'av-active-drag' ); 448 } 449 450 onResize( event ) 451 { 452 let lastPos = 0, 453 lastDim = 0; 454 455 if( this.divider == 'horizontal' ) 456 { 457 lastPos = this.handle.style.top; 458 lastDim = this.imgDimension.height; 459 } 460 else 461 { 462 lastPos = this.handle.style.left; 463 lastDim = this.imgDimension.width; 464 } 465 466 lastPos = parseInt( lastPos.replace( 'px', '' ) ); 467 468 if( lastPos < 0 ) 469 { 470 lastDim = 0; 471 } 472 else if( lastDim != 0 ) 473 { 474 lastDim = Math.round( ( lastPos / lastDim ) * 100.0 ); 475 } 476 477 if( lastDim > 100 ) 478 { 479 lastDim = 100; 480 } 481 482 this.settings.drag_start = lastDim; 483 484 this.imgBefore[0].style['clip-path'] = 'inset( 0 0 0 0 )'; 485 this.imgAfter[0].style['clip-path'] = 'inset( 0 0 0 0 )'; 486 487 this.initialPositionHandler(); 488 } 489 490 onHandleClick( event ) 491 { 492 // needed to prevent jumping around after mouse move events 493 event.preventDefault(); 494 event.stopPropagation(); 495 } 496 497 onClickBtnBefore( event ) 498 { 499 event.preventDefault(); 500 event.stopPropagation(); 501 502 this.adjustDividerFrame( 0 ); 503 } 504 505 onClickBtnAfter( event ) 506 { 507 event.preventDefault(); 508 event.stopPropagation(); 509 510 let newPos = 0; 511 512 if( this.divider == 'horizontal' ) 513 { 514 newPos = this.imgDimension.height; 515 } 516 else 517 { 518 newPos = this.imgDimension.width; 519 } 520 521 this.adjustDividerFrame( newPos + 15 ); 522 } 523 524 onClickWrapper( event ) 525 { 526 event.preventDefault(); 527 event.stopPropagation(); 528 529 let newPos = 0; 530 531 if( this.divider == 'horizontal' ) 532 { 533 newPos = event.layerY; 534 } 535 else 536 { 537 newPos = event.layerX; 538 } 539 540 this.adjustDividerFrame( newPos ); 541 } 542 543 } 544 545 // class factory 546 avia_js_shortcodes.aviaImageDiff = function( container ) 547 { 548 return new scAviaImageDiff( container ); 549 }; 550 551 aviaJS.aviaPlugins.register( avia_js_shortcodes.aviaImageDiff, '.avia-image-diff-container' ); 552 } 553 554})(); 555
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.