Home > JavaScript > jQuery.elementData() and event

jQuery.elementData() and event

Three weekends ago, my friends and I went to jQuery Camp 2008 at MIT. It was in Boston at the MIT Stata Center on Sunday, September 28th. I have been to Boston a few times, but I never been inside MIT (technically, it’s in Cambridge, which is different city than Boston…), and Stata Center was a beautiful Frank Gehry’s building.

And those friends who I went with are in the group called Flax, which I organized for young Design/Programming professionals around New York city area. We meet up every month and drink beers, talk about what’s interesting, and give one presentation every month.

So this entry is from my presentation at October Flax, about what I recently learned from jQuery Camp 2008.

_0012318 In the second presentation John Resig gave at jQuery Camp, he was talking about several cool stuffs,

_0012329and jQuery.data() appeals to me a lot because I have done very similar thing! He called elementData(), but on the syntax, you do like jQuery.data(). What it does is bascially dictionary (more CS-precisely it is a Set or Associative array). You can store data with key under certain DOM Element. Though it seems no ways to fetch what vocaburary it has (like.. getAllKeys()). So I take this as a name-spaced dictionary designed for event handling. Why? That’s how my presentation goes.

Module aware design

Let’s start with how I get to think like this way. When you do Event in HTML, there’s several ways to do it. You can do <body.onload="do();">, or document.body.addEventListener('click', function(){do()}, false);. If you’re using prototype, you can do Evnet.observe(). In jQuery, you can do either $(document.body).bind('click'...); or $(document.body).click(...);. The issue is, either one of ways, when the event happens, the function context will be different, in other words, “this” keyword points different object.

page1 Let’s see the world situation. Like in this picture, you wanna add Drop-down menu on each <li> tag. What I originally did was..

  1. build a Controller Object to each page
  2. then made a dictionary object in Controller Object
  3. register functions associated with each <li> in dictionary
  4. register events wrapping by this Controller’s event receiver
  5. every time event happens, it will lookup dictionary where the event happens

It works pretty well, until some point.

page2 As this picture, if you have subsidiary (child) elements in <li> elements, what will happen? When the event happens, browser fires an associated function with a first argument as DOMEvent, and that has .target property. Why that is important? Because I used it as a key to look up the dictionary. But as shown in this picture, the targe might be different from what it was originally registered. I needed to tweak it by the event receving process, that was not beautiful.

Then, I listened to John Resing’s presentaiton, jQuery.elementData() idea. I can use this as dictionary and I can write wrapper function. My answer is building EventRunner.js.

  1. First you will register your event like this: EventRunner.register(dom, ‘click’, obj.click, obj)
  2. EventRunner actually register event with wrapping by EventRunner.receiveEvent()
  3. if it’s Firefox or Safari, just pass the .currentTarget object to EventRunner.perform()
  4. if not, use EventRunner.ascendEvent() will happen recursively…

Here’s some demos.

var EventRunner = {}

EventRunner.MAX_DEPTH = 5;

EventRunner.ascendEvent = function (ev, elm, counter)
{
  counter = counter || 0;
  //console.log(counter + ': ' + elm.tagName);
  if ((elm.tagName.toUpperCase() === 'BODY') || (counter > EventRunner.MAX_DEPTH))
  {
    console.log(counter + ': ' + elm.tagName);
    return false;
  }
  if (!EventRunner.perform(elm, ev))
  {
    EventRunner.ascendEvent(ev, elm.parentNode, ++counter);
  }
}

EventRunner.perform = function (elm, ev)
{
  var result = false;
  var value  = jQuery.data(elm, ev.type);
  if (value instanceof Function)
  {
    try
    {
      result = {'result': value(ev)};
    }
    catch (err)
    {
      console.log('error occurs');
      console.log(err);
      //alert(err.message);
    }
  }
  else if (value !== null)
  {
    result = value;
  }
  return result;
}

EventRunner.receiveEvent = function (ev)
{
  if (ev.currentTarget)
  {
    EventRunner.perform(ev.currentTarget, ev);
  }
  else
  {
    EventRunner.ascendEvent(ev, ev.target);
  }
}

EventRunner.register = function (dom, type, func, context)
{
  if (!dom)
  {
    throw new Error('You have to pass DOM Object');
  }
  if (context)
  {
    func = EventRunner.scope(context, func);
  }
  if (dom === window)
  {
    $(dom).bind(type, func);
    return;
  }
  jQuery.data(dom, type, func);
  $(dom).bind(type, EventRunner.receiveEvent);
}

EventRunner.scope = function (target, func)
{
  return function ()
  {
    func.apply(target, arguments);
  }
}

Comments:0

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://blog.nydd.org/2008/10/jquery-elementdata-and-event/trackback/
Listed below are links to weblogs that reference
jQuery.elementData() and event from Vantage Point of Queens

Home > JavaScript > jQuery.elementData() and event

Search
Feeds
Meta
Links
Ads!

Return to page top

levitra buy isotretinoin payday loan yes kamagra buy diflucan online order lasix online bad credit payday loans buy cipro buy azithromycin instant payday loans