'Propagation of custom events
I expect my CustomEvent to be propagated from document to all the DOM elements. For some reason, it does not happen. What am I doing wrong?
<html>
<script>
function onLoad() {
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener("myEvent",function(){alert("Yes!");});
document.dispatchEvent(new CustomEvent("myEvent",{detail:null}));
}
</script>
<body onload="onLoad()">
<div id="myDiv"></div>
</body>
</html>
Solution 1:[1]
You have to dispatchEvent the event on the element you want the event 'triggered' on. It will then propagate down and back up the DOM
<html>
<script>
function onLoad() {
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener("myEvent",function(){alert("Yes!");});
myDiv.dispatchEvent(new CustomEvent("myEvent",{detail:null}));
}
</script>
<body onload="onLoad()">
<div id="myDiv"></div>
</body>
</html>
fiddle: https://jsfiddle.net/yrf9cvr3/
How propagation works: The event starts at the document and works it's way down to the element it was dispatched on (You can capture the event going this way using onCapture flag). Then goes back up to the document. Because you are dispatching on the document the event doesn't really go anywhere, only document see the event.
Solution 2:[2]
Try this one. Use document.querySelector and specify the events you want to track. Click the button or type some text in the text box
<html>
<script>
function onLoad() {
// var myDiv = document.getElementById("myDiv");
// myDiv.addEventListener("myEvent",function(){alert("Yes!");});
// document.dispatchEvent(new CustomEvent("myEvent",{detail:null}));
var myDiv = document.querySelector("#myDiv");
myDiv.addEventListener("click", myEventHandler, false);
myDiv.addEventListener("change", myEventHandler, false);
}
function myEventHandler(e)
{
alert('Element was '+e.target.id+'\nEvent was '+e.type);
}
</script>
<body onload="onLoad()">
<div id="myDiv">
<input type="button" id= "Button 1" value="Button 1"><br>
<input type="text" id="Text 2">
</div>
</body>
</html>
Solution 3:[3]
I am posting some solution, not really an answer. This will propagate a custom event to all the elements in the DOM.
<html>
<script>
document.dispatchCustomEvent = function(event) {
function visit(elem,event) {
elem.dispatchEvent(event);
var child = elem.firstChild;
while(child) {
if(child.nodeType==1) visit(child,event);
child = child.nextSibling;
}
}
visit(document.documentElement,event);
}
function onLoad() {
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener("myEvent",function(){alert("Yes!");});
document.dispatchCustomEvent(new CustomEvent("myEvent",{detail:null}));
}
</script>
<body onload="onLoad()">
<div id="myDiv"></div>
</body>
</html>
Solution 4:[4]
Going with the extreme. Events propagate down to the element they are dispatched on and back up... So in order to trigger an event on any and essentially all elements (since it is unknown which elements need the event) you can find the "ends" of all of the "branches" of the DOM and dispatch events to them.
jQuery makes it easy to select the end of the branches
function onLoad() {
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener("myEvent", function() {
alert("Yes!");
});
$(':not(:has(*))').each(function(i, el){
el.dispatchEvent(new CustomEvent("myEvent", {
detail: null,
bubbles: true
}));
});
}
https://jsfiddle.net/dkqagnph/1/
Using this will ensure EVERY DOM element (attached to the body) gets the event (assuming that no element stop propagation itself) and thus making there be no need to know which elements are listening or care about the event. This doesn't dispatch to every individual element, as that would be overkill, but just the end and lets bubbling do it's thing.
NOTE: elements with more than one child will get the event more than one time. You may want to have a way to ensure that your code does run more than once or does not care if it runs more than once.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | TheSharpieOne |
| Solution 2 | Claus |
| Solution 3 | Rediska |
| Solution 4 |
