mirror of
https://github.com/Sped0n/bridget.git
synced 2026-04-21 05:29:31 -07:00
refactor: better event listener cleanup (#279)
* refactor: change hires loader function name * feat: add loading transition animation and improve performance * refactor: refactor gallery creation and update functions * feat: create createDivWithClass utility function * feat: refactor abort signal handling in event listener and promise chain - Add functionality to set up an abort controller for cleanup - Add an event listener to abort the controller when necessary - Modify event listener to include the abort signal - Modify promise chain to include the abort signal
This commit is contained in:
@@ -344,6 +344,10 @@ function lores(imgs: DesktopImage[]): void {
|
|||||||
function setLoaderForHiresImage(e: HTMLImageElement): void {
|
function setLoaderForHiresImage(e: HTMLImageElement): void {
|
||||||
if (!e.complete) {
|
if (!e.complete) {
|
||||||
isLoading.set(true)
|
isLoading.set(true)
|
||||||
|
// abort controller for cleanup
|
||||||
|
const controller = new AbortController()
|
||||||
|
const abortSignal = controller.signal
|
||||||
|
// event listeners
|
||||||
e.addEventListener(
|
e.addEventListener(
|
||||||
'load',
|
'load',
|
||||||
() => {
|
() => {
|
||||||
@@ -355,8 +359,11 @@ function setLoaderForHiresImage(e: HTMLImageElement): void {
|
|||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
controller.abort()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
{ once: true, passive: true }
|
{ once: true, passive: true, signal: abortSignal }
|
||||||
)
|
)
|
||||||
e.addEventListener(
|
e.addEventListener(
|
||||||
'error',
|
'error',
|
||||||
@@ -369,8 +376,11 @@ function setLoaderForHiresImage(e: HTMLImageElement): void {
|
|||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
controller.abort()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
{ once: true, passive: true }
|
{ once: true, passive: true, signal: abortSignal }
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
_gsap
|
_gsap
|
||||||
|
|||||||
@@ -32,6 +32,13 @@ export function removeDuplicates<T>(arr: T[]): T[] {
|
|||||||
return [...new Set(arr)]
|
return [...new Set(arr)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createDivWithClass(className: string): HTMLDivElement {
|
||||||
|
const div = document.createElement('div')
|
||||||
|
if (className === '') return div // optimization
|
||||||
|
div.classList.add(className)
|
||||||
|
return div
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* custom "reactive" object
|
* custom "reactive" object
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { type Swiper } from 'swiper'
|
|||||||
|
|
||||||
import { container, scrollable } from '../container'
|
import { container, scrollable } from '../container'
|
||||||
import { isAnimating, navigateVector, setIndex, state } from '../globalState'
|
import { isAnimating, navigateVector, setIndex, state } from '../globalState'
|
||||||
import { expand, loadGsap, removeDuplicates } from '../globalUtils'
|
import { createDivWithClass, expand, loadGsap, removeDuplicates } from '../globalUtils'
|
||||||
import { type ImageJSON } from '../resources'
|
import { type ImageJSON } from '../resources'
|
||||||
|
|
||||||
import { mounted } from './state'
|
import { mounted } from './state'
|
||||||
@@ -14,9 +14,11 @@ import { capitalizeFirstLetter, loadSwiper, type MobileImage } from './utils'
|
|||||||
* variables
|
* variables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let swiperNode: HTMLDivElement
|
let galleryInner: HTMLDivElement
|
||||||
let gallery: HTMLDivElement
|
let gallery: HTMLDivElement
|
||||||
let curtain: HTMLDivElement
|
let curtain: HTMLDivElement
|
||||||
|
let indexDiv: HTMLDivElement
|
||||||
|
let navDiv: HTMLDivElement
|
||||||
let indexDispNums: HTMLSpanElement[] = []
|
let indexDispNums: HTMLSpanElement[] = []
|
||||||
let galleryImages: MobileImage[] = []
|
let galleryImages: MobileImage[] = []
|
||||||
let collectionImages: MobileImage[] = []
|
let collectionImages: MobileImage[] = []
|
||||||
@@ -89,14 +91,11 @@ function slideDown(): void {
|
|||||||
|
|
||||||
export function initGallery(ijs: ImageJSON[]): void {
|
export function initGallery(ijs: ImageJSON[]): void {
|
||||||
// create gallery
|
// create gallery
|
||||||
createGallery(ijs)
|
constructGallery(ijs)
|
||||||
// get elements
|
// get elements
|
||||||
indexDispNums = Array.from(
|
indexDispNums = Array.from(
|
||||||
document.getElementsByClassName('nav').item(0)?.getElementsByClassName('num') ?? []
|
indexDiv.getElementsByClassName('num') ?? []
|
||||||
) as HTMLSpanElement[]
|
) as HTMLSpanElement[]
|
||||||
swiperNode = document.getElementsByClassName('galleryInner').item(0) as HTMLDivElement
|
|
||||||
gallery = document.getElementsByClassName('gallery').item(0) as HTMLDivElement
|
|
||||||
curtain = document.getElementsByClassName('curtain').item(0) as HTMLDivElement
|
|
||||||
galleryImages = Array.from(gallery.getElementsByTagName('img')) as MobileImage[]
|
galleryImages = Array.from(gallery.getElementsByTagName('img')) as MobileImage[]
|
||||||
collectionImages = Array.from(
|
collectionImages = Array.from(
|
||||||
document
|
document
|
||||||
@@ -137,7 +136,7 @@ export function initGallery(ijs: ImageJSON[]): void {
|
|||||||
})
|
})
|
||||||
loadSwiper()
|
loadSwiper()
|
||||||
.then((S) => {
|
.then((S) => {
|
||||||
_swiper = new S(swiperNode, { spaceBetween: 20 })
|
_swiper = new S(galleryInner, { spaceBetween: 20 })
|
||||||
_swiper.on('slideChange', ({ realIndex }) => {
|
_swiper.on('slideChange', ({ realIndex }) => {
|
||||||
setIndex(realIndex)
|
setIndex(realIndex)
|
||||||
})
|
})
|
||||||
@@ -204,32 +203,47 @@ function galleryLoadImages(): void {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function createGallery(ijs: ImageJSON[]): void {
|
function constructGalleryNav(): void {
|
||||||
/**
|
// index
|
||||||
* gallery
|
indexDiv = document.createElement('div')
|
||||||
* |- galleryInner
|
indexDiv.insertAdjacentHTML(
|
||||||
* |- swiper-wrapper
|
'afterbegin',
|
||||||
* |- swiper-slide
|
`<span class="num"></span><span class="num"></span><span class="num"></span><span class="num"></span>
|
||||||
* |- img
|
<span>/</span>
|
||||||
* |- swiper-slide
|
<span class="num"></span><span class="num"></span><span class="num"></span><span class="num"></span>`
|
||||||
* |- img
|
)
|
||||||
* |- ...
|
// close
|
||||||
* |- nav
|
const closeDiv = document.createElement('div')
|
||||||
* |- index
|
closeDiv.innerText = capitalizeFirstLetter(container.dataset.close)
|
||||||
* |- close
|
closeDiv.addEventListener(
|
||||||
*/
|
'click',
|
||||||
|
() => {
|
||||||
|
slideDown()
|
||||||
|
},
|
||||||
|
{ passive: true }
|
||||||
|
)
|
||||||
|
closeDiv.addEventListener(
|
||||||
|
'keydown',
|
||||||
|
() => {
|
||||||
|
slideDown()
|
||||||
|
},
|
||||||
|
{ passive: true }
|
||||||
|
)
|
||||||
|
// nav
|
||||||
|
navDiv = createDivWithClass('nav')
|
||||||
|
navDiv.append(indexDiv, closeDiv)
|
||||||
|
}
|
||||||
|
|
||||||
|
function constructGalleryInner(ijs: ImageJSON[]): void {
|
||||||
// swiper wrapper
|
// swiper wrapper
|
||||||
const _swiperWrapper = document.createElement('div')
|
const swiperWrapper = createDivWithClass('swiper-wrapper')
|
||||||
_swiperWrapper.className = 'swiper-wrapper'
|
|
||||||
// loading text
|
// loading text
|
||||||
const loadingText = container.dataset.loading + '...'
|
const loadingText = container.dataset.loading + '...'
|
||||||
for (const ij of ijs) {
|
for (const ij of ijs) {
|
||||||
// swiper slide
|
// swiper slide
|
||||||
const _swiperSlide = document.createElement('div')
|
const swiperSlide = createDivWithClass('swiper-slide')
|
||||||
_swiperSlide.className = 'swiper-slide'
|
|
||||||
// loading indicator
|
// loading indicator
|
||||||
const l = document.createElement('div')
|
const l = createDivWithClass('loadingText')
|
||||||
l.className = 'loadingText'
|
|
||||||
l.innerText = loadingText
|
l.innerText = loadingText
|
||||||
// img
|
// img
|
||||||
const e = document.createElement('img') as MobileImage
|
const e = document.createElement('img') as MobileImage
|
||||||
@@ -253,63 +267,46 @@ function createGallery(ijs: ImageJSON[]): void {
|
|||||||
{ once: true, passive: true }
|
{ once: true, passive: true }
|
||||||
)
|
)
|
||||||
// parent container
|
// parent container
|
||||||
const p = document.createElement('div')
|
const p = createDivWithClass('slideContainer')
|
||||||
p.className = 'slideContainer'
|
|
||||||
// append
|
// append
|
||||||
p.append(e)
|
p.append(e, l)
|
||||||
p.append(l)
|
swiperSlide.append(p)
|
||||||
_swiperSlide.append(p)
|
swiperWrapper.append(swiperSlide)
|
||||||
_swiperWrapper.append(_swiperSlide)
|
|
||||||
}
|
}
|
||||||
// swiper node
|
// swiper node
|
||||||
const _swiperNode = document.createElement('div')
|
galleryInner = createDivWithClass('galleryInner')
|
||||||
_swiperNode.className = 'galleryInner'
|
galleryInner.append(swiperWrapper)
|
||||||
_swiperNode.append(_swiperWrapper)
|
}
|
||||||
// index
|
|
||||||
const _index = document.createElement('div')
|
function constructGallery(ijs: ImageJSON[]): void {
|
||||||
_index.insertAdjacentHTML(
|
/**
|
||||||
'afterbegin',
|
* gallery
|
||||||
`<span class="num"></span><span class="num"></span><span class="num"></span><span class="num"></span>
|
* |- galleryInner
|
||||||
<span>/</span>
|
* |- swiper-wrapper
|
||||||
<span class="num"></span><span class="num"></span><span class="num"></span><span class="num"></span>`
|
* |- swiper-slide
|
||||||
)
|
* |- img
|
||||||
// close
|
* |- swiper-slide
|
||||||
const _close = document.createElement('div')
|
* |- img
|
||||||
_close.innerText = capitalizeFirstLetter(container.dataset.close)
|
* |- ...
|
||||||
_close.addEventListener(
|
* |- nav
|
||||||
'click',
|
* |- index
|
||||||
() => {
|
* |- close
|
||||||
slideDown()
|
*/
|
||||||
},
|
|
||||||
{ passive: true }
|
|
||||||
)
|
|
||||||
_close.addEventListener(
|
|
||||||
'keydown',
|
|
||||||
() => {
|
|
||||||
slideDown()
|
|
||||||
},
|
|
||||||
{ passive: true }
|
|
||||||
)
|
|
||||||
// nav
|
|
||||||
const _navDiv = document.createElement('div')
|
|
||||||
_navDiv.className = 'nav'
|
|
||||||
_navDiv.append(_index, _close)
|
|
||||||
// gallery
|
// gallery
|
||||||
const _gallery = document.createElement('div')
|
gallery = createDivWithClass('gallery')
|
||||||
_gallery.className = 'gallery'
|
constructGalleryInner(ijs)
|
||||||
_gallery.append(_swiperNode)
|
constructGalleryNav()
|
||||||
_gallery.append(_navDiv)
|
gallery.append(galleryInner, navDiv)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* curtain
|
* curtain
|
||||||
*/
|
*/
|
||||||
const _curtain = document.createElement('div')
|
curtain = createDivWithClass('curtain')
|
||||||
_curtain.className = 'curtain'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* container
|
* container
|
||||||
* |- gallery
|
* |- gallery
|
||||||
* |- curtain
|
* |- curtain
|
||||||
*/
|
*/
|
||||||
container.append(_gallery, _curtain)
|
container.append(gallery, curtain)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user