Remove event before when run child event - javascript

In this example, when I click button so has two alert, how remove event divExamp when click button and just has one alert.
<button id="abc">sdfsdfsdf</button>
<div id="example">zczczxczxc</div>
<script>
let divExamp = document.querySelector('#example');
document.querySelector('#abc').addEventListener('click', async e =>{
divExamp.insertAdjacentHTML('beforeend', '<button id="click">click</button>');
document.querySelector('#click').addEventListener('click', async e =>{
alert('click!');
})
})
</script>

let divExamp = document.querySelector('#example');
let abc = document.querySelector('#abc');
abc.addEventListener('click', temp);
function temp(e) {
abc.removeEventListener('click', temp);
divExamp.insertAdjacentHTML('beforeend', '<button id="click">click</button>');
document.querySelector('#click').addEventListener('click', e => {
alert('click!');
});
}
<button id="abc">sdfsdfsdf</button>
<div id="example">zczczxczxc</div>

Related

Event listener not working after elements are rendered in the dom

I am creating a project that when I click a certain category card I get the id of that category and redirect to movies screen.
I am aware that the row.eventlistener() in index.js it will be executed before the elements are rendered and that is why it does not pick the id. How should I add the event listener to each newly rendered item before adding it to the container so that I can get the id for each category card.
index.js
async function getCategories() {
let url = 'http://localhost:8080/movieCategories';
try {
let res = await fetch(url);
return await res.json();
} catch (error) {
console.log(error);
}
}
async function renderCategories() {
let categories = await getCategories();
let html = '';
categories.forEach(category => {
let htmlSegment = `
<div class="category-card" id=${category.id}>
<img src="./assets/images/sci-fi.jpg" alt="" class="card-img">
<div class="name">${category.name}</div>
</div>
`;
html += htmlSegment;
});
let container = document.querySelector('.category-grid');
container.innerHTML = html;
}
renderCategories();
document.querySelectorAll('div.category-card').forEach(row=>{
row.addEventListener('click',event=>{
console.log('Category clicked', event.currentTarget.id)
window.location= 'movies.html?categoryId=' +event.currentTarget.id;
});
});
index.html
<section class="category" >
<h2 class="section-heading">Category</h2>
<div class="category-grid">
</div>
</section>
You could also just add the event on the div itself directly when you create it and pass the id or whatever you want.
<div class="category-card" id=${category.id} onclick="onCatClick(${category.id})">
After this, you can move your logic inside a top level onCatClick function.
function onCatClick(id) {
console.log('Category clicked', id)
window.location= 'movies.html?categoryId=' + id;
}
This is if your styling/layout doesn't allow you to use an anchor element. Otherwise, you could simply replace the div with an anchor element:
You are not awaiting the call to renderCategories, move your event listener logic inside the renderCategories method OR You could use an immediately invoked async function expression or IIAFE for short, more about this here immediately-invoked-async-function-expression:
(async () => {
await renderCategories();
document.querySelectorAll('div.category-card').forEach(row => {
row.addEventListener('click', event => {
console.log('Category clicked', event.currentTarget.id)
window.location= 'movies.html?categoryId=' +event.currentTarget.id;
});
});
})();
try:
async function getCategories() {
let url = 'http://localhost:8080/movieCategories';
try {
let res = await fetch(url);
return await res.json();
} catch (error) {
console.log(error);
}
}
async function renderCategories() {
let categories = await getCategories();
let html = '';
categories.forEach(category => {
let htmlSegment = `
<div class="category-card" id=${category.id}>
<img src="./assets/images/sci-fi.jpg" alt="" class="card-img">
<div class="name">${category.name}</div>
</div>
`;
html += htmlSegment;
});
let container = document.querySelector('.category-grid');
container.innerHTML = html;
}
//es8
await renderCategories();
// fix timeout async render element
setTimeout(() => {
document.querySelectorAll('div.category-card').forEach(row=>{
row.addEventListener('click',event=>{
console.log('Category clicked', event.currentTarget.id)
window.location= 'movies.html?categoryId=' +event.currentTarget.id;
});
})
});

li element vanish after page reload

I am trying to add a li element in the below div (Functionality is to upload an attachment)
See below pic 1
My JavaScript functionality of Submit button adds the Li in the div perfectly fine. But, when I refresh the page it's gone.
<input type="file" id="real-file" hidden="hidden" />
<button type="button" id="custom-button">CHOOSE A FILE</button>
<span id="custom-text">No file chosen, yet.</span>
<button type="button" id="submit-button" onclick="Submit()">Submit</button>
<div id="collapseThree">
</div>
<script>
const realFileBtn = document.getElementById("real-file");
const customBtn = document.getElementById("custom-button");
const customTxt = document.getElementById("custom-text");
const submitBtn = document.getElementById("submit-button");
const slides = [];
var str = '';
customBtn.addEventListener("click", function() {
realFileBtn.click();
});
window.addEventListener('load', (event) => {
console.log(slides)
console.log('The page has fully loaded yo');
// document.getElementById("collapseThree").innerHTML
});
/* window.onload = document.getElementById("slideContainer").innerHTML
*/
function Submit() {
console.log("going in");
document.getElementById("collapseThree").innerHTML += str
}
realFileBtn.addEventListener("change", function() {
if (realFileBtn.value) {
customTxt.innerHTML = realFileBtn.value.match(
/[\/\\]([\w\d\s\.\-\(\)]+)$/
)[1];
console.log(customTxt.innerHTML)
slides.push(customTxt.innerHTML);
slides.forEach(function(slide) {
str = '<li>' + slide + '</li>';
});
console.log(arr)
console.log(slides)
} else {
customTxt.innerHTML = "No file chosen, yet.";
}
});
</script>
You can use localStorage to save and read data. Simply call
function getSlides() {
var slidesJson = localStorage.getItem('slides') || '[]';
return JSON.parse(slidesJson);
}
to get all current slides and
function setSlides(slides) {
localStorage.setItem('slides', JSON.stringify(slides))
}
to save the current state of the array.

why check is undefined in my code? 'pure js'

** I want when to click on the active button if the checkbox is checked to add filtered class in HTML element but it doesn't work and give me an undefined error in this line check.parentElement.classList.add("filtered"); **
<ul class="ul-list"></ul>
</section>
</main>
<footer class="footer">
<button class="all footer-btn">All</button>
<button class="active footer-btn">Active</button>
<button class="complete footer-btn">Complete</button>
</footer>
let check = document.querySelectorAll(".complete-txt");
let complete_btn = document.querySelector(".complete");
let active_btn = document.querySelector(".active");
let all_btn = document.querySelector(".all");
let edit_list = document.querySelector(".edit-list");
let main_text = document.querySelector(".main-text");
let list_item = document.querySelector(".list-item");
let footer = document.querySelector(".footer");
const generateTemplate = (todo) => {
const html = `
<li class="list-item">
<input type="checkbox" class="complete-txt" name="" id="check"><span class="main-text">${todo}</span><div class="edit-list"></div><div class="delete-list"></div>
</li>
`;
list.innerHTML += html;
};
// add todos event
addForm.addEventListener("submit", (e) => {
e.preventDefault();
const todo = addForm.add.value.trim();
if (todo.length) {
generateTemplate(todo);
addForm.reset();
}
});
active_btn.addEventListener("click", function () {
let check_id = document.querySelector(".complete-txt");
// check.forEach(function () {
debugger;
if (check.checked !== "true") {
check.parentElement.classList.add("filtered");
console.log("hi");
}
// });
// console.log("hi");
console.log("hi");
// console.log(check.checked.value);
});
if the larger document fixes all other inconcistencies you should be able to change the eventlistener to
active_btn.addEventListener("click", function () {
let check_id = document.querySelector(".complete-txt");
if (check_id.checked !== "true") {
check_id.parentElement.classList.add("filtered");
}
});
BUT!!! this will not "fix" all of your errors, like defining let check before the checkbox is created with generateTemplate

javascript - modal return value when close

I'm trying to make modal when i close it it will resolved/return a true value to make the timer continue and delete element if it isn't return false/reject, i don't know how to write it at all. I feel like i can make it somehow with Promise resolved and reject but i don't know how :( .
(to make the timer continue i need to set "timer.pause = false")
class MODAL{
constructor(){
this.modal_container = document.createElement("div")
this.modal_container.classList.add("modal")
document.querySelector("body").appendChild(this.modal_container)
this.overlay = document.createElement("div")
this.overlay.classList.add("overlay")
this.modal_container.appendChild(this.overlay)
this.content_container = document.createElement("div")
this.content_container.classList.add("modal-content")
this.modal_container.appendChild(this.content_container)
this.boxContent = document.createElement("div")
this.boxContent.classList.add("modal-box")
this.content_container.appendChild(this.boxContent)
this.events()
}
close(){
this.modal_container.parentNode.removeChild(this.modal_container);
}
open(content){
this.boxContent.appendChild(content);
}
// EVENTS
events(){
this.closeEvent()
// need to add more
}
closeEvent(){
this.modal_container.addEventListener("click", e =>{
if(!e.target.closest(".modal-box")){
this.close();
}
})
}
}
function Open(issue){
issue.addEventListener("click", () => {
let content = document.createElement("div");
content.classList.add("rows");
let html = `
<div>
<h1 class = "title">TITLE</h1>
</div>
<div>
<input type = "text" placeholder = "מערכת">
</div>
<div>
<input type = "text" placeholder = "פורט">
</div>
<div>
<input type = "text" placeholder = "RIT">
</div>
<div>
<input type = "text" placeholder = "כמה זמן לקח">
</div>
<div>
<input type = "time" placeholder = "התחיל מ">
</div>
<div>
<input type = "time" placeholder = "נגמר ב">
</div>
`
content.innerHTML = html
timer.pause = true
new MODAL().open(content) // when close continue timer (timer.pause = false)
})
}
I think you can work with a callback. To give you some idea, something like:
From your Open(issue) function:
// pass the callback here to continue timer
new MODAL().open(content, () => timer.pause = false);
Then in your MODAL class:
open (content, callbackFn) {
this.boxContent.appendChild(content);
// referenced from your closeEvent() function
this.modal_container.addEventListener("click", e => {
if (!e.target.closest(".modal-box")) {
this.close();
callbackFn(); // trigger the callback function here.
}
});
}
Let me know if this satisfies what you're trying to do.
open(issue) function:
new MODAL().open(content)
.then(value => {
console.log(value);
})
.catch(value => {
console.log(value);
})
MODAL class:
open (content) {
this.boxContent.appendChild(content);
return new Promise((resolve, reject) => {
this.modal_container.addEventListener("click", e => {
if (!e.target.closest(".modal-box")) {
this.close();
reject(false)
}
if (e.target.closest(".submit")) {
this.close();
resolve(true)
}
});
})
}

Passing onclick event in template literal

I'm trying to pass url through onclick event, its not working.
there is <body onload="displayBookmarks()"> to initialise displayBookmarks function as soon as the page gets loaded
function deleteBookmark(url){
alert(url);
};
function displayBookmarks(){
bookmarksResults.innerHTML = "";
for (let a in bookmarks){
let name = bookmarks[a].name;
let url = bookmarks[a].url;
bookmarksResults.innerHTML += `<div class="well"> <h3> ${name} <a class="btn btn-default" target="_blank" href=${url} >Visit</a> <a onclick=${deleteBookmark(url)} class="btn btn-danger" >Delete</a></h3></div>`
}
}
The main problem is onclick=${deleteBookmark(url)}
As soon as the page loads it starts displaying the url but I want to to be shown only when delete button is pressed.
I've found that there is another way to do this with encapsulation. I don't know if I would recommend doing it like this at all but since you've asked the question.
const app = document.getElementById("app");
const button = ((app) => {
let _url;
const _log = (data) => {
console.log(data);
}
let _content = `<button onclick="(${_log})('${_url}')">test</button>`;
const _setContent = () => {
_content = `<button onclick="(${_log})('${_url}')">test</button>`;
}
const _setUrl = (url) => {
_url = url;
}
return {
setUrl: (url) => {
_setUrl(url);
_setContent();
},
render: () => {
app.innerHTML = _content;
}
}
})(app)
const url = 'www.something.com';
button.setUrl(url);
button.render();
<section id="app">...</section>
const markUp = `
<button onclick="myFunction()">Click me</button>
`;
document.body.innerHTML = markUp;
window.myFunction = () => {
console.log('Button clicked');
};

Categories

Resources