JavaScript behaviours are roughly defined as an event handler that is set once, then handled by elements that are created on the fly later on.

For example, if I have a list of links referencing images which are loaded inline, adding an removing the links from this list would not require me to re-hook the event handler.

There is a jQuery plugin called LiveQuery which can handle this for you, and does so by caching the event handler you set and hooking in to the .append(), .after(), etc, methods to reattach the cached event handler to the newly created elements.

The poor man's behaviours takes a different approach.

UK EVENTAttend 2024

The conference for people who are passionate about the web. 8 amazing speakers with real human interaction and content you can't just read in a blog post or watch on a tiktok!

The technique is really very simple, and if you've been writing JavaScript you may have already made use of it in some form. It doesn't use a timer, and makes use of event bubbling.

In our example, our HTML would look like this:

<ul id="imageLinks">
  <li><a href="/images/1.jpg">Image 1</a></li>
  <li><a href="/images/2.jpg">Image 2</a></li>
  <li><a href="/images/3.jpg">Image 3</a></li>

Clicking on a link would load the image dynamically, but for our example, we'll just log the image url.

The JavaScript event handling is set on the ul element instead of the anchor elements.

// addEvent function for IE + Firefox
var addEvent = (function () {
  return document.body.addEventListener ? function (e, ev, fn) {
    e.addEventListener(ev, fn, false);
  } : function () {
    e.attachEvent("on" + ev, fn);

addEvent(document.getElementById('imageLinks'), 'click', function (event) {
  // only proceed if the user click on an anchor
  var el =;
  if (el.nodeName == 'A') {
    // this is our real event code - which we can read values
    // from the 'el' variable, including .href, .rel, etc. to
    // handle specific like code
    return false; // cancel click event

As you can see the core of the event handling is within the if (el.nodeName == 'A') (note the casing on the nodeName must be capitalised). If you need to match a class name, you can do it here too.

Taking it Further

This can be converted to a jQuery plugin, that supports more complicated selector matches, again without any timeouts.

It's limitation over LiveQuery, is that it's restricted to a subset of elements, i.e. a group of links that match X selector within a UL.

(function ($) {
  $.fn.behaviour = function (selector, fn) {
    return (ev) {
      var el =;
      if ($(el).is(selector)) {

$(function () {
  $('#imageLinks').behaviour('a', function () {
    console.log('Clicked link: ' + this.href);
    return false;

Here's a working demonstration of poor man's behaviours