DOM - DOM Event
in Dev on Java Script
DOM Events Overview
<!-- inline attribute event handler pattern -->
<body onclick="console.log('fire/trigger attribute event handler')">
<div>click me</div>
<script>
const elementDiv = document.querySelector('div');
// property event handler pattern
elementDiv.onclick = function()
{console.log('fire/trigger property event handler')};
//addEventListener method pattern
elementDiv.addEventListener('click',function()
{console.log('fire/trigger addEventListener')}, false);
</script>
only the addEventListener() provides a robust and organized solution. The inline attribute event handler mixes together JavaScript and HTML, and best practices advise keeping these things separate. Additionally, using event handlers inline on property event handlers can suffer from scoping nuances as one attempts to leverage the scope chain from the function that is invoked by the event. The addEventListener() method smooths out these issues.
Adding Event Listeners to Element Nodes, the window Object, and the document Object
The addEventListener() method is available on all Element nodes, the window object, and the document object, providing the ability to add event listeners to parts of an HTML document as well as JavaScript objects relating to the DOM and the Browser Object Model [or BOM].
<div>mouse over me</div>
<script>
/* add a mousemove event to the window object, invoking the event during the bubbling phase */
window.addEventListener('mousemove',function()
{console.log('moving over window');},false);
/* add a mousemove event to the document object, invoking the event during the bubbling phase */
document.addEventListener('mousemove',function()
{console.log('moving over document');},false);
/* add a mousemove event to a <div> element object, invoking the event during the bubbling phase */
document.querySelector('div').addEventListener('mousemove',function()
{console.log('moving over div');},false);
</script>
The addEventListener() method used in the preceding code example takes three ar‐ guments. The first argument is the type of event to listen for. Notice that the event type string does not contain the “on” prefix (i.e., onmousemove) that event handlers require. The second argument is the function to be invoked when the event occurs. The third parameter is a Boolean indicating whether the event should be fired during the capture phase or the bubbling phase of the event flow.
Typically, a developer wants events to fire during the bubbling phase so that object eventing handles the event before bubbling the event up the DOM. Because of this, you almost always provide a false value as the last argument to the addEventListener(). In modern browsers, if the third parameter is not specified, it will default to false.
The Value of this When Using addEventListener()
<div>click me</div>
<script>
document.querySelector('div').addEventListener('click',function(){
// 'this' will be the element or node the event listener is attached to
console.log(this); //logs '<div>'
},false);
</script>
Custom Events
A developer is not limited to the predefined event types. It’s possible to attach and invoke a custom event, using the addEventListener() method like normal in combination with document.createEvent(), initCustomEvent(), and dispatchEvent().
<div>click me</div>
<script>
const divElement = document.querySelector('div');
//create the custom event
const cheer = document.createEvent('CustomEvent');
/* the 'CustomEvent' parameter is required */
//create an event listener for the custom event
divElement.addEventListener('goBigBlue',function(event)
{ console.log(event.detail.goBigBlueIs)
},false);
/* Use the initCustomEvent method to set up the details of the custom event. Parameters for initCustomEvent are: (event, bubble?, cancelable?, pass values to event.detail) */ cheer.initCustomEvent('goBigBlue',true,false,{goBigBlueIs:'its gone!'});
//invoke the custom event using dispatchEvent
divElement.dispatchEvent(cheer);
</script>
Event Delegation
Event delegation, stated simply, is the programmatic act of leveraging the event flow and a single event listener to deal with multiple event targets. A side effect of event delegation is that the event targets don’t have to be in the DOM when the event is created in order for the targets to respond to the event. This is, of course, rather handy when dealing with XHR responses that update the DOM. By implementing event delegation, new content that is added to the DOM post JavaScript load parsing can immediately start responding to events. Imagine we have a table with an unlimited number of rows and columns. Using event delegation, we can add a single event listener to the table node that acts as a delegate for the node or object that is the initial target of the event. In the following code example, clicking any of the td s (i.e., the target of the event) will delegate its event to the click listener on the table. Don’t forget, this is all made possible because of the event flow, and in this specific case, the bubbling phase.
<table border="1"> <tbody>
<tr><td>row 1 column 1</td><td>row 1 column 2</td></tr>
<tr><td>row 2 column 1</td><td>row 2 column 2</td></tr>
<tr><td>row 3 column 1</td><td>row 3 column 2</td></tr>
<tr><td>row 4 column 1</td><td>row 4 column 2</td></tr>
<tr><td>row 5 column 1</td><td>row 5 column 2</td></tr>
<tr><td>row 6 column 1</td><td>row 6 column 2</td></tr>
</tbody>
</table>
<script>
document.querySelector('table').addEventListener('click',function(event){
if(event.target.tagName.toLowerCase() === 'td'){
/* make sure we only run code if a td is the target */
console.log(event.target.textContent);
/* use event.target to gain access to target of the event which is the td*/
},false);