There are books in my incoming data. I want to make these books slider by categories. In other words, when I click on the 1st class, the books belonging to the 1st class will be listed. When I click on 2nd grade I want 2nd grade books to be listed. But I want it to be in slider shape. The categories will increase more after that. like 3rd grade 4th grade. Please run the codes in full page
const books = [
{
id: 1,
bookname: "Book Name 1",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class"
},
{
id: 2,
bookname: "Book Name 2",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class"
},
{
id: 3,
bookname: "Book Name 3",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class"
},
{
id: 4,
bookname: "Book Name 4",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class"
},
{
id: 5,
bookname: "Book Name 5",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class"
},
{
id: 6,
bookname: "Book Name 6",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class"
},
{
id: 7,
bookname: "Book Name 7",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class"
},
{
id: 8,
bookname: "Book Name 8",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class"
},
{
id: 9,
bookname: "Book Name 9",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "Second Class"
},
{
id: 10,
bookname: "Book Name 10",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "Second Class"
},
]
const n = 6;
const bookshelfbox = document.querySelector('.bookshelfbox');
const bookproduct = document.querySelectorAll('.bookproduct');
const className = document.querySelector('.slides');
const bookproductbox = document.querySelector('.bookproductbox');
const grouredBooks = books.reduce((r, e, i) =>
(i % n ? r[r.length - 1].push(e) : r.push([e])) && r
, []);
console.log(grouredBooks)
grouredBooks.map((books) => {
const row = document.createElement('div');
row.className = 'row';
bookshelfbox.appendChild(row);
return books.map(
(book) =>
(row.innerHTML += `
<div class="bookproductbox">
<div class="bookproduct">
<img
src="${book.bookimage}"
alt=""
width="120"
height="180"
class="img_thumb" style="width: 120px; height: 180px; top: -73px;"
>
<div class="producttitle">
<p> ${book.bookname} </p>
<p> ${book.bookClass} </p>
</div>
</div>
`)
);
});
#charset "UTF-8";
#import url("https://fonts.googleapis.com/css2?family=Montserrat:wght#300;400;600;800&family=PT+Serif:wght#400;700&display=swap");
*,
html {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow-x: hidden;
font-family: 'PT Serif', serif;
}
body a {
text-decoration: none;
}
body a:hover {
text-decoration: none;
}
body .form-control:focus {
outline: none;
box-shadow: none !important;
}
body button:focus {
outline: none;
box-shadow: none;
}
body p {
margin-bottom: 0 !important;
}
.wrapper .booklib {
width: 100%;
height: 100%;
}
.wrapper .booklib .header {
background: #93643a url('images/header2.png') repeat;
color: #e4b173;
width: 100%;
height: 70px;
text-align: center;
margin: 0 auto;
overflow: hidden;
}
.wrapper .booklib .header ul {
list-style: none;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.wrapper .booklib .header ul li {
list-style: none;
margin: 0;
padding: 0;
display: block;
float: left;
margin-right: 15px;
padding: 4px 8px;
border-radius: 5px;
border: #d39e6b solid 1px;
cursor: pointer;
box-shadow: 1px 1px 4px rgb(0 0 0 / 40%);
font-size: 18px;
opacity: 0.7;
transform: scale(0.9);
transition: all .5s ease;
font-weight: 900;
}
.wrapper .booklib .header ul .active {
opacity: 1;
transform: scale(1);
}
.bookshelfbox {
position: relative;
margin: 0;
padding: 0;
left: 0px;
top: 0px;
float: left;
display: block;
width: 100%;
height: auto;
}
.bookshelfbox .bookproductbox {
background: url('images/shelf2.png');
width: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
padding: 1rem;
height: 225px;
}
.bookproduct {
margin-left: 50px;
position: relative !important;
display: block;
direction: ltr !important;
}
.bookproduct img {
display: block !important;
border: none !important;
cursor: pointer;
margin: 0 !important;
padding: 0 !important;
}
.producttitle {
position: absolute;
top: 80%;
z-index: 1;
text-align: center !important;
color: #ffffff;
background: #c33b4e;
overflow: hidden;
max-height: auto;
line-height: 14px !important;
width: 100%;
box-shadow: 0px 0px 8px rgb(0 0 0 / 40%);
font-size: 11px;
padding: 1px 5px 3px 5px;
font-family: Arial, Helvetica, sans-serif;
}
.bookproduct:hover .producttitle {
color: rgb(255, 255, 255);
background: url("http://srvalle.com/wp-content/plugins/bookshelf-slider/assets/title_product_bg.png") repeat rgb(195, 59, 78);
overflow: visible;
max-height: 150px;
}
.flexslider {
margin:0;
border:0;
background: none!important;
}
.flex-nav-prev, .flex-nav-next {
display: none;
}
#media (max-width: 575.98px) {
.wrapper .booklib .booklibnav .header {
left: 60px;
right: 60px;
}
.book-content {
margin-left: 15px;
}
}
#media (min-width: 576px) and (max-width: 767.98px) {
.wrapper .booklib .booklibnav .header {
left: 60px;
right: 60px;
}
}
#media (min-width: 768px) and (max-width: 991.98px) {
}
.bookshelfbox {
display: flex;
flex-direction: column;
}
.bookproductbox, .row {
display: flex;
}
<!doctype html>
<html lang="tr">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<link rel="shortcut icon" type="image/x-icon" href="/_tema/cms/images/favicon.png">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Custom CSS -->
<link rel="stylesheet" href="css/bootstrap.min.css">
<title> TG Book Library </title>
</head>
<body>
<div class="wrapper">
<div class="container">
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="booklib">
<div class="header">
<ul class="slides">
<li class="active">
First Class
</li>
<li>
Second Class
</li>
</ul>
</div>
<div class="bookshelfbox">
</div>
</div>
</div>
</div>
<!--/ container end -->
</div>
</body>
</html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
I used SwiperApi for this. Check and customize by yourself please.
const books = [
{
id: 1,
bookname: "Book Name 1",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class",
},
{
id: 2,
bookname: "Book Name 2",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class",
},
{
id: 3,
bookname: "Book Name 3",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class",
},
{
id: 4,
bookname: "Book Name 4",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class",
},
{
id: 5,
bookname: "Book Name 5",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class",
},
{
id: 6,
bookname: "Book Name 6",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class",
},
{
id: 7,
bookname: "Book Name 7",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class",
},
{
id: 8,
bookname: "Book Name 8",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "First Class",
},
{
id: 9,
bookname: "Book Name 9",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "Second Class",
},
{
id: 10,
bookname: "Book Name 10",
bookimage: "http://srvalle.com/wp-content/uploads/2013/11/issuu5.jpg",
bookClass: "Second Class",
},
];
const n = 6; // slide per page
const booksBase = $("#booksInto"); // books going to be added into swiper-swapper class.
let defaultClass = $(".btnFilter").data("classname"); // initialize class.
$(document).ready(function () {
$(".btnFilter").click(filterBooks);
filterBooks();
});
filterBooks = function (classname = null) {
// getting value from data attribute if any button clicked
if (classname != null) defaultClass = $(this).data("classname");
let theDiv = "";
$.each(
books.filter((t) => t.bookClass == defaultClass),
function (index, obj) {
theDiv += `
<div class="swiper-slide">
<div class="bookItem">
<img class="card-img-top" src="${obj.bookimage}" alt="${obj.bookname}" />
<div class="card-body">
<p class="card-text">${obj.bookname}</h5>
<p class="card-text">${obj.bookClass}</h5>
Read Book
</div>
</div>
</div>
`;
}
);
booksBase.html(theDiv);
makeSlider();
};
makeSlider = function () {
const swiper = new Swiper(".swiper", {
slidesPerView: n,
spaceBetween: 30,
pagination: {
el: ".swiper-pagination",
clickable: true,
},
});
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
/>
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<link
rel="stylesheet"
href="https://unpkg.com/swiper#7/swiper-bundle.min.css"
/>
<script src="https://unpkg.com/swiper#7/swiper-bundle.min.js"></script>
</head>
<body>
<div class="container">
<div class="row mb-5">
<div class="col-lg-12">
<div class="btn-group" role="group" aria-label="Basic example">
<button
type="button"
class="btn btn-secondary btnFilter defaultClass"
data-classname="First Class"
>
Class 1
</button>
<button
type="button"
class="btn btn-secondary btnFilter"
data-classname="Second Class"
>
Class 2
</button>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<!-- Slider main container -->
<div class="swiper">
<!-- Additional required wrapper -->
<div class="swiper-wrapper" id="booksInto"></div>
<!-- If we need pagination -->
<div class="swiper-pagination"></div>
<!-- If we need navigation buttons -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- If we need scrollbar -->
<div class="swiper-scrollbar"></div>
</div>
</div>
</div>
</div>
</body>
</html>
Related
I am using the 'required' tag in HTML to validate input. However, I am having an error with the the selection. It does not show the option nor am I able to continue.
const slidePage = document.querySelector(".slide-page");
const nextBtnFirst = document.querySelector(".firstNext");
const prevBtnSec = document.querySelector(".prev-1");
const nextBtnSec = document.querySelector(".next-1");
const prevBtnThird = document.querySelector(".prev-2");
const nextBtnThird = document.querySelector(".next-2");
const prevBtnFourth = document.querySelector(".prev-3");
const submitBtn = document.querySelector(".submit");
const progressText = document.querySelectorAll(".step p");
const progressCheck = document.querySelectorAll(".step .check");
const bullet = document.querySelectorAll(".step .bullet");
let current = 1;
nextBtnFirst.addEventListener("click", function(event) {
event.preventDefault();
slidePage.style.marginLeft = "-25%";
bullet[current - 1].classList.add("active");
progressCheck[current - 1].classList.add("active");
progressText[current - 1].classList.add("active");
current += 1;
});
nextBtnSec.addEventListener("click", function(event) {
event.preventDefault();
slidePage.style.marginLeft = "-50%";
bullet[current - 1].classList.add("active");
progressCheck[current - 1].classList.add("active");
progressText[current - 1].classList.add("active");
current += 1;
});
nextBtnThird.addEventListener("click", function(event) {
event.preventDefault();
slidePage.style.marginLeft = "-75%";
bullet[current - 1].classList.add("active");
progressCheck[current - 1].classList.add("active");
progressText[current - 1].classList.add("active");
current += 1;
});
submitBtn.addEventListener("click", function() {
bullet[current - 1].classList.add("active");
progressCheck[current - 1].classList.add("active");
progressText[current - 1].classList.add("active");
current += 1;
setTimeout(function() {
alert("Your Consultation Successfully Submitted");
location.reload();
}, 800);
});
prevBtnSec.addEventListener("click", function(event) {
event.preventDefault();
slidePage.style.marginLeft = "0%";
bullet[current - 2].classList.remove("active");
progressCheck[current - 2].classList.remove("active");
progressText[current - 2].classList.remove("active");
current -= 1;
});
prevBtnThird.addEventListener("click", function(event) {
event.preventDefault();
slidePage.style.marginLeft = "-25%";
bullet[current - 2].classList.remove("active");
progressCheck[current - 2].classList.remove("active");
progressText[current - 2].classList.remove("active");
current -= 1;
});
prevBtnFourth.addEventListener("click", function(event) {
event.preventDefault();
slidePage.style.marginLeft = "-50%";
bullet[current - 2].classList.remove("active");
progressCheck[current - 2].classList.remove("active");
progressText[current - 2].classList.remove("active");
current -= 1;
});
let data = [{
"id": 1,
"name": "Management",
"parentid": 0
},
{
"id": 2,
"name": "Support",
"parentid": 0
},
{
"id": 3,
"name": "Digital Business",
"parentid": 0
},
{
"id": 4,
"name": "Cyber Security",
"parentid": 0
},
{
"id": 5,
"name": "Infrastructure",
"parentid": 0
},
{
"id": 6,
"name": "Network",
"parentid": 0
},
{
"id": 8,
"name": "MDM Solution",
"parentid": 1
},
{
"id": 9,
"name": "IT Procurement",
"parentid": 1
},
{
"id": 10,
"name": "Vendor Management",
"parentid": 1
},
{
"id": 11,
"name": "Managed servers, Network, Firewall",
"parentid": 1
},
{
"id": 12,
"name": "Backup and Storage",
"parentid": 1
},
{
"id": 13,
"name": "Email Management",
"parentid": 1
},
{
"id": 14,
"name": "Microsoft Office Management",
"parentid": 1
},
{
"id": 15,
"name": "Asset Management",
"parentid": 1
},
{
"id": 16,
"name": "Network Management",
"parentid": 1
},
{
"id": 17,
"name": "Communication Management",
"parentid": 1
},
{
"id": 21,
"name": "Patch Management",
"parentid": 1
},
{
"id": 18,
"name": "IT Helpdesk",
"parentid": 2
},
{
"id": 19,
"name": "Maintenance of Servers",
"parentid": 2
},
{
"id": 20,
"name": "Network Maintenance",
"parentid": 2
},
{
"id": 21,
"name": "Communication Maintenance",
"parentid": 2
},
{
"id": 21,
"name": "Patch Management",
"parentid": 2
},
{
"id": 22,
"name": "Disaster Recovery Testing and Support",
"parentid": 2
},
{
"id": 23,
"name": "Pro-active Capacity Planning and Support",
"parentid": 2
},
{
"id": 24,
"name": "Remote and Onsite Support",
"parentid": 2
},
{
"id": 25,
"name": "Office 365 Migration",
"parentid": 3
},
{
"id": 26,
"name": "Managed Offsite Backups",
"parentid": 3
},
{
"id": 27,
"name": "Azure Migration & Uplift",
"parentid": 3
},
{
"id": 28,
"name": "SaaS Products Support ",
"parentid": 3
},
{
"id": 29,
"name": "Microsoft Teams Setup",
"parentid": 3
},
{
"id": 30,
"name": "SharePoint Configuration",
"parentid": 3
},
{
"id": 32,
"name": "Risk Assessment",
"parentid": 4
},
{
"id": 33,
"name": "Cloud base & on prem SIEM Solution Implementation",
"parentid": 4
},
{
"id": 34,
"name": "Vulnerability & penetration testing",
"parentid": 4
},
{
"id": 35,
"name": "Cyber Security Incident Response Plan",
"parentid": 4
},
{
"id": 36,
"name": "Cloud Security",
"parentid": 4
},
{
"id": 37,
"name": "CyberArk PAM solution",
"parentid": 4
},
{
"id": 38,
"name": "SME Upgrades and Consolidation",
"parentid": 5
},
{
"id": 39,
"name": "Dell Networking",
"parentid": 5
},
{
"id": 40,
"name": "Data Centre Design",
"parentid": 5
},
{
"id": 41,
"name": "Storage Design and Installation",
"parentid": 5
},
{
"id": 42,
"name": "Disaster Recovery Infrastructure",
"parentid": 5
},
{
"id": 43,
"name": "Redundancy Planning",
"parentid": 6
},
{
"id": 44,
"name": "Internet and WAN Connectivity Design",
"parentid": 6
},
{
"id": 45,
"name": "Cabling Design",
"parentid": 6
},
{
"id": 46,
"name": "Network Switching Design and Scale",
"parentid": 6
},
{
"id": 47,
"name": "Routing Design ",
"parentid": 6
},
{
"id": 48,
"name": "Firewall Design and Maintenance ",
"parentid": 6
},
{
"id": 49,
"name": "Fibre, Cat5, Cat6 and WiFi Planning and Installation",
"parentid": 6
},
{
"id": 50,
"name": "Access Network Design ",
"parentid": 6
},
{
"id": 51,
"name": "Automation Workflows and Software Development",
"parentid": 6
},
{
"id": 52,
"name": "Campus Network Design",
"parentid": 6
},
{
"id": 53,
"name": "ISP Network Design",
"parentid": 6
},
]
function populateList(list, pid) {
let l = document.getElementById(list);
l.innerHTML = "";
let topItem = document.createElement("option");
topItem.value = 0;
topItem.text = "--Select--";
l.appendChild(topItem);
let items = data.filter(item => item.parentid == pid);
items.forEach(function(item) {
let newItem = document.createElement("option");
newItem.value = item.id;
newItem.text = item.name;
l.appendChild(newItem);
})
}
function updateList(selList, thisList) {
if (thisList.value != 0) {
populateList(selList, Number(thisList.value));
} else {
let s = document.getElementById(selList);
s.value = 0;
triggerEvent(s, "onchange");
let sCopy = s.cloneNode(false);
let p = s.parentNode;
p.replaceChild(sCopy, s);
}
}
function triggerEvent(e, trigger) {
if ((e[trigger] || false) && typeof e[trigger] == 'function') {
e[trigger](e);
}
}
function loadList1() {
populateList("list1", 0);
}
window.onload = loadList1;
if (FullNameValue === '') {
setErrorFor(FullName, FullName 'Full Name cannot be blank');
}
::selection {
color: #fffef8;
background: #4197a9;
}
.container {
width: 750px;
margin-left: 0px;
text-align: center;
border-radius: 5px;
padding: 50px 35px 10px 35px;
}
.container header {
font-size: 35px;
font-weight: 600;
margin: 0 0 30px 0;
right: auto;
}
.container .form-outer {
width: 100%;
overflow: hidden;
margin-left: 300px;
}
.container .form-outer form {
display: flex;
width: 600%;
}
.form-outer form .page {
width: 25%;
transition: margin-left 0.3s ease-in-out;
}
.form-outer form .page .title {
text-align: left;
font-size: 25px;
font-weight: 500;
}
.form-outer form .page .field {
width: 800px;
height: 45px;
margin: 90px 0;
display: flex;
position: relative;
}
form .page .field .label {
position: absolute;
top: -30px;
font-weight: 500;
}
form .page .field input {
height: 80%;
width: 70%;
border: 1px solid #33343d;
border-radius: 5px;
padding-left: 15px;
font-size: 18px;
}
form .page .field select {
width: 80%;
padding-left: 10px;
font-size: 17px;
font-weight: 500;
}
form .page .field button {
width: 250px;
height: calc(100% + 5px);
border: none;
background: #4197a9;
margin-top: -10px;
border-radius: 5px;
color: #fff;
cursor: pointer;
font-size: 18px;
font-weight: 500;
letter-spacing: 1px;
text-transform: uppercase;
transition: 0.5s ease;
margin-left: 10px;
margin-right: 10px;
}
form .page .field button:hover {
background: #000;
}
form .page .btns button {
margin-top: -20px!important;
}
form .page .btns button.prev {
margin-right: 10px;
font-size: 17px;
}
form .page .btns button.next {
margin-left: 20px;
}
.container .progress-bar {
display: flex;
user-select: none;
left: 250px;
position: relative;
}
.container .progress-bar .step {
text-align: center;
width: 100%;
position: relative;
}
.container .progress-bar .step p {
font-weight: 500;
font-size: 18px;
color: #000;
margin-bottom: 8px;
}
.progress-bar .step .bullet {
height: 28px;
width: 28px;
border: 2px solid #000;
display: inline-block;
border-radius: 50%;
position: relative;
transition: 0.2s;
font-weight: 500;
font-size: 17px;
line-height: 24px;
}
.progress-bar .step .bullet.active {
border-color: #4197a9;
background: #4197a9;
}
.progress-bar .step .bullet span {
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.progress-bar .step .bullet.active span {
display: none;
}
.progress-bar .step .bullet:before,
.progress-bar .step .bullet:after {
position: absolute;
content: '';
bottom: 11px;
right: -51px;
left: 50px;
height: 3px;
width: 100px;
background: black;
}
.progress-bar .step .bullet.active:after {
background: #4197a9;
transform: scaleX(0);
transform-origin: left;
animation: animate 0.3s linear forwards;
}
#keyframes animate {
100% {
transform: scaleX(1);
}
}
.progress-bar .step:last-child .bullet:before,
.progress-bar .step:last-child .bullet:after {
display: none;
}
.progress-bar .step p.active {
color: #d43f8d;
transition: 0.2s linear;
}
.progress-bar .step .check {
position: absolute;
left: 50%;
top: 70%;
font-size: 15px;
transform: translate(-50%, -50%);
display: none;
}
.progress-bar .step .check.active {
display: block;
color: #fffef8;
}
<div class="progress-bar">
<div class="step">
<p>
Name</p>
<div class="bullet">
<span>1</span>
</div>
<div class="check fas fa-check">
</div>
</div>
<div class="step">
<p>
Contact</p>
<div class="bullet">
<span>2</span>
</div>
<div class="check fas fa-check">
</div>
</div>
<div class="step">
<p>
Service</p>
<div class="bullet">
<span>3</span>
</div>
<div class="check fas fa-check">
</div>
</div>
<div class="step">
<p>
Submit</p>
<div class="bullet">
<span>4</span>
</div>
<div class="check fas fa-check">
</div>
</div>
</div>
<div class="form-outer">
<form action="#">
<div class="page slide-page">
<div class="title">
Lets get Started
</div>
<div class="form-control">
<div class="field">
<div class="label">
Full Name </div>
<input type="text" placeholder="FirstName SecondName " id="FullName" required>
</div>
<div class="field">
<div class="label">
Company Name</div>
<input type="text" placeholder="Name" id="comname" required>
</div>
<div class="field">
<button class="firstNext next" style="position: relative; left: 280px;">Next</button>
</div>
</div>
</div>
<div class="page">
<div class="title">
Contact Info:</div>
<div class="field">
<div class="label">
Email Address</div>
<input type="email" placeholder="name#example.com" required>
</div>
<div class="field">
<div class="label">
Phone Number</div>
<input type="number" placeholder="+61 412 345 678" required>
</div>
<div class="field btns">
<button class="prev-1 prev">Previous</button>
<button class="next-1 next">Next</button>
</div>
</div>
<div class="page">
<div class="title">
Services</div>
<div class="field">
<div class="label">
Service Category</div>
<select id="list1" onchange="updateList('list2', this);" required>
</select>
</div>
<div class="field">
<div class="label">
Service</div>
<select id="list2" onchange="updateList('list3', this);" required></select>
</div>
<div class="field">
<div class="label">
Description
</div>
<textarea name="Description" id="" cols="75" rows="100" style="height:60px;" placeholder="Provide a small description about the service you have selected."></textarea>
</div>
<div class="field btns">
<button class="prev-2 prev" style="position: relative; left: 30px;">Previous</button>
<button class="next-2 next" style="position: relative; left: 30px;">Next</button>
</div>
</div>
<div class="page">
<div class="title">
Submit</div>
<div class="field">
<div class="label">
Pefered method of Communication</div>
<select name="communica" id="" required>
<option value=""></option>
<option value="Phone">Phone </option>
<option value="Email ">Email </option>
<option value="SMS">SMS </option>
</select>
</div>
<div class="textsub" style="position: relative; left: 0; margin-right: 400px;">
We will reach out to you with some proposal and we will discuss which will be the best for you while hearing your feedback. You should recieve an email within 24 hours with what will be happening. Thank you
</div>
<div class="field btns">
<button class="prev-3 prev">Previous</button>
<button class="submit" style="left: 50px; position: relative;">Submit</button>
</div>
</div>
</form>
</div>
</div>
I have included the relevant code below.
<select id="list1" onchange="updateList('list2', this);" required >
</select>
</div>
<div class="field">
<div class="label">
Service</div>
<select id="list2" onchange="updateList('list3', this);" required ></select>
</div>
const question = document.querySelector('#question');
const choices = Array.from(document.querySelectorAll('.choice-text'));
const progressText = document.querySelector('#progressText');
const scoreText = document.querySelector('#score');
let currentQuestion = {}
let acceptingAnswers = true
let score = 0
let questionCounter = 0
let availableQuestions = []
let questions = [
{
question: "Question 1",
choice1: "Spain",
choice2: "France",
choice3: "Colombia",
choice4: "China",
answer: 2,
},
{
question:"Question 2",
choice1: "Hungary",
choice2: "Switzerland",
choice3: "Chile",
choice4: "Austrailia",
answer: 1,
},
{
question: "Question 3",
choice1: "Chile",
choice2: "Brazil",
choice3: "New Zealand",
choice4: "Morocco",
answer: 4,
},
]
const SCORE_POINTS = 1
const MAX_QUESTIONS = 6
function startGame(){
questionCounter = 0
score = 0
availableQuestions = [...questions]
getNewQuestion()
}
function getNewQuestion(){
if(availableQuestions.length === 0 || questionCounter > MAX_QUESTIONS) {
localStorage.setItem('mostRecentScore', score)
return window.location.assign('end.html')
}
questionCounter++
progressText.innerText = `Question ${questionCounter} of ${MAX_QUESTIONS}`
// progressBarFull.style.width = `${(questionCounter/MAX_QUESTIONS) * 100}%`
const questionsIndex = Math.floor(Math.random() * availableQuestions.length)
currentQuestion = availableQuestions[questionsIndex]
question.innerText = currentQuestion.question
choices.forEach(choice => {
const number = choice.dataset['number']
choice.innerText = currentQuestion['choice' + number]
})
availableQuestions.splice(questionsIndex, 1)
acceptingAnswers = true
}
choices.forEach(choice => {
choice.addEventListener('click', e => {
if(!acceptingAnswers) return
acceptingAnswers = false
const selectedChoice = e.target
const selectedAnswer = selectedChoice.dataset['number']
let classToApply = selectedAnswer == currentQuestion.answer ? 'correct' : 'incorrect'
if(classToApply === 'correct') {
incrementScore(SCORE_POINTS)
}
selectedChoice.parentElement.classList.add(classToApply)
setTimeout(() => {
selectedChoice.parentElement.classList.remove(classToApply)
getNewQuestion()
}, 1000)
})
})
function incrementScore(num){
score +=num
scoreText.innerText = score
}
startGame()
body{
background-color: gray;
}
*{
box-sizing: border-box;
margin: 0;
padding: 0;
font-size: 62.5%;
}
h1{
text-align: center;
font-size: 5.4rem;
color: black;
margin-bottom: 5rem;
}
h2{
font-size: 4.2rem;
margin-bottom: 4rem;
}
.container{
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
max-width: 80rem;
margin: 0 auto;
padding: 2rem;
}
.flex-column{
display: flex;
flex-direction: column;
}
.flex-center{
justify-content: center;
align-items: center;
}
.justify-center{
justify-content: center;
}
.text-center{
text-align: center;
}
.hidden{
display: none;
}
.btn{
font-size: 2.4rem;
padding:2rem 0;
width: 30rem;
text-align: center;
margin-bottom: 1rem;
text-decoration: none;
color: rgb(29, 26, 26);
background: lightblue;
border-radius: 4px;
}
.btn:hover{
cursor: pointer;
background: teal;
box-shadow: rgb(130, 170, 183);
transition:transform 150ms;
transform: scale(1.03);
}
.btn[disabled]:hover{
cursor: not-allowed;
box-shadow: none;
transform: none;
}
body {
color: black;
}
.choice-container {
display: flex;
margin-bottom: 0.8rem;
width: 100%;
border-radius: 4px;
background: lightblue;
font-size: 3rem;
min-width: 80rem;
}
.choice-container:hover {
cursor: pointer;
box-shadow: 0 0.4rem 1.4rem 0 rgba(6, 103, 247, 0.5);
transform: scale(1.02);
transform: transform 100ms;
}
.choice-prefix {
padding: 2rem 2.5rem;
color: black
}
.choice-text {
padding: 2rem;
width: 100%;
}
.progressText{
text-align: center;
}
.correct {
background: green;
}
.incorrect {
background: red;
}
/* Heads up Display */
#hud {
display: flex;
justify-content: space-between;
}
.hud-prefix {
text-align: center;
font-size: 2rem;
}
.hud-main-text {
text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quiz Page</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="game.css">
<style>
img{
align-self: center;
width: 80px;
height: 150;
padding-bottom: 50px;
}
</style>
</head>
<body>
<div class="container">
<div id="game" class="justify-center flex-column">
<div id="hud">
<div class="hud-item">
<p id="progressText" class="hud-prefix">
Question
</p>
<div id="progressBarFull"></div>
</div>
<div class="hud-item">
<p class="hud-prefix">
Score
</p>
<h1 class="hud-main-text" id="score">
0
</h1>
</div>
</div>
<h1 id="question">What is the answer to this question</h1>
<img id="france" src="france.jpg">
<img id="hungary" src="hungary.jpg">
<img id="morocco" src="morocco.jpg">
<div class="choice-container">
<p class="choice-prefix">A</p>
<p class="choice-text" data-number="1">Choice</p>
</div>
<div class="choice-container">
<p class="choice-prefix">B</p>
<p class="choice-text" data-number="2">Choice 2</p>
</div>
<div class="choice-container">
<p class="choice-prefix">C</p>
<p class="choice-text" data-number="3">Choice 3</p>
</div>
<div class="choice-container">
<p class="choice-prefix">D</p>
<p class="choice-text" data-number="4">Choice 4</p>
</div>
</div>
</div>
<script src="Flag.js"></script>
</body>
</html>
Im creating a quiz game that shows the user a country flag and the user has to choose from four choices to pick the correct one. Currently I have all the questions flags being shown because I cant figure out how to show just one image per question. Is there a way to hide the other pictures or put the image to specify an image to a question. The quiz also randomizes each time you play so if the first time you play is different the second time.
I added a code snippet of just the flag questions. my entire code as a home page and an end page that shows the final score and lets the user play again.
Here you go: https://codepen.io/chrisbradshaw/pen/yLaLLVo.
Remove the flag images from HTML and add:
<img src="" alt="quiz show question" id="flagImage" />
Include flag image in question objects:
{
question: "Question 1",
choice1: "Spain",
choice2: "France",
choice3: "Colombia",
choice4: "China",
answer: 2,
flagImage: 'https://placekitten.com/200/300'
}
Create a variable for #flagImage DOM img:
const flagImageHtml = document.querySelector('#flagImage');
Update the src of the #flagImage DOM img when you change the current question:
flagImageHtml.src = currentQuestion.flagImage;
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 2 years ago.
I would like to increase, decrease and remove items from my cart page but the buttons only work on the first items and the buttons increase the total amount of items in the cart instead of increasing the individual number of items.I would also like to decrease and increase the total amount as I press the buttons.What am I doing wrong? This is my github hosted page for the final result:/my hosted page.
var carts = document.querySelectorAll(".cart-button");
var products = [
{
id: 1,
name: "Brown Brim",
image: "https://i.ibb.co/ZYW3VTp/brown-brim.png",
price: 25,
inCart:0
},
{
id: 2,
name: "Blue Beanie",
image: "https://i.ibb.co/ypkgK0X/blue-beanie.png",
price: 18,
inCart:0
},
{
id: 3,
name: "Brown Cowboy",
image: "https://i.ibb.co/QdJwgmp/brown-cowboy.png",
price: 35,
inCart:0
},
{
id: 4,
name: "Grey Brim",
image:"https://i.ibb.co/RjBLWxB/grey-brim.png",
price: 25,
inCart:0
},
{
id: 5,
name: "Adidas NMD",
image: "https://i.ibb.co/0s3pdnc/adidas-nmd.png",
price: 220,
inCart:0
},
{
id: 6,
name: "Adidas Yeezy",
image:"https://i.ibb.co/dJbG1cT/yeezy.png",
price: 280,
inCart:0
},
{
id: 7,
name: "Black Converse",
image:"https://i.ibb.co/bPmVXyP/black-converse.png",
price: 110,
inCart:0
},
{
id: 8,
name: "Nike White AirForce",
image:"https://i.ibb.co/1RcFPk0/white-nike-high-tops.png",
price: 160,
inCart:0
},
{
id: 9,
name: "Black Jean Shearling",
image:"https://i.ibb.co/XzcwL5s/black-shearling.png",
price: 125,
inCart:0
},
{
id: 10,
name: "Blue Jean Jacket",
image:"https://i.ibb.co/mJS6vz0/blue-jean-jacket.png",
price: 90,
inCart:0
},
{
id: 11,
name: "Grey Jean Jacket",
image:"https://i.ibb.co/N71k1ML/grey-jean-jacket.png",
price: 90,
inCart:0
},
{
id: 12,
name: "Brown Shearling",
image:"https://i.ibb.co/s96FpdP/brown-shearling.png",
price: 165,
inCart:0
},
{
id: 13,
name: "Blue Tanktop",
image:"https://i.ibb.co/7CQVJNm/blue-tank.png",
price: 25,
inCart:0
},
{
id: 14,
name: "Floral Blouse",
image:"https://i.ibb.co/4W2DGKm/floral-blouse.png",
price: 20,
inCart:0
},
{
id: 15,
name: "Floral Dress",
image:"https://i.ibb.co/KV18Ysr/floral-skirt.png",
price: 80,
inCart:0
},
{
id: 16,
name: "Red Dots Dress",
image:"https://i.ibb.co/N3BN1bh/red-polka-dot-dress.png",
price: 80,
inCart:0
},
{
id: 17,
name: "Camo Down Vest",
image:"https://i.ibb.co/xJS0T3Y/camo-vest.png",
price: 325,
inCart:0
},
{
id: 18,
name: "Floral T-shirt",
image:"https://i.ibb.co/qMQ75QZ/floral-shirt.png",
price: 20,
inCart:0
},
{
id: 19,
name: "Black & White Longsleeve",
image:"https://i.ibb.co/55z32tw/long-sleeve.png",
price: 25,
inCart:0
},
{
id: 20,
name: "Pink T-shirt",
image:"https://i.ibb.co/RvwnBL8/pink-shirt.png",
price: 25,
inCart:0
}
];
for (let i = 0; i < carts.length; i++){
carts[i].addEventListener("click", ()=>{
cartNumbers(products[i]);
totalCost(products[i]);
});
}
function onLoadCartNumbers(){
let productNumbers = localStorage.getItem("cartNumbers");
if(productNumbers){
document.querySelector(".item-count").textContent = productNumbers;
}
}
function cartNumbers(product){
let productNumbers = localStorage.getItem("cartNumbers");
productNumbers = parseInt(productNumbers);
if (productNumbers){
localStorage.setItem("cartNumbers", productNumbers + 1);
document.querySelector(".item-count").textContent = productNumbers + 1;
}else {
localStorage.setItem("cartNumbers", 1);
document.querySelector(".item-count").textContent = 1;
}
setItems(product);
}
function setItems(product){
let cartItems = localStorage.getItem("productsInCart");
cartItems = JSON.parse(cartItems);
if(cartItems !== null){
if (cartItems[product.name] === undefined){
cartItems = {
...cartItems,
[product.name]:product
}
}
cartItems[product.name].inCart += 1;
}else{
product.inCart = 1;
cartItems = {
[product.name]:product
}
}
localStorage.setItem("productsInCart",JSON.stringify(cartItems));
}
function totalCost(product){
var cartCost = localStorage.getItem("totalCost");
if(cartCost !== null){
cartCost = parseInt(cartCost);
localStorage.setItem("totalCost", cartCost + product.price);
}else{
localStorage.setItem("totalCost", product.price);
}
}
function displayCart(){
var cartCost = localStorage.getItem("totalCost");
let cartItems = localStorage.getItem("productsInCart");
cartItems = JSON.parse(cartItems);
let productContainer = document.querySelector(".output");
if( cartItems && productContainer ){
productContainer.innerHTML = "";
Object.values(cartItems).map(item =>{
productContainer.innerHTML += `
<div id="cartResult" class="cart-contain">
<div class="cart-header">
<div class="product">
<img src=${item.image}>
</div>
<div class="description">
<p >${item.name}</p></div>
<div class="quantity">
<button onclick="subtract()" class="add"><</button>
<p class="in-cart" id="cartCount">${item.inCart}</p>
<button onclick="add()" class="minus">></button>
</div>
<div class="price"><p>N ${item.price}.00</p></div>
<div class="remove"><button onclick="remove(cartResult)">тип</button></div>
</div>
</div>
`
;
}
);
productContainer.innerHTML += `
<div class="total-container"><h3 class="total-title">TOTAL:</h3>
<h3 class="total">${cartCost}</h3
</div>
`
}
}
function remove() {
let productNumbers = localStorage.getItem("cartNumbers");
var myobj = document.querySelector("#cartResult");
myobj.remove();
}
function add(cartCount)
{
var increase = document.querySelector('.minus');
let productNumbers = localStorage.getItem("item.inCart");
productNumbers = parseInt(productNumbers);
if (productNumbers){
localStorage.setItem("item.inCart", productNumbers + 1);
document.querySelector("#cartCount").textContent = productNumbers + 1;
}else {
localStorage.setItem("item.inCart", 1);
document.querySelector("#cartCount").textContent = 1;
}
setItems(i);
}
function subtract(cartCount)
{
var decrease = document.querySelector('.add');
var productNumbers = localStorage.getItem("item.inCart");
productNumbers = parseInt(productNumbers);
if (productNumbers){
localStorage.setItem("item.inCart", productNumbers - 1);
document.querySelector("#cartCount").innerHTML = productNumbers - 1;
}else {
localStorage.setItem("item.inCart", 1);
document.querySelector("cartCount").textContent = 1;
}
setItems();
}
displayCart();
onLoadCartNumbers();
#import url('https://fonts.googleapis.com/css2?family=Open+Sans+Condensed:wght#300&display=swap');
*{
box-sizing: border-box;
}
body{
font-family: 'Open Sans Condensed', sans-serif;
margin: 50px;
}
.shopping-icon{
width: 24px;
height: 24px;
}
.cart-icon .item-count{
position: absolute;
font-size: 10px;
font-weight: 700;
bottom: 12px;
}
.cart-icon{
color: #000;
width: 45px;
height: 45px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
header .option{
width: 100%;
height: 100%;
margin-top: -50px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.collection-item {
width: 22vw;
height: 350px;
align-items: center;
position: relative;
}
.collection-page .items .collection-item {
margin-bottom: 30px;
}
.collection-item .image {
width: 100%;
height: 95%;
background-size: cover;
background-position: 50%;
margin-bottom: 5px;
}
.items{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
align-items: center;
}
.cart-button{
position: relative;
bottom: 110px;
width: 80%;
justify-content: center;
opacity: .7;
left: 10%;
right: 10%;
visibility: hidden ;
height: 50px;
letter-spacing: .5px;
line-height: 50px;
font-family: 'Open Sans Condensed', sans-serif;
font-size: 15px;
font-weight: bolder;
cursor: pointer;
}
#inc{
outline: none;
border: none;
margin-left: 0px;
height: 15px;
width: 10px;
cursor: pointer;
color: transparent;
text-shadow: 0px 1px 0px #000;
}
.collection-item:hover .cart-button{
visibility: visible;
opacity: .9;
border: 1px solid #000;
}
.collection-item:hover .image{
opacity: .7;
}
.cart-button:hover{
background-color: #000;
color: #fff;
border:1px solid #000;
}
.collection-footer{
display: flex;
justify-content: space-between;
}
/*cart page*/
.cart-container{
max-width: 650px;
justify-content: space-around;
margin: 0 auto;
margin-top: 50px;
}
.cart-contain{
max-width: 650px;
justify-content: space-around;
margin: 0 auto;
margin-top: 50px;
}
.cart-heading{
width: 100%;
max-width: 650px;
display: flex;
justify-content: flex-start;
border-bottom: 1px solid #000;
margin: 0 auto;
}
.cart-header{
width: 100%;
max-width: 650px;
display: flex;
justify-content: flex-start;
border-bottom: 1px solid #000;
margin: 0 auto;
}
.product{
width: 30%;
}
.product img{
margin-top: 40px;
height: 200px;
width: 150px;
}
.description{
width: 20%;
display: flex;
align-items: center;
}
.description p{
font-size: 1.3rem;
}
.quantity{
width: 30%;
display: flex;
align-items: center;
display: flex;
justify-content: space-around;
}
.price{
width: 20%;
display: flex;
align-items: center;
}
.price p{
font-size: 1.3rem;
}
.remove{
width: 20%;
display: flex;
align-items: center;
}
.in-cart{
font-size: 1.3rem;
}
.add{
font-size: 30px;
cursor: pointer;
font-weight: bold;
border: none;
background-color: transparent;
outline: none;
}
.minus{
font-size: 30px;
cursor: pointer;
font-weight: bold;
border: none;
background-color: transparent;
outline: none;
}
.remove button{
font-size:30px;
cursor: pointer;
border: none;
background-color: transparent;
outline: none;
}
.test-warning{
text-align: center;
margin-top: 40px;
font-size: 24px;
color: red;
}
.total-container{
display: flex;
justify-content: flex-end;
width: 100%;
padding: 10px 0;
}
.total-title{
width: 20%;
}
.total{
width: 10%;
}
.StripeCheckout{
overflow: hidden;
display: inline-block;
background: linear-gradient(rgb(40, 160, 229), rgb(1, 94, 148));
border: 0px;
padding: 1px;
text-decoration: none;
border-radius: 5px;
box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 0px;
cursor: pointer;
visibility: visible;
user-select: none;
margin-left: 50%;
margin-top: 50px;
}
<!DOCTYPE html>
<html>
<head>
<title>CRWN Clothing</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script type="text/javascript"src="index.js"></script>
</head>
<body>
<header>
<div class="logo">
<a class="logo-container" href="index.html">
<svg width="50px" height="39px" viewBox="0 0 50 39" class="logo"><title>Group</title><desc>Created with Sketch.</desc><g id="WiP" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Artboard" transform="translate(-90.000000, -38.000000)"><g id="Group" transform="translate(90.000000, 38.000000)"><polygon id="Rectangle" fill="#808282" points="3 14 25 26.5 47 14 40.855176 39 9.08421785 39"></polygon><polygon id="Triangle" fill-opacity="0.262838724" fill="#101A1A" points="25 8 40 39 10 39"></polygon><circle id="Oval" fill="#5E6363" cx="2" cy="9" r="2"></circle><circle id="Oval" fill="#5E6363" cx="25" cy="2" r="2"></circle><circle id="Oval" fill="#5E6363" cx="48" cy="9" r="2"></circle>
</g></g></g>
</svg>
</a>
</div>
<div class="option" onclick="location.href='./cart.html'">
<div class="cart-icon" onclick="location.href='./cart.html'">
<svg id="Capa_1" x="0px" y="0px" viewBox="0 0 407.453 407.453" xml:space="preserve" class="shopping-icon"><g><path d="M255.099,116.515c4.487,0,8.129-3.633,8.129-8.129c0-4.495-3.642-8.129-8.129-8.129H143.486 c-4.487,0-8.129,3.633-8.129,8.129c0,4.495,3.642,8.129,8.129,8.129H255.099z" style="fill: rgb(1, 0, 2);"></path><path d="M367.062,100.258H311.69c-4.487,0-8.129,3.633-8.129,8.129c0,4.495,3.642,8.129,8.129,8.129h47.243 v274.681H48.519V116.515h44.536c4.487,0,8.129-3.633,8.129-8.129c0-4.495-3.642-8.129-8.129-8.129H40.391 c-4.487,0-8.129,3.633-8.129,8.129v290.938c0,4.495,3.642,8.129,8.129,8.129h326.671c4.487,0,8.129-3.633,8.129-8.129V108.386 C375.191,103.891,371.557,100.258,367.062,100.258z" style="fill: rgb(1, 0, 2);"></path><path d="M282.59,134.796c4.487,0,8.129-3.633,8.129-8.129V67.394C290.718,30.238,250.604,0,201.101,0 c-49.308,0-89.414,30.238-89.414,67.394v59.274c0,4.495,3.642,8.129,8.129,8.129s8.129-3.633,8.129-8.129V67.394 c0-28.198,32.823-51.137,73.36-51.137c40.334,0,73.157,22.939,73.157,51.137v59.274 C274.461,131.163,278.095,134.796,282.59,134.796z" style="fill: rgb(1, 0, 2);"></path><path d="M98.892,147.566c0,11.526,9.389,20.907,20.923,20.907c11.534,0,20.923-9.38,20.923-20.907 c0-4.495-3.642-8.129-8.129-8.129s-8.129,3.633-8.129,8.129c0,2.561-2.089,4.65-4.666,4.65c-2.569,0-4.666-2.089-4.666-4.65 c0-4.495-3.642-8.129-8.129-8.129S98.892,143.071,98.892,147.566z" style="fill: rgb(1, 0, 2);"></path><path d="M282.59,168.473c11.534,0,20.923-9.38,20.923-20.907c0-4.495-3.642-8.129-8.129-8.129 c-4.487,0-8.129,3.633-8.129,8.129c0,2.561-2.089,4.65-4.666,4.65c-2.577,0-4.666-2.089-4.666-4.65 c0-4.495-3.642-8.129-8.129-8.129c-4.487,0-8.129,3.633-8.129,8.129C261.667,159.092,271.055,168.473,282.59,168.473z" style="fill: rgb(1, 0, 2);"></path></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg>
<span class="item-count"> 0 </span>
</div>
</div>
</header>
<main>
<div class="collection-page">
<center><h1>Hats</h1></center>
<div class="items">
<div class="collection-item">
<div class="image" style="background-image: url("https://i.ibb.co/ZYW3VTp/brown-brim.png");"></div><div class="collection-footer"><span class="name">Brown Brim</span><span class="price">N25</span></div>
<button class="cart-button" >Add to cart</button></div>
<div class="collection-item">
<div class="image" style="background-image: url("https://i.ibb.co/ypkgK0X/blue-beanie.png");"></div>
<div class="collection-footer"><span class="name">Blue Beanie</span><span class="price">N18</span></div>
<button class="cart-button" >Add to cart</button></div>
<div class="collection-item">
<div class="image" style="background-image: url("https://i.ibb.co/QdJwgmp/brown-cowboy.png");"></div>
<div class="collection-footer"><span class="name">Brown Cowboy</span><span class="price">N35</span>
</div>
<button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/RjBLWxB/grey-brim.png");"></div>
<div class="collection-footer"><span class="name">Grey Brim</span><span class="price">N25</span></div><button class="cart-button" >Add to cart</button></div></div>
<center><h1 class="title">SNEAKERS</h1></center>
<div class="items">
<div class="collection-item">
<div class="image" style="background-image: url("https://i.ibb.co/0s3pdnc/adidas-nmd.png");"></div>
<div class="collection-footer"><span class="name">Adidas NMD</span><span class="price">N220</span></div><button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/dJbG1cT/yeezy.png");"></div><div class="collection-footer"><span class="name">Adidas Yeezy</span><span class="price">N280</span></div><button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/bPmVXyP/black-converse.png");"></div><div class="collection-footer"><span class="name">Black Converse</span><span class="price">N110</span></div><button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/1RcFPk0/white-nike-high-tops.png");"></div><div class="collection-footer"><span class="name">Nike White AirForce</span><span class="price">N160</span></div><button class="cart-button" >Add to cart</button></div></div>
<center><h1 class="title">JACKETS</h1></center>
<div class="items"><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/XzcwL5s/black-shearling.png");"></div><div class="collection-footer"><span class="name">Black Jean Shearling</span><span class="price">N125</span></div><button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/mJS6vz0/blue-jean-jacket.png");"></div><div class="collection-footer"><span class="name">Blue Jean Jacket</span><span class="price">N90</span></div><button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/N71k1ML/grey-jean-jacket.png");"></div><div class="collection-footer"><span class="name">Grey Jean Jacket</span><span class="price">N90</span></div><button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/s96FpdP/brown-shearling.png");"></div><div class="collection-footer"><span class="name">Brown Shearling</span><span class="price">N165</span></div><button class="cart-button" >Add to cart</button></div></div>
<center><h1 class="title">WOMEN</h1></center>
<div class="items"><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/7CQVJNm/blue-tank.png");"></div><div class="collection-footer"><span class="name">Blue Tanktop</span><span class="price">N25</span></div><button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/4W2DGKm/floral-blouse.png");"></div><div class="collection-footer"><span class="name">Floral Blouse</span><span class="price">N20</span></div><button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/KV18Ysr/floral-skirt.png");"></div><div class="collection-footer"><span class="name">Floral Dress</span><span class="price">N80</span></div><button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/N3BN1bh/red-polka-dot-dress.png");"></div><div class="collection-footer"><span class="name">Red Dots Dress</span><span class="price">N80</span></div><button class="cart-button" >Add to cart</button></div></div>
<center><h1 class="title">MEN</h1></center>
<div class="items">
<div class="collection-item">
<div class="image" style="background-image: url("https://i.ibb.co/xJS0T3Y/camo-vest.png");"></div>
<div class="collection-footer"><span class="name">Camo Down Vest</span><span class="price">N325</span></div>
<button class="cart-button">Add to cart</button></div>
<div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/qMQ75QZ/floral-shirt.png");"></div><div class="collection-footer"><span class="name">Floral T-shirt</span><span class="price">N20</span></div><button class="cart-button" >Add to cart</button></div><div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/55z32tw/long-sleeve.png");"></div><div class="collection-footer"><span class="name">Black & White Longsleeve</span><span class="price">N25</span></div>
<button class="cart-button" >Add to cart</button></div>
<div class="collection-item"><div class="image" style="background-image: url("https://i.ibb.co/RvwnBL8/pink-shirt.png");"></div>
<div class="collection-footer"><span class="name">Pink T-shirt</span><span class="price">N25</span></div>
<button class="cart-button" >Add to cart</button>
</div>
</div>
</div>
</main>
</body>
<script type="text/javascript"src="index.js"></script>
</html>
You are using the cart-contain class to identify an object and remove it. Since you have multiple items with that same class, whenever you click on any 'remove' button, it finds the first item with class cart-contain and removes it.
You want some unique identifier, which you add as an id to every .cart-contain item. Then you can refer to that id when you click remove.
<div id="SOME_ID_HERE" class="cart-contain">
<button onclick="remove(SOME_ID_HERE)">
function remove(id) {
let productNumbers = localStorage.getItem("cartNumbers");
var myobj = document.querySelector(id);
myobj.remove();
}
I'm making a small page for the product based on this tutorial. On the page I have a product component, where I keep a "add to cart" button. The card itself, however, is separated from the component and located inside index.html, that's why my cart property is being kept inside vue app (where app is an id of my root div in index.html).
Problem: I need my "add to cart" button to increment the number in the cart itself. I can't really understand how can I do this using addToCart and updateCart methods, as shown in the tutorial.
Can anyone help me out with this issue? I will appreciate any help! Thanks in advance!
Vue.component('product', {
props: {
premium: {
type: Boolean,
required: true
}
},
template: `
<div id="product">
<div class="product-image">
<img :src="image" />
</div>
<div class="product-info">
<h1>{{ title }}</h1>
<p>Shipping: {{ shipping }}</p>
<p v-if="inStock">In Stock</p>
<p v-else>Out of Stock</p>
<h2>Details</h2>
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
<h3>Colors:</h3>
<div v-for="(variant,index) in variants" :key="variant.variantId">
<div class="color-box" :style="{ backgroundColor: variant.variantColor }" #mouseover="updateProduct(index)"></div>
</div>
<button :class="{ disabledButton: !inStock }" v-on:click="add-to-cart" :disabled="!inStock">Add to Cart</button>
</div>
</div>
`,
data() {
return {
product: "Socks",
brand: "Vue Mastery",
selectedVariant: 0,
details: ["80% cotton", "20% polyester", "Gender-neutral"],
variants: [
{
variantId: 2234,
variantQuantity: 15,
variantColor: "green",
variantImage: "./assets/vmSocks-green.jpg"
},
{
variantId: 2235,
variantQuantity: 0,
variantColor: "blue",
variantImage: "./assets/vmSocks-blue.jpg"
}
]
}
},
methods: {
addToCart() {
this.$emit('add-to-cart')
},
updateProduct(index) {
this.selectedVariant = index
}
},
computed: {
title() {
return this.brand + ' ' + this.product
},
image() {
return this.variants[this.selectedVariant].variantImage
},
inStock() {
if (this.variants[this.selectedVariant].variantQuantity > 0) {
return true
} else {
return false
}
},
shipping() {
if (this.premium) {
return "Free"
} else {
return 2.99
}
}
}
})
var app = new Vue({
el: '#app',
data: {
premium: true,
cart: 0
},
methods: {
updateCart() {
this.cart += 1
}
}
})
body {
font-family: tahoma;
color:#282828;
margin: 0px;
}
.nav-bar {
background: linear-gradient(-90deg, #84CF6A, #16C0B0);
height: 60px;
margin-bottom: 15px;
}
.product {
display: flex;
flex-flow: wrap;
padding: 1rem;
}
img {
border: 1px solid #d8d8d8;
width: 70%;
margin: 40px;
box-shadow: 0px .5px 1px #d8d8d8;
}
.product-image {
width: 80%;
}
.product-image,
.product-info {
margin-top: 10px;
width: 50%;
}
.color-box {
width: 40px;
height: 40px;
margin-top: 5px;
}
.cart {
margin-right: 25px;
float: right;
border: 1px solid #d8d8d8;
padding: 5px 20px;
}
button {
margin-top: 30px;
border: none;
background-color: #1E95EA;
color: white;
height: 40px;
width: 100px;
font-size: 14px;
}
.disabledButton {
background-color: #d8d8d8;
}
.review-form {
width: 400px;
padding: 20px;
margin: 40px;
border: 1px solid #d8d8d8;
}
input {
width: 100%;
height: 25px;
margin-bottom: 20px;
}
textarea {
width: 100%;
height: 60px;
}
.tab {
margin-left: 20px;
cursor: pointer;
}
.activeTab {
color: #16C0B0;
text-decoration: underline;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewpoint" content="width=devide-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
<title>Vue app</title>
</head>
<body>
<div class="nav-bar"></div>
<div id="app">
<div class="cart">
<p>Cart({{ cart }})</p>
</div>
<product :premium="premium" #add-to-cart="updateCart"></product>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="prior.js"></script>
</body>
</html>
Change This:
<button :class="{ disabledButton: !inStock }" v-on:click="add-to-cart" :disabled="!inStock">Add to Cart</button>
To be this:
<button :class="{ disabledButton: !inStock }" v-on:click="addToCart" :disabled="!inStock">Add to Cart</button>
So addToCart: and this function will emit add-to-cart event
Also you can immediately run emmit onClick without adding function:
<button :class="{ disabledButton: !inStock }" v-on:click="$emit('add-to-cart')" :disabled="!inStock">Add to Cart</button>
Vue.component('product', {
props: {
premium: {
type: Boolean,
required: true
}
},
template: `
<div id="product">
<div class="product-image">
<img :src="image" />
</div>
<div class="product-info">
<h1>{{ title }}</h1>
<p>Shipping: {{ shipping }}</p>
<p v-if="inStock">In Stock</p>
<p v-else>Out of Stock</p>
<h2>Details</h2>
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
<h3>Colors:</h3>
<div v-for="(variant,index) in variants" :key="variant.variantId">
<div class="color-box" :style="{ backgroundColor: variant.variantColor }" #mouseover="updateProduct(index)"></div>
</div>
<button :class="{ disabledButton: !inStock }" v-on:click="addToCart" :disabled="!inStock">Add to Cart</button>
</div>
</div>
`,
data() {
return {
product: "Socks",
brand: "Vue Mastery",
selectedVariant: 0,
details: ["80% cotton", "20% polyester", "Gender-neutral"],
variants: [
{
variantId: 2234,
variantQuantity: 15,
variantColor: "green",
variantImage: "./assets/vmSocks-green.jpg"
},
{
variantId: 2235,
variantQuantity: 0,
variantColor: "blue",
variantImage: "./assets/vmSocks-blue.jpg"
}
]
}
},
methods: {
addToCart() {
this.$emit('add-to-cart')
},
updateProduct(index) {
this.selectedVariant = index
}
},
computed: {
title() {
return this.brand + ' ' + this.product
},
image() {
return this.variants[this.selectedVariant].variantImage
},
inStock() {
if (this.variants[this.selectedVariant].variantQuantity > 0) {
return true
} else {
return false
}
},
shipping() {
if (this.premium) {
return "Free"
} else {
return 2.99
}
}
}
})
var app = new Vue({
el: '#app',
data: {
premium: true,
cart: 0
},
methods: {
updateCart() {
this.cart += 1
}
}
})
body {
font-family: tahoma;
color:#282828;
margin: 0px;
}
.nav-bar {
background: linear-gradient(-90deg, #84CF6A, #16C0B0);
height: 60px;
margin-bottom: 15px;
}
.product {
display: flex;
flex-flow: wrap;
padding: 1rem;
}
img {
border: 1px solid #d8d8d8;
width: 70%;
margin: 40px;
box-shadow: 0px .5px 1px #d8d8d8;
}
.product-image {
width: 80%;
}
.product-image,
.product-info {
margin-top: 10px;
width: 50%;
}
.color-box {
width: 40px;
height: 40px;
margin-top: 5px;
}
.cart {
margin-right: 25px;
float: right;
border: 1px solid #d8d8d8;
padding: 5px 20px;
}
button {
margin-top: 30px;
border: none;
background-color: #1E95EA;
color: white;
height: 40px;
width: 100px;
font-size: 14px;
}
.disabledButton {
background-color: #d8d8d8;
}
.review-form {
width: 400px;
padding: 20px;
margin: 40px;
border: 1px solid #d8d8d8;
}
input {
width: 100%;
height: 25px;
margin-bottom: 20px;
}
textarea {
width: 100%;
height: 60px;
}
.tab {
margin-left: 20px;
cursor: pointer;
}
.activeTab {
color: #16C0B0;
text-decoration: underline;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewpoint" content="width=devide-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
<title>Vue app</title>
</head>
<body>
<div class="nav-bar"></div>
<div id="app">
<div class="cart">
<p>Cart({{ cart }})</p>
</div>
<product :premium="premium" #add-to-cart="updateCart"></product>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="prior.js"></script>
</body>
</html>
I have an interesting problem with one of my RoR application pages that is a bit hard to explain.
Basically, I have a page vendor.html.erb which allows the user to input data for vendors, including selecting their location (country, state, city) from dropdowns that appear depending on the country and states selected. This seems to work just fine when I refresh the web page but when I access the page through the navigation bar (_header.html.erb), the dropdowns fail to appear. The input placeholders also fail to appear when accessing the page through links.
Below is my /app/views/static_pages/vendor.html.erb
<head>
<style>
.hidden {
display: none;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="/application-258e88d.css" data-turbolinks-track="reload">
<script src="/application-cbd3cd4.js" data-turbolinks-track="reload"></script>
<meta name="turbolinks-visit-control" content="reload">
<script>
var data = {
countries: [{
name: 'China',
childs: [{
name: 'Beijing',
childs: [{name: 'Beijing'}, {name: 'Dongcheng'}]
}, {
name: 'Tianjin',
childs: [{name: 'Guangzhou'}, {name: 'Shanghai'}]
}]
}, {
name: 'India',
childs: [{
name: 'Uttar',
childs: [{name: 'Kanpur'}, {name: 'Ghaziabad'}]
}, {
name: 'Maharashtra',
childs: [{name: 'Mumbai'}, {name: 'Pune'}]
}]
}, {
name: 'USA',
childs: [{
name: 'Washington',
childs: [{name: 'Washington'}, {name: 'Seatle'}]
}, {
name: 'Florida',
childs: [{name: 'Orlando'}, {name: 'Miami'}]
}]
}]
};
function buildSelect(name, data, childs) {
var div = $('<div>');
div.addClass('hidden autoSelect ' + data.name + ' ' + name);
var label = $('<label>');
label.text(name);
var select = $('<select>');
var option = $('<option>');
option.text('--');
select.append(option);
data.childs.forEach(function (child) {
option = $('<option>');
option.val(child.name);
option.text(child.name);
select.append(option);
});
if (childs) select.on('change', updateCities);
label.append(select);
div.append(label);
$('.country').append(div);
}
function buildForms(data) {
data.countries.forEach(function (country) {
buildSelect('State', country, true);
country.childs.forEach(function (state) {
buildSelect('City', state);
});
});
}
function hideAutoSelect (name) {
$('div.autoSelect.'+name).addClass('hidden');
}
function updateStates() {
var v = this.value;
if (v) {
hideAutoSelect('State');
hideAutoSelect('City');
var div = $('div.autoSelect.'+v);
div.removeClass('hidden');
var select = $('select', div);
if (select.val()) $('div.autoSelect.'+select.val()).removeClass('hidden');
}
}
function updateCities() {
var v = $(this).val();
if (v) {
hideAutoSelect('City');
$('div.autoSelect.'+v).removeClass('hidden');
}
}
$(document).on('ready',function () {
buildForms(data);
$('[name=country]').on('change', updateStates);
});
</script>
</head>
<body>
<div class="container">
<h3>Add Vendor</h3>
<div class="tab-content">
<form action="/add/vendors" method="post">
<!-- ################# Our own in-house ID for this vendor #################-->
<div class="top-row">
<div class="field-wrap">
<label>Create vendor ID<span class="req">*</span>
<input placeholder="V00000">
</label>
</div>
</div>
<!-- ############################### Vendor name #################################-->
<div class="top-row">
<div class="field-wrap">
<label>Vendor name<span class="req">*</span>
<input placeholder="John">
</label>
</div>
</div>
<!-- ################################ Vendor type ################################-->
<div class="field-wrap">
<label>
Vendor type<span class= "req">*</span>
<select>
<option selected="--">--</option>
</select></label>
</div>
<!-- ############################## Vendor location ##############################-->
<div class="field-wrap country">
<label>Vendor origin<span class="req">*</span>
<select name="country">
<option selected= "--">--</option>
<option value= "China" >China</option>
<option value= "India" >India</option>
<option value= "USA" >USA</option>
</select>
</label>
</div>
</form>
</div>
</div>
</body>
Below is my /app/views/layouts/_header.html.erb
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html{
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
}
body{
padding: 80px;
}
header {
padding: 10px;
top: 0px;
left: 0px;
margin: 0;
background: #fff;
min-width: 100%;
z-index: 1;
justify-content: center;
position: fixed;
display: flex;
}
.nav {
background: #232323;
height: 60px;
*display:inline;
*zoom:1;
width: 60%;
margin: 0;
padding: 0;
text-align: center;
vertical-align: top;
}
.nav li {
display: inline;
float: left;
list-style-type: none;
position: relative;
}
.nav li a {
font-size: 14px;
color: white;
display: block;
line-height: 60px;
padding: 0 26px;
text-decoration: none;
border-left: 1px solid #2e2e2e;
font-family: Arial;
text-shadow: 0 0 1px rgba(255, 255, 255, 0.5);
}
.nav li a:hover {
background-color: #2e2e2e;
}
#search {
width: 357px;
margin: 4px;
}
#search_text{
width: 297px;
padding: 15px 0 15px 20px;
font-size: 16px;
font-family: Arial;
border: 0 none;
height: 52px;
margin-right: 0;
color: white;
outline: none;
background: #494949;
float: left;
box-sizing: border-box;
transition: all 0.15s;
}
::-webkit-input-placeholder { /* WebKit browsers */
color: white;
}
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: white;
}
::-moz-placeholder { /* Mozilla Firefox 19+ */
color: white;
}
:-ms-input-placeholder { /* Internet Explorer 10+ */
color: white;
}
#search_text:focus {
background: #5a5a5a;
}
#options a{
border-left: 0 none;
}
.subnav {
visibility: hidden;
position: absolute;
top: 110%;
right: 0;
width: 200px;
height: auto;
opacity: 0;
z-index: 1;
transition: all 0.1s;
background: #232323;
}
.subnav li {
float: none;
}
.subnav li a {
border-bottom: 1px solid #2e2e2e;
}
#options:hover .subnav {
visibility: visible;
top: 100%;
opacity: 1;
}
button {
display: inline-block;
padding: 10px;
}
</style>
</head>
<body>
<header>
<ul class= "nav">
<li><a class="active" href="/home">Home</a></li>
<% if logged_in? %>
<li><%= link_to "Profile", edit_user_path(current_user.id) %></li>
<%end%>
<li id= "options">
Add
<ul class= "subnav">
<li><%= link_to "Part", add_parts_path%></li>
<li><%= link_to "Project", add_projects_path%></li>
<li><%= link_to "Vendor", add_vendors_path%></li>
</ul>
</li>
<li><%= link_to "Contact", inquires_path, method: :get %></li>
<li><%= link_to "Log Out", logout_path, method: :delete %></li>
<li id= "search">
<form action= "" method= "get">
<input type="text" name="search_text" id= "search_text" placeholder="Search Page"/>
<button type="submit"><i class="fa fa-search"></i></button>
</form>
</li>
</ul>
</header>
</body>
As you are using turbolinks you should change ready for turbolinks:load.
$(document).on('turbolinks:load', function() {
buildForms(data);
$('[name=country]').on('change', updateStates);
})
According to this link (https://github.com/turbolinks/turbolinks#loading-your-applications-javascript-bundle), you should be using <script> elements in the <head> of your document.
Also you should consider adding data-turbolinks-track="reload" to your script element https://github.com/turbolinks/turbolinks#reloading-when-assets-change