Master Sword
<%= 'Cause it's late and your mama don't know %>
Sword

Event Selectors, Data Objects, and akt.js

When developing web applications without an organized approach to writing JavaScript, you can quickly end up with quite the mess. Inlining script tags in HTML partials may seem innocent enough—especially when a project is in its infancy. However, a few click handlers here and a dash of data-binding there can spiral out-of-control in a hurry. The appeal of inlining server-rendered arguments in function invocations becomes an afterthought. The behavioral component of your application becomes exceedingly brittle, and each subsequent change becomes a new turn in a frustrating game of Jenga.

...
<button class="btn">Go!</button>
<script>
  jQuery('.btn').on('click', function(e) {
    alert('Go!'); 
  });
</script>
...

Here are a few weaknesses to this approach:

  1. Increased likelihood of global scope pollution
  2. Scattered and incoherent code
  3. Blocking inline scripts

A separate concern is the common usage of class- and id-based selectors for wrapping DOM elements in jQuery objects. While there are certainly performance considerations to be made when stepping away from this practice, it is worth thinking about selection in terms of separating concerns. In the code snippet above, the btn class is probably serving multiple purposes: we use it as a CSS selector to apply styles and as a DOM element selector to bind an event handler. This type of coupling should trouble us. If at some point we decide to apply the styles associated with the flat-btn class—switching out the class name—we effectively break the behavior associated with the .btn selector.

Event Selectors & Data Objects

I’ve found that using a separate “event selector” can be a great way to isolate responsibility and convey behavioral meaning. This is essentially just a specific data attribute with intention-revealing values used throughout the application. We can of course use the data attribute and its value as a DOM element selector, much like we would use a class or id.

<button data-event-selector="btn-trigger-go">Go!</button>

...

function $(selector) {
  return jQuery('[data-event-selector="' + selector + '"]');
}

var $btn = $('btn-trigger-go'); 

Also, in the absence of view models (a la Knockout or Angular), it helps to have a painless way to pass data around the application. Rather than creating separate data attributes for each piece of information we need to process, we can make use of something like Michael Best’s JavaScript Object Literal Parser to parse all data from a single “data object” attribute.

<button data-event-selector="btn-trigger-go"
        data-data-object="name: 'Gatsby', teams: 2">Go!</button>

...

var data = parseObjectLiteral($('btn-trigger-go').
           data('eventSelector'));

akt.js

I bundled these two concepts—event selectors and data objects—into a small JavaScript library called akt.js. The README describes things fairly succinctly. Enjoy.