mirror of
https://git.kh3group.com/georgebiri/khy_website.git
synced 2026-07-02 07:03:33 +00:00
refactor: enhance product detail page with dynamic content loading and improved gallery functionality
- Updated product-detail.html to replace static content with dynamic placeholders for images, title, description, sizes, and colors. - Modified main.js to implement dynamic loading of product details, including title, description, images, sizes, and colors. - Improved gallery functionality to support a carousel view for product images, including navigation buttons. - Adjusted CSS to add new transition durations and easing functions for smoother animations.
This commit is contained in:
parent
195286e6c8
commit
7295bcba7e
4 changed files with 533 additions and 785 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -194,71 +194,33 @@
|
|||
<div
|
||||
class="flex flex-row md:flex-col gap-3 md:gap-4 w-full md:w-32 overflow-x-auto md:overflow-visible"
|
||||
>
|
||||
<div
|
||||
class="w-32 h-32 bg-floral-white rounded-lg overflow-hidden cursor-pointer"
|
||||
>
|
||||
<img
|
||||
src="assets/images/outdoor_sofa_set.png"
|
||||
alt="Outdoor sofa set"
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="w-32 h-32 bg-floral-white rounded-lg overflow-hidden cursor-pointer"
|
||||
>
|
||||
<img
|
||||
src="assets/images/outdoor_sofa_set.png"
|
||||
alt="Outdoor sofa set 2"
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="w-32 h-32 bg-floral-white rounded-lg overflow-hidden cursor-pointer"
|
||||
>
|
||||
<img
|
||||
src="assets/images/outdoor_sofa_set.png"
|
||||
alt="Stuart sofa"
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="w-32 h-32 bg-floral-white rounded-lg overflow-hidden cursor-pointer"
|
||||
>
|
||||
<img
|
||||
src="assets/images/outdoor_sofa_set.png"
|
||||
alt="Maya sofa three seater"
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<!-- Thumbnail images will be populated dynamically -->
|
||||
</div>
|
||||
|
||||
<!-- Main Product Image -->
|
||||
<div
|
||||
class="w-full h-80 md:w-[500px] md:h-[500px] bg-floral-white rounded-lg overflow-hidden"
|
||||
>
|
||||
<img
|
||||
src="assets/images/asgaard_sofa.png"
|
||||
alt="Asgaard sofa"
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
<!-- Main product image will be populated dynamically -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Section - Product Details -->
|
||||
<div class="w-full md:w-[500px]">
|
||||
<!-- Product Title -->
|
||||
<h1 class="font-playfair font-normal text-4xl text-black mb-8">
|
||||
Asgaard sofa
|
||||
<h1
|
||||
class="font-playfair font-normal text-4xl text-black mb-8"
|
||||
id="product-title"
|
||||
>
|
||||
<!-- Product title will be populated dynamically -->
|
||||
</h1>
|
||||
|
||||
<!-- Product Description -->
|
||||
<p
|
||||
class="font-playfair font-normal text-sm text-black mb-12 max-w-md"
|
||||
id="product-description"
|
||||
>
|
||||
Setting the bar as one of the loudest speakers in its class, the
|
||||
Kilburn is a compact, stout-hearted hero with a well-balanced
|
||||
audio which boasts a clear midrange and extended highs for a
|
||||
sound.
|
||||
<!-- Product description will be populated dynamically -->
|
||||
</p>
|
||||
|
||||
<!-- Size Options -->
|
||||
|
|
@ -269,36 +231,7 @@
|
|||
Size
|
||||
</h3>
|
||||
<div class="grid grid-cols-6 gap-2" id="size-buttons-container">
|
||||
<button
|
||||
class="w-8 h-8 bg-uc-gold text-white font-playfair font-normal text-sm rounded flex items-center justify-center size-button"
|
||||
>
|
||||
L
|
||||
</button>
|
||||
<button
|
||||
class="w-8 h-8 bg-floral-white text-black font-playfair font-normal text-sm rounded flex items-center justify-center size-button"
|
||||
>
|
||||
XL
|
||||
</button>
|
||||
<button
|
||||
class="w-8 h-8 bg-floral-white text-black font-playfair font-normal text-sm rounded flex items-center justify-center size-button"
|
||||
>
|
||||
XS
|
||||
</button>
|
||||
<button
|
||||
class="w-8 h-8 bg-floral-white text-black font-playfair font-normal text-sm rounded flex items-center justify-center size-button"
|
||||
>
|
||||
S
|
||||
</button>
|
||||
<button
|
||||
class="w-8 h-8 bg-floral-white text-black font-playfair font-normal text-sm rounded flex items-center justify-center size-button"
|
||||
>
|
||||
M
|
||||
</button>
|
||||
<button
|
||||
class="w-8 h-8 bg-floral-white text-black font-playfair font-normal text-sm rounded flex items-center justify-center size-button"
|
||||
>
|
||||
2XL
|
||||
</button>
|
||||
<!-- Size buttons will be populated dynamically -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -309,12 +242,8 @@
|
|||
>
|
||||
Color
|
||||
</h3>
|
||||
<div class="flex gap-4">
|
||||
<button
|
||||
class="w-8 h-8 bg-purple-500 rounded-full border-2 border-black"
|
||||
></button>
|
||||
<button class="w-8 h-8 bg-black rounded-full"></button>
|
||||
<button class="w-8 h-8 bg-uc-gold rounded-full"></button>
|
||||
<div class="flex gap-4" id="color-buttons-container">
|
||||
<!-- Color buttons will be populated dynamically -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -365,62 +294,7 @@
|
|||
|
||||
<!-- Product Metadata -->
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<span
|
||||
class="font-playfair font-normal text-base text-quick-silver w-20"
|
||||
>Model No.</span
|
||||
>
|
||||
<span
|
||||
class="font-playfair font-medium text-base text-quick-silver mx-2"
|
||||
>:</span
|
||||
>
|
||||
<span
|
||||
class="font-playfair font-normal text-base text-quick-silver"
|
||||
>SS001</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<span
|
||||
class="font-playfair font-normal text-base text-quick-silver w-20"
|
||||
>Category</span
|
||||
>
|
||||
<span
|
||||
class="font-playfair font-medium text-base text-quick-silver mx-2"
|
||||
>:</span
|
||||
>
|
||||
<span
|
||||
class="font-playfair font-normal text-base text-quick-silver"
|
||||
>Sofas</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<span
|
||||
class="font-playfair font-normal text-base text-quick-silver w-20"
|
||||
>Tags</span
|
||||
>
|
||||
<span
|
||||
class="font-playfair font-medium text-base text-quick-silver mx-2"
|
||||
>:</span
|
||||
>
|
||||
<span
|
||||
class="font-playfair font-normal text-base text-quick-silver"
|
||||
>Sofa, Chair, Home, Shop</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<span
|
||||
class="font-playfair font-normal text-base text-quick-silver w-20"
|
||||
>Dimension</span
|
||||
>
|
||||
<span
|
||||
class="font-playfair font-medium text-base text-quick-silver mx-2"
|
||||
>:</span
|
||||
>
|
||||
<span
|
||||
class="font-playfair font-normal text-base text-quick-silver"
|
||||
>180cm x 85cm x 75cm</span
|
||||
>
|
||||
</div>
|
||||
<!-- Product metadata will be populated dynamically -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -439,45 +313,61 @@
|
|||
</div>
|
||||
|
||||
<!-- Copy -->
|
||||
<div class="max-w-5xl mx-auto space-y-6">
|
||||
<p
|
||||
class="font-playfair text-base leading-6 text-[#333333] text-justify"
|
||||
>
|
||||
Embodying the raw, wayward spirit of rock ‘n’ roll, the Kilburn
|
||||
portable active stereo speaker takes the unmistakable look and
|
||||
sound of Marshall, unplugs the chords, and takes the show on the
|
||||
road.
|
||||
</p>
|
||||
<p
|
||||
class="font-playfair text-base leading-6 text-[#333333] text-justify"
|
||||
>
|
||||
Weighing in under 7 pounds, the Kilburn is a lightweight piece of
|
||||
vintage styled engineering. Setting the bar as one of the loudest
|
||||
speakers in its class, the Kilburn is a compact, stout-hearted
|
||||
hero with a well-balanced audio which boasts a clear midrange and
|
||||
extended highs for a sound that is both articulate and pronounced.
|
||||
The analogue knobs allow you to fine tune the controls to your
|
||||
personal preferences while the guitar-influenced leather strap
|
||||
enables easy and stylish travel.
|
||||
</p>
|
||||
<div
|
||||
class="max-w-5xl mx-auto space-y-6"
|
||||
id="product-description-content"
|
||||
>
|
||||
<!-- Product description content will be populated dynamically -->
|
||||
</div>
|
||||
|
||||
<!-- Images -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 mt-10">
|
||||
<div class="rounded-[10px] bg-floral-white p-6">
|
||||
<img
|
||||
src="assets/images/asgaard_sofa.png"
|
||||
alt="Sofa variant left"
|
||||
class="w-full h-80 object-contain mx-auto"
|
||||
/>
|
||||
</div>
|
||||
<div class="rounded-[10px] bg-floral-white p-6">
|
||||
<img
|
||||
src="assets/images/asgaard_sofa.png"
|
||||
alt="Sofa variant right"
|
||||
class="w-full h-80 object-contain mx-auto"
|
||||
/>
|
||||
<div class="relative mt-10">
|
||||
<div
|
||||
class="grid grid-cols-1 md:grid-cols-2 gap-8"
|
||||
id="product-gallery-images"
|
||||
>
|
||||
<!-- Product gallery images will be populated dynamically -->
|
||||
</div>
|
||||
<!-- Back Arrow -->
|
||||
<button
|
||||
id="gallery-back-btn"
|
||||
class="absolute top-1/2 left-0 transform -translate-y-1/2 bg-white border border-gray-300 rounded-full p-3 shadow-lg hover:shadow-xl transition-all duration-200 opacity-0 pointer-events-none"
|
||||
style="display: none"
|
||||
>
|
||||
<svg
|
||||
class="w-6 h-6 text-gray-600"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 19l-7-7 7-7"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- Forward Arrow -->
|
||||
<button
|
||||
id="gallery-next-btn"
|
||||
class="absolute top-1/2 right-0 transform -translate-y-1/2 bg-white border border-gray-300 rounded-full p-3 shadow-lg hover:shadow-xl transition-all duration-200 opacity-0 pointer-events-none"
|
||||
style="display: none"
|
||||
>
|
||||
<svg
|
||||
class="w-6 h-6 text-gray-600"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
421
scripts/main.js
421
scripts/main.js
|
|
@ -222,10 +222,12 @@ function initSite() {
|
|||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Product detail page functionality
|
||||
(async function initProductDetail() {
|
||||
async function initProductDetail() {
|
||||
console.log("Product detail script running...");
|
||||
console.log("Current URL:", window.location.href);
|
||||
|
||||
// Check if we're on the product detail page
|
||||
const productTitle = document.querySelector("h1");
|
||||
|
|
@ -233,6 +235,7 @@ function initSite() {
|
|||
console.log("No h1 found, not on product detail page");
|
||||
return;
|
||||
}
|
||||
console.log("Found h1 element:", productTitle);
|
||||
|
||||
// Get product ID from URL
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
|
|
@ -269,161 +272,103 @@ function initSite() {
|
|||
}
|
||||
|
||||
// Update product title (the main product title, not the breadcrumb)
|
||||
const allH1s = document.querySelectorAll("h1");
|
||||
console.log("All H1 elements:", allH1s);
|
||||
if (allH1s.length > 1) {
|
||||
const mainProductTitle = allH1s[1]; // The second h1 should be the product title
|
||||
console.log("Main product title element:", mainProductTitle);
|
||||
if (mainProductTitle) {
|
||||
mainProductTitle.textContent = product.name;
|
||||
}
|
||||
}
|
||||
const productTitle = document.getElementById("product-title");
|
||||
console.log("Product title element:", productTitle);
|
||||
if (productTitle) {
|
||||
productTitle.textContent = product.name;
|
||||
console.log("Updated product title to:", product.name);
|
||||
}
|
||||
|
||||
// Update product description - find by text content
|
||||
const allParagraphs = document.querySelectorAll("p");
|
||||
console.log("All paragraphs:", allParagraphs);
|
||||
const descriptionEl = Array.from(allParagraphs).find(
|
||||
(p) =>
|
||||
p.textContent &&
|
||||
p.textContent.includes(
|
||||
"Setting the bar as one of the loudest speakers"
|
||||
)
|
||||
// Update product description
|
||||
const productDescription = document.getElementById("product-description");
|
||||
console.log("Product description element:", productDescription);
|
||||
if (productDescription) {
|
||||
productDescription.textContent = product.description;
|
||||
console.log("Updated product description to:", product.description);
|
||||
}
|
||||
|
||||
// Update main product image
|
||||
const mainImageContainer = document.querySelector(
|
||||
".w-full.h-80.md\\:w-\\[500px\\].md\\:h-\\[500px\\]"
|
||||
);
|
||||
console.log("Main image container:", mainImageContainer);
|
||||
if (mainImageContainer) {
|
||||
mainImageContainer.innerHTML = `
|
||||
<img
|
||||
src="${product.image}"
|
||||
alt="${product.alt || product.name}"
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
`;
|
||||
console.log("Updated main image to:", product.image);
|
||||
}
|
||||
|
||||
// Update thumbnail images
|
||||
const thumbnailContainer = document.querySelector(
|
||||
".flex.flex-row.md\\:flex-col.gap-3.md\\:gap-4"
|
||||
);
|
||||
console.log("Thumbnail container:", thumbnailContainer);
|
||||
if (thumbnailContainer && product.images) {
|
||||
thumbnailContainer.innerHTML = product.images
|
||||
.slice(0, 4)
|
||||
.map(
|
||||
(img, index) => `
|
||||
<div class="w-32 h-32 bg-floral-white rounded-lg overflow-hidden cursor-pointer">
|
||||
<img
|
||||
src="${img}"
|
||||
alt="${product.name} ${index + 1}"
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
console.log("Updated thumbnails with", product.images.length, "images");
|
||||
}
|
||||
|
||||
// Update size options
|
||||
const sizeContainer = document.getElementById("size-buttons-container");
|
||||
console.log("Size container:", sizeContainer);
|
||||
if (sizeContainer && product.sizes) {
|
||||
sizeContainer.innerHTML = product.sizes
|
||||
.map(
|
||||
(size, index) => `
|
||||
<button
|
||||
class="w-8 h-8 ${
|
||||
index === 0
|
||||
? "bg-uc-gold text-white"
|
||||
: "bg-floral-white text-black"
|
||||
} font-playfair font-normal text-sm rounded flex items-center justify-center size-button"
|
||||
>
|
||||
${size}
|
||||
</button>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
console.log("Updated size options with", product.sizes.length, "sizes");
|
||||
}
|
||||
|
||||
// Update color options
|
||||
const colorContainer = document.getElementById("color-buttons-container");
|
||||
console.log("Color container:", colorContainer);
|
||||
if (colorContainer && product.colors) {
|
||||
colorContainer.innerHTML = product.colors
|
||||
.map(
|
||||
(color, index) => `
|
||||
<button
|
||||
class="w-8 h-8 rounded-full ${
|
||||
index === 0 ? "border-2 border-black" : ""
|
||||
}"
|
||||
style="background-color: ${color}"
|
||||
></button>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
console.log(
|
||||
"Updated color options with",
|
||||
product.colors.length,
|
||||
"colors"
|
||||
);
|
||||
console.log("Description element:", descriptionEl);
|
||||
if (descriptionEl) {
|
||||
descriptionEl.textContent = product.description;
|
||||
}
|
||||
|
||||
// Update main product image - find by alt text
|
||||
const allImages = document.querySelectorAll("img");
|
||||
console.log("All images:", allImages);
|
||||
const mainImage = Array.from(allImages).find(
|
||||
(img) => img.alt && img.alt.includes("Asgaard sofa")
|
||||
);
|
||||
console.log("Main image element:", mainImage);
|
||||
if (mainImage) {
|
||||
mainImage.src = product.image;
|
||||
mainImage.alt = product.alt || product.name;
|
||||
}
|
||||
|
||||
// Update thumbnail images - find by alt text
|
||||
if (product.images && product.images.length > 0) {
|
||||
const allImages = document.querySelectorAll("img");
|
||||
const thumbnails = Array.from(allImages).filter(
|
||||
(img) =>
|
||||
img.alt &&
|
||||
(img.alt.includes("Outdoor sofa set") ||
|
||||
img.alt.includes("Stuart sofa") ||
|
||||
img.alt.includes("Maya sofa"))
|
||||
);
|
||||
console.log("Thumbnail images found:", thumbnails);
|
||||
product.images.forEach((imageSrc, index) => {
|
||||
if (thumbnails[index]) {
|
||||
thumbnails[index].src = imageSrc;
|
||||
thumbnails[index].alt = product.alt || product.name;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update size options - use the specific size-button class
|
||||
if (product.sizes) {
|
||||
const sizeButtons = document.querySelectorAll(".size-button");
|
||||
console.log("Size buttons found:", sizeButtons);
|
||||
|
||||
// Hide all size buttons first
|
||||
sizeButtons.forEach((button) => {
|
||||
button.style.display = "none";
|
||||
});
|
||||
|
||||
// Show and update only the buttons we need
|
||||
product.sizes.forEach((size, index) => {
|
||||
if (sizeButtons[index]) {
|
||||
sizeButtons[index].style.display = "flex";
|
||||
sizeButtons[index].textContent = size;
|
||||
sizeButtons[index].setAttribute("data-size", size);
|
||||
// Set selected size
|
||||
if (size === product.selectedSize) {
|
||||
sizeButtons[index].classList.remove(
|
||||
"bg-floral-white",
|
||||
"text-black"
|
||||
);
|
||||
sizeButtons[index].classList.add("bg-uc-gold", "text-white");
|
||||
sizeButtons[index].classList.add("selected");
|
||||
} else {
|
||||
sizeButtons[index].classList.remove(
|
||||
"bg-uc-gold",
|
||||
"text-white",
|
||||
"selected"
|
||||
);
|
||||
sizeButtons[index].classList.add("bg-floral-white", "text-black");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add click event listeners for size buttons
|
||||
sizeButtons.forEach((button) => {
|
||||
button.addEventListener("click", function () {
|
||||
// Remove selected state from all size buttons
|
||||
sizeButtons.forEach((btn) => {
|
||||
btn.classList.remove("bg-uc-gold", "text-white", "selected");
|
||||
btn.classList.add("bg-floral-white", "text-black");
|
||||
});
|
||||
|
||||
// Add selected state to clicked button
|
||||
this.classList.remove("bg-floral-white", "text-black");
|
||||
this.classList.add("bg-uc-gold", "text-white", "selected");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Update color options - find only the rounded color buttons, not size buttons
|
||||
if (product.colors) {
|
||||
const allButtons = document.querySelectorAll("button");
|
||||
const colorButtons = Array.from(allButtons).filter(
|
||||
(button) =>
|
||||
button.classList.contains("w-8") &&
|
||||
button.classList.contains("h-8") &&
|
||||
button.classList.contains("rounded-full") &&
|
||||
!button.textContent // Color buttons should not have text content
|
||||
);
|
||||
console.log("Color buttons found:", colorButtons);
|
||||
|
||||
product.colors.forEach((color, index) => {
|
||||
if (colorButtons[index]) {
|
||||
colorButtons[index].style.backgroundColor = color.value;
|
||||
colorButtons[index].setAttribute(
|
||||
"data-color",
|
||||
color.name || color.value
|
||||
);
|
||||
// Set selected color
|
||||
if (color.selected) {
|
||||
colorButtons[index].classList.add(
|
||||
"border-2",
|
||||
"border-black",
|
||||
"selected"
|
||||
);
|
||||
} else {
|
||||
colorButtons[index].classList.remove(
|
||||
"border-2",
|
||||
"border-black",
|
||||
"selected"
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add click event listeners for color buttons
|
||||
colorButtons.forEach((button) => {
|
||||
button.addEventListener("click", function () {
|
||||
// Remove selected state from all color buttons
|
||||
colorButtons.forEach((btn) => {
|
||||
btn.classList.remove("border-2", "border-black", "selected");
|
||||
});
|
||||
|
||||
// Add selected state to clicked button
|
||||
this.classList.add("border-2", "border-black", "selected");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Update product metadata - find by text content
|
||||
|
|
@ -450,8 +395,7 @@ function initSite() {
|
|||
categoryLabel.parentElement.querySelector("span:last-child");
|
||||
if (categoryValue) {
|
||||
categoryValue.textContent =
|
||||
product.category.charAt(0).toUpperCase() +
|
||||
product.category.slice(1);
|
||||
product.category.charAt(0).toUpperCase() + product.category.slice(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -485,45 +429,133 @@ function initSite() {
|
|||
}
|
||||
|
||||
// Update description content
|
||||
if (product.descriptionLong) {
|
||||
const descriptionContainer = document.querySelector(
|
||||
".max-w-5xl.mx-auto.space-y-6"
|
||||
);
|
||||
if (descriptionContainer) {
|
||||
const descriptionParagraphs =
|
||||
descriptionContainer.querySelectorAll("p");
|
||||
console.log("Description paragraphs found:", descriptionParagraphs);
|
||||
const descriptionContainer = document.getElementById(
|
||||
"product-description-content"
|
||||
);
|
||||
console.log("Description content container:", descriptionContainer);
|
||||
if (descriptionContainer && product.descriptionLong) {
|
||||
descriptionContainer.innerHTML = product.descriptionLong
|
||||
.map(
|
||||
(paragraph) => `
|
||||
<p class="font-playfair text-base leading-6 text-[#333333] text-justify">
|
||||
${paragraph}
|
||||
</p>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
console.log(
|
||||
"Updated description content with",
|
||||
product.descriptionLong.length,
|
||||
"paragraphs"
|
||||
);
|
||||
}
|
||||
|
||||
// Update each paragraph with the product's description content
|
||||
product.descriptionLong.forEach((paragraph, index) => {
|
||||
if (descriptionParagraphs[index]) {
|
||||
descriptionParagraphs[index].textContent = paragraph;
|
||||
}
|
||||
});
|
||||
}
|
||||
// Update gallery images with carousel
|
||||
const galleryContainer = document.getElementById("product-gallery-images");
|
||||
const galleryBackBtn = document.getElementById("gallery-back-btn");
|
||||
const galleryNextBtn = document.getElementById("gallery-next-btn");
|
||||
console.log("Gallery container:", galleryContainer);
|
||||
|
||||
if (galleryContainer && product.galleryPairs) {
|
||||
// galleryPairs is now a simple array of image paths
|
||||
const allGalleryImages = product.galleryPairs;
|
||||
|
||||
// Store gallery images for carousel
|
||||
window.currentGalleryImages = allGalleryImages;
|
||||
window.currentGalleryIndex = 0;
|
||||
|
||||
// Render initial gallery view
|
||||
renderGalleryCarousel();
|
||||
|
||||
// Show navigation arrows for looped carousel (always show if more than 2 images)
|
||||
if (allGalleryImages.length > 2) {
|
||||
galleryBackBtn.style.display = "block";
|
||||
galleryNextBtn.style.display = "block";
|
||||
} else {
|
||||
galleryBackBtn.style.display = "none";
|
||||
galleryNextBtn.style.display = "none";
|
||||
}
|
||||
|
||||
// Update gallery images
|
||||
if (product.galleryPairs) {
|
||||
// Find gallery images by alt text
|
||||
const allImages = document.querySelectorAll("img");
|
||||
const galleryImages = Array.from(allImages).filter(
|
||||
(img) =>
|
||||
img.alt &&
|
||||
(img.alt.includes("Sofa variant left") ||
|
||||
img.alt.includes("Sofa variant right"))
|
||||
);
|
||||
console.log("Gallery images found:", galleryImages);
|
||||
console.log(
|
||||
"Gallery carousel:",
|
||||
allGalleryImages.length,
|
||||
"gallery images total (sliding)"
|
||||
);
|
||||
}
|
||||
|
||||
product.galleryPairs.forEach((pair, index) => {
|
||||
if (galleryImages[index * 2]) {
|
||||
galleryImages[index * 2].src = pair.left;
|
||||
galleryImages[index * 2].alt = product.alt || product.name;
|
||||
}
|
||||
if (galleryImages[index * 2 + 1]) {
|
||||
galleryImages[index * 2 + 1].src = pair.right;
|
||||
galleryImages[index * 2 + 1].alt = product.alt || product.name;
|
||||
}
|
||||
function renderGalleryCarousel() {
|
||||
if (!window.currentGalleryImages || !galleryContainer) return;
|
||||
|
||||
// Handle single image vs multiple images
|
||||
if (window.currentGalleryImages.length === 1) {
|
||||
// Single image - show only one image, hide arrows
|
||||
const image1 = window.currentGalleryImages[0];
|
||||
galleryContainer.innerHTML = `
|
||||
<div class="rounded-[10px] bg-floral-white p-6 transition-all duration-1500 ease-out" id="gallery-image-1">
|
||||
<img
|
||||
src="${image1}"
|
||||
alt="${product.name} gallery"
|
||||
class="w-full h-80 object-contain mx-auto"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Hide arrows for single image
|
||||
galleryBackBtn.style.display = "none";
|
||||
galleryNextBtn.style.display = "none";
|
||||
} else {
|
||||
// Multiple images - show 2 images with carousel
|
||||
const image1 = window.currentGalleryImages[window.currentGalleryIndex];
|
||||
const image2Index =
|
||||
(window.currentGalleryIndex + 1) % window.currentGalleryImages.length;
|
||||
const image2 = window.currentGalleryImages[image2Index];
|
||||
|
||||
galleryContainer.innerHTML = `
|
||||
<div class="rounded-[10px] bg-floral-white p-6 transition-all duration-1500 ease-out" id="gallery-image-1">
|
||||
<img
|
||||
src="${image1}"
|
||||
alt="${product.name} gallery"
|
||||
class="w-full h-80 object-contain mx-auto"
|
||||
/>
|
||||
</div>
|
||||
<div class="rounded-[10px] bg-floral-white p-6 transition-all duration-1500 ease-out" id="gallery-image-2">
|
||||
<img
|
||||
src="${image2}"
|
||||
alt="${product.name} gallery"
|
||||
class="w-full h-80 object-contain mx-auto"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Show arrows for multiple images
|
||||
galleryBackBtn.style.display = "block";
|
||||
galleryBackBtn.style.opacity = "1";
|
||||
galleryBackBtn.style.pointerEvents = "auto";
|
||||
|
||||
galleryNextBtn.style.display = "block";
|
||||
galleryNextBtn.style.opacity = "1";
|
||||
galleryNextBtn.style.pointerEvents = "auto";
|
||||
}
|
||||
}
|
||||
|
||||
// Add click handlers for looped gallery carousel navigation
|
||||
if (galleryBackBtn) {
|
||||
galleryBackBtn.addEventListener("click", function () {
|
||||
// Left arrow moves forward: if at last position, go to 0
|
||||
window.currentGalleryIndex =
|
||||
(window.currentGalleryIndex + 1) % window.currentGalleryImages.length;
|
||||
renderGalleryCarousel();
|
||||
});
|
||||
}
|
||||
|
||||
if (galleryNextBtn) {
|
||||
galleryNextBtn.addEventListener("click", function () {
|
||||
// Right arrow moves backward: if at 0, go to last position
|
||||
window.currentGalleryIndex =
|
||||
window.currentGalleryIndex === 0
|
||||
? window.currentGalleryImages.length - 1
|
||||
: window.currentGalleryIndex - 1;
|
||||
renderGalleryCarousel();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -608,7 +640,6 @@ function initSite() {
|
|||
} catch (error) {
|
||||
console.error("Error loading product data:", error);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
// Product Comparison Page Functionality
|
||||
|
|
@ -1001,6 +1032,8 @@ if (window.location.pathname.includes("product-detail.html")) {
|
|||
"Product detail page detected, initializing compare functionality immediately"
|
||||
);
|
||||
initProductDetailCompare();
|
||||
// Also initialize product detail loading
|
||||
initProductDetail();
|
||||
}
|
||||
|
||||
// Also try to initialize on DOMContentLoaded
|
||||
|
|
@ -1009,6 +1042,8 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
if (window.location.pathname.includes("product-detail.html")) {
|
||||
console.log("Product detail page detected in DOMContentLoaded");
|
||||
initProductDetailCompare();
|
||||
// Also initialize product detail loading
|
||||
initProductDetail();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -1116,7 +1151,7 @@ function initHeroCarousel() {
|
|||
|
||||
// Ensure image always fits its container uniformly
|
||||
heroImage.style.height = "100%";
|
||||
heroImage.style.objectFit = "cover";
|
||||
heroImage.style.objectFit = "cover";
|
||||
|
||||
// Fade in new image
|
||||
heroImage.style.opacity = "1";
|
||||
|
|
|
|||
|
|
@ -1922,10 +1922,22 @@ video {
|
|||
transition-duration: 300ms;
|
||||
}
|
||||
|
||||
.duration-500 {
|
||||
transition-duration: 500ms;
|
||||
}
|
||||
|
||||
.duration-1000 {
|
||||
transition-duration: 1000ms;
|
||||
}
|
||||
|
||||
.ease-in-out {
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.ease-out {
|
||||
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.hover\:-translate-y-0\.5:hover {
|
||||
--tw-translate-y: -0.125rem;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue