Skip to Content
✨ v2.2.4 Released - See the release notes
DocumentationMCA-420 (B) : Lab on Web Programming10. Dynamic E-Commerce Website (HTML, JS, Bootstrap, jQuery)

Q10. Design a Dynamic Website Demonstrating Web Technologies

Question 10:
Design a dynamic website using HTML, JavaScript, Bootstrap, and jQuery (no AngularJS).

Below is a compact, functional single-page e-commerce demo oriented to Indian products and prices (INR). It demonstrates:

  • HTML5 structure & semantic elements
  • Bootstrap 5 responsive layout & components
  • jQuery + vanilla JS for DOM manipulation & events
  • AJAX try/catch to load product JSON with fallback
  • Cart operations (add, update qty, remove) and persistence (localStorage)
  • Checkout form with client-side validation

Files

index.html

<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <title>DesiStore — Demo E-Commerce (INR)</title> <meta name="description" content="DesiStore demo e-commerce site built with HTML, JS, Bootstrap 5 and jQuery. Cart, checkout, filters and INR currency." /> <!-- Bootstrap 5 --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" /> <!-- Optional: Bootstrap icons --> <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet" /> <!-- Custom CSS --> <link rel="stylesheet" href="styles.css" /> <!-- jQuery --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> </head> <body class="bg-light"> <!-- NAVBAR --> <nav class="navbar navbar-expand-lg navbar-dark bg-primary shadow-sm" > <div class="container"> <a class="navbar-brand fw-bold" href="#">DesiStore</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#nav" > <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="nav"> <ul class="navbar-nav me-auto mb-2 mb-lg-0"> <li class="nav-item"> <a class="nav-link active" href="#">Home</a> </li> <li class="nav-item"> <a class="nav-link" href="#products">Products</a> </li> <li class="nav-item"> <a class="nav-link" href="#contact">Contact</a> </li> </ul> <form class="d-flex me-3" id="searchForm" onsubmit="return false;" > <input id="searchInput" class="form-control form-control-sm" type="search" placeholder="Search products..." aria-label="Search" /> </form> <button id="cartBtn" class="btn btn-outline-light position-relative" > <i class="bi bi-cart3"></i> Cart <span id="cartCount" class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger" >0</span > </button> </div> </div> </nav> <!-- HERO --> <header class="py-5 text-white hero"> <div class="container text-center"> <h1 class="display-5 fw-bold"> DesiStore — Quality Goods, Local Prices </h1> <p class="lead"> A demo e-commerce site built with HTML, JavaScript, Bootstrap & jQuery — prices shown in INR. </p> </div> </header> <!-- CONTROLS --> <section class="container my-4"> <div class="d-flex gap-2 flex-column flex-md-row align-items-start align-items-md-center" > <div class="me-auto"> <div class="btn-group" role="group" aria-label="categories"> <button class="btn btn-outline-primary category-btn active" data-cat="all" > All </button> <button class="btn btn-outline-primary category-btn" data-cat="electronics" > Electronics </button> <button class="btn btn-outline-primary category-btn" data-cat="fashion" > Fashion </button> <button class="btn btn-outline-primary category-btn" data-cat="home" > Home </button> <button class="btn btn-outline-primary category-btn" data-cat="books" > Books </button> </div> </div> <div class="d-flex gap-2"> <select id="sortSelect" class="form-select form-select-sm"> <option value="default">Sort: Featured</option> <option value="price-asc">Price: Low to High</option> <option value="price-desc">Price: High to Low</option> <option value="name-asc">Name: A → Z</option> </select> <button id="refreshBtn" class="btn btn-sm btn-primary"> Refresh </button> </div> </div> </section> <!-- PRODUCTS GRID --> <main class="container mb-5" id="products"> <div id="productsRow" class="row g-4"></div> </main> <!-- CHECKOUT / CART OFFCANVAS --> <div class="offcanvas offcanvas-end" tabindex="-1" id="cartOffcanvas" > <div class="offcanvas-header"> <h5 class="offcanvas-title">Your Cart</h5> <button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" ></button> </div> <div class="offcanvas-body d-flex flex-column"> <div id="cartItems" class="mb-3"></div> <div class="mt-auto"> <div class="d-flex justify-content-between align-items-center mb-3" > <strong>Total:</strong> <h5 id="cartTotal" class="m-0">₹0.00</h5> </div> <button id="checkoutBtn" class="btn btn-success w-100 mb-2"> Checkout </button> <button id="clearCartBtn" class="btn btn-outline-danger w-100" > Clear Cart </button> </div> </div> </div> <!-- CHECKOUT MODAL --> <div class="modal fade" id="checkoutModal" tabindex="-1"> <div class="modal-dialog"> <form id="checkoutForm" class="modal-content needs-validation" novalidate > <div class="modal-header"> <h5 class="modal-title">Checkout</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" ></button> </div> <div class="modal-body"> <div id="orderSummary" class="mb-3"></div> <div class="mb-3"> <label class="form-label">Full Name</label> <input type="text" class="form-control" id="custName" required /> <div class="invalid-feedback"> Please enter your name. </div> </div> <div class="mb-3"> <label class="form-label">Email</label> <input type="email" class="form-control" id="custEmail" required /> <div class="invalid-feedback"> Please enter a valid email. </div> </div> <div class="mb-3"> <label class="form-label">Phone</label> <input type="tel" class="form-control" id="custPhone" pattern="[0-9]{10}" required /> <div class="invalid-feedback"> Enter 10 digit phone number. </div> </div> <div class="mb-3"> <label class="form-label">Address</label> <textarea id="custAddress" class="form-control" rows="2" required ></textarea> <div class="invalid-feedback"> Please enter shipping address. </div> </div> <div class="form-text"> This is a demo checkout — payments are not processed. </div> </div> <div class="modal-footer"> <button type="submit" class="btn btn-primary"> Place Order </button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" > Cancel </button> </div> </form> </div> </div> <!-- Contact/Footer --> <section id="contact" class="py-5 bg-white"> <div class="container text-center"> <h4>About Me</h4> </div> </section> <section class="container py-5" style="min-height: 85vh;"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card shadow-lg border-0 rounded-3"> <div class="card-body text-center p-5"> <img src="/img/profile.webp" alt="Ansari Intesab" class="rounded-circle mb-3" width="150" height="150" /> <h2 class="fw-bold mb-3">Ansari Intesab</h2> <p class="lead text-muted"> I am a <span class="fw-bold">Full-Stack Web Developer</span> skilled in <strong>MERN Stack</strong>, <strong>DevOps</strong>, <strong>PHP</strong>, <strong>WordPress</strong>, and <strong>Python</strong>. Passionate about building modern, responsive web applications that solve real-world problems. </p> <hr class="my-4" /> <h4 class="mb-3">Core Skills</h4> <div class="row"> <div class="col-md-6 text-start"> <ul class="list-unstyled"> <li>MongoDB, Express, React, Node</li> <li>DevOps & CI/CD Workflows</li> <li>Mobile Apps</li> </ul> </div> <div class="col-md-6 text-start"> <ul class="list-unstyled"> <li>PHP & Python Development</li> <li>WordPress Themes & Plugins</li> <li>Modern Web Security</li> </ul> </div> </div> <a href="https://intesab.live" target="_blank" class="btn btn-primary btn-lg mt-4 shadow" > 🌐 Visit My Portfolio </a> </div> </div> </div> </div> </section> <footer class="py-3 bg-dark text-white text-center"> <div class="container"> © <span id="yr"></span> DesiStore — Demo by Ansari Intesab </div> </footer> <!-- Bootstrap JS bundle --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script> <!-- App JS --> <script src="app.js"></script> </body> </html>

styles.css

/* Basic look */ body { font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial; color: #222; } /* Hero */ .hero { background: linear-gradient(90deg, #007bff 0%, #00b4d8 100%); padding-top: 3.5rem; padding-bottom: 3.5rem; color: #fff; } /* Product card style */ .product-card { border-radius: 12px; overflow: hidden; border: 0; transition: transform 0.28s ease, box-shadow 0.28s ease; } .product-card:hover { transform: translateY(-6px); box-shadow: 0 12px 30px rgba(2, 6, 23, 0.12); } .product-img { height: 190px; object-fit: cover; width: 100%; } /* Price badge */ .price-tag { display: inline-block; background: linear-gradient(90deg, #ff9a9e, #fecfef); color: #8b0000; font-weight: 700; padding: 6px 10px; border-radius: 8px; } /* Small utilities */ .card-text { color: #555; font-size: 0.95rem; } .badge-cat { text-transform: capitalize; } /* Cart offcanvas tweaks */ .offcanvas { width: 420px; max-width: 100%; } .offcanvas .btn { border-radius: 8px; } /* Responsive tweaks */ @media (max-width: 576px) { .product-img { height: 150px; } }

products.json

{ "products": [ { "id": 1, "title": "Smartphone — Nova X", "category": "electronics", "price": 12999, "image": "https://via.placeholder.com/400x300?text=Smartphone" }, { "id": 2, "title": "Men's Kurta Cotton", "category": "fashion", "price": 899, "image": "https://via.placeholder.com/400x300?text=Kurta" }, { "id": 3, "title": "LED TV 32 inch", "category": "electronics", "price": 15999, "image": "https://via.placeholder.com/400x300?text=LED+TV" }, { "id": 4, "title": "Non-Stick Cookware Set", "category": "home", "price": 2499, "image": "https://via.placeholder.com/400x300?text=Cookware" }, { "id": 5, "title": "Classic Novel Pack (3 books)", "category": "books", "price": 599, "image": "https://via.placeholder.com/400x300?text=Books" }, { "id": 6, "title": "Women's Ethnic Saree", "category": "fashion", "price": 1999, "image": "https://via.placeholder.com/400x300?text=Saree" }, { "id": 7, "title": "Bluetooth Headphones", "category": "electronics", "price": 2199, "image": "https://via.placeholder.com/400x300?text=Headphones" }, { "id": 8, "title": "Floor Lamp Modern", "category": "home", "price": 1299, "image": "https://via.placeholder.com/400x300?text=Lamp" } ] }

app.js (JS logic: load products, cart, checkout)

// Wait for DOM $(function () { const productsUrl = './products.json'; // try fetching JSON file let products = []; const $productsRow = $('#productsRow'); const cartKey = 'desistore_cart'; // Utility: format INR function toINR(value) { return value.toLocaleString('en-IN', { style: 'currency', currency: 'INR', }); } // Load products via AJAX with try/catch and fallback inline data async function loadProducts() { try { const resp = await $.ajax({ url: productsUrl, method: 'GET', dataType: 'json', cache: false, }); products = resp.products || []; } catch (err) { console.warn( 'Failed loading products.json — using inline fallback', err ); // fallback inline products (same structure as products.json) products = [ { id: 1, title: 'Smartphone — Nova X', category: 'electronics', price: 12999, image: './img/Smartphone.webp', }, { id: 2, title: "Men's Kurta Cotton", category: 'fashion', price: 899, image: './img/mens.webp', }, { id: 3, title: 'LED TV 32 inch', category: 'electronics', price: 15999, image: './img/led.webp', }, { id: 4, title: 'Non-Stick Cookware Set', category: 'home', price: 2499, image: './img/nonstick.jpg', }, { id: 5, title: 'Classic Novel Pack (3 books)', category: 'books', price: 599, image: './img/3books.jpg', }, { id: 6, title: "Women's Ethnic Saree", category: 'fashion', price: 1999, image: './img/women.jpg', }, { id: 7, title: 'Bluetooth Headphones', category: 'electronics', price: 2199, image: './img/blue.jpg', }, { id: 8, title: 'Floor Lamp Modern', category: 'home', price: 1299, image: './img/lamp.webp', }, ]; } renderProducts(products); } // Render product cards function renderProducts(list) { $productsRow.empty(); if (!list.length) { $productsRow.html( '<div class="col-12 text-center py-5"><h5 class="text-muted">No products found</h5></div>' ); return; } list.forEach((p) => { const col = $(` <div class="col-sm-6 col-md-4 col-lg-3"> <div class="card product-card h-100"> <img src="${p.image}" class="product-img card-img-top" alt="${p.title}" onerror="this.onerror=null;this.src='https://via.placeholder.com/400x300?text=Image';"> <div class="card-body d-flex flex-column"> <small class="badge bg-secondary badge-cat mb-2">${p.category}</small> <h6 class="card-title">${p.title}</h6> <p class="card-text mb-2">${toINR(p.price)}</p> <div class="mt-auto"> <button class="btn btn-primary w-100 add-to-cart" data-id="${p.id}"><i class="bi bi-cart-plus"></i> Add to Cart</button> </div> </div> </div> </div> `); $productsRow.append(col); }); } // CART helpers function loadCart() { try { return JSON.parse(localStorage.getItem(cartKey)) || {}; } catch (e) { return {}; } } function saveCart(cart) { localStorage.setItem(cartKey, JSON.stringify(cart)); updateCartCount(); } function updateCartCount() { const cart = loadCart(); const count = Object.values(cart).reduce((s, i) => s + i.qty, 0); $('#cartCount').text(count); } function renderCart() { const cart = loadCart(); const $cartItems = $('#cartItems'); $cartItems.empty(); let total = 0; if (!Object.keys(cart).length) { $cartItems.html( '<p class="text-muted">Your cart is empty.</p>' ); } else { Object.values(cart).forEach((item) => { total += item.qty * item.price; const row = $(` <div class="d-flex align-items-center mb-3"> <img src="${item.image}" style="width:60px;height:45px;object-fit:cover;border-radius:8px;margin-right:10px"> <div class="flex-fill"> <div class="small text-muted">${item.title}</div> <div><strong>${toINR(item.price)}</strong> x <input type="number" min="1" value="${item.qty}" data-id="${item.id}" class="form-control form-control-sm d-inline-block ms-1 qty-input" style="width:72px;"> <button class="btn btn-sm btn-link text-danger remove-item" data-id="${item.id}">Remove</button> </div> </div> </div> `); $cartItems.append(row); }); } $('#cartTotal').text(toINR(total)); $('#orderSummary').html( `<p><strong>Items:</strong> ${Object.keys(cart).length} • <strong>Total:</strong> ${toINR(total)}</p>` ); } // Add to cart handler (delegated) $(document).on('click', '.add-to-cart', function () { const id = $(this).data('id'); const product = products.find((p) => p.id === id); if (!product) return; const cart = loadCart(); if (!cart[id]) cart[id] = { id: product.id, title: product.title, price: product.price, qty: 0, image: product.image, }; cart[id].qty += 1; saveCart(cart); renderCart(); // open offcanvas const offcanvas = new bootstrap.Offcanvas($('#cartOffcanvas')[0]); offcanvas.show(); }); // Cart quantity change $(document).on('change', '.qty-input', function () { const id = $(this).data('id'); const val = parseInt($(this).val(), 10) || 1; const cart = loadCart(); if (cart[id]) { cart[id].qty = val; saveCart(cart); renderCart(); } }); // Remove item $(document).on('click', '.remove-item', function () { const id = $(this).data('id'); const cart = loadCart(); delete cart[id]; saveCart(cart); renderCart(); }); // Cart button open $('#cartBtn').on('click', function () { renderCart(); const offcanvas = new bootstrap.Offcanvas($('#cartOffcanvas')[0]); offcanvas.show(); }); // Clear cart $('#clearCartBtn').on('click', function () { if (!confirm('Clear cart?')) return; localStorage.removeItem(cartKey); renderCart(); updateCartCount(); }); // Checkout $('#checkoutBtn').on('click', function () { const cart = loadCart(); if (!Object.keys(cart).length) { alert('Cart is empty.'); return; } renderCart(); const modal = new bootstrap.Modal($('#checkoutModal')); modal.show(); }); // Submit checkout form with validation $('#checkoutForm').on('submit', function (e) { e.preventDefault(); const form = this; if (!form.checkValidity()) { form.classList.add('was-validated'); return; } // simulate order placement try { const cart = loadCart(); const order = { items: cart, total: $('#cartTotal').text(), customer: { name: $('#custName').val(), email: $('#custEmail').val(), phone: $('#custPhone').val(), address: $('#custAddress').val(), }, createdAt: new Date().toISOString(), }; // In real app: send order via AJAX to server console.log('Order placed (demo):', order); // clear cart and close modal/offcanvas localStorage.removeItem(cartKey); updateCartCount(); $('#cartOffcanvas').removeClass('show'); // hide offcanvas if open const bsModal = bootstrap.Modal.getInstance( $('#checkoutModal')[0] ); bsModal.hide(); alert( 'Order placed! (Demo) — check console for order details.' ); } catch (err) { console.error('Checkout error:', err); alert('Something went wrong during checkout.'); } }); // Search & filter & sort $('#searchInput').on('input', function () { const q = $(this).val().trim().toLowerCase(); filterSortSearch( q, $('.category-btn.active').data('cat'), $('#sortSelect').val() ); }); $('.category-btn').on('click', function () { $('.category-btn').removeClass('active'); $(this).addClass('active'); filterSortSearch( $('#searchInput').val().trim().toLowerCase(), $(this).data('cat'), $('#sortSelect').val() ); }); $('#sortSelect').on('change', function () { filterSortSearch( $('#searchInput').val().trim().toLowerCase(), $('.category-btn.active').data('cat'), $(this).val() ); }); $('#refreshBtn').on('click', function () { loadProducts(); }); // Generic filter + sort + search pipeline function filterSortSearch(q, cat, sort) { let list = [...products]; if (cat && cat !== 'all') list = list.filter((p) => p.category === cat); if (q) list = list.filter((p) => (p.title + ' ' + p.category).toLowerCase().includes(q) ); if (sort === 'price-asc') list.sort((a, b) => a.price - b.price); else if (sort === 'price-desc') list.sort((a, b) => b.price - a.price); else if (sort === 'name-asc') list.sort((a, b) => a.title.localeCompare(b.title)); renderProducts(list); } // Initialize $('#yr').text(new Date().getFullYear()); loadProducts(); updateCartCount(); });

Output Preview : DesiStore


How to use / Integrate

  1. Put these 4 files in one folder and open index.html in browser (for local AJAX products.json, use a local server — e.g., npx http-server or VSCode Live Server).
  2. Or host on your Node/Express app’s public/ folder and visit the route.
  3. Add/modify products.json for more items. The app uses AJAX try/catch so if products.json is missing the inline fallback still shows products.

Notes (for grading / write-up)

  • Why this demonstrates web technologies:

    • HTML5: semantic sections, forms, structure.
    • CSS & Bootstrap 5: responsive layout and components.
    • JavaScript + jQuery: DOM updates, events, AJAX, try/catch fallback.
    • Client-side persistence: localStorage for cart.
    • Simple checkout validation demonstrates interactive web UX.
  • SEO tip: use descriptive <title>, <meta description>, product pages (if you expand to per-product pages) should include canonical and unique meta tags.

Last updated on