Applying a behavior to an element is a very common task in web applications and rich web sites. Something like an element onload event that is called whenever it?s ready, regardless of whether it?s pre-created in the html, or dynamically added.

For example:

  • Converting a dropdown list ( can be converted to image base on its .checked property as soon as it’s appended to the document.

    If you use Ajax to get HTML from server, you shouldn’t be worried about wiring up events to elements.

    As Event Delegation is good for attaching events to all elements of a certain type, OhBehave does the same for more complex behaviors.

    How does it work?

    For every browser I had to find a different solution, as each of which implements the desired functionality differently. Each of the implementations is a small browser-specific code that calls OhBehave.initialize, which receives an element and applies all behaviors needed.

    The behaviors for that element are defined in its class attribute, each of which is prefixed with ?oh-behave-? (optional). E.g. oh-behave-AutoComplete, oh-behave-WrapWithFrame.

    Example for a behavior

    1
    2
    3
    4
    5
    6
    7
    
    OhBehave.behaviors["AlertTheTime"]=function (element) {
        element.onclick=function () {
            alert(new Date());
        };
    };
    
    // or, as a global function -- function AlertTheTime(element) { ... }
    

    Implementations

    Firefox (Gecko Engine) - XBL

    XBL, or ? XML Binding Language, is a markup language, based on XML, that is defined according to a W3C standard and is used for applying rich behavior to an element. XBL allows us to declare properties (including getters/setters), custom events (and to fire them), custom methods and custom style. The XBL is placed on an element using css:

    1
    
    .oh-behave { -moz-binding:url("oh-behave.xml#oh-behave"); }
    

    The XML structure:

    1
    2
    3
    4
    5
    6
    7
    
    <bindings xmlns="http://www.mozilla.org/xbl" xmlns:html="http://www.w3.org/1999/xhtml">
    <binding id="oh-behave">
            <implementation>
                <constructor>OhBehave.initialize(this);</constructor>
            </implementation>
        </binding>
    </bindings>
    

    As for now, only the Gecko engine supports XBL, even though it?s a standard.

    IE (Trident Engine) - HTC

    HTC, or ? HTML Component is Microsoft?s implementation for applying rich behavior to an element. It supports more or less the same as XBL.

    Safari/Chrome (WebKit Engine) and Opera (Presto Engine) - The Event DOMNodeInserted

    As WebKit/Presto didn’t include XBL yet (there are some mentions in the source code but it’s still turned off probably), I had to find a different solution.

    The DOMNodeInserted event (a W3C standard) is fired any time an element is inserted dynamically (innerHTML / createElement & appendChild). Through this event I look for elements that should have the behavior. The lookup is done with querySelectorAll - a method of a document or element that gets a CSS selector and returns all elements for that selector.

    For elements that are already in the document, I used the DOMContentLoaded event, which may cause a small flick but the engine is so fast that I barely believe it’s noticeable.

    Code

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    // behavior example - assigns alert of the current time onclick
    OhBehave.behaviors["AlertTheTime"]=function (element) {
      element.onclick=function () {
          alert(new Date());
      };
    };
    // behavior example - adds a frame around an element
    OhBehave.behaviors["WrapWithFrame"]=function (element) {
      var frame=document.createElement("div");
      frame.className="cornerized";
      element.parentNode.replaceChild(frame,element);
      frame.appendChild(element);
    
      var corners=["tl","tr","bl","br"];
      for (var i=corners.length;i--;) {
          var corner=document.createElement("div");
          corner.className="c "+corners[i];
          frame.appendChild(corner);
      }
    };
    
    1
    
    <div class="oh-behave oh-behave-WrapWithFrame oh-behave-AlertTheTime">Auto apply behavior on existing element</div>
    

    When the div appears on the screen, it obtains immediately the onclick event and being wrapped with a box with 4 corners.

    Demo

    In the demo page there are two behaviors applied on same element: 1) Wraps the element with a frame and some other elements, 2) Attaches a click event to show current date.

    In addition, there’s a button that adds more elements, dynamically and the behaviors applied automagically.

    Demo of OhBehave | Download Source

    Attention! In case you only need to attach events, you should use the Event Delegation method.

Comments