Thursday, February 11, 2016

JavaScript Events

Types of Events

In a browser events are dispatched to objects to signal that something has happened, such as network activity or user interaction.
  • W3C DOM Events Interfaces
    • UIEvent: user interface events occur for an interaction with browser's window
    • FocusEvent: occur when an element (link or form field) gains or loses focus
    • MouseEvent: occur when user uses mouse, touchscreen, trackpad
    • KeyboardEvent: occur when user uses keyboard
    • [deprecated] MutationEvent: occur for a modification of DOM structure or DOM node
    • MutationObserver: occur for a modification of DOM structure or DOM node
  • W3C HTML5 Events Interfaces
    • FormEvent: occur for an interaction with form element
    • Various Interfaces: occur for an interaction with web page
  • Vendor Specific BOM Events
    • Events that deals with touchscreen and accelerometer

Event Terminology

The image below is not meant to be an UML diagram, it is simply a collection of terms commonly used when speaking about events in JavaScript.

Event Handling Workflow

  1. select a DOM node
  2. bind the selected node with the wanted event
  3. write the code that is to be executed when the event fires

How to bind events to an element

When you bind an event to an element you are stating which element you are waiting to happen and which element you expect that event to happen upon.

There are three ways to register an event handler:

  • HTML event handler attributes
  • DOM level 1 event handler
  • DOM level 2 event listener

HTML Event Handler Attributes

Some HTML elements have attributes that can be used to respond to events: you bind the attribute to a function that is to run when the even fires. HTML event handler attributes are bad practice, because they mix HTML and JavaScript, do not use them.

Example: HTML event handler attributes

DOM level 1 event handler

The GlobalEventHandlers interface is implemented by window, document and HTMLElement.

With DOM event handlers, you can bind only a function to each event handler property.

How to use DOM event handlers:

<script>
function handler(){}
window.ontype = handler;
</script>
<script>
function handler(){}
var element = document.getElementById('id');
element.ontype = handler;
</script>

Example: DOM1 element.onblur event handler

DOM level 2 event listener

The EventTarget interface is implemented by DOM and BOM objects. The interface allows registration of EventListeners on an EventTarget and dispatch of events to that EventTarget.

How to use DOM event listener:

<script>
function listener(){}

var element = document.getElementById('id');

if (element.addEventListener) {
  element.addEventListener('type', listener[, isCapture]); 
} else {
  element.attachEvent('ontype', listener);  // IE 5-8 fallback
}
</script>

What is the value of the this keyword inside the listener function body ?

  • with the obj.addEventListener() method, the listener is invoked as a method of obj and the this keyword refers to the that object.
  • with the obj.attachEvent('ontype', listener) method (IE 5-8), the listener is invoked as a global function and the this keyword refers to the window object.

Example: DOM2 listener for blur events

How to pass values to event handlers and event listeners

Assign the event handler/listener an anonymous function, in the body of the anonymous function call a named function passing values.

<script>
function listener(par1, par2, ... ){}

var element = document.getElementById('id');

element.addEventListener('type', function(){ listener(arg1, arg2, ... ); } [, boolean]);
</script>

Event Flow

HTML elements are contained inside other elements. When you click on a link, an event fires on the <a> element and also on the other nodes that are ancestors of the <a> element node.

You can bind events to the <a> element and also to any containing element: <div>, <body>, <document>, <window>.

The order in which the events fire is known as event flow:

  • event bubbling: events start from the most specific and flow outwards
  • event capturing: events start at the least specific and flow inwards

When flow matter? The flow of events matters when your code has event handlers on an element and its ancestor or descendant element nodes.

  • event handlers: defaults to using capture
  • event listeners: third argument is true/false means capturing/bubbling phase

The event object

The event object contains helpful information such as which node raised the event (the target element), which key was pressed (for keypress event), which part of the viewport the user pressed (for a click event).

The event object is passed to the function that is an event handler or an event listener. If you use an anonymous wrapper function to pass arguments, the event will be the first argument passed to the anonymous wrapper function.

Important properties of the event object.

property nameIE8 property namemeaning
e.targete.srcElementthe element interacted
e.typee.typethe type of the event fired

How to pass the event object to event listeners

Event listener without parameters
function listener(e){
  if (!e) { e = window.event; }
  var targetEl = e.target || e.srcElement;
}
obj.addEventListener('type', listener[, boolean])
The listener function has to define a parameter (usually named e) to get a reference to the event object.
Event listener with parameters
function listener(e, par1, par2, ... ){
  if (!e) { e = window.event; }
  var targetEl = e.target || e.srcElement;
}
obj.addEventListener('type', function(e){
  listener(e, arg1, arg2, ... );
} [, boolean])

The anonymous function must name the event parameter. In the body of the anonymous function, invoke the named function passing the event as first argument.

Example: passing event object to blur event listener

Event Delegation

The user may interact with a lot of elements on a web page, such as many <td> or many <li> or many <button>, instead of adding an event listener on each element, you can add a single listener on a parent element. Event flow allows you to respond to a single element rather than responding to all its children elements: this is delegating the job to a parent element. Event delegation involves some benefits such as to solve browser inconsistency for the this keyword and work for new children elements
Example: an event listener listening to blur events on two target elements

Element's Default Behaviour - Event's Propagation

property nameIE8 property namemeaning
e.cancelablenot supportedcan you cancel the default behavior of the event?
method nameIE8 property namemeaning
e.preventDefault()e.returnValuecancel the default behaviour
e.stopPropagation()e.cancelBubblestop the event from bubbling or capturing

Some events (such as click event on a link, submit event on form) take the user to another page, this is called the default behaviour of the element. You can prevent the default behaviour of such elements by calling event's method: e.preventDefault(), IE5-8 has an equivalent property: e.returnValue = false.
If you have an event handler on an element and on its ancestors, you may want to stop the event from bubbling up. You can use the method: e.stopPropagation() or set the IE5-8 property e.cancelBubble = true to stop the event.

If you want to prevent default behaviour and the event from bubbling up further, you can use the return false in your function, it will work in all browsers.

No comments :

Post a Comment