I have a problem creating a search box i my JS code. The search needs to find in the restaurant name and the restaurant description. Actually when I search, the code duplicate the cards in my web because my function showRestaurants creates the cards of the web. I don't know how to fix this problem.
The JS code:
import { RestaurantService } from './restaurant-service.class.js';
import '../node_modules/bootstrap/dist/css/bootstrap.css';
import css from '../styles.css';
import RestaurantTemplate from '../templates/restaurant.handlebars';
let restaurants = [];
const restaurantService = new RestaurantService();
const weekdays = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
const currentDay = new Date().getDay();
restaurantService.getAll().then((array) => {
restaurants = array;
restaurants = array.filter((restaurant) => restaurants.id !== restaurant.id);
showRestaurants(restaurants);
});
function createCard(titleName, descriptionText, openDays, cuisineText, phone, image, id) {
// I need a new form to create the cards with handlebars
const objectCard = {
restaurantName: titleName,
restaurantDescription: descriptionText,
restaurantOpenDays: openDays.map(day => weekdays[day]).join(', '),
restaurantOpen: openDays.includes(String(currentDay)),
restaurantCuisine: cuisineText,
restaurantPhoneNumber: phone,
restaurantImageSource: image,
};
const htmlCard = RestaurantTemplate(objectCard);
const container = document.createElement('div');
container.className = 'col';
container.innerHTML = htmlCard;
container.getElementsByTagName('button')[0].addEventListener('click', () => {
if (window.confirm('Are you sure to delete this card?')) {
restaurantService.delete(id).then(() => {
container.remove();
});
}
});
document.getElementById('placesContainer').appendChild(container);
}
function showRestaurants(restaurants) {
for (let index = 0; index < restaurants.length; index++) {
createCard(restaurants[index].name, restaurants[index].description, restaurants[index].daysOpen, restaurants[index].cuisine, restaurants[index].phone, restaurants[index].image ,restaurants[index].id);
}
}
// Search box but actually duplicates the cards that find
document.getElementById('search').addEventListener('keyup', e => {
const searchRestaurant = restaurants.filter(restaurant =>
restaurant.name.toLowerCase().includes(document.getElementById('search').value.toLowerCase()) ||
restaurant.description.toLowerCase().includes(document.getElementById('search').value.toLowerCase()));
showRestaurants(searchRestaurant);
});
The html code:
<html>
<head>
<title>Exercise 3 | Home</title>
<meta charset="UTF-8">
</head>
<body>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">FoodScore</a>
<ul class="navbar-nav me-auto mb-lg-0">
<li class="nav-item">
<a class="nav-link active" href="index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="new-restaurant.html">New restaurant</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<!--Optional-->
<nav class="navbar navbar-light bg-light justify-content-between mt-3">
<form class="container-fluid">
<input class="form-control" type="text" name="search" id="search" placeholder="Search"
aria-label="Search">
</form>
</nav>
<div id="placesContainer" class="mb-4 mt-2 row row-cols-1 row-cols-md-2 row-cols-xl-3 g-4">
<!-- <div class="col">
<div class="card h-100 shadow">
<img class="card-img-top" src="IMAGE_BASE64">
<div class="card-body">
<button class="btn btn-danger btn-sm float-end">Delete</button>
<h4 class="card-title">Restaurant Name</h4>
<p class="card-text">Restaurant Description</p>
<div class="card-text">
<small class="text-muted">
<strong>Opens: </strong>Mo, Tu, We, Th, Fr, Sa, Su
</small>
<span class="badge ms-2 bg-success">Open</span>
</div>
<div class="card-text">
<small class="text-muted">
<strong>Phone: </strong>999999999
</small>
</div>
</div>
<div class="card-footer">
<small class="text-muted">Cuisine style</small>
</div>
</div>
</div> -->
</div>
</div>
</body>
</html>
The handlebars:
<div class="card h-100 shadow">
<img class="card-img-top" src="{{restaurantImageSource}}">
<div class="card-body">
<button class="btn btn-danger btn-sm float-end">Delete</button>
<h4 class="card-title">{{restaurantName}}</h4>
<p class="card-text">{{restaurantDescription}}</p>
<div class="card-text">
<small class="text-muted">
<strong>Opens: </strong>{{restaurantOpenDays}}
</small>
{{#if restaurantOpen}}
<span class="badge ms-2 bg-success">Open</span>
{{else}}
<span class="badge ms-2 bg-danger">Closed</span>
{{/if}}
</div>
<div class="card-text">
<small class="text-muted">
<strong>Phone: </strong>{{restaurantPhoneNumber}}
</small>
</div>
</div>
<div class="card-footer">
<small class="text-muted">{{restaurantCuisine}}</small>
</div>
</div>
I've tried making a function similar to showRestaurants to filter the array, but is not really necessary because the includes is already in the eventlistener from the search box.
Thanks to James for the clue, I can fix the problem with a function:
function clearRestaurants() {
const everyChildren = document.getElementById('placesContainer').children;
const arrayEveryChildren = Array.from(everyChildren);
for (let index = 0; index < arrayEveryChildren.length; index++) {
arrayEveryChildren[index].remove();
}
}
And adding the function just before the showRestaurants(searchRestaurant)
Related
Currently i am working in a project in which i require specific page views, users and sessions. I have configured out how to fetch it for the whole website using google analytics data api and now i am curious to know about how to do it for specific page.
Below i am attaching my html and js code.
HTML CODE
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Google Analtyics</title>
<!-- Font Awesome -->
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.11.2/css/all.css"
/>
<!-- Google Fonts Roboto -->
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto:wght#300;400;500;700&display=swap"
/>
<!-- MDB UI KIT -->
<link rel="stylesheet" href="css/mdb.min.css" />
<!-- Custom styles -->
<style></style>
</head>
<body style="background-color: hsl(0, 0%, 96%)">
<!--Main Navigation-->
<header class="mb-10">
<!-- Navbar-->
<nav
class="navbar navbar-expand-lg navbar-light bg-white shadow-2 fixed-top"
>
<div
class="
container-fluid
justify-content-center justify-content-md-between
"
>
<!-- Right elements -->
<ul class="navbar-nav flex-row d-none d-md-flex">
<li class="nav-item me-3 me-lg-1">
<button
id="sign-in-btn"
type="button"
class="btn btn-primary btn-rounded"
style="display: none"
onclick="signIn()"
>
Login
</button>
</li>
<li class="nav-item me-3 me-lg-1">
<button
id="sign-out-btn"
type="button"
class="btn btn-primary btn-rounded"
style="display: none"
onclick="signOut()"
>
Logout
</button>
</li>
<li class="nav-item me-3 me-lg-1">
<button
type="button"
class="btn btn-primary btn-rounded"
style="display: none"
onclick="loadData()"
>
Load Data
</button>
</li>
</ul>
<!-- Right elements -->
</div>
</nav>
<!-- Navbar -->
</header>
<!--Main Navigation-->
<!--Main layout-->
<main>
<div class="container">
<!--Section: Design Block-->
<section class="mb-8">
<h3 class="mb-7 text-center fw-bold">Last 7 days</h3>
<div class="row">
<div class="col-md-4 mb-4 mb-md-0">
<!-- Card -->
<div class="card">
<div
class="
card-body
d-flex
justify-content-start
align-items-center
"
>
<div
class="
bg-primary
text-white
rounded-4
d-flex
justify-content-center
align-items-center
"
style="width: 50px; height: 50px"
>
<i class="fas fa-users fa-lg"></i>
</div>
<div class="ms-3">
<p class="text-muted mb-1">Users</p>
<p class="mb-0">
<span id="displayUsers" class="h4 me-2"></span>
</p>
</div>
</div>
</div>
<!-- Card -->
</div>
<div class="col-md-4 mb-4 mb-md-0">
<!-- Card -->
<div class="card">
<div
class="
card-body
d-flex
justify-content-start
align-items-center
"
>
<div
class="
bg-primary
text-white
rounded-4
d-flex
justify-content-center
align-items-center
"
style="width: 50px; height: 50px"
>
<i class="fas fa-file fa-lg"></i>
</div>
<div class="ms-3">
<p class="text-muted mb-1">Page views</p>
<p class="mb-0">
<span id="displayPageViews" class="h4 me-2"></span>
</p>
</div>
</div>
</div>
<!-- Card -->
</div>
<div class="col-md-4">
<!-- Card -->
<div class="card">
<div
class="
card-body
d-flex
justify-content-start
align-items-center
"
>
<div
class="
bg-primary
text-white
rounded-4
d-flex
justify-content-center
align-items-center
"
style="width: 50px; height: 50px"
>
<i class="fas fa-chart-line fa-lg"></i>
</div>
<div class="ms-3">
<p class="text-muted mb-1">Sessions</p>
<p class="mb-0">
<span id="displaySessions" class="h4 me-2"></span>
</p>
</div>
</div>
</div>
<!-- Card -->
</div>
</div>
</section>
<!--Section: Design Block-->
</div>
</main>
<!--Main layout-->
<!--Footer-->
<footer></footer>
<!--Footer-->
</body>
<!-- MDB ESSENTIAL -->
<script type="text/javascript" src="js/mdb.min.js"></script>
<!-- Google API -->
<script src="https://apis.google.com/js/api.js"></script>
<!-- easyData - Google Analtyics -->
<script type="text/javascript" src="js/easyData-google-analtyics.js"></script>
<!--Fetching data-->
<script>
// Your Client ID
const CLIENT_ID = "";
function loadData() {
// Your GA property ID
const propertyId = "";
const startDate = "7daysAgo";
const endDate = "today";
const metrics = [
{ name: "activeUsers" },
{ name: "screenPageViews" },
{ name: "sessions" },
];
const query = {
dateRanges: [{ startDate, endDate }],
metrics: metrics,
};
runReport(propertyId, query, displayResult);
}
function displayResult(response) {
document.getElementById("displayUsers").innerHTML =
response.result.rows[0].metricValues[0].value;
document.getElementById("displayPageViews").innerHTML =
response.result.rows[0].metricValues[1].value;
document.getElementById("displaySessions").innerHTML =
response.result.rows[0].metricValues[2].value;
}
// Login buttons
document.addEventListener("gapi-loaded", (e) => {
if (isSignedIn()) {
document.getElementById("sign-out-btn").style.display = "block";
document.getElementById("sign-in-btn").style.display = "none";
loadData();
} else {
document.getElementById("sign-in-btn").style.display = "block";
document.getElementById("sign-out-btn").style.display = "none";
}
});
</script>
</html>
JAVASCRIPT CODE
// Google Analytics
const GA_SCOPE = "https://www.googleapis.com/auth/analytics.readonly";
const GA_API_URL = "https://analyticsdata.googleapis.com/$discovery/rest?version=v1beta";
gapi.load("client:auth2", function () {
gapi.auth2.init({ client_id: CLIENT_ID }).then(() => document.dispatchEvent(new Event('gapi-loaded')));
});
function signIn(scope = GA_SCOPE) {
return gapi.auth2.getAuthInstance().signIn({ scope }).then(() => {
setCookie('guser-loggedin', 'true', 1);
location.reload();
}, (e) => console.error(e));
}
function signOut() {
return gapi.auth2.getAuthInstance().signOut().then(() => {
setCookie('guser-loggedin', 'true', -1);
location.reload();}, (e) => console.error(e));
}
function loadClient(apiPath = GA_API_URL) {
return gapi.client.load(apiPath);
}
function runReport(propertyId, query, cb = function (res) { console.log(res); }, err = function (err) { console.error(err); }) {
return loadClient().then(() => gapi.client.analyticsdata.properties
.runReport({
property: "properties/" + propertyId,
resource: query
})
.then(cb, err));
}
function isSignedIn() {
if (getCookie('guser-loggedin') === 'true') return true;
return false;
}
function setCookie(cname = 'guser-loggedin', cvalue, exdays) {
const d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
let expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
function getCookie(cname) {
let name = cname + "=";
let ca = document.cookie.split(';');
for(let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
I am trying to build a shopping cart function.
I have a product page, that displays API data. When pressing the "Add to cart" button, the item should be added to local storage, and fetched from local storage to build the html content for the shopping cart.
The cart page should display this:
A list of all products added to the cart, each item must include a title, price, a link to the product view page and a product image.
If the cart is empty I want to display a message indicating this.
After the list of products, i want to display the total price of all the products in the cart.
Here is the combined code for the productDetail page and all cart functions that I have built so far.
import { baseUrl } from "../../constants/api.js";
import displayMessage from "../displayMessage.js";
// const productsURL = baseUrl + "/products";
const queryString = document.location.search;
const params = new URLSearchParams(queryString);
const id = params.get ("id");
let cartArray = [];
if(!id) {
document.location.href ="./index.html";
}
const productsUrl = baseUrl + "/products/" + id;
const results = await fetch(productsUrl);
const details = await results.json();
export async function productDetails() {
try {
// const response = await fetch(productUrl);
// const details = await response.json();
document.title = details.name;
const productContainer = document.querySelector(".product__card");
productContainer.innerHTML = `
<img src="${baseUrl + details.image.url}" class="card-img-top rounded-0 card__image" alt="${details.image.name}">
<div class="card-body p-0 pt-2 details">
<h2 class="">${details.title}</h2>
<div class="accordion" id="accordionExample">
<div class="card product__details">
<div class="details__header p-0 mt-2">
<p class="mb-0">
<button class="btn btn-link btn-block text-left p-0 m-0 text-decoration-none text-transform-none" type="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
<span class="padding__wrapper details__btn">Details</span>
<i class="fas fa-chevron-down"></i>
</button>
</p>
</div>
<div id="collapseOne" class="collapse" aria-labelledby="headingOne" data-parent="#accordionExample">
<div class="card-body details__text">
${details.description}
</div>
</div>
</div>
</div>
<p class="card-text mt-2 details__price">
$${details.price}
</p>
<button class="btn btn-primary mt-3 shadow-none cart__button" data-product="${details.id}" type="button">
<span class="padding__wrapper">Add to cart</span>
<i class="fas fa-shopping-bag"></i>
</button>
</div>`;
const addCartButton = document.querySelectorAll("button.cart__button");
console.log(addCartButton);
addCartButton.forEach(function(button){
button.onclick = function(event) {
console.log(button);
cartArray.push(event.target.dataset.product);
console.log(cartArray);
// this line should look inside the function that loops the html and finds the item with the correct id
// const itemToAdd = details.find(item => item.id === event.target.dataset.product);
// console.log(itemToAdd);
// cartArray.push(itemToAdd);
// showCart(cartArray);
// localStorage.setItem("cartList", JSON.stringify(cartArray));
}
});
}catch(error) {
displayMessage("error", "Error when loading the product", ".product__card");
}
};
function showCart(cartItems) {
const cartContainer = document.querySelector(".cart__container");
const totalContainer = document.querySelector(".total__container");
cartContainer.innerHTML = "";
let total = 0;
cartItems.forEach(function (cartElement) {
total += cartElement.price;
cartContainer.innerHTML += `
<div class="row no-gutters">
<div class="loading"></div>
<div class="col-xs-4">
<img src="${baseUrl + cartElement.image.url}" class="card-img cart__product__image" alt="${cartElement.image.name}">
</div>
<div class="col-xs-8">
<div class="card-body">
<h5 class="card-title">${cartElement.title}</h5>
<p class="card-text">$${cartElement.price}</p>
<div class="row edit__amount">
<i class="fas fa-minus-circle"></i>
<div class=""></div>
<i class="fas fa-plus-circle"></i>
</div>
</div>
</div>
<div class="col-xs-4">
<i class="fas fa-trash-alt"></i>
</div>
</div>`;
})
totalContainer.innerHTML =
`<h2>Order Summary</h2>
<p>You order:</p>
<div class="table-responsive table-sm">
<table class="table">
<tr>
<td>Subtotal:</td>
<td>$${total}</td>
</tr>
<tr>
<td>Shipping:</td>
<td>Free Shipping</td>
</tr>
</table>
</div>
<hr/>
<div class="table-responsive table-sm">
<table class="table">
<tr>
<td>Total:</td>
<td>$${total}</td>
</tr>
</table>
</div>
To Checkout`;
};
When I click on a product in the store section I want it to go in the cart. For some reason nothing is showing up in the cart but empty space. `//show cart
(function(){
const cartInfo = document.getElementById('cart-info');
const cart = document.getElementById('cart');
cartInfo.addEventListener('click', function(){
cart.classList.toggle('show-cart')
})
})();
//add items to cart
(function() {
const cartBtn = document.querySelectorAll('.store-item-icon');
cartBtn.forEach(function(btn) {
btn.addEventListener('click', function(event) {
if (event.target.parentElement.classList.contains('store-item-icon'))
{
let fullPath =
event.target.parentElement.previousElementSibling.src;
let pos = fullPath.indexOf('img') + 3;
let partPath = fullPath.slice(pos);
const item = {};
item.img = `
img - cart$ {
partPath
}
`;
let name =
event.target.parentElement.parentElement.nextElementSibling
.children[0].children[0].textContent;
item.name = name;
let price =
event.target.parentElement.parentElement.nextElementSibling
.children[0].children[1].textContent;
let finalPrice = price.slice(1).trim();
item.price = finalPrice;
console.log(finalPrice);
console.log(item);
const cartItem = document.createElement('div')
cartItem.classList.add('cart-item', 'd-flex', 'justify-content-between',
'text-capitalize', 'my-3');
cartItem.innerHtML = ` < img
src = "${item.img}"
class = "img-fluid rounded-circle"
id = "item-img"
alt = "" /
>
<
div class = "item-text" >
<
p id = "cart-item-title"
class = "font-weight-bold mb-0" >
$ {
item.name
} <
/p> <
span > £ < /span> <
span id = "cart-item-price"
class = "cart-item-price mb-0" >
$ {
item.price
} < /span >
<
/div> <
a href = "#"
id = "cart-item-remove"
class = "cart-item-remove" >
<
i class = "fas fa-trash" > < /i> <
/a> <
/div> *
/
`;
//select cart
const cart = document.getElementById('cart');
const total = document.querySelector('.cart-total-container');
cart.insertBefore(cartItem, total);
alert('item added to the cart')
}
});
});
})();
<!--cart-->
<div class="cart" id="cart">
<!--cart item-->
<div class="cart-item d-flex justify-content-between text-capitalize my-3">
<img src="img-cart/creamicon.jpg" class="img-fluid rounded-circle" id="item-img" alt="" />
<div class="item-text">
<p id="cart-item-title" class="font-weight-bold mb-0">cart item</p>
<span>£ </span>
<span id="cart-item-price" class="cart-item-price mb-0">10.99</span>
</div>
<a href="#" id="cart-item-remove" class="cart-item-remove">
<i class="fas fa-trash"></i>
</a>
</div>
<!--cart item end-->
<!--cart item-->
<div class="cart-item d-flex justify-content-between text-capitalize my-3">
<img src="img-cart/creamicon2.jpg" class="img-fluid rounded-circle" id="item-img" alt="" />
<div class="item-text">
<p id="cart-item-title" class="font-weight-bold mb-0">cart item</p>
<span>£ </span>
<span id="cart-item-price" class="cart-item-price mb-0">10.99</span>
</div>
<a href="#" id="cart-item-remove" class="cart-item-remove">
<i class="fas fa-trash"></i>
</a>
</div>
<!--cart item end-->
<!--total-->
<div class="cart-total-container d-flex justify-content-around text-capitalize mt-5">
<h5>total</h5>
<h5>£ <strong id="cart-total" class="font-weight-bold">21.99</strong></h5>
</div>
<!--end of total-->
<!--buttons-->
<div class="cart-buttons-container mt-3 d-flex justify-content-between">
clear cart
checkout
</div>
</div>
</div>
</div>
<!--store items-->
<div class="row store-items" id="store-items">
<!-- single item-->
<div class="col-10 col-sm-6 col-lg-4 mx-auto my-3 store-item sweets" data-item="sweets">
<div class="card single-item">
<div class="img-container">
<img src="img/bodybutter.jpg" class="card-img-top store-img" />
<span class="store-item-icon"><i class="fas fa-shopping-cart"></i> </span>
</div>
<div class="card-body">
<div class="card-text d-flex justify-content-between text-capitalize">
<h5 id="store-item-name">body butter</h5>
<h5 class="store-item-value">£ <strong id="store-item-price" class="font-weight-bold">10.99</strong></h5>
</div>
</div>
</div>
</div>
<!--singles item end -->
There are more then one errors in your code starting with innerHtML instead of innerHTML and incorrectly formatted template literal and incorrect bindings inside it ... so I have decided to just post a working code. Keep in mind that incorrect HTML will be treated as text only, so check the correctness of the HTML block you want to place inside innerHTML, because there was as an extra closing div also.
(function(){
const cartInfo = document.getElementById('cart-info');
const cart = document.getElementById('cart');
cartInfo.addEventListener('click', function(){
cart.classList.toggle('show-cart')
})
})();
//add items to cart
(function() {
const cartBtn = document.querySelectorAll('.store-item-icon');
cartBtn.forEach(function(btn) {
btn.addEventListener('click', function(event) {
if (event.target.parentElement.classList.contains('store-item-icon'))
{
let fullPath =
event.target.parentElement.previousElementSibling.src;
let pos = fullPath.indexOf('img') + 3;
let partPath = fullPath.slice(pos);
const item = {};
item.img = `img - cart${partPath}`;
let name = event.target.parentElement.parentElement.nextElementSibling
.children[0].children[0].textContent;
item.name = name;
let price =
event.target.parentElement.parentElement.nextElementSibling
.children[0].children[1].textContent;
let finalPrice = price.slice(1).trim();
item.price = finalPrice;
console.log(finalPrice);
console.log(item);
const cartItem = document.createElement('div')
cartItem.classList.add('cart-item', 'd-flex', 'justify-content-between', 'text-capitalize', 'my-3');
cartItem.innerHTML =
`<img src = "${item.img}" class="img-fluid rounded-circle" id="item-img" alt="" />
<div class="item-text">
<p id="cart-item-title" class="font-weight-bold mb-0">${item.name}</p>
<span>£ </span>
<span id="cart-item-price" class="cart-item-price mb-0">${item.price}</span>
</div>
<a href="#" id="cart-item-remove" class="cart-item-remove">
<i class="fas fa-trash"></i></a>`;
//select cart
const cart = document.getElementById('cart');
const total = document.querySelector('.cart-total-container');
cart.insertBefore(cartItem, total);
alert('item added to the cart')
}
});
});
})();
.cart.show-cart{display:block}
.cart{display:none; border: 1px solid #000; padding: 20px}
.store-items{margin:20px 0;border:1px solid #000;padding: 20px}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta2/css/all.min.css" integrity="sha512-YWzhKL2whUzgiheMoBFwW8CKV4qpHQAEuvilg9FAn5VJUDwKZZxkJNuGM4XkWuk94WCrrwslk8yWNGmY1EduTA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<a id="cart-info" href="javascript:;">Toggle Cart</a>
<!--cart-->
<div class="cart" id="cart">
<!--cart item-->
<div class="cart-item d-flex justify-content-between text-capitalize my-3">
<img src="img-cart/creamicon.jpg" class="img-fluid rounded-circle" id="item-img" alt="" />
<div class="item-text">
<p id="cart-item-title" class="font-weight-bold mb-0">cart item</p>
<span>£ </span>
<span id="cart-item-price" class="cart-item-price mb-0">10.99</span>
</div>
<a href="#" id="cart-item-remove" class="cart-item-remove">
<i class="fas fa-trash"></i>
</a>
</div>
<!--cart item end-->
<!--cart item-->
<div class="cart-item d-flex justify-content-between text-capitalize my-3">
<img src="img-cart/creamicon2.jpg" class="img-fluid rounded-circle" id="item-img" alt="" />
<div class="item-text">
<p id="cart-item-title" class="font-weight-bold mb-0">cart item</p>
<span>£ </span>
<span id="cart-item-price" class="cart-item-price mb-0">10.99</span>
</div>
<a href="#" id="cart-item-remove" class="cart-item-remove">
<i class="fas fa-trash"></i>
</a>
</div>
<!--cart item end-->
<!--total-->
<div class="cart-total-container d-flex justify-content-around text-capitalize mt-5">
<h5>total</h5>
<h5>£ <strong id="cart-total" class="font-weight-bold">21.99</strong></h5>
</div>
<!--end of total-->
<!--buttons-->
<div class="cart-buttons-container mt-3 d-flex justify-content-between">
clear cart
checkout
</div>
</div>
</div>
</div>
<!--store items-->
<div class="row store-items" id="store-items">
<!-- single item-->
<div class="col-10 col-sm-6 col-lg-4 mx-auto my-3 store-item sweets" data-item="sweets">
<div class="card single-item">
<div class="img-container">
<img src="img/bodybutter.jpg" class="card-img-top store-img" />
<span class="store-item-icon"><i class="fas fa-shopping-cart"></i></span>
</div>
<div class="card-body">
<div class="card-text d-flex justify-content-between text-capitalize">
<h5 id="store-item-name">body butter</h5>
<h5 class="store-item-value">£ <strong id="store-item-price" class="font-weight-bold">10.99</strong></h5>
</div>
</div>
</div>
</div>
<!--singles item end -->
I am programming an action where after a button press, games on the platform "console" or "pc" is shown. I would like it when the button for "pc" is pressed first, all pc games are shown. And after when the "console" button is pressed, all "pc" games are removed and then all "console" games are appended
code for the buttons is this:
<button class="btn btn-success" type="submit" onclick="searchPC()">PC</button>
<button class="btn btn-success" type="submit" onclick="searchCon()">Console</button>
code for the function is similar across the two buttons;
function searchPC() {
$("search").replaceWith(`<div></div>`);
axios
.get(`${baseUrl}/game/PC`)
.then((response) => {
const posts = response.data;
console.log(posts);
posts.forEach((post) => {
const postPHtml = `
<div class="card sm-6" style="margin-top: 2rem;">
<div class="card-body ">
<p class="card-text">${post.title}</p>
</div>
<div class="card-footer text-muted">
<p>${post.description}</p>
<p>SGD$${post.price}</p>
</div>
<div class="card-footer text-muted">
<a class="nav-link" href="/gamesinfo/${post.gameid}">Home</a>
</div>
</div>
`;
$("#search").replaceWith(postPHtml);
});
})
.catch((error) => {
console.log(error);
});
}
What I have attempted is to replace any info with an empty div, then adding the desired information, however, it still shows the older information (referring to above, "pc" is still shown even after pressing "console".
Furthermore, I have more than 1 card to add, ie there are >2 sets of information for console and pc games
original file with js included is:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Friendbook</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body class='bg-dark'>
<div class="container-fluid bg-dark">
<div class="">
<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
<a class="navbar-brand" href="/">
<div>
<img src="http://localhost:8082/images/image.jpg" alt="logo" style="width:40px;" id="logo">
</div>
</a>
<a class="nav-link" href="/">Home</a>
<button class="btn btn-success" type="submit" onclick="searchPC()">PC</button>
<button class="btn btn-success" type="submit" onclick="searchCon()">Console</button>
</nav>
<nav class="navbar navbar-expand-sm bg-dark navbar-dark mt-1">
<form class="form-inline ml-2" action="/action_page.php">
<input class="form-control" id='searchP' type="text" placeholder="Search by Price">
<button class="btn btn-success" type="submit">Search</button>
</form>
<form class="form-inline ml-2" action="/action_page.php">
<input class="form-control" id='searchN' type="text" placeholder="Search by Name">
<button class="btn btn-success" type="submit">Search</button>
</form>
</nav>
<div class="row" style="margin-top: 2rem;">
</div>
</div>
<div class="card" style="margin-top: 2rem;">
<div class="card-body col-md-10">
<h4 class='title '>Search Games</h4>
<div id="search" class="container-fluid md-6 sm-6">
</div>
</div>
</div>
<div class="card" style="margin-top: 2rem;">
<div class="card-body col-md-10">
<h4 class='title '>All Games</h4>
</div>
</div>
<div class="row" style="margin-top: 2rem;">
<div class="col-md-11 col-xs-12 ml-5">
<div id="posts" class="container-fluid md-6 sm-6">
</div>
</div>
</div>
</div>
<footer class='bg-dark p-3'>
<div class='ml-2 mt-2'>
<form>
<button class="btn btn-success" type="submit" onclick="logout()">logout</button>
</form>
</div>
</footer>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const baseUrl = "http://localhost:8081";
const token = localStorage.getItem("token");
const loggedInUserID = parseInt(localStorage.getItem("loggedInUserID"));
if (token === null /* || isNaN(loggedInUserID) */) {
window.location.href = "/login/";
} else {
axios.get(`${baseUrl}/gameall/all`)
.then((response) => {
const posts = response.data;
console.log(posts)
posts.forEach((post) => {
const postHtml = `
<div class="card sm-6" style="margin-top: 2rem;">
<div class="card-body ">
<p class="card-text">${post.title}</p>
</div>
<div class="card-footer text-muted">
<p>${post.description}</p>
<p>SGD$${post.price}</p>
</div>
<div class="card-footer text-muted">
<a class="nav-link" href="/gamesinfo/${post.gameid}">Home</a>
</div>
</div>
`;
$("#posts").append(postHtml);
});
})
.catch((error) => {
console.log(error);
});
/*
axios.get(`${baseUrl}/game/console/`)
.then((response) => {
const posts = response.data;
console.log(posts)
posts.forEach((post) => {
const postHtml = `
<div class="card sm-6" style="margin-top: 2rem;">
<div class="card-body ">
<p class="card-text">${post.title}</p>
</div>
<div class="card-footer text-muted">
${post.description}
</div>
<div class="card-footer text-muted">
<a class="nav-link" href="/gamesinfo/${post.gameid}">Home</a>
<p class="card-text">${post.price}</p>
</div>
</div>
`;
$("#posts").append(postHtml);
});
})
.catch((error) => {
console.log(error);
});*/
//acts as addpost api
$("#create-post-form").submit((event) => {
// prevents the page from refreshing
event.preventDefault();
const requestBody = {
text_body: $("#create-post-form-body").val(),
fk_poster_id: loggedInUserID
};
// create the post
axios.post(`${baseUrl}/posts/`, requestBody)
.then((response) => {
// reset form value.
$("#create-post-form-body").val("");
// fetch the post with the returned postID
axios.get(`${baseUrl}/posts/${response.data.postID}`)
.then((response) => {
const post = response.data;
const postHtml = `
<div class="card sm-6" style="margin-top: 2rem;">
<div class="card-body sm-6">
<p class="card-text">${post.text_body}</p>
</div>
<div class="card-footer text-muted">
${post.created_at}
</div>
</div>
`;
$("#posts").append(postHtml);
})
.catch((error) => {
console.log(error);
});
});
});
}
function logout() {
localStorage.removeItem('token')
localStorage.removeItem('role')
localStorage.removeItem('id')
}
function searchPC() {
axios.get(`${baseUrl}/game/PC`)
.then((response) => {
const posts = response.data;
console.log(posts)
posts.forEach((post) => {
const postPHtml = `
<div class="card sm-6" style="margin-top: 2rem;">
<div class="card-body ">
<p class="card-text">${post.title}</p>
</div>
<div class="card-footer text-muted">
<p>${post.description}</p>
<p>SGD$${post.price}</p>
</div>
<div class="card-footer text-muted">
<a class="nav-link" href="/gamesinfo/${post.gameid}">Home</a>
</div>
</div>
`;
$("#search").appendChild(postPHtml);
});
})
.catch((error) => {
console.log(error);
});
}
function searchCon() {
axios.get(`${baseUrl}/game/console`)
.then((response) => {
const posts = response.data;
posts.forEach((post) => {
const postCHtml = `
<div class="card sm-6" style="margin-top: 2rem;">
<div class="card-body ">
<p class="card-text">${post.title}</p>
</div>
<div class="card-footer text-muted">
<p>${post.description}</p>
<p>SGD$${post.price}</p>
</div>
<div class="card-footer text-muted">
<a class="nav-link" href="/gamesinfo/${post.gameid}">Home</a>
</div>
</div>
`;
$("#search").appendChild(postCHtml);
});
})
.catch((error) => {
console.log(error);
});
}
</script>
</body>
</html>```
I think you need to use **html(htmlString) **
Description: Set the HTML contents of each element in the set of matched elements
replace $("#search").replaceWith(postPHtml);
with $("#search").html(postPHtml);
see:https://api.jquery.com/html/
I'm developping a web page were there is some products in their prices and the quantity of each one, what I'm trying to do, is to calculate the total price, but, with the same class name for every product
I've already tried the solution in the code bellow, but I'm not getting the right price
<ul class="list-group list-group-flush">
<li class="list-group-item">
<div class="row">
<div class="col-md-4">
<img src="../img/produit_newyork_0.jpeg" class="img-fluid float-left mr-5" width="80" height="60"/>
</div>
<div class="col-md-4">
<p class="mb-auto">Lego Architecture</p>
<p class="font-weight-bold">New York City</p>
<p class="font-italic">Quantité : <span class="qte">1</span></p>
</div>
<div class="col-md-4">
<h4 class="text-right prix">49,99€</h4>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-outline-danger btn-sm float-right">Supprimer <i class="fas fa-trash-alt"></i></button>
</div>
</div>
</li>
<li class="list-group-item">
<div class="row">
<div class="col-md-4">
<img src="../img/produit_londres_0.jpeg" class="img-fluid float-left mr-5" width="80" height="60"/>
</div>
<div class="col-md-4">
<p class="mb-auto">Lego Architecture</p>
<p class="font-weight-bold">Londres City</p>
<p class="font-italic">Quantité : <span class="qte">3</span></p>
</div>
<div class="col-md-4">
<h4 class="text-right prix">49,99€</h4>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-outline-danger btn-sm float-right">Supprimer <i class="fas fa-trash-alt"></i></button>
</div>
</div>
</li>
</ul>
<script type="text/javascript>
const qte = document.querySelectorAll('.qte');
const prix = document.querySelectorAll('.prix');
const prixPanier = document.querySelector('#prixPanier');
const TVA = document.querySelector('#TVA');
const Total = document.querySelector('#Total');
let prixTotal = 0;
for(let i=0; i < qte.length; i++){
prixTotal = prixTotal + (parseInt(qte[i].innerText)* parseFloat(prix[i].innerText));
}
prixPanier.innerText = prixTotal;
TVA.innerText = prixTotal * 0.15;
</script>
So what I'm looking for, is the right solution also for my last question, How can i add the total and the TVA so i can get the final or the total price ?
When you are working with numbers that contain symbols that are not detected or parsed with JavaScript internal functions, you should make sure to avoid those problems by simply removing the symbol before parsing anything.
This is how the code working looks like:
for(let i=0; i < qte.length; i++){
let price = parseFloat(prix[i].innerText.replace('€','').replace(',','.')),
quantity = parseInt(qte[i].innerText);
prixTotal += (quantity*price);
}
Also, it has kind of a better readability. I'll leave you a
Fiddle so you can check if it is giving your desired output:
https://jsfiddle.net/y0x84rwq/
You have some issues:
the price contain comma, need convert to dot before use.
let price = parseFloat(prix[i].innerHTML.replace(/,/g, '.')).toFixed(2);
This is worked code:
const qte = document.querySelectorAll('.qte');
const prix = document.querySelectorAll('.prix');
const prixPanier = document.querySelector('#prixPanier');
const TVA = document.querySelector('#TVA');
const Total = document.querySelector('#Total');
let prixTotal = 0.0;
for(let i=0; i < qte.length; i++){
let price = parseFloat(prix[i].innerText.replace(/,/g, '.')).toFixed(2);
//console.log(price)
prixTotal = prixTotal + (parseInt(qte[i].innerHTML)* price);
}
prixPanier.innerText = prixTotal;
TVA.innerText = prixTotal * 0.15;
<ul class="list-group list-group-flush">
<li class="list-group-item">
<div class="row">
<div class="col-md-4">
<img src="../img/produit_newyork_0.jpeg" class="img-fluid float-left mr-5" width="80" height="60"/>
</div>
<div class="col-md-4">
<p class="mb-auto">Lego Architecture</p>
<p class="font-weight-bold">New York City</p>
<p class="font-italic">Quantité : <span class="qte">1</span></p>
</div>
<div class="col-md-4">
<h4 class="text-right prix">49,99€</h4>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-outline-danger btn-sm float-right">Supprimer <i class="fas fa-trash-alt"></i></button>
</div>
</div>
</li>
<li class="list-group-item">
<div class="row">
<div class="col-md-4">
<img src="../img/produit_londres_0.jpeg" class="img-fluid float-left mr-5" width="80" height="60"/>
</div>
<div class="col-md-4">
<p class="mb-auto">Lego Architecture</p>
<p class="font-weight-bold">Londres City</p>
<p class="font-italic">Quantité : <span class="qte">3</span></p>
</div>
<div class="col-md-4">
<h4 class="text-right prix">49,99€</h4>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-outline-danger btn-sm float-right">Supprimer <i class="fas fa-trash-alt"></i></button>
</div>
</div>
</li>
</ul>
<div id="prixPanier"></div>
<div id="TVA"></div>