diff options
author | Jimmy Cai <github@jimmycai.com> | 2022-10-29 18:14:19 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-29 18:14:19 +0300 |
commit | b03390d237427a2b9cfee55949cb1da62f1a6856 (patch) | |
tree | fd7da57cfcebc07d16483f3e9c3d71aee3562138 /assets/ts/gallery.ts | |
parent | 8a597a5c9c861d2bce22a5e06c7667cd9c8e263a (diff) |
Revert "Merge branch 'canary' into master" (#712)
Revert "Merge branch 'canary' into master (#711)"
This reverts commit 8a597a5c9c861d2bce22a5e06c7667cd9c8e263a.
Diffstat (limited to 'assets/ts/gallery.ts')
-rw-r--r-- | assets/ts/gallery.ts | 240 |
1 files changed, 167 insertions, 73 deletions
diff --git a/assets/ts/gallery.ts b/assets/ts/gallery.ts index e0124d1..9840f1e 100644 --- a/assets/ts/gallery.ts +++ b/assets/ts/gallery.ts @@ -1,92 +1,186 @@ -const wrap = (figures: HTMLElement[]) => { - const galleryContainer = document.createElement('div'); - galleryContainer.className = 'gallery'; +declare global { + interface Window { + PhotoSwipe: any; + PhotoSwipeUI_Default: any + } +} - const parentNode = figures[0].parentNode, - first = figures[0]; +interface PhotoSwipeItem { + w: number; + h: number; + src: string; + msrc: string; + title?: string; + el: HTMLElement; +} - parentNode.insertBefore(galleryContainer, first) +class StackGallery { + private galleryUID: number; + private items: PhotoSwipeItem[] = []; + + constructor(container: HTMLElement, galleryUID = 1) { + if (window.PhotoSwipe == undefined || window.PhotoSwipeUI_Default == undefined) { + console.error("PhotoSwipe lib not loaded."); + return; + } - for (const figure of figures) { - galleryContainer.appendChild(figure); + this.galleryUID = galleryUID; + + StackGallery.createGallery(container); + this.loadItems(container); + this.bindClick(); } -} -export default (container: HTMLElement) => { - /// The process of wrapping image with figure tag is done using JavaScript instead of only Hugo markdown render hook - /// because it can not detect whether image is being wrapped by a link or not - /// and it lead to a invalid HTML construction (<a><figure><img></figure></a>) - const images = container.querySelectorAll('img.gallery-image') as NodeListOf<HTMLImageElement>; - for (const img of Array.from(images)) { - /// Images are wrapped with figure tag if the paragraph has only images without texts - /// This is done to allow inline images within paragraphs - const paragraph = img.closest('p'); - - if (!paragraph || !container.contains(paragraph)) continue; - - if (paragraph.textContent.trim() == '') { - /// Once we insert figcaption, this check no longer works - /// So we add a class to paragraph to mark it - paragraph.classList.add('no-text'); + private loadItems(container: HTMLElement) { + this.items = []; + + const figures = container.querySelectorAll('figure.gallery-image'); + + for (const el of figures) { + const figcaption = el.querySelector('figcaption'), + img = el.querySelector('img'); + + let aux: PhotoSwipeItem = { + w: parseInt(img.getAttribute('width')), + h: parseInt(img.getAttribute('height')), + src: img.src, + msrc: img.getAttribute('data-thumb') || img.src, + el: el + } + + if (figcaption) { + aux.title = figcaption.innerHTML; + } + + this.items.push(aux); } + } + + public static createGallery(container: HTMLElement) { + /// The process of wrapping image with figure tag is done using JavaScript instead of only Hugo markdown render hook + /// because it can not detect whether image is being wrapped by a link or not + /// and it lead to a invalid HTML construction (<a><figure><img></figure></a>) + + const images = container.querySelectorAll('img.gallery-image'); + for (const img of Array.from(images)) { + /// Images are wrapped with figure tag if the paragraph has only images without texts + /// This is done to allow inline images within paragraphs + const paragraph = img.closest('p'); + + if (!paragraph || !container.contains(paragraph)) continue; + + if (paragraph.textContent.trim() == '') { + /// Once we insert figcaption, this check no longer works + /// So we add a class to paragraph to mark it + paragraph.classList.add('no-text'); + } + + let isNewLineImage = paragraph.classList.contains('no-text'); + if (!isNewLineImage) continue; - let isNewLineImage = paragraph.classList.contains('no-text'); - if (!isNewLineImage) continue; + const hasLink = img.parentElement.tagName == 'A'; - const hasLink = img.parentElement.tagName == 'A'; + let el: HTMLElement = img; + /// Wrap image with figure tag, with flex-grow and flex-basis values extracted from img's data attributes + const figure = document.createElement('figure'); + figure.style.setProperty('flex-grow', img.getAttribute('data-flex-grow') || '1'); + figure.style.setProperty('flex-basis', img.getAttribute('data-flex-basis') || '0'); + if (hasLink) { + /// Wrap <a> if it exists + el = img.parentElement; + } + el.parentElement.insertBefore(figure, el); + figure.appendChild(el); - let el: HTMLElement = img; - /// Wrap image with figure tag, with flex-grow and flex-basis values extracted from img's data attributes - const figure = document.createElement('figure'); - figure.style.setProperty('flex-grow', img.getAttribute('data-flex-grow') || '1'); - figure.style.setProperty('flex-basis', img.getAttribute('data-flex-basis') || '0'); - if (hasLink) { - /// Wrap <a> if it exists - el = img.parentElement; + /// Add figcaption if it exists + if (img.hasAttribute('alt')) { + const figcaption = document.createElement('figcaption'); + figcaption.innerText = img.getAttribute('alt'); + figure.appendChild(figcaption); + } + + /// Wrap img tag with <a> tag if image was not wrapped by <a> tag + if (!hasLink) { + figure.className = 'gallery-image'; + + const a = document.createElement('a'); + a.href = img.src; + a.setAttribute('target', '_blank'); + img.parentNode.insertBefore(a, img); + a.appendChild(img); + } } - el.parentElement.insertBefore(figure, el); - figure.appendChild(el); - - /// Add figcaption if it exists - if (img.hasAttribute('alt')) { - const figcaption = document.createElement('figcaption'); - figcaption.innerText = img.getAttribute('alt'); - figure.appendChild(figcaption); + + const figuresEl = container.querySelectorAll('figure.gallery-image'); + + let currentGallery = []; + + for (const figure of figuresEl) { + if (!currentGallery.length) { + /// First iteration + currentGallery = [figure]; + } + else if (figure.previousElementSibling === currentGallery[currentGallery.length - 1]) { + /// Adjacent figures + currentGallery.push(figure); + } + else if (currentGallery.length) { + /// End gallery + StackGallery.wrap(currentGallery); + currentGallery = [figure]; + } } - /// Wrap img tag with <a> tag if image was not wrapped by <a> tag - if (!hasLink) { - figure.className = 'gallery-image'; - - const a = document.createElement('a'); - a.href = img.src; - a.setAttribute('target', '_blank'); - a.setAttribute('data-pswp-width', img.width.toString()); - a.setAttribute('data-pswp-height', img.height.toString()); - img.parentNode.insertBefore(a, img); - a.appendChild(img); + if (currentGallery.length > 0) { + StackGallery.wrap(currentGallery); } } - const figuresEl = container.querySelectorAll('figure.gallery-image') as NodeListOf<HTMLElement>; - let currentGallery = []; - for (const figure of Array.from(figuresEl)) { - if (!currentGallery.length) { - /// First iteration - currentGallery = [figure]; - } - else if (figure.previousElementSibling === currentGallery[currentGallery.length - 1]) { - /// Adjacent figures - currentGallery.push(figure); - } - else if (currentGallery.length) { - /// End gallery - wrap(currentGallery); - currentGallery = [figure]; + /** + * Wrap adjacent figure tags with div.gallery + * @param figures + */ + public static wrap(figures: HTMLElement[]) { + const galleryContainer = document.createElement('div'); + galleryContainer.className = 'gallery'; + + const parentNode = figures[0].parentNode, + first = figures[0]; + + parentNode.insertBefore(galleryContainer, first) + + for (const figure of figures) { + galleryContainer.appendChild(figure); } } - if (currentGallery.length > 0) { - wrap(currentGallery); + public open(index: number) { + const pswp = document.querySelector('.pswp') as HTMLDivElement; + const ps = new window.PhotoSwipe(pswp, window.PhotoSwipeUI_Default, this.items, { + index: index, + galleryUID: this.galleryUID, + getThumbBoundsFn: (index) => { + const thumbnail = this.items[index].el.getElementsByTagName('img')[0], + pageYScroll = window.pageYOffset || document.documentElement.scrollTop, + rect = thumbnail.getBoundingClientRect(); + + return { x: rect.left, y: rect.top + pageYScroll, w: rect.width }; + } + }); + + ps.init(); } -};
\ No newline at end of file + + private bindClick() { + for (const [index, item] of this.items.entries()) { + const a = item.el.querySelector('a'); + + a.addEventListener('click', (e) => { + e.preventDefault(); + this.open(index); + }) + } + } +} + +export default StackGallery;
\ No newline at end of file |