summaryrefslogtreecommitdiff
path: root/EventListener.js
blob: fa3423b245938019465f11b5c522da6d84a736ff (plain)
  1. // EventListener | MIT/GPL2 | github.com/jonathantneal/EventListener
  2. this.Element && Element.prototype.attachEvent && !Element.prototype.addEventListener && (function () {
  3. function addToPrototype(name, method) {
  4. Window.prototype[name] = HTMLDocument.prototype[name] = Element.prototype[name] = method;
  5. }
  6. // add
  7. addToPrototype("addEventListener", function (type, listener) {
  8. var
  9. target = this,
  10. listeners = target.addEventListener.listeners = target.addEventListener.listeners || {},
  11. typeListeners = listeners[type] = listeners[type] || [];
  12. // if no events exist, attach the listener
  13. if (!typeListeners.length) {
  14. target.attachEvent("on" + type, typeListeners.event = function (event) {
  15. var documentElement = target.document && target.document.documentElement || target.documentElement || { scrollLeft: 0, scrollTop: 0 };
  16. // polyfill w3c properties and methods
  17. event.currentTarget = target;
  18. event.pageX = event.clientX + documentElement.scrollLeft;
  19. event.pageY = event.clientY + documentElement.scrollTop;
  20. event.preventDefault = function () { event.returnValue = false };
  21. event.relatedTarget = event.fromElement || null;
  22. event.stopImmediatePropagation = function () { immediatePropagation = false; event.cancelBubble = true };
  23. event.stopPropagation = function () { event.cancelBubble = true };
  24. event.target = event.srcElement || target;
  25. event.timeStamp = +new Date;
  26. // create an cached list of the master events list (to protect this loop from breaking when an event is removed)
  27. for (var i = 0, typeListenersCache = [].concat(typeListeners), typeListenerCache, immediatePropagation = true; immediatePropagation && (typeListenerCache = typeListenersCache[i]); ++i) {
  28. // check to see if the cached event still exists in the master events list
  29. for (var ii = 0, typeListener; typeListener = typeListeners[ii]; ++ii) {
  30. if (typeListener == typeListenerCache) {
  31. typeListener.call(target, event);
  32. break;
  33. }
  34. }
  35. }
  36. });
  37. }
  38. // add the event to the master event list
  39. typeListeners.push(listener);
  40. });
  41. // remove
  42. addToPrototype("removeEventListener", function (type, listener) {
  43. var
  44. target = this,
  45. listeners = target.addEventListener.listeners = target.addEventListener.listeners || {},
  46. typeListeners = listeners[type] = listeners[type] || [];
  47. // remove the newest matching event from the master event list
  48. for (var i = typeListeners.length - 1, typeListener; typeListener = typeListeners[i]; --i) {
  49. if (typeListener == listener) {
  50. typeListeners.splice(i, 1);
  51. break;
  52. }
  53. }
  54. // if no events exist, detach the listener
  55. if (!typeListeners.length && typeListeners.event) {
  56. target.detachEvent("on" + type, typeListeners.event);
  57. }
  58. });
  59. // dispatch
  60. addToPrototype("dispatchEvent", function (eventObject) {
  61. var
  62. target = this,
  63. type = eventObject.type,
  64. listeners = target.addEventListener.listeners = target.addEventListener.listeners || {},
  65. typeListeners = listeners[type] = listeners[type] || [];
  66. try {
  67. return target.fireEvent("on" + type, eventObject);
  68. } catch (error) {
  69. if (typeListeners.event) {
  70. typeListeners.event(eventObject);
  71. }
  72. return;
  73. }
  74. });
  75. // CustomEvent
  76. Object.defineProperty(Window.prototype, "CustomEvent", {
  77. get: function () {
  78. var self = this;
  79. return function CustomEvent(type, eventInitDict) {
  80. var event = self.document.createEventObject(), key;
  81. event.type = type;
  82. for (key in eventInitDict) {
  83. if (key == 'cancelable'){
  84. event.returnValue = !eventInitDict.cancelable;
  85. } else if (key == 'bubbles'){
  86. event.cancelBubble = !eventInitDict.bubbles;
  87. } else if (key == 'detail'){
  88. event.detail = eventInitDict.detail;
  89. }
  90. }
  91. return event;
  92. };
  93. }
  94. });
  95. // ready
  96. function ready(event) {
  97. if (ready.interval && document.body) {
  98. ready.interval = clearInterval(ready.interval);
  99. document.dispatchEvent(new CustomEvent("DOMContentLoaded"));
  100. }
  101. }
  102. ready.interval = setInterval(ready, 1);
  103. window.addEventListener("load", ready);
  104. })();