Event.html 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js">Ext.require('Ext.util.DelayedTask', function() {
  19. <span id='Ext-util-Event'> /**
  20. </span> * Represents single event type that an Observable object listens to.
  21. * All actual listeners are tracked inside here. When the event fires,
  22. * it calls all the registered listener functions.
  23. *
  24. * @private
  25. */
  26. Ext.util.Event = Ext.extend(Object, (function() {
  27. var noOptions = {};
  28. function createTargeted(handler, listener, o, scope){
  29. return function(){
  30. if (o.target === arguments[0]){
  31. handler.apply(scope, arguments);
  32. }
  33. };
  34. }
  35. function createBuffered(handler, listener, o, scope) {
  36. listener.task = new Ext.util.DelayedTask();
  37. return function() {
  38. listener.task.delay(o.buffer, handler, scope, Ext.Array.toArray(arguments));
  39. };
  40. }
  41. function createDelayed(handler, listener, o, scope) {
  42. return function() {
  43. var task = new Ext.util.DelayedTask();
  44. if (!listener.tasks) {
  45. listener.tasks = [];
  46. }
  47. listener.tasks.push(task);
  48. task.delay(o.delay || 10, handler, scope, Ext.Array.toArray(arguments));
  49. };
  50. }
  51. function createSingle(handler, listener, o, scope) {
  52. return function() {
  53. var event = listener.ev;
  54. if (event.removeListener(listener.fn, scope) &amp;&amp; event.observable) {
  55. // Removing from a regular Observable-owned, named event (not an anonymous
  56. // event such as Ext's readyEvent): Decrement the listeners count
  57. event.observable.hasListeners[event.name]--;
  58. }
  59. return handler.apply(scope, arguments);
  60. };
  61. }
  62. return {
  63. <span id='Ext-util-Event-property-isEvent'> /**
  64. </span> * @property {Boolean} isEvent
  65. * `true` in this class to identify an object as an instantiated Event, or subclass thereof.
  66. */
  67. isEvent: true,
  68. constructor: function(observable, name) {
  69. this.name = name;
  70. this.observable = observable;
  71. this.listeners = [];
  72. },
  73. addListener: function(fn, scope, options) {
  74. var me = this,
  75. listener;
  76. scope = scope || me.observable;
  77. //&lt;debug error&gt;
  78. if (!fn) {
  79. Ext.Error.raise({
  80. sourceClass: Ext.getClassName(this.observable),
  81. sourceMethod: &quot;addListener&quot;,
  82. msg: &quot;The specified callback function is undefined&quot;
  83. });
  84. }
  85. //&lt;/debug&gt;
  86. if (!me.isListening(fn, scope)) {
  87. listener = me.createListener(fn, scope, options);
  88. if (me.firing) {
  89. // if we are currently firing this event, don't disturb the listener loop
  90. me.listeners = me.listeners.slice(0);
  91. }
  92. me.listeners.push(listener);
  93. }
  94. },
  95. createListener: function(fn, scope, options) {
  96. options = options || noOptions;
  97. scope = scope || this.observable;
  98. var listener = {
  99. fn: fn,
  100. scope: scope,
  101. o: options,
  102. ev: this
  103. },
  104. handler = fn;
  105. // The order is important. The 'single' wrapper must be wrapped by the 'buffer' and 'delayed' wrapper
  106. // because the event removal that the single listener does destroys the listener's DelayedTask(s)
  107. if (options.single) {
  108. handler = createSingle(handler, listener, options, scope);
  109. }
  110. if (options.target) {
  111. handler = createTargeted(handler, listener, options, scope);
  112. }
  113. if (options.delay) {
  114. handler = createDelayed(handler, listener, options, scope);
  115. }
  116. if (options.buffer) {
  117. handler = createBuffered(handler, listener, options, scope);
  118. }
  119. listener.fireFn = handler;
  120. return listener;
  121. },
  122. findListener: function(fn, scope) {
  123. var listeners = this.listeners,
  124. i = listeners.length,
  125. listener,
  126. s;
  127. while (i--) {
  128. listener = listeners[i];
  129. if (listener) {
  130. s = listener.scope;
  131. // Compare the listener's scope with *JUST THE PASSED SCOPE* if one is passed, and only fall back to the owning Observable if none is passed.
  132. // We cannot use the test (s == scope || s == this.observable)
  133. // Otherwise, if the Observable itself adds Ext.emptyFn as a listener, and then Ext.emptyFn is added under another scope, there will be a false match.
  134. if (listener.fn == fn &amp;&amp; (s == (scope || this.observable))) {
  135. return i;
  136. }
  137. }
  138. }
  139. return - 1;
  140. },
  141. isListening: function(fn, scope) {
  142. return this.findListener(fn, scope) !== -1;
  143. },
  144. removeListener: function(fn, scope) {
  145. var me = this,
  146. index,
  147. listener,
  148. k;
  149. index = me.findListener(fn, scope);
  150. if (index != -1) {
  151. listener = me.listeners[index];
  152. if (me.firing) {
  153. me.listeners = me.listeners.slice(0);
  154. }
  155. // cancel and remove a buffered handler that hasn't fired yet
  156. if (listener.task) {
  157. listener.task.cancel();
  158. delete listener.task;
  159. }
  160. // cancel and remove all delayed handlers that haven't fired yet
  161. k = listener.tasks &amp;&amp; listener.tasks.length;
  162. if (k) {
  163. while (k--) {
  164. listener.tasks[k].cancel();
  165. }
  166. delete listener.tasks;
  167. }
  168. // remove this listener from the listeners array
  169. Ext.Array.erase(me.listeners, index, 1);
  170. return true;
  171. }
  172. return false;
  173. },
  174. // Iterate to stop any buffered/delayed events
  175. clearListeners: function() {
  176. var listeners = this.listeners,
  177. i = listeners.length;
  178. while (i--) {
  179. this.removeListener(listeners[i].fn, listeners[i].scope);
  180. }
  181. },
  182. fire: function() {
  183. var me = this,
  184. listeners = me.listeners,
  185. count = listeners.length,
  186. i,
  187. args,
  188. listener;
  189. if (count &gt; 0) {
  190. me.firing = true;
  191. for (i = 0; i &lt; count; i++) {
  192. listener = listeners[i];
  193. args = arguments.length ? Array.prototype.slice.call(arguments, 0) : [];
  194. if (listener.o) {
  195. args.push(listener.o);
  196. }
  197. if (listener &amp;&amp; listener.fireFn.apply(listener.scope || me.observable, args) === false) {
  198. return (me.firing = false);
  199. }
  200. }
  201. }
  202. me.firing = false;
  203. return true;
  204. }
  205. };
  206. }()));
  207. });
  208. </pre>
  209. </body>
  210. </html>