I am using the Bootstrap alert system, but I encountered a problem. My Alert appears when the button is pressed, and then the setTimeout function works and my alert does not appear after 1 second. But the problem is here, the alert part does not appear again when I make a successful or incorrect login. I want my alert to appear on every successful or incorrect login. Thanks advance for your answers. (ı don't want Jquery, only Vanilla JavaScript.) Codepen.io: https://codepen.io/BerkayAkgurgen/pen/xxEmQLo (All Code)
function showAlert(type, message) {
if (alert == null) {
alert = document.createElement("div");
alert.className = `alert alert-${type}`;
alert.id = "alertID";
alert.textContent = message;
firstCardBody.appendChild(alert);
alert.style.marginTop = "1rem";
} else {
alert.className = `alert alert-${type}`;
alert.textContent = message;
}
setTimeout(function myFunction2() {
document.getElementById("alertID").style.display = 'none';
}, 1000)
};
const form = document.querySelector("#todo-form");
const todoInput = document.querySelector("#todo");
const todoList = document.querySelector(".list-group");
const firstCardBody = document.querySelectorAll(".card-body")[0];
const secondCardBody = document.querySelectorAll(".card-body")[1];
const filter = document.querySelector("#filter")[0];
const clearButton = document.querySelector("#clear-todos")[0];
let alert = document.getElementById("alertID");
eventListeners();
//Event Listeners
function eventListeners() {
secondCardBody.addEventListener("click", deleteTodo);
form.addEventListener("submit", addTodo);
document.addEventListener("DOMContentLoaded", loadAllTodosToUI);
}
// Todo Ekleme
function addTodo(e) {
const newTodo = todoInput.value.trim();
if (newTodo === "") {
showAlert("danger", "Lütfen bir todo giriniz");
} else {
showAlert("success", "Giriş Başarılı");
addTodoToUI(newTodo);
addTodoToStorage(newTodo);
}
e.preventDefault();
}
function addTodoToUI(newTodo) {
const listItem = document.createElement("li");
const link = document.createElement("a");
link.href = "#";
link.className = "delete-item";
link.innerHTML = " <i class = 'fa fa-remove'></i>";
listItem.className = "list-group-item d-flex justify-content-between";
listItem.appendChild(document.createTextNode(newTodo));
listItem.appendChild(link);
todoList.appendChild(listItem);
todoInput.value = "";
}
// Alert
function showAlert(type, message) {
if (alert == null) {
alert = document.createElement("div");
alert.className = `alert alert-${type}`;
alert.id = "alertID";
alert.textContent = message;
firstCardBody.appendChild(alert);
alert.style.marginTop = "1rem";
} else {
alert.className = `alert alert-${type}`;
alert.textContent = message;
}
setTimeout(function myFunction2() {
document.getElementById("alertID").style.display = 'none';
}, 1000)
};
// Todo Storage Ekleme
function addTodoToStorage(newTodo) {
let todos = getTodosFromStorage();
todos.push(newTodo);
localStorage.setItem("todos", JSON.stringify(todos));
}
function getTodosFromStorage() { // Storage'den Todoları Almak
let todos;
if (localStorage.getItem("todos") === null) {
todos = [];
} else {
todos = JSON.parse(localStorage.getItem("todos"));
}
return todos;
}
// Sayfa Yüklendiğinde Storage Yükleme
function loadAllTodosToUI() {
let todos = getTodosFromStorage();
todos.forEach(function(todo) {
addTodoToUI(todo);
})
}
// Todo Silme
function deleteTodo(e) {
if (e.target.className === "fa fa-remove") {
e.target.parentElement.parentElement.remove();
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
<link rel="stylesheet" href="berkay.css">
<title>Todo List</title>
</head>
<body>
<div class="container" id="bal" style="margin-top: 20px">
<div class="card row">
<div class="card-header">Todo List</div>
<div class="card-body bdy">
<form id="todo-form" name="form">
<div class="form-row">
<div class="form-group col-md-6">
<input class="form-control" type="text" name="todo" id="todo" placeholder="Bir Todo Girin" autocomplete="off" tabindex="1" />
</div>
</div>
<button type="submit" class="btn btn-danger">Todo Ekleyin</button>
</form>
<!-- <div class="alert alert-danger" role="alert">
This is a danger alert—check it out!
</div> -->
</div>
<div class="card-body body">
<hr />
<h5 class="card-title" id="tasks-title">Todolar</h5>
<div class="form-row">
<div class="form-group col-md-6">
<input class="form-control" type="text" name="filter" id="filter" placeholder="Bir Todo Arayın" tabindex="2" />
</div>
</div>
<hr />
<ul class="list-group">
<!-- <li class="list-group-item d-flex justify-content-between">
Todo 1
<a href = "#" class ="delete-item">
<i class = "fa fa-remove"></i>
</a>
</li>-->
</ul>
<hr />
<a id="clear-todos" class="btn btn-dark" href="#">Tüm Taskları Temizleyin</a>
</div>
</div>
</div>
<div class="box" style="display: none;"></div>
<div class="box2" style="display: none;"></div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous">
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous">
</script>
<script src="berkay.js"></script>
</body>
</html>
Add an extra line to your alert code:
......
} else {
alert.className = `alert alert-${type}`;
alert.textContent = message;
document.getElementById("alertID").style.display = 'initial';
}
More info here
Related
I keep getting this error in my browser console when I inspect it: Uncaught TypeError: allSections.addEventListener is not a function
at PageTransitions (app.js:16:17)
at app.js:33:1
This is strange because in my vs code editer it isn't showing any errors. Here is the code I'm using below.
const sections = document.querySelectorAll('.section');
const secBtns = document.querySelectorAll('.controls');
const secBtn = document.querySelectorAll('.control');
const allSections = document.querySelectorAll('.main-content');
function PageTransitions(){
for(let i = 0; i < secBtn.length; i++){
secBtn[i].addEventListener('click', function(){
let currentBtn = document.querySelectorAll('.active-btn');
currentBtn[0].className = currentBtn[0].className.replace('active-btn', '')
this.className += ' active-btn';
})
}
allSections.addEventListener('click', (e) =>{
const id = e.target.dataset.id;
if(id) {
secBtns.forEach((btn) => {
btn.classList.remove('active')
})
e.target.classList.add('active')
sections.forEach((section)=>{
section.classList.remove('active')
})
const element = document.getElementById(id);
element.classList.add('active');
}
})
}
PageTransitions();
also here is the html its for below.
<!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">
<title>Portfolio</title>
<link rel="stylesheet" href="styles/styles.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital#1&family=Ubuntu:wght#300&display=swap" rel="stylesheet">
</head>
<body class="main-content">
<header class="section sec1 header active" id="home">
</header>
<main>
<section class="section sec2 about" id="about"></section>
<section class="section sec3 portfolio" id="portfolio"></section>
<section class="section sec4 blogs" id="blogs"></section>
<section class="section sec5 contacts" id="contact"></section>
</main>
<div class="controls">
<div class="control control-1 active-btn" data-id="home">
<i class="fas fa-home"></i>
</div>
<div class="control control-2 " data-id="about">
<i class="fas fa-user"></i>
</div>
<div class="control control-3 " data-id="portfolio">
<i class="fas fa-briefcase"></i>
</div>
<div class="control control-4 " data-id="blogs">
<i class="far fa-newspaper"></i>
</div>
<div class="control control-5 " data-id="contact">
<i class="fas fa-envelope-open"></i>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
That's because allSections contains a NodeList since querySelectorAll method returns a static (not live) NodeList representing a list of the document's elements that match the specified group of selectors. , not just one element to listen on:
const allSections = document.querySelectorAll('.main-content');
So to solve that you need to loop over all sections with forEach and for section listen the click:
allSections.forEach((section) =>
section.addEventListener("click", (e) => {
const id = e.target.dataset.id;
if (id) {
secBtns.forEach((btn) => {
btn.classList.remove("active");
});
e.target.classList.add("active");
sections.forEach((section) => {
section.classList.remove("active");
});
const element = document.getElementById(id);
element.classList.add("active");
}
})
);
const sections = document.querySelectorAll('.section');
const secBtns = document.querySelectorAll('.controls');
const secBtn = document.querySelectorAll('.control');
const allSections = document.querySelectorAll('.main-content');
I was having the same problem. The problem here is that when you are using querySelectorAll on the allSections variable the error arises. addEventListener can be applied to a single element only and querySelectorAll is giving a list. To solve this use querySelector instead of querySelectorAll
Hope this helps!
const sections = document.querySelectorAll('.section');
const sectBtns = document.querySelectorAll('.controlls');
const sectBtn = document.querySelectorAll('.control');
const allSections = document.querySelectorAll('.main-content');
function PageTransitions() {
//Button click active class
for (let i = 0; i < sectBtn.length; i++) {
sectBtn[i].addEventListener('click', function () {
let currentBtn = document.querySelectorAll('.active-btn');
currentBtn[0].className = currentBtn[0].className.replace('active-btn', '');
this.className += 'active-btn';
})
}
//Sections Active class
allSections.forEach((section) =>
section.addEventListener('click', (e) => {
const id = e.target.dataset.id;
if (id) {
//remove selected from the other btns
sectBtns.forEach((btn) => {
btn.classList.remove('active')
})
e.target.classList.add('active')
//hide other sections
sections.forEach((section) => {
section.classList.remove('active')
})
const element = document.getElementById(id);
element.classList.add('active')
}
}))
}
PageTransitions();
Blockquote I want to change the color of my card when i press the mark as important button but when i add two or three cards and click on a mark as important of a single card it will change the color of all cards
Blockquote
i want that if i click on mark as important button then a single card color will changed it will not change the color of all cards
console.log("welcome to our website");
shownNotes();
impNotes();
let addbtn = document.getElementById("addbtn");
addbtn.addEventListener("click", handler)
function handler() {
let txtarea = document.getElementById("txtarea");
let notes = localStorage.getItem("notes");
if (notes == null) {
notesObj = [];
}
else {
notesObj = JSON.parse(notes);
}
notesObj.push(txtarea.value);
localStorage.setItem("notes", JSON.stringify(notesObj));
txtarea.value = "";
console.log(notesObj);
shownNotes();
}
function shownNotes() {
let notes = localStorage.getItem("notes");
if (notes == null) {
notesObj = [];
}
else
notesObj = JSON.parse(notes);
let html = "";
notesObj.forEach(function (element, index) {
html +=
`<div class="card mx-2 my-2 funny" style="width: 18rem;" >
<div class="card-body">
<h5 class="card-title">${index}</h5>
<p class="card-text">${element}</p>
<button id="${index} "onclick="delNotes(this.id)" class="btn btn-primary">Delete Note</button>
<button id="impbtn" onclick="impNotes(this.id)" class=" my-2 btn btn-primary">Mark Important</button>
</div>
</div>`
});
let notesElm = document.getElementById("notes");
if (notesObj.length != 0) {
notesElm.innerHTML = html;
}
else {
notesElm.innerHTML = "<b>Nothing to show</b>"
}
}
//function to delete notes
function delNotes(index) {
console.log("i m deleting", index)
let notes = localStorage.getItem("notes");
if (notes == null) {
notesObj = [];
}
else
notesObj = JSON.parse(notes);
notesObj.splice(index, 1);
localStorage.setItem("notes", JSON.stringify(notesObj));
shownNotes();
}
// function to imp notes
function impNotes() {
console.log("important function is firing ");
let impbtn = document.getElementsByClassName("funny");
Array.from(impbtn).forEach(function (element, index) {
element.style.backgroundColor = "yellow";
})
}
<!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">
<title>Magic Notes</title>
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.4.1/dist/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.4.1/dist/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
</body>
</html>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">Magic Notes</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
<div class="container my-4 text-center">
<h1>WELCOME TO MAGIC NOTES </h1>
</div>
<div class="container-sm card text-center ">
<div class="card-body">
<h5 class="card-title">Add a Note </h5>
<div class="form-group">
<textarea class="form-control" id="txtarea" rows="3"></textarea>
</div>
<button class="btn btn-primary" id="addbtn">Click me to add Note </button>
</div>
</div>
<Hr>
<H1 class="text-center">Your Notes </H1>
<div class="row justify-content-center" id="notes"></div>
<!-- <hr> -->
<script src="app.js"></script>
</body>
</html>
The impNotes() function should take in a parameter that will help you identify which note color to change so impNote should be
function impNotes(id) {
console.log("important function is firing ");
let impbtn = document.getElementsByClassName("funny");
Array.from(impbtn).forEach(function (element, index) {
if(index === id)
element.style.backgroundColor = "yellow";
})
}
For you to pass argument to impNote you should change the code in showNotes()
function shownNotes() {
let notes = localStorage.getItem("notes");
if (notes == null) {
notesObj = [];
}
else
notesObj = JSON.parse(notes);
let html = "";
notesObj.forEach(function (element, index) {
html +=
`<div class="card mx-2 my-2 funny" style="width: 18rem;" >
<div class="card-body">
<h5 class="card-title">${index}</h5>
<p class="card-text">${element}</p>
<button id="${index} "onclick="delNotes(this.id)" class="btn btn-primary">Delete Note</button>
<button id="impbtn" onclick="impNotes(${index})" class=" my-2 btn btn-primary">Mark Important</button>
</div>
</div>`
});
let notesElm = document.getElementById("notes");
if (notesObj.length != 0) {
notesElm.innerHTML = html;
}
else {
notesElm.innerHTML = "<b>Nothing to show</b>"
}
}
You pass index to impNote
function shownNotes() {
let notes = localStorage.getItem("notes");
if (notes == null) {
notesObj = [];
}
else
notesObj = JSON.parse(notes);
let html = "";
notesObj.forEach(function (element, index) {
html +=
`<div class="card mx-2 my-2 funny" id="card-${index}" style="width: 18rem;" >
<div class="card-body">
<h5 class="card-title">${index}</h5>
<p class="card-text">${element}</p>
<button id="${index} "onclick="delNotes(this.id)" class="btn btn-primary">Delete Note</button>
<button id="impbtn" onclick="impNotes('card-${index}')" class=" my-2 btn btn-primary">Mark Important</button>
</div>
</div>`
});
let notesElm = document.getElementById("notes");
if (notesObj.length != 0) {
notesElm.innerHTML = html;
}
else {
notesElm.innerHTML = "<b>Nothing to show</b>"
}
}
pass the id for each card based on index as shown and pass the id to impNotes method
function impNotes(id) {
if(id) {
let impbtn = document.getElementById(id);
impbtn.style.backgroundColor = "yellow"
}
}
I am using API for my website.My handleGetDetailsOrAddToFavorites event handler is working but handleRemoveFavorites EventHandler which has been implemented the same way is not working.But why???It gives no Error.Also console.log(e.target.value) in handleRemoveFavorites console logs Nothing.I want my handleRemoveFavorites to give out (e.target.value) so that i can fetch indivisual items Id and delete them from localstorage.
var url = 'https://www.themealdb.com/api/json/v1/1/search.php?s=';
var urlId = 'https://www.themealdb.com/api/json/v1/1/lookup.php?i='; //search by id
const mealList = document.getElementById('list-Items-container');
var input = document.getElementById('inputText');
const mealListFavorites = document.getElementById(
'list-Items-container-favorites'
);
window.onload = renderFavorites;
document.querySelector('form').addEventListener('submit', handleSubmitForm);
// .getElementById('get-details')
mealList.addEventListener('click', handleGetDetailsOrAddToFavorites);
mealListFavorites.addEventListener('click', handleRemoveFavorites);
function handleRemoveFavorites(e) {
e.preventDefault();
console.log(e.target.value);
}
function handleGetDetailsOrAddToFavorites(e) {
e.preventDefault();
console.log('clicked');
if (e.target.value == 'details') {
let mealItem = e.target.parentElement.parentElement;
fetch(
`https://www.themealdb.com/api/json/v1/1/lookup.php?i=${mealItem.dataset.id}`
)
.then(function(res) {
return res.json();
})
.then((data) => {
mealRecipeModal(data.meals);
});
} else if (e.target.value == 'favour') {
let mealItem = e.target.parentElement.parentElement;
fetch(
`https://www.themealdb.com/api/json/v1/1/lookup.php?i=${mealItem.dataset.id}`
)
.then(function(res) {
return res.json();
})
.then((data) => {
window.localStorage.setItem(
mealItem.dataset.id,
JSON.stringify(data.meals)
);
});
}
console.log(Object.entries(localStorage));
}
function mealRecipeModal(meal) {
console.log(meal[0]);
const destination = meal[0].strSource;
console.log(destination);
window.open(`${meal[0].strSource}`);
}
function handleSubmitForm(e) {
e.preventDefault();
let input = document.querySelector('input');
findFood(url + input.value);
input.value = '';
}
function findFood(address) {
fetch(address)
.then(function(res) {
//console.log(res);
return res.json();
})
.then((data) => {
console.log(data);
let html = '';
if (data.meals) {
data.meals.forEach((meal) => {
html += `<div class="food-card" data-id="${meal.idMeal}">
<div class="food-card-image">
<img src="${meal.strMealThumb}" alt="${meal.strMeal}" >
</div>
<div class="food-card-info">
<h3>${meal.strMeal}</h3>
</div>
<div class="food-card-features">
<button id="favorites" value="favour">Add</button>
<button id="get-details" value="details" >Details</button>
</div>
</div>`;
});
}
console.log(html);
mealList.innerHTML = html;
});
}
var html1 = '';
function findFoodFavorite(address) {
fetch(address)
.then(function(res) {
//console.log(res);
return res.json();
})
.then((data) => {
console.log(data);
if (data.meals) {
data.meals.forEach((meal) => {
html1 += `<div class="food-card" data-id="${meal.idMeal}">
<div class="food-card-image">
<img src="${meal.strMealThumb}" alt="${meal.strMeal}" >
</div>
<div class="food-card-info">
<h3>${meal.strMeal}</h3>
</div>
<div class="food-card-features">
<button id="favorites" value="defavour" >Remove</button>
<button id="get-details" value="details" >Details</button>
</div>
</div>`;
});
}
console.log(html1);
mealListFavorites.innerHTML = html1;
});
}
function renderFavorites() {
const urlArray = [];
console.log(Object.entries(localStorage));
for (var i = 0; i < localStorage.length; i++) {
console.log(Object.entries(localStorage)[i][0]);
urlArray.push(Object.entries(localStorage)[i][0]);
}
console.log(urlArray);
urlArray.forEach((id) => findFoodFavorite(urlId + id));
}
This is Index.html(homepage)
<!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="styles.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=M+PLUS+2:wght#200&family=Poppins:ital,wght#0,100;1,200&display=swap" rel="stylesheet">
<title>Meals App | HomePage</title>
</head>
<body>
<header>
<div class="topnav">
<a class="active" href="index.html">Home</a>
Favorites
Details
About
</div>
</header>
<div class="Heading">
<h1>The FoodAPP</h1>
</div>
<div class="form-container">
<form action="submit" method="get">
<input type="text" id="inputText" placeholder="Enter dish...">
<button id="btn" type="submit">Find</button>
</form>
</div>
<div id="list-Items-container">
<!-- <div class="food-card">
<div class="food-card-image">
<img src="http://placehold.it/120x120&text=image3" alt="food">
</div>
<div class="food-card-info">
<h3>Foood namae</h3>
</div>
</div> -->
</div>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
This is favorites page
<!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="styles.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=M+PLUS+2:wght#200&family=Poppins:ital,wght#0,100;1,200&display=swap" rel="stylesheet">
<title>Meals App | Favaorites</title>
</head>
<body>
<header>
<div class="topnav">
<a class="active" href="index.html">Home</a>
Favorites
Details
About
</div>
</header>
<div id="list-Items-container-favorites">
<!-- <div class="food-card">
<div class="food-card-image">
<img src="http://placehold.it/120x120&text=image3" alt="food">
</div>
<div class="food-card-info">
<h3>Foood namae</h3>
</div>
</div> -->
</div>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
I have separated your js file into two parts, one for home and one for favorite and put all of your code in window on load event :
index.js
var url = "https://www.themealdb.com/api/json/v1/1/search.php?s=";
function findFood(address, mealListEl) {
fetch(address)
.then(function (res) {
return res.json();
})
.then((data) => {
let html = "";
if (data.meals) {
data.meals.forEach((meal) => {
html += `<div class="food-card" data-id="${meal.idMeal}">
<div class="food-card-image">
<img src="${meal.strMealThumb}" alt="${meal.strMeal}" >
</div>
<div class="food-card-info">
<h3>${meal.strMeal}</h3>
</div>
<div class="food-card-features">
<button id="favorites" value="favour">Add</button>
<button id="get-details" value="details" >Details</button>
</div>
</div>`;
});
}
mealListEl.innerHTML = html;
});
}
function handleGetDetailsOrAddToFavorites(e) {
e.preventDefault();
if (e.target.value == "details") {
let mealItem = e.target.parentElement.parentElement;
fetch(
`https://www.themealdb.com/api/json/v1/1/lookup.php?i=${mealItem.dataset.id}`
)
.then((res) => res.json())
.then((data) => {
mealRecipeModal(data.meals);
});
} else if (e.target.value == "favour") {
let mealItem = e.target.parentElement.parentElement;
fetch(
`https://www.themealdb.com/api/json/v1/1/lookup.php?i=${mealItem.dataset.id}`
)
.then(function (res) {
return res.json();
})
.then((data) => {
window.localStorage.setItem(
mealItem.dataset.id,
JSON.stringify(data.meals)
);
});
}
}
function mealRecipeModal(meal) {
const destination = meal[0].strSource;
window.open(`${destination}`);
}
window.onload = function () {
const mealListEl = document.getElementById("list-Items-container");
function handleSubmitForm(e) {
e.preventDefault();
let input = document.querySelector("input");
findFood(url + input.value, mealListEl);
input.value = "";
}
document.querySelector("form").addEventListener("submit", handleSubmitForm);
mealList.addEventListener("click", handleGetDetailsOrAddToFavorites);
};
favorite.js:
var urlId = "https://www.themealdb.com/api/json/v1/1/lookup.php?i="; //search by id
function handleRemoveFavorites(e) {
e.preventDefault();
console.log(e.target.value);
}
function findFoodFavorite(address, mealListFavoritesEl) {
var html1 = "";
fetch(address)
.then((res) => res.json())
.then((data) => {
if (data.meals) {
data.meals.forEach((meal) => {
html1 += `<div class="food-card" data-id="${meal.idMeal}">
<div class="food-card-image">
<img src="${meal.strMealThumb}" alt="${meal.strMeal}" >
</div>
<div class="food-card-info">
<h3>${meal.strMeal}</h3>
</div>
<div class="food-card-features">
<button id="favorites" value="defavour" >Remove</button>
<button id="get-details" value="details" >Details</button>
</div>
</div>`;
});
}
mealListFavoritesEl.innerHTML += html1;
});
}
window.onload = function () {
const mealListFavoritesEl = document.getElementById(
"list-Items-container-favorites"
);
function renderFavorites() {
const urlArray = [];
for (var i = 0; i < localStorage.length; i++) {
urlArray.push(Object.entries(localStorage)[i][0]);
}
urlArray.forEach((id) => findFoodFavorite(urlId + id, mealListFavoritesEl));
}
mealListFavoritesEl.addEventListener("click", handleRemoveFavorites);
renderFavorites();
};
home.html:
</head>
<body>
<header>
<div class="topnav">
<a class="active" href="home.html">Home</a>
Favorites
Details
About
</div>
</header>
<div class="Heading">
<h1>The FoodAPP</h1>
</div>
<div class="form-container">
<form action="submit" method="get">
<input type="text" id="inputText" placeholder="Enter dish...">
<button id="btn" type="submit">Find</button>
</form>
</div>
<div id="list-Items-container">
</div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
favorite.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="styles.css" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=M+PLUS+2:wght#200&family=Poppins:ital,wght#0,100;1,200&display=swap"
rel="stylesheet"
/>
<title>Meals App | Favaorites</title>
</head>
<body>
<header>
<div class="topnav">
<a class="active" href="home.html">Home</a>
Favorites
Details
About
</div>
</header>
<div id="list-Items-container-favorites">
</div>
<script type="text/javascript" src="favorite.js"></script>
</body>
</html>
I can successfully add div to my ".list-group" div and localstorage, they work dynamically. But these elements do not appear to be offspring of its container. If you try it in your own browser, you will see that it returns a null value. Why don't my list items appear as kids? And how can I make it appear Child. Thank's adavance for your answers. Codepen: https://codepen.io/BerkayAkgurgen/pen/xxEmQLo
const form = document.querySelector("#todo-form");
const todoInput = document.querySelector("#todo");
const todoList = document.querySelector(".list-group");
const firstCardBody = document.querySelectorAll(".card-body")[0];
const secondCardBody = document.querySelectorAll(".card-body")[1];
const filter = document.querySelector("#filter");
const clearButton = document.querySelector("#clear-todos");
let alert = document.getElementById("alertID");
eventListeners();
console.log(todoList.firstElementChild);
//Event Listeners
function eventListeners() {
secondCardBody.addEventListener("click", deleteTodo);
form.addEventListener("submit", addTodo);
document.addEventListener("DOMContentLoaded", loadAllTodosToUI);
filter.addEventListener("keyup", filterTodos);
clearButton.addEventListener("click",clearAllTodos);
}
// Todo Ekleme
function addTodo(e) {
const newTodo = todoInput.value.trim();
if (newTodo === "") {
showAlert("danger", "Lütfen bir todo giriniz");
} else {
showAlert("success", "Giriş Başarılı");
addTodoToUI(newTodo);
addTodoToStorage(newTodo);
}
e.preventDefault();
}
function addTodoToUI(newTodo) {
const listItem = document.createElement("li");
const link = document.createElement("a");
link.href = "#";
link.className = "delete-item";
link.innerHTML = " <i class = 'fa fa-remove'></i>";
listItem.className = "list-group-item d-flex justify-content-between";
listItem.appendChild(document.createTextNode(newTodo));
listItem.appendChild(link);
todoList.appendChild(listItem);
todoInput.value = "";
}
// Alert
function showAlert(type, message) {
let = alert;
if (alert == null) {
alert = document.createElement("div");
alert.className = `alert alert-${type}`;
alert.id = "alertID";
alert.textContent = message;
firstCardBody.appendChild(alert);
alert.style.marginTop = "1rem";
} else {
alert.className = `alert alert-${type}`;
alert.textContent = message;
document.getElementById("alertID").style.display = 'block';
}
setTimeout (function myFunction2() {
document.getElementById("alertID").style.display = 'none';
}, 1000)
};
// Todo Storage Ekleme
function addTodoToStorage(newTodo) {
let todos = getTodosFromStorage();
todos.push(newTodo);
localStorage.setItem("todos", JSON.stringify(todos));
}
function getTodosFromStorage() { // Storage'den Todoları Almak
let todos;
if (localStorage.getItem("todos") === null) {
todos = [];
} else {
todos = JSON.parse(localStorage.getItem("todos"));
}
return todos;
}
// Sayfa Yüklendiğinde Storage Yükleme
function loadAllTodosToUI() {
let todos = getTodosFromStorage();
todos.forEach(function (todo) {
addTodoToUI(todo);
})
}
// Todo Silme
function deleteTodo(e) {
if (e.target.className === "fa fa-remove") {
e.target.parentElement.parentElement.remove();
}
}
// Todo Filtreleme
function filterTodos(e) {
const filterValue = e.target.value.toLowerCase();
const listItems = document.querySelectorAll(".list-group-item");
listItems.forEach(function (listItem) {
const text = listItem.textContent.toLowerCase();
if (text.indexOf(filterValue) === -1) {
// Bulamadı
listItem.setAttribute("style", "display : none !important");
} else {
listItem.setAttribute("style", "display : block");
}
});
}
// Tüm Todoları Silme
function clearAllTodos(e) {
if (confirm("Tümünü Silmek istediğinize Emin Misiniz?")) {
// Arayüzden Todoları Temizleme
// todoList.innerHTML = ""; // Yavaş Yöntem
}
}
console.log(todoList.firstElementChild);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
<link rel="stylesheet" href="berkay.css">
<title>Todo List</title>
</head>
<body>
<div class="container" id="bal" style="margin-top: 20px">
<div class="card row">
<div class="card-header">Todo List</div>
<div class="card-body bdy">
<form id="todo-form" name="form">
<div class="form-row">
<div class="form-group col-md-6">
<input class="form-control" type="text" name="todo" id="todo" placeholder="Bir Todo Girin"
autocomplete="off" tabindex="1" />
</div>
</div>
<button type="submit" class="btn btn-danger">Todo Ekleyin</button>
</form>
<!-- <div class="alert alert-danger" role="alert">
This is a danger alert—check it out!
</div> -->
</div>
<div class="card-body body">
<hr />
<h5 class="card-title" id="tasks-title">Todolar</h5>
<div class="form-row">
<div class="form-group col-md-6">
<input class="form-control" type="text" name="filter" id="filter" placeholder="Bir Todo Arayın"
tabindex="2" />
</div>
</div>
<hr />
<ul class="list-group"></ul>
<hr />
<a id="clear-todos" class="btn btn-dark" href="#">Tüm Taskları Temizleyin</a>
</div>
</div>
</div>
<div class="box" style="display: none;"></div>
<div class="box2" style="display: none;"></div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous">
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous">
</script>
<script src="berkay.js"></script>
</body>
</html>
when I click on the "Todo Ekleyin" button, I get a warning. However, I would like this alert to appear only once per press, not multiple times, and can be pressed again after the alert disappears. How can I achieve this and?
Thank you in advance for your answer, good work. (If there is a method other than the method you suggested, I would be glad if you can write its name.)
// Tüm Elementleri Seçme
const form = document.querySelector("#todo-form");
const todoInput = document.querySelector("#todo");
const todoList = document.querySelector(".list-group");
const firstCardBody = document.querySelectorAll(".card-body")[0];
const secondCardBody = document.querySelectorAll(".card-body")[1];
const filter = document.querySelector("#filter");
const clearButton = document.querySelector("#clear-todos");
eventListeners();
function eventListeners() { // Tüm Event Listenerlar
form.addEventListener("submit", addTodo);
}
function addTodo(e) {
const newTodo = todoInput.value.trim();
if (newTodo === "") { // Alarm Verme
showAlert("danger","Lütfen Bir Todo Giriniz");
}
else {
addTodoToUI(newTodo);
}
addTodoToUI(newTodo);
e.preventDefault();
}
function showAlert(type,message){
const alert = document.createElement("div");
alert.className = `alert alert-${type}`;
alert.textContent = message;
firstCardBody.appendChild(alert);
//setTimeout
setTimeout(function(){
alert.remove();
}, 1000);
}
function addTodoToUI(newTodo) { // String Değerini List Item olarak Ekleyecek.
// List Item Oluşturma.
const listItem = document.createElement("li");
// Link Oluşturma
const link = document.createElement("a");
link.href = "#";
link.className = "delete-item";
link.innerHTML = "<i class = 'fa fa-remove'></i>";
listItem.className = "list-group-item d-flex justify-content-between";
// Text Node
listItem.appendChild(document.createTextNode(newTodo));
listItem.appendChild(link);
// Todo List'e List Item'ı Ekleme
todoList.appendChild(listItem);
// Ekleme Sonrası Input'tan yazı Silme
todoInput.value = "";
}
// Todo Ekleme Bilgi Mesajı
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
<title>Todo List</title>
</head>
<body>
<div class="container" style="margin-top: 20px">
<div class="card row">
<div class="card-header">Todo List</div>
<div class="card-body">
<form id="todo-form" name="form">
<div class="form-row">
<div class="form-group col-md-6">
<input class="form-control" type="text" name="todo" id="todo"
placeholder="Bir Todo Girin" />
</div>
</div>
<button type="submit" class="btn btn-danger">Todo Ekleyin</button>
</form>
<hr />
<!-- <div class="alert alert-danger" role="alert">
This is a danger alert—check it out!
</div> -->
</div>
<div class="card-body">
<hr />
<h5 class="card-title" id="tasks-title">Todolar</h5>
<div class="form-row">
<div class="form-group col-md-6">
<input class="form-control" type="text" name="filter" id="filter"
placeholder="Bir Todo Arayın" />
</div>
</div>
<hr />
<ul class="list-group">
<!-- <li class="list-group-item d-flex justify-content-between">
Todo 1
<a href = "#" class ="delete-item">
<i class = "fa fa-remove"></i>
</a>
</li>-->
</ul>
<hr />
<a id="clear-todos" class="btn btn-dark" href="#">Tüm Taskları Temizleyin</a>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous">
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous">
</script>
<script src="berkay.js"></script>
</body>
</html>
You can put an integer in your alert function and every using array increase a one more.
For example, if you want after 5 times don't show alert.
var a = 0;
var b = true;
if (newTodo === "" || b) { // Alarm Verme
showAlert("danger","Please Give me a Todo!");
a++;
if(a == 5 ){
b = false;
}
}