JQuery on() method in native javascript for dynamically generated elements [duplicate] - javascript

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 6 years ago.
I'm looking for native JavaScript code for this example with jQuery:
$("#parent").on("click", ".child", function(){
alert("clicked");
});
What I did so far works with the elements that come with the page but not the dynamically generated ones:
var children = document.getElementById("parent").getElementsByClassName("child");
for (var i = 0, l = children.length; i < l; i++)
{
children[i].onclick = foo;
}
function foo(el)
{
alert("child clicked");
}
How can I make this code work for the dynamically generated elements?
If you are looking for the answer, here it is:
https://stackoverflow.com/a/27373951/2748984

You could do something like the following, which listens for elements being added to the document, and then binds your function. I would also recommend binding an event listener rather than assigning your method to the onclick attribute, but check out this answer to see what you really need:
// listen for new elements being added to the document
document.addEventListener('DOMNodeInserted', function(event) {
// check if they're the type of node you're looking for
if (event.relatedNode.querySelectorAll('your selector')) {
// bind the event listener
event.relatedNode.addEventListener('click', function(event) {
// your code
});
}
});

Related

Is it possible to call function when HTML element gets loaded? [duplicate]

This question already has answers here:
How to add onload event to a div element
(26 answers)
Closed 3 years ago.
For example if I have in my body following
<button id="start"></button>
Is it possible to define in the HTML code a JS function that will be called when this element is loaded/shwon? So for example I can set some value of this element in JS? I know I can do in JS getElementBy... but that would be in the opposite direction I'm wanting to achieve this.
If yes, is it then possible to access the id of this html element in the called function?
var startNode = document.getElementById('start');
var observer = new MutationObserver(() => {
if(startNode.style.display !='none' ){
//when DOM is visible
}else {
//when DOM is hidden
}
});
observer.observe(startNode, { attributes: true, childList: true });
You can just use MutationObserver to observe the changes for specific element.

RemoveClass not working on a class name just added using jquery [duplicate]

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 6 years ago.
For some reason when I add a class to an element using Jquery I cannot perform a function using the class name just added:
$('.openslidecontent .arrow.off').click(function() {
$('.openslidecontent,.rightwrapper .arrow').removeClass('off')
$('.openslidecontent,.rightwrapper .arrow').addClass('on');
return false;
});
$('.openslidecontent .arrow.on').click(function() { // THIS FUNCTION DOES NOT EXECUTE
$('.openslidecontent,.rightwrapper .arrow').removeClass('on');
$('.openslidecontent,.rightwrapper .arrow').addClass('off');
return false;
});
The event listener is only attached to existing elements. You can switch to event delegation to have the listener react on newly created elements too
$(document).on('click', '.openslidecontent .arrow', function() {
$('.openslidecontent,.rightwrapper .arrow').toggleClass('on off');
})
Also, as Rory commented, you can just change your code to use toggleClass() and hook the event to both at the same time

I am having issues with es6 classes and event listeners? [duplicate]

This question already has answers here:
Is it possible to append to innerHTML without destroying descendants' event listeners?
(13 answers)
Closed 6 years ago.
This has now been answered. Not an issue with ES6 or event listeners, but rather how innerHTML is working. It is removing all the html (breaking the listeners) and then adding the html back in with only the latest listener attached. Thank you.
Basically I am having issues with ES6 Classes and event listeners. Or it could very well just be my understanding of the whole thing.
I am dynamically creating 5 instances of the same class called 'Thing'. Each 'Thing' writes a piece of HTML to the DOM containing a button and adds an event listener to handle clicks. Elements are being selected using document.querySelector and based off a data attribute called 'indexNumber' to uniquely identify each button.
As each thing is its own instance I imagined that each button would work but only the last button does. Why is one instance of a class overwriting another?
Can anyone explain what is happening here?
HTML
<h1>Things</h1>
<span class="output"></span>
<div class="thingHolder"></div>
JS (Babel)
class Thing {
constructor(index) {
this.Index = index;
this.html = '<div class="thing" data-index-number="'+ index +'">Thing ' + index + '<button type="button">Click Me!</button></div>';
this.renderDom();
}
renderDom(){
const thingHolder = document.querySelector(".thingHolder");
thingHolder.innerHTML += this.html;
this.addEventListeners();
}
addEventListeners(){
const button = document.querySelector('.thingHolder .thing[data-index-number="' + this.Index + '"] button');
button.addEventListener("click", () => {
this.doSomething()
}, false);
}
doSomething(){
const output = document.querySelector(".output");
output.innerHTML = 'You clicked thing #' + this.Index;
console.log('You clicked thing #' + this.Index)
}
}
for(var i = 0; i < 5; i++) {
var thing = new Thing(i);
}
The problem has nothing to do with ES6 or JavaScript.
thingHolder.innerHTML += this.html;
will destroy and recreate all existing children of thingHolder. In that process, existing event handlers are destroyed.
Instead of creating HTML and using innerHTML you should be using the DOM API to create and append new element.
Example:
var div = document.createElement('div');
div.addEventListener('click', () => { ... });
// ...
thingHolder.appendChild(div);
When you use thingHolder.innerHTML += html the old objects in the container are removed and recreated, but without their event listeners. So you are recreating them all every time you insert a new node that way.
The fact that the first button is the only one that works is because you are attaching an event only to the first element you encounter inside the parent (with querySelector), just after you removed all other events.
So the solution would be to create your elements with JS (or whatever is used in Babel) instead of using innerHTML.

on click fire addEventListener [duplicate]

This question already has answers here:
Add click event on div tag using JavaScript
(6 answers)
Closed 7 years ago.
This is basic but I have no idea how to do this.
There is an addEventListener that fires on page load.
var imgcnvs = document.createElement('canvas');
var imagecxt = imgcnvs.getContext('2d');
window.addEventListener('load', function(){
//do something
}, false);
How can I convert window.addEventListener('load', function(){ to work when $('#startBtn') is clicked? `
$( "#startBtn" ).click(function() {
//dosomething
});
Please read the jquery documentation.
You need to get your target element, using document.getElementById for instance, and then attach the event listener to it. As follows:
document.getElementById("startBtn").addEventListener("click", function(event) {
// Do something
}, false);

Trouble executing functions in javascript loops [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
What I am trying to do is to set the same function to different elements with similar id, for example "icon-1","icon-2","icon-3". The function opens up a window that corresponds to those ids -- "window-1", "window-2","window-3". I was trying to use this code block:
for (var i=1; i<=3; i++) {
$("#icon"+i.toString()).click(function(){
$("#window"+i.toString()).show();
)};
)};
Ideally, when "icon-1" is clicked, it opens "window-1", etc. But it's not working.
And I checked console.log(i), every time when a click event occurs, it prints out the final count of i, which is 4.
Is there any way to fix or walk around this?
Thanks a lot!
When you say 'opens up a window', do you mean to open up a popup window or just showing an existing element?
Assuming it's the latter, I would give each of your icons a class that they all share and attach the click handler to elements with that class rather than using three different click handlers. Then use the data attribute to store the corresponding window number:
<div class="icon" data-window="1">This is an icon</div>
<div class="icon" data-window="2">This is an icon</div>
$('.icon').click(function(){
var windowNum = $(this).data();
$('#window-' + windowNum).show();
});
Try classes to achieve that.
$('.yourIconClass').each(function() {
$(this).click(function(){
$('.yourWindowClass').eq($(this).index).show();
});
});
I wouldn't use a for loop for this. I don't use query, so I'll speak in javascript.
I would assign the buttons/icons to variables in javascript and then just have an event listener for each of the buttons. That event listener will send a value to a function that will determine which window to open:
var button1 = document.getElementById("button_1_id");
var button2 = document.getElementById("button_2_id");
var button2 = document.getElementById("button_2_id");
button1.addEventListener('click',function(){
triggerWindow(1);
});
button2.addEventListener('click',function(){
triggerWindow(2);
});
button3.addEventListener('click',function(){
triggerWindow(3);
});
function triggerWindow(input) {
if(input === 1){
/* code to trigger window one */
}
else if(input === 2){
/* code to trigger window two */
}
else if(input === 3){
/* code to trigger window three */
}
}

Categories

Resources