Does anyone know why this code is not working the way I want it to? - javascript

I am creating a web app with node.js, express and pug templates and here I am trying to simulate a warning when the user tries to remove a review he has posted.
so, in the front end I have a button that the user clicks to remove his review
when the user clicks that button I run
index.js
import { showWarning } from './warning';
const removerStoreReviewBtn = document.querySelector('.side-nav__removeStoreReviewbtn');
if (removerStoreReviewBtn)
removerStoreReviewBtn.addEventListener('click', e => {
e.preventDefault();
showWarning('Would you like to remove this review ?');
});
warning.js
export const hideWarning = () => {
const el = document.querySelector('.warning');
const warningText = document.querySelector('.warning__text');
if (el) el.parentElement.removeChild(el);
if (warningText) warningText.parentElement.removeChild(warningText);
};
export const showWarning = (msg, time = 30) => {
hideWarning();
console.log(msg);
const markUp = `
<div class="warning">
<div class="warning__text">${msg}</div>
<button class="warning--no">
<span>Cancelar</span>
</button>
<button class="warning--yes">
<span>Apagar</span>
</button>
</div>`;
document.querySelector('.header').insertAdjacentHTML('afterend', markUp);
window.setTimeout(hideWarning, time * 1000);
};
The showWarning function display everything the way I want in the front end
then back at the index.js file I have the following code
index.js
const warningBtnYes = document.querySelector('.warning--yes');
const warningBtnNo = document.querySelector('.warning--no');
if (warningBtnYes)
warningBtnYes.addEventListener('click', e => {
e.preventDefault();
console.log('remove');
//removerStoreReview(reviewId);
});
if (warningBtnNo)
warningBtnNo.addEventListener('click', e => {
e.preventDefault();
console.log('Do not remove');
});
when I click any of these buttons nothing happens (I am expecting the console.logs) and I can't figure out why nothing happens, hopefully anyone can help me.
Thanks
Mateus

When you use .parentElement.removeChild() you have turned off all event listeners for those button.
You have two options. You can preserve the event listeners by storing the return value from the .removeChild() call. In order to restore the event listeners you will need to reuse the stored (previously removed) node.
Alternatively, you'll need to re-add your event listeners after inserting the new HTML.
Helpful docs

Related

Adding an Event Listener for Uploading a File that 'Fires' every time

I am trying to upload an excel file to my react app. I am using an event listener but it is only "picking up" the data the first time I upload a file. For example, I start my local server and then upload a file, test1.xlsx this works correctly. I then upload a second file, test2.xlsx. This also works. However, now if I try to upload either test1.xslx or test2.xlsx. Nothing will appear in the console. My code is as follows:
const input = document.getElementById('input-data')
if(input){
input.addEventListener('change', () => {
var data = [];
readXlsxFile(input.files[0]).then((rows) => {
data.push(rows)
})
console.log(data)
})
}
I am fairly new to all this so I am not sure if there is an event listener other than 'change' that would be better or if it is something to due with how the browser is storing the data. Let me know!
I've had success with this (only showing skeleton, but using this structure to load images):
<input onInput={onSelectFile} type="file" ... />
and
const onSelectFile = (e) => {
const onLoadFn = (dataURL) => {
// processing goes here, maybe something like
setImage(dataURL);
};
if (e.target.files && e.target.files.length > 0) {
const reader = new FileReader();
reader.addEventListener("load", () => onLoadFn(reader.result));
reader.readAsDataURL(e.target.files[0]);
// setState etc could go here, something like
setDialogOpen(true);
}
};

addEventListener not working on document.createElement elements

I'm trying to build a simple signup form that does some basic validation on the username, including checking whether a given user name is taken and if so, a list of suggested usernames. A problem that I ran into was that the dynamically generated list of suggestions (anchor tags) won't take an event listener for some reason. Here is the sample code of this.
singup.html
<script type="module">
import { check_username } from './signup.js';
const username_input = document.getElementById('id_username');
username_input.addEventListener('change', (event) => {
check_username(event, check_url);
}, false);
</script>
signup.js
export const check_username = async (event, url) => {
...
// check username with server
if (!data.unique) {
error_flag = true;
error_p.innerHTML = 'Username taken, please consider:<br>';
for (let name of data.suggestions) {
let child_elem = document.createElement('a');
child_elem.innerHTML = `${name}`;
error_p.appendChild(child_elem);
error_p.innerHTML += ' ';
child_elem.addEventListener('click', clickHandler, false);
}
}
}
According to some other posts, I tried adding the event listener both before and after the element has been added, i.e. before and after calling appendChild, but neither worked. Curiously, I tried adding the event listener in the browser console, and that worked like a charm. I ended up resolving this by adding the event listener to the body and checking whether the event.target is the element in question, but I'm curious to know why my initial approach didn't work to get a better understanding of things.
Setting the innerHTML of error_p replaces the content including all elements with their event handlers. Just insert a text node instead of a space with inner html
for (let name of data.suggestions) {
let child_elem = document.createElement('a');
child_elem.innerHTML = `${name}`;
error_p.appendChild(child_elem);
error_p.appendChild(document.createTextNode(' '));
child_elem.addEventListener('click', clickHandler, false);
}

Javascript - Fetch request happening after it supposed

I'm still new to javascript, I have this javascript problem from CS50 that is supposed to open a mailbox and clicking on an email is supposed to open the email. I think my on click part of the problem is right, but when I open my page and click on an email it doesnt call the open_mail() function.
I've solved that the problem is that the load_mailbox function for being asynchronous is beign called after the DOM finishes to load, so technically theres no div with the class email-box when the DOM finishes to load, but i don't know how to solve this problem, can someone help please.
document.addEventListener('DOMContentLoaded', function() {
// Use buttons to toggle between views
document.querySelector('#inbox').addEventListener('click', () => load_mailbox('inbox'));
document.querySelector('#sent').addEventListener('click', () => load_mailbox('sent'));
document.querySelector('#archived').addEventListener('click', () => load_mailbox('archive'));
document.querySelector('#compose').addEventListener('click', compose_email);
document.querySelector('#compose-form').addEventListener('submit', send_mail);
document.querySelectorAll('.email-box').forEach(function(box) {
box.addEventListener('click', function (){
open_mail();
})
});
// By default, load the inbox
load_mailbox('inbox');
});
function load_mailbox(mailbox) {
fetch(`/emails/${mailbox}`)
.then(response => response.json())
.then(emails => {
document.querySelector('#email-content').innerHTML = "";
emails.forEach(inbox_mail);
})
};
function inbox_mail(email) {
const element = document.createElement('div');
if (document.querySelector(`#email-${email.id}`) === null) {
element.id = (`email-${email.id}`);
element.className = ("email-box");
element.innerHTML = `<p>From ${email.sender}</p><p>${email.subject}</p><p>At ${email.timestamp}
</p>`;
document.querySelector('#email-content').append(element);
}
}
I´d say the easiest solution would be to put the addEventListener to a point after the elements with class .email-box are created, e.g in your .then function after inbox_mail ran for each email
.then(emails => {
document.querySelector('#email-content').innerHTML = "";
emails.forEach(inbox_mail);
document.querySelectorAll('.email-box').forEach(function(box) {
box.addEventListener('click', function (){
open_mail();
});
});
});
DOMContentLoaded will trigger when the DOM from the initial request/response was loaded. What you are doing in your fetch callback is called "DOM-Manipulation" as you create elements and append them to the DOM that has already been loaded.

My Buttons are not working after using fetch api along with express.js

I have strange problem with buttons that are requesting for displaying templates on client page.
This is client side code. The main task of entire class is to just enable user to click button, send request and get response with HTML that has been rendered from handlebars template and just paste it in partiuclar place on client side. It works, but only once. After first click and displaying elements, I totally lose any interaction with those buttons. There is no request, and there is no even EventListener for clicking. I get no error. Completely there is no single reaction after clicking.
class Weapons {
constructor() {
this.buttons = document.querySelectorAll('.type')
}
async displayWeapon(path) {
const container = document.querySelector('.shop-container')
await fetch(`weapons/${path}`).then(response => response.json()).then(data => container.innerHTML += data);
}
chooseWeapon() {
this.buttons.forEach(btn => {
btn.addEventListener('click', (e) => {
console.log('click');
let weaponType = e.target.dataset.type
switch (weaponType) {
case 'pistols':
console.log('click');
return this.displayWeapon(weaponType)
case 'rifles':
console.log('click');
return this.displayWeapon(weaponType)
case 'grenades':
console.log('click');
return this.displayWeapon(weaponType)
case 'closerange':
console.log('click');
return this.displayWeapon(weaponType)
case 'rocketlauchner':
console.log('click');
return this.displayWeapon(weaponType)
}
})
})
}
}
document.addEventListener('DOMContentLoaded', function () {
const weapons = new Weapons();
weapons.chooseWeapon();
> When I invoke displayWeapon(path) here it also works, but immidiately
> after displaying html elements clicking on buttons again does not
> initiate any action.
})
Here is app.get function but I doubt it's source of problem.
app.get('/weapons/:id', (req, res) => {
console.log('req');
console.log(req.url);
let type = req.params.id;
res.render(type, function (err, html) {
res.json(html);
})
})
Ok. The answer is actually simple. In fetch function container.innerHTML += data. This line deletes my html with buttons, and the same time it deletes eventListeners. So I need just to modify my html.

Event Listener not working in cookie modal

first time caller here, please be gentle..
I am in the process of my JavaScript reflection and having a problem with the cookie modal. You need to be able to have the cookie pop up upon entering the site, the user needs to click ok, it is stored locally, and doesn't pop up if the user refreshes the browser.
I have created a basic modal and written the JavaScript, which partly works, but the eventHandler isn't working.
The cookie value is false, which you can see in the console, but when you click the button, it doesn't turn to true.
I have put the code below and if anyone could help I'd really appreciate it.
<div id ="overlay">
<div class="modal">
<p>
</p>
</div>
<button class="settings_button">CHANGE SETTINGS</button>
<button class="modal_accept_button">ACCEPT COOKIES</button>
<button class="modal_accept_button">Accept</button>
</div>
let modalObject = document.querySelector(".modal");
let modalSettings = document.querySelector('.settings_button');
let modalAccept = document.querySelector('.modal_accept_button');
let modalOverlay = document.querySelector("#overlay");
function showModal() {
modalObject.classList.remove('deactive');
modalOverlay.classList.remove('deactive');
}
function disableModal() {
modalObject.classList.add('deactive');
modalOverlay.classList.add('deactive');
}
localStorage.setItem('cookie', 'false');
window.addEventListener('DOMContentLoaded', () => {
if (localStorage.getItem('cookie') == 'true') {
console.log("Cookie is already in place.");
} else if (localStorage.getItem('cookie') === null ||
localStorage.getItem("Cookie accepted") == 'false') {
console.log("Cookie has been not yet been accepted.");
showModal();
modalAccept.addEventListener('click', () => {
localStorage.setItem('cookie','true');
disableModal() ;
});
}
});
You have localStorage.setItem('cookie', 'false'); in your code and this changes your ls to false every time that your codes run, just remove it and I think it's better if you save your local storage in a variable then use that variable in your if statement:
const modal = document.querySelector('.modal');
const acceptBtn = document.querySelector('#acceptCookies');
(() => {
const isCookieAccepted = JSON.parse(window.localStorage.getItem('cookie'));
if (isCookieAccepted) {
alert(`Cookie status: ${isCookieAccepted}`)
} else {
modal.classList.add('show')
}
})();
acceptBtn.addEventListener('click', () => {
window.localStorage.setItem('cookie', true);
modal.classList.remove('show')
})
In your code, you have a line that sets it to false:
localStorage.setItem('cookie', 'false');
This will always set it to false every time you go to that page. So even if you set it to true, when you refresh it will be back to false again.
Removing that line should work, as you dont need to set it to false

Categories

Resources