Bootstrap
Bootstrap4
Loading
Product
Html
Css
Template de chargement de produit Bootstrap 4 avec design élégant et moderne.
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="copyright" content="MEZGANI Said" />
<meta name="author" content="AngularForAll" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Loading Product Bootstrap 4 | AngularForAll</title>
<!-- Bootstrap 5 + Icons -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', sans-serif;
background: #f8fafc;
min-height: 100vh;
}
/* Navbar */
.navbar {
background: white !important;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.03);
padding: 1rem 0;
}
.navbar-brand {
font-weight: 700;
font-size: 1.5rem;
color: #1e293b !important;
}
.navbar-brand span {
color: #3b82f6;
}
/* Header de page */
.page-header {
background: white;
border-bottom: 1px solid #e2e8f0;
padding: 1.5rem 0;
margin-bottom: 2rem;
}
.page-title {
font-weight: 700;
font-size: 1.8rem;
color: #0f172a;
margin-bottom: 0.25rem;
}
.breadcrumb {
margin-bottom: 0;
}
.breadcrumb-item a {
color: #64748b;
text-decoration: none;
}
.result-count {
color: #64748b;
font-size: 0.9rem;
}
/* Filtres sidebar */
.filter-section {
background: white;
border-radius: 16px;
padding: 1.5rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.02);
border: 1px solid #e2e8f0;
margin-bottom: 1.5rem;
}
.filter-title {
font-weight: 700;
font-size: 1rem;
margin-bottom: 1rem;
color: #1e293b;
}
/* Squelettes de chargement (Skeleton Loaders) */
.skeleton {
background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%);
background-size: 200% 100%;
animation: skeleton-loading 1.5s ease-in-out infinite;
border-radius: 8px;
}
@keyframes skeleton-loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.skeleton-text {
height: 14px;
margin-bottom: 8px;
border-radius: 6px;
}
.skeleton-text-sm {
height: 12px;
width: 60%;
margin-bottom: 8px;
border-radius: 6px;
}
.skeleton-text-lg {
height: 18px;
width: 80%;
margin-bottom: 10px;
border-radius: 6px;
}
.skeleton-filter {
height: 30px;
margin-bottom: 12px;
border-radius: 8px;
}
.skeleton-checkbox {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.skeleton-checkbox .skeleton-box {
width: 18px;
height: 18px;
border-radius: 4px;
margin-right: 10px;
}
/* Product Card Skeleton */
.product-card-skeleton {
background: white;
border-radius: 16px;
padding: 1rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
border: 1px solid #e2e8f0;
height: 100%;
}
.skeleton-image {
width: 100%;
height: 180px;
border-radius: 12px;
margin-bottom: 1rem;
}
.skeleton-badge {
width: 70px;
height: 24px;
border-radius: 20px;
margin-bottom: 10px;
}
.skeleton-price {
width: 100px;
height: 24px;
border-radius: 6px;
margin-top: 10px;
}
.skeleton-button {
width: 100%;
height: 40px;
border-radius: 8px;
margin-top: 15px;
}
/* Product Card Réelle (pour la démonstration) */
.product-card {
background: white;
border-radius: 16px;
padding: 1rem;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
border: 1px solid #e2e8f0;
height: 100%;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.product-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.08);
border-color: #cbd5e1;
}
.product-badge {
position: absolute;
top: 1rem;
left: 1rem;
background: #ef4444;
color: white;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
z-index: 2;
}
.product-badge.new {
background: #10b981;
}
.product-badge.sale {
background: #f59e0b;
}
.product-image {
width: 100%;
height: 180px;
object-fit: cover;
border-radius: 12px;
margin-bottom: 1rem;
background: #f1f5f9;
}
.product-category {
color: #64748b;
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 0.25rem;
}
.product-title {
font-weight: 700;
font-size: 1rem;
color: #1e293b;
margin-bottom: 0.5rem;
line-height: 1.4;
}
.product-rating {
display: flex;
align-items: center;
gap: 6px;
margin-bottom: 0.5rem;
}
.stars {
color: #fbbf24;
letter-spacing: 2px;
font-size: 0.85rem;
}
.rating-count {
color: #64748b;
font-size: 0.8rem;
}
.product-price {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 1rem;
}
.current-price {
font-weight: 700;
font-size: 1.3rem;
color: #1e293b;
}
.old-price {
color: #94a3b8;
text-decoration: line-through;
font-size: 0.9rem;
}
.btn-add-cart {
width: 100%;
background: #1e293b;
color: white;
border: none;
border-radius: 8px;
padding: 0.7rem;
font-weight: 600;
font-size: 0.9rem;
transition: all 0.2s;
}
.btn-add-cart:hover {
background: #3b82f6;
}
/* Loader spinner */
.loader-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(4px);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
transition: opacity 0.3s ease;
}
.loader-content {
text-align: center;
}
.spinner {
width: 60px;
height: 60px;
border: 4px solid #e2e8f0;
border-top-color: #3b82f6;
border-radius: 50%;
animation: spin 0.8s linear infinite;
margin: 0 auto 1rem;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.loader-text {
color: #1e293b;
font-weight: 600;
font-size: 1.1rem;
}
.loader-subtext {
color: #64748b;
font-size: 0.9rem;
margin-top: 0.25rem;
}
/* Progress bar de chargement */
.loading-progress {
width: 200px;
height: 4px;
background: #e2e8f0;
border-radius: 4px;
margin: 1rem auto 0;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: #3b82f6;
border-radius: 4px;
animation: progressFill 2s ease-in-out infinite;
width: 0%;
}
@keyframes progressFill {
0% { width: 0%; }
50% { width: 70%; }
100% { width: 100%; }
}
/* Pagination skeleton */
.pagination-skeleton {
display: flex;
justify-content: center;
gap: 8px;
margin-top: 2rem;
}
.skeleton-page {
width: 40px;
height: 40px;
border-radius: 8px;
}
/* Animation de fondu */
.fade-in {
animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Responsive */
@media (max-width: 768px) {
.page-title {
font-size: 1.5rem;
}
.skeleton-image {
height: 150px;
}
.product-image {
height: 150px;
}
}
/* Mode démonstration - basculer entre loading et loaded */
.demo-controls {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 10000;
display: flex;
gap: 10px;
}
.demo-btn {
background: white;
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 10px 20px;
font-weight: 600;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.2s;
}
.demo-btn:hover {
background: #3b82f6;
color: white;
border-color: #3b82f6;
}
/* Conteneur principal */
.products-container {
transition: opacity 0.3s ease;
}
.products-container.loading {
opacity: 0.6;
pointer-events: none;
}
</style>
</head>
<body>
<!-- Loader Overlay -->
<div class="loader-overlay" id="loaderOverlay">
<div class="loader-content">
<div class="spinner"></div>
<div class="loader-text">Chargement des produits...</div>
<div class="loader-subtext">Cela ne prendra qu'un instant</div>
<div class="loading-progress">
<div class="progress-fill"></div>
</div>
</div>
</div>
<!-- Navbar -->
<nav class="navbar">
<div class="container">
<a class="navbar-brand" href="#">
<i class="bi bi-bag-fill me-2" style="color: #3b82f6;"></i>Shop<span>Now</span>
</a>
<div class="d-flex gap-3">
<a href="#" class="text-dark"><i class="bi bi-search fs-5"></i></a>
<a href="#" class="text-dark"><i class="bi bi-heart fs-5"></i></a>
<a href="#" class="text-dark position-relative">
<i class="bi bi-cart3 fs-5"></i>
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">2</span>
</a>
</div>
</div>
</nav>
<!-- Header de page -->
<div class="page-header">
<div class="container">
<h1 class="page-title">Tous les produits</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Accueil</a></li>
<li class="breadcrumb-item"><a href="#">Boutique</a></li>
<li class="breadcrumb-item active">Produits</li>
</ol>
</nav>
</div>
</div>
<!-- Contenu principal -->
<div class="container pb-5">
<div class="row">
<!-- Sidebar Filtres -->
<div class="col-lg-3">
<!-- Filtres Skeleton (affiché pendant le chargement) -->
<div id="filtersSkeleton">
<div class="filter-section">
<div class="filter-title skeleton skeleton-text"></div>
<div class="skeleton skeleton-filter"></div>
<div class="skeleton skeleton-filter"></div>
<div class="skeleton skeleton-filter"></div>
</div>
<div class="filter-section">
<div class="filter-title skeleton skeleton-text"></div>
<div class="skeleton-checkbox">
<div class="skeleton skeleton-box"></div>
<div class="skeleton skeleton-text-sm" style="flex:1;"></div>
</div>
<div class="skeleton-checkbox">
<div class="skeleton skeleton-box"></div>
<div class="skeleton skeleton-text-sm" style="flex:1;"></div>
</div>
<div class="skeleton-checkbox">
<div class="skeleton skeleton-box"></div>
<div class="skeleton skeleton-text-sm" style="flex:1;"></div>
</div>
<div class="skeleton-checkbox">
<div class="skeleton skeleton-box"></div>
<div class="skeleton skeleton-text-sm" style="flex:1;"></div>
</div>
</div>
<div class="filter-section">
<div class="filter-title skeleton skeleton-text"></div>
<div class="skeleton skeleton-text-sm" style="width:100%;"></div>
<div class="skeleton" style="height:6px; margin:15px 0;"></div>
<div class="d-flex justify-content-between">
<div class="skeleton skeleton-text-sm" style="width:40px;"></div>
<div class="skeleton skeleton-text-sm" style="width:40px;"></div>
</div>
</div>
</div>
<!-- Filtres Réels (cachés initialement) -->
<div id="filtersReal" style="display: none;">
<div class="filter-section">
<h6 class="filter-title">Catégories</h6>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="cat1" checked>
<label class="form-check-label" for="cat1">Électronique (24)</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="cat2">
<label class="form-check-label" for="cat2">Mode (18)</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="cat3">
<label class="form-check-label" for="cat3">Maison (15)</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="cat4">
<label class="form-check-label" for="cat4">Sports (12)</label>
</div>
</div>
<div class="filter-section">
<h6 class="filter-title">Marques</h6>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="brand1">
<label class="form-check-label" for="brand1">Apple (8)</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="brand2">
<label class="form-check-label" for="brand2">Samsung (12)</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="brand3">
<label class="form-check-label" for="brand3">Nike (6)</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="brand4">
<label class="form-check-label" for="brand4">Adidas (5)</label>
</div>
</div>
<div class="filter-section">
<h6 class="filter-title">Prix</h6>
<input type="range" class="form-range mb-3" min="0" max="1000" value="500">
<div class="d-flex justify-content-between">
<span class="small text-secondary">0€</span>
<span class="small text-secondary">1000€</span>
</div>
</div>
</div>
</div>
<!-- Zone des produits -->
<div class="col-lg-9">
<!-- Barre de tri et résultat -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div id="resultCount">
<span class="skeleton skeleton-text-sm d-inline-block" style="width:100px;"></span>
</div>
<div id="sortSelect">
<span class="skeleton d-inline-block" style="width:150px; height:35px; border-radius:8px;"></span>
</div>
</div>
<!-- Grille de produits -->
<div class="row g-4" id="productsGrid">
<!-- Squelettes de produits (8 items) -->
<div class="col-md-4 col-sm-6 product-skeleton-item">
<div class="product-card-skeleton">
<div class="skeleton skeleton-image"></div>
<div class="skeleton skeleton-badge"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text-sm"></div>
<div class="skeleton skeleton-price"></div>
<div class="skeleton skeleton-button"></div>
</div>
</div>
<div class="col-md-4 col-sm-6 product-skeleton-item">
<div class="product-card-skeleton">
<div class="skeleton skeleton-image"></div>
<div class="skeleton skeleton-badge"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text-sm"></div>
<div class="skeleton skeleton-price"></div>
<div class="skeleton skeleton-button"></div>
</div>
</div>
<div class="col-md-4 col-sm-6 product-skeleton-item">
<div class="product-card-skeleton">
<div class="skeleton skeleton-image"></div>
<div class="skeleton skeleton-badge"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text-sm"></div>
<div class="skeleton skeleton-price"></div>
<div class="skeleton skeleton-button"></div>
</div>
</div>
<div class="col-md-4 col-sm-6 product-skeleton-item">
<div class="product-card-skeleton">
<div class="skeleton skeleton-image"></div>
<div class="skeleton skeleton-badge"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text-sm"></div>
<div class="skeleton skeleton-price"></div>
<div class="skeleton skeleton-button"></div>
</div>
</div>
<div class="col-md-4 col-sm-6 product-skeleton-item">
<div class="product-card-skeleton">
<div class="skeleton skeleton-image"></div>
<div class="skeleton skeleton-badge"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text-sm"></div>
<div class="skeleton skeleton-price"></div>
<div class="skeleton skeleton-button"></div>
</div>
</div>
<div class="col-md-4 col-sm-6 product-skeleton-item">
<div class="product-card-skeleton">
<div class="skeleton skeleton-image"></div>
<div class="skeleton skeleton-badge"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text-sm"></div>
<div class="skeleton skeleton-price"></div>
<div class="skeleton skeleton-button"></div>
</div>
</div>
<div class="col-md-4 col-sm-6 product-skeleton-item">
<div class="product-card-skeleton">
<div class="skeleton skeleton-image"></div>
<div class="skeleton skeleton-badge"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text-sm"></div>
<div class="skeleton skeleton-price"></div>
<div class="skeleton skeleton-button"></div>
</div>
</div>
<div class="col-md-4 col-sm-6 product-skeleton-item">
<div class="product-card-skeleton">
<div class="skeleton skeleton-image"></div>
<div class="skeleton skeleton-badge"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text-sm"></div>
<div class="skeleton skeleton-price"></div>
<div class="skeleton skeleton-button"></div>
</div>
</div>
</div>
<!-- Produits Réels (cachés initialement) -->
<div class="row g-4" id="productsReal" style="display: none;"></div>
<!-- Pagination Skeleton -->
<div class="pagination-skeleton" id="paginationSkeleton">
<div class="skeleton skeleton-page"></div>
<div class="skeleton skeleton-page"></div>
<div class="skeleton skeleton-page"></div>
<div class="skeleton skeleton-page"></div>
<div class="skeleton skeleton-page"></div>
</div>
<!-- Pagination Réelle (cachée initialement) -->
<div id="paginationReal" style="display: none;">
<nav class="mt-5">
<ul class="pagination justify-content-center">
<li class="page-item disabled"><a class="page-link" href="#">Précédent</a></li>
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">4</a></li>
<li class="page-item"><a class="page-link" href="#">Suivant</a></li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<!-- Boutons de démonstration -->
<div class="demo-controls">
<button class="demo-btn" id="showLoadingBtn">
<i class="bi bi-arrow-repeat me-2"></i>Simuler chargement
</button>
<button class="demo-btn" id="showLoadedBtn">
<i class="bi bi-check-circle me-2"></i>Afficher produits
</button>
</div>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
(function() {
'use strict';
// Éléments DOM
const loaderOverlay = document.getElementById('loaderOverlay');
const filtersSkeleton = document.getElementById('filtersSkeleton');
const filtersReal = document.getElementById('filtersReal');
const productsGrid = document.getElementById('productsGrid');
const productsReal = document.getElementById('productsReal');
const paginationSkeleton = document.getElementById('paginationSkeleton');
const paginationReal = document.getElementById('paginationReal');
const resultCount = document.getElementById('resultCount');
const sortSelect = document.getElementById('sortSelect');
// Données des produits
const products = [
{ id: 1, name: 'Écouteurs Sans Fil Pro', category: 'Électronique', price: 89.99, oldPrice: 129.99, rating: 4.8, reviews: 234, badge: 'sale', image: '🎧' },
{ id: 2, name: 'Montre Connectée Sport', category: 'Électronique', price: 199.99, oldPrice: null, rating: 4.9, reviews: 156, badge: 'new', image: '⌚' },
{ id: 3, name: 'Sac à Dos Urbain', category: 'Mode', price: 59.99, oldPrice: 79.99, rating: 4.7, reviews: 89, badge: 'sale', image: '🎒' },
{ id: 4, name: 'Enceinte Bluetooth Portable', category: 'Électronique', price: 49.99, oldPrice: null, rating: 4.6, reviews: 312, badge: null, image: '🔊' },
{ id: 5, name: 'Baskets Running Air', category: 'Sports', price: 129.99, oldPrice: 159.99, rating: 4.8, reviews: 178, badge: 'sale', image: '👟' },
{ id: 6, name: 'Lampe de Bureau LED', category: 'Maison', price: 34.99, oldPrice: null, rating: 4.5, reviews: 67, badge: null, image: '💡' },
{ id: 7, name: 'Gourde Isotherme', category: 'Sports', price: 24.99, oldPrice: 34.99, rating: 4.7, reviews: 145, badge: 'sale', image: '🧴' },
{ id: 8, name: 'Chargeur Rapide USB-C', category: 'Électronique', price: 29.99, oldPrice: null, rating: 4.8, reviews: 423, badge: null, image: '🔌' },
{ id: 9, name: 'T-shirt Premium Coton', category: 'Mode', price: 29.99, oldPrice: 39.99, rating: 4.4, reviews: 98, badge: 'sale', image: '👕' }
];
// Générer les étoiles
function getStars(rating) {
const fullStars = Math.floor(rating);
const halfStar = rating % 1 >= 0.5;
let stars = '';
for (let i = 0; i < fullStars; i++) stars += '★';
if (halfStar) stars += '½';
while (stars.length < 5) stars += '☆';
return stars;
}
// Afficher les produits réels
function renderProducts() {
let html = '';
products.forEach(product => {
const badgeHtml = product.badge ?
`<span class="product-badge ${product.badge}">${product.badge === 'sale' ? '-30%' : 'Nouveau'}</span>` : '';
html += `
<div class="col-md-4 col-sm-6 fade-in">
<div class="product-card">
${badgeHtml}
<div class="product-image d-flex align-items-center justify-content-center" style="font-size: 4rem;">
${product.image}
</div>
<div class="product-category">${product.category}</div>
<h3 class="product-title">${product.name}</h3>
<div class="product-rating">
<span class="stars">${getStars(product.rating)}</span>
<span class="rating-count">(${product.reviews})</span>
</div>
<div class="product-price">
<span class="current-price">${product.price.toFixed(2)}€</span>
${product.oldPrice ? `<span class="old-price">${product.oldPrice.toFixed(2)}€</span>` : ''}
</div>
<button class="btn-add-cart">
<i class="bi bi-cart-plus me-2"></i>Ajouter au panier
</button>
</div>
</div>
`;
});
productsReal.innerHTML = html;
}
// Afficher le compteur de résultats réel
function renderResultCount() {
resultCount.innerHTML = `<span class="result-count"><i class="bi bi-grid-3x3-gap-fill me-1"></i>${products.length} produits trouvés</span>`;
}
// Afficher le select de tri réel
function renderSortSelect() {
sortSelect.innerHTML = `
<select class="form-select" style="width: auto; min-width: 180px;">
<option selected>Trier par : Popularité</option>
<option>Prix : croissant</option>
<option>Prix : décroissant</option>
<option>Nouveautés</option>
<option>Meilleures ventes</option>
</select>
`;
}
// Mode chargement
function showLoading() {
loaderOverlay.style.display = 'flex';
filtersSkeleton.style.display = 'block';
filtersReal.style.display = 'none';
productsGrid.style.display = 'flex';
productsReal.style.display = 'none';
paginationSkeleton.style.display = 'flex';
paginationReal.style.display = 'none';
resultCount.innerHTML = '<span class="skeleton skeleton-text-sm d-inline-block" style="width:100px;"></span>';
sortSelect.innerHTML = '<span class="skeleton d-inline-block" style="width:150px; height:35px; border-radius:8px;"></span>';
}
// Mode chargé
function showLoaded() {
loaderOverlay.style.display = 'none';
filtersSkeleton.style.display = 'none';
filtersReal.style.display = 'block';
productsGrid.style.display = 'none';
productsReal.style.display = 'flex';
paginationSkeleton.style.display = 'none';
paginationReal.style.display = 'block';
renderProducts();
renderResultCount();
renderSortSelect();
}
// Simuler un temps de chargement
function simulateLoading() {
showLoading();
setTimeout(() => {
showLoaded();
}, 2500);
}
// Boutons de démonstration
document.getElementById('showLoadingBtn').addEventListener('click', () => {
showLoading();
setTimeout(() => {
// Reste en loading jusqu'à ce qu'on clique sur "Afficher produits"
}, 100);
});
document.getElementById('showLoadedBtn').addEventListener('click', () => {
showLoaded();
});
// Masquer le loader après 2 secondes au chargement initial
window.addEventListener('load', () => {
setTimeout(() => {
showLoaded();
}, 2000);
});
// Initialiser en mode chargement
showLoading();
})();
</script>
</body>
</html>