Button not responding (even not hover) - javascript

const sentence = document.getElementById('sentence')
const word = document.getElementById('word')
const number = document.getElementById('number')
const btnContainer = document.getElementById('btnContainer')
function Start() {
btnContainer.style.display = 'flex';
}
Start()
sentence.addEventListener('click', () => {
type = 1;
Start();
})
word.addEventListener('click', () => {
type = 2;
Start();
})
number.addEventListener('click', () => {
type = 3;
Start();
})
.btnContainer {
position: absolute;
top: 60px;
right: .5vw;
gap: .2em;
width: 25vw;
height: 10vh;
align-items: center;
justify-content: center;
}
.btn {
background-color: transparent;
border: transparent;
font-size: 1.1rem;
color: var(--lightprimary);
transition: ease-in-out .2s;
}
.btn:hover {
color: var(--darkprimary);
}
<div class="btnContainer" id="btnContainer">
<button class="sentenceButton btn" id="sentence">Sentence</button>
<button class="wordButton btn" id="word">Words</button>
<button class="numberButton btn" id="number">Numbers</button>
</div>
There is more code that hasn't something to do with the buttons.
The 'btnContainer.style.display' is necessary to work with the other code.

Please confirm that your CSS :root selector is structured like so. In order for it to grab the primary color, you have to define that color first. Also, as mentioned in the comments it appears your buttons are responding via the console log.
const sentence = document.getElementById('sentence')
const word = document.getElementById('word')
const number = document.getElementById('number')
const btnContainer = document.getElementById('btnContainer')
function Start() {
btnContainer.style.display = 'flex';
}
Start()
sentence.addEventListener('click', () => { type = 1; Start(); })
word.addEventListener('click', () => { type = 2; Start(); })
number.addEventListener('click', () => { type = 3; Start(); })
.btnContainer {
position: absolute;
top: 60px;
right: .5vw;
gap: .2em;
width: 25vw;
height: 10vh;
align-items: center;
justify-content: center;
}
.btn {
background-color: white;
border: hidden;
font-size: 1.1rem;
color: var(--lightprimary);
transition: ease-in-out .2s;
}
.btn:hover {
background-color: var(--darkprimary-color);
}
:root {
--darkprimary-color: yellow;
}
<div class="btnContainer" id="btnContainer">
<button class="sentenceButton btn" id="sentence" type="button">Sentence</button>
<button class="wordButton btn" id="word" type="button">Words</button>
<button class="numberButton btn" id="number" type="button">Numbers</button>
</div>

Without the Javascript code and with defined --lightprimary and --darkprimary, everything works.
:root{
--lightprimary: green;
--darkprimary: red;
}
.btnContainer {
position: absolute;
top: 60px;
right: .5vw;
gap: .2em;
width: 25vw;
height: 10vh;
align-items: center;
justify-content: center;
}
.btn {
background-color: transparent;
border: transparent;
font-size: 1.1rem;
color: var(--lightprimary);
transition: ease-in-out .2s;
}
.btn:hover {
color: var(--darkprimary);
}
<div class="btnContainer" id="btnContainer">
<button class="sentenceButton btn" id="sentence">Sentence</button>
<button class="wordButton btn" id="word">Words</button>
<button class="numberButton btn" id="number">Numbers</button>
</div>

const shortApi = 'https://api.quotable.io/random?minLength=60&maxLength=80'
const mediumApi = 'https://api.quotable.io/random?minLength=100&maxLength=180'
const longApi = 'https://api.quotable.io/random?minLength=200&maxLength=220'
const display = document.getElementById('display')
const input = document.getElementById('input')
const restart = document.getElementById('restart-btn')
const sentence = document.getElementById('sentence')
const word = document.getElementById('word')
const number = document.getElementById('number')
const actionBtn1 = document.getElementById('btn1')
const actionBtn2 = document.getElementById('btn2')
const actionBtn3 = document.getElementById('btn3')
const actionBtn4 = document.getElementById('btn4')
const container = document.getElementById('container')
const btnContainer = document.getElementById('btnContainer')
const smallBtnContainer = document.getElementById('smallBtnContainer')
const stats = document.getElementById('stats')
const exit = document.getElementById('exit')
var type = 1
async function newQuote() {
display.innerText = '';
var quote = 'hello world'
let arr = quote.split("").map(value => {
return "<span class='span'>" + value + "</span>"
})
display.innerHTML += arr.join("");
}
function Start() {
newQuote()
input.value = null
stats.style.display = 'none';
container.style.display = 'flex';
btnContainer.style.display = 'flex';
smallBtnContainer.style.display = 'block';
input.disabled = false;
let startTime = null
let endTime = null
input.addEventListener('input', () => {
if (startTime == null)
startTime = new Date()
let quoteChars = document.querySelectorAll(".span")
var mistakes = 0
quoteChars = Array.from(quoteChars)
let inputChars = input.value.split("")
quoteChars.forEach((char, index) => {
if (char.innerText === inputChars[index]) {
char.classList.add('correct')
char.classList.remove('incorrect')
} else if (inputChars[index] == null) {
char.classList.remove('correct')
char.classList.remove('incorrect')
} else {
char.classList.remove('correct')
char.classList.add('incorrect')
mistakes += 1
}
})
if (inputChars.length >= quoteChars.length) {
clicked = false
stats.style.display = 'block';
container.style.display = 'none';
btnContainer.style.display = 'none';
smallBtnContainer.style.display = 'none';
input.disabled = true;
endTime = new Date()
const delta = endTime - startTime
const seconds = delta / 1000
const minutes = seconds / 60
const accuracy = Math.round(((input.value.length - mistakes) / input.value.length) * 100)
const wpm = (input.value.length / 5 / minutes).toFixed(2) + " wpm"
document.getElementById('score').innerHTML = wpm
document.getElementById('mistakes').innerText = mistakes
document.getElementById('accuracy').innerText = accuracy + "%"
}
})
}
function changeActionButtons(type) {
actionBtn1.style.display = 'block'
actionBtn2.style.display = 'block'
actionBtn3.style.display = 'block'
actionBtn4.style.display = 'block'
if (type == 1) {
actionBtn1.style.display = 'none'
actionBtn2.textContent = 'short'
actionBtn3.textContent = 'medium'
actionBtn4.textContent = 'long'
} else if (type == 2) {
actionBtn1.textContent = '1'
actionBtn2.textContent = '10'
actionBtn3.textContent = '20'
actionBtn4.textContent = '30'
} else if (type == 3) {
actionBtn1.textContent = '1'
actionBtn2.textContent = '5'
actionBtn3.textContent = '10'
actionBtn4.textContent = '15'
}
}
changeActionButtons(type)
Start()
exit.addEventListener('click', () => {
stats.style.display = 'none';
container.style.display = 'flex';
btnContainer.style.display = 'block';
smallBtnContainer.style.display = 'block';
Start()
})
restart.addEventListener('click', () => {
Start();
})
sentence.addEventListener('click', () => {
console.log('gello');
type = 1;
changeActionButtons(1);
Start();
console.log('clicked');
})
word.addEventListener('click', () => {
type = 2;
changeActionButtons(2);
Start();
})
number.addEventListener('click', () => {
type = 3;
changeActionButtons(3);
Start();
})
* {
box-sizing: border-box;
}
:root {
--primary: #222;
--lightprimary: #555;
--darkprimary: #0f0f0f;
--secondary: #ffcf00;
--incorrect: #ff2d2d;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background-color: var(--primary);
font-size: 2rem;
font-family: 'Oxygen', Arial, sans-serif;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
-khtml-user-select: none;
}
button {
font-family: 'Oxygen', Arial, sans-serif;
}
.container {
position: relative;
display: flex;
width: 90%;
height: 50vh;
text-align: center;
justify-content: center;
align-items: center;
padding: 1rem;
color: var(--lightprimary);
max-width: 1000px;
transition: ease-in-out .2s;
}
.quote {
font-family: 'Oxygen Mono', monospace;
display: block;
position: absolute;
top: 100px;
}
.input {
font-family: 'Oxygen Mono', monospace;
position: absolute;
top: 280px;
resize: none;
width: 100%;
border: 2px solid var(--lightprimary);
border-radius: 20px;
text-align: left;
font-size: 1.1rem;
margin: auto;
outline: none;
text-align: center;
color: var(--lightprimary);
background-color: transparent;
}
.input:focus {
border-color: var(--darkprimary);
}
.restart-btn {
position: absolute;
top: 340px;
background-color: transparent;
border: transparent;
font-size: 4rem;
color: var(--lightprimary);
transition: ease-in-out .2s;
}
.restart-btn:hover {
color: var(--darkprimary);
}
.btnContainer {
position: absolute;
top: 60px;
right: .5vw;
gap: .2em;
width: 25vw;
height: 10vh;
align-items: center;
justify-content: center;
}
.btn {
font-size: 1.1rem;
color: var(--lightprimary);
transition: ease-in-out .2s;
}
.btn:hover {
color: var(--darkprimary);
}
.smallBtnContainer {
position: absolute;
top: 70px;
right: 6.5vw;
gap: .2em;
width: 25vw;
height: 10vh;
align-items: center;
justify-content: center;
}
.smallBtn {
background-color: transparent;
border: transparent;
font-size: 1rem;
color: var(--lightprimary);
transition: ease-in-out .2s;
}
.smallBtn:hover {
color: var(--darkprimary);
}
.stats {
display: none;
justify-content: center;
align-items: center;
width: 40vw;
height: 40vh;
position: absolute;
color: var(--secondary);
text-align: center;
font-size: 1.6rem;
transition: ease-in-out .2s;
}
.exit {
font-size: 2rem;
background-color: transparent;
border: transparent;
color: var(--lightprimary);
transition: ease-in-out .2s;
}
.exit:hover {
color: var(--darkprimary);
}
.logo {
position: absolute;
width: 200px;
aspect-ratio: 1;
top: 0;
left: 0;
}
.title {
position: absolute;
color: var(--secondary);
top: 75px;
left: 150px;
}
.correct {
color: var(--secondary);
text-decoration: none;
}
.incorrect {
color: var(--incorrect);
text-decoration: underline;
}
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css2?family=Oxygen&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Oxygen+Mono&display=swap" rel="stylesheet">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<title>Type Lite</title>
<script src="script.js" defer></script>
</head>
<body>
<img class="logo" alt='logo'>
<p class='title'>logo</p>
<div class="stats" id="stats">
<p>Score: <span id="score"></span></p>
<p>Mistakes: <span id="mistakes"></span></p>
<p>Accuracy: <span id="accuracy"></span></p>
<button class="exit" id="exit">X</button>
</div>
<div class="container" id="container">
<div class="quote" id="display"></div>
<textarea class="input" id="input" cols="90" rows="2" placeholder="Type here to start." autofocus></textarea>
<button class="restart-btn" id="restart-btn">Restart</button>
</div>
<div class="btnContainer" id="btnContainer">
<button class="sentenceButton btn" id="sentence">Sentence</button>
<button class="wordButton btn" id="word">Words</button>
<button class="numberButton btn" id="number">Numbers</button>
</div>
<div class="smallBtnContainer" id="smallBtnContainer">
<button class="smallBtn" id="btn1">1</button>
<button class="smallBtn" id="btn2">2</button>
<button class="smallBtn" id="btn3">3</button>
<button class="smallBtn" id="btn4">4</button>
</div>
</body>
</html>

Related

Trying to update html with javascript

So here is my code that i need help with
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style8.css" />
<title>Progress Steps</title>
</head>
<body>
<div class="container">
<div class="progress-container">
<div class="progress" id="progress"></div>
<div class="circle active">1</div>
<div class="circle">2</div>
<div class="circle">3</div>
<div class="circle">4</div>
</div>
<button class="btn" id="prev" disabled>Prev</button>
<button class="btn" id="next">Next</button>
</div>
<script src="script8.js"></script>
</body>
</html>
Here is the css
#import url('https://fonts.googleapis.com/css?family=Muli&display=swap');
:root {
--line-border-fill: #3498db;
--line-border-empty: #383838;
}
* {
box-sizing: border-box;
}
body {
background-color: #1f1f1f;
font-family: 'Muli', sans-serif;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
margin: 0;
}
.container {
text-align: center;
}
.progress-container { //im trying to use this
display: flex;
justify-content: space-between;
position: relative;
margin-bottom: 30px;
max-width: 100%;
width: 350px;
}
.progress-container::before { //im trying to use this
content: '';
background-color: var(--line-border-empty);
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 100%;
z-index: -1;
}
.progress { //im trying to use this
background-color: var(--line-border-fill);
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 0%;
z-index: -1;
transition: 0.4s ease;
}
.circle {
background-color: #1f1f1f;
color:#e2e2e2;
border-radius: 50%;
height: 30px;
width: 30px;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid var(--line-border-empty);
transition: 0.4s ease;
}
.circle.active {
border-color: var(--line-border-fill);
}
.btn {
background-color: var(--line-border-fill);
color: #fff;
border: 0;
border-radius: 6px;
cursor: pointer;
font-family: inherit;
padding: 8px 30px;
margin: 5px;
font-size: 14px;
}
.btn:active {
transform: scale(0.98);
}
.btn:focus {
outline: 0;
}
.btn:disabled {
background-color: var(--line-border-empty);
cursor: not-allowed;
}
And here is the javascript. Im not really familiar with javascript. Kind of a newbie at it.
const progress = document.getElementById("progress");
const prev = document.getElementById("prev");
const next = document.getElementById("next");
const circles = document.querySelectorAll(".circle");
let currentActive = 1;
next.addEventListener("click", () => {
currentActive++;
if (currentActive > circles.length) {
currentActive = circles.length;
}
update();
});
prev.addEventListener("click", () => {
currentActive--;
if (currentActive < 1) {
currentActive = 1;
}
update();
});
function update() { //here is the part i need help with
}
const actives = document.querySelectorAll(".active");
progress.style.width =
((actives.length - 1) / (circles.length - 1)) * 100 + "%";
if (currentActive === 1) {
prev.disabled = true;
} else if (currentActive === circles.length) {
next.disabled = true;
} else {
prev.disabled = false;
next.disabled = false;
}
Im trying to write a function to update the html when the back or next button is pressed and i need to use the progress css class. I have no idea how to implement it.
You should be able to use the DOM control functions in JavaScript to fix your problem.
Send my answer. Sincerely
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Progress Steps</title>
</head>
<style>
#import url('https://fonts.googleapis.com/css?family=Muli&display=swap');
:root {
--line-border-fill: #3498db;
--line-border-empty: #383838;
}
* {
box-sizing: border-box;
}
body {
background-color: #1f1f1f;
font-family: 'Muli', sans-serif;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
margin: 0;
}
.container {
text-align: center;
}
.progress-container {
display: flex;
justify-content: space-between;
position: relative;
margin-bottom: 30px;
max-width: 100%;
width: 350px;
}
.progress-container::before {
content: '';
background-color: var(--line-border-empty);
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 100%;
z-index: -1;
}
.progress {
background-color: #3498db;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 0%;
z-index: -1;
transition: 0.4s ease;
}
.circle {
background-color: #1f1f1f;
color:#e2e2e2;
border-radius: 50%;
height: 30px;
width: 30px;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid var(--line-border-empty);
transition: 0.4s ease;
}
.circle.active {
border-color: #3498db;
}
.btn {
background-color: #3498db;
color: #fff;
border: 0;
border-radius: 6px;
cursor: pointer;
font-family: inherit;
padding: 8px 30px;
margin: 5px;
font-size: 14px;
}
.btn:active {
transform: scale(0.98);
}
.btn:focus {
outline: 0;
}
.btn:disabled {
background-color: var(--line-border-empty);
cursor: not-allowed;
}
</style>
<body>
<div class="container">
<div id="content" style="border: 1px solid black; margin: 0 auto; width: 300px; height: 100px; background-color: white;">
Content 1
</div>
<div class="progress-container">
<div class="progress" id="progress"></div>
<div class="circle active">1</div>
<div class="circle">2</div>
<div class="circle">3</div>
<div class="circle">4</div>
</div>
<button class="btn" id="prev" disabled>Prev</button>
<button class="btn" id="next">Next</button>
</div>
</body>
<script>
const progress = document.getElementById("progress");
const prev = document.getElementById("prev");
const next = document.getElementById("next");
const content = document.getElementById("content"); // added
const circles = document.querySelectorAll(".circle");
let currentActive = 1;
next.addEventListener("click", () => {
currentActive++;
if (currentActive > circles.length) {
currentActive = circles.length;
}
update(currentActive);
});
prev.addEventListener("click", () => {
currentActive--;
if (currentActive < 1) {
currentActive = 1;
}
update(currentActive);
});
function update(currentStep) {
//here is the part I fixed
let stepItems = document.getElementsByClassName("circle");
for (let i = 0; i < stepItems.length; i++) {
const stepItem = stepItems[i];
if (stepItem.textContent == currentStep) {
stepItem.classList.toggle("active");
}
}
prev.toggleAttribute("disabled", false);
next.toggleAttribute("disabled", false);
if (currentStep == 1) prev.setAttribute("disabled", true);
if (currentStep == 4) next.setAttribute("disabled", true);
content.innerText = "Content" + currentStep;
}
const actives = document.querySelectorAll(".active");
progress.style.width = ((actives.length - 1) / (circles.length - 1)) * 100 + "%";
if (currentActive === 1) {
prev.disabled = true;
} else if (currentActive === circles.length) {
next.disabled = true;
} else {
prev.disabled = false;
next.disabled = false;
}
</script>
</html>

Insert HTML element

I am trying to insert an HTML element (in my file it is called "baseketTotal"). This element is something like a checkout form that has the total price and etc... The thing is that I am trying to put it only on the last movie in the list which I add to the bag.
In this link, it is a picture of how it looks now. So I need to display it only on the last movie, no matter if the list has 1,2, or 10 movies. Only on the last one.
HTML
<!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://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD#48,400,0,0"
/>
<link rel="stylesheet" href="style.css" />
<title>Filmovizija</title>
</head>
<body>
<h1>Filmovizija</h1>
<div class="prozor"></div>
<h2>Shooping bag</h2>
<div class="shooping-cart"></div>
<script src="script.js"></script>
</body>
</html>
css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #22254b;
font-family: "Poppins", sans-serif;
}
h1 {
text-align: center;
color: #eee;
font-family: inherit;
margin-top: 30px;
margin-bottom: 30px;
}
.prozor {
display: flex;
flex-wrap: wrap;
}
.movie {
width: 300px;
border-radius: 4px;
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.3);
background-color: #373b69;
margin: 25px;
}
.movie-info {
color: #eee;
display: flex;
justify-content: space-between;
padding: 10px;
letter-spacing: 1px;
align-items: center;
}
.movie img {
width: 100%;
border-bottom: 1px solid white;
height: 450px;
}
.movie-info h3 {
font-weight: 300;
margin: 0;
}
.movie-info span {
font-weight: 400;
border-radius: 3px;
background-color: #22254b;
padding: 3px 7px;
}
.movie .kupi {
color: #eee;
display: flex;
justify-content: space-between;
padding: 10px;
padding-bottom: 15px;
letter-spacing: 1px;
align-items: center;
}
.movie .kupi button {
padding: 2px 8px;
font-size: 14px;
font-weight: 500;
}
.movie .kupi span {
font-size: 18px;
font-weight: 500;
}
/* ----------------------------------- SHOOPING CART ------------------------------------------------ */
.shooping-cart {
border-top: 2px solid rgb(214, 214, 214);
width: 1000px;
height: 500px;
margin-left: 25px;
}
h2 {
color: whitesmoke;
text-transform: uppercase;
font-size: 20px;
font-weight: 300;
margin-bottom: 20px;
margin-left: 25px;
}
.shooping-cart .single-item {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px;
border-bottom: 2px dotted grey;
}
.shooping-cart .single-item span {
background-color: rgb(255, 255, 255);
margin-left: 20px;
border-radius: 50%;
color: black;
}
.smallPic {
height: 70px;
width: 70px;
border: 1px solid grey;
}
.shooping-cart .single-item .opis {
align-items: center;
display: flex;
flex-direction: column;
color: white;
font-family: inherit;
}
.shooping-cart .single-item .opis h2 {
font-weight: 300;
margin-bottom: 5px;
}
.shooping-cart .single-item .opis h3 {
font-size: 14px;
font-weight: bold;
color: antiquewhite;
text-transform: uppercase;
}
.shooping-cart .single-item .kolicina input {
width: 30px;
text-align: center;
}
.shooping-cart .single-item .kolicina button {
padding: 2px 6px;
background-color: whitesmoke;
border: 0;
}
.single-total {
color: white;
margin-right: 20px;
}
/* ----------------------------------- SHOOPING CART TOTAL ALL ------------------------------------------------ */
.totalKosara {
float: right;
display: flex;
flex-direction: column;
width: 350px;
height: 160px;
margin-top: 15px;
}
.potvrdi {
display: flex;
width: 100%;
margin: 20px 0;
justify-content: space-between;
text-align: center;
}
.potvrdi .sub,
.price {
color: #eee;
font-weight: bold;
padding: 5px;
}
.text {
color: white;
font-size: 14px;
text-align: center;
}
.blue {
width: 100%;
align-items: center;
display: flex;
justify-content: center;
margin-top: 30px;
}
.blue button {
width: 100%;
border-radius: 2px;
border: 0;
padding: 10px;
background-color: #0b1050;
color: #eee;
font-family: inherit;
border: 1px solid grey;
}
scriptJS
const options = {
method: "GET",
headers: {
"X-RapidAPI-Key": "cd782e9b03mshbd50bac036f1802p16179djsn48c38f33f263",
"X-RapidAPI-Host": "online-movie-database.p.rapidapi.com",
},
};
const main = document.querySelector(`.prozor`);
const shoopingCart = document.querySelector(`.shooping-cart`);
const checkoutBtn = document.querySelector(`.checkoutBtn`);
fetch(
"https://online-movie-database.p.rapidapi.com/auto-complete?q=hacker",
options
)
.then((response) => response.json())
.then((data) => {
const list = data.d;
list.map((item) => {
const name = item.l;
const rank = item.rank;
const price = Math.floor(rank / 100);
const poster = item.i.imageUrl;
const movie = ` <div class="movie">
<img src=${poster} alt="${name}" />
<div class="movie-info">
<h3>${name}</h3>
<span>#${rank}</span>
</div>
<div class="kupi">
<button class="addToBag">Kupi film</button>
<span>${price} HRK</span>
</div>
</div>`;
main.innerHTML += movie;
//---------------------------------- add to basket --------------------------//
const button = document.querySelectorAll(`.addToBag`);
button.forEach((button) => {
button.addEventListener(`click`, function (e) {
const clicked = e.target;
const kupi = clicked.closest(`.kupi`);
const cijena2 = kupi.querySelector(`span`).innerText;
const cijena = cijena2.split(` `)[0];
const parent = kupi.closest(`.movie`);
const imeFilma = parent.querySelector(`.movie-info h3`).innerText;
const imgSrc = parent.querySelector(`img`).src;
const singleItem = `
<div class="single-item">
<span class="material-symbols-outlined deleteItem"> close </span>
<img src=${imgSrc} alt="aaa" class="smallPic" />
<div class="opis">
<h2>${imeFilma}</h2>
</div>
<div class="kolicina">
<button class="plus">+</button>
<input type="text" value="1" max="3" min="1" class="input"/>
<button class="minus">-</button>
</div>
<div class="single-total" data-value="${cijena}">${cijena} KN</div>
</div>
`;
shoopingCart.innerHTML += singleItem;
const basketTotal = `
<div class="totalKosara vidljivo">
<div class="potvrdi">
<p class="sub">Subtotal</p>
<p class="price">675 KN</p>
</div>
<div class="text">
<p>Shipping, taxes and discounts calculated at checkout.</p>
</div>
<div class="blue"><button>Checkout</button></div>
</div>
`;
const removeElement = function () {
const nodes = document.querySelectorAll(`.single-item`);
let lastNode = nodes[nodes.length - 1];
console.log(lastNode);
};
removeElement();
//OBRISI ITEM
const deleteItem = document.querySelectorAll(`.deleteItem`);
deleteItem.forEach((btn) => {
btn.addEventListener(`click`, function (e) {
const mainEl = e.target.closest(`.single-item`);
mainEl.parentNode.removeChild(mainEl);
button.disabled = false;
});
});
//add more movies btn
const plusBtn = document.querySelectorAll(`.plus`);
const minusBtn = document.querySelectorAll(`.minus`);
plusBtn.forEach((btn) => {
btn.addEventListener(`click`, function (e) {
let plus = e.target;
let parent = plus.closest(`.kolicina`);
let input = parent.querySelector(`.input`);
let singleEl = parent.closest(`.single-item`);
let singleTotal = singleEl.querySelector(`.single-total`);
input.value++;
if (input.value > 3) input.value = 3;
singleTotal.innerText = `${
singleTotal.dataset.value * input.value
} KN`;
});
});
minusBtn.forEach((btn) => {
btn.addEventListener(`click`, function (e) {
let plus = e.target;
let parent = plus.closest(`.kolicina`);
let input = parent.querySelector(`.input`);
let singleEl = parent.closest(`.single-item`);
let singleTotal = singleEl.querySelector(`.single-total`);
input.value--;
console.log(input.innerText);
if (input.value < 1) input.value = 1;
singleTotal.innerText = `${
singleTotal.dataset.value * input.value
} KN`;
});
});
});
});
});
})
.catch(
(err) => console.error(err));
I couldn't understand clearly what you are trying to say. But as far as considered to append a child to parent div you can use
parentDiv.appendChild(childElement);
Appreciate it if you can make the question more understable.

Text flows out of input after next event is fired if input is focued

While building a basic application, when I click a button, the text inside my currently focused input overflows only in Chrome. However, that text can be accessed using (right) arrow key(s). Is there any way to avoid this? I tried clipboard copy-paste but that did not work.
const peopleElem = document.querySelector("#people");
const billElem = document.querySelector("#bill");
const submit = document.querySelector("[type=\"submit\"]");
const form = document.querySelector("form");
const tipPerPersonElem = document.querySelector("[data-tip-person]");
const totalPerPersonElem = document.querySelector("[data-total-person]");
let billError = peopleError = false;
class TipCalc {
constructor() {
this.tipPerPerson = 0;
this.totalPerPerson = 0;
this.tip = 0
this.tipPercent = 0;
this.bill = parseFloat(billElem.value);
this.people = parseFloat(peopleElem.value);
}
getTip() {
const element = document.querySelector(".active");
if (!element) return 0;
if (element.tagName === "BUTTON") return this.tipPercent = element.innerText.replace("%", "");
return this.tipPercent = element.value.replace("%", "");
}
getTipPerPerson() {
this.getTip();
this.tip = ((this.tipPercent / 100) * this.bill);
this.tipPerPerson = this.tip / this.people;
return this.tipPerPerson;
}
getTotalPerPerson() {
this.getTipPerPerson();
this.totalPerPerson = (this.bill + this.tip) / this.people
return this.totalPerPerson;
}
}
const tipOptions = [...document.querySelectorAll("button"), document.querySelector("#custom")];
tipOptions.forEach(option => {
if (option.tagName === "INPUT" && option.value.length) option.addEventListener("keyup", () => {
tipOptions.forEach(option => option.classList.remove("active"));
option.classList.toggle("active");
})
if (!(option.type == "submit")) option.addEventListener("click", () => {
tipOptions.forEach(option => option.classList.remove("active"));
option.classList.toggle("active");
})
})
form.addEventListener("submit", event => {
event.preventDefault();
checkInputForError(peopleElem, peopleError, true);
checkInputForError(billElem, billError, false);
if (billError || peopleError) return;
const tipCalculator = new TipCalc();
const tip = isNaN(tipCalculator.getTipPerPerson()) ? 0 : tipCalculator.getTipPerPerson();
const total = isNaN(tipCalculator.getTotalPerPerson()) ? 0 : tipCalculator.getTotalPerPerson();
const formatter = new Intl.NumberFormat(undefined, {
style: "currency",
currency: "USD",
signDisplay: "never"
});
tipPerPersonElem.innerText = formatter.format(tip);
totalPerPersonElem.innerText = formatter.format(total);
submit.style.display = "none";
const resetBtn = document.querySelector("[type=\"reset\"]");
resetBtn.style.display = "block";
resetBtn.addEventListener("click", () => {
reset()
resetBtn.style.display = "none";
submit.style.display = "block";
})
})
document.addEventListener("DOMContentLoaded", () => {
reset()
})
peopleElem.addEventListener("keyup", () => checkInputForError(peopleElem, peopleError, true));
billElem.addEventListener("keyup", () => checkInputForError(billElem, billError, false));
function checkInputForError(input, error, showError) {
const value = input.value.trim() || 0;
if (!value || isNaN(parseFloat(value)) || parseFloat(value) == 0) {
if (showError) document.querySelector(".warning").style.display = "inline";
input.classList.add("error");
error = true;
} else {
if (showError) document.querySelector(".warning").style.display = "none";
input.classList.remove("error");
input.classList.add("correct");
error = false;
}
}
function reset(submit = false) {
const tipPerPersonElem = document.querySelector("[data-tip-person]");
const totalPerPersonElem = document.querySelector("[data-total-person]");
tipPerPersonElem.innerText = "";
totalPerPersonElem.innerText = "";
console.log(tipPerPersonElem.innerText, totalPerPersonElem.innerText, "reset", submit);
tipOptions.forEach(option => option.classList.remove("active"));
document.querySelectorAll("input").forEach(input => {
input.classList.remove("correct");
input.classList.remove("error");
input.value = "";
})
}
:root {
--primary-color: hsl(172, 67%, 45%);
--very-dark-cyan: hsl(183, 100%, 15%);
--dark-grayish-cyan: hsl(186, 14%, 43%);
--grayish-cyan: hsl(184, 14%, 56%);
--light-grayish-cyan: hsl(185, 41%, 84%);
--very-light-grayish-cyan: hsl(189, 41%, 97%);
--white: hsl(0, 0%, 100%);
--primary-font-size: 24px;
--primary-font-family: 'Space Mono', monospace;
}
/* GLOABAL TAGS */
body {
width: 100%;
margin: 0;
overflow: hidden;
font-family: var(--primary-font-family);
background-color: var(--light-grayish-cyan);
}
header {
text-align: center;
}
h1 {
color: var(--very-dark-cyan);
margin-top: 0;
text-transform: uppercase;
}
h1 span {
display: block;
margin: 0;
}
label {
display: block;
text-transform: capitalize;
}
button {
outline: none;
border: none;
text-align: center;
background-color: var(--very-dark-cyan);
font-size: var(--primary-font-size);
color: var(--white);
text-transform: capitalize;
margin: 8px;
padding-top: 8px;
padding-bottom: 8px;
border-radius: 4px;
cursor: pointer;
}
legend {
margin-bottom: 8px;
}
/* Chrome,
Safari,
Edge, */
/* Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
-moz-appearance: textfield;
}
input {
display: block;
border: none;
background-color: var(--very-light-grayish-cyan);
font-size: var(--primary-font-size);
height: 30px;
color: var(--very-dark-cyan);
background-repeat: no-repeat;
background-position: left center;
}
input:not(#custom) {
text-indent: 99.8%;
}
aside {
font-size: 11px;
text-align: center;
}
aside a {
color: hsl(228, 45%, 44%);
}
/* END OF GLOBAL TAGS GENERIC IDs */
#bill {
background-image: url('https://kaustubhmaladkar.github.io/Tip-Calculator/images/icon-dollar.svg');
}
#people {
background-image: url('https://kaustubhmaladkar.github.io/Tip-Calculator/images/icon-person.svg');
}
/* END OF GENERIC IDs GENERIC CLASSES*/
button,
#custom {
width: calc(50% - 20px);
font-weight: bold;
}
/* END OF GENERIC CLASSES */
/* INPUT */
.input {
background-color: var(--white);
color: var(--dark-grayish-cyan);
border-top-right-radius: 20px;
border-top-left-radius: 20px;
margin-top: 20px;
padding-bottom: 30px;
}
.input legend {
margin-top: 20px;
margin-left: 20px;
}
legend:nth-of-type(2) label {
width: 100%;
}
legend:nth-of-type(2) {
display: flex;
flex-wrap: wrap;
}
[for="people"] {
display: inline;
}
.warning {
display: none;
/* margin-left: 92px; */
color: red;
font-size: 12px;
background-color: transparent;
}
input#custom {
background-color: var(--white);
color: var(--dark-grayish-cyan);
margin-top: 12px;
margin-left: 2px;
padding-bottom: 8px;
opacity: 1;
}
input#custom::placeholder {
text-transform: capitalize;
color: var(--dark-grayish-cyan);
opacity: 1;
}
/* END OF INPUT */
/*OUTPUT*/
.output {
background-color: var(--very-dark-cyan);
display: flex;
margin-top: -8px;
justify-content: center;
align-items: center;
flex-direction: column;
border-radius: 10px;
}
.output div,
.output span {
width: 100%;
}
.output>div>div {
display: flex;
gap: 15px;
}
.output>div>div:first-of-type {
margin-top: 30px;
margin-bottom: 15px;
}
.output>div>div:last-of-type {
margin-top: 15px;
margin-bottom: 30px;
}
[type="submit"],
[type="reset"] {
font-family: var(--primary-font-family);
background-color: var(--primary-color);
width: 90%;
text-align: center;
color: var(--very-dark-cyan);
}
.tip-person,
.total-person {
font-size: 35px;
color: var(--primary-color);
}
.output>div>div>div>span:first-of-type {
text-transform: capitalize;
color: var(--white);
display: block;
}
.output>div>div>div>span:last-of-type {
color: var(--grayish-cyan);
}
/*END OF OUTPUT */
.active:not(input) {
background-color: var(--primary-color);
color: var(--very-dark-cyan);
transition: background 0.7s ease-in-out;
}
.correct {
border: lightgreen 2px solid;
}
.error {
border: red 2px solid;
}
.correct:focus,
.error:focus {
outline: none;
}
/* JAVASCRIPT CLASSES */
/* END OF JAVASCRIPT CLASSES */
/* FOR DESKTOP */
#media (min-width: 1200px) {
/* RESET */
html,
body,
main {
margin: 0;
}
/* END OF RESET */
/* GENERIC TAGS */
form {
width: 100%;
max-width: 900px;
border-radius: 15px;
overflow: hidden;
margin: auto;
padding-right: 15px;
display: flex;
width: fit-content;
background-color: var(--white);
}
input {
width: 90%;
}
aside {
display: none;
}
/* END OF GENERIC TAGS */
/* GENERIC CLASSES */
.output,
.input {
height: 400px;
}
.warning {
margin-left: 92px;
}
/* END OF GENERIC CLASSES */
/* INPUT */
.input button,
.input input#custom {
width: calc(100% / 3 - 20px);
}
.input {
width: 50%;
padding-bottom: 0;
}
.input legend {
margin-left: 25px;
}
/* END OF INPUT */
/* OUTPUT */
.output {
width: 50%;
margin: 22px;
padding: 0;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.output div {
margin-left: 20px;
}
.output>div>div:first-of-type {
margin-top: -20px;
margin-bottom: 40px;
}
[type="reset"] {
display: none;
}
/* END OF OUTPUT */
}
<h1>
<span>spli</span>
<span>tter</span>
</h1>
<form action="post">
<div class="input">
<legend>
<label for="bill">bill</label>
<input type="number" name="bill" id="bill" class="correct">
</legend>
<legend>
<label for="custom">select tip %</label>
<button type="button">5%</button>
<button type="button" class="">10%</button>
<button type="button">15%</button>
<button type="button">25%</button>
<button type="button">50%</button>
<input placeholder="custom" name="custom" id="custom" class="">
</legend>
<legend>
<label for="people">Number of People</label>
<p class="warning" style="display: inline;">Can't be zero</p>
<input type="number" name="people" id="people" class="">
</legend>
</div>
<div class="output">
<div>
<div>
<div>
<span>tip amount</span>
<span>/ person</span>
</div>
<span class="tip-person" data-tip-person=""></span>
</div>
<div>
<div>
<span>Total</span>
<span>/ person</span>
</div>
<span class="total-person" data-total-person=""></span>
</div>
</div>
<button type="submit" style="display: block;">Calculate</button>
<button type="reset" class="" style="display: none;">Reset</button>
</div>
</form>
Live site: https://kaustubhmaladkar.github.io/Tip-Calculator/
Code on Github: https://github.com/KaustubhMaladkar/Tip-Calculator/
The problem comes from this line:
input:not(#custom) {
text-indent: 99.8%;
}
If you only want a alignment to the right, change it to:
input:not(#custom) {
text-align: right;
}
Working example:
const peopleElem = document.querySelector("#people");
const billElem = document.querySelector("#bill");
const submit = document.querySelector("[type=\"submit\"]");
const form = document.querySelector("form");
const tipPerPersonElem = document.querySelector("[data-tip-person]");
const totalPerPersonElem = document.querySelector("[data-total-person]");
let billError = peopleError = false;
class TipCalc {
constructor() {
this.tipPerPerson = 0;
this.totalPerPerson = 0;
this.tip = 0
this.tipPercent = 0;
this.bill = parseFloat(billElem.value);
this.people = parseFloat(peopleElem.value);
}
getTip() {
const element = document.querySelector(".active");
if (!element) return 0;
if (element.tagName === "BUTTON") return this.tipPercent = element.innerText.replace("%", "");
return this.tipPercent = element.value.replace("%", "");
}
getTipPerPerson() {
this.getTip();
this.tip = ((this.tipPercent / 100) * this.bill);
this.tipPerPerson = this.tip / this.people;
return this.tipPerPerson;
}
getTotalPerPerson() {
this.getTipPerPerson();
this.totalPerPerson = (this.bill + this.tip) / this.people
return this.totalPerPerson;
}
}
const tipOptions = [...document.querySelectorAll("button"), document.querySelector("#custom")];
tipOptions.forEach(option => {
if (option.tagName === "INPUT" && option.value.length) option.addEventListener("keyup", () => {
tipOptions.forEach(option => option.classList.remove("active"));
option.classList.toggle("active");
})
if (!(option.type == "submit")) option.addEventListener("click", () => {
tipOptions.forEach(option => option.classList.remove("active"));
option.classList.toggle("active");
})
})
form.addEventListener("submit", event => {
event.preventDefault();
checkInputForError(peopleElem, peopleError, true);
checkInputForError(billElem, billError, false);
if (billError || peopleError) return;
const tipCalculator = new TipCalc();
const tip = isNaN(tipCalculator.getTipPerPerson()) ? 0 : tipCalculator.getTipPerPerson();
const total = isNaN(tipCalculator.getTotalPerPerson()) ? 0 : tipCalculator.getTotalPerPerson();
const formatter = new Intl.NumberFormat(undefined, {
style: "currency",
currency: "USD",
signDisplay: "never"
});
tipPerPersonElem.innerText = formatter.format(tip);
totalPerPersonElem.innerText = formatter.format(total);
submit.style.display = "none";
const resetBtn = document.querySelector("[type=\"reset\"]");
resetBtn.style.display = "block";
resetBtn.addEventListener("click", () => {
reset()
resetBtn.style.display = "none";
submit.style.display = "block";
})
})
document.addEventListener("DOMContentLoaded", () => {
reset()
})
peopleElem.addEventListener("keyup", () => checkInputForError(peopleElem, peopleError, true));
billElem.addEventListener("keyup", () => checkInputForError(billElem, billError, false));
function checkInputForError(input, error, showError) {
const value = input.value.trim() || 0;
if (!value || isNaN(parseFloat(value)) || parseFloat(value) == 0) {
if (showError) document.querySelector(".warning").style.display = "inline";
input.classList.add("error");
error = true;
} else {
if (showError) document.querySelector(".warning").style.display = "none";
input.classList.remove("error");
input.classList.add("correct");
error = false;
}
}
function reset(submit = false) {
const tipPerPersonElem = document.querySelector("[data-tip-person]");
const totalPerPersonElem = document.querySelector("[data-total-person]");
tipPerPersonElem.innerText = "";
totalPerPersonElem.innerText = "";
console.log(tipPerPersonElem.innerText, totalPerPersonElem.innerText, "reset", submit);
tipOptions.forEach(option => option.classList.remove("active"));
document.querySelectorAll("input").forEach(input => {
input.classList.remove("correct");
input.classList.remove("error");
input.value = "";
})
}
:root {
--primary-color: hsl(172, 67%, 45%);
--very-dark-cyan: hsl(183, 100%, 15%);
--dark-grayish-cyan: hsl(186, 14%, 43%);
--grayish-cyan: hsl(184, 14%, 56%);
--light-grayish-cyan: hsl(185, 41%, 84%);
--very-light-grayish-cyan: hsl(189, 41%, 97%);
--white: hsl(0, 0%, 100%);
--primary-font-size: 24px;
--primary-font-family: 'Space Mono', monospace;
}
/* GLOABAL TAGS */
body {
width: 100%;
margin: 0;
overflow: hidden;
font-family: var(--primary-font-family);
background-color: var(--light-grayish-cyan);
}
header {
text-align: center;
}
h1 {
color: var(--very-dark-cyan);
margin-top: 0;
text-transform: uppercase;
}
h1 span {
display: block;
margin: 0;
}
label {
display: block;
text-transform: capitalize;
}
button {
outline: none;
border: none;
text-align: center;
background-color: var(--very-dark-cyan);
font-size: var(--primary-font-size);
color: var(--white);
text-transform: capitalize;
margin: 8px;
padding-top: 8px;
padding-bottom: 8px;
border-radius: 4px;
cursor: pointer;
}
legend {
margin-bottom: 8px;
}
/* Chrome,
Safari,
Edge, */
/* Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
-moz-appearance: textfield;
}
input {
display: block;
border: none;
background-color: var(--very-light-grayish-cyan);
font-size: var(--primary-font-size);
height: 30px;
color: var(--very-dark-cyan);
background-repeat: no-repeat;
background-position: left center;
}
input:not(#custom) {
text-align: right;
}
aside {
font-size: 11px;
text-align: center;
}
aside a {
color: hsl(228, 45%, 44%);
}
/* END OF GLOBAL TAGS GENERIC IDs */
#bill {
background-image: url('https://kaustubhmaladkar.github.io/Tip-Calculator/images/icon-dollar.svg');
}
#people {
background-image: url('https://kaustubhmaladkar.github.io/Tip-Calculator/images/icon-person.svg');
}
/* END OF GENERIC IDs GENERIC CLASSES*/
button,
#custom {
width: calc(50% - 20px);
font-weight: bold;
}
/* END OF GENERIC CLASSES */
/* INPUT */
.input {
background-color: var(--white);
color: var(--dark-grayish-cyan);
border-top-right-radius: 20px;
border-top-left-radius: 20px;
margin-top: 20px;
padding-bottom: 30px;
}
.input legend {
margin-top: 20px;
margin-left: 20px;
}
legend:nth-of-type(2) label {
width: 100%;
}
legend:nth-of-type(2) {
display: flex;
flex-wrap: wrap;
}
[for="people"] {
display: inline;
}
.warning {
display: none;
/* margin-left: 92px; */
color: red;
font-size: 12px;
background-color: transparent;
}
input#custom {
background-color: var(--white);
color: var(--dark-grayish-cyan);
margin-top: 12px;
margin-left: 2px;
padding-bottom: 8px;
opacity: 1;
}
input#custom::placeholder {
text-transform: capitalize;
color: var(--dark-grayish-cyan);
opacity: 1;
}
/* END OF INPUT */
/*OUTPUT*/
.output {
background-color: var(--very-dark-cyan);
display: flex;
margin-top: -8px;
justify-content: center;
align-items: center;
flex-direction: column;
border-radius: 10px;
}
.output div,
.output span {
width: 100%;
}
.output>div>div {
display: flex;
gap: 15px;
}
.output>div>div:first-of-type {
margin-top: 30px;
margin-bottom: 15px;
}
.output>div>div:last-of-type {
margin-top: 15px;
margin-bottom: 30px;
}
[type="submit"],
[type="reset"] {
font-family: var(--primary-font-family);
background-color: var(--primary-color);
width: 90%;
text-align: center;
color: var(--very-dark-cyan);
}
.tip-person,
.total-person {
font-size: 35px;
color: var(--primary-color);
}
.output>div>div>div>span:first-of-type {
text-transform: capitalize;
color: var(--white);
display: block;
}
.output>div>div>div>span:last-of-type {
color: var(--grayish-cyan);
}
/*END OF OUTPUT */
.active:not(input) {
background-color: var(--primary-color);
color: var(--very-dark-cyan);
transition: background 0.7s ease-in-out;
}
.correct {
border: lightgreen 2px solid;
}
.error {
border: red 2px solid;
}
.correct:focus,
.error:focus {
outline: none;
}
/* JAVASCRIPT CLASSES */
/* END OF JAVASCRIPT CLASSES */
/* FOR DESKTOP */
#media (min-width: 1200px) {
/* RESET */
html,
body,
main {
margin: 0;
}
/* END OF RESET */
/* GENERIC TAGS */
form {
width: 100%;
max-width: 900px;
border-radius: 15px;
overflow: hidden;
margin: auto;
padding-right: 15px;
display: flex;
width: fit-content;
background-color: var(--white);
}
input {
width: 90%;
}
aside {
display: none;
}
/* END OF GENERIC TAGS */
/* GENERIC CLASSES */
.output,
.input {
height: 400px;
}
.warning {
margin-left: 92px;
}
/* END OF GENERIC CLASSES */
/* INPUT */
.input button,
.input input#custom {
width: calc(100% / 3 - 20px);
}
.input {
width: 50%;
padding-bottom: 0;
}
.input legend {
margin-left: 25px;
}
/* END OF INPUT */
/* OUTPUT */
.output {
width: 50%;
margin: 22px;
padding: 0;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.output div {
margin-left: 20px;
}
.output>div>div:first-of-type {
margin-top: -20px;
margin-bottom: 40px;
}
[type="reset"] {
display: none;
}
/* END OF OUTPUT */
}
<h1>
<span>spli</span>
<span>tter</span>
</h1>
<form action="post">
<div class="input">
<legend>
<label for="bill">bill</label>
<input type="number" name="bill" id="bill" class="correct">
</legend>
<legend>
<label for="custom">select tip %</label>
<button type="button">5%</button>
<button type="button" class="">10%</button>
<button type="button">15%</button>
<button type="button">25%</button>
<button type="button">50%</button>
<input placeholder="custom" name="custom" id="custom" class="">
</legend>
<legend>
<label for="people">Number of People</label>
<p class="warning" style="display: inline;">Can't be zero</p>
<input type="number" name="people" id="people" class="">
</legend>
</div>
<div class="output">
<div>
<div>
<div>
<span>tip amount</span>
<span>/ person</span>
</div>
<span class="tip-person" data-tip-person=""></span>
</div>
<div>
<div>
<span>Total</span>
<span>/ person</span>
</div>
<span class="total-person" data-total-person=""></span>
</div>
</div>
<button type="submit" style="display: block;">Calculate</button>
<button type="reset" class="" style="display: none;">Reset</button>
</div>
</form>

How to make modal window accurately reflect contents of each note in a note-taking app?

I am fairly new to javascript, and am working on a note-taking app to practice some things I have learned so far. It all works fine, however, when I click on the Read More button to view overflow text of the note, it displays the text from the most recent note, as opposed to the note I click Read More on. I want the entire text of a particular note to be displayed when its corresponding Read More button is pressed. Am I overthinking this? I think some kind of implementation of for...of, or for loops may help me achieve this outcome. This is a link to my codepen: https://codepen.io/oliverc96/pen/xxdZYrr
const addNote = document.querySelector('.add-note');
const newNote = document.querySelector('#new-note');
const noteFeed = document.querySelector('#note-feed');
let modalBg = document.createElement('div');
let modalWindow = document.createElement('div');
let exitSymbol = document.createElement('i');
let modalText = document.createElement('p');
function expandNote() {
modalWindow.classList.add('enterAnimation');
modalBg.style.visibility = 'visible';
exitSymbol.addEventListener('click', () => {
modalBg.style.visibility = 'hidden';
modalWindow.classList.remove('enterAnimation');
})
}
function createNote() {
const noteContainer = document.createElement('div');
noteContainer.classList.add('containerStyle');
let noteHeader = document.createElement('h1');
const noteNum = noteFeed.childElementCount;
noteHeader.innerText = `Note #${noteNum + 1}`;
noteHeader.classList.add('headerStyle');
noteContainer.append(noteHeader);
let noteText = document.createElement('p');
noteText.innerText = `${newNote.value}`;
noteText.classList.add('paraStyle');
noteContainer.append(noteText);
let readMore = document.createElement('button');
readMore.innerText = 'Read More';
readMore.classList.add('btnStyle');
noteContainer.append(readMore);
noteFeed.append(noteContainer);
readMore.addEventListener('click', expandNote);
modalBg.classList.add('modal-bg');
modalWindow.classList.add('modal-window');
exitSymbol.className = 'far fa-times-circle';
exitSymbol.classList.add('exitSymbol');
modalWindow.append(exitSymbol);
modalText.classList.add('fullTextStyle');
modalText.innerText = `${noteText.innerText}`;
modalWindow.append(modalText);
modalBg.append(modalWindow);
noteContainer.append(modalBg);
newNote.value = '';
}
addNote.addEventListener('click', createNote);
newNote.addEventListener('keyup', function(e) {
if (e.keyCode === 13) {
e.preventDefault();
createNote();
}
})
Actually your modalText will always store the latest value according to your code. You can follow the following steps to solve this.
Attach an data-attribute to that noteText.
When click on read more pass the id of that specific note.
Now just show the innerText of that selected item. You can use querySelector to get the element using data-attribute.
You can check my implementation.
console.clear();
const addNote = document.querySelector('.add-note');
const newNote = document.querySelector('#new-note');
const noteFeed = document.querySelector('#note-feed');
let modalBg = document.createElement('div');
let modalWindow = document.createElement('div');
let exitSymbol = document.createElement('i');
let modalText = document.createElement('p');
function expandNote(noteContainer, noteNum) {
return function () {
modalWindow.classList.add('enterAnimation');
modalBg.style.visibility = 'visible';
exitSymbol.addEventListener('click', () => {
modalBg.style.visibility = 'hidden';
modalWindow.classList.remove('enterAnimation');
})
const data = document.querySelector(`[data-id='${noteNum}']`).innerText;
showMoreModal(noteContainer, data);
}
}
function showMoreModal(noteContainer, data) {
modalBg.classList.add('modal-bg');
modalWindow.classList.add('modal-window');
exitSymbol.className = 'far fa-times-circle';
exitSymbol.classList.add('exitSymbol');
modalWindow.append(exitSymbol);
modalText.classList.add('fullTextStyle');
modalText.innerText = `${data}`;
modalWindow.append(modalText);
modalBg.append(modalWindow);
noteContainer.append(modalBg);
}
function createNote() {
const noteContainer = document.createElement('div');
noteContainer.classList.add('containerStyle');
let noteHeader = document.createElement('h1');
const noteNum = noteFeed.childElementCount;
noteHeader.innerText = `Note #${noteNum + 1}`;
noteHeader.classList.add('headerStyle');
noteContainer.append(noteHeader);
let noteText = document.createElement('p');
noteText.innerText = `${newNote.value}`;
noteText.classList.add('paraStyle');
noteText.setAttribute('data-id', noteNum);
noteContainer.append(noteText);
let readMore = document.createElement('button');
readMore.innerText = 'Read More';
readMore.classList.add('btnStyle');
noteContainer.append(readMore);
noteFeed.append(noteContainer);
readMore.addEventListener('click', expandNote(noteContainer, noteNum));
newNote.value = '';
}
addNote.addEventListener('click', createNote);
newNote.addEventListener('keyup', function(e) {
if (e.keyCode === 13) {
e.preventDefault();
createNote();
}
})
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'Montserrat', sans-serif;
}
#wrapper {
width: 1600px;
height: 100vh;
margin: auto;
text-align: center;
}
h1 {
font-size: 100px;
margin-top: 20px;
font-weight: 500;
}
h2 {
font-size: 50px;
font-weight: 400;
margin-top: 10px;
}
#add-new-note {
color: rgb(0, 153, 153);
}
textarea {
width: 1500px;
margin-top: 30px;
height: 60px;
border-radius: 6px;
padding: 20px;
font-size: 18px;
}
textarea:focus {
outline-color: black;
}
.add-note {
font-size: 20px;
width: 180px;
height: 50px;
border-radius: 6px;
margin-top: 30px;
background-color: rgb(0, 153, 153);
color: white;
border-style: solid;
border-color: rgb(0, 102, 102);
}
.add-note:hover {
background-color: rgb(0, 128, 128);
cursor: pointer;
}
#note-feed {
background-color: rgb(0, 153, 153);
height: 500px;
margin-top: 25px;
width: 1500px;
border-radius: 6px;
display: flex;
overflow: scroll;
flex-wrap: wrap;
padding: 20px 10px;
margin-left: 50px;
}
.containerStyle {
display: flex;
flex-direction: column;
justify-content: space-around;
background-color: rgb(169, 169, 214);
height: 48%;
width: 31%;
margin-right: 11px;
margin-left: 20px;
border-radius: 6px;
margin-bottom: 20px;
overflow: hidden;
padding: 0 28px;
padding-bottom: 15px;
text-align: left;
}
.headerStyle {
font-size: 30px;
}
.paraStyle {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
font-size: 18px;
text-overflow: ellipsis;
overflow: hidden;
}
.btnStyle {
font-size: 20px;
width: 150px;
height: 40px;
border-radius: 6px;
background-color: rgb(255, 128, 128);
color: white;
border-style: solid;
border-color: rgb(255, 77, 77);
align-self: left;
}
.btnStyle:hover {
background-color: rgb(255, 102, 102);
cursor: pointer;
}
.modal-bg {
z-index: 1;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(0,0,0,0.5);
color: white;
display: flex;
justify-content: center;
align-items: center;
visibility: hidden;
overflow: scroll;
}
.modal-window {
border-radius: 6px;
background: white;
width: 70%;
min-height: 30%;
max-height: 70%;
overflow: scroll;
display: flex;
justify-content: flex-start;
align-items: flex-start;
}
.enterAnimation {
animation-name: fadeInDown;
animation-duration: 1s;
}
#keyframes fadeInDown {
0% {
opacity: 0;
transform: translateY(-200px);
}
100% {
opacity: 1;
}
}
.exitSymbol {
color: rgb(0, 128, 128);
font-size: 30px;
margin: 20px 20px;
}
.exitSymbol:hover {
cursor: pointer;
opacity: 0.8;
}
.fullTextStyle {
color: black;
width: 90%;
height: 80%;
text-align: left;
margin-top: 60px;
margin-bottom: 30px;
font-size: 18px;
}
<html>
<head>
<title> Note Taker </title>
<link type="text/css" href="notes.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#100;200;300;400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div id="wrapper">
<h1> Note Taker </h1>
<h2 id="add-new-note"> Add A New Note: </h2>
<textarea id="new-note" name="note-box" placeholder="Write your note here"></textarea>
<button class="add-note"> Add Note </button>
<div id="note-feed">
</div>
</div>
<script src="notes.js"></script>
<script src="https://kit.fontawesome.com/6fc6f370ca.js" crossorigin="anonymous"></script>
</body>
</html>

Javascript removeChild doesn't work as expected

I have a code that gets characters names and gender after clicking on film name. This information appears in modal window and my goal is to delete HTML element with characters every time I close modal, so if I select another film the new set of characters will appear, and the old one is already deleted.
The problem is that removeChild method doesn't work as expected. I've tried different variations including parentNode but nothing helped.
Here is the code:
window.addEventListener('DOMContentLoaded', function() {
let btn = document.querySelector('.sw-btn');
let content = document.querySelector('.content');
let modal = document.querySelector('.modal');
let modalBody = document.querySelector('.modal-body');
let closeBtn = document.querySelector('.close-btn');
let filmsList = document.createElement('ul');
let charsList = document.createElement('ol');
function getFilms() {
axios.get('https://swapi.co/api/films/').then(res => {
content.appendChild(filmsList);
for (var i = 0; i < res.data.results.length; i++) {
res.data.results.sort(function(a, b) {
let dateA = new Date(a.release_date),
dateB = new Date(b.release_date);
return dateA - dateB;
});
(function updateFilms() {
let addFilm = document.createElement('li');
filmsList.appendChild(addFilm);
let addFilmAnchor = document.createElement('a');
let addFilmId = document.createElement('p');
let addFilmCrawl = document.createElement('p');
let addFilmDirector = document.createElement('p');
let addFilmDate = document.createElement('p');
addFilmAnchor.textContent = res.data.results[i].title;
addFilmId.textContent = `Episode ID: ${res.data.results[i].episode_id}`;
addFilmCrawl.textContent = `Episode description: ${res.data.results[i].opening_crawl}`;
addFilmDirector.textContent = `Episode director: ${res.data.results[i].director}`;
addFilmDate.textContent = `Episode release date: ${res.data.results[i].release_date}`;
addFilm.append(addFilmAnchor, addFilmId, addFilmCrawl, addFilmDirector, addFilmDate);
})();
}
let links = document.getElementsByTagName('a');
for (let j = 0; j < links.length; j++) {
links[j].onclick = function() {
modal.style.display = 'block';
modalBody.appendChild(charsList);
let chars = res.data.results[j].characters;
for (let k = 0; k < chars.length; k++) {
const element = chars[k];
axios.get(element).then(res => {
let addChar = document.createElement('li');
charsList.appendChild(addChar);
let addCharName = document.createElement('p');
let addCharGender = document.createElement('p');
addCharName.textContent = `Character name: ${res.data.name}`;
addCharGender.textContent = `Character gender: ${res.data.gender}`;
addChar.append(addCharName, addCharGender);
})
}
closeBtn.addEventListener('click', () => {
modal.style.display = 'none';
console.log(modalBody.childNodes[0]);
// Problem is here
modalBody.removeChild(modalBody.childNodes[0]);
});
window.addEventListener('click', (e) => {
if (e.target == modal) {
modal.style.display = 'none';
console.log(modalBody.childNodes[0]);
modalBody.removeChild(modalBody.childNodes[0]);
}
})
}
}
}).catch(err => {
console.log("An error occured");
})
};
btn.addEventListener('click', getFilms);
closeBtn.addEventListener('click', () => {
modal.style.display = 'none';
});
window.addEventListener('click', (e) => {
if (e.target == modal) {
modal.style.display = 'none';
}
})
});
body {
max-height: 100vh;
padding: 0;
margin: 0;
font-family: Muli;
}
body::before {
background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Star_Wars_Logo.svg/1200px-Star_Wars_Logo.svg.png') no-repeat center / cover;
background-size: cover;
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -2;
opacity: 0.1;
}
h1 {
text-align: center;
color: #660d41;
font-size: 3em;
margin-top: 10px;
letter-spacing: 1px;
}
main {
display: flex;
align-items: center;
flex-direction: column;
}
.content {
max-width: 55%;
overflow-y: scroll;
max-height: 75vh;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #f4f4f4;
margin: 20% auto;
width: 40%;
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.2);
animation: modalOpen 1s;
}
.modal-header {
background: coral;
padding: 15px;
color: white;
letter-spacing: 1px;
position: relative;
}
.modal-header h2 {
margin: 0;
}
.modal-body {
padding: 10px 20px;
}
.close-btn {
color: white;
float: right;
font-size: 30px;
position: absolute;
top: 0px;
right: 10px;
}
.close-btn:hover,
.close-btn:focus {
color: black;
text-decoration: none;
cursor: pointer;
transition: all 0.4s ease-in;
}
ul {
list-style-type: none;
padding: 10px 20px;
}
li {
border-bottom: 1px solid orangered;
margin-bottom: 30px;
}
li:last-child {
border-bottom: none;
margin-bottom: 0;
}
a {
font-size: 1.7em;
color: #b907d9;
cursor: pointer;
margin-bottom: 10px;
}
p {
font-size: 1.2rem;
color: #0f063f;
margin: 10px 0;
}
button {
padding: .5em 1.5em;
border: none;
color: white;
transition: all 0.2s ease-in;
background: #da2417;
border-radius: 20px;
font-size: 1em;
cursor: pointer;
margin-top: 15px;
}
button:focus {
outline: none;
}
button:hover {
background: #e7736b;
}
button:active {
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.7) inset;
}
#keyframes modalOpen {
from {
opacity: 0
}
to {
opacity: 1
}
}
<link href="https://fonts.googleapis.com/css?family=Muli&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<h1>Star wars films</h1>
<main>
<div class="content"></div>
<div class="modal">
<div class="modal-content">
<div class="modal-header">
<span class="close-btn">×</span>
<h2>Episode Characters</h2>
</div>
<div class="modal-body"></div>
</div>
</div>
<button class="sw-btn">Find Films</button>
</main>
Any help would be appreciated.
The problem is that you are using the same ol element when appending the characters to the list, since you instantiate it at the beginning and re-use it later: let charsList = document.createElement('ol');
When you close the modal, you will remove that ol element from the modal, but you will not remove its content. When opening the modal again, the ol will be added again - with your old content.
If you move the declaration of charsList inside your onclick handler, it will work.
Also, you should register the close handlers of your modal only once. Otherwise, it will be called as often as you open your modal.
Demo:
window.addEventListener('DOMContentLoaded', function () {
let btn = document.querySelector('.sw-btn');
let content = document.querySelector('.content');
let modal = document.querySelector('.modal');
let modalBody = document.querySelector('.modal-body');
let closeBtn = document.querySelector('.close-btn');
let filmsList = document.createElement('ul');
closeBtn.addEventListener('click', () => {
modal.style.display = 'none';
console.log(modalBody.childNodes[0]);
modalBody.removeChild(modalBody.childNodes[0]);
});
window.addEventListener('click', (e) => {
if (e.target == modal) {
modal.style.display = 'none';
console.log(modalBody.childNodes[0]);
modalBody.removeChild(modalBody.childNodes[0]);
}
})
function getFilms() {
axios.get('https://swapi.co/api/films/').then(res => {
content.appendChild(filmsList);
for (var i = 0; i < res.data.results.length; i++) {
res.data.results.sort(function (a, b) {
let dateA = new Date(a.release_date),
dateB = new Date(b.release_date);
return dateA - dateB;
});
(function updateFilms() {
let addFilm = document.createElement('li');
filmsList.appendChild(addFilm);
let addFilmAnchor = document.createElement('a');
let addFilmId = document.createElement('p');
let addFilmCrawl = document.createElement('p');
let addFilmDirector = document.createElement('p');
let addFilmDate = document.createElement('p');
addFilmAnchor.textContent = res.data.results[i].title;
addFilmId.textContent = `Episode ID: ${res.data.results[i].episode_id}`;
addFilmCrawl.textContent = `Episode description: ${res.data.results[i].opening_crawl}`;
addFilmDirector.textContent = `Episode director: ${res.data.results[i].director}`;
addFilmDate.textContent = `Episode release date: ${res.data.results[i].release_date}`;
addFilm.append(addFilmAnchor, addFilmId, addFilmCrawl, addFilmDirector, addFilmDate);
})();
}
let links = document.getElementsByTagName('a');
for (let j = 0; j < links.length; j++) {
links[j].onclick = function () {
modal.style.display = 'block';
let charsList = document.createElement('ol');
modalBody.appendChild(charsList);
let chars = res.data.results[j].characters;
for (let k = 0; k < chars.length; k++) {
const element = chars[k];
axios.get(element).then(res => {
let addChar = document.createElement('li');
charsList.appendChild(addChar);
let addCharName = document.createElement('p');
let addCharGender = document.createElement('p');
addCharName.textContent = `Character name: ${res.data.name}`;
addCharGender.textContent = `Character gender: ${res.data.gender}`;
addChar.append(addCharName, addCharGender);
})
}
}
}
}).catch(err => {
console.log("An error occured");
})
};
btn.addEventListener('click', getFilms);
closeBtn.addEventListener('click', () => {
modal.style.display = 'none';
});
window.addEventListener('click', (e) => {
if (e.target == modal) {
modal.style.display = 'none';
}
})
});
body {
max-height: 100vh;
padding: 0;
margin: 0;
font-family: Muli;
}
body::before {
background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Star_Wars_Logo.svg/1200px-Star_Wars_Logo.svg.png') no-repeat center / cover;
background-size: cover;
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -2;
opacity: 0.1;
}
h1 {
text-align: center;
color: #660d41;
font-size: 3em;
margin-top: 10px;
letter-spacing: 1px;
}
main {
display: flex;
align-items: center;
flex-direction: column;
}
.content {
max-width: 55%;
overflow-y: scroll;
max-height: 75vh;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #f4f4f4;
margin: 20% auto;
width: 40%;
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.2);
animation: modalOpen 1s;
}
.modal-header {
background: coral;
padding: 15px;
color: white;
letter-spacing: 1px;
position: relative;
}
.modal-header h2 {
margin: 0;
}
.modal-body {
padding: 10px 20px;
}
.close-btn {
color: white;
float: right;
font-size: 30px;
position: absolute;
top: 0px;
right: 10px;
}
.close-btn:hover,
.close-btn:focus {
color: black;
text-decoration: none;
cursor: pointer;
transition: all 0.4s ease-in;
}
ul {
list-style-type: none;
padding: 10px 20px;
}
li {
border-bottom: 1px solid orangered;
margin-bottom: 30px;
}
li:last-child {
border-bottom: none;
margin-bottom: 0;
}
a {
font-size: 1.7em;
color: #b907d9;
cursor: pointer;
margin-bottom: 10px;
}
p {
font-size: 1.2rem;
color: #0f063f;
margin: 10px 0;
}
button {
padding: .5em 1.5em;
border: none;
color: white;
transition: all 0.2s ease-in;
background: #da2417;
border-radius: 20px;
font-size: 1em;
cursor: pointer;
margin-top: 15px;
}
button:focus {
outline: none;
}
button:hover {
background: #e7736b;
}
button:active {
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.7) inset;
}
#keyframes modalOpen {
from {
opacity: 0
}
to {
opacity: 1
}
}
<link href="https://fonts.googleapis.com/css?family=Muli&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<h1>Star wars films</h1>
<main>
<div class="content"></div>
<div class="modal">
<div class="modal-content">
<div class="modal-header">
<span class="close-btn">×</span>
<h2>Episode Characters</h2>
</div>
<div class="modal-body"></div>
</div>
</div>
<button class="sw-btn">Find Films</button>
</main>
Do this charsList.innerText = ''; when click close button.
When you call removeChild you take off the <ol> from modalbody in UI. You can see the modalBody is empty after clicking close button.
But you already store the <ol> element in js variable by let charsList = document.createElement('ol'); so the ol element itself doesn't change actually.
The <li> element still inside the <ol>. Then you add more new <li> and put it back to modalBody.
My solution is remove all element in <ol> when clicking close button.

Categories