I need to watch children's events in Document
level, but if the children stop propagation by using method stopPropagation()
, I cannot listen those events occur in children.
Can someone know a better way to do this?
EDIT: now I want to create an chrome extension to monitor DOM node event, but the event could be stopped propagation, and it is not a good practice to add extra listener to all nodes. Following example will show my question.
customer HTML fragment
<body>
<input type="button" value="Click Me" id="b">
</body>
customer javascript
var button = document.querySelector('#b');
button.addEventListener('click', function(e) {
console.log('Button has been clicked');
e.stopPropagation();
});
chrome extension content scripts
document.addEventListener('click', function(e) {
console.log('Node(' + e.target.nodeName + ') has been clicked');
// this listener will not be invoked because event has been stopped
// propagation.
});
You can use "capturing" to track an event before bubbling. There's a very good description of how capturing works (as contrasted with bubbling) in this article: Bubbling and capturing.
In summary, all browsers except IE before IE9, send events down the chain to the leaf where the event occurred and then they bubble the events back up. Normal event listening only listens for the event on the actual object or for propagated events, but if you set the third argument to .addEventListener()
to true, then it will also listen to events going down the chain where the document
object will see the event FIRST before bubbling has even started or been cancelled.
Here's a working snippet demo:
// show output
function log(x) {
var div = document.createElement("div");
div.innerHTML = x;
document.body.appendChild(div);
}
// stop propagation on leaf click
var leaf = document.getElementById("leaf");
leaf.addEventListener("click", function(e) {
log("leaf message - click in leaf, propagation stopped")
e.stopPropagation();
}, false);
// capture listen
document.addEventListener("click", function(e) {
if (e.target === leaf) {
log("document message - click in leaf");
}
}, true);
<div id="topParent">
<div id="midParent">
<div id="leaf">
Click Here
</div>
</div>
</div>