Event Handling

When doing Ajax event handling is necessary. Most (or actually all) Ajax libraries support browser-abstracted event handling. I took from many of these and made my own with nice features from all of them.

I will list the features here later, but here's the code now:

  1. //////////// EVENT ///////////////
  2.  
  3. var addEvent;
  4. var removeEvent;
  5. var getEvent;
  6.  
  7. (function() {
  8. var curId = 0;
  9. var delayedListeners = [];
  10. var listeners = {};
  11. var windowLoaded = false;
  12. function getObjId(object) {
  13. if (!object.__eventId)
  14. object.__eventId = ++curId;
  15. return object.__eventId;
  16. }
  17. function getEventId(element, event, listener) {
  18. var listener = listener.length == 2 ? getObjId(listener[0]) + '_' + getObjId(listener[1]) : getObjId(listener);
  19. return getObjId(element) + "_" + event + "_" + listener;
  20. }
  21. function addListener(element, event, listener) {
  22. if (typeof element == 'string' && !windowLoaded) {
  23. delayedListeners.push(arguments);
  24. return true;
  25. }
  26. if (typeof element == "string")
  27. element = document.getElementById(element);
  28. if (!element)
  29. return false;
  30. var obj = listener.length == 2 ? listener[0] : element;
  31. var func = listener.length == 2 ? listener[1] : listener;
  32. var args = Array.prototype.splice.call(arguments, 3, arguments.length);
  33. var proxy = function(event) {
  34. args.push(event);
  35. func.apply(obj, args);
  36. }
  37. listeners[getEventId(element, event, listener)] = {listener: listener, proxy: proxy};
  38. if (element.addEventListener)
  39. element.addEventListener(event, proxy, false);
  40. else if (element.attachEvent)
  41. element.attachEvent('on' + event, proxy);
  42. return true;
  43. }
  44. function removeListener(element, event, listener) {
  45. if (typeof element == "string")
  46. element = document.getElementById(element);
  47. var eventId = getEventId(element, event, listener);
  48. if (!eventId in listeners)
  49. return false
  50. var proxy = listeners[eventId].proxy;
  51. delete listeners[eventId];
  52. if (element.removeEventListener)
  53. element.removeEventListener(event, proxy, false);
  54. else if (element.detachEvent)
  55. element.detachEvent('on' + event, proxy);
  56. return true;
  57. }
  58. addEvent = function(element, event, listener) {
  59. if (element.length && typeof element != 'string') {
  60. var args = Array.prototype.splice.call(arguments, 0, arguments.length);
  61. for (var i = 0; i < element.length; i++) {
  62. args[0] = element[i];
  63. addListener.apply(this, args);
  64. }
  65. } else
  66. addListener.apply(this, arguments);
  67. };
  68. removeEvent = function(element, event, listener) {
  69. if (element.length && typeof element != 'string') {
  70. for (var i = 0; i < element.length; i++)
  71. removeListener(element, event, listener);
  72. } else
  73. removeListener(element, event, listener);
  74. };
  75. function stop() {
  76. this.stopPropagation();
  77. this.preventDefault();
  78. }
  79. function find(nodeName, useRelatedTarget) {
  80. nodeName = nodeName.toUpperCase();
  81. var node = useRelatedTarget ? this.relatedTarget : this.target;
  82. while (node.nodeName != nodeName && node.parentNode)
  83. node = node.parentNode;
  84. if (node.nodeName == nodeName)
  85. return node;
  86. }
  87. getEvent = function(event, property) {
  88. if (event.isSetup)
  89. return event;
  90. if (isIE) {
  91. event = window.event;
  92. event.stopPropagation = new Function("this.cancelBubble = true");
  93. event.preventDefault = new Function("this.returnValue = false");
  94. event.target = event.srcElement;
  95. if ("fromElement" in event)
  96. event.relatedTarget = event.fromElement;
  97. else if ("toElement" in event)
  98. event.relatedTarget = event.toElement;
  99. if (!("layerX" in event) && "offsetX" in event) {
  100. event.layerX = event.offsetX;
  101. event.layerY = event.offsetY;
  102. }
  103. } else {
  104. if (event.target.nodeType == 3) event.target = event.target.parentNode;
  105. }
  106. if ("button" in event)
  107. event.mouseButton = event.button != 2 ? 1 : 2;
  108. if (!("pageX" in event) && "clientX" in event) {
  109. event.pageX = event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
  110. event.pageY = event.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
  111. }
  112. event.stop = stop;
  113. event.find = find;
  114. event.isSetup = true;
  115. return event;
  116. };
  117. function onWindowUnload() {
  118. if (!listeners) return;
  119. for (var i = 0; i < listeners.length; i++) {
  120. var element = listeners[i][0];
  121. var event = listeners[i][1];
  122. var proxy = listeners[i][4];
  123. try { // if the element no longer exists, don't throw an error
  124. if (element.removeEventListener)
  125. element.removeEventListener(event, proxy, false);
  126. else if (element.detachEvent)
  127. element.detachEvent('on' + event, proxy);
  128. } catch(e) {}
  129. delete listeners[i];
  130. }
  131. delete listeners;
  132. }
  133. function onWindowLoad() {
  134. windowLoaded = true;
  135. for (var i = 0; i < delayedListeners.length; i++) {
  136. addListener.apply(this, delayedListeners[i]);
  137. }
  138. }
  139. addEvent(window, 'unload', onWindowUnload);
  140. addEvent(window, 'load', onWindowLoad);
  141. })();