/*
File: EventRunner.js

EventRunner is a utility object that will handle Event with jQuery way.  All mehtods/properties exist STATIC on EventRunner object.

License:
  MIT-style license.

Author:
  Takashi Mizohata <beatak@nydd.org>

Copyright:
  2008 [nydd](http://code.nydd.org/).
*/


var EventRunner = {}


/*
Variable: MAX_DEPTH

Maximum depth for ascending dom tree when the event performs.
*/
EventRunner.MAX_DEPTH = 5;


/*
Method: ascendEvent

if the given elm has event, will perform, otherwise ascend DOM tree recursively.

Arguments:
  ev - (DOMEvent)
  elm - (DOMNode)
  counter - (uint)

Return:
  (undef)
*/
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);
  }
}


/*
Method: perform

Thie will execute the method or return values which are associated with the given element and event.

Arguments:
  elm - (DOMNode)
  ev - (DOMEvent)

Return:
  (*) Object if the event method found and executed, or variable associated with the given event, or false if nothing is associated with the given event
*/
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;
}


/*
Method: receiveEvent

If currentTarget is propery set (in Firefox and Safari), will execute the method right away, if not (in IE) will ascend DOMNode recursively.

Arguments:
  ev - (DOMEvent)

Return:
  (undef)
*/
EventRunner.receiveEvent = function (ev)
{
  if (ev.currentTarget)
  {
    EventRunner.perform(ev.currentTarget, ev);
  }
  else
  {
    EventRunner.ascendEvent(ev, ev.target);
  }
}


/*
Method: register

Wrapping event dispatching into EventRunner framwork.

Arguments:
  dom - (DOMNode)
  type - (String)
  func - (Function)
  context - (Object)

Return:
  (undef)
*/
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);
}


/*
Method: scope

will return fixed context for given function.  Equvalent to bind in prototype.js.

Arguments:
  target - (Object)
  func - (Function)

Return:
  (undef)
*/
EventRunner.scope = function (target, func)
{
  return function () 
  {
    func.apply(target, arguments);
  }
}


