// protoHover2
// a simple hover implementation for prototype.js
// Sasha Sklar and David Still - Updated by Rick Waldron
(function() {
  // Extend event with mouseEnter and mouseLeave
  Object.extend(Event, {
    //  Derived from jQuery
    isWithin:   function(_elem, evt) {
      // Check if mouse(over|out) are still within the same parent element
      var parent = evt.relatedTarget;

      // Traverse up the tree
      while (parent && parent != _elem) {
        try {
          parent = parent.parentNode;
        } catch (error) {
          parent = _elem;
        }
      }
      // Return true if we actually just moused on to a sub-element
      return parent == el;
    },
    mouseEnter: function(_elem, f, options) {
      _elem = $(_elem);
      // curry the delay into f
      var fc = (options && options.enterDelay)?(function(){window.setTimeout(f, options.enterDelay);}):(f);
      _elem.hovered = false;
      _elem.observe(  Prototype.Browser.IE ? 'mouseenter' : 'mouseover', function(evt) {
        // set this to the element and pass event as argument
        var _fc = function () { fc.call(_elem, evt); };
        // mouseover is simple, the only change to default behavior is we don't want hover fireing multiple times on one element
        if (!_elem.hovered) {
          // set hovered to true
          _elem.hovered = true;
          // fire the mouseover function
          _fc();
        }
      });
    },
    mouseLeave: function(_elem, f, options) {
      _elem = $(_elem);
      // curry the delay into f
      var fc = (options && options.leaveDelay)?(function(){window.setTimeout(f, options.leaveDelay);}):(f);
      _elem.observe(Prototype.Browser.IE ? 'mouseleave' : 'mouseoout', function(evt) {
        // set this to the element and pass event as argument
        var _fc = function () { fc.call(_elem, evt); };
        // get the element that fired the event
        var target = Event.element(evt);

        // if we leave the element we're observing
        if (!_elem.isWithin(evt)) {
          // fire the mouseover function
          _fc();
          // set hovered to false
          _elem.hovered = false;
        }
      });
    }      
  });
  // add method to Prototype extended element
  Element.addMethods({
    hover: function(_elem, _enterFn, _leaveFn, options) {
      options = Object.extend({}, options) || {};
      Event.mouseEnter(_elem, _enterFn, options);
      Event.mouseLeave(_elem, _leaveFn, options);
    }
  });
})();