summaryrefslogtreecommitdiff
path: root/src/slides.js
blob: 94af74ec3103ec0b3820950c5cf815b65456b214 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
const Flickity = require("flickity")
import "flickity/dist/flickity.min.css"
import apiConnector from "./connector.js"

class Slides {
	constructor(slidesContainer) {
		/* previous selected index */
		this.selectedIndex = 0

		this.slidesContainer = slidesContainer

		/* initialize slides */
		this.flickity = new Flickity("#slideshow-carousel", {
			wrapAround: true,
			prevNextButtons: false,
			pageDots: false,
			resize: true,
			setGallerySize: false,
		})

		this.flickity.on("scroll", progress => { this.scroll(progress) })
		this.flickity.on("staticClick", (e, pointer, cellElement, cellIndex) => { this.staticClick(e, pointer, cellElement, cellIndex) })
		this.flickity.on("dragEnd", () => { this.seek() })
		this.initImages()

		/* initialize seek buttons */
		const seekPrevButton = this.slidesContainer.querySelector("#prevSlide")
		const seekNextButton = this.slidesContainer.querySelector("#nextSlide")

		seekPrevButton.addEventListener("click", () => { this.flickity.previous() ; this.seek() })
		seekNextButton.addEventListener("click", () => { this.flickity.next()     ; this.seek() })
	}

	seek() {
		// this is just like calculating movement in lazycachelist.py
		// gets the min of the absolute values and returns signed value
		const increment = [
			this.flickity.selectedIndex - this.selectedIndex,         // no list wrap
			this.flickity.selectedIndex - this.flickity.cells.length, // wrap backwards (0  -> -1)
			this.flickity.cells.length  - this.selectedIndex,         // wrap forwards  (-1 ->  0)
		].reduce((key, v) => Math.abs(v) < Math.abs(key) ? v : key)
		this.selectedIndex = this.flickity.selectedIndex
		apiConnector.seek(increment)
	}

	/* Flickity function for scrolling to ensure next and prev pics are always
	 * visible and to transition between states */
	scroll(progress) {
		const normalizedProgress = progress / (1 / (this.flickity.cells.length-1))
		const liveSelectedIndex = Math.round(normalizedProgress)
		const localizedProgress = normalizedProgress - liveSelectedIndex

		const prevSelectedCell = this.flickity.cells.at((liveSelectedIndex-1) % this.flickity.cells.length).element
		const liveSelectedCell = this.flickity.cells.at((liveSelectedIndex  ) % this.flickity.cells.length).element
		const nextSelectedCell = this.flickity.cells.at((liveSelectedIndex+1) % this.flickity.cells.length).element

		const prevSelectedImage = prevSelectedCell.firstElementChild
		const liveSelectedImage = liveSelectedCell.firstElementChild
		const nextSelectedImage = nextSelectedCell.firstElementChild

		const prevMargin = prevSelectedCell.clientWidth - prevSelectedImage.clientWidth
		const liveMargin = liveSelectedCell.clientWidth - liveSelectedImage.clientWidth
		const nextMargin = nextSelectedCell.clientWidth - nextSelectedImage.clientWidth

		liveSelectedImage.style.marginLeft = liveMargin / 2 + "px"
		nextSelectedImage.style.marginLeft = Math.max(0, Math.min(nextMargin, nextMargin * (localizedProgress))) + "px"
		prevSelectedImage.style.marginLeft = prevMargin - Math.max(0, Math.min(prevMargin, prevMargin * localizedProgress * -1)) + "px" // TODO clean this
	}

	/* jump to clicked on slide */
	staticClick(e, pointer, cellElement, cellIndex) {
		this.flickity.select(cellIndex)
		this.seek()
	}

	/* make sure images have correct margin when loaded since scroll function
	 * depends on them being loaded */
	positionImageStatic(img) {
		const i = parseInt(img.dataset.index)
		if (i == this.flickity.selectedIndex)
			img.style.marginLeft = (img.parentElement.clientWidth - img.clientWidth) / 2 + "px"
		else if ((i + 1) % this.flickity.cells.length == this.flickity.selectedIndex)
			img.style.marginLeft = img.parentElement.clientWidth - img.clientWidth + "px"
	}

	imageLoaded(e) { this.positionImageStatic(e.target) }
	initImages() {
		const imgs = this.slidesContainer.querySelectorAll("#slideshow-carousel img")
		for (let i = 0; i < imgs.length; i++) {
			const img = imgs[i]
			img.dataset.index = i
			img.addEventListener("load", this.imageLoaded)
			if (img.complete)
				this.positionImageStatic(img)
		}
	}
}

export default slidesContainer => { new Slides(slidesContainer); return true }