With event listeners we can interact (run a function) every time the event takes place
On this page we discuss a few commonly used events
If you understand how this works you can make your own event listeners to interact with every possible event
An event listener has always two (sometimes three) parameters:
first the <event> to watch for,
second the callback function that will be executed when the event fires
third and optional a boolean value to disable event bubbling (default value for bubbling is true)
<element>.addEventListener('<event>',function(e){// do something when the <event> is triggered// 'e' is the event itself});// or with an arrow function<element>.addEventListener('<event>',e=>{// ...});
The "animations" in the previous example are very straightforward
Open es6/events/mouse_2.html and es6/events/mouse_2.js
In this example, we change the layout with classes instead of inline CSS
show/hide will be replaced with a nice slide-up/slide-down effect
the rotate effect will be replaced with a 3D effect
All effects will take 1 second
Line 8: the transition for all effects on #section1 is set to 1 second
Line 9: it's not possible to animate the height attribute over time, but you can use the max-height
(for now, set the max-height to a value higher the actual height of the element)
line 10: for the slide-up effect we set overflow to hidden because otherwise only box itself will close, but the content inside the box stays visible
Line 13 to 16: adding the class .hide to #section1 provides the slide-up effect:
the max-height goes from 300px to 0px
the opacity goes from 1 to 0
for the slide-down effect we have to remove the class .hide from #section1
Line 17 to 19: adding the class .flip to #section1 provides the 3D flip effect
(without the perspective() it's only a 2D effect)
Line 11: we are only interested in the height value of #section1 and this is placed as the inline style max-height on the #section1
Line 13 to 18: every time we resize the window, we get the new height of #section1 and update the max-height of the element (we first delete the old max-height and then set the max-height to its new value)
const btnHide = document.getElementById('hide');const btnShow = document.getElementById('show');const btnToggle = document.getElementById('toggle');const section1 = document.getElementById('section1');const section2 = document.getElementById('section2');const styles1 = window.getComputedStyle(section1);
console.log('all css properties of #section1', styles1);
console.log('the height of #section1', styles1.height);
section1.style.maxHeight = styles1.height;
window.addEventListener('resize',(e)=>{
section1.style.maxHeight ='';// delete the old max-height
console.clear();
console.log('the height of #section1', styles1.height);
section1.style.maxHeight = styles1.height;// set the new max-height});
btnHide.addEventListener('click',function(e){
section1.classList.add('hide');});
btnShow.addEventListener('click',function(e){
section1.classList.remove('hide');});
btnToggle.addEventListener('dblclick',function(e){
section1.classList.toggle('hide');});
section2.addEventListener('mouseenter',function(e){
section1.classList.add('flip');});
section2.addEventListener('mouseleave',function(e){
section1.classList.remove('flip');});
When an event happens on an element, it first runs the callback function of the corresponding event listener after which the event bubbles up the DOM tree
Open es6/events/bubbling.html and es6/events/bubbling.js
Look at the DOM structure
We set a click event on the figure, the img, the figcaption and the b tag inside the figcaption
When you click on the b element, the event bubbles up the DOM tree, and (it looks as) you also have clicked on the figcaption and on the figure!
Sometimes this may lead to unexpected behavior ...
Open es6/events/preventDefault.html and es6/events/preventDefault.js
...
<mainclass="container"><h1>Dispatch event</h1><h1>Prevent default action</h1><p>Link to <ahref="https://bing.com"id="bing">bing.com</a></p><formid="searchForm"action="https://google.com/search"method="get"target="_blank"><labelfor="q">Search on Google</label><inputtype="text"name="q"id="q"/><buttontype="submit"class="primary">Submit</button></form><pre></pre>
...
</main>
1 2 3 4 5 6 7 8 9 10 11 12 13
Line 7: The default action (going to bing.com) when clicking on the link is prevented
Line 9: window.open('https://google.com', '_blank'): a new browser tab (google.com) is opened
Line 13 to 14: if the search term (#q) contains less than 3 characters, the default action of the event (submitting the form) is prevented
const bing = document.getElementById('bing');const searchForm = document.getElementById('searchForm');const q = document.getElementById('q');const output = document.querySelector('main pre');
bing.addEventListener('click',function(e){
e.preventDefault();// prevent to open the default URL
output.innerText =`Sorry I'm sending you to google.com`;
window.open('https://google.com','_blank');});
searchForm.addEventListener('submit',function(e){if(q.value.length <3){
e.preventDefault();// prevent submitting the form if length < 3 characters
output.innerHTML =`Search term must contain <b>at least 3</b> characters`;}});
const button = document.querySelector('main button');const output = document.querySelector('main pre');
button.addEventListener('click',function(e){
console.log('button is clicked');
output.innerHTML +='button is clicked<br>';});// trigger a click event on the button
button.dispatchEvent(newEvent('click'));
1 2 3 4 5 6 7 8 9 10
Without touching the button, the first click event has already been triggered
To add an event listener (listening to the same event and with the same callback function) to every element inside a NodeList, you first have to loop over the NodeList and add the event
listener inside the loop
Open es6/events/nodelist.html and es6/events/nodelist.js
Line 5 to 15: loop, with the forEach() method, over the NodeList of buttons
Line 7 to 14: add an event listener to every button inside the NodeList; the parameter e inside the callback function represents the event
Line 9: the event contains a lot of information: the cursor position, which event was triggered, the button that was clicked on, ...
Line 11: usually you just need to know which element was clicked on and then e.target gives you enough information
// select all buttons inside #buttongroupconst buttons = document.querySelectorAll('#buttongroup button');// loop over the buttons inside the NodeList
buttons.forEach(function(button){// add event on every button
button.addEventListener('click',function(e){// log the whole event
console.log('event', e);// get the clicked button via the event
console.log('e.target', e.target);// or get the clicked button via the this keyword
console.log('this',this);});});
Sometimes multiple event listeners use the same callback function
To keep your code DRY (Don't Repeat Yourself), you can move the callback to a separate function and reuse it for multiple events
Functions will be discussed in more detail later in this course
<element>.addEventListener('<event>',function(e){// callback function});// is the same asfunctioncb(e){// callback function}<element>.addEventListener('<event>', cb);
1 2 3 4 5 6 7 8 9 10
WARNING
Never use parentheses when referring to the callback function