| | |
| | | window.jvbGallery=class{constructor(e,t){this.imageWrapper=t.imageWrapper??null,this.container=t.container?document.querySelector(t.container):document.querySelector("main"),this.modal=new window.jvbModal(e,{onOpen:!1,onSave:!1,onClose:()=>this.closeGallery(!1)}),this.items=this.getGalleryItems()||[],this.loadMore=t.loadMore??!1,this.modalElement="string"==typeof e?document.querySelector(e)??!1:e,this.modal&&(this.a11y=window.jvbA11y,this.openWhenReady=!1,this.initElements(),this.imageWrapper="string"==typeof this.imageWrapper?this.imageWrapper:"."+this.imageWrapper.classList.join("."),this.index=0,this.swipe={touchStart:null,touchEnd:null,minSwipe:50},this.isLoading=!1)}initElements(){this.prevBtn=this.modalElement.querySelector(".prev"),this.nextBtn=this.modalElement.querySelector(".next"),this.favourite=this.modalElement.querySelector(".favourite"),this.image=this.modalElement.querySelector(".image"),this.counter=this.modalElement.querySelector(".counter"),this.extra=this.modalElement.querySelector(".item-info"),this.imageWrapper||(this.favourite.remove(),this.extra.remove())}getGalleryItems(){let e=this.imageWrapper?this.imageWrapper:"img";return Array.from(this.container.querySelectorAll(e)).map((e=>{const t=this.imageWrapper?e.querySelector("img"):e;return t?{id:this.imageWrapper?e.querySelector("button.favourite").dataset.id:"",small:t.dataset.small||t.src,large:t.dataset.large||t.src,full:t.dataset.full||t.src,alt:t.alt||"",fav:this.imageWrapper?e.querySelector("button.favourite")?.cloneNode(!0):"",info:this.imageWrapper?e.querySelector(".item-info")?.cloneNode(!0):""}:null})).filter(Boolean)}initListeners(){this.container.addEventListener("click",this.handleClick.bind(this)),document.addEventListener("keydown",this.handleKeys.bind(this)),document.addEventListener("touchstart",this.handleTouchStart.bind(this)),document.addEventListener("touchend",this.handleTouchEnd.bind(this)),document.addEventListener("touchmove",this.handleTouchMove.bind(this))}destroyListeners(){this.container.removeEventListener("click",this.handleClick.bind(this)),document.removeEventListener("keydown",this.handleKeys.bind(this)),document.removeEventListener("touchstart",this.handleTouchStart.bind(this)),document.removeEventListener("touchend",this.handleTouchEnd.bind(this)),document.removeEventListener("touchmove",this.handleTouchMove.bind(this))}handleKeys(e){switch(e.key){case"ArrowLeft":this.navigate(-1);break;case"ArrowRight":this.navigate(1)}}handleTouchStart(e){this.swipe.touchStart=e.touches[0].clientX}handleTouchMove(e){this.swipe.touchEnd=e.touches[0].clientX}handleTouchEnd(e){if(!this.swipe.touchStart||!this.swipe.touchEnd)return;const t=this.swipe.touchStart-this.swipe.touchEnd,i=t>this.swipe.minSwipe,s=t<-this.swipe.minSwipe;i?this.navigate(1):s&&this.navigate(-1),this.swipe.touchStart=null,this.swipe.touchEnd=null}handleClick(e){window.targetCheck(e,".feed-images")&&this.handleGalleryOpen(e),window.targetCheck(e,".nav")&&(window.targetCheck(e,".next")?this.navigate(1):this.navigate(-1)),window.targetCheck(e,"button.cancel")&&this.closeGallery()}async navigate(e){let t=this.index+e;(t<0||t>=this.items.length)&&(this.a11y.announceNavigation(t,this.items.length,e<0,e>0),t=t<0?this.items.length-1:0),this.index=t,this.updateDisplay(),this.preloadImages(),this.a11y.announceNavigation(this.index,this.items.length),"function"==typeof this.loadMore&&e>0&&t>=this.items.length-3&&window.feedBlock.hasMore&&(await this.loadMore(),this.updateGalleryItems(this.getGalleryItems()))}updateGalleryItems(e){const t=this.items[this.index];if(this.items=e,t){const e=this.items.findIndex((e=>e.full===t.full||e.large===t.large));-1!==e&&(this.index=e)}if(this.updateNavigationButtons(),this.items.length>0&&this.openWhenReady){let e=this.findIndex("id",this.openWhenReady);this.openGallery(e)}}preloadImages(){[-1,0,1].forEach((e=>{const t=this.index+e;if(t>=0&&t<this.items.length){const e=new Image,i=this.items[t];window.innerWidth<1e3?e.src=i.large||i.src:e.src=i.full||i.src}}))}updateDisplay(){const e=this.items[this.index];e&&([this.image.src,this.image.alt,this.counter.textContent]=[window.innerWidth<1e3?e.large||e.src:e.full||e.src,e.alt||"",`${this.index+1} / ${this.items.length}`],this.imageWrapper&&(e.fav&&(window.removeChildren(this.favourite),this.favourite.appendChild(e.fav.cloneNode(!0))),e.info&&(window.removeChildren(this.extra),this.extra.appendChild(e.info.cloneNode(!0)))),this.updateNavigationButtons())}updateNavigationButtons(){this.prevBtn.classList.toggle("end",this.index>0?"":"none"),this.nextBtn.classList.toggle("end",this.index<this.items.length-1?"":"none")}handleGalleryOpen(e){let t=this.imageWrapper?e.target.closest(this.imageWrapper):e.target.closest("img"),i=this.imageWrapper?"id":"small",s=t.dataset[i],n=this.findIndex(i,s);this.openGallery(n)}findIndex(e,t){return this.items.findIndex((i=>i[e]===t))}openGallery(e){this.initListeners(),this.index=e,this.modal.handleOpen(),this.updateDisplay(),this.preloadImages(),this.a11y.announce(`Image ${this.index+1} of ${this.items.length}. Use arrow keys to navigate.`)}closeGallery(e=!0){this.destroyListeners(),e&&this.modal.handleClose()}}; |
| | | (()=>{class e{constructor(){this.a11y=window.jvbA11y,this.index=0,this.images=[],this.zoom={scale:1,min:1,max:4,threshold:50,x:0,y:0,startX:0,startY:0,ease:.2,panning:!1},this.swipe=this.resetSwipe(),this.activePointers=new Map,this.lastTap=0,this.initElements(),this.initModal(),this.initListeners(),this.initSubscribers(),console.log("Gallery loaded...")}initElements(){this.elements={imageSelector:"img[data-gallery]",gallery:{modal:"dialog.gallery",wrap:".wrap",nextButton:".next",prevButton:".prev",image:".image",leftImage:".image-left",rightImage:".image-right",counter:".counter"}},this.ui=window.uiFromSelectors(this.elements)}initModal(){this.modal=new window.jvbModal(this.ui.gallery.modal,{openMessage:"Opened Gallery",closeMessage:"Closed Gallery"}),this.modal.subscribe(e=>{"modal-close"===e&&this.toggleGallery(!1)})}buildGalleryItems(e=null){let t=e?`[data-gallery="${e}"]`:this.elements.imageSelector;this.items=Array.from(document.querySelectorAll(t)).map((e,t)=>({id:e.dataset.id||t,srcset:e.srcset||e.src,sizes:e.sizes||"100vw",src:e.currentSrc||e.src,full:e.dataset.full||e.src,alt:e.alt||"",element:e}))}initListeners(){this.clickHandler=this.handleClick.bind(this),this.pointerDownHandler=this.onPointerDown.bind(this),this.pointerMoveHandler=this.onPointerMove.bind(this),this.pointerUpHandler=this.onPointerUp.bind(this),this.wheelHandler=this.onWheel.bind(this),this.keyHandler=this.handleKeys.bind(this),document.addEventListener("click",this.clickHandler)}handleClick(e){let t=window.targetCheck(e,this.elements.imageSelector);t&&!this.modal.isOpen?(e.preventDefault(),this.buildGalleryItems(t.dataset.gallery||null),this.index=this.items.findIndex(e=>e.element===t),this.toggleGallery(!0)):this.modal.isOpen&&(window.targetCheck(e,this.elements.gallery.nextButton)?(console.log("Next"),this.nextElement()):window.targetCheck(e,this.elements.gallery.prevButton)&&(console.log("Previous"),this.prevElement()))}handleKeys(e){if(this.modal.isOpen){switch(e.key){case"ArrowLeft":e.preventDefault(),this.prevElement();break;case"ArrowRight":e.preventDefault(),this.nextElement()}e.ctrlKey&&("+"!==e.key&&"="!==e.key||(e.preventDefault(),this.handleZoom(.2)),"-"===e.key&&(e.preventDefault(),this.handleZoom(-.2)),"0"===e.key&&(e.preventDefault(),this.resetZoom()))}}onPointerDown(e){e.preventDefault(),this.swipe.startX=e.clientX,this.swipe.startY=e.clientY,this.ui.gallery.image.setPointerCapture(e.pointerId),this.activePointers.set(e.pointerId,{x:e.clientX,y:e.clientY});const t=performance.now();if(t-this.lastTap<300&&1===this.activePointers.size)return this.zoom.scale>1?this.resetZoom():this.handleZoom(1,e.clientX,e.clientY),void(this.lastTap=0);if(this.lastTap=t,2===this.activePointers.size){const e=[...this.activePointers.values()];return this.pinchStartDist=Math.hypot(e[0].x-e[1].x,e[0].y-e[1].y),void(this.pinchStartScale=this.zoom.scale)}this.zoom.scale>1&&(this.zoom.panning=!0,this.zoom.startX=e.clientX-this.zoom.x,this.zoom.startY=e.clientY-this.zoom.y,this.ui.gallery.image.style.cursor="grabbing")}onPointerMove(e){if(this.activePointers.has(e.pointerId)){if(this.activePointers.set(e.pointerId,{x:e.clientX,y:e.clientY}),2===this.activePointers.size){const e=[...this.activePointers.values()],t=Math.hypot(e[0].x-e[1].x,e[0].y-e[1].y),i=this.pinchStartScale*(t/this.pinchStartDist)-this.zoom.scale,s=(e[0].x+e[1].x)/2,n=(e[0].y+e[1].y)/2;return void this.handleZoom(i,s,n)}this.zoom.panning&&(this.zoom.x=e.clientX-this.zoom.startX,this.zoom.y=e.clientY-this.zoom.startY,this.applyTransform())}}onPointerUp(e){const t=this.activePointers.get(e.pointerId);if(this.activePointers.delete(e.pointerId),this.activePointers.size<2&&(this.pinchStartDist=0),this.zoom.scale<=1&&!this.zoom.panning&&0===this.activePointers.size){const i=t?.x??e.clientX,s=t?.y??e.clientY,n=i-this.swipe.startX,o=s-this.swipe.startY;Math.abs(n)>this.zoom.threshold&&Math.abs(n)>Math.abs(o)&&(n>0?this.prevElement():this.nextElement())}0===this.activePointers.size&&(this.zoom.panning=!1,this.ui.gallery.image.style.cursor=this.zoom.scale>1?"grab":"default")}onWheel(e){if(!e.ctrlKey)return;e.preventDefault();const t=e.deltaY<0?.2:-.2;this.handleZoom(t,e.clientX,e.clientY)}handleZoom(e,t=null,i=null){const s=this.zoom.scale;let n=s+e;if(n=Math.min(this.zoom.max,Math.max(this.zoom.min,n)),n===s)return;const o=n/s;let l=this.ui.gallery.image.getBoundingClientRect();null!==t&&null!==i||(t=l.left+l.width/2,i=l.top+l.height/2);const r=t-l.left,a=i-l.top;this.zoom.x=(this.zoom.x-r)*o+r,this.zoom.y=(this.zoom.y-a)*o+a,this.zoom.scale=n,this.applyTransform(),this.notify("zoom",{scale:this.zoom.scale})}applyTransform(){this.clampPan();const e=this.ui.gallery.image;e.style.transform=`translate(${this.zoom.x}px, ${this.zoom.y}px) scale(${this.zoom.scale})`,e.style.cursor=this.zoom.scale>1?"grab":"default"}clampPan(){const e=this.ui.gallery.image,t=Math.max(0,(e.offsetWidth*this.zoom.scale-window.innerWidth)/2),i=Math.max(0,(e.offsetHeight*this.zoom.scale-window.innerHeight)/2);this.zoom.x=Math.max(-t,Math.min(t,this.zoom.x)),this.zoom.y=Math.max(-i,Math.min(i,this.zoom.y))}resetZoom(){this.zoom.scale=1,this.zoom.x=0,this.zoom.y=0,this.zoom.startX=0,this.zoom.startY=0,this.zoom.panning=!1,this.applyTransform()}resetSwipe(){return{startX:null,startY:null,endX:null,endY:null}}toggleGallery(e){e?(this.ui.gallery.image.draggable=!1,this.ui.gallery.image.style.userSelect="none",this.ui.gallery.image.addEventListener("pointerdown",this.pointerDownHandler),this.ui.gallery.image.addEventListener("pointermove",this.pointerMoveHandler),this.ui.gallery.image.addEventListener("pointerup",this.pointerUpHandler),this.ui.gallery.image.addEventListener("pointercancel",this.pointerUpHandler),window.addEventListener("wheel",this.wheelHandler,{passive:!1}),window.addEventListener("keydown",this.keyHandler),this.moveIntoView()):(this.ui.gallery.image.removeEventListener("pointerdown",this.pointerDownHandler),this.ui.gallery.image.removeEventListener("pointermove",this.pointerMoveHandler),this.ui.gallery.image.removeEventListener("pointerup",this.pointerUpHandler),this.ui.gallery.image.removeEventListener("pointercancel",this.pointerUpHandler),window.removeEventListener("wheel",this.wheelHandler),window.removeEventListener("keydown",this.keyHandler),this.resetZoom(),this.resetSwipe(),this.activePointers.clear(),this.lastTap=0),e&&!this.modal.isOpen&&this.modal.handleOpen()}moveIntoView(e=0){let t=this.index+e;t<0?t=this.items.length-1:t>=this.items.length?t=0:t===this.items.length-3&&this.notify("load-more"),this.index=t,this.updateDisplay(),this.preloadAdjacent(),this.a11y.announce(`Image ${this.index+1} of ${this.items.length}`)}nextElement(){this.resetZoom(),this.moveIntoView(1)}prevElement(){this.resetZoom(),this.moveIntoView(-1)}updateDisplay(){const e=this.items[this.index];if(!e)return;const t=this.ui.gallery.image;if(e.srcset&&(t.srcset=e.srcset,t.sizes=e.sizes),t.src=e.src,t.alt=e.alt,e.full&&e.full!==e.src){const i=new Image;i.onload=()=>{this.items[this.index]===e&&(t.src=e.full,t.removeAttribute("srcset"),t.removeAttribute("sizes"))},i.src=e.full}this.ui.gallery.counter.textContent=`${this.index+1} / ${this.items.length}`,this.ui.gallery.prevButton.disabled=this.items.length<=1,this.ui.gallery.nextButton.disabled=this.items.length<=1}preloadAdjacent(){[-1,1].forEach(e=>{const t=this.index+e;if(t>0&&t<this.items.length){const i=this.items[t];(e<0?this.ui.gallery.leftImage:this.ui.gallery.rightImage).src=i.full}})}initSubscribers(){this.subscribers=new Set}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(e,t={}){this.subscribers.forEach(i=>{try{i(e,t)}catch(e){console.error("Subscriber error:",e)}})}destroy(){this.subscribers.clear(),this.toggleGallery(!1),document.removeEventListener("click",this.clickHandler)}}document.addEventListener("DOMContentLoaded",function(){document.querySelector("dialog.gallery")&&(window.jvbGallery=new e)})})(); |