Contextual event binding with HTML 5 data attributes

Today we’ll see how to bind events along with the target context using the HTML 5 data attributes. This new event binding technique relies on the 3-actors model we introduce in this article.

Please note that the demo application in this article can be found in a demo application on GitHub https://github.com/doanduyhai/HTML5Tutorial

 

I One actor model

event-listener-one-actor-model

In the old days of web design, people used to put inline event handlers into their HTML tags:

...
<a href="#" onclick="doSomething();" title="click here to trigger action">Click Me</a>
...

In this model, the event binding is done in the HTML tag itself. The tag is playing two roles: data display and event listener.

No need to say that this is an anti-pattern leading to a bloated HTML code.

 

II Two actors model

After the DOM Level 2 Event Model specs were released, it is a best practice to move event listener out of HTML tags. This is the two actors model.

event-listener-two-actors-model
In this model, the event binding is achieved by two actors:

  • the DOM element, with a marker to be identified in the DOM tree. It is usually a dedicated style-less CSS class or an id attribute
  • the event listener, which listens to events and delegates the processing to an event handler
...
<a id="myLink" href="#" title="click here to trigger action">Click Me</a>
...
<span class="descriptionText">This is a description text</span>
...
<script type="text/JavaScript">

	jQuery('#myLink').click(doSomething);
	jQuery('.descriptionText').click(doSomethingElse);

	function doSomething() {...}
	function doSomethingElse() {...}
</script>

 

III Three actors model

HTML 5 has introduced a very convenient new feature: custom data-* attributes. It is now possible to embed custom data in HTML tags. A new event binding model is now possible: three actors model.

event-listener-three-actors-model

The first two actors is similar to the previous model. The new thing is that now it is possible for the event listeners and event handlers to retrieve the contextual custom data embedded in the event target.

  • the DOM element, with a marker to be identified in the DOM tree. It is usually a dedicated style-less CSS class, an id attribute. Now it can also be a custom data attribute
  • the event listener, which listens to events and delegates the processing to an event handler
  • the custom data which is exposed to event listeners and passed to event handlers

Let’s suppose we have table listing some books:

...
	<tr>
		...
		<td>Authors</td>
		<td>
			<a href="#" data-authors="Craig WALLS,Ryan BREIDENBACH">Craig WALLS,Ryan ...</a>
		</td>
		...
	</tr>
	...	
	<tr>
		...
		<td>Authors</td>
		<td>
			<a href="#" data-authors="Isaac ASIMOV">Isaac ASIMOV</a>
		</td>
		...
	</tr>
...

 

	...
	jQuery('[data-authors]').click(function(event)
	{
		var authors = $(event.currentTaget).attr('data-authors');
		displayAuthorsDetails(authors);
	});
	...
	...
	function displayAuthorsDetails(authors) {...}
	...

In the above example, the <a> tag exposes the custom data attribute “data-authors” which contains a list of authors for a book.

We use this custom data attribute as a selector to identify all <a> tags in the DOM tree (line 2) and bind a handler to the click event. The authors information is retrieved from the <a> tag and then passed to the event handler as argument (line 4).

This is a very convenient way to pass extra argument to event handlers. Before HTML 5 we had to rely on some hacks to do that, for example storing information in a hidden input element:

...
	&lt;tr&gt;
		...
		&lt;td&gt;Authors&lt;/td&gt;
		&lt;td&gt;
			&lt;input type=&quot;hidden&quot; value=&quot;Craig WALLS,Ryan BREIDENBACH&quot;/&gt;
			&lt;a href=&quot;#&quot;&gt;Craig WALLS,Ryan ...&lt;/a&gt;
		&lt;/td&gt;
		...
	&lt;/tr&gt;
	...	
	&lt;tr&gt;
		...
		&lt;td&gt;Authors&lt;/td&gt;
		&lt;td&gt;
			&lt;input type=&quot;hidden&quot; value=&quot;Isaac ASIMOV&quot;/&gt;
			&lt;a href=&quot;#&quot;&gt;Isaac ASIMOV&lt;/a&gt;
		&lt;/td&gt;
		...
	&lt;/tr&gt;
...

It is possible to have many custom attributes per DOM element, each of them bound to a distinct event handler.

...
	&lt;div class=&quot;tweet&quot; data-tweetId=&quot;123456&quot; data-tweetAuthor=&quot;duyhai&quot;&gt;
		...
		...
	&lt;/div&gt;
...

 

IV Demo

Please note that the demo application in this article can be found in a demo application on GitHub https://github.com/doanduyhai/HTML5Tutorial

I’ve created a demo application displaying a simple page with a list of books.

For each book, the title, authors and availability information are displayed. Authors name are abbrievated but it is possible to have the full list displayed by putting the mouse over the link (tooltip component by Twitter Bootstrap). The event binding is done using the data-authors attribute as selector.

event-listener-data-authors

It is possible to click on the magnifying glass icon to trigger an Ajax call to the server and retrieve all complete book details.

Internally the link tag contains a data-isbn custom attribute, containing the ISBN of the book. This attribute is used as selector to bind with an event listener and passed to event handler as parameter to trigger Ajax call.

event-listener-books

On response from the server, we display a modal panel with all the book details:

event-listener-book-details

Below is the Javascript code

!function ( $ )
{
	bindListeners('#booksTable');
	
	bindListeners('#bookDetails');
	
}(window.jQuery);

function bindListeners(selector)
{
	$(selector).find('[data-authors]').each(function(index, element)
	{
		var authors = $(element).attr('data-authors');
		createToolTip($(element),authors);
		
	});
	
	$(selector).find('[data-isbn]').click(function(e)
	{
		var isbn = $(e.currentTarget).attr('data-isbn');
		displayDetails(isbn);
		
	});
}

function createToolTip($element, message)
{
	$element.tooltip(
	{
			title: message
	});
}

function displayDetails(isbn)
{
	$.ajax({
		type: 'GET',
		url: 'book/find/'+isbn,
		dataType: 'json',
		success: function(book) {
			...		
			...
		}
	});
}

It is quite straightforward. On page load complete, we call a generic bindListener() method, passing the target DOM element as argument (lines 3 & 5).

This function will select all elements having the appropriate custom attribute and for each of them, bind the corresponding event handler function (lines 11 & 18).

With this approach, it is possible to create a generic event binding function delegating the event handling to appropriate handlers. This function acts as a central dispatcher for event binding.

 
 

3 Comments

  1. Vick Sa

    HTML Attributes are property of the elements which may have values and these attribute values are always enclosed in quotes. It’s providing to the browser with some additional information about an elements how the elements should appear or behave. HTML elements can contain one or more attributes, attribute names and attribute values are case-insensitive and separated by an equals (=) sign.

    [HTML Attributes](http://www.willvick.com/HTML/HTMLAttribute.aspx)

    [HTML Attributes Examples](http://www.willvick.com/HTML/HTMLExampleAttribute.aspx)

    [Youtube – HTML Tutorial – Attributes](http://www.youtube.com/watch?v=ucOXvaCEZgg)

    Reply
  2. हिन्दी

    Enjoy the open spaces while you are out too. yet. take it up with the sponsoring organization.

    Reply
  3. EDISON

    It is truly a nice and helpful piece of info. I am happy that you shared this helpful info with us. Please stay us informed like this. Thanks for sharing.

    Reply

Leave a Reply to Vick Sa Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.