Reputation: 361
I know already about event delegation by jQuery. However, How can I do same thing with pure Javascript without jQuery.
Although I attached change
event on body or the top element(div), change
event is not triggered when value of input element in body or top element is changed...
How can I do this?
Upvotes: 4
Views: 4164
Reputation: 5412
Tl;DR: you probably need to listen on the input event instead.
The reason you are probably not seeing the event being triggered, is because it is triggered: "...when the element loses focus after its value was changed." Source: MDN.
What you probably need to listen to, is the input
event instead which "fires when the value has been changed." Source: MDN
Here's an event listener attached to the <body>
HTML element which captures all the 'bubbled' input
and change
events (see how the input
event is triggered immediately whereas the change
event requires that the input element loses focus, e.g. when pressing Tab):
<!DOCTYPE html>
<html lang="en">
<head>
<title>Input Event Delegation</title>
</head>
<body>
<input name="email" type="email" />
<input name="name" type="text" />
<script>
document.body.addEventListener("input", (e) => {
console.log("type:", e.type, "value:", e.target.value);
});
document.body.addEventListener("change", (e) => {
console.log("type:", e.type, "value:", e.target.value);
});
</script>
</body>
</html>
Upvotes: 0
Reputation: 10096
You can just listen for the event on one element (in this case elSelector
) and then only execute the event when the actual target fits a selector
in that element.
function on(elSelector, eventName, selector, fn) {
var element = document.querySelector(elSelector);
element.addEventListener(eventName, function(event) {
var possibleTargets = element.querySelectorAll(selector);
var target = event.target;
for (var i = 0, l = possibleTargets.length; i < l; i++) {
var el = target;
var p = possibleTargets[i];
while(el && el !== element) {
if (el === p) {
return fn.call(p, event);
}
el = el.parentNode;
}
}
});
}
In the example below you can see that it also works with dynamic elements!
on("#inputs", "change", ".event", (target, evt) => console.log(target.target));
function on(elSelector, eventName, selector, fn) {
var element = document.querySelector(elSelector);
element.addEventListener(eventName, function(event) {
var possibleTargets = element.querySelectorAll(selector);
var target = event.target;
for (var i = 0, l = possibleTargets.length; i < l; i++) {
var el = target;
var p = possibleTargets[i];
while (el && el !== element) {
if (el === p) {
return fn.call(p, event);
}
el = el.parentNode;
}
}
});
}
/** random code for the button to add more inputs **/
let i = 7;
document.querySelector("#b").addEventListener("click", () => {
document.querySelector("#inputs").innerHTML += i + ` <input type="text" class="event"> <br>`;
i++;
});
<div id="inputs">
1 <input type="text" class="event"> <br>
2 <input type="text" class=""> <br>
3 <input type="text" class="event"> <br>
4 <input type="text" class=""> <br>
5 <input type="text" class="event"> <br>
6 <input type="text" class=""> <br>
</div>
<br><br>
<button id="b">Add another input</button>
Upvotes: 1
Reputation: 76464
Let's define your event function
:
function(event) doSomething{
//Your code
}
Let's get all the input
tags inside your body
:
var inputs = document.getElementsByTagName('input');
Now, let's iterate them and attach the event:
for (var inputIndex = 0; inputIndex < inputs.length; inputIndex++) {
inputs.addEventListener('change', doSomething);
}
Upvotes: 0