diff --git a/assets/scripts/photos/carousel.js b/assets/scripts/photos/carousel.js new file mode 100644 index 0000000..827d9e6 --- /dev/null +++ b/assets/scripts/photos/carousel.js @@ -0,0 +1,304 @@ +// Eryn Wells + +class Carousel { + carousel = null; + #items = null; + #caption = null; + + constructor(element) { + this.carousel = element; + this.#caption = element.querySelector("figcaption"); + } + + get items() { + if (this.#items === null) { + const boundingRect = this.carousel.getBoundingClientRect(); + this.#items = Array.from(this.carousel.querySelectorAll("ul > li")).map(item => { + let itemRect = item.getClientRects()[0]; + let relativeX = itemRect.x - boundingRect.x; + return new CarouselItem(item, relativeX); + }); + } + + return this.#items; + } + + get scrollContainer() { + return this.carousel.querySelector("ul"); + } + + setCaption(caption) { + if (!this.#caption) { + return; + } + this.#caption.innerHTML = caption; + } + + scrollTo(index) { + this.scrollContainer.scrollTo(this.items[index].relativeX, 0); + } + + setUpScrollEventListener(photoParametersTable) { + let previousScrollLeft = null; + let isScrollingLeft = true; + + this.scrollContainer.addEventListener("scroll", event => { + const target = event.target; + const scrollLeft = target.scrollLeft; + + const carouselRect = target.getBoundingClientRect(); + const carouselRectHorizontalCenter = carouselRect.width / 2.0; + + if (previousScrollLeft !== null) { + isScrollingLeft = scrollLeft > previousScrollLeft; + } + previousScrollLeft = scrollLeft; + + this.items.forEach(item => { + const itemRelativeXCoordinate = isScrollingLeft ? item.relativeX - scrollLeft : item.relativeMaxX - scrollLeft; + + const itemWasLeftOfContainerCenter = item.isLeftOfContainerCenter; + const itemIsLeftOfContainerCenter = itemRelativeXCoordinate < carouselRectHorizontalCenter; + item.isLeftOfContainerCenter = itemIsLeftOfContainerCenter; + + if ( (isScrollingLeft && (!itemWasLeftOfContainerCenter && itemIsLeftOfContainerCenter)) + || (!isScrollingLeft && (itemWasLeftOfContainerCenter && !itemIsLeftOfContainerCenter))) { + this.setCaption(item.title); + photoParametersTable.setMakeModel(item.make, item.model); + photoParametersTable.setLocation(item.latitude, item.longitude); + photoParametersTable.setMegapixels(item.megapixels); + photoParametersTable.setSize(item.width, item.height); + photoParametersTable.setISO(item.iso); + photoParametersTable.setFocalLength(item.focalLength); + photoParametersTable.setFNumber(item.fNumber); + photoParametersTable.setExposureTime(item.exposureTime); + } + }); + }); + } +} + +class CarouselItem { + element = null; + relativeX = 0; + isLeftOfContainerCenter = false; + + constructor(element, relativeX) { + this.element = element; + this.relativeX = relativeX + } + + get relativeMaxX() { + const rect = this.element.getBoundingClientRect(); + return this.relativeX + rect.width; + } + + get title() { return this.element.dataset.title; } + get latitude() { return this.element.dataset.latitude; } + get longitude() { return this.element.dataset.longitude; } + get megapixels() { return this.element.dataset.megapixels; } + get width() { return this.element.dataset.width; } + get height() { return this.element.dataset.height; } + get make() { return this.element.dataset.make; } + get model() { return this.element.dataset.model; } + get iso() { return this.element.dataset.iso; } + get focalLength() { return this.element.dataset.focalLength; } + get fNumber() { return this.element.dataset.fNumber; } + get exposureTime() { return this.element.dataset.exposureTime; } +} + +class PhotoParametersTable { + tableElement; + + #makeModelElement; + #latitudeElement; + #longitudeElement; + #megapixelsElement; + #widthElement; + #heightElement; + #isoElement; + #focalLengthElement; + #fNumberElement; + #exposureTimeElement; + + constructor(element) { + this.tableElement = element; + } + + setMakeModel(make, model) { + if (!this.#makeModelElement) { + this.#makeModelElement = this.#getElementWithQuerySelector("td.make-model"); + } + + if (!this.#makeModelElement) { + return; + } + + let makeModel = ""; + if (make && model) { + return `${make} ${model}`; + } else if (make) { + return make; + } else if (model) { + return model; + } else { + return ""; + } + + this.#makeModelElement.innerHTML = makeModel; + } + + setLocation(latitude, longitude) { + let latitudeElement = this.#latitudeElement; + if (!latitudeElement) { + latitudeElement = this.#getElementWithQuerySelector("td.location > data.latitude"); + this.#latitudeElement = latitudeElement; + } + + let longitudeElement = this.#longitudeElement; + if (!longitudeElement) { + longitudeElement = this.#getElementWithQuerySelector("td.location > data.longitude"); + this.#longitudeElement = longitudeElement; + } + + if (!latitudeElement || !longitudeElement) { + return; + } + + latitudeElement.innerHTML = latitude; + longitudeElement.innerHTML = longitude; + } + + setMegapixels(megapixels) { + let megapixelsElement = this.#megapixelsElement; + if (!megapixelsElement) { + megapixelsElement = this.#getElementWithQuerySelector("td.size > data.megapixels"); + this.#megapixelsElement = megapixelsElement; + } + + if (!megapixelsElement) { + return; + } + + megapixelsElement.innerHTML = megapixels; + } + + setSize(width, height) { + let widthElement = this.#widthElement; + if (!widthElement) { + widthElement = this.#getElementWithQuerySelector("td.size > data.width"); + this.#widthElement = widthElement; + } + + let heightElement = this.#heightElement; + if (heightElement) { + heightElement = this.#getElementWithQuerySelector("td.size > data.height"); + this.#heightElement = heightElement; + } + + if (!widthElement || !heightElement) { + return; + } + + widthElement.innerHTML = width; + heightElement.innerHTML = height; + } + + setISO(iso) { + let isoElement = this.#isoElement; + if (!isoElement) { + isoElement = this.#getElementWithQuerySelector("td.iso"); + this.#isoElement = isoElement; + } + + if (!isoElement) { + return; + } + + isoElement.innerHTML = `ISO ${iso}`; + } + + setFocalLength(focalLength) { + let focalLengthElement = this.#focalLengthElement; + if (!focalLengthElement) { + focalLengthElement = this.#getElementWithQuerySelector("td.focal-length"); + this.#focalLengthElement = focalLengthElement; + } + + if (!focalLengthElement) { + return; + } + + focalLengthElement.innerHTML = `${focalLength} mm`; + } + + setFNumber(f) { + let fNumberElement = this.#fNumberElement; + if (!fNumberElement) { + fNumberElement = this.#getElementWithQuerySelector("td.f-number"); + this.#fNumberElement = fNumberElement; + } + + if (!fNumberElement) { + return; + } + + fNumberElement.innerHTML = `ƒ${f}`; + } + + setExposureTime(exposureTime) { + let exposureTimeElement = this.#exposureTimeElement; + if (!exposureTimeElement) { + exposureTimeElement = this.#getElementWithQuerySelector("td.exposure-time"); + this.#exposureTimeElement = exposureTimeElement; + } + + if (!exposureTimeElement) { + return; + } + + exposureTimeElement.innerHTML = `${exposureTime} s`; + } + + #getElementWithQuerySelector(query) { + const element = this.tableElement.querySelector(query); + if (!element) { + return null; + } + return element; + } +} + +document.addEventListener("DOMContentLoaded", (event) => { + const carouselElements = document.querySelectorAll("figure.carousel"); + if (carouselElements.length === 0) { + return; + } + + const allCarousels = Array.from(carouselElements).sort((a, b) => { + const aRect = a.getBoundingClientRect(); + const bRect = a.getBoundingClientRect(); + return aRect.top - bRect.top; + }).map(elem => new Carousel(elem)); + + let photoParametersTable = null; + const photoParamsTableElement = document.querySelector(".photo-params table"); + if (photoParamsTableElement) { + photoParametersTable = new PhotoParametersTable(photoParamsTableElement); + } + + allCarousels.forEach(carousel => { + carousel.setUpScrollEventListener(photoParametersTable); + }); + + const url = new URL(window.location); + let photoGetParameter = url.searchParams.get("photo"); + if (photoGetParameter) { + try { + photoGetParameter = parseInt(photoGetParameter); + allCarousels[0].scrollTo(photoGetParameter); + } catch (e) { + console.error("Unable to parse 'photo' GET parameter as integer:", e); + } + } +}); diff --git a/assets/scripts/photos/list.js b/assets/scripts/photos/list.js new file mode 100644 index 0000000..370e6d1 --- /dev/null +++ b/assets/scripts/photos/list.js @@ -0,0 +1,111 @@ +// Eryn Wells + +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; + }); +}); diff --git a/assets/styles/photos.css b/assets/styles/photos.css index e13bb06..b90a71d 100644 --- a/assets/styles/photos.css +++ b/assets/styles/photos.css @@ -1,10 +1,14 @@ :root { --date-item-background-color: rgb(var(--lt-gray)); + --photo-grid-item-size: 200px; + --photo-params-background-color: rgb(var(--lt-gray)); --photo-params-container-background-color: rgb(var(--super-lt-gray)); --photo-params-color: rgb(var(--sub-dk-gray)); --photo-params-border-color: rgb(var(--super-lt-gray)); + + --carousel-gradient-full-opaque: var(--background); } @media (prefers-color-scheme: dark) { :root { @@ -26,7 +30,7 @@ .photos.list { display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + grid-template-columns: repeat(auto-fill, minmax(var(--photo-grid-item-size), 1fr)); gap: 4px; } @@ -34,6 +38,10 @@ margin-block-end: 0; } +.photos.list > :has(img) { + aspect-ratio: 1; +} + .photos.page > nav { margin-block-end: var(--body-item-spacing); } @@ -41,11 +49,37 @@ .photos.list > a { display: block; line-height: 0; + position: relative; +} +.photos.list > a:hover { + text-decoration: none; } .photos.list > a > img { border-radius: 3px; image-orientation: from-image; + position: absolute; + top: 0; + left: 0; +} + +.photos.list > a > .badge { + align-items: center; + aspect-ratio: 1; + background: rgba(255, 255, 255, 0.6); + border-radius: 4px; + color: rgb(var(--mid-gray)); + display: flex; + left: 4px; + line-height: 0; + padding: 1rem; + position: relative; + top: 4px; + width: max-content; + z-index: 1; +} +.photos.list > a > .badge:hover { + text-decoration: none; } .photos.list > div { @@ -80,7 +114,7 @@ content: "⏵︎"; font-size: 80%; } -@media (max-width: calc(24px + 400px + 4px)) { +@media (max-width: calc(24px + 400px + 9px)) { .photos.list > div > h6 > span { width: max-content; padding-block: calc(0.25 * var(--body-item-spacing)); @@ -90,6 +124,62 @@ } } +.photos.page > figure.carousel { + position: relative; + max-width: 100%; + width: 100%; +} + +.photos.page > figure.carousel > ul { + align-items: stretch; + display: flex; + flex-flow: row nowrap; + gap: 0 calc(0.5 * var(--body-item-spacing)); + margin: 0; + overflow-x: scroll; + scroll-snap-type: x mandatory; + padding: 0; + padding-inline: var(--body-item-spacing); +} + +.photos.page > figure.carousel > ul::-webkit-scrollbar { + background: transparent; + width: 0; +} + +.photos.page > figure.carousel > .shadow { + position: absolute; + top: 0; + height: 100%; + width: var(--body-item-spacing); + z-index: 10; +} + +.photos.page > figure.carousel > .shadow.left { + background: linear-gradient( + to right, + rgba(var(--carousel-gradient-full-opaque), 1), + rgba(var(--carousel-gradient-full-opaque), 0)); + left: 0; +} + +.photos.page > figure.carousel > .shadow.right { + background: linear-gradient( + to left, + rgba(var(--carousel-gradient-full-opaque), 1), + rgba(var(--carousel-gradient-full-opaque), 0)); + right: 0; +} + +.photos.page > figure.carousel > ul > li { + scroll-snap-align: center; + margin: 0; + width: var(--content-width); + flex-shrink: 0; + list-style: none; + padding: 0; +} + .photo-params { width: 100%; } diff --git a/content/photos/2022/temple-of-hephaestus/IMG_3771.jpeg b/content/photos/2022/temple-of-hephaestus/IMG_3771.jpeg new file mode 100644 index 0000000..1e12b53 --- /dev/null +++ b/content/photos/2022/temple-of-hephaestus/IMG_3771.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24f36ad3a467713f846f7816429e646ca433eadf7132c628e34a04dcaa839757 +size 4278990 diff --git a/content/photos/2022/temple-of-hephaestus/IMG_3794.jpeg b/content/photos/2022/temple-of-hephaestus/IMG_3794.jpeg new file mode 100644 index 0000000..dd943f0 --- /dev/null +++ b/content/photos/2022/temple-of-hephaestus/IMG_3794.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0fbece7eb21b370ed75658d5b82501bd6f49737cd5a5db4988cceecf829083b +size 4152181 diff --git a/content/photos/2022/temple-of-hephaestus/index.md b/content/photos/2022/temple-of-hephaestus/index.md new file mode 100644 index 0000000..60d024d --- /dev/null +++ b/content/photos/2022/temple-of-hephaestus/index.md @@ -0,0 +1,14 @@ +--- +title: "Temple of Hephaestus" +date: 2022-07-30T04:30:43-07:00 +series: Greece +categories: Travel +resources: + - title: The Temple of Hephaestus from the Agora + src: IMG_3771.jpeg + - title: The front of the Temple of Hephaestus + src: IMG_3794.jpeg +--- + +This temple is the best preserved building on the site of the Ancient Agora of +Athens, {{< lang gr >}}Αρχαία Αγορά της Αθήνας{{< /lang >}}. diff --git a/layouts/partials/photo_exif_table.html b/layouts/partials/photo_exif_table.html index 7f18b6d..55552db 100644 --- a/layouts/partials/photo_exif_table.html +++ b/layouts/partials/photo_exif_table.html @@ -9,10 +9,8 @@ {{ if and .Lat .Long }} - {{ $lat := float .Lat }}{{ $latDir := cond (eq $lat 0) "" (cond (gt $lat 0) "N" "S") }} - {{ .Lat | lang.FormatNumber (cond (ne $lat 0) 3 0) }}º{{ $latDir }}, - {{ $long := float .Long }}{{ $longDir := cond (eq $long 0) "" (cond (gt $long 0) "E" "W") }} - {{ .Long | lang.FormatNumber (cond (ne $long 0) 3 0) }}º{{ $longDir }} + {{ partial "photos/latitude.html" . }}, + {{ partial "photos/longitude.html" . }} {{ end }} {{ if and .Tags.PixelXDimension .Tags.PixelYDimension }} @@ -20,8 +18,8 @@ {{ $widthpx := .Tags.PixelXDimension }} {{ $heightpx := .Tags.PixelYDimension }} {{ if and (gt $widthpx 0) (gt $heightpx 0) }} - {{ $megapixels := div (mul $widthpx $heightpx) 1e6 }} - {{ $megapixels | lang.FormatNumber 0 }} MP • {{ $widthpx }} × {{ $heightpx }} + {{ partial "photos/megapixels.html" .Tags }}{{ + $widthpx }} × {{ $heightpx }} {{ end }} {{ end }} diff --git a/layouts/partials/photos/latitude.html b/layouts/partials/photos/latitude.html new file mode 100644 index 0000000..6c1842d --- /dev/null +++ b/layouts/partials/photos/latitude.html @@ -0,0 +1,4 @@ +{{ $lat := float .Lat }} +{{ $latDir := cond (eq $lat 0) "" (cond (gt $lat 0) "N" "S") }} +{{ $formattedLat := printf "%sº%s" (.Lat | lang.FormatNumber (cond (ne $lat 0) 3 0)) $latDir }} +{{ return $formattedLat }} diff --git a/layouts/partials/photos/longitude.html b/layouts/partials/photos/longitude.html new file mode 100644 index 0000000..8fe93d1 --- /dev/null +++ b/layouts/partials/photos/longitude.html @@ -0,0 +1,4 @@ +{{ $long := float .Long }} +{{ $longDir := cond (eq $long 0) "" (cond (gt $long 0) "E" "W") }} +{{ $formattedLong := printf "%sº%s" (.Long | lang.FormatNumber (cond (ne $long 0) 3 0)) $longDir }} +{{ return $formattedLong }} diff --git a/layouts/partials/photos/megapixels.html b/layouts/partials/photos/megapixels.html new file mode 100644 index 0000000..401bedd --- /dev/null +++ b/layouts/partials/photos/megapixels.html @@ -0,0 +1,8 @@ +{{ $widthpx := .PixelXDimension }} +{{ $heightpx := .PixelYDimension }} +{{ $megapixels := 0 }} +{{ if and (gt $widthpx 0) (gt $heightpx 0) }} + {{ $megapixels = div (mul $widthpx $heightpx) 1e6 }} +{{ end }} +{{ $formattedMegapixels := printf "%.0f MP" $megapixels }} +{{ return $formattedMegapixels }} diff --git a/layouts/partials/photos/thumbnail_for_list.html b/layouts/partials/photos/thumbnail_for_list.html new file mode 100644 index 0000000..952218f --- /dev/null +++ b/layouts/partials/photos/thumbnail_for_list.html @@ -0,0 +1,28 @@ +{{ $thumbnailResource := .Image }} + +{{ $orientation := partial "images/orientation_angle.html" $thumbnailResource }} + +{{ $targetWidth := 0 }} +{{ if isset . "Width" }} + {{ $targetWidth = .Width }} +{{ else }} + {{ $targetWidth = $thumbnailResource.Width }} +{{ end }} + +{{ $targetHeight := 0 }} +{{ if isset . "Height" }} + {{ $targetHeight = .Height }} +{{ else }} + {{ $targetHeight = $thumbnailResource.Height }} +{{ end }} + +{{ $thumbnail := false }} +{{ if not (and (eq $orientation 0) + (eq $targetWidth $thumbnailResource.Width) + (eq $targetHeight $thumbnailResource.Height)) }} + {{ $thumbnail = $thumbnailResource.Fit (printf "%dx%d r%d" $targetWidth $targetHeight (sub 360 $orientation)) }} +{{ else }} + {{ $thumbnail = $thumbnailResource }} +{{ end }} + +{{ return $thumbnail }} diff --git a/layouts/partials/photos/thumbnails.html b/layouts/partials/photos/thumbnails.html new file mode 100644 index 0000000..06ddb01 --- /dev/null +++ b/layouts/partials/photos/thumbnails.html @@ -0,0 +1,51 @@ +{{ $page := .Page }} + +{{ $thumbnails := slice }} +{{ with $thumbnailNamesList := $page.Params "thumbnails" }} + {{/* Specify a list of thumbnails to use with the page "thumbnails" param */}} + {{ range $thumbnailNamesList }} + {{ with $page.Resources.GetMatch . }} + {{ $thumbnails = $thumbnails | append . }} + {{ else }} + {{ errorf "No image resources available for %s from thumbnails param" . }} + {{ end }} + {{ end }} +{{ else }} + {{/* Get a list of all the image resources and see if any of them specify + thumbnails for themselves. If they do, use those, otherwise use the image + resource itself. */}} + {{ range $img := $page.Resources.ByType "image" }} + {{ with $thumbnailResourceName := $img.params.thumbnail }} + {{ with $page.Resources.GetMatch $thumbnailResourceName }} + {{ $thumbnails = $thumbnails | append . }} + {{ else }} + {{ errorf "No image resources available for '%s' from thumbnail param for image resources %s" + $thumbnailResourceName + $img.Name }} + {{ end }} + {{ else }} + {{/* TODO: Look for a named image that indicates it's a thumbnail of + another resources. Something like ${imgBasename}_thumbnail.${ext}. + I don't know how easy Hugo makes filename processing, so this could + be painful. */}} + {{ $thumbnails = $thumbnails | append $img }} + {{ end }} + {{ end }} +{{ end }} + +{{ if eq (len $thumbnails) 0 }} + {{ errorf "Couldn't find any thumbnails for %s" $page.Permalink }} +{{ end }} + +{{ $thumbnailOptions := dict }} +{{ if isset . "Width" }}{{ $thumbnailOptions = $thumbnailOptions | merge (dict "Width" .Width) }}{{ end }} +{{ if isset . "Height" }}{{ $thumbnailOptions = $thumbnailOptions | merge (dict "Height" .Height) }}{{ end }} + +{{ $processedThumbnails := slice }} +{{ range $thumbnails }} + {{ $options := $thumbnailOptions | merge "Image" . }} + {{ $processedThumbnail := partial "photos/thumbnail_for_list.html" $options }} + {{ $processedThumbnails = $processedThumbnails | append $processedThumbnail }} +{{ end }} + +{{ return $processedThumbnails }} diff --git a/layouts/partials/resources/section_css.html b/layouts/partials/resources/section_css.html index 0801efb..f7f26fd 100644 --- a/layouts/partials/resources/section_css.html +++ b/layouts/partials/resources/section_css.html @@ -5,7 +5,7 @@ {{ else }} {{ $sectionStylesheet = printf "styles/%s.css" .Section }} {{ end }} -{{ with resources.Get $sectionStylesheet }} +{{ with resources.Get $sectionStylesheet }} {{ $sectionCSS = . | fingerprint "md5" }} {{ end }} {{ return $sectionCSS }} diff --git a/layouts/partials/single_styles.html b/layouts/partials/single_styles.html index 287f7c7..dc636b4 100644 --- a/layouts/partials/single_styles.html +++ b/layouts/partials/single_styles.html @@ -1,4 +1,4 @@ {{- range .Resources.Match "*.css" -}} {{- $stylesheet := . | fingerprint "md5" }} - + {{- end -}} diff --git a/layouts/photos/li_thumbnail_in_grid.html b/layouts/photos/li_thumbnail_in_grid.html index e35b156..d7c9418 100644 --- a/layouts/photos/li_thumbnail_in_grid.html +++ b/layouts/photos/li_thumbnail_in_grid.html @@ -1,6 +1,11 @@ {{- $thumbnail := partial "photos/thumbnail.html" (dict "Page" . "Width" 600 "Height" 600) -}} {{- $thumbnail = $thumbnail.Crop "600x600" -}} -{{- $altText := $thumbnail.Params.alt -}} - - {{ . }} +{{- $numberOfImages := len (partial "photos/list.html" .) -}} +{{- $hasMultipleImages := gt $numberOfImages 1 -}} + + {{ if $hasMultipleImages }}
{{ $numberOfImages }}
{{ end }} + {{ range partial "photos/thumbnails.html" (dict "Page" . "Height" 600 "Width" 600) -}} + {{- $altText := .Params.alt -}} + {{ . }} + {{- end }}
diff --git a/layouts/photos/list.html b/layouts/photos/list.html index 9153577..f33bfdd 100644 --- a/layouts/photos/list.html +++ b/layouts/photos/list.html @@ -17,3 +17,9 @@ {{ define "footer" }} {{ partial "footer.html" . }} {{ end }} + +{{ define "scripts" }} +{{- with resources.Get "scripts/photos/list.js" | fingerprint "md5" -}} + +{{- end -}} +{{ end }} diff --git a/layouts/photos/single.html b/layouts/photos/single.html index 2eab4b2..90b2404 100644 --- a/layouts/photos/single.html +++ b/layouts/photos/single.html @@ -12,29 +12,56 @@ {{ errorf "Missing photo from photos page %q" .Path }} {{ end }} +{{- $firstImage := index $photos 0 -}} {{ if eq (len $photos) 1 }} - {{- $img := index $photos 0 -}} -
{{ . }}
- - {{ .Content }} - - {{- if .Params.photo_details | default true -}} - {{- partial "photo_exif_table.html" $img.Exif -}} - - {{- if in ($.Site.BaseURL | string) "localhost" -}} - {{- partial "development/photo_exif_table.html" $img.Exif -}} - {{- end -}} - {{- end -}} -{{ else }}
-
+{{ else }} + {{ end }} +
+ {{ .Content }} +
+ +{{- if .Params.photo_details | default true -}} + {{- partial "photo_exif_table.html" $firstImage.Exif -}} + + {{- if in ($.Site.BaseURL | string) "localhost" -}} + {{- partial "development/photo_exif_table.html" $firstImage.Exif -}} + {{- end -}} +{{- end -}} +
{{ partial "footer_tags.html" . }}
@@ -43,3 +70,12 @@ {{ define "footer" }} {{ partial "footer.html" . }} {{ end }} + +{{ define "scripts" }} +{{- $photos := partial "photos/list.html" . -}} +{{ if gt (len $photos) 1 -}} + {{- with resources.Get "scripts/photos/carousel.js" | fingerprint "md5" -}} + + {{- end -}} +{{- end }} +{{ end }}