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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
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.assetIndex = 0
this.slidesContainer = slidesContainer
/* append 11 cells to carousel */
const carousel = this.slidesContainer.querySelector("#slideshow-carousel")
const cellTemplate = this.slidesContainer.querySelector("#carousel-cell-template")
this.cells = []
for (let i = 0; i < 11; i++)
carousel.appendChild(cellTemplate.content.cloneNode(true))
/* initialize slides */
this.flickity = new Flickity(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("#prev-slide")
const seekNextButton = this.slidesContainer.querySelector("#next-slide")
seekPrevButton.addEventListener("click", () => { this.flickity.previous() ; this.seek() })
seekNextButton.addEventListener("click", () => { this.flickity.next() ; this.seek() })
/* initialize seek callback */
apiConnector.seekCallbacks.push(c => { this.seekCallback() })
/* initialize top controls */
const assetDownloadButton = this.slidesContainer.querySelector("#download")
assetDownloadButton.addEventListener("click", () => { apiConnector.assetDownload(apiConnector.currentAsset) })
}
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
this.assetIndex += increment
apiConnector.seek(increment)
}
seekCallback() {
let i
if (this.assetIndex !== apiConnector.assetIndex) {
this.assetIndex = apiConnector.assetIndex
i = apiConnector.movement
for (; i > 0; i--) this.flickity.next()
for (; i < 0; i++) this.flickity.previous()
this.selectedIndex = this.flickity.selectedIndex
}
// load new imgs
// TODO need to make the 11 cells a constant somehow
for (i = 0; i < this.flickity.cells.length; i++) {
const x = (i + this.selectedIndex + 6) % this.flickity.cells.length
const e = this.flickity.cells[x].element
const img = e.firstElementChild
img.src = apiConnector.assetPreviewSrc(apiConnector.assets[i])
}
}
/* 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", e => { this.imageLoaded(e) })
if (img.complete)
this.positionImageStatic(img)
}
}
}
export default slidesContainer => { new Slides(slidesContainer); return true }
|