Tobiasz Cudnik

Posts Tagged ‘reglib’

Utilizing Mutation Events for automatic and persistent event attaching

In Ideas, Snippets on 19.01.2009 at 19:43

Most of you probably heard about Event Delegation, a technique where you bind to event of interest on parent node and when triggered event bubbles from child node, action in taken inside the parent. This pattern is widely popularized by reglib and Live Query (plugin for jQuery). Newly released jQuery 1.3 has it’s own implementation thou $.live() method.

This patten has couple of advantages over classic attaching model. First, it’s faster for BIG number of (same) nodes. Secondly, which is most important i think, it allows easy content exchange via AJAX. But with all that it has also disadvantages and main is that you doesn’t really attach to a node, only to it’s parent. That means when you relocate node in the DOM it looses it’s behavior.

That’s why i’ve came with the idea of using Mutation Events to take best parts from both patterns. Mutation Events aren’t supported in IE, but i’ve rolled out some compatibility layer to target this problem. Works also with document fragment appends introduced in jQuery 1.3.

You can go straight to the demo, which was tested and works with:

  • Firefox 3 and 2 linux
  • IE6 SP2 win32
  • Opera 9.63 linux
  • Safari 3.6 win32
  • Chrome 1.0 win32

First lets see main code:

function attachEvents(node) {
	// node is an optional callback for filter()
	// that applies rules only for new nodes
	node = node || '*';
	$('.container1 .trigger1').filter(node).click(function(e) {
		alert('mutation events work');
		e.preventDefault();
	});
}

This is simple, common function that applies behaviors to the document. The only major difference from other such functions is node parameter, used as callback for filter() method, which limits found nodes to interesting ones. Now the actual event bindings:

// node inserted into DOM
$(document).bind('DOMNodeInserted', function(e) {
	attachEvents(function(node){
		return !e.target.skipEventAttaching &&
			this == e.target
	});
});
// node removed from DOM
$(document).bind('DOMNodeRemoved', function(e) {
	// add information property, that node has been detached
	e.target.skipEventAttaching = true;
});

Here the magic happens ;) First handler fires up our event attaching function with callback for filter as a parameter. Callback will check if found node is target of the mutation event or is it reinserted. Second handler adds flag about reinserting.

You can see demo which compares this technique with jQuery 1.3 and reglib. It consists of 3 different implementation:

  • jQuery 1.3 using Mutation Events
  • jQuery 1.3 using $.live
  • reglib

Test it like this: click add node (couple of times), click .trigger (first one, last one) then do move node and again click moved node. Each time when clicking on .trigger, one (and only one) alert should pop out saying that certain technique works.

Additionally there’s a IE compatibility for mutation events in conditional comment. Great help writing it was from ieproto example.

Of course this is proof-of-concept and souldn’t be used in production until fully tested and fixed.