if (!window.Event) {

  var Event = new Object();

}


Object.extend(Event, {

  KEY_BACKSPACE: 8,

  KEY_TAB:       9,

  KEY_RETURN:   13,

  KEY_ESC:      27,

  KEY_LEFT:     37,

  KEY_UP:       38,

  KEY_RIGHT:    39,

  KEY_DOWN:     40,

  KEY_DELETE:   46,

  KEY_HOME:     36,

  KEY_END:      35,

  KEY_PAGEUP:   33,

  KEY_PAGEDOWN: 34,


  element: function(event) {

    return event.target || event.srcElement;

  },


  isLeftClick: function(event) {

    return (((event.which) && (event.which == 1)) ||

            ((event.button) && (event.button == 1)));

  },


  pointerX: function(event) {

    return event.pageX || (event.clientX +

      (document.documentElement.scrollLeft || document.body.scrollLeft));

  },


  pointerY: function(event) {

    return event.pageY || (event.clientY +

      (document.documentElement.scrollTop || document.body.scrollTop));

  },


  stop: function(event) {

    if (event.preventDefault) {

      event.preventDefault();

      event.stopPropagation();

    } else {

      event.returnValue = false;

      event.cancelBubble = true;

    }

  },


  // find the first node with the given tagName, starting from the

  // node the event was triggered on; traverses the DOM upwards

  findElement: function(event, tagName) {

    var element = Event.element(event);

    while (element.parentNode && (!element.tagName ||

        (element.tagName.toUpperCase() != tagName.toUpperCase())))

      element = element.parentNode;

    return element;

  },


  observers: false,


  _observeAndCache: function(element, name, observer, useCapture) {

    if (!this.observers) this.observers = [];

    if (element.addEventListener) {

      this.observers.push([element, name, observer, useCapture]);

      element.addEventListener(name, observer, useCapture);

    } else if (element.attachEvent) {

      this.observers.push([element, name, observer, useCapture]);

      element.attachEvent('on' + name, observer);

    }

  },


  unloadCache: function() {

    if (!Event.observers) return;

    for (var i = 0, length = Event.observers.length; i < length; i++) {

      Event.stopObserving.apply(this, Event.observers[i]);

      Event.observers[i][0] = null;

    }

    Event.observers = false;

  },


  observe: function(element, name, observer, useCapture) {

    element = $(element);

    useCapture = useCapture || false;


    if (name == 'keypress' &&

        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)

        || element.attachEvent))

      name = 'keydown';


    Event._observeAndCache(element, name, observer, useCapture);

  },


  stopObserving: function(element, name, observer, useCapture) {

    element = $(element);

    useCapture = useCapture || false;


    if (name == 'keypress' &&

        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)

        || element.detachEvent))

      name = 'keydown';


    if (element.removeEventListener) {

      element.removeEventListener(name, observer, useCapture);

    } else if (element.detachEvent) {

      try {

        element.detachEvent('on' + name, observer);

      } catch (e) {}

    }

  }

});


/* prevent memory leaks in IE */

if (navigator.appVersion.match(/\bMSIE\b/))

  Event.observe(window, 'unload', Event.unloadCache, false);

