3

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>
Rediska
  • 1,392
  • 10
  • 14
  • Yes, but I do not want to do it directly. In my real code, DOM structure is dynamic, elements come and go, so I want event handlers to be active only when its element is attached to DOM. – Rediska Dec 22 '16 at 16:29
  • Might be an event bubbling thingy. Have you tried `myDiv.addEventListener("myEvent",function(){alert("Yes!"), true});` – Shilly Dec 22 '16 at 16:30
  • yes I did, both true and false. Doesn't help. – Rediska Dec 22 '16 at 16:30
  • This is a complete and verifiable example. If the event is propagated, you should see "Yes!" alert. Just copy the code and run it in a browser. – Rediska Dec 22 '16 at 16:40
  • 1
    @Rediska The fiddle I provided fixes your code to do just that. If this was a [mcve] then the answer would be correct. You complete example indicates you know which element you want to trigger the event on. If not, then the explanation of how event propagation works that I gave would indicate that is it not possible to do what you want given the information you have provided. – TheSharpieOne Dec 22 '16 at 16:43

4 Answers4

6

By default Custom Events are not bubbled.

Reason being, Custom Event definition says:

let event = new CustomEvent(type,[,options]).

Options have a flag : bubbles, which is false by default, we have to enable it.

Following will fix your code

<html>
<script>
function onLoad() {
  var myDiv = document.getElementById("myDiv");
  myDiv.addEventListener("myEvent",function(){alert("Yes!");});
  document.dispatchEvent(new CustomEvent("myEvent",{detail:null,bubbles:true}));
}
</script>
<body onload="onLoad()">
<div id="myDiv"></div>
</body>
</html>
Sai Varun
  • 136
  • 1
  • 6
0

This is currently not possible as stated in the MDN doc https://developer.mozilla.org/en-US/docs/Web/Events/Creating_and_triggering_events#event_bubbling, event can only bubble from child to ancestors, i.e. upward for now.

The best way you can achieve this is use document.querySelector to target the element(s) you want to dispatch the event to, then dispatch as needed.

document.querySelector("#myDiv").dispatchEvent(customEv);
jking
  • 194
  • 2
  • 9
-1

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>
Claus
  • 532
  • 2
  • 8
  • 20
-1

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>
Rediska
  • 1,392
  • 10
  • 14