PageRenderTime 212ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/app/scripts/common/EventEmitter.js

https://gitlab.com/yutiansut/Strut
JavaScript | 165 lines | 103 code | 29 blank | 33 comment | 20 complexity | 07ffad1381b36f15655798ffcda1c4ba MD5 | raw file
  1. /**
  2. The eventEmitter pattern from nodeJS ported to the browser.
  3. @author Matt Crinklaw
  4. */
  5. define(
  6. function() {
  7. function EventEmitter() {
  8. if (!(this instanceof EventEmitter)) return new EventEmitter();
  9. this._events = null;
  10. if (typeof(process) !== 'undefined' && typeof(process.nextTick) !== 'undefined') {
  11. this._deferer = function(cb, topic, args) {
  12. process.nextTick(function() { cb(topic, args); } );
  13. };
  14. } else {
  15. this._deferer = function(cb, topic, args) {
  16. setTimeout(function () {cb(topic, args); }, 0);
  17. };
  18. }
  19. };
  20. EventEmitter.prototype = {
  21. _listeners: function listeners(type) {
  22. var events = this._events || (this._events = {});
  23. return events[type] || (events[type] = []);
  24. },
  25. _emit: function(topic, args) {
  26. if (topic instanceof Array)
  27. topic = JSON.stringify(topic);
  28. if (!this._events) return;
  29. var subs = this._events[topic];
  30. if (!subs) return;
  31. var len = subs.length;
  32. while(len--){
  33. var sub = subs[len];
  34. // try {
  35. if (sub)
  36. sub.cb.apply(sub.context, args);
  37. // } catch(e) {
  38. // console.log(e.stack);
  39. // }
  40. }
  41. },
  42. _splice: function(args, start, end) {
  43. args = Array.prototype.slice.call(args);
  44. return args.splice(start, end);
  45. },
  46. _indexOfSub: function(arr, cb, context) {
  47. for (var i = 0; i < arr.length; ++i) {
  48. if (arr[i].cb === cb && arr[i].context === context)
  49. return i;
  50. }
  51. return -1;
  52. },
  53. /**
  54. Publish an event on the given topic
  55. */
  56. emit: function(topic) {
  57. var args = arguments.length > 1 ? this._splice(arguments, 1, arguments.length) : [];
  58. this._emit(topic, args);
  59. },
  60. trigger: function() {
  61. this.emit.apply(this, arguments);
  62. },
  63. /**
  64. Publish an event on the given topic on the next iteration
  65. through the event loop
  66. */
  67. emitDeferred: function(topic) {
  68. var args = arguments.length > 1 ? this._splice(arguments, 1, arguments.length) : [];
  69. this._deferer(emit, topic, args);
  70. },
  71. /**
  72. Register a callback for the given topic.
  73. Optionally, a context may be provided. The provided
  74. context will be used for the this argument to callback.
  75. */
  76. on: function(topic, callback, context) {
  77. if (!callback)
  78. throw "Undefined callback provided";
  79. if (topic instanceof Array)
  80. topic = JSON.stringify(topic);
  81. var subs = this._listeners(topic);
  82. var index = this._indexOfSub(subs, callback, context);
  83. if (index < 0) {
  84. subs.push({cb: callback, context: context});
  85. index = subs.length - 1;
  86. }
  87. var self = this;
  88. return {dispose: function() {
  89. self.removeListener(topic, callback, context);
  90. }};
  91. },
  92. /**
  93. Register a callback that will be removed after
  94. its first notification
  95. */
  96. once: function(topic, callback, context) {
  97. var holder = {sub: null};
  98. holder.sub = this.on(topic, function() {
  99. holder.sub.dispose();
  100. callback.apply(context, arguments);
  101. });
  102. return holder.sub;
  103. },
  104. /**
  105. remove a listener. If the listener was registerd
  106. with a context, a context must be provided for its removal.
  107. */
  108. removeListener: function(topic, callback, context) {
  109. var subs = this._listeners(topic);
  110. var index = this._indexOfSub(subs, callback, context);
  111. if (0 <= index)
  112. subs.splice(index, 1);
  113. if (subs.length == 0)
  114. delete this._events[topic];
  115. },
  116. getNumListeners: function(topic){
  117. var numListeners = 0;
  118. if (this._events[topic]){
  119. numListeners = this._events[topic].length;
  120. }
  121. return numListeners;
  122. },
  123. off: function(topic, callback, context) {
  124. this.removeListener(topic, callback, context);
  125. },
  126. removeAllListeners: function() {
  127. this._events = null;
  128. }
  129. };
  130. return EventEmitter;
  131. });
  132. //try {
  133. //if (exports) {
  134. //exports.EventBus = EventBus;
  135. //}} catch (e) {}