I'm building a small quiz app, and want to display the user score on a different html page immediately the user finished answering the questions. what am getting right now the user finish answering the questions the in which the score is suppose to display loads and open without the score displayed.
`
<body>
<div class="quiz-title">
<h1>JS Quiz</h1>
</div>
<div class="container">
<h2 id="score-board">00</h2>
<div id="questions"></div>
<div id="answers">
</div>
<button type="submit"class="nbtn">Play</button>
</div>
<script src="quiz.js"></script>
<!-- <script type="text/javascript" src="quiz1.js"></script> -->
</body>
the page to display the score
<body>
<h2 id="score-board">00</h2>
<div>
<button id="play-btn">play</button>
</div>
<script src="quiz.js"></script>
<!-- <script type="text/javascript" src="quiz1.js"></script> -->
</body>
var questionElement = document.getElementById('questions');
var answerElement = document.getElementById('answers');
var scoreBoard = document.querySelector('#score-board');
const state = {
currentQuestionIndex: 0,
score: 0
};
var questions = [
{ question: " 1. javaScript is an....... language?",
answers: [ "object-oriented", "object-based", "procedural", "none of the above"],
correct: 1
},
{ question: " 2.which of the following keywords is used a define variable in javaScript",
answers: [ "var", "let", "both A and B", "none of the above"],
correct: 2
},
{
question: "3. which of the following methods is used to HTML elements using javaScript",
answers: ["getElementsById", "getElementByClassName", "both A and B", "none of the above"] ,
correct: 2
}
];
function showQuestion(questionIndex){
const question = questions[questionIndex];
let qDiv = document.createElement('div');
let p = document.createElement('p');
questionElement.innerHTML = "";
answerElement.innerHTML = "";
p.textContent = question.question;
qDiv.appendChild(p);
questionElement.appendChild(qDiv);
question.answers.forEach((answers, answerIndex) =>{
const $input = document.createElement('input');
const $label = document.createElement('label');
$label.appendChild($input);
$label.appendChild(document.createTextNode(answers));
$input.name = `question${questionIndex}`;
$input.type = 'radio';
$input.value = answerIndex;
answerElement.append($label);
// if ($input.checked === false) {
// console.log('select answer');
// } else{
// showQuestion(state.currentQuestionIndex);
// }
});
};
showQuestion(0);
var nBtn = document.querySelector('.nbtn');
nBtn.addEventListener('click', function(){
state.currentQuestionIndex += 1;
if (state.currentQuestionIndex === questions.length) {
removeLastQuestion();
scorePage();
showScores();
} else{
showQuestion(state.currentQuestionIndex)
}
});
const $answers = document.getElementById("answers");
$answers.addEventListener("change", (event) => {
const currentQuestion = questions[state.currentQuestionIndex];
const selectedAnswerIndex = Number(event.target.value);
const correctAnswerIndex = currentQuestion.correct;
const isCorrect = selectedAnswerIndex === correctAnswerIndex;
state.score += isCorrect ? 1 : 0;
// if (isCorrect) {
// var scoreBoard = document2.querySelector('.score-board');
// // scoreBoard.textContent = state.score;
// // console.log("correct answer");
// } else {
// var scoreBoard = document.querySelector('.score-board');
// // scoreBoard.textContent = state.score += 0;
// // console.log("wrong answer");
// }
});
function showScores() {
if (state.currentQuestionIndex === questions.length) {
scoreBoard.innerHTML = `${state.score}/${questions.length}`
}
}
function removeLastQuestion(){
if (state.currentQuestionIndex > questions.length - 1) {
questionElement.innerHTML = "";
answerElement.innerHTML = "";
}
}
function scorePage() {
if (state.currentQuestionIndex > questions.length -1) {
window.location.href = 'index23.html';
// scoreBoard = document.querySelector('#score-board');
// scoreBoard.innerText = `${state.score}/${questions.length}`;
}
}
// const playBtn = document.querySelector('#play-btn');
// playBtn.addEventListener('click', showQuestion);
`
I am making a todo app. In the app, there are delete and edit functions. But the Delete function works at the first todo. If I try other todos, It deletes a lot of todos. I tried many ways but disn't work. Please help!
const todoForm = document.querySelector(".todo-form");
const todos = document.querySelector(".todos");
const todoTitle = document.querySelector(".todo-title");
const modal = document.querySelector("#modal");
const modalClose = document.querySelector(".close-button");
const editedText = document.querySelector(".edited-text ");
const submitEdit = document.querySelector(".submit");
const todoList = [];
let totalTodo = 0;
function findFromArray(id, array) {
for (let i = 0; i < array.length; i++) {
if (id === array[i].id) {
return array[i];
}
}
return null;
}
function deleteTodo(id) {
const element = document.getElementById(id);
element.remove();
const data = findFromArray(id, todoList);
todoList.splice(todoList.indexOf(data), 1);
}
function editTodo(id) {
const element = document.querySelector("#" + id + " h1");
modal.showModal();
modalClose.addEventListener("click", () => {
modal.close();
});
submitEdit.addEventListener("click", () => {
const newTodoText = editedText.value;
element.innerText = newTodoText;
modal.close();
});
}
todoForm.addEventListener("submit", (e) => {
e.preventDefault();
let title = todoTitle.value;
const newTodo = document.createElement("div");
const h1 = document.createElement("h1");
const deleteButton = document.createElement("button");
const editButton = document.createElement("button");
deleteButton.innerText = "Delete";
editButton.innerText = "Edit";
todoList.push({
id: "Todo" + totalTodo,
title,
});
totalTodo++;
for (let i = 0; i < todoList.length; i++) {
newTodo.classList.add("todo-card");
todos.appendChild(newTodo);
h1.innerText = todoList[i].title;
deleteButton.addEventListener("click", () => deleteTodo(todoList[i].id));
editButton.addEventListener("click", () => editTodo(todoList[i].id));
newTodo.appendChild(h1);
newTodo.appendChild(deleteButton);
newTodo.appendChild(editButton);
newTodo.id = todoList[i].id;
}
todoTitle.value = "";
});
<body>
<h1 class="todo-heading">Todo App</h1>
<form class="todo-form">
<input class="todo-title" type="text" placeholder="Todo Name" />
<input type="Submit" class="todo-button" />
</form>
<br />
<div class="todos"></div>
<dialog id="modal">
<h1>Edit</h1>
<input type="text" class="edited-text" placeholder="New Todo" />
<br />
<br />
<button class="submit">Submit</button>
<button class="close-button">
<svg class="svg-icon" viewBox="0 0 20 20">
<path
d="M10.185,1.417c-4.741,0-8.583,3.842-8.583,8.583c0,4.74,3.842,8.582,8.583,8.582S18.768,14.74,18.768,10C18.768,5.259,14.926,1.417,10.185,1.417 M10.185,17.68c-4.235,0-7.679-3.445-7.679-7.68c0-4.235,3.444-7.679,7.679-7.679S17.864,5.765,17.864,10C17.864,14.234,14.42,17.68,10.185,17.68 M10.824,10l2.842-2.844c0.178-0.176,0.178-0.46,0-0.637c-0.177-0.178-0.461-0.178-0.637,0l-2.844,2.841L7.341,6.52c-0.176-0.178-0.46-0.178-0.637,0c-0.178,0.176-0.178,0.461,0,0.637L9.546,10l-2.841,2.844c-0.178,0.176-0.178,0.461,0,0.637c0.178,0.178,0.459,0.178,0.637,0l2.844-2.841l2.844,2.841c0.178,0.178,0.459,0.178,0.637,0c0.178-0.176,0.178-0.461,0-0.637L10.824,10z"
></path>
</svg>
</button>
</dialog>
I was expecting to remove a todo element and the todo data. But It removes a lot of todo elements and data. I tried the splice method and the delete keyword but didn't work. Please help!
I think the problem is with the for loop you are using to create the new elements. The loop is iterating through the entire todoList array, but it should only be creating a new todo element for the last array item.
todoForm.addEventListener("submit", (e) => {
e.preventDefault();
let title = todoTitle.value;
const newTodo = document.createElement("div");
const h1 = document.createElement("h1");
const deleteButton = document.createElement("button");
const editButton = document.createElement("button");
deleteButton.innerText = "Delete";
editButton.innerText = "Edit";
todoList.push({
id: "Todo" + totalTodo,
title,
});
totalTodo++;
const lastTodo = todoList[todoList.length - 1];
newTodo.classList.add("todo-card");
todos.appendChild(newTodo);
h1.innerText = lastTodo.title;
deleteButton.addEventListener("click", () => deleteTodo(lastTodo.id));
editButton.addEventListener("click", () => editTodo(lastTodo.id));
newTodo.appendChild(h1);
newTodo.appendChild(deleteButton);
newTodo.appendChild(editButton);
newTodo.id = lastTodo.id;
todoTitle.value = "";
});
Also, like Jelmer commented.. In the deleteTodo function, remove todoList =. You should use the splice method directly on the todoList array to remove the element.
todoList.splice(todoList.indexOf(data), 1);
I was working on a code where I fetch and display data from an API. I used to store it in Localstorage of browser's port.But now I wish to connect it to mongoDB.
When I import mongoclient my HTML elements become unused and their reference points nowhere.
This is the Script.js file
const searchInput = document.getElementById('searchInput')
const searchBtn = document.getElementById('searchBtn')
const moviesList = document.getElementById('moviesList')
const watchlist = document.getElementById('watchlist')
const removeWatchlistBtn = document.getElementsByClassName('remove-watchlist-btn')
const cardWatchlistBtn = document.getElementsByClassName('watchlist-btn')
const readMore = document.getElementsByClassName('read-more')
const readMorePlot = document.getElementsByClassName('read-more-plot')
const movieKey = document.getElementsByClassName('movie-key')
const localStorageKeys = Object.keys(localStorage)
if (searchBtn) {
searchBtn.addEventListener('click', searchMovies)
}
async function searchMovies() {
// Hide default elements
if (moviesList.children) {
let children = moviesList.children
let childrenArr = Array.prototype.slice.call(children)
childrenArr.forEach((child) => child.remove())
}
let res = await fetch(`https://www.omdbapi.com/?s=${searchInput.value.trim()}&apikey=e668e570`)
let data = await res.json()
const movies = data.Search
// Get and display search results
movies.forEach(async (movie) => {
let response = await fetch(`https://www.omdbapi.com/?i=${movie.imdbID}&apikey=e668e570`)
let moviesListData = await response.json()
console.log(moviesListData)
const readMoreMovieID = moviesListData.imdbID + 'more'
const hideReadMore = moviesListData.imdbID + 'hide'
const summaryPlot = `${moviesListData.Plot.substring(0, 110)}<span id=${hideReadMore}>...<button class="black read-more" onclick="showCompletePlot(${readMoreMovieID}, ${hideReadMore})">Read more</button></span>`
const readMorePlot = `<span class="read-more-plot" id=${readMoreMovieID} >${moviesListData.Plot.substring(110, moviesListData.Plot.length)}</span>`
const completePlot = moviesListData.Plot
const longPlot = summaryPlot + readMorePlot
const movieID = moviesListData.imdbID
const movieIDkey = moviesListData.imdbID + 'key'
const watchlistBtnKey = moviesListData.imdbID + 'watchlistBtn'
const removeBtnKey = moviesListData.imdbID + 'removeBtn'
moviesList.innerHTML += `
<div class="cards">
<div class="card" id=${movieID}>
<span id=${movieIDkey} class="hide movie-key">${movieIDkey}</span>
<img src=${moviesListData.Poster} class="card-poster" />
<div class="card-header">
<h2 class="card-title">${moviesListData.Title}</h2>
<img src="images/star-icon.svg" class="star-icon" />
<span class="card-rating">${moviesListData.imdbRating}</span>
</div>
<div class="card-meta">
<span class="card-runtime">${moviesListData.Runtime}</span>
<span>${moviesListData.Genre}</span>
<button class="card-btn card-watchlist watchlist-btn" id="${watchlistBtnKey}" onclick="addToWatchlist(${movieIDkey}, ${movieID}, ${watchlistBtnKey}, ${removeBtnKey})"><img src="images/watchlist-icon.svg" alt="Add film to watchlist" class="card-watchlist-plus-icon" /> Watchlist</button>
<button class="card-btn card-watchlist remove-watchlist-btn" id="${removeBtnKey}" onclick="removeFromWatchlist(${movieIDkey}, ${removeBtnKey}, ${watchlistBtnKey}, ${removeBtnKey})"><img src="images/remove-icon.svg" alt="Remove film to watchlist" class="card-watchlist-plus-icon" /> Remove</button>
</div>
<p class="card-plot">${completePlot.length < 110 ? completePlot : longPlot}</p>
</div>
</div>
`
displayWatchlistOrRemoveBtn()
})
}
function displayWatchlistOrRemoveBtn() {
for (let movie of movieKey) {
const removeBtnID = movie.id.slice(0, 9) + 'removeBtn'
const removeBtn = document.getElementById(removeBtnID)
const watchlistBtnID = movie.id.slice(0, 9) + 'watchlistBtn'
const watchlistBtn = document.getElementById(watchlistBtnID)
localStorageKeys.forEach((key) => {
if (movie.id === key) {
removeBtn.style.display = 'inline'
watchlistBtn.style.display = 'none'
}
})
}
}
function showCompletePlot(readMoreMovieID, hideReadMore) {
readMoreMovieID.style.display = 'inline'
hideReadMore.style.display = 'none'
}
async function addToWatchlist(movieIDkey, movieID, watchlistBtnKey, removeBtnKey) {
console.log(movieID.id)
const a = movieID.id
const b= movieID.Title
let sanket = await fetch(`https://www.omdbapi.com/?i=${movieID.id}&apikey=e668e570`)
const ab = await sanket.json()
console.log(ab)
localStorage.setItem(movieIDkey.innerHTML, movieID.innerHTML)
watchlistBtnKey.style.display = 'none'
removeBtnKey.style.display = 'inline'
}
function removeFromWatchlist(movieIDkey, watchlistBtnKey, removeBtnKey) {
localStorage.removeItem(movieIDkey.innerHTML)
// Get parent element (the movie card div) and remove it
if (watchlist) {
localStorage.removeItem(movieIDkey.innerHTML)
const parentEl = document.getElementById(movieIDkey.innerHTML).parentElement
parentEl.remove()
}
watchlistBtnKey.style.display = 'inline'
removeBtnKey.style.display = 'none'
// Display default elements if local storage empty
if (watchlist && localStorage.length === 0) {
if (watchlist.children) {
const children = watchlist.children
const childrenArr = Array.prototype.slice.call(children)
childrenArr.forEach((child) => (child.style.display = 'flex'))
}
}
}
// Hide default elements if data is in local storage
if (watchlist && localStorage.length > 0) {
if (watchlist.children) {
const children = watchlist.children
const childrenArr = Array.prototype.slice.call(children)
childrenArr.forEach((child) => (child.style.display = 'none'))
}
}
for (let i = 0; i < localStorage.length; i++) {
const getLocalStorage = localStorage.getItem(localStorage.key(i))
// Display every key's value to the watchlist
if (watchlist) {
watchlist.innerHTML += `<div class="card">${getLocalStorage}</div>`
// Hide the 'add to watchlist' button
for (let button of cardWatchlistBtn) {
button.style.display = 'none'
}
// Display the 'remove from watchlist' button
for (let button of removeWatchlistBtn) {
button.style.display = 'inline'
}
}
}
Here when I use const { MongoClient } = require("mongodb"); the elements readMore and readMorePlot (Line no.7 and 8) become unused.
I tried exporting my addToWatchlist function but problem persists.
I also have tried adding Type=Module in html file but that doesn't work.
I'm working on a to-do list project and stuck at this part where when a trash button is clicked all the list items will be deleted and it won't add any new to-do items.
I've checked other posts but couldn't really find the answer for my project, please help!
let input = document.querySelector('#todo')
let btn = document.querySelector('#btn');
let list = document.querySelector('#list');
btn.addEventListener('click', () => {
let txt = input.value;
if (txt === "") {
alert('Please write something to do!');
} else {
let li = document.createElement('li');
li.innerHTML = txt;
list.insertBefore(li, list.childNodes[0]);
input.value = '';
const delBtn = document.createElement("i");
delBtn.classList.add("fas", "fa-trash-alt");
li.appendChild(delBtn);
delBtn.addEventListener('click', e => {
list.parentNode.removeChild(list);
})
}
})
list.addEventListener('click', e => {
if(e.target.tagName == 'LI') {
e.target.classList.toggle('checked');
}
})
<div class="todoList">
<h1>To-do List</h1>
<div class="add-element">
<input type="text" id="todo" placeholder="Add new to-do">
<button id="btn">Add</button>
</div>
<div class="element-list">
<ul id="list"></ul>
</div>
</div>
list.parentNode.removeChild(list); deletes all the list, if you want to delete only one element from the list, add a button to every li and change this line to li.parentNode.removeChild(li); like this:
let input = document.querySelector('#todo')
let btn = document.querySelector('#btn');
let list = document.querySelector('#list');
btn.addEventListener('click', () => {
let txt = input.value;
if (txt === "") {
alert('Please write something to do!');
} else {
let li = document.createElement('li');
li.innerHTML = txt;
list.insertBefore(li, list.childNodes[0]);
input.value = '';
const delBtn = document.createElement("i");
li.appendChild(delBtn);
delBtn.addEventListener('click', e => {
li.parentNode.removeChild(li);
})
}
})
list.addEventListener('click', e => {
if(e.target.tagName == 'LI') {
e.target.classList.toggle('checked');
}
})
<div class="todoList">
<h1>To-do List</h1>
<div class="add-element">
<input type="text" id="todo" placeholder="Add new to-do">
<button id="btn">Add</button>
</div>
<div class="element-list">
<ul id="list"></ul>
</div>
</div>
I'm creating something like GMAIL functionality with JavaScript ES5 ( I use only const and let, that's it, rest ES5).
So I manage to create the list functionality, all works except that when I select the items and move them to a different list, they lose any functionality, and I can't do anything with them.
I believe I need to use querySelectorAll to get all the lists, but that doesn't work. Not sure what should I do here.
I think I need to select all the lists, and then loop them to add interactivity.
CodePen: https://codepen.io/Aurelian/pen/dJryrX?editors=1010
JS:
window.onload = function() {
//////////////////////////////////
// VARIABLES
//////////////////////////////////
// Form
const form = document.querySelector('#registrar');
const input = form.querySelector('input');
// Lists
const partyList = document.querySelector('.party-lists');
const partyInvitedList = document.querySelector('#list-invited')
const partyGoingList = document.querySelector('#list-going');
const partyNotSure = document.querySelector('#list-not-sure');
const partyNotGoing = document.querySelector('#list-not-going');
// List Options
const listOptions = document.querySelector('.list-options');
const btnMoveToGoing = document.querySelector('.btnMoveGoing');
const btnMoveToNotSure = document.querySelector('.btnMoveNotSure');
const btnMoveToNotGoing = document.querySelector('.btnMoveNotGoing');
const btnDeleteSelected = document.querySelector('.btnDeleteSelected');
//////////////////////////////////
// FUNCTIONS
//////////////////////////////////
function createLI(text) {
const li = document.createElement('li');
const span = document.createElement('span');
span.textContent = text;
li.appendChild(span);
const label = document.createElement('label');
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
label.appendChild(checkbox);
li.appendChild(label);
const editButton = document.createElement('button');
editButton.textContent = 'edit';
li.appendChild(editButton);
const removeButton = document.createElement('button');
removeButton.textContent = 'remove';
li.appendChild(removeButton);
return li;
}
//////////////////////////////////
// EVENT HANDLERS
//////////////////////////////////
form.addEventListener('submit', function(e) {
e.preventDefault();
const text = input.value;
input.value = '';
const li = createLI(text);
partyInvitedList.appendChild(li);
});
partyList.addEventListener('click', function(e) {
if (e.target.tagName === 'BUTTON') {
const button = e.target;
const li = button.parentNode;
const ul = li.parentNode;
if (button.textContent === 'remove') {
ul.removeChild(li);
} else if (button.textContent === 'edit') {
const span = li.firstElementChild;
const input = document.createElement('input');
input.type = 'text';
input.value = span.textContent;
li.insertBefore(input, span);
li.removeChild(span);
button.textContent = 'save';
} else if (button.textContent === 'save') {
const input = li.firstElementChild;
const span = document.createElement('span');
span.textContent = input.value;
li.insertBefore(span, input);
li.removeChild(input);
button.textContent = 'edit';
}
}
});
listOptions.addEventListener('click', function(e) {
partyList.querySelectorAll('*:checked').forEach(function (listItems) {
const button = e.target;
var items = listItems.parentNode.parentNode;
if(button.className === 'btnMoveGoing') {
partyGoingList.appendChild(items);
items.checked = false;
var item = listItems;
item.checked = false;
} else if(button.className === 'btnMoveNotSure'){
partyNotSure.appendChild(items);
var item = listItems;
item.checked = false;
} else if(button.className === 'btnMoveNotGoing'){
partyNotGoing.appendChild(items);
var item = listItems;
item.checked = false;
} else if(button.className === 'btnDeleteSelected'){
listItems.parentNode.parentNode.remove();
var item = listItems;
item.checked = false;
}
});
});
}
HTML:
<div class="top">
<form id="registrar">
<input type="text" name="name" placeholder="Invite Someone">
<button type="submit" name="submit" value="submit">Submit</button>
</form>
<div class="list-options">
<button class="btnMoveGoing">Move to Going</button>
<button class="btnMoveNotSure">Move to Not Sure</button>
<button class="btnMoveNotGoing">Move to Not Going</button>
<button class="btnDeleteSelected">Delete Selected</button>
</div>
</div><!-- /top -->
<div class="col">
<h3>Invited</h3>
<ul id="list-invited" class="party-lists">
</ul>
</div>
<div class="col">
<h3>Going</h3>
<ul id="list-going" class="party-lists">
</ul>
</div>
<div class="col">
<h3>Not Sure</h3>
<ul id="list-not-sure" class="party-lists">
</ul>
</div>
<div class="col">
<h3>Not Going</h3>
<ul id="list-not-going" class="party-lists">
</ul>
</div>