Add a JavaScript file for the photos list
This commit is contained in:
parent
ad9f83ed39
commit
da994bd6b7
2 changed files with 117 additions and 0 deletions
111
assets/scripts/photos/list.js
Normal file
111
assets/scripts/photos/list.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
class Item {
|
||||
static allItems = [];
|
||||
|
||||
element;
|
||||
|
||||
#mouseoverRegionOffsets;
|
||||
#currentRegion = 0;
|
||||
|
||||
constructor(element) {
|
||||
this.element = element;
|
||||
this.setUpEventHandlers();
|
||||
|
||||
element._item = this;
|
||||
}
|
||||
|
||||
get title() {
|
||||
return this.element.getAttribute("title");
|
||||
}
|
||||
|
||||
get numberOfImages() {
|
||||
const numberOfImages = this.element.dataset.numberOfImages;
|
||||
if (typeof numberOfImages === "undefined" || numberOfImages === null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
return parseInt(numberOfImages);
|
||||
} catch (e) {
|
||||
console.error("Unable to parse data-number-of-images attribute:", numberOfImages);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
get mouseoverRegionOffsets() {
|
||||
let offsets = this.#mouseoverRegionOffsets;
|
||||
|
||||
if (!offsets) {
|
||||
const numberOfImages = this.numberOfImages;
|
||||
offsets = new Array(numberOfImages);
|
||||
|
||||
const rect = this.element.getBoundingClientRect();
|
||||
const widthOfRegion = rect.width / numberOfImages;
|
||||
for (let i = 0; i < numberOfImages; i++) {
|
||||
offsets[i] = i * widthOfRegion;
|
||||
}
|
||||
|
||||
this.#mouseoverRegionOffsets = offsets;
|
||||
}
|
||||
|
||||
return offsets;
|
||||
}
|
||||
|
||||
setUpEventHandlers() {
|
||||
if (this.numberOfImages <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.element.addEventListener("mousemove", event => {
|
||||
const offsetX = event.offsetX;
|
||||
|
||||
let indexOfRegion = -1;
|
||||
for (let regionOffset of this.mouseoverRegionOffsets) {
|
||||
if (regionOffset > offsetX) {
|
||||
break;
|
||||
}
|
||||
indexOfRegion += 1;
|
||||
}
|
||||
|
||||
if (indexOfRegion !== this.#currentRegion) {
|
||||
console.debug(`Mouse moved at ${offsetX}, ${event.offsetY} in cell for '${this.title}' in region ${indexOfRegion}`);
|
||||
// TODO: Set image to images[indexOfRegion]
|
||||
this.#currentRegion = indexOfRegion;
|
||||
}
|
||||
});
|
||||
|
||||
this.element.addEventListener("mouseout", event => {
|
||||
console.debug(`Mouse left cell for '${this.title}'`);
|
||||
// TODO: Reset to the first image.
|
||||
});
|
||||
}
|
||||
|
||||
addToIntersectionObserver(intersectionObserver) {
|
||||
intersectionObserver.observe(this.element);
|
||||
}
|
||||
|
||||
handleIntersectionObservation(entry, observer) {
|
||||
if (entry.isIntersecting) {
|
||||
console.debug(`Cell for ${this.title} entered the viewport`);
|
||||
} else {
|
||||
console.debug(`Cell for ${this.title} left the viewport`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let intersectionObserver;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", event => {
|
||||
intersectionObserver = new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
entry.target._item.handleIntersectionObservation(entry, observer);
|
||||
});
|
||||
}, { threshold: 0.5 });
|
||||
|
||||
Item.allItems = Array.from(document.querySelectorAll(".photos.list > a")).map(cell => {
|
||||
const item = new Item(cell)
|
||||
item.addToIntersectionObserver(intersectionObserver);
|
||||
return item;
|
||||
});
|
||||
});
|
|
@ -17,3 +17,9 @@
|
|||
{{ define "footer" }}
|
||||
{{ partial "footer.html" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "scripts" }}
|
||||
{{- with resources.Get "scripts/photos/list.js" | fingerprint "md5" -}}
|
||||
<script src="{{ .RelPermalink }}"></script>
|
||||
{{- end -}}
|
||||
{{ end }}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue