[JavaScript] Events

Events and handlers are the basic programming model of JavaScript in web browsers. JavaScript has been evolved to provide native support for handling events, and all modern browsers support the features.

Adding Handlers to Events

There are three ways to add handlers to events.

  • as an attribute to HTML tags
  • using the DOM object in the code
  • using the DOM methods – addEventListener() / removeEventListener()

To add the click event handler to the second button in code, you need to get the DOM element first.

function btnClicked() {
  alert("Button is clicked");
}
 
$(document).ready(function () {
  document.getElementById('click2').onclick = btnClicked;
});

Another way to add handlers to events is using the DOM methods.

  • addEventListener(type, listener)
  • removeEventListener(type, listener)

The “addEventListener()” method lets you add as many handlers as you want.

function btnClicked1() {
  alert("1. Button is clicked");
}
function btnClicked2()
{
  alert("2. Button is clicked ");
}
 
$(document).ready(function () {
  var btn = document.getElementById('click2');
  btn.addEventListener("click", btnClicked1);
  btn.addEventListener("click", btnClicked2);
});

Event Object

You can pass the Event object as the first parameter of an event handler. When an event is triggered, the appropriate event object is created and passed as an argument. It is very useful for keyboard or mouse events.

All event has the following properties :

  • bubbles: boolean
  • cancelable: boolean
  • target: the element that triggered the event
  • type: the name of the event
document.getElementById("btn1").onclick = function (e) {
  alert(e.target);
  alert(e.type);
};

Mouse and Keyboard events have the following properties :

  • clientX: the horizontal coordinate of the mouse pointer
  • clientY: the vertical coordinate of the mouse pointer
  • button: which mouse button is clicked
  • altKey: flag for ALT key
  • ctrlKey: flag for CTRL key
  • shiftKey: flag for SHIFT key

Note that there is no direct way to get which key is pressed. I will explain later how to do it.

Also event objects provide the following methods:

  • preventDefault() : to cancel any default action
  • stopPropagation() : to prevent further propagation of an event

Mouse Events

The most commonly used mouse events are :

  • onclick: clicks on an element
  • ondblclick: double-clicks on an element
  • onmouseover: the pointer is moved onto an element
  • onmouseout: the pointer is out of an element
  • onmousedown: presses a mouse button over an element
  • onmouseup: releases a mouse button over an element
function btnClicked(e) {
  alert(e.type + " : " + e.clientX + ", " + e.clientY);
  alert("target : " + e.target.tagName + " - " + e.target.id);
}
 
$(document).ready(function () {
  document.getElementById('btn1').onclick = btnClicked;
});

Keyboard Events

Keyboard related are :

  • onkeydown: the user is pressing a key
  • onkeypress: the user presses a key
  • onkeyup: when the user releases a key

To get the which key is pressed, you need to do some work.

In general, you can use the “which” property of the event.

function keyPressed(e) {
  var keycode = e.which; 
  alert(keycode);
}
 
$(document).ready(function () {
  document.getElementById('text1').onkeypress = keyPressed;
});

Page / Window Events

  • onload: a page or <object> has been loaded
  • onresize: a page view is resized
  • onscroll: a page view is scrolled
  • onunload: a page has unloaded
function pageResized() {
  var w = window.innerWidth;
  var h = window.innerHeight;
  alert(w + ", " + h);
}
 
$(document).ready(function () {
  window.onresize = pageResized;
});

Form Events

  • onfocus: an element gets focus
  • onblur: an element loses focus
  • onchange: the content of an element, the selection, or the checked state have changed
  • onreset: when a form is reset
  • onselect: a user selects some text for <input> and <textarea>
var txtBox = document.getElementById("text1");
txtBox.onfocus = function (e) {
  alert(e.target.id + " gets focus");
};
txtBox.onblur = function (e) {
  alert(e.target.id + " loses focus");
};
txtBox.onchange = function (e) {
  alert(e.target.value);
};

Events – Propagation

Understanding how events are propagated and when to add handlers are very important for web developers. Naive coding might result in unexpected behaviors that are hard to trace.

Event Propagation Models

There are three ways for the events to propagate:

  • Capturing: top-down
  • Bubbling: down-top
  • W3C model: Capturing -> Bubbling

All modern browsers support the W3C model. Therefore you can attach the event handler either at the capturing phase or the bubbling phase.

Traditional Model (using “onclick”)

For all browsers, a traditional event registration attaches the handler to the bubbling phase.

document.getElementById("div1").onclick = onClick1;
document.getElementById("btn1").onclick = onClick2;
 
function onClick1() { 
  alert("1"); 
}
function onClick2() { 
  alert("2"); 
}

The elements are nested.

<div id="div1" style="height:100px;background-color:Gray;">
  <input id="btn1" type="button" value="Click 1">
</div>

When the button is clicked, both elements respond to the click event.

Registering Events using “addEventListener()”

  • addEventListener(type, listener, bUseCapture)

The third parameter, “bUseCapture” is a Boolean value to specify which stage (capturing – ‘true’ or bubbling – ‘false’) the event is registered. It is very useful to control when the event is captured precisely.

document.getElementById("div1").addEventListener('click', onClick1, true);
document.getElementById("div2").addEventListener('click', onClick2, false);
document.getElementById("btn1").addEventListener('click', onClick3, true);
 
function onClick1() { alert("1"); }
function onClick2() { alert("2"); }
function onClick3() { alert("3"); }

The elements are also nested.

<div id="div1" style="height:300px;background-color:#ccc;">
  <div id="div2" style="height:200px;background-color:#999;">
    <input id="btn1" type="button" value="Click 1" />
  </div>
</div>

When the button is clicked, message boxes will be popped up in this order “1” – “3” – “2”.

If you want to register all handlers in the bubbling phase, set the flag to “false” or omit it (the default is false).


Stopping Event Propagation

When you attach handlers to the nested elements, all attached handlers will be triggered because of bubbling. This is usually not what you usually want.

The recommended way to cancel the bubbling is to use the event’s “stopPropagation()” method.

document.getElementById("clickBtn1").onclick = onClick1;
 
function onClick1(e) {
  alert("1");
  e.stopPropagation();
}

Canceling the Default Action

When you attach the “click” event handler to the anchor tag, it does not prevent you from navigating to another page, which is the default behavior of the <a>. What if you want not to execute the default action?

One way to prevent the default action is to return “false” from the event handler.

document.getElementById("myLink").onclick = onLinkClicked;

function onLinkClicked() {
  alert("Hello");
  return false;
}
 <a id="myLink">link</a>

This approach works in all major browsers.

W3C recommends to use the “preventDefault()” method.

document.getElementById("myLink").onclick = onLinkClicked;
 
function onLinkClicked(e) {
  alert("Hello");
  e.preventDefault();
}

load / DOMContentLoaded events

When working with JavaScript, you might wonder where you need to initialize your code (especially with DOM elements). There are a couple of ways to do it.

Initializing DOM elements

Suppose you want to set the random initial value (from 1 to 10) to the textbox.

<div>
  Random Value =
  <input id="randVal" type="text" />
</div>

You have a function to get the value.

var textbox = document.getElementById("randVal");
textbox.value = Math.floor((Math.random() * 10) + 1);

Now, where do you place this code to initialize the textbox successfully?

<head>

The most common place to put the code is in the section.

<head>
  <script>
  var textbox = document.getElementById("randVal");
  textbox.value = Math.floor((Math.random() * 10) + 1);
  </script>
</head>

If you open this page in the browser, you will get an error, something like “Unable to set the value of the property ‘value’: object is null or undefined.

When the document is parsed, browsers execute the JavaScript code as soon as the code is encountered. The code is executed even before the element is loaded.

At the end of the Document

Now, you can make use of the feature mentioned in the previous section. You can place the <script> tags at the end of the document. When the code is executed, all elements are already loaded.

<body>
  <div>
    Random Value =
    <input id="randVal" type="text" />
  </div>
  <script>
  var textbox = document.getElementById("randVal");
  textbox.value = Math.floor((Math.random() * 10) + 1);
  </script>
</body>

load Event

Even though you can put the code at the end of the document, it is not a good practice. What if you want to move the code to a separate file?

The better approach is to use the events. Let’s start with the familiar “load” event.

window.onload = function () {
  var textbox = document.getElementById("randVal");
  textbox.value = Math.floor((Math.random() * 10) + 1);
};

You can place this code at any place.

DOMContentLoaded

The problem with the “load” event is that the event is fired when all supporting files (styles and images) are completely downloaded and loaded. This behavior might be problematic when the page includes many big image files.

The “DOMContentLoaded” event is fired when the document has been completely loaded and parsed but without waiting for stylesheets, images, and subframes to finish loading.

document.addEventListener("DOMContentLoaded", function () {
  var textbox = document.getElementById("randVal");
  textbox.value = Math.floor((Math.random() * 10) + 1);
});

This event is HTML5 feature and supported in all major browsers.

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s