Responsive layout cards are not working on mobile - javascript

Description
Whilst creating a webpage, everything was working on Chrome DevTools as expected, until I tried the mobile version. Why is that happening? Never faced such issue.
Steps to Reproduce
This is how it is on the desktop version.
After reducing the width:
Which is expected. It's when I activate the mobile version that it's suddenly not working:
Even with the .cards class using flex + flex-wrap + flex-direction or using grid + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); it does not work for mobile.
Environment
The code I am using is as follows:
const data = [
{
CODIGO: "a1",
NOME: "TESTING",
CLASSE: "ALUNO",
},
{
CODIGO: "a2",
NOME: "TESTING",
CLASSE: "ALUNO",
},
{
CODIGO: "a3",
NOME: "TESTING",
CLASSE: "ALUNO",
},
{
CODIGO: "a4",
NOME: "TESTING",
CLASSE: "ALUNO",
},
{
CODIGO: "a5",
NOME: "TESTING",
CLASSE: "ALUNO",
},
{
CODIGO: "a6",
NOME: "TESTING",
CLASSE: "ALUNO",
},
];
const groupByKey = (list, key, { omitKey = false }) =>
list.reduce((hash, { [key]: value, ...rest }) => {
const item = omitKey ? rest : { [key]: value, ...rest };
const group = hash[value] || [];
return { ...hash, [value]: [...group, item] };
}, {});
const result = groupByKey(data, "CLASSE", { omitKey: true });
const ALUNO = result.ALUNO;
const PROFESSOR = result.PROFESSOR;
const MIDIA = result.MIDIA;
const PASTOR = result.PASTOR;
document.addEventListener("DOMContentLoaded", function () {
const listElements = {
alunoList: document.getElementById("alunos"),
professorList: document.getElementById("professores"),
midiaList: document.getElementById("midia"),
pastorList: document.getElementById("pastores"),
};
const createCard = (person, aluno = false) => {
const card = document.createElement("div");
card.classList.add("card");
const cardImage = document.createElement("div");
cardImage.classList.add("card__image");
const image = new Image();
image.src = `assets/img/${person.CODIGO}i.webp`;
cardImage.appendChild(image);
const cardContent = document.createElement("div");
cardContent.classList.add("card__content");
const cardTitle = document.createElement("div");
cardTitle.classList.add("card__title");
cardTitle.innerHTML = person.NOME;
const cardText = document.createElement("p");
cardText.classList.add("card__text");
const cardLink = document.createElement("a");
cardLink.setAttribute("target", "_blank");
cardLink.setAttribute("href", `${person.CODIGO}.html`);
const cardButton = document.createElement("button");
cardButton.classList.add("btn");
cardButton.classList.add("btn--block");
cardButton.innerHTML = "Mais detalhes ➜";
cardLink.appendChild(cardButton);
cardContent.appendChild(cardTitle);
cardContent.appendChild(cardText);
cardContent.appendChild(cardLink);
card.appendChild(cardImage);
card.appendChild(cardContent);
const li = document.createElement("li");
li.classList.add("cards__item");
li.appendChild(card);
return li;
};
const addCardsToList = (personList, person, aluno = false) => {
listElements[personList].appendChild(createCard(person, aluno));
};
ALUNO.forEach((person) =>
addCardsToList("alunoList", person, (aluno = true))
);
});
:root {
--gray-darker: #444444;
--gray-dark: #696969;
--gray: #999999;
--gray-light: #cccccc;
--gray-lighter: #ececec;
--gray-lightest: lighten(--gray-lighter, 4%);
text-decoration: none;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
list-style: none;
scroll-behavior: smooth;
}
a,
a:hover,
a:visited,
a:active,
a:link {
text-decoration: none;
}
section {
min-height: 100vh;
width: 100%;
}
html {
background-color: #f0f0f0;
}
body {
color: var(--gray);
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-style: normal;
font-weight: 400;
padding: 1rem;
}
h1 {
font-size: 5rem;
padding: 3rem;
}
.cards {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-evenly;
gap: 1rem;
}
.cards .card {
display: flex;
flex-direction: column;
overflow: hidden;
background-color: #fff;
border-radius: 0.25rem;
max-width: 300px;
box-shadow: 0 20px 40px -14px rgba(0, 0, 0, 0.25);
}
.cards .card:hover .card__image {
filter: contrast(100%);
}
.cards .card__content {
padding: 1rem;
}
.cards .card__content .btn {
background-color: #fff;
border: 1px solid var(--gray-light);
border-radius: 1rem;
color: var(--gray-dark);
padding: 0.5rem;
text-transform: lowercase;
cursor: pointer;
transition: all 0.5s cubic-bezier(0.43, 0.41, 0.22, 0.91);
}
.cards .card__content .btn:hover {
background-color: #c00;
color: #fff;
}
.cards .card__content .btn--block {
width: 100%;
height: 48px;
font-size: 1.2rem;
}
.cards .card__image {
filter: contrast(70%);
overflow: hidden;
position: relative;
transition: filter 0.5s cubic-bezier(0.43, 0.41, 0.22, 0.91);
height: 400px;
}
.cards .card__image img {
width: 100%;
max-height: 400px;
-o-object-fit: contain;
object-fit: contain;
}
.cards .card__title {
color: var(--gray-dark);
font-size: 1.7rem;
font-weight: 300;
letter-spacing: 2px;
text-transform: uppercase;
}
.cards .card__text {
font-size: 1rem;
line-height: 1.5;
margin-bottom: 1.25rem;
}
#media screen and (max-width: 600px) {
h1 {
font-size: 3rem;
padding: 1.5rem;
}
.cards .card {
margin-bottom: 1rem;
}
.cards .card__image {
max-height: 200px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
<link rel="stylesheet" href="assets/style.css">
<script defer src="assets/script.js"></script>
</head>
<body>
<section>
<h1>Alunos</h1>
<ul class="cards" id="alunos"></ul>
</section>
</body>
</html>
As this never happened to me, I don't even know where to begin. I know that it's happening due to the css, but any tips would be awesome.
Thanks!

Try Adding
<meta name="viewport" content="width=device-width, initial-scale=1">
into your head tag.

Related

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.

Accordion Javascript plus sign doesn't work

I am doing an accordion in JavaScipt, in my HTML I have two separate divs for questions title and separate div for "+" sign. My goal is when I click on div with class accordionTitle I want "+" sign change to "-" and at the same time show the answer. I am pretty new to development, what the best approach here? Can you help me?
HTML:
<section class="qnaSection">
<h1 class="qnaTitle">FAQ</h1>
<div id="qnaContainer" class="qnaContainer"></div>
</section>
CSS:
.qnaSection {
background-color: rgb(35, 57, 94);
color: var(--brown);
}
.qnaTitle {
text-align: center;
margin: 10px 0;
font-size: 28px;
}
.qnaContainer {
width: 90%;
max-width: 1000px;
margin: 20px auto;
}
.accordionItem {
background-color: rgb(222, 222, 222);
color: black;
margin: 10px 0;
border-radius: 10px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.25);
}
.accordionItemTitle {
padding: 1rem;
min-height: 3.5rem;
width: 100%;
line-height: 1.25rem;
font-weight: bold;
display: flex;
justify-content: space-between;
position: relative;
cursor: pointer;
box-sizing: border-box;
}
.accordionItemPush {
/* content: '\002B'; */
font-size: 2rem;
/* position: absolute;
right: 1rem; */
transition: transform 0.2s ease-in-out;
min-width: 70px;
display: flex;
justify-content: space-around;
align-items: center;
}
.accordionItemPush.active::after {
/* content: '\2212'; */
transform: rotate(45deg);
}
.accordionContent {
max-height: 0;
overflow: hidden;
}
.accordionParagraph {
padding: 1rem;
line-height: 1.5rem;
border-top: 1px solid;
border-image: linear-gradient(to right, transparent, rgb(101, 101, 136), transparent) 1 ;
transition: max-heigth 0.2s ease-out;
}
.accordionItem.active + .accordionContent {
max-height: auto;
display: block;
}
JS:
const questions = [] // array with questions
const qnaContainer = document.getElementById("qnaContainer")
const generateTitleHtml = title => {
return `
<h3>${title}</h3>
`
}
const generateQuestionHtml = item => {
return `
<div class="accordionItem">
<div class="accordionItemTitle">
<p>${item.question}</p>
<div class="accordionItemPush">
+
</div>
</div>
<div class="accordionContent">
<p class="accordionParagraph">${item.answer}</p>
</div>
</div>
`
}
const listQ = questions => {
qnaContainer.insertAdjacentHTML('beforeend', generateTitleHtml(questions.title))
questions.items.forEach( question => {
qnaContainer.insertAdjacentHTML('beforeend', generateQuestionHtml(question))
})
}
listQ(questions.regularQuestions)
listQ(questions.membershipBilling)
const accordionItemHeaders = document.querySelectorAll(".accordionItemTitle");
const toggleBar = () => {
accordionItemHeaders.forEach(item => {
item.addEventListener("click", () => {
checkCurrentlyActiveItem(item)
toggleActive(item)
})
});
}
const checkCurrentlyActiveItem = (accordionItemHeader) => {
const currentlyActiveItem = document.querySelector(".accordionItemTitle.active");
if(currentlyActiveItem && currentlyActiveItem!==accordionItemHeader) {
currentlyActiveItem.classList.toggle("active");
currentlyActiveItem.nextElementSibling.style.maxHeight = 0;
}
}
const toggleActive = (accordionItemHeader, itemBtn) => {
accordionItemHeader.classList.toggle("active");
const accordionItemBody = accordionItemHeader.nextElementSibling;
if(accordionItemHeader.classList.contains("active")) {
accordionItemBody.style.maxHeight = accordionItemBody.scrollHeight + "px";
}
else {
accordionItemBody.style.maxHeight = 0;
}
}
toggleBar()
What you could do is: instead of putting the HTML code in the javascript, create elements with document.createElement("elementName") and then set its class name or id. Then you can set an onclick-event on the element and change its innerText or innerHTML to a "-". I think this link can be useful. If you have any questions, ask them :)

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 HTML DOM wont put content in seperate cards

this is my first attempt at using javascript HTML DOM. Im trying to put the content of the birds (the name and an image) in seperate cards but it instead it puts them all in the same card. I'm guessing my problem lies in the divs part of my javascript but I dont understand how to fix this. Can someone help me?
const cardsContainer = document.querySelector("#cards")
const birdNames = ["Koolmees", "Specht", "kerkuil"]
const birdImages = ["https://www.natuurpunt.be/sites/default/files/styles/content-wide/public/koolmees_fr_van_bauwel.jpg?itok=arfFjeTb&c=312068de040ea85bb4eb43164e28b3b2", "https://www.buitenleven.nl/wp-content/uploads/2019/10/grote-bonte-specht.jpg", "https://www.vogelhuisjes.nl/media/wysiwyg/vogels-in-de-tuin/vogels-in-nederland/xkerkuil.jpg.pagespeed.ic.8a2v4rM0Z3.jpg"]
const birds = [
{ name: "Koolmees", image: "https://www.natuurpunt.be/sites/default/files/styles/content-wide/public/koolmees_fr_van_bauwel.jpg?itok=arfFjeTb&c=312068de040ea85bb4eb43164e28b3b2" },
{ name: "specht", image: "https://www.buitenleven.nl/wp-content/uploads/2019/10/grote-bonte-specht.jpg" },
{ name: "kerkuil", image: "https://www.vogelhuisjes.nl/media/wysiwyg/vogels-in-de-tuin/vogels-in-nederland/xkerkuil.jpg.pagespeed.ic.8a2v4rM0Z3.jpg" }
]
function addCard(birdImage, birdName){
const cardDiv = document.createElement("div")
cardDiv.classList.add("card")
cardsContainer.appendChild(cardDiv)
const img = document.createElement("img")
img.src = birdImage
cardDiv.appendChild(img)
const nameDiv = document.createElement("div")
nameDiv.innerText = birdName
cardDiv.appendChild(nameDiv)
}
function addCards(){
for(let i = 0; i<birdNames.length; i++){
addCard(birdImages[i], birdNames[i])
}
}
addCards()
flex-container {
/* We first create a flex layout context */
display: flex;
/* Then we define the flow direction
and if we allow the items to wrap
* Remember this is the same as:
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap;
/* Then we define how is distributed the remaining space */
justify-content: space-around;
padding: 0;
margin: 0;
list-style: none;
}
flex-item {
background: #ABEBC6;
padding: 5px;
width: 250px;
height: 200px;
margin-top: 10px;
line-height: 50px;
color: black;
font-weight: bold;
font-size: 3em;
text-align: center;
}
nav {
display: flex;
flex-flow: row wrap;
justify-content: flex-end;
list-style: none;
margin: 0;
background: #A2D9CE;
}
nav a {
text-decoration: none;
display: block;
padding: 1em;
color: white;
}
nav a:hover {
background: #1565C0;
}
wrapper {
display: flex;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
}
wrapper > * {
padding: 10px;
flex: 1 100%;
}
header {
background: #DAF7A6;
}
footer {
background: #28B463;
}
main {
text-align: left;
background: #A2D9CE;
}
aside {
background: #28B463;
}
#media all and (min-width: 600px) {
.aside { flex: 1 0 0; }
}
#media all and (min-width: 800px) {
main { flex: 3 0px; }
aside { order: 1; }
main { order: 2; }
footer { order: 3; }
}
body {
width: 100%;
}
#media all and (max-width: 800px) {
nav {
justify-content: space-around;
}
}
#media all and (max-width: 600px) {
nav {
flex-flow: column wrap;
padding: 0;
}
nav a {
text-align: center;
padding: 10px;
border-top: 1px solid rgba(255, 255, 255,0.3);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
nav li:last-of-type a {
border-bottom: none;
}
}
p1 {
font-family: "Times New Roman", Times, serif;
font-size: 40px;
}
p2 {
font-family: Arial, Helvetica, sans-serif;
}
p3 {
font-family: "Lucida Console", "Courier New", monospace;
}
img {
width: 250px;
height: 150px;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="css/style.css">
<title>Test week 2</title>
</head>
<body>
<wrapper>
<header><p1>Vogel magazine voor vogelspotters!</p1></header>
<main>
<flex-container>
<flex-item id="cards"></flex-item>
</flex-container>
</main>
<aside>Aside 1</aside>
<footer>Footer</footer>
</wrapper>
<script src="js/DOM2.js"></script>
</body>
</html>
In your function addCard(birdImage, birdName) change const cardDiv = document.createElement("div") by const cardDiv = document.createElement("flex-item"), remove the flex-item tag and pass the id="cards to <flex-container id="cards">
const cardsContainer = document.querySelector("#cards")
const birdNames = ["Koolmees", "Specht", "kerkuil"]
const birdImages = ["https://www.natuurpunt.be/sites/default/files/styles/content-wide/public/koolmees_fr_van_bauwel.jpg?itok=arfFjeTb&c=312068de040ea85bb4eb43164e28b3b2", "https://www.buitenleven.nl/wp-content/uploads/2019/10/grote-bonte-specht.jpg", "https://www.vogelhuisjes.nl/media/wysiwyg/vogels-in-de-tuin/vogels-in-nederland/xkerkuil.jpg.pagespeed.ic.8a2v4rM0Z3.jpg"]
const birds = [
{ name: "Koolmees", image: "https://www.natuurpunt.be/sites/default/files/styles/content-wide/public/koolmees_fr_van_bauwel.jpg?itok=arfFjeTb&c=312068de040ea85bb4eb43164e28b3b2" },
{ name: "specht", image: "https://www.buitenleven.nl/wp-content/uploads/2019/10/grote-bonte-specht.jpg" },
{ name: "kerkuil", image: "https://www.vogelhuisjes.nl/media/wysiwyg/vogels-in-de-tuin/vogels-in-nederland/xkerkuil.jpg.pagespeed.ic.8a2v4rM0Z3.jpg" }
]
function addCard(birdImage, birdName){
const cardDiv = document.createElement("flex-item")
cardDiv.classList.add("card")
cardsContainer.appendChild(cardDiv)
const img = document.createElement("img")
img.src = birdImage
cardDiv.appendChild(img)
const nameDiv = document.createElement("div")
nameDiv.innerText = birdName
cardDiv.appendChild(nameDiv)
}
function addCards(){
for(let i = 0; i<birdNames.length; i++){
addCard(birdImages[i], birdNames[i])
}
}
addCards()
flex-container {
/* We first create a flex layout context */
display: flex;
/* Then we define the flow direction
and if we allow the items to wrap
* Remember this is the same as:
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap;
/* Then we define how is distributed the remaining space */
justify-content: space-around;
padding: 0;
margin: 0;
list-style: none;
}
flex-item {
background: #ABEBC6;
padding: 5px;
width: 250px;
height: 200px;
margin-top: 10px;
line-height: 50px;
color: black;
font-weight: bold;
font-size: 3em;
text-align: center;
}
nav {
display: flex;
flex-flow: row wrap;
justify-content: flex-end;
list-style: none;
margin: 0;
background: #A2D9CE;
}
nav a {
text-decoration: none;
display: block;
padding: 1em;
color: white;
}
nav a:hover {
background: #1565C0;
}
wrapper {
display: flex;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
}
wrapper > * {
padding: 10px;
flex: 1 100%;
}
header {
background: #DAF7A6;
}
footer {
background: #28B463;
}
main {
text-align: left;
background: #A2D9CE;
}
aside {
background: #28B463;
}
#media all and (min-width: 600px) {
.aside { flex: 1 0 0; }
}
#media all and (min-width: 800px) {
main { flex: 3 0px; }
aside { order: 1; }
main { order: 2; }
footer { order: 3; }
}
body {
width: 100%;
}
#media all and (max-width: 800px) {
nav {
justify-content: space-around;
}
}
#media all and (max-width: 600px) {
nav {
flex-flow: column wrap;
padding: 0;
}
nav a {
text-align: center;
padding: 10px;
border-top: 1px solid rgba(255, 255, 255,0.3);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
nav li:last-of-type a {
border-bottom: none;
}
}
p1 {
font-family: "Times New Roman", Times, serif;
font-size: 40px;
}
p2 {
font-family: Arial, Helvetica, sans-serif;
}
p3 {
font-family: "Lucida Console", "Courier New", monospace;
}
img {
width: 250px;
height: 150px;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="css/style.css">
<title>Test week 2</title>
</head>
<body>
<wrapper>
<header><p1>Vogel magazine voor vogelspotters!</p1></header>
<main>
<flex-container id="cards">
</flex-container>
</main>
<aside>Aside 1</aside>
<footer>Footer</footer>
</wrapper>
<script src="js/DOM2.js"></script>
</body>
</html>

Why does my for loop stop after one execution?

I created an array with four objects. I am attempting to show a new random object in the array each time a button (HAPPY) is clicked, using a FOR loop. However, on button click, the loop only runs once with no error messages given. I have looked through other peoples' for loops and they are similar or identical to mine. So I am not sure where I have gone wrong.
I know that a small part of code is missing to bring everything together. I suspected it was something to do with [i] and have tried adding this to different parts of the code - to no avail.
Any help appreciated, thank you. JS Fiddle HERE
window.onload = () => {
/* HTML ELEMENTS */
var arrow = document.getElementById("arrow");
var welcomeButton = document.getElementById("welcome-button");
var welcomeBox = document.getElementById("welcome-box");
var introQuestion = document.getElementById("intro-question");
var happyButton = document.getElementById("happy");
const nextVerseButton = document.querySelector(".box-button");
const slider = document.querySelector(".happy-slider");
const bibleBox = document.querySelector(".happy-bible-box");
var pageTitle = document.getElementById("title");
var pageVerse = document.getElementById("verse");
const happyVerses = [{
title: "Psalm 28:7",
verse: "The Lord is my strength and shield. I trust him with all my heart. He helps me, and my heart is filled with joy.I burst out in songs of thanksgiving."
},
{
title: "Philippians 4:4",
verse: "Rejoice in the Lord always. Again I will say, rejoice!"
},
{
title: "John 15:11",
verse: "These things have I spoken to you, that My joy may remain in you, and that your joy may be full."
},
{
title: "2 Corinthians 6:10",
verse: "Our hearts ache, but we always have joy. We are poor, but we give spiritual riches to others.We own nothing, and yet we have everything."
},
];
console.log(happyVerses);
// Random verse
const randomVerse = happyVerses[Math.floor(Math.random() * happyVerses.length)];
let newTitle = randomVerse.title;
let newVerse = randomVerse.verse;
welcomeButton.onclick = () => {
welcomeBox.style.display = "none";
introQuestion.style.display = "flex";
}
happyButton.onclick = () => {
introQuestion.style.display = "none";
arrow.style.display = "block";
bibleBox.style.display = "block";
}
arrow.onclick = () => {
arrow.style.display = "none";
introQuestion.style.display = "flex";
bibleBox.style.display = "none";
}
changeText = () => {
pageTitle.innerHTML = newTitle;
pageVerse.innerHTML = newVerse;
}
nextVerseButton.onclick = () => {
for (i = 0; i < happyVerses.length; i++) {
changeText();
};
i++;
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
outline: none;
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
}
.fade {
transition: ease 0.3s;
opacity: 0;
}
button {
cursor: pointer;
transition: ease 0.3s;
}
button:hover {
background-color: white !important;
color: black !important;
transform: scale(1.1, 1.1);
}
.page-wrap {
width: 1000px;
max-width: 100%;
/*Wrapper width*/
margin-left: 5%;
/*Nice space between content and device border*/
margin-right: 5%;
/*Nice space between content and device border*/
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 500px;
position: relative;
}
#arrow {
align-self: flex-start;
position: absolute;
top: 0;
font-size: 2em;
color: white;
display: none;
cursor: pointer;
}
#header-2 {
width: 100%;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
#header-2 h1 {
color: white;
}
main {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #0E7CFF;
}
#main-wrap {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
#welcome-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#welcome h1 {
color: white;
margin-bottom: 12px;
}
#welcome-button {
padding: 12px 30px 12px 30px;
border: solid 1.5px white;
border-radius: 50px;
background-color: transparent;
color: white;
}
#button-div {
display: flex;
flex-direction: column;
display: flex;
justify-content: space-evenly;
max-width: 300px;
width: 100%;
}
#button-div button {
margin-top: 20px;
margin-bottom: 20px;
padding: 12px;
}
#intro-question {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
display: none;
}
#intro-question button {
padding: 12px;
border: solid 1.5px white;
border-radius: 50px;
background-color: transparent;
color: white;
}
#intro-question button:nth-child(1) {
margin-top: 0;
}
#intro-question button:nth-child(4) {
margin-bottom: 0;
}
#intro-question h1 {
font-size: 2em;
margin-bottom: 50px;
}
.happy-bible-box {
color: white;
max-width: 500px;
width: 100%;
display: none;
transition: ease 0.3s;
}
#title {
font-family: 'Baloo Bhaina 2', cursive;
font-weight: 400;
}
.happy-bible-box p {
margin-top: 12px;
margin-bottom: 30px;
font-family: 'Baloo Bhaina 2', cursive;
transition: all 0.5s;
}
.box-button {
padding-left: 20px;
padding-right: 20px;
padding-top: 10px;
padding-bottom: 10px;
border: solid 1.5px white;
border-radius: 50px;
background-color: transparent;
color: white;
font-family: 'Baloo Bhaina 2', cursive;
}
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Bible</title>
<script src="script.js"></script>
<script src="https://kit.fontawesome.com/cd801faa65.js" crossorigin="anonymous"></script>
<link href="https://fonts.googleapis.com/css?family=Baloo+Bhaina+2:400,500&display=swap" rel="stylesheet">
</head>
<body>
<main id="main">
<div class="page-wrap">
<i class="fa fa-angle-left" id="arrow"></i>
<div id="welcome-box">
<h1>Welcome to Bible</h1>
<button id="welcome-button">Let's go</button>
</div>
<div id="intro-question">
<h1>How are you feeling today?</h1>
<div id="button-div">
<button id="happy">Happy</button>
<button id="anxious">Anxious</button>
<button id="worried">Worried</button>
<button id="lustful">Confused</button>
</div>
</div>
<article class="happy-bible-box">
<h2 id="title">John 15:11</h2>
<p id="verse">These things have I spoken to you, that My joy may remain in you, and that your joy may be full.</p>
<button class="box-button">Show me another</button>
</article>
</div>
You get random verse for once :
let randomVerse = happyVerses[Math.floor(Math.random()*happyVerses.length)];
let newTitle = randomVerse.title;
let newVerse = randomVerse.verse;
Put this in the changetext function to get random verse every time.
Like this:
changeText = () => {
let randomVerse = happyVerses[Math.floor(Math.random()*happyVerses.length)];
pageTitle.innerHTML = randomVerse.title;
pageVerse.innerHTML = randomVerse.verse;
}
You have to put the randomVerse into changeText() function to get it executed everytime nextVerseButton is clicked
You don't need to for loop, just run the change function: changeText();
Your logic is a little confused. You need to get another random verse, your for loop is currently just setting the same thing everytime
nextVerseButton.onclick = () => {
let randomVerse = happyVerses[Math.floor(Math.random()*happyVerses.length)];
let newTitle = randomVerse.title;
let newVerse = randomVerse.verse;
changeText();
}

Categories