How to put a EventListener for all divs generated by JavaScript
Your issue is that you're adding your event listeners initially when the page loads. This means that your for
loop that adds your event listeners will only loop over the video-container
elements that are present on the initial load of your page. Any video-container
elements created after you've added your event listeners won't have an event listener attached to them. Even if you are using .cloneNode()
on an element that has an event listener attached with addEventListener()
, the event listener won't be copied across to the new element as addEventListener()
event handlers are not copied.
One idea is to add a new event listener to videoComponent
every time createVideo()
is called. The problem with this is that this can lead to you adding many event listeners to your page, which can slow down the performance of your webpage.
A better idea is to use event delegation. The idea of event delegation is that you can add your event listener to one parent element (in your case the <main>
element). When one of your video-container
elements nested under the parent <main>
element is clicked, the click event will "bubble" up to the <main>
element, triggering the click event listener on the parent <main>
element. Within the event listener attached to the parent <main>
element, you can obtain a reference to the originally clicked video-container
element using e.target
, where e
is the Event object provided in the event listeners callback function. As the click event listener is on the parent main
container, the click event listener for any newly created children elements will work, as the event from the child element will bubble up to the parent main container's event handler.
To achieve event delegation in your code, you can remove your for
loop that adds the individual event listenerrs and instead add your click event listener to your mainContainer
element. This will capture click events that bubble up to it when its children are clicked:
mainContainer.addEventListener("click", function(e) { // e = event object
if (e.target && e.target.matches(".video-container")) {
const clickedVideoContainer = e.target;
// do stuff with `clickedVideoContainer`
}
});
Here we're also checking that the clicked element (e.target
) is in fact a video-container element by seeing if it matches()
the selector .video-container
. This is needed as our mainContainer
event listener can trigger for any click events that bubble up to it from any of its children, grandchildren, etc.
As also noted in the comments by @Dai, you might also want to consider using the passive
option when adding your scroll event listener to improve performance.
Adding Event Listener to dynamically created divs
Change
listDiv.addEventListener = ('click',gotoOutcomesLO, false);
to
listDiv.addEventListener('click',gotoOutcomesLO, false);
Adding an event listener to a dynamically created div, and passing this to it
Further to my comment above, here's an example of the automatic access to the this
keyword I spoke of. Clicking any of the buttons will cause the text on that particular button to be alerted.
<!DOCTYPE html>
<html>
<head>
<script>
"use strict";
function allByTag(tagName,parent){return (parent == undefined ? document : parent).getElementsByTagName(tagName);}
function forEachNode(nodeList, func){for (var i=0, n=nodeList.length; i<n; i++) func(nodeList[i], i, nodeList); }
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded()
{
forEachNode( allByTag('button'), function(curNode, curIndex, nodeList){ curNode.addEventListener('click', onBtnClick, false); } );
}
/*
// expanded version of the above function
//
function onDocLoaded()
{
var btns = allByTag('button');
forEachNode(btns, attachBtnHandler);
function attachBtnHandler(curNode, curIndex, nodeList)
{
curNode.addEventListener('click', onBtnClick, false);
}
}
*/
function onBtnClick(evt)
{
alert(this.textContent);
}
</script>
<style>
</style>
</head>
<body>
<button>This is btn1</button>
<button>This is btn2</button>
<button>This is btn3</button>
</body>
</html>
How to add event listener on dynamically created div with interactive content
You can use Element.closest
to retrieve the element you need.
document.getElementById('container').insertAdjacentHTML(
'beforeend', `<div class="card">
<div class="card-header">Card header content</div>
<div class="card-body">
<h2>Card body</h2>
<select>
<option value="value1">Value 1</option>
</select><br>
Some more text
</div>
</div>`
);
// Event delegation
document.addEventListener('click', function (e) {
console.clear();
// exclude select element action ...
if (!(e.target instanceof HTMLSelectElement)) {
return console.log(e.target.closest(`.card`));
}
});
.card{
background: rosybrown;
text-align: center;
width: 50%;
}
h2{
margin-top: 0;
}
<div id="container">
</div>
How to add an event listener to all items in array
Instead of attaching listeners to each button, add one to the container (set
) and, using event delegation, let that listener capture all the events that "bubble up" the DOM from its child elements, and call a function.
const set = document.querySelector('.set');
set.addEventListener('click', handleClick, false);
function handleClick(e) {
if (e.target.matches('button')) {
const { textContent } = e.target;
console.log(`Banging the ${textContent} drum!`);
}
}
<h1 id="title">Drum Kit</h1>
<div class="set">
<button class="w drum">w</button>
<button class="a drum">a</button>
<button class="s drum">s</button>
<button class="d drum">d</button>
<button class="j drum">j</button>
<button class="k drum">k</button>
<button class="l drum">l</button>
</div>
<footer>
Made with ❤️ in London.
</footer>
Attach event to dynamic elements in javascript
This is due to the fact that your element is dynamically created, so it is attached to the DOM later, but your addEventListener
call already occurred in the past.
You should use event delegation to handle the event.
document.addEventListener("click", function(e){
const target = e.target.closest("#btnPrepend"); // Or any other selector.
if(target){
// Do something with `target`.
}
});
closest
ensures that the click occurred anywhere inside the target element or is the target element itself.
This is useful if, for example, instead of your <input id="btnPrepend"/>
you had a <button id="btnPrepend"><i class="icon">+</i> prepend</button>
and you clicked the <i class="icon">+</i>
.
jQuery makes it easier:
$(document).on("click", "#btnPrepend", function(){
// Do something with `$(this)`.
});
Here is an article about event delegation.
Difficulty adding unique event listener to created div elements via a for loop
Your problem is with the way your declaring the email within the loop:
var email = emails[i];
Because of scoping, you create a single closure around email
and all iterations of the loop use one value. Change it to let
for block level scope so that each loop iteration gets its own value to work with:
let email = emails[i];
Other:
To make your code simpler to read and maintain, don't set up inline styles. Instead create CSS Classes and just apply/remove the classes as needed. So instead of:
document.querySelector('#emails-view').style.display = 'none';
document.querySelector('#compose-view').style.display = 'none';
document.querySelector('#single-view').style.display = 'block';
Just make a CSS class called, say .hidden
, like this:
.hidden { display:none; }
And, when an element needs that class or needs it removed do:
someElement.classList.add("hidden");
someElement.classList.remove("hidden");
Similarly, instead of this:
// Create div, set class, and append email content to HTML
var reademail = document.createElement('div');
reademail.innerHTML = '';
reademail.style.borderStyle = 'solid';
reademail.style.borderColor = 'black';
reademail.style.borderWidth = '0.1rem';
reademail.style.borderRadius = '0';
reademail.style.marginBottom = '0.2rem';
reademail.style.padding = '0.3rem';
Make a CSS Class, like this:
.readEmail {
border: 0.1rem solid black;
border-radius: 0;
margin-bottom: 0.2rem;
padding: 0.3rem;
}
And then just add it to the new element (also, don't use .innerHTML
when your string doesn't contain any HTML because .innerHTML
has security and performance implications):
var reademail = document.createElement('div');
reademail.textContent = '';
reademail.classList.add("readEmail");
Dynamic Event Listener Working only on the Last Created Element
That's because you are modifying innerHTML
of the wrapper element. After modification the innerHTML
is parsed and the new Nodes are generated. Since the old Nodes are replaced with the new Nodes, the event listeners that had been bound to the (now deleted) elements in the previous iterations won't work.
You should either use the event delegation technique or generate the elements using document.createElement
method and append them using the .appendChild
of the wrapper element (the #window
element).
Here is an example of the second suggested method:
function openRow(event) {
var id = this.id;
// ...
}
var el, win = document.getElementById('window');
for (var i = 0; i < total; i++)
{
el = document.createElement('div');
el.classList.add('detail-view');
el.id = 'row_' + i;
el.addEventListener('click', openRow);
win.appendChild(el);
}
Is it possible to add an eventlistener on a DIV?
Yeah, that's how you do it.
document.getElementById("div").addEventListener("touchstart", touchHandler, false);
document.getElementById("div").addEventListener("touchmove", touchHandler, false);
document.getElementById("div").addEventListener("touchend", touchHandler, false);
function touchHandler(e) {
if (e.type == "touchstart") {
alert("You touched the screen!");
} else if (e.type == "touchmove") {
alert("You moved your finger!");
} else if (e.type == "touchend" || e.type == "touchcancel") {
alert("You removed your finger from the screen!");
}
}
Or with jQuery
$(function(){
$("#div").bind("touchstart", function (event) {
alert(event.touches.length);
});
});
Related Topics
Need to Load Image as Modal on Click in Bootstrap CSS
What Exactly Is Cdata and What Does It Do
Replacing Normal File Upload Input with an Image
How to Jump to Top of Browser Page
JavaScript Image Overlay Over a Specified Div
Performance Difference Between JavaScript Created Inline Styles and JavaScript Created Stylesheets
Can't Change Bootstrap Tooltip Title
How to Change the Design of the Textarea Resize Handle in CSS
How to Make the Whole Card Component Clickable in Material UI Using React Js
Vertical-Align Text Within a Textarea
Add Custom Buttons on Slick Carousel
Add Page-Specific JavaScript or CSS in Joomla
Window.Scrollto Not Working in Phonegap - Alternative Solution or Workaround
How to Make Cross-Browser CSS3 Code Dry
How to Position Popover Over a Highlighted Portion of Text
Animate CSS3 Gradient-Positions Using Jquery