delegate.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. var Class = require('./Class');
  2. var contain = require('./contain');
  3. function retTrue() {
  4. return true;
  5. }
  6. function retFalse() {
  7. return false;
  8. }
  9. function trigger(e) {
  10. var handlers = this.events[e.type];
  11. var handler;
  12. var handlerQueue = formatHandlers.call(this, e, handlers);
  13. e = new exports.Event(e);
  14. var i = 0,
  15. j,
  16. matched,
  17. ret;
  18. while ((matched = handlerQueue[i++]) && !e.isPropagationStopped()) {
  19. e.curTarget = matched.el;
  20. j = 0;
  21. while (
  22. (handler = matched.handlers[j++]) &&
  23. !e.isImmediatePropagationStopped()
  24. ) {
  25. ret = handler.handler.apply(matched.el, [e]);
  26. if (ret === false) {
  27. e.preventDefault();
  28. e.stopPropagation();
  29. }
  30. }
  31. }
  32. }
  33. function formatHandlers(e, handlers) {
  34. var current = e.target;
  35. var ret = [];
  36. var delegateCount = handlers.delegateCount;
  37. var selector;
  38. var matches;
  39. var handler;
  40. var i;
  41. if (current.nodeType) {
  42. for (; current !== this; current = current.parentNode || this) {
  43. matches = [];
  44. for (i = 0; i < delegateCount; i++) {
  45. handler = handlers[i];
  46. selector = handler.selector + ' ';
  47. if (matches[selector] === undefined) {
  48. matches[selector] = contain(
  49. this.querySelectorAll(selector),
  50. current
  51. );
  52. }
  53. if (matches[selector]) matches.push(handler);
  54. }
  55. if (matches.length)
  56. ret.push({
  57. el: current,
  58. handlers: matches
  59. });
  60. }
  61. }
  62. if (delegateCount < handlers.length) {
  63. ret.push({
  64. el: this,
  65. handlers: handlers.slice(delegateCount)
  66. });
  67. }
  68. return ret;
  69. }
  70. exports = {
  71. add: function(el, type, selector, fn) {
  72. var handler = {
  73. selector: selector,
  74. handler: fn
  75. };
  76. var handlers;
  77. if (!el.events) el.events = {};
  78. if (!(handlers = el.events[type])) {
  79. handlers = el.events[type] = [];
  80. handlers.delegateCount = 0;
  81. el.addEventListener(
  82. type,
  83. function() {
  84. trigger.apply(el, arguments);
  85. },
  86. false
  87. );
  88. }
  89. selector
  90. ? handlers.splice(handlers.delegateCount++, 0, handler)
  91. : handlers.push(handler);
  92. },
  93. remove: function(el, type, selector, fn) {
  94. var events = el.events;
  95. if (!events || !events[type]) return;
  96. var handlers = events[type];
  97. var i = handlers.length;
  98. var handler;
  99. while (i--) {
  100. handler = handlers[i];
  101. if (
  102. (!selector || handler.selector == selector) &&
  103. handler.handler == fn
  104. ) {
  105. handlers.splice(i, 1);
  106. if (handler.selector) {
  107. handlers.delegateCount--;
  108. }
  109. }
  110. }
  111. },
  112. Event: Class({
  113. className: 'Event',
  114. initialize: function Event(e) {
  115. this.origEvent = e;
  116. },
  117. isDefaultPrevented: retFalse,
  118. isPropagationStopped: retFalse,
  119. isImmediatePropagationStopped: retFalse,
  120. preventDefault: function() {
  121. var e = this.origEvent;
  122. this.isDefaultPrevented = retTrue;
  123. if (e && e.preventDefault) e.preventDefault();
  124. },
  125. stopPropagation: function() {
  126. var e = this.origEvent;
  127. this.isPropagationStopped = retTrue;
  128. if (e && e.stopPropagation) e.stopPropagation();
  129. },
  130. stopImmediatePropagation: function() {
  131. var e = this.origEvent;
  132. this.isImmediatePropagationStopped = retTrue;
  133. if (e && e.stopImmediatePropagation) e.stopImmediatePropagation();
  134. this.stopPropagation();
  135. }
  136. })
  137. };
  138. module.exports = exports;