"use strict()"; export class SphinxGalleria { constructor(target, options, data) { var self = this; self.target = target; self.options = options; self.data = data; self.oneimage = self.data.length === 1; self.swipe_delay = 1500; self.touch_data = { id: -1, x: null, y: null, current_x: null, current_y: null, interval: null, swiped: false, noclick: false }; self.node_target = null; self.node_figure = document.createElement('figure'); self.button_modal = document.createElement('button'); self.button_modal.setAttribute('aria-haspopup', 'dialog'); self.button_modal.classList.add('button-modal'); self.node_image = document.createElement('img'); self.node_caption = document.createElement('figcaption'); self.node_alt = document.createElement('p'); self.node_alt.setAttribute('id', self.target+'-'+'alt'); self.node_image.setAttribute('aria-labelledby', self.target+'-'+'alt'); self.node_thumbnails = document.createElement('ul'); self.node_thumbnails.classList.add('thumbnails'); self.node_dialog = document.createElement('dialog'); self.node_mask = document.createElement('div'); self.node_mask.classList.add('mask'); self.node_mask.hidden = true; self.node_mask.setAttribute('aria-hidden', true); var node_submask = document.createElement('div'); node_submask.classList.add('submask'); self.node_div_caption = document.createElement('div'); self.node_div_caption.classList.add('caption'); var figure_row = document.createElement('div'); figure_row.classList.add('row'); self.dialog_button_close_icon = document.createElement('button'); self.dialog_button_close_icon.setAttribute('aria-label', self.options.label_close); self.dialog_image = document.createElement('img'); self.dialog_image.setAttribute('aria-labelledby', self.target+'-'+'alt'); self.dialog_title = document.createElement('h1'); var dialog_header = document.createElement('header'); var dialog_menu = document.createElement('menu'); if(self.oneimage) { self.node_thumbnails.hidden = true; self.node_thumbnails.setAttribute('aria-hidden', true); self.node_thumbnails.style.display = 'none'; } else { self.node_slider = document.createElement('input'); self.node_slider.setAttribute('type', 'range'); self.node_slider.setAttribute('min', 1); self.node_slider.setAttribute('max', self.data.length); self.node_slider.setAttribute('value', 1); self.button_prev = document.createElement('button'); self.button_prev.classList.add('prev'); self.button_prev.setAttribute('aria-label', self.options.label_prev); self.button_next = document.createElement('button'); self.button_next.classList.add('next'); self.button_next.setAttribute('aria-label', self.options.label_next); self.dialog_button_prev = document.createElement('button'); self.dialog_button_prev.classList.add('prev'); self.dialog_button_next = document.createElement('button'); self.dialog_button_next.classList.add('next'); self.dialog_button_prev.appendChild(document.createTextNode(self.options.label_prev)); self.dialog_button_next.appendChild(document.createTextNode(self.options.label_next)); figure_row.appendChild(self.button_prev); dialog_menu.appendChild(self.dialog_button_prev); dialog_menu.appendChild(self.dialog_button_next); } node_submask.appendChild(self.node_dialog); self.node_mask.appendChild(node_submask); figure_row.appendChild(self.button_modal); self.node_figure.appendChild(figure_row); self.node_div_caption.appendChild(self.node_caption); self.node_div_caption.appendChild(self.node_alt); self.button_modal.appendChild(self.node_image); self.button_modal.appendChild(self.node_div_caption); dialog_header.appendChild(self.dialog_title); dialog_header.appendChild(self.dialog_button_close_icon); self.node_dialog.appendChild(dialog_header); self.node_dialog.appendChild(self.dialog_image); self.node_dialog.appendChild(dialog_menu); if(!self.oneimage) { figure_row.appendChild(self.button_next); self.node_figure.appendChild(self.node_slider); } } init() { var self = this; self.node_target = document.getElementById(self.target); if(self.options.no_transition || self.oneimage) { if(!self.node_target.classList.contains('no-transition')) { self.node_target.classList.add('no-transition'); } } self.node_target.innerHTML = ''; self.node_target.classList.add("sphinxgalleria-core"); self.node_target.appendChild(self.node_figure); self.node_target.appendChild(self.node_thumbnails); self.node_target.appendChild(self.node_mask); var onmodal = function(ev) { if(self.touch_data.noclick) { self.touch_data.noclick = false; ev.preventDefault(); return; } var key = ev.key; if(ev.type==='keypress' && key!==" " && key!=="Enter") { return; } ev.preventDefault(); self.showModal(); }; self.button_modal.addEventListener('click', onmodal); self.button_modal.addEventListener('keypress', onmodal); var onclose = function(ev) { if(self.touch_data.noclick) { self.touch_data.noclick = false; ev.preventDefault(); return; } var key = ev.key; if(ev.type==='keypress' && key!==" " && key!=="Enter") { return; } ev.preventDefault(); self.closeModal(); }; self.node_mask.addEventListener('click', onclose); self.node_dialog.addEventListener('click', function(ev) {ev.stopPropagation();}); self.dialog_button_close_icon.addEventListener('click', onclose); self.dialog_button_close_icon.addEventListener('keypress', onclose); if(!self.oneimage) { if(self.options.timer){ setInterval(function(){ self.next(); }, self.options.timer*1000); } var startSwipe = function(ev) {self.startSwipe(ev);}; var moveSwipe = function(ev) {self.moveSwipe(ev);}; var endSwipe = function(ev) {self.endSwipe(ev);}; self.node_mask.addEventListener('touchstart', startSwipe, true); self.node_mask.addEventListener('touchmove', moveSwipe, true); self.node_mask.addEventListener('touchend', endSwipe, true); self.node_target.addEventListener('touchstart', startSwipe, true); self.node_target.addEventListener('touchmove', moveSwipe); self.node_target.addEventListener('touchend', endSwipe, true); self.node_image.addEventListener('touchstart', startSwipe, true); self.node_image.addEventListener('touchmove', moveSwipe); self.node_image.addEventListener('touchend', endSwipe, true); self.dialog_image.addEventListener('touchstart', startSwipe, true); self.dialog_image.addEventListener('touchmove', moveSwipe); self.dialog_image.addEventListener('touchend', endSwipe, true); self.node_mask.addEventListener('mousedown', startSwipe, true); self.node_mask.addEventListener('mousemove', moveSwipe, true); self.node_mask.addEventListener('mouseup', endSwipe, true); self.node_target.addEventListener('mousedown', startSwipe, true); self.node_target.addEventListener('mousemove', moveSwipe, true); self.node_target.addEventListener('mouseup', endSwipe, true); self.node_image.addEventListener('mousedown', startSwipe, true); self.node_image.addEventListener('mousemove', moveSwipe, true); self.node_image.addEventListener('mouseup', endSwipe, true); self.dialog_image.addEventListener('mousedown', startSwipe, true); self.dialog_image.addEventListener('mousemove', moveSwipe, true); self.dialog_image.addEventListener('mouseup', endSwipe, true); var removeClick = function(ev) { if(self.touch_data.noclick) { self.touch_data.noclick = false; ev.preventDefault(); ev.stopImmediatePropagation(); } }; self.node_mask.addEventListener('click', removeClick, true); self.node_target.addEventListener('click', removeClick, true); var onprev = function(ev) { var key = ev.key; if(ev.type==='keypress' && key!==" " && key!=="Enter") { return; } ev.preventDefault(); self.prev(); }; var onnext = function(ev) { var key = ev.key; if(ev.type==='keypress' && key!==" " && key!=="Enter") { return; } ev.preventDefault(); self.next(); }; self.button_prev.addEventListener('keypress', onprev); self.button_prev.addEventListener('click', onprev); self.button_next.addEventListener('keypress', onnext); self.button_next.addEventListener('click', onnext); self.dialog_button_prev.addEventListener('keypress', onprev); self.dialog_button_prev.addEventListener('click', onprev); self.dialog_button_next.addEventListener('keypress', onnext); self.dialog_button_next.addEventListener('click', onnext); self.dialog_image.addEventListener('click', function(ev) { if(self.touch_data.noclick) { self.touch_data.noclick = false; ev.preventDefault(); return; } var x = ev.layerX - ev.target.x; if(x < ev.target.width/2) { self.prev(); ev.preventDefault(); } else if(x > ev.target.width/2) { self.next(); ev.preventDefault(); } }); self.node_slider.addEventListener('change', function() { var idx = self.node_slider.value - 1; self.node_thumbnails.querySelector('input[data-index="'+idx+'"]').click(); }); } self.data.forEach(function(image_data, idx) { var image_element = document.createElement('li'); var image_button = document.createElement('input'); image_button.setAttribute('type', 'radio'); image_button.setAttribute('value', image_data.path); image_button.setAttribute('name', self.target); image_button.setAttribute('data-index', idx); image_button.setAttribute('id', self.target+'-'+idx); if(idx===0) { image_button.checked = true; } image_element.appendChild(image_button); var image_label = document.createElement('label'); image_label.setAttribute('for', self.target+'-'+idx); image_element.appendChild(image_label); var image_thumb = document.createElement('img'); image_thumb.setAttribute('src', image_data.thumb); image_thumb.setAttribute('width', image_data.thumbsize[0]); image_thumb.setAttribute('heigh', image_data.thumbsize[1]); if(image_data.alt) { image_button.setAttribute('data-alt', image_data.alt); image_thumb.setAttribute('alt', image_data.alt); } else { image_thumb.setAttribute('alt', self.options.label_thumbnail); } if(image_data.title) { image_button.setAttribute('data-title', image_data.title); } if(image_data.hide_alt) { image_button.setAttribute('data-hide-alt', true); } if(image_data.hide_alt) { image_button.setAttribute('data-hide-title', true); } image_label.appendChild(image_thumb); self.node_thumbnails.appendChild(image_element); image_button.addEventListener('change', function() {self.changeImage();}); }); document.addEventListener('keydown', function(ev) { var key = ev.key; if(!self.node_dialog.open && !self.node_target.contains(document.activeElement)) { return; } if(!self.oneimage && key==="ArrowLeft") { self.prev(); ev.preventDefault(); } else if(!self.oneimage && key==="ArrowRight") { self.next(); ev.preventDefault(); } else if(key==="Escape") { self.closeModal(); ev.preventDefault(); } }); if(self.node_dialog.showModal) { self.node_dialog.addEventListener('close', function() { self.closeModal(); }); } self.changeImage(); } prev() { var self = this; if(!self.oneimage) { var idx = self.node_thumbnails.querySelector('input:checked').getAttribute('data-index'); idx = parseInt(idx) - 1; if(idx < 0) { idx = self.data.length - 1; } document.getElementById(self.target+'-'+idx).checked = true; self.changeImage(); } } next() { var self = this; if(!self.oneimage) { var idx = self.node_thumbnails.querySelector('input:checked').getAttribute('data-index'); idx = parseInt(idx) + 1; if(idx > self.data.length - 1) { idx = 0; } document.getElementById(self.target+'-'+idx).checked = true; self.changeImage(); } } changeImage() { var self = this; var current = self.node_thumbnails.querySelector('input:checked'); var title = current.getAttribute('data-title'); var alt = current.getAttribute('data-alt'); var hide_title = current.hasAttribute('data-hide-title'); var hide_alt = current.hasAttribute('data-hide-alt'); var url = current.getAttribute('value'); var hide_caption = true; var idx = parseInt(current.getAttribute('data-index')); if(!self.options.no_transition && !self.oneimage) { self.node_image.style.opacity = 0.2; self.dialog_image.style.opacity = 0.2; } if(!self.oneimage) { if(self.node_slider.value !== idx+1) { self.node_slider.value = idx + 1; } var current_img = current.nextSibling.childNodes[0]; var offset = current_img.offsetLeft - self.node_thumbnails.offsetLeft; offset -= self.node_thumbnails.offsetWidth / 2; offset += current_img.offsetWidth / 2; self.node_thumbnails.scrollTo({ left: offset, behavior: 'smooth', }); } if(!hide_title && title) { self.node_caption.innerHTML = title; self.node_caption.hidden = false; self.dialog_title.innerHTML = title; self.dialog_title.hidden = false; self.dialog_title.removeAttribute('aria-hidden'); hide_caption = false; } else if(title) { self.node_caption.innerHTML = ''; self.node_caption.hidden = true; self.dialog_title.innerHTML = title; self.dialog_title.hidden = false; self.dialog_title.removeAttribute('aria-hidden'); } else { self.node_caption.innerHTML = ''; self.node_caption.hidden = true; self.dialog_title.innerHTML = ''; self.dialog_title.hidden = true; self.dialog_title.setAttribute('aria-hidden', true); } if(!hide_alt && alt) { self.node_alt.innerHTML = alt; self.node_alt.hidden = false; hide_caption = false; } else { self.node_alt.innerHTML = ''; self.node_alt.hidden = true; } if(hide_caption) { self.node_div_caption.hidden = true; } else { self.node_div_caption.hidden = false; } if(self.options.no_transition || self.oneimage) { self.node_image.setAttribute('src', url); self.dialog_image.setAttribute('src', url); } else { setTimeout(function() { self.node_image.setAttribute('src', url); self.dialog_image.setAttribute('src', url); setTimeout(function() { self.node_image.style.opacity = 1; self.dialog_image.style.opacity = 1; }, 200); }, 200); } } showModal() { this.node_mask.hidden = false; this.node_mask.removeAttribute('aria-hidden'); if(this.node_dialog.showModal) { this.node_dialog.showModal(); } else { this.node_dialog.open = true; this.node_dialog.setAttribute('open', true); this.node_dialog.setAttribute('aria-modal', true); this.node_dialog.hidden = false; this.node_dialog.removeAttribute('aria-hidden'); } } closeModal() { if(this.node_dialog.showModal) { this.node_dialog.close(); } else { this.node_dialog.open = false; this.node_dialog.removeAttribute('open'); this.node_dialog.removeAttribute('aria-modal'); this.node_dialog.hidden = true; this.node_dialog.setAttribute('aria-hidden', true); } this.node_mask.hidden = true; this.node_mask.setAttribute('aria-hidden', true); } startSwipe(ev) { var self = this; if(!self.oneimage && self.touch_data.id === -1) { ev.preventDefault(); if(ev.type === 'touchstart') { self.touch_data.id = ev.changedTouches[0].identifier; self.touch_data.x = ev.changedTouches[0].clientX; self.touch_data.y = ev.changedTouches[1].clientY; } else { self.touch_data.id = -2; self.touch_data.x = ev.clientX; self.touch_data.y = ev.clientY; } self.touch_data.current_x = self.touch_data.x; self.touch_data.current_y = self.touch_data.y; if(!self.touch_data.interval) { self.touch_data.interval = setInterval(function() { self.swipeItem(); }, self.swipe_delay); } } } moveSwipe(ev) { var self = this; var move = false; if(!self.oneimage && self.touch_data.x) { ev.preventDefault(); if(ev.type === 'touchmove') { ev.changedTouches.forEach(function(touch) { if(touch.identifier === self.touch_data.id) { move = true; self.touch_data.current_x = touch.clientX; } }); } else if(ev.which > 0) { move = true; self.touch_data.current_x = ev.clientX; } } } endSwipe(ev) { var self = this; var stop = false; if(!self.oneimage && self.touch_data.x) { ev.preventDefault(); if(ev.type === "touchend") { ev.changedTouches.forEach(function(touch) { if(touch.identifier === self.touch_data.id) { stop = true; self.touch_data.current_x = touch.clientX; self.touch_data.current_y = touch.clientY; } }); } else { stop = true; self.touch_data.current_x = ev.clientX; self.touch_data.current_y = ev.clientY; } if(stop) { self.touch_data.id = -1; if(self.touch_data.interval) { clearInterval(self.touch_data.interval); self.touch_data.interval = null; } if(!self.touch_data.swiped) { self.swipeItem(); } self.touch_data.x = null; self.touch_data.y = null; self.touch_data.current_x = null; self.touch_data.current_y = null; self.touch_data.swiped = false; } } } swipeItem() { var self = this; var width = self.touch_data.current_x - self.touch_data.x; var height = self.touch_data.current_y - self.touch_data.y; if(Math.abs(width) > self.getMinWidthSwipe()) { if(width > 0) { self.next(true); self.touch_data.noclick = true; self.touch_data.swiped = true; } else { self.prev(true); self.touch_data.noclick = true; self.touch_data.swiped = true; } } else if(Math.abs(height) > self.node_mask.clientHeight/2) { self.closeModal(); self.touch_data.noclick = true; } } getMinWidthSwipe() { if(this.node_mask.hidden) { return this.node_image.clientWidth/2; } return this.dialog_image.clientWidth/2; } }