
pulp.Modules['event.delegate'] = false;

/** @ignore */
pulp.event.custom['event:delegate'] = {
  /** @ignore */
  add: function(delegator, eventDelegate, selector, type, handler, bubbleLevel) {
    delegator = delegator || pulp.document;
    bubbleLevel = bubbleLevel || 0;
    return {
      /** @ignore */
      handler: function(event) {
        var node = event.target;
        do {
          if (pulp.cssQuery.match(node, selector)) {
            handler.call(event.target, event);
          }
        } while (bubbleLevel-- && (node = node.parentNode) && node != delegator)
      },
      type: type,
      node: delegator
    };
  },
  /** @ignore */
  remove: function(delegator, eventDelegate, selector, type/*, handler, delegator*/) {
    return {
      type: type
    };      
  }
};

/**
 * Add event handlers to elements via CSS selectors
 * @class
 * @param {String} selector  The CSS selector identifying a set of elements
 * @param {String} type  The event type (e.g. mouseover, click, etc.)
 * @param {Function} handler  The function to call when the event is triggered
 * @param {String|Element} delegator [optional]  The parent container inside which events are observed [default=document]
 * @param {Number} bubbleLevel [optional]  The number of steps to traverse up the DOM tree to look for matches [default=0]
 * @return {Element}  The element passed
 * @example
 *   // pass arguments
 *   pulp.event.delegate('a.modal', 'click', displayMyModal);
 *   pulp.event.delegate('div.expand', 'click', expandSection);
 *   
 *   // pass a "ruleset" object
 *   pulp.event.delegate({
 *     'a.modal': {
 *       click: displayMyModal
 *     },
 *     'div.expand': {
 *       click: expandSection
 *     }
 *   });
 */
pulp.event.delegate = function(selector, type, handler, delegator, bubbleLevel) {
  if (typeof selector == 'string') {
    pulp.event.observe(delegator, 'event:delegate', selector, type, handler, bubbleLevel);
    
  } else {
    var ruleset = selector;
    delegator = type;
    bubbleLevel = handler;
    for (selector in ruleset) {
      for (type in ruleset[selector]) {
        pulp.event.observe(delegator, 'event:delegate', selector, type, ruleset[selector][type], bubbleLevel);
      }
    }
  }
};

/**
 * Remove a handler
 * 
 * @param {String} selector  The CSS selector identifying a set of elements
 * @param {String} type  The event type (e.g. mouseover, click, etc.)
 * @param {Function} handler  The function to call when the event is triggered
 * @param {String|Element} delegator [optional]  The parent container inside which events are observed [default=document]
 * @param {Number} bubbleLevel [optional]  The number of steps to traverse up the DOM tree to look for matches [default=0]
 * @return {Element}  The element passed
 * 
 * @example
 *   // pass arguments
 *   pulp.event.stopDelegating('a.modal', 'click', displayMyModal);
 *   pulp.event.stopDelegating('div.expand', 'click', expandSection);
 *   
 *   // pass a "ruleset" object
 *   pulp.event.stopDelegating({
 *     'a.modal': {
 *       click: displayMyModal
 *     },
 *     'div.expand': {
 *       click: expandSection
 *     }
 *   }); 
 */
pulp.event.stopDelegating = function(selector, type, handler, delegator) {
  if (typeof selector == 'string') {
    pulp.event.stopObserving(delegator, 'event:delegate', selector, type, handler);
    
  } else {
    var ruleset = selector;
    delegator = type;      
    for (selector in ruleset) {
      for (type in ruleset[selector]) {          
        pulp.event.stopObserving(delegator, 'event:delegate', selector, type, ruleset[selector][type]);
      }
    }
  }
};
