Show:
  1. /**
  2. * @module proact-core
  3. */
  4.  
  5.  
  6. /**
  7. * ActorUtil provides methods that can be used to make the Actor to 'act'.
  8. * The Actor is ProAct.js version of the base `Observable` object. Various types
  9. * of listeners can be attached to it and used to observe its `actions`.
  10. *
  11. * On the other hand the `Actor` should do something or `act`, because something
  12. * has to be observed after all.
  13. *
  14. * The `ActorUtil` contains a set of methods that help implementing these `acts`.
  15. *
  16. * For example the we can trigger events/values in the `Streams`. This is thier `act`.
  17. * This triggering can be implemented with ease using the methods defined in `ActorUtil`.
  18. *
  19. * Another example is `Properties` - they can be set or updated by the reactive flow -> they should react.
  20. *
  21. * So `ActorUtil` provides the `Actors` with helpful methods for `acting` and `reacting`.
  22. *
  23. * All these methods use the {{#crossLink "ProAct.Flow"}}{{/crossLink}} to defer the changes the right way.
  24. * And the using the `flow` these methods handle the dependencies between the `Actors`.
  25. *
  26. * Use the methods in the `ActorUtil` to implement your `Actor's` `actions` and `reactions`.
  27. *
  28. * @namespace ProAct
  29. * @private
  30. * @class ActorUtil
  31. * @extensionfor ProAct.Actor
  32. * @static
  33. */
  34. ActorUtil = {
  35.  
  36. /**
  37. * Updating/notifying method that can be applied to an {{#crossLink "ProAct.Actor"}}{{/crossLink}}
  38. *
  39. * This method defers the update and the notifications into {{#crossLink "ProAct.flow"}}{{/crossLink}}.
  40. *
  41. * If the state of the caller is {{#crossLink "ProAct.States.destroyed)"}}{{/crossLink}}, an exception will be thrown.
  42. * If the state of the caller is {{#crossLink "ProAct.States.closed)"}}{{/crossLink}}, nothing will happen.
  43. *
  44. * Examples:
  45. *
  46. * You can implement a stream and in it's `trigger` method use this:
  47. * ```
  48. * ActorUtil.update.call(this, event);
  49. * ```
  50. * This way the event will be triggered into the stream and all the listeners to the stream will be notified.
  51. * For this to work you'll have to override the `makeEvent` method of the stream to return the unmodified source - no state/no event generation,
  52. * the event will just go through.
  53. *
  54. *
  55. * If you want to implement a statefull `Actor` like a `property`, you can set a state in it and just notify all the
  56. * observing `Actors` with this method.
  57. *
  58. *
  59. * @method update
  60. * @protected
  61. * @param {Object} [source] The event/value, causing the update -> can be null : no source.
  62. * @param {Object} [actions] For which actions should notify -> can be null : default actions.
  63. * @param {Object} [eventData] Data for creating the updating event -> can be null : no data.
  64. * @return {Object} The calling object.
  65. */
  66. update: function (source, actions, eventData) {
  67. if (this.state === ProAct.States.destroyed) {
  68. throw new Error('You can not trigger actions on destroyed actors!');
  69. }
  70.  
  71. if (this.state === ProAct.States.closed) {
  72. return;
  73. }
  74.  
  75. var actor = this;
  76. if (!P.flow.isRunning()) {
  77. P.flow.run(function () {
  78. ActorUtil.doUpdate.call(actor, source, actions, eventData);
  79. });
  80. } else {
  81. ActorUtil.doUpdate.call(actor, source, actions, eventData);
  82. }
  83. return this;
  84. },
  85.  
  86. /**
  87. * Contains the real notify/update logic defered by {{#crossLink "ProAct.ActorUtil/update:method"}}{{/crossLink}} into the flow.
  88. * It is private method, should not be used - use `update`.
  89. *
  90. * @method doUpdate
  91. * @private
  92. * @param {Object} [source] The event/value, causing the update -> can be null : no source.
  93. * @param {Object} [actions] For which actions should notify -> can be null : default actions.
  94. * @param {Object} [eventData] Data for creating the updating event -> can be null : no data.
  95. * @return {Object} The calling object.
  96. */
  97. doUpdate: function (source, actions, eventData) {
  98. if (!actions) {
  99. actions = this.defaultActions();
  100. }
  101.  
  102. var ln, i, j,
  103. listener,
  104. listeners,
  105. length,
  106. event;
  107.  
  108. if (P.U.isString(actions)) {
  109. listeners = this.listeners[actions];
  110. } else {
  111. while (actions.indexOf('close') !== -1) {
  112. P.U.remove(actions, 'close');
  113. }
  114.  
  115. listeners = [];
  116. ln = actions.length;
  117.  
  118. if (this.parent === null && actions.length === 0) {
  119. return this;
  120. }
  121.  
  122. for (i = 0; i < ln; i++) {
  123. listenersForAction = this.listeners[actions[i]];
  124.  
  125. if (listenersForAction) {
  126. for (j = 0; j < listenersForAction.length; j++) {
  127. if (listenersForAction[j].destroyed || listenersForAction[j].closed) {
  128. this.off(actions[i], listenersForAction[j]);
  129. continue;
  130. }
  131. }
  132. listeners = listeners.concat(listenersForAction);
  133. }
  134. }
  135. }
  136.  
  137. if (listeners.length === 0 && this.parent === null && actions !== 'close') {
  138. return this;
  139. }
  140.  
  141. if (actions === 'close' && !this.canClose()) {
  142. return this;
  143. }
  144.  
  145. length = listeners.length;
  146. event = this.makeEvent(source, eventData);
  147.  
  148. for (i = 0; i < length; i++) {
  149. listener = listeners[i];
  150. if (!listener) {
  151. throw new Error('Invalid null listener for actions : ' + actions);
  152. }
  153.  
  154. if (P.U.isString(actions) && listener.destroyed) {
  155. this.off(actions, listener);
  156. continue;
  157. }
  158.  
  159. this.defer(event, listener);
  160.  
  161. if (listener.property) {
  162. ActorUtil.doUpdate.call(listener.property, event);
  163. }
  164. }
  165.  
  166. if (this.parent && this.parent.call) {
  167. this.defer(event, this.parent);
  168. }
  169.  
  170. if (actions === 'close') {
  171. P.flow.pushClose(this, this.doClose);
  172. }
  173.  
  174. return this;
  175. }
  176. };
  177. P.U.defValProp(ProAct, 'ActorUtil', false, false, false, ActorUtil);
  178.