Posts Tagged ‘elements’
OhBehave – Apply Behavior to Static/Dynamic Elements, Immediately
Wednesday, June 23rd, 2010Applying 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 (<select> tag) to an AutoComplete/custom designed select control
- Converting input type=checkbox/radio into images
- Wrapping an element with a complex frame (rounded corners, shadows, opacity)
- A floating label on a textbox and hiding it on a value change or focus
The Common, Bad Solution
A standard solution will be waiting until the DOM is ready (a function that exists in every self-respecting JS library), finding all elements with a certain class and calling a JS function on that element that will attach the behavior.
Disadvantages of this solution:
- Sometimes, it takes a little while until the DOM is ready, and meanwhile, the element appears in its original, behavior-less form
- When elements are dynamically added to the DOM (innerHTML / createElement & appendChild) – the behavior must be applied again on all new elements, manually.
- A generic solution for dynamic elements is having an interval in which looks for these elements. However, this lookup is slow and the delay may cause flickering.
Code Sample for the Bad Solution:
function applyBehaviors() {
var elements=$.select(".behavior");
for (var i=0;i<elements.length;i++) applySpecificBehavior(elements[i]);
}
$.domready(function () {
applyBehaviors();
});
$.ajax("url.html",{
onSuccess:function () {
applyBehaviors();
}
});
Or, an interval:
setInterval(function () {
var elements=$.select(".behavior");
for (var i=0;i<elements.length;i++) {
if (elements[i]._behaviorApplied) continue;
applySpecificBehavior(elements[i]);
elements[i]._behaviorApplied=true;
}
},200);
(The functions $.select, $.domready and $.ajax can be found in any JS library).
The Desired Solution – OhBehave
OhBehave is a neat script that is responsible for applying behaviors to elements immediately, as soon as they are available, without waiting for the rest of the DOM to load. In addition, it also applies the behavior on new dynamic elements.
You can create new elements on the fly or set an element’s innerHTML with new html tags, without worrying about attaching behaviors. An <input type=”checkbox”> 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
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:
.oh-behave { -moz-binding:url("oh-behave.xml#oh-behave"); }The XML structure:
<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
// 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);
}
};
<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.