index.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /**
  2. * Initialize a new `Emitter`.
  3. *
  4. * @api public
  5. */
  6. export function Emitter(obj) {
  7. if (obj) return mixin(obj);
  8. }
  9. /**
  10. * Mixin the emitter properties.
  11. *
  12. * @param {Object} obj
  13. * @return {Object}
  14. * @api private
  15. */
  16. function mixin(obj) {
  17. for (var key in Emitter.prototype) {
  18. obj[key] = Emitter.prototype[key];
  19. }
  20. return obj;
  21. }
  22. /**
  23. * Listen on the given `event` with `fn`.
  24. *
  25. * @param {String} event
  26. * @param {Function} fn
  27. * @return {Emitter}
  28. * @api public
  29. */
  30. Emitter.prototype.on =
  31. Emitter.prototype.addEventListener = function(event, fn){
  32. this._callbacks = this._callbacks || {};
  33. (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
  34. .push(fn);
  35. return this;
  36. };
  37. /**
  38. * Adds an `event` listener that will be invoked a single
  39. * time then automatically removed.
  40. *
  41. * @param {String} event
  42. * @param {Function} fn
  43. * @return {Emitter}
  44. * @api public
  45. */
  46. Emitter.prototype.once = function(event, fn){
  47. function on() {
  48. this.off(event, on);
  49. fn.apply(this, arguments);
  50. }
  51. on.fn = fn;
  52. this.on(event, on);
  53. return this;
  54. };
  55. /**
  56. * Remove the given callback for `event` or all
  57. * registered callbacks.
  58. *
  59. * @param {String} event
  60. * @param {Function} fn
  61. * @return {Emitter}
  62. * @api public
  63. */
  64. Emitter.prototype.off =
  65. Emitter.prototype.removeListener =
  66. Emitter.prototype.removeAllListeners =
  67. Emitter.prototype.removeEventListener = function(event, fn){
  68. this._callbacks = this._callbacks || {};
  69. // all
  70. if (0 == arguments.length) {
  71. this._callbacks = {};
  72. return this;
  73. }
  74. // specific event
  75. var callbacks = this._callbacks['$' + event];
  76. if (!callbacks) return this;
  77. // remove all handlers
  78. if (1 == arguments.length) {
  79. delete this._callbacks['$' + event];
  80. return this;
  81. }
  82. // remove specific handler
  83. var cb;
  84. for (var i = 0; i < callbacks.length; i++) {
  85. cb = callbacks[i];
  86. if (cb === fn || cb.fn === fn) {
  87. callbacks.splice(i, 1);
  88. break;
  89. }
  90. }
  91. // Remove event specific arrays for event types that no
  92. // one is subscribed for to avoid memory leak.
  93. if (callbacks.length === 0) {
  94. delete this._callbacks['$' + event];
  95. }
  96. return this;
  97. };
  98. /**
  99. * Emit `event` with the given args.
  100. *
  101. * @param {String} event
  102. * @param {Mixed} ...
  103. * @return {Emitter}
  104. */
  105. Emitter.prototype.emit = function(event){
  106. this._callbacks = this._callbacks || {};
  107. var args = new Array(arguments.length - 1)
  108. , callbacks = this._callbacks['$' + event];
  109. for (var i = 1; i < arguments.length; i++) {
  110. args[i - 1] = arguments[i];
  111. }
  112. if (callbacks) {
  113. callbacks = callbacks.slice(0);
  114. for (var i = 0, len = callbacks.length; i < len; ++i) {
  115. callbacks[i].apply(this, args);
  116. }
  117. }
  118. return this;
  119. };
  120. // alias used for reserved events (protected method)
  121. Emitter.prototype.emitReserved = Emitter.prototype.emit;
  122. /**
  123. * Return array of callbacks for `event`.
  124. *
  125. * @param {String} event
  126. * @return {Array}
  127. * @api public
  128. */
  129. Emitter.prototype.listeners = function(event){
  130. this._callbacks = this._callbacks || {};
  131. return this._callbacks['$' + event] || [];
  132. };
  133. /**
  134. * Check if this emitter has `event` handlers.
  135. *
  136. * @param {String} event
  137. * @return {Boolean}
  138. * @api public
  139. */
  140. Emitter.prototype.hasListeners = function(event){
  141. return !! this.listeners(event).length;
  142. };