How to prevent this warning message from revealing multiple times - javascript

As you can see in the image, the warning shows up whenever I trigger the click eventListener, naturally. But how can I make it show up only once. Thanks in advance.
function eventListeners() {
form.addEventListener("submit", addTodo)
}
function showAlert(type, message) {
const alert = document.createElement("div")
alert.className = `alert alert-${type} d-inline p-1`
alert.setAttribute("style", "border-radius: 2rem")
alert.textContent = message
form.appendChild(alert)
setTimeout(function () {
alert.remove()
}, 1000)
}

// Not a good solution.
Try this :
let isAlertBeingShown = false
function eventListeners() {
form.addEventListener("submit", addTodo)
}
function showAlert(type, message) {
if( isAlertBeingShown ) {
//Do not show alert. Simply return.
return;
// or you can do alert.remove here instead of return.
}
const alert = document.createElement("div")
alert.className = `alert alert-${type} d-inline p-1`
alert.setAttribute("style", "border-radius: 2rem")
alert.textContent = message
form.appendChild(alert);
isAlertBeingShown = true;
setTimeout(function () {
alert.remove();
isAlertBeingShown = false;
}, 1000)
}

Note: Instead of creating div and adding to form and then removing it again and again you can just add single div with id message in html for message and hide it using its css display property to none and then use javascript function to change message in div and show/hide it.
let alert = document.querySelector('#message');
function showAlert(type, message) {
alert.textContent = message;
alert.display = 'block';
setTimeout(function () {
alert.display = 'none';
alert.textContent = '';
}, 1000)
}

Related

push is not a function javascript

I am new in JavaScript. I wrote function to save data to local storage, but every time I try to save a data,it doesnt work and it always get this error: push is not a function.and this error just appears a second in console.log and dissappear by itself. apart from this my problem is it doesn't save the data to the local storage How can I fix this? (the function,not working is "addTodoToStorage"
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() {
form.addEventListener("submit",addTodo);
}
function addTodo(e) {
const newTodo = todoInput.value.trim();
if (newTodo === ""){
showAlert("danger","please type something");
}
else{
addTodoToUI(newTodo);
addTodoToStorage(newTodo);
showAlert("success","successfully added");
}
e.preventDefault();
}
function getTodosFromStorage() {
let todos;
if(localStorage.getItem("todos") === null){
todos = [];
}
else{
todos= JSON.parse(localStorage.getItem("todos"));
}
return todos;
}
function addTodoToStorage(newTodo) {
let todos = getTodosFromStorage();
todos.push(newTodo);
localStorage.setItem("todos",JSON.stringify(todos));
}
function showAlert(type,message) {
const alert = document.createElement("div");
alert.className= `alert alert-${type}`;
alert.textContent= message;
firstCardBody.appendChild(alert);
//set time out
setTimeout(function () {
alert.remove();
},2000);
}
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 = "";
}
As for the error msg disappearing after a while, it's because you haven't prevented the default behavior of the form. Or rather, you have prevented it at the bottom, which is fine if you want the form to prevent GET-ing(its default method) to the URL(in action attribute).
But if an error occurs inside the submit handler (in your case, it probably does), the JavaScript stops the execution, and the form continues its default behavior, because there's is nothing to tell it that it can't do that. It can, so it will. HTML forms be ratchet like that. Due to which the page reloads.
For the part why there's an error, I couldn't find any errors here. If this is the same code you're using, there shouldn't be a problem.
EDIT
I tried to reproduce your example as follows and it works. It adds items to my localStorage successfully.
<form id="todo-form">
<input id="todo" type="text" />
</form>
<script>
const form =document.querySelector("#todo-form");
const todoInput = document.querySelector("#todo");
eventListeners();
function eventListeners() {
form.addEventListener("submit",addTodo);
}
function addTodo(e) {
e.preventDefault();
const newTodo = todoInput.value.trim();
if (newTodo === ""){
showAlert("danger","please type something");
}
else{
addTodoToStorage(newTodo);
showAlert("success","successfully added");
}
}
function getTodosFromStorage() {
let todos;
if(localStorage.getItem("todos") === null){
todos = [];
}
else{
todos= JSON.parse(localStorage.getItem("todos"));
}
return todos;
}
function addTodoToStorage(newTodo) {
let todos = getTodosFromStorage();
todos.push(newTodo);
localStorage.setItem("todos",JSON.stringify(todos));
}
function showAlert(type,message) {
const alert = document.createElement("div");
alert.className = `alert alert-${type}`;
alert.textContent = message;
document.body.appendChild(alert);
//set time out
setTimeout(function () {
alert.remove();
}, 2000);
}
</script>

disclose the alert button using javascript

In my project, I've added the alert box and try to close the box if the user clicks on disclose button. But I don't know why this if condition is not executed.
can anyone tells me where I did make a mistake?
window.onload = function(){
var button = document.querySelector(".close");
var successMessage = document.querySelector(".messageStackSuccess");
var messageStack = document.querySelector(".messageStackError");
// console.log(successMessage.className);
button.onclick = function () {
if (messageStack.className == "messageStackError") {
messageStack.classList.add("displayNone");
}
else if (successMessage.className == "messageStackSuccess") {
successMessage.classList.add("displayNone");
}
};
};

How to prevent modal event listener from affecting other items?

I'm currently working on a Library app where a user can track unread and read books. I have it setup where when you click a book a modal pops up with the title, author, and buttons allowing you to mark the book as read or completely delete it.
I'm trying to fix a problem where opening and closing more than one modal and then clicking the delete button will delete all the items you previously clicked.
Here's the delete function -
Book.prototype.delete = function() {
myLibrary = myLibrary.filter((e) => {
return e !== this;
});
};
Here's how I'm opening each modal -
const render = () => {
const booksUnreadList = document.getElementById('unread');
const booksReadList = document.getElementById('read');
booksUnreadList.innerHTML = 'Unread';
booksReadList.innerHTML = 'Read';
myLibrary.forEach((book) => {
const li = document.createElement('li');
li.className = 'book';
book.read === 'Read'
? booksReadList.appendChild(li)
: booksUnreadList.appendChild(li);
li.innerHTML = book.info();
li.addEventListener('click', function handler() {
openBookModal(book);
});
});
And then the modal itself -
function openBookModal(book) {
document
.getElementById('book-modal-mark-complete')
.removeEventListener('click', markReadHandler);
document
.getElementById('book-modal-delete')
.removeEventListener('click', deleteHandler);
bookForm.style.display = 'none';
toggleForm.style.backgroundColor = '#978de0';
toggleForm.innerHTML = 'Add Book';
const bookModal = document.getElementById('book-modal');
bookModal.style.display = 'grid';
document.getElementById('book-modal-title').innerHTML = book.title;
document.getElementById('book-modal-author').innerHTML = 'By ' + book.author;
document
.getElementById('book-modal-mark-complete')
.addEventListener('click', markReadHandler);
function markReadHandler() {
book.read = 'Read';
render();
bookModal.style.display = 'none';
}
document
.getElementById('book-modal-delete')
.addEventListener('click', deleteHandler);
function deleteHandler() {
book.delete();
render();
bookModal.style.display = 'none';
}
document.getElementById('book-modal-close').addEventListener('click', () => {
bookModal.style.display = 'none';
});
}
Here's a jsfiddle of everything, to recreate the problem just open and close 2+ books and then delete 1 of them.
https://jsfiddle.net/Spawn_Bot/w6j4b8Lh/4/
Thanks!
You could store the currently selected book in the currentBook variable, move the modal event handlers outside the openBookModal() function and in the event handlers you could delete the currentBook:
let currentBook = {};
...
function openBookModal(book) {
currentBook = book;
...
}
document
.getElementById('book-modal-mark-complete')
.addEventListener('click', markReadHandler);
function markReadHandler() {
currentBook.read = 'Read';
render();
bookModal.style.display = 'none';
}
document
.getElementById('book-modal-delete')
.addEventListener('click', deleteHandler);
function deleteHandler() {
currentBook.delete();
render();
bookModal.style.display = 'none';
}
Here's the demo: https://jsfiddle.net/k6z08m2q/

dynamically create element with onclick

I'm obviously missing something, but I haven't been able to find what I am doing wrong and I have been staring at this for entirely too long
function message(options) {
...
options.onclose = options.onclose || null;
...
this.gui = document.createElement('div');
this.msg = document.createElement('div');
...
if (options.onclose != null) {
var close = document.createElement('i');
close.innerHTML = 'close';
close.className = 'material-icons close';
close.onclick = options.onclose;
console.log(close.onclick);
this.msg.append(close);
}
this.msg.innerHTML += options.msg;
this.gui.append(this.msg);
...
return this.gui;
}
msgContainer.append(new message({
class: 'update',
sticky: true,
icon: 'mic',
msg: 'You are in a call',
onclose: () => { console.log('click'); }
}));
from the developer console document.querySelector('.close').onclick is null, but if I add an on click document.querySelector('.close').onclick = () => { console.log('click'); }; it works?
Why it wont work is because on click is a function:
document.querySelector('.close').onclick
doesn't do anything so why call it.
document.querySelector('.close').onclick = () {
alert("did something");
}
so the real question is what do you want to do when clicked? create a new link or div.. look below. I would start using jQuery.
jQuery answer:
$(document).ready(function(){
$(".myclass").click(function(){
$(".container_div").append("<a href='test.php'>test link</a>");
// also .prepend, .html are good too
});
});
Here is working example. I changed your code a little bit. You can add more events by passing it to an array. I used addEventListener.
var msgContainer = document.getElementById('msgContainer');
function message(options) {
options.onclose = options.onclose || null;
this.gui = document.createElement('div');
this.msg = document.createElement('div');
if (options.onclose != null) {
var close = document.createElement('i');
close.innerHTML = 'closepp';
close.className = 'material-icons close';
close.dataset.action = 'close';
this.msg.append(close);
}
this.msg.innerHTML += options.msg;
this.gui.append(this.msg);
// Create listeners dynamically later on
events = [
{ selector: close.dataset.action, eventType: 'click', event: options.onclose }
];
renderElement(this.gui, events);
}
function renderElement(element, events) {
msgContainer.append(element);
for (i = 0; i < events.length; i++) {
var currentEvent = events[i];
var selector = element.querySelector('[data-action="' + currentEvent['selector'] + '"]');
selector.addEventListener(currentEvent['eventType'], currentEvent['event'].bind(this), false);
}
}
new message({
class: 'update',
sticky: true,
icon: 'mic',
msg: 'You are in a call',
onclose: () => { console.log('click'); }
});
<div id="msgContainer">
</div>
I finally figured it out! setting innerHTML makes chrome rebuild the dom and in the process it loses the onclick event, onclick works fine if I use textContent instead of innerHTML. In the below example if you comment out the last line of JS the onclick works, here's the same thing in jsFiddle
var blah = document.getElementById('blah');
var div = document.createElement('button');
div.style['background-color'] = 'black';
div.style.padding = '20px;';
div.style.innerHTML = 'a';
div.onclick = () => { alert('wtf');};
blah.appendChild(div);
// Uncomment this to make onclick stop working
blah.innerHTML += ' this is the culprit';
<div id="blah">
</div>

Javascript onclick() show and onclick() hide

I wanted to make a function with onclick where if I press the div the content should be displayed. If I click on that content it will give me the "starting"-form.
Let me show you the code:
HTML:
<div id="demo">click</div>
Javascript:
var div = document.getElementById("demo");
var info = "This is the information for the user.";
var status = true;
if(status){
div.onclick = function() { div.innerHTML = info };
status=false;
}
else {
div.onclick = function() { div.innerHTML = "click" };
status=true;
}
So I made a variable status that checks what is being shown.
I hope i could express myself good enough. :)
The if statement is not going to magically run again. You need to do the check inside the click. Do not try to bind separate click events.
(function () {
var div = document.getElementById("demo");
var info = "This is the information for the user.";
var status = false;
div.addEventListener("click", function() {
status = !status;
div.innerHTML = status ? info : "click";
});
}());
<div id="demo">click</div>

Categories

Resources