emitter.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /**
  2. * Simple event emitter based on component/emitter.
  3. *
  4. * @constructor
  5. * @param {Object} ctx - the context to call listners with.
  6. */
  7. function Emitter (ctx) {
  8. this._ctx = ctx || this
  9. }
  10. var p = Emitter.prototype
  11. /**
  12. * Listen on the given `event` with `fn`.
  13. *
  14. * @param {String} event
  15. * @param {Function} fn
  16. * @return {Emitter}
  17. */
  18. p.on = function (event, fn) {
  19. this._cbs = this._cbs || {}
  20. ;(this._cbs[event] || (this._cbs[event] = []))
  21. .push(fn)
  22. return this
  23. }
  24. /**
  25. * Adds an `event` listener that will be invoked a single
  26. * time then automatically removed.
  27. *
  28. * @param {String} event
  29. * @param {Function} fn
  30. * @return {Emitter}
  31. */
  32. p.once = function (event, fn) {
  33. var self = this
  34. this._cbs = this._cbs || {}
  35. function on () {
  36. self.off(event, on)
  37. fn.apply(this, arguments)
  38. }
  39. on.fn = fn
  40. this.on(event, on)
  41. return this
  42. }
  43. /**
  44. * Remove the given callback for `event` or all
  45. * registered callbacks.
  46. *
  47. * @param {String} event
  48. * @param {Function} fn
  49. * @return {Emitter}
  50. */
  51. p.off = function (event, fn) {
  52. this._cbs = this._cbs || {}
  53. // all
  54. if (!arguments.length) {
  55. this._cbs = {}
  56. return this
  57. }
  58. // specific event
  59. var callbacks = this._cbs[event]
  60. if (!callbacks) return this
  61. // remove all handlers
  62. if (arguments.length === 1) {
  63. delete this._cbs[event]
  64. return this
  65. }
  66. // remove specific handler
  67. var cb
  68. for (var i = 0; i < callbacks.length; i++) {
  69. cb = callbacks[i]
  70. if (cb === fn || cb.fn === fn) {
  71. callbacks.splice(i, 1)
  72. break
  73. }
  74. }
  75. return this
  76. }
  77. /**
  78. * The internal, faster emit with fixed amount of arguments
  79. * using Function.call.
  80. *
  81. * @param {Object} event
  82. * @return {Emitter}
  83. */
  84. p.emit = function (event, a, b, c) {
  85. this._cbs = this._cbs || {}
  86. var callbacks = this._cbs[event]
  87. if (callbacks) {
  88. callbacks = callbacks.slice(0)
  89. for (var i = 0, len = callbacks.length; i < len; i++) {
  90. callbacks[i].call(this._ctx, a, b, c)
  91. }
  92. }
  93. return this
  94. }
  95. /**
  96. * The external emit using Function.apply, used
  97. * by Vue instance event methods.
  98. *
  99. * @param {Object} event
  100. * @return {Emitter}
  101. */
  102. p.applyEmit = function (event) {
  103. this._cbs = this._cbs || {}
  104. var callbacks = this._cbs[event], args
  105. if (callbacks) {
  106. callbacks = callbacks.slice(0)
  107. args = callbacks.slice.call(arguments, 1)
  108. for (var i = 0, len = callbacks.length; i < len; i++) {
  109. callbacks[i].apply(this._ctx, args)
  110. }
  111. }
  112. return this
  113. }
  114. module.exports = Emitter