آموزش ساخت سبد خرید با جاوا اسکریپت
ساخت یک سبد خرید برای وبسایتهای تجارت الکترونیک، بخش مهمی از تجربه کاربری است که به کاربران امکان میدهد محصولات را انتخاب کرده و به راحتی خرید خود را تکمیل کنند. با استفاده از جاوا اسکریپت، میتوانید به طور مؤثر و کارآمد سبد خرید را ایجاد کرده و مدیریت کنید. این زبان برنامهنویسی به شما کمک میکند تا به سادگی ویژگیهای مورد نیاز مانند افزودن، حذف و ویرایش محصولات را پیادهسازی کنید.
مجتمع فنی تهران با ارائه دورههای آموزش جاوا اسکریپت، به شما این امکان را میدهد که با مفاهیم و تکنیکهای مورد نیاز آشنا شوید و پروژههای واقعی را پیادهسازی کنید. این دورهها شامل تمرینات عملی و آموزشهای جامع برای طراحی و پیادهسازی سبد خرید آنلاین با جاوا اسکریپت است.
با یادگیری و پیادهسازی مهارتهای ارائهشده در این دوره، قادر خواهید بود تا یک سیستم خرید آنلاین حرفهای و کاربرپسند ایجاد کنید که تجربه خرید بهتری را برای کاربران فراهم کند.
فایل index.html
@import url(“https://fonts.googleapis.com/css?family=Lato:400,700”);
:root {
–primaryColor: #f09d51;
–mainWhite: #fff;
–mainBlack: #222;
–mainGrey: #ececec;
–mainSpacing: 0.1rem;
–mainTransition: all 0.3s linear;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
color: var(–mainBlack);
background: var(–mainWhite);
font-family: “Lato”, sans-serif;
}
/* ————— Navbar —————- */
.navbar {
position: sticky;
top: 0;
height: 60px;
width: 100%;
display: flex;
align-items: center;
background: rgb(231, 226, 221);
z-index: 1;
}
.navbar-center {
width: 100%;
max-width: 1170px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 1.5rem;
}
.nav-icon {
font-size: 1.5rem;
}
.cart-btn {
position: relative;
cursor: pointer;
}
.cart-items {
position: absolute;
top: -8px;
right: -8px;
background: var(–primaryColor);
padding: 0 5px;
border-radius: 30%;
color: var(–mainWhite);
}
/* ————— End of Navbar —————- */
/* ————— Hero —————- */
.hero {
min-height: calc(100vh – 60px);
background: url(“./images/hero-bcg.jpeg”) center/cover no-repeat;
display: flex;
align-items: center;
justify-content: center;
}
.banner {
text-align: center;
background: rgba(255, 255, 255, 0.8);
display: inline-block;
padding: 2rem;
}
.banner-title {
font-size: 3.4rem;
text-transform: uppercase;
letter-spacing: var(–mainSpacing);
margin-bottom: 3rem;
}
.banner-btn {
padding: 1rem 3rem;
text-transform: uppercase;
letter-spacing: var(–mainSpacing);
font-size: 1rem;
background: var(–primaryColor);
color: var(–mainBlack);
border: 1px solid var(–primaryColor);
transition: var(–mainTransition);
cursor: pointer;
}
.banner-btn:hover {
background: transparent;
color: var(–primaryColor);
}
/* ————— End of Hero —————- */
/* ————— Products —————- */
.products {
padding: 4rem 0;
}
.section-title h2 {
text-align: center;
font-size: 2.5rem;
margin-bottom: 5rem;
text-transform: capitalize;
letter-spacing: var(–mainSpacing);
}
.products-center {
width: 90vw;
margin: 0 auto;
max-width: 1170px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
grid-column-gap: 1.5rem;
grid-row-gap: 2rem;
}
.img-container {
position: relative;
overflow: hidden;
}
.bag-btn {
position: absolute;
top: 70%;
right: 0;
background: var(–primaryColor);
border: none;
text-transform: uppercase;
padding: 0.5rem 0.75rem;
letter-spacing: var(–mainSpacing);
font-weight: bold;
transition: var(–mainTransition);
transform: translateX(101%);
cursor: pointer;
}
.bag-btn:hover {
color: var(–mainWhite);
}
.fa-shopping-cart {
margin-right: 0.5rem;
}
.img-container:hover .bag-btn {
transform: translateX(0);
}
.product-img {
display: block;
width: 100%;
min-height: 12rem;
transition: var(–mainTransition);
}
.img-container:hover .product-img {
opacity: 0.5;
}
.product h3 {
text-transform: capitalize;
font-size: 1.1rem;
margin-top: 1rem;
letter-spacing: var(–mainSpacing);
text-align: center;
}
.product h4 {
margin-top: 0.7rem;
letter-spacing: var(–mainSpacing);
color: var(–primaryColor);
text-align: center;
}
/* —————End of Products —————- */
/* ————— Cart —————- */
.cart-overlay {
position: fixed;
top: 0;
right: 0;
width: 100%;
height: 100%;
transition: var(–mainTransition);
background: rgb(240, 157, 81, 0.5);
z-index: 2;
visibility: hidden;
}
.cart {
position: fixed;
top: 0;
right: 0;
width: 100%;
height: 100%;
overflow: scroll;
z-index: 3;
background: rgb(231, 226, 221);
padding: 1.5rem;
transition: var(–mainTransition);
transform: translateX(100%);
}
.showCart {
transform: translateX(0);
}
.transparentBcg {
visibility: visible;
}
@media screen and (min-width: 768px) {
.cart {
width: 30vw;
min-width: 450px;
}
}
.close-cart {
font-size: 1.7rem;
cursor: pointer;
}
.cart h2 {
text-transform: capitalize;
text-align: center;
letter-spacing: var(–mainSpacing);
margin-bottom: 2rem;
}
/*———- Cart Item ——————– */
.cart-item {
display: grid;
align-items: center;
grid-template-columns: auto 1fr auto;
grid-column-gap: 1.5rem;
margin: 1.5rem 0;
}
.cart-item img {
width: 75px;
height: 75px;
}
.cart-item h4 {
font-size: 0.85rem;
text-transform: capitalize;
letter-spacing: var(–mainSpacing);
}
.cart-item h5 {
margin: 0.5rem 0;
letter-spacing: var(–mainSpacing);
}
.item-amount {
text-align: center;
}
.remove-item {
color: grey;
cursor: pointer;
}
.fa-chevron-up,
.fa-chevron-down {
color: var(–primaryColor);
cursor: pointer;
}
/*———- End of Cart Item ——————– */
.cart-footer {
margin-top: 2rem;
letter-spacing: var(–mainSpacing);
text-align: center;
}
.cart-footer h3 {
text-transform: capitalize;
margin-bottom: 1rem;
}
/* ————— End of Cart —————- */
قسمت های مهم index.html به شرح زیر هستند:
- تگ nav با کلاس navbar (تعداد محصولاتی که در سبد هستند در بالای آیکون سبد خرید قرار می گیرد. آیکون سبد خرید در تگ div با کلاس cart-btn قرار می گیرد. در این تگ تعداد محصولات تنظیم می شود در تگ div با کلاس cart-items قرار می گیرد.)
- تگ section با کلاس products (محصولات در این جا قرار می گیرند).
- تگ div با کلاس cart-overlay (این تگ برای کارت است که به صورت پرده ای کنار و جلو می آید)
منطق برنامه و مغز آن در این فایل پیاده سازی می شود. در این فایل محصولات را از products.json می خوانیم و آن ها در DOM قرار می دهیم. افزودن محصول به کارت، کاهش و افزایش محصول، حذف محصول، نمایش کارت، پنهان کردن کارت و پاک کردن کارت همگی در این جا انجام می شوند. فایل products.json در زیر آمده است:
{
“items”: [
{
“sys”: { “id”: “1” },
“fields”: {
“title”: “queen panel bed”,
“price”: 10.99,
“image”: { “fields”: { “file”: { “url”: “./images/product-1.jpeg” } } }
}
},
{
“sys”: { “id”: “2” },
“fields”: {
“title”: “king panel bed”,
“price”: 12.99,
“image”: { “fields”: { “file”: { “url”: “./images/product-2.jpeg” } } }
}
},
{
“sys”: { “id”: “3” },
“fields”: {
“title”: “single panel bed”,
“price”: 12.99,
“image”: { “fields”: { “file”: { “url”: “./images/product-3.jpeg” } } }
}
},
{
“sys”: { “id”: “4” },
“fields”: {
“title”: “twin panel bed”,
“price”: 22.99,
“image”: { “fields”: { “file”: { “url”: “./images/product-4.jpeg” } } }
}
},
{
“sys”: { “id”: “5” },
“fields”: {
“title”: “fridge”,
“price”: 88.99,
“image”: { “fields”: { “file”: { “url”: “./images/product-5.jpeg” } } }
}
},
{
“sys”: { “id”: “6” },
“fields”: {
“title”: “dresser”,
“price”: 32.99,
“image”: { “fields”: { “file”: { “url”: “./images/product-6.jpeg” } } }
}
},
{
“sys”: { “id”: “7” },
“fields”: {
“title”: “couch”,
“price”: 45.99,
“image”: { “fields”: { “file”: { “url”: “./images/product-7.jpeg” } } }
}
},
{
“sys”: { “id”: “8” },
“fields”: {
“title”: “table”,
“price”: 33.99,
“image”: { “fields”: { “file”: { “url”: “./images/product-8.jpeg” } } }
}
}
]
}
// variables
const cartBtn = document.querySelector(“.cart-btn”);
const closeCartBtn = document.querySelector(“.close-cart”);
const clearCartBtn = document.querySelector(“.clear-cart”);
const cartDOM = document.querySelector(“.cart”);
const cartOverlay = document.querySelector(“.cart-overlay”);
const cartItems = document.querySelector(“.cart-items”);
const cartTotal = document.querySelector(“.cart-total”);
const cartContent = document.querySelector(“.cart-content”);
const productsDOM = document.querySelector(“.products-center”);
let cart = [];
let buttonsDOM = [];
//syntactical sugar of writing constructor function
// products
class Products {
async getProducts() {
try {
let result = await fetch(“products.json”);
let data = await result.json();
let products = data.items;
products = products.map(item => {
const { title, price } = item.fields;
const { id } = item.sys;
const image = item.fields.image.fields.file.url;
return { title, price, id, image };
});
return products;
} catch (error) {
console.log(error);
}
}
}
// ui
class UI {
displayProducts(products) {
let result = “”;
products.forEach(product => {
result += `
${product.title}
${product.price}
`;
});
productsDOM.innerHTML = result;
}
getBagButtons() {
let buttons = […document.querySelectorAll(“.bag-btn”)];
buttonsDOM = buttons;
buttons.forEach(button => {
let id = button.dataset.id;
let inCart = cart.find(item => item.id === id);
if (inCart) {
button.innerText = “In Cart”;
button.disabled = true;
}
button.addEventListener(“click”, event => {
// disable button
event.target.innerText = “In Cart”;
event.target.disabled = true;
// add to cart
let cartItem = { …Storage.getProduct(id), amount: 1 };
cart = […cart, cartItem];
Storage.saveCart(cart);
// add to DOM
this.setCartValues(cart);
this.addCartItem(cartItem);
this.showCart();
});
});
}
setCartValues(cart) {
let tempTotal = 0;
let itemsTotal = 0;
cart.map(item => {
tempTotal += item.price * item.amount;
itemsTotal += item.amount;
});
cartTotal.innerText = parseFloat(tempTotal.toFixed(2));
cartItems.innerText = itemsTotal;
}
addCartItem(item) {
const div = document.createElement(“div”);
div.classList.add(“cart-item”);
div.innerHTML = `
${item.title}
${item.price}
remove
`;
cartContent.appendChild(div);
}
showCart() {
cartOverlay.classList.add(“transparentBcg”);
cartDOM.classList.add(“showCart”);
}
setupAPP() {
cart = Storage.getCart();
this.setCartValues(cart);
this.populateCart(cart);
cartBtn.addEventListener(“click”, this.showCart);
closeCartBtn.addEventListener(“click”, this.hideCart);
}
populateCart(cart) {
cart.forEach(item => this.addCartItem(item));
}
hideCart() {
cartOverlay.classList.remove(“transparentBcg”);
cartDOM.classList.remove(“showCart”);
}
cartLogic() {
clearCartBtn.addEventListener(“click”, () => {
this.clearCart();
});
cartContent.addEventListener(“click”, event => {
if (event.target.classList.contains(“remove-item”)) {
let removeItem = event.target;
let id = removeItem.dataset.id;
console.log(cartContent);
cartContent.removeChild(removeItem.parentElement.parentElement);
// remove item
this.removeItem(id);
} else if (event.target.classList.contains(“fa-chevron-up”)) {
let addAmount = event.target;
let id = addAmount.dataset.id;
let tempItem = cart.find(item => item.id === id);
tempItem.amount = tempItem.amount + 1;
Storage.saveCart(cart);
this.setCartValues(cart);
addAmount.nextElementSibling.innerText = tempItem.amount;
} else if (event.target.classList.contains(“fa-chevron-down”)) {
let lowerAmount = event.target;
let id = lowerAmount.dataset.id;
let tempItem = cart.find(item => item.id === id);
tempItem.amount = tempItem.amount – 1;
if (tempItem.amount > 0) {
Storage.saveCart(cart);
this.setCartValues(cart);
lowerAmount.previousElementSibling.innerText = tempItem.amount;
} else {
cartContent.removeChild(lowerAmount.parentElement.parentElement);
this.removeItem(id);
}
}
});
}
clearCart() {
// console.log(this);
let cartItems = cart.map(item => item.id);
cartItems.forEach(id => this.removeItem(id));
while (cartContent.children.length > 0) {
cartContent.removeChild(cartContent.children[0]);
}
this.hideCart();
}
removeItem(id) {
cart = cart.filter(item => item.id !== id);
this.setCartValues(cart);
Storage.saveCart(cart);
let button = this.getSingleButton(id);
button.disabled = false;
button.innerHTML = `add to bag`;
}
getSingleButton(id) {
return buttonsDOM.find(button => button.dataset.id === id);
}
}
class Storage {
static saveProducts(products) {
localStorage.setItem(“products”, JSON.stringify(products));
}
static getProduct(id) {
let products = JSON.parse(localStorage.getItem(“products”));
return products.find(product => product.id === id);
}
static saveCart(cart) {
localStorage.setItem(“cart”, JSON.stringify(cart));
}
static getCart() {
return localStorage.getItem(“cart”)
? JSON.parse(localStorage.getItem(“cart”))
: [];
}
}
document.addEventListener(“DOMContentLoaded”, () => {
const ui = new UI();
const products = new Products();
ui.setupAPP();
// get all products
products
.getProducts()
.then(products => {
ui.displayProducts(products);
Storage.saveProducts(products);
})
.then(() => {
ui.getBagButtons();
ui.cartLogic();
});
});
برای ادامه کار به سه کلاس نیاز داریم:
- کلاس Products برای واکشی محصول ها
- کلاس UI برای نمایش محصولات و ظاهر و منطق برنامه
- کلاس Storage برای ذخیره داده ها در localStorage
کلاس Products
همان طور که قبلا گفتم کلاس Products برای واکشی محصول ها از فایل products.json به کار می رود. تابع getProducts را در این کلاس تعریف می کنیم.
class Products {
async getProducts() {
try {
let result = await fetch(“products.json”);
let data = await result.json();
let products = data.items;
products = products.map(item => {
const { title, price } = item.fields;
const { id } = item.sys;
const image = item.fields.image.fields.file.url;
return { title, price, id, image };
});
return products;
} catch (error) {
console.log(error);
}
}
}
class UI{
displayProducts(products){
console.log(products);
}
}
document.addEventListener(“DOMContentLoaded”, () => {
const ui=new UI()
const products=new Products()
products.getProducts().then(products=>{
ui.displayProducts(products)
})
});
اگر مرورگر را باز کنیم و console را نگاه کنیم باید تصویر زیر را ببینیم.
کلاس UI
displayProducts(products){
let result = “”;
products.forEach(product => {
result += `
${product.title}
${product.price}
`;
});
productsDOM.innerHTML = result;
}
اگر مرورگر را باز کنیم باید تصویر محصولات را ببینیم. کد بالا المنت های html لازم را عنصر ایجاد می کند و سپس آن ها را وارد productsDOM می کند.
getBagButtons() {
let buttons = […document.querySelectorAll(“.bag-btn”)];
buttonsDOM = buttons;
buttons.forEach(button => {
let id = button.dataset.id;
let inCart = cart.find(item => item.id === id);
if (inCart) {
button.innerText = “In Cart”;
button.disabled = true;
}
button.addEventListener(“click”, event => {
// disable button
event.target.innerText = “In Cart”;
event.target.disabled = true;
// add to cart
let cartItem = { …Storage.getProduct(id), amount: 1 };
cart = […cart, cartItem];
Storage.saveCart(cart);
// add to DOM
this.setCartValues(cart);
this.addCartItem(cartItem);
this.showCart();
});
});
}
اگر مرورگر را باز یک برنامه سبد خرید با جاوا اسکریپت خواهیم دید که همه توانایی های لازم را دارد.