From e9967fa22781d922ba4eb8fb44fe72d200ac4b14 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Mon, 10 Nov 2025 21:04:10 +0000
Subject: [PATCH] =IconsManager.php update

---
 assets/js/concise/Media.js |  235 +++++++++++++++-------------------------------------------
 1 files changed, 63 insertions(+), 172 deletions(-)

diff --git a/assets/js/concise/Media.js b/assets/js/concise/Media.js
index 3f733a0..ab20c7f 100644
--- a/assets/js/concise/Media.js
+++ b/assets/js/concise/Media.js
@@ -1,207 +1,98 @@
-/*
-SITE GALLERY MANAGER
-Handles two main functions:
-
-1. Responsive Images
-- Automatically loads appropriate image sizes based on screen width
-- Listens for resize events and updates images accordingly
-- Uses data-small, data-medium, and data-full attributes on images
-
-2. Gallery Management
-- HTML Structure:
-  <a class="open-gallery" data-opens="gallery-id" data-focus="image-to-show">
-    <figure><img...></figure>
-  </a>
-
-  <dialog class="gallery" id="gallery-id">
-    - Main image display (.images with multiple <figure>s)
-    - Navigation bar on bottom (nav.thumbnails) with:
-      - Previous/Next buttons
-      - Thumbnail list (toggles with .open class)
-      - Expand button (toggles .expanded class)
-    - Visibility toggle (toggles .hide-info class)
-    - Close button
-  </dialog>
-
-Key Features:
-- Opens in modal dialog with keyboard navigation
-- Manages thumbnail navigation state
-- Handles responsive image loading
-- Uses class-based state management (open, expanded, hide-info)
-- All event handling through delegation
-- Built on UIHandler base class for state management
-
-State Management:
-- Dialog: open/closed
-- Thumbnails: collapsed/open/expanded
-- Info panel: visible/hidden
-- Active image: tracked with .focused class
-*/
 class Media {
 	constructor() {
 		this.currentWidth = window.innerWidth;
-		this.initElements();
-		if (this.images.length === 0) {
-			return;
-		}
-		this.store = new window.jvbStore({
-			name: 'images',
-			TTL: 604800
-		});
-		this.touch = {
-			x: null,
-			y: null
-		}
-		this.a11y = window.jvbA11y;
-		this.debouncer = window.debouncer;
-		this.isTouching = false;
+		this.images = document.querySelectorAll('.wp-site-blocks img[data-small]');
+
+		if (this.images.length === 0) return;
+
+		// Immediately load visible images
+		this.loadVisibleImages();
+
 		this.initListeners();
-		document.addEventListener('beforeunload', this.cleanup);
 	}
 
-	initElements(){
-		this.images = document.querySelectorAll('.wp-site-blocks img');
-		this.gallery = document.querySelector('dialog.gallery');
-		this.modal = new window.jvbModal(this.gallery, {
-			openMessage: 'Opened Gallery',
-			closeMessage: 'Closed Gallery',
-			open: '.open-gallery',
-			close: '.close'
-		});
+	loadVisibleImages() {
+		// Load first image immediately, plus any in viewport
+		this.images.forEach((img, index) => {
+			const rect = img.getBoundingClientRect();
+			const isVisible = rect.top < window.innerHeight && rect.bottom > 0;
 
-		this.modal.subscribe((event, data) => {
-			if (event === 'modal-open') {
-				this.openGallery();
-			} else if (event === 'modal-close') {
-				this.closeGallery();
+			// Always load first image, or if currently visible
+			if (index === 0 || isVisible) {
+				this.loadAppropriateImage(img);
+				img.dataset.loaded = 'true'; // Mark so we don't observe it
 			}
 		});
 	}
 
 	initListeners() {
 		this.resizeHandler = this.handleResize.bind(this);
-		this.clickHandler = this.handleClick.bind(this);
-		this.keysHandler = this.handleKeys.bind(this);
-		this.touchStartHandler = this.handleTouchStart.bind(this);
-		this.touchEndHandler = this.handleTouchEnd.bind(this);
-
-		document.addEventListener('click', this.clickHandler);
 		window.addEventListener('resize', this.resizeHandler);
-		console.log('window hash: ',window.location.hash);
-		let target = document.querySelector(window.location.hash);
-		if (target && target.tagName === 'LI') {
-			let trigger = target.querySelector('.open-gallery');
-			if (trigger) {
-				this.openGallery(trigger);
-			}
-		}
 
-		this.observer = new IntersectionObserver((entries) =>{
+		// Only observe images that weren't immediately loaded
+		this.observer = new IntersectionObserver((entries) => {
 			entries.forEach(entry => {
 				if (entry.isIntersecting) {
-					let img = entry.target;
-					if (!img.closest('dialog')) {
-						this.loadAppropriateImage(img);
-						this.observer.unobserve(img);
-					}
+					this.loadAppropriateImage(entry.target);
+					this.observer.unobserve(entry.target);
 				}
-			})
+			});
 		}, {
-			root: null,
 			rootMargin: '50px',
-			threshold: .1
+			threshold: 0.1
 		});
+
 		this.images.forEach(img => {
-			if (!img.closest('dialog')) {
+			if (!img.dataset.loaded) {
 				this.observer.observe(img);
 			}
-		})
+		});
 	}
 
-	initTouchHandling() {
-		this.isTouching = true;
-		this.touch.x = 0;
-		this.touch.y = 0;
-
-		this.gallery.addEventListener('touchstart', this.touchStartHandler);
-		this.gallery.addEventListener('touchend', this.touchEndHandler);
-	}
-	cancelTouchHandling() {
-		this.isTouching = false;
-		this.gallery.removeEventListener('touchstart', this.touchStartHandler);
-		this.gallery.removeEventListener('touchend', this.touchEndHandler);
-	}
-
-	handleTouchStart(e) {
-		this.touch.x = e.touches[0].clientX;
-		this.touch.y = e.touches[0].clientY;
-	}
-	handleTouchEnd(e) {
-		const diffX = e.changedTouches[0].clientX - this.touch.x;
-		const diffY = e.changedTouches[0].clientY - this.touch.y;
-
-		if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 50) {
-			this.navigateImages({target: this.gallery}, diffX < 0 ? 'next' : 'previous');
-		}
-	}
-	handleResize(e) {
-		window.debouncer.schedule(
-			'resize',
-			()=> {
-				const currentWidth = window.innerWidth;
-				if (Math.abs(currentWidth - this.currentWidth) > 100) {
-					this.currentWidth = currentWidth;
-					this.handleImageResize();
-				}
-			},
-			150
-		);
-	}
-	handleClick(e) {
-
-	}
-	handleKeys(e) {
-		//Escape handled by Modal.js
-		if (e.key === 'Tab') {
-			if (e.shiftKey) {
-
-			} else {
-
+	handleResize() {
+		window.debouncer.schedule('image-resize', () => {
+			const newWidth = window.innerWidth;
+			if (Math.abs(newWidth - this.currentWidth) > 100) {
+				this.currentWidth = newWidth;
+				this.updateVisibleImages();
 			}
+		}, 150);
+	}
+
+	updateVisibleImages() {
+		this.images.forEach(img => {
+			const rect = img.getBoundingClientRect();
+			if (rect.top < window.innerHeight && rect.bottom > 0) {
+				this.loadAppropriateImage(img, true);
+			}
+		});
+	}
+
+	loadAppropriateImage(img, forceUpdate = false) {
+		const targetSize = this.getTargetSize();
+		const newSrc = img.dataset[targetSize];
+
+		if (newSrc && (forceUpdate || newSrc !== img.currentSrc)) {
+			img.src = newSrc;
 		}
 	}
 
-	openGallery(target = null) {
-		document.addEventListener('keydown', this.clickHandler);
-		const id = target.dataset.opens;
-		this.initTouchHandling();
-		let focus;
-		if (!target) {
-			focus = this.images[0];
-		} else {
-			focus = target.dataset.focus;
-		}
-		if (focus) {
-			this.updateImage(this.gallery.querySelector(`#${focus}`));
-		}
-	}
-
-	closeGallery() {
-		this.cancelTouchHandling();
-		document.removeEventListener('keydown', this.keysHandler);
-		//Restore focus
-		if (this.lastFocusedElement) {
-			this.lastFocusedElement.focus();
-		}
+	getTargetSize() {
+		if (this.currentWidth < 768) return 'small';
+		if (this.currentWidth < 1200) return 'medium';
+		return 'full';
 	}
 
 	cleanup() {
-		this.observer.disconnect();
-		window.removeEventListener('resize', this.resizeHandler)
-		if (this.isTouching) {
-			this.cancelTouchHandling();
-			document.removeEventListener('keydown', this.keysHandler);
-		}
-		document.removeEventListener('click', this.clickHandler);
+		this.observer?.disconnect();
+		window.removeEventListener('resize', this.resizeHandler);
 	}
 }
+
+window.isLoaded = false;
+document.addEventListener('readystatechange', () => {
+	if (!window.isLoaded && document.querySelector('.wp-site-blocks img')) {
+		window.jvbMedia = new Media();
+		window.isLoaded = true;
+	}
+});

--
Gitblit v1.10.0