mirror of
https://github.com/jgthms/bulma.git
synced 2024-11-14 11:14:24 +00:00
Add carousel
This commit is contained in:
parent
1a6164b836
commit
6cebea9ce2
@ -58,6 +58,22 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getPreviousIndex = (list, current) => {
|
||||||
|
if (current === 0) {
|
||||||
|
return list.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getNextIndex = (list, current) => {
|
||||||
|
if (current === list.length - 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current + 1;
|
||||||
|
}
|
||||||
|
|
||||||
const THEME_COLOR = "success";
|
const THEME_COLOR = "success";
|
||||||
const STORAGE_CART_ID = "bulma-shop-cart-id";
|
const STORAGE_CART_ID = "bulma-shop-cart-id";
|
||||||
|
|
||||||
@ -366,10 +382,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const openModal = (product) => {
|
const openModal = (product) => {
|
||||||
$title = $modal.querySelector(".modal-title");
|
const $title = $modal.querySelector(".modal-title");
|
||||||
$body = $modal.querySelector(".modal-body");
|
const $body = $modal.querySelector(".modal-body");
|
||||||
$buttons = $modal.querySelector(".modal .buttons");
|
const $buttons = $modal.querySelector(".modal .buttons");
|
||||||
$close = $modal.querySelector(".modal .buttons .button.is-close");
|
|
||||||
|
|
||||||
$title.replaceChildren();
|
$title.replaceChildren();
|
||||||
buildHeading($title, product);
|
buildHeading($title, product);
|
||||||
@ -462,19 +477,14 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
const $option = El("", "option");
|
const $option = El("", "option");
|
||||||
$option.dataset.id = id;
|
$option.dataset.id = id;
|
||||||
$option.innerText = title;
|
$option.innerText = title;
|
||||||
|
$option.value = id;
|
||||||
// $option.addEventListener("click", (event) => {
|
|
||||||
// event.preventDefault();
|
|
||||||
// product.selectedVariant = id;
|
|
||||||
// update();
|
|
||||||
// });
|
|
||||||
|
|
||||||
$options.appendChild($option);
|
$options.appendChild($option);
|
||||||
});
|
});
|
||||||
|
|
||||||
$select.addEventListener("change", (event) => {
|
$select.addEventListener("change", (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
product.selectedVariant = id;
|
product.selectedVariant = event.target.value;
|
||||||
update();
|
update();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -507,7 +517,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
state.products.forEach((product) => {
|
state.products.forEach((product) => {
|
||||||
const { id, availableForSale, featuredImage } = product;
|
const { id, availableForSale, images } = product;
|
||||||
|
|
||||||
if (!availableForSale) {
|
if (!availableForSale) {
|
||||||
return;
|
return;
|
||||||
@ -518,17 +528,52 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
|
|
||||||
const el = El("card-content");
|
const el = El("card-content");
|
||||||
|
|
||||||
|
const $images = El("shop-product-images image is-square");
|
||||||
|
const $carousel = El("shop-product-carousel image is-square");
|
||||||
|
|
||||||
|
if (images) {
|
||||||
|
images.forEach(img => {
|
||||||
const $figure = El("shop-product-image image is-square", "figure");
|
const $figure = El("shop-product-image image is-square", "figure");
|
||||||
const $img = document.createElement("img");
|
const $img = document.createElement("img");
|
||||||
$img.src = featuredImage.url;
|
$img.src = img.url;
|
||||||
$figure.appendChild($img);
|
$figure.appendChild($img);
|
||||||
$card.appendChild($figure);
|
$carousel.appendChild($figure);
|
||||||
|
|
||||||
$figure.addEventListener("click", async (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
openModal(product);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$images.appendChild($carousel);
|
||||||
|
|
||||||
|
if (images.length > 1) {
|
||||||
|
const $prev = El("shop-product-arrow shop-product-prev", "button");
|
||||||
|
const $prevArrow = El("icon", "button");
|
||||||
|
const $prevIcon = El("fa-solid fa-arrow-left", "i");
|
||||||
|
$prevArrow.appendChild($prevIcon);
|
||||||
|
$prev.appendChild($prevArrow);
|
||||||
|
|
||||||
|
$prev.addEventListener("click", event => {
|
||||||
|
event.preventDefault();
|
||||||
|
product.selectedImage = getPreviousIndex(images, product.selectedImage);
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
|
||||||
|
const $next = El("shop-product-arrow shop-product-next", "button");
|
||||||
|
const $nextArrow = El("icon", "button");
|
||||||
|
const $nextIcon = El("fa-solid fa-arrow-right", "i");
|
||||||
|
$nextArrow.appendChild($nextIcon);
|
||||||
|
$next.appendChild($nextArrow);
|
||||||
|
|
||||||
|
$next.addEventListener("click", event => {
|
||||||
|
event.preventDefault();
|
||||||
|
product.selectedImage = getNextIndex(images, product.selectedImage);
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
|
||||||
|
$images.appendChild($prev);
|
||||||
|
$images.appendChild($next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$card.appendChild($images);
|
||||||
|
|
||||||
buildHeading(el, product);
|
buildHeading(el, product);
|
||||||
buildDescription(el, product);
|
buildDescription(el, product);
|
||||||
buildOptions(el, product);
|
buildOptions(el, product);
|
||||||
@ -552,6 +597,20 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateImages = () => {
|
||||||
|
state.products.forEach((product) => {
|
||||||
|
const $blocs = document.querySelectorAll(
|
||||||
|
`.shop-product-${getId(product.id)}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
$blocs.forEach(($bloc) => {
|
||||||
|
const $carousel = $bloc.querySelector(`.shop-product-carousel`);
|
||||||
|
const offset = product.selectedImage * 100;
|
||||||
|
$carousel.style.transform = `translateX(-${offset}%`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const updateCart = () => {
|
const updateCart = () => {
|
||||||
if (isEmpty(state.cart)) {
|
if (isEmpty(state.cart)) {
|
||||||
return;
|
return;
|
||||||
@ -577,13 +636,23 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
$item.dataset.id = line.id;
|
$item.dataset.id = line.id;
|
||||||
|
|
||||||
const $left = El("media-left");
|
const $left = El("media-left");
|
||||||
|
// const $images = El("shop-item-images");
|
||||||
const $image = El("shop-item-image image is-64x64");
|
const $image = El("shop-item-image image is-64x64");
|
||||||
const $img = El("", "img");
|
const $img = El("", "img");
|
||||||
|
|
||||||
if (product.featuredImage) {
|
if (product.featuredImage) {
|
||||||
$img.src = product.featuredImage.url;
|
$img.src = product.featuredImage.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (product.images) {
|
||||||
|
// product.images.forEach(img => {
|
||||||
|
// const $image = El("shop-item-image image is-64x64");
|
||||||
|
// const $img = El("", "img");
|
||||||
|
// $img.src = img.url;
|
||||||
|
// $image.appendChild($img);
|
||||||
|
// $images.appendChild($image);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
$image.appendChild($img);
|
$image.appendChild($img);
|
||||||
$left.appendChild($image);
|
$left.appendChild($image);
|
||||||
|
|
||||||
@ -720,17 +789,17 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
`.shop-product-${getId(product.id)}`,
|
`.shop-product-${getId(product.id)}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// $blocs.forEach(($bloc) => {
|
$blocs.forEach(($bloc) => {
|
||||||
// const $variants = $bloc.querySelectorAll(`.variants .button`);
|
const $variants = $bloc.querySelectorAll(`.shop-product-select option`);
|
||||||
|
|
||||||
// $variants.forEach(($el) => {
|
$variants.forEach(($el) => {
|
||||||
// if ($el.dataset.id === product.selectedVariant) {
|
if ($el.dataset.id === product.selectedVariant) {
|
||||||
// $el.classList.add(`is-${THEME_COLOR}`);
|
$el.setAttribute("selected", "");
|
||||||
// } else {
|
} else {
|
||||||
// $el.classList.remove(`is-${THEME_COLOR}`);
|
$el.removeAttribute("selected");
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
// });
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -739,6 +808,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
updateCart();
|
updateCart();
|
||||||
updateButtons();
|
updateButtons();
|
||||||
updateVariants();
|
updateVariants();
|
||||||
|
updateImages();
|
||||||
};
|
};
|
||||||
|
|
||||||
// HTML Elements
|
// HTML Elements
|
||||||
@ -855,6 +925,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
state.products = clean.products.map((product) => {
|
state.products = clean.products.map((product) => {
|
||||||
return {
|
return {
|
||||||
...product,
|
...product,
|
||||||
|
selectedImage: 0,
|
||||||
selectedVariant: product.variants[0].id,
|
selectedVariant: product.variants[0].id,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -235,7 +235,58 @@ breadcrumb:
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shop-product-images {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-product-images:hover .shop-product-arrow {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-product-arrow {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-product-arrow .icon {
|
||||||
|
background-color: rgb(0 0 0 / 10%);
|
||||||
|
border-radius: 9999px;
|
||||||
|
transition-duration: var(--shop-duration);
|
||||||
|
transition-property: background-color, color, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-product-arrow:hover .icon {
|
||||||
|
background-color: rgb(0 0 0 / 50%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-product-arrow:active .icon {
|
||||||
|
background-color: rgb(0 0 0 / 70%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-product-prev {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-product-next {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-product-carousel {
|
||||||
|
display: flex;
|
||||||
|
transition-duration: 300ms;
|
||||||
|
transition-property: transform;
|
||||||
|
}
|
||||||
|
|
||||||
.shop-product-image {
|
.shop-product-image {
|
||||||
|
flex-shrink: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
@ -246,7 +297,7 @@ breadcrumb:
|
|||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shop-product-image:hover img {
|
.shop-product-images:hover img {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,19 +394,21 @@ breadcrumb:
|
|||||||
{% include global/header.html %}
|
{% include global/header.html %}
|
||||||
|
|
||||||
{% capture shop_placeholder %}
|
{% capture shop_placeholder %}
|
||||||
<div class="shop-product is-placeholder">
|
<div class="card shop-product is-placeholder">
|
||||||
<figure class="shop-product-image image is-square is-skeleton">
|
<figure class="shop-product-image image is-square is-skeleton">
|
||||||
<img
|
<img
|
||||||
src="https://cdn.shopify.com/s/files/1/0837/0451/2860/files/unisex-basic-softstyle-t-shirt-white-front-6665a0551b5c8.jpg?v=1717936223"
|
src="https://cdn.shopify.com/s/files/1/0837/0451/2860/files/unisex-basic-softstyle-t-shirt-white-front-6665a0551b5c8.jpg?v=1717936223"
|
||||||
/>
|
/>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
<div class="card-content">
|
||||||
<div class="shop-product-heading">
|
<div class="shop-product-heading">
|
||||||
<h3 class="shop-product-title is-skeleton">The Bulma T-Shirt</h3>
|
<h3 class="shop-product-title is-skeleton">The Bulma T-Shirt</h3>
|
||||||
<div class="shop-product-price">
|
<div class="shop-product-price">
|
||||||
<span class="shop-price is-skeleton">$15</span>
|
<span class="shop-price is-skeleton">$15</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="shop-product-description content">
|
<div class="shop-product-description content">
|
||||||
<div class="shop-product-tagline content is-skeleton">
|
<div class="shop-product-tagline content is-skeleton">
|
||||||
Show your CSS skills and add a little extra motivation with the
|
Show your CSS skills and add a little extra motivation with the
|
||||||
@ -363,11 +416,13 @@ breadcrumb:
|
|||||||
with your favorite framework.
|
with your favorite framework.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="shop-product-buttons buttons">
|
<div class="shop-product-buttons buttons">
|
||||||
<button class="button is-medium is-skeleton">Add to cart</button
|
<button class="button is-skeleton">Add to cart</button
|
||||||
><button class="button is-text is-skeleton">Learn more</button>
|
><button class="button is-text is-skeleton">Learn more</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endcapture %}
|
{% endcapture %}
|
||||||
|
|
||||||
<div class="shop-hero">
|
<div class="shop-hero">
|
||||||
|
Loading…
Reference in New Issue
Block a user