Introduction to Browser Events

Events are considered occurrences or actions, happening in the system you are developing that the latter informs you about so that you can respond to them. In brief, it is a signal that something has happened in your system. All of the DOM nodes generate signals like that ( of course, they are not limited to DOM).

To be more precise, let’s consider a situation. For example, if a user clicks a webpage button, you can respond to it by displaying an information box.

Let’s take a look at the handiest DOM events:

Mouse Events:

  • click– when a click is made on an element by the mouse ( touchscreen devices are capable of generating it on tap).
  • contextmenu – the right-click of the mouse on an element.
  • mouseover/mouseout –when the cursor of the mouse moves onto or leaves an element.
  • mousedown/mouseup - while the mouse button is pressed or is over an element.
  • mousemove- the mouse is moved.
Form Element Events:

Form Element Events:

  • submit - the event of submitting a <form> by the visitor.
  • focus - focusing on an element by the visitor.

Keyboard Events:

  • keydown - when the visitor presses the button.
  • keyup - when any key is released by the visitor.

Document Events:

DOMContentLoaded - the state of loading and proceeding of HTML, the DOM is completely built.

CSS Events

transitionend - completion of a CSS-animation.

There are more events, but the ones above are the most essential.

Event Handlers

A handler is assigned for reacting to events: it is a function, running in case of an event. Handlers are a means of running JavaScript code in case of user actions. Several ways of assigning a handler can be distinguished. Let’s explore them, starting from the most straightforward one.

HTML-attribute

You can set a handler in HTML with an attribute called on<event>. For example, if you want to assign a click handler for an input, use onclick, as follows:

<input value="Click" onclick="alert('Click')" type="button">

The code inside onclick runs on mouse click. Please, take into account that you need to use single quotes inside onclick. The reason is that the attribute itself is inside double-quotes. Forgetting that the code is inside the attribute and using double quotes inside (onclick="alert('Click')") will lead to an error. An HTML-attribute is not the proper place for writing too much code. Hence, it would be best if you created a JavaScript function and called it.

The click in the following example will run the carsCount() function:

<!DOCTYPE html>
<html>
  <body>
    <script>
      function carsCount() {
        for(let i=1; i<=5; i++) {
          alert("Car " + i);
        }
      }
    </script>
    <input type="button" onclick="carsCount()" value="Cars count">
  </body>
</html>
let input = document.createElement('input');
input.id = 'inputId';
input.setAttribute("type", "button");
input.setAttribute("value", "Click");
document.body.appendChild(input);
 
inputId.onclick = function carsCount() {
  for (let i = 1; i <= 5; i++) {
    alert("Car " + i);
  }
}

As you know, the HTML attribute names are not considered case-sensitive: ONCLICK will work as onClick and onCLICK. But, as a rule, attributes should be lowercase: for example, onclick.

DOM Property

A handler can also be assigned with a DOM property on<event>. Let’s see elem.onclick in the example below:

<!DOCTYPE html>
<html>
  <body>
    <input id="inputId" type="button" value="Click">
    <script>
      inputId.onclick = function() {
        alert('Welcome to W3Docs');
      };
    </script>
  </body>
</html>

And the same thing in javascript:

let input = document.createElement('input');
input.id = 'inputId';
input.setAttribute("type", "button");
input.setAttribute("value", "Click");
document.body.appendChild(input);
 
inputId.onclick = function () {
  console.log('Welcome to W3Docs');
};

In case the handler is assigned by using an HTML-attribute, the browser will be able to read it, creating a new function from the attribute content and writing it to the DOM property.

Please, note that the handler is always in the DOM property, and the HTML-attribute is one of the ways of initializing it.

Let’s view two codes that operate the same:

  1. HTML Only:
    <!DOCTYPE html>
    <html>
      <body>
        <input type="button" onclick="alert('Click')" value="Button">
      </body>
    </html>
  2. HTML Plus JavaScript:
    <!DOCTYPE html>
    <html>
      <body>
        <input type="button" id="button" value="Button">
        <script>
          button.onclick = function() {
            alert('Click');
          };
        </script>
      </body>
    </html>

You can’t assign more than a single event handler, because there is only one onclick property. Let’s take an example where handling with JavaScript overwrites the handler that already exists.

<!DOCTYPE html>
<html>
  <body>
    <input type="button" id="buttonId" value="Button">
    <script>
      buttonId.onclick = function() {
        alert('Click');
      };
    </script>
  </body>
</html>

By the way, direct assigning an existing function as a handler is possible, like here:

let div = document.createElement('div');
div.id = 'elem';
div.innerHTML = 'Click on text';
document.body.appendChild(div);

function welcome() {
  alert('Welcome to W3Docs');
}
elem.onclick = welcome;

For removing a handler, you should assign elem.onclick = null.

Accessing the Element: this

The element is the value of this inside a handler. Let’s see an example where button through this.innerHTML shows its content:

<!DOCTYPE html>
<html>
  <body>
    <button onclick="alert(this.innerHTML)">Click me</button>
  </body>
</html>

And the same thing in javascript:

let button = document.createElement('button');
button.innerHTML = 'Click on button';
document.body.appendChild(button);
 
button.onclick = function () {
  console.log(this.innerHTML);
};

Possible Mistakes

There can be subtleties in the process of working with events. The function needs to be assigned as welcome, not welcome() like in the example below:

// right
button.onclick = welcome;
 
// wrong
button.onclick = welcome();

In the event of adding parentheses,welcome() is a function call. So, the last line will take the result of the function execution. It is undefined, as the function doesn’t return anything, so it is assigned to onclick. That will not work. On the other hand, the parentheses are necessary for the markup, as follows:

<!DOCTYPE html>
<html>
  <body>
   <input type="button" id="button" onclick="welcome()" value="Button">
    <script>
      function welcome() {
       alert('Welcome')
      }                 
    </script>
  </body>
</html>

Let’s explain the difference. At the time the browser reads the attribute, it generates a handler function using the body from the content of it: welcome(). Therefore the markup creates the property below:

<!DOCTYPE html>
<html>
  <body>
    <input type="button" id="button" value="Button" >
    <script>
      function welcome() {
       alert('Welcome')
      }      
      button.onclick = function () {
        welcome(); // the attribute content
      }       
    </script>
  </body>
</html>

It is recommended to use functions and not strings.

The elem.onclick = "alert(1)" also works but we don’t recommend you to use it.

You shouldn’t use setAttribute either.

It is useless to call the following:

// a click on <body> will generate errors,
// because attributes are always strings, function becomes a string
document.body.setAttribute('onclick', function () {
  alert(1)
});

Keep in mind the DOM-property case: assign a handler to elem.onclick and not to elem.ONCLICK. The reason is already spoken about: the properties of DOM are case-sensitive.

addEventListener

There is a fundamental problem in the ways of assigning handlers above- they don’t allow you to add multiple handlers to a single event. For example, if it is necessary to highlight a button on click in one part of your code and to show code in another one. If you assign two event handlers for that, the DOM property will overwrite the existing one, like this:

let input = document.createElement('input');
input.setAttribute('type', 'button');
input.setAttribute('value', 'Button');
document.body.appendChild(input);
 
input.onclick = function () {
  alert(1);
}
// ...
input.onclick = function () {
  alert(2);
} // replaces the previous handler

Using the specific methods, such as addEventListener addEventListener and removeEventListenerremoveEventListener will free you from that kind of problem. The syntax to add a handler will look like this:

element.addEventListener(event, handler[, options]);

event

Event name ( for example, click).

handler

The function of the handler.

options

An additional optional object obtaining the following properties:

  • once: in case it’s true, the listener will automatically be removed after it releases.
  • capture: the phase where the event should be handled. More about it is represented in chapter Bubbling and capturing.
  • passive: in the case of true, the handler will not be preventDefault().

Finally, for removing the handler, you can apply removeEventListener, like this:

element.removeEventListener(event, handler[, options]);

Event Object

For handling the event properly, you need to get more detailed information about what has happened. It’s not just about a keypress or a click, but about the exact pointer coordinates.

Whenever an event happens, an event object is created by your browser: all the details are inserted to it, and it is passed as a handler argument. Let’s take a look at an example, where the mouse coordinates are got from the event object:

<!DOCTYPE html>
<html>
  <body>
    <input type="button" value="Click" id="inputId">
    <script>
      inputId.onclick = function(event) {
        // show event type, element and coordinates of the click
        alert(event.type + " at " + event.currentTarget);
        alert("Coordinates: " + event.clientX + ":" + event.clientY);
      };
    </script>
  </body>
</html>

And the same thing in javascript:

let input = document.createElement('input');
input.id = 'inputId';
input.setAttribute('type', 'button');
input.setAttribute('value', 'Click');
document.body.appendChild(input);
  
inputId.onclick = function (event) {
  // show event type, element and coordinates of the click
  alert(event.type + " at " + event.currentTarget);
  alert("Coordinates: " + event.clientX + ":" + event.clientY);
};

Some of the properties of the event object are the following:

  • event.type: the type of the event ( in the example above, it’s “click”).
  • event.currentTarget: the element, which handled the event. It is equivalent to this, unless the handler belongs to arrow functions, or this is linked to something else. Then you should get the element from event.currentTarget.
  • event.clientX / event.clientY: these are the cursor’s window-relative coordinates, for the mouse.

The properties of the event object are not limited to what was represented above, but these are the most common ones.

Object handlers: handleEvent

Like a function, an object can also be assigned as an event handler with the help of addEventListener. Whenever an event happens, its handleEvent method is called, like here:

<!DOCTYPE html>
<html>
  <body>
    <button id="buttonId">Click</button>
    <script>
      buttonId.addEventListener('click', {
        handleEvent(event) {
          alert(event.type + " at " + event.currentTarget);
        }
      });
    </script>
  </body>
</html>

You can notice that addEventListener gets an object as a handler, calling object.handleEvent(event) in case of an event.

A class can also be used for that purpose, like this:

<!DOCTYPE html>
<html>
  <body>
    <button id="buttonId">Click me</button>
    <script>
      class Welcome {
        handleEvent(event) {
          switch(event.type) {
            case 'mousedown':
              buttonId.innerHTML = "Welcome to";
              break;
            case 'mouseup':
              buttonId.innerHTML += "... W3Docs.";
              break;
          }
        }
      }      
      let welcome = new Welcome();
      buttonId.addEventListener('mousedown', welcome);
      buttonId.addEventListener('mouseup', welcome);
    </script>
  </body>
</html>

However, the handleEvent method doesn’t have to do the whole job alone. It might call other event-specific methods too. Here is an example of calling an event-specific method:

<!DOCTYPE html>
<html>
  <body>
    <button id="buttonId">Click me</button>
    <script>
      class Welcome {
        handleEvent(event) {
          // mousedown -> onMousedown
          let method = 'on' + event.type[0].toUpperCase() + event.type.slice(1);
          this[method](event);
        }
        // Mouse button pressed
        onMousedown() {
          buttonId.innerHTML = "Welcome to ";
        }
  //and released     
        onMouseup() {
          buttonId.innerHTML += "...W3Docs.";
        }
      }      
      let welcome = new Welcome();
      buttonId.addEventListener('mousedown', welcome);
      buttonId.addEventListener('mouseup', welcome);
    </script>
  </body>
</html>

Summary

Events are not a part of the core JavaScript: they are defined in the browser Web APIs.

For any website with dynamic functionality, it is vital to deal with users that interact with them. In practice, events are the means that make it possible.

In general, events are a signal that something has occurred, telling you to respond to it.

There exist 3 ways of assigning the event handlers:

  • HTML attribute, such as onclick="...".
  • The property of DOM: elem.onclick = function.
  • Methods of adding and removing. Among them are elem.addEventListener(event, handler[, phase]) (for adding) and removeEventListener (for removing).

You need to use HTML properties moderately, as JavaScript can look a little odd in the middle of an HTML tag. Also, it is not possible to write a lot of code in it.

You can also use the DOM properties, but it is not possible to assign more than a handler of the specific event.

The last point, noted above, is the most flexible one. But, it’s the longest way of writing.




Do you find this helpful?

Related articles