Skip to main content
The gallery functions control the main property image viewer, featuring a large main image display with thumbnail navigation and pagination controls.

State Variables

The gallery system maintains the following state:
let galleryImages = [];           // Array of image URLs
let galleryCurrentIndex = 0;      // Currently displayed image index
let galleryThumbPage = 0;         // Current thumbnail page
let galleryThumbsPerPage = 8;    // Thumbnails per page (4 on mobile)

renderGallery

Initializes and renders the complete gallery system with main image, thumbnails, and navigation controls.
const renderGallery = (images) => {
  // Full implementation in ~/workspace/source/app.js:237-392
}
images
string[]
required
Array of image URLs or paths. URLs starting with “http” are used as-is; others are prefixed with images/. Falls back to placeholder if array is empty.

Behavior

  • Image resolution: Converts relative paths to images/{filename} format
  • Fallback handling: Shows placeholder image when no images provided
  • State initialization: Populates lightboxImages and galleryImages arrays
  • Responsive setup: Adjusts galleryThumbsPerPage based on viewport (4 for mobile, 8 for desktop)
  • Photo counter: Updates the photo count display element
  • Event binding: Attaches click handlers for navigation, lightbox opening, and window resize
  • Initial display: Renders thumbnails and activates first image

Side Effects

  • Updates DOM elements: #gallery-main-image, #gallery-thumbnails, #photo-count
  • Binds click handlers to #thumb-prev, #thumb-next, #gallery-main-prev, #gallery-main-next
  • Makes main image clickable to open lightbox
  • Registers resize listener to handle responsive thumbnail adjustments
  • Controls visibility of 360° tour button (shown only on first image)

Example Usage

const propertyImages = [
  "https://example.com/image1.jpg",
  "photo2.jpg",  // Becomes "images/photo2.jpg"
  "photo3.jpg"
];
renderGallery(propertyImages);
// Displays main image, 8 thumbnails (or 4 on mobile), and navigation controls

setActive

Changes the currently displayed image in the gallery.
const setActive = (index) => {
  galleryCurrentIndex = index;
  mainImage.src = resolvedImages[index];
  mainImage.alt = `Imagen ${index + 1}`;
  updateGalleryThumbHighlights();
  // Controls 360° button visibility
}
index
number
required
Zero-based index of the image to display

Behavior

  • Updates galleryCurrentIndex state
  • Changes main image src and alt attributes
  • Calls updateGalleryThumbHighlights() to update thumbnail styling
  • Shows 360° tour button only when index === 0 (first image)
Location: Defined inside renderGallery() at ~/workspace/source/app.js:261-272

updateGalleryThumbHighlights

Updates the visual styling of thumbnails to indicate the active image.
const updateGalleryThumbHighlights = () => {
  const thumbs = thumbContainer.querySelectorAll(".thumbnail-item");
  const startIndex = galleryThumbPage * galleryThumbsPerPage;
  
  thumbs.forEach((thumb, i) => {
    const actualIndex = startIndex + i;
    const isActive = actualIndex === galleryCurrentIndex;
    thumb.classList.toggle("ring-2", isActive);
    thumb.classList.toggle("ring-primary", isActive);
    thumb.classList.toggle("opacity-80", !isActive);
    thumb.classList.toggle("opacity-100", isActive);
  });
};

Behavior

  • Queries all .thumbnail-item elements
  • Calculates actual image index based on current pagination page
  • Toggles CSS classes:
    • Active: ring-2 ring-primary opacity-100
    • Inactive: opacity-80
Location: Defined inside renderGallery() at ~/workspace/source/app.js:274-286

renderThumbnails

Renders the current page of thumbnails with pagination controls.
const renderThumbnails = () => {
  thumbContainer.innerHTML = "";
  galleryThumbsPerPage = getThumbsPerPage();
  
  const totalPages = getTotalPages(resolvedImages.length, galleryThumbsPerPage);
  const startIndex = galleryThumbPage * galleryThumbsPerPage;
  const endIndex = Math.min(startIndex + galleryThumbsPerPage, resolvedImages.length);
  
  // Creates thumbnail elements for current page
  // Updates navigation button states
  // Renders pagination dots
}

Behavior

  • Clears thumbnail container
  • Recalculates galleryThumbsPerPage for current viewport
  • Creates thumbnail DOM elements for visible page
  • Binds click handlers:
    • Single click: Calls setActive(i)
    • Double click: Calls openLightbox(i)
  • Updates navigation button disabled states
  • Renders pagination dots with renderPaginationDots()

DOM Structure

Each thumbnail has:
  • Classes: thumbnail-item aspect-square rounded-md overflow-hidden bg-slate-100 dark:bg-slate-700 cursor-pointer transition
  • Active styling: ring-2 ring-primary opacity-100
  • Inactive styling: opacity-80 hover:opacity-100
Location: Defined inside renderGallery() at ~/workspace/source/app.js:288-322

galleryNextImage

Navigates to the next image in the gallery, with wraparound.
const galleryNextImage = () => {
  const newIndex = (galleryCurrentIndex + 1) % resolvedImages.length;
  setActive(newIndex);
  // Auto-advance page if needed
  const newPage = Math.floor(newIndex / galleryThumbsPerPage);
  if (newPage !== galleryThumbPage) {
    galleryThumbPage = newPage;
    renderThumbnails();
  }
}

Behavior

  • Increments index with modulo wraparound (last → first)
  • Calls setActive() to update display
  • Auto-advances thumbnail page if new image is on different page
Location: Defined inside renderGallery() at ~/workspace/source/app.js:324-333

galleryPrevImage

Navigates to the previous image in the gallery, with wraparound.
const galleryPrevImage = () => {
  const newIndex = (galleryCurrentIndex - 1 + resolvedImages.length) % resolvedImages.length;
  setActive(newIndex);
  // Auto-advance page if needed
  const newPage = Math.floor(newIndex / galleryThumbsPerPage);
  if (newPage !== galleryThumbPage) {
    galleryThumbPage = newPage;
    renderThumbnails();
  }
}

Behavior

  • Decrements index with modulo wraparound (first → last)
  • Calls setActive() to update display
  • Auto-advances thumbnail page if new image is on different page
Location: Defined inside renderGallery() at ~/workspace/source/app.js:335-344

thumbNextPage

Advances to the next page of thumbnails.
const thumbNextPage = () => {
  const totalPages = getTotalPages(resolvedImages.length, galleryThumbsPerPage);
  if (galleryThumbPage < totalPages - 1) {
    galleryThumbPage++;
    renderThumbnails();
  }
}

Behavior

  • Checks if next page exists
  • Increments galleryThumbPage
  • Calls renderThumbnails() to update display
Location: Defined inside renderGallery() at ~/workspace/source/app.js:346-352

thumbPrevPage

Goes back to the previous page of thumbnails.
const thumbPrevPage = () => {
  if (galleryThumbPage > 0) {
    galleryThumbPage--;
    renderThumbnails();
  }
}

Behavior

  • Checks if previous page exists
  • Decrements galleryThumbPage
  • Calls renderThumbnails() to update display
Location: Defined inside renderGallery() at ~/workspace/source/app.js:354-359

Integration

The gallery functions work together in this flow:
  1. renderGallery(images) initializes the system
  2. renderThumbnails() displays current page of thumbnails
  3. setActive(index) changes the main image
  4. updateGalleryThumbHighlights() updates thumbnail styling
  5. Navigation functions (galleryNextImage, galleryPrevImage, thumbNextPage, thumbPrevPage) modify state and trigger re-renders

Event Handlers

  • Thumbnail click: setActive(i)
  • Thumbnail double-click: openLightbox(i)
  • Main image click: openLightbox(galleryCurrentIndex)
  • Window resize: Recalculates galleryThumbsPerPage and re-renders
  • Navigation buttons: Bound to respective next/prev functions

Build docs developers (and LLMs) love