Action.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.wire.ml.Action"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.wire.ml.Action"] = true;
  8. dojo.provide("dojox.wire.ml.Action");
  9. dojo.provide("dojox.wire.ml.ActionFilter");
  10. dojo.require("dijit._Widget");
  11. dojo.require("dijit._Container");
  12. dojo.require("dojox.wire.Wire");
  13. dojo.require("dojox.wire.ml.util");
  14. dojo.declare("dojox.wire.ml.Action", [dijit._Widget, dijit._Container], {
  15. // summary:
  16. // A base widget to "run" a task on an event or a topic
  17. // description:
  18. // This widget represents a controller task to be run when an event
  19. // (a function) or a topic is issued.
  20. // Sub-classes must implement _run() method to implement their tasks.
  21. // 'trigger' specifies an event scope, an ID of a widget or an DOM
  22. // element, or its property with the optional dotted notation.
  23. // If this widget has child ActionFilter widgets, their filter()
  24. // methods are called with the arguments to the event or the topic.
  25. // If one of filter() methods returns false, run() won't be invoked.
  26. // This widget also can serve as a composite task to run child
  27. // Actions on an event or a topic specified to this widget.
  28. // trigger:
  29. // An event scope
  30. // triggerEvent:
  31. // An event (function) name
  32. // triggerTopic:
  33. // A topic name
  34. trigger: "",
  35. triggerEvent: "",
  36. triggerTopic: "",
  37. postCreate: function(){
  38. // summary:
  39. // Call _connect()
  40. // description:
  41. // See _connect().
  42. this._connect();
  43. },
  44. _connect: function(){
  45. // summary:
  46. // Connect run() method to an event or a topic
  47. // description:
  48. // If 'triggerEvent' and 'trigger' are specified, connect() is
  49. // used to set up run() to be called on the event.
  50. // If 'triggerTopic' is specified, subscribe() is used to set up
  51. // run() to be called on the topic.
  52. if(this.triggerEvent){
  53. if(this.trigger){
  54. var scope = dojox.wire.ml._getValue(this.trigger);
  55. if(scope){
  56. if(!scope[this.triggerEvent]){
  57. // set a dummy function for an anonymous object
  58. scope[this.triggerEvent] = function(){};
  59. }
  60. this._triggerHandle = dojo.connect(scope, this.triggerEvent, this, "run");
  61. }
  62. }else{
  63. var event = this.triggerEvent.toLowerCase();
  64. if(event == "onload"){
  65. var self = this;
  66. dojo.addOnLoad(function(){
  67. self._run.apply(self, arguments);
  68. });
  69. }
  70. }
  71. }else if(this.triggerTopic){
  72. this._triggerHandle = dojo.subscribe(this.triggerTopic, this, "run");
  73. }
  74. },
  75. _disconnect: function(){
  76. // summary:
  77. // Disconnect run() method from an event or a topic
  78. // description:
  79. // If 'triggerEvent' and 'trigger' are specified, disconnect() is
  80. // used to set up run() not to be called on the event.
  81. // If 'triggerTopic' is specified, unsubscribe() is used to set up
  82. // run() not to be called on the topic.
  83. if(this._triggerHandle){
  84. if(this.triggerTopic){
  85. dojo.unsubscribe(this.triggerTopic, this._triggerHandle);
  86. }else{
  87. dojo.disconnect(this._triggerHandle);
  88. }
  89. }
  90. },
  91. run: function(){
  92. // summary:
  93. // Run a task
  94. // description:
  95. // This method calls filter() method of child ActionFilter
  96. // widgets.
  97. // If one of them returns false, this method returns.
  98. // Otherwise, _run() method is called.
  99. var children = this.getChildren();
  100. for(var i in children){
  101. var child = children[i];
  102. if(child instanceof dojox.wire.ml.ActionFilter){
  103. if(!child.filter.apply(child, arguments)){
  104. return;
  105. }
  106. }
  107. }
  108. this._run.apply(this, arguments);
  109. },
  110. _run: function(){
  111. // summary:
  112. // Call run() methods of child Action widgets
  113. // description:
  114. // If this widget has child Action widgets, their run() methods
  115. // are called.
  116. var children = this.getChildren();
  117. for(var i in children){
  118. var child = children[i];
  119. if(child instanceof dojox.wire.ml.Action){
  120. child.run.apply(child, arguments);
  121. }
  122. }
  123. },
  124. uninitialize: function(){
  125. // summary:
  126. // Over-ride of base widget unitialize function to do some connection cleanup.
  127. this._disconnect();
  128. return true;
  129. }
  130. });
  131. dojo.declare("dojox.wire.ml.ActionFilter", dijit._Widget, {
  132. // summary:
  133. // A widget to define a filter for the parent Action to run
  134. // description:
  135. // This base class checks a required property specified with
  136. // 'required' attribute.
  137. // If 'message' is specified, the message is set to a property
  138. // specified with 'error'.
  139. // Subclasses may implement their own filter() method.
  140. // required:
  141. // A property required
  142. // requiredValue:
  143. // Optional. A specific value the property is required to have. If this isn't provided
  144. // than any non-false/non-null value of the required propery will cause this filter
  145. // to pass.
  146. // type:
  147. // Optional. A specific type to compare the values as (if requiredValue is set)
  148. // Valid values for type are boolean, int, string. Default is string.
  149. // message:
  150. // An error message to emit if the filter doesn't execute due to property mismatch.
  151. // error:
  152. // A property to store an error due to property mismatch.
  153. required: "",
  154. requiredValue: "",
  155. type: "",
  156. message: "",
  157. error: "",
  158. filter: function(){
  159. // summary:
  160. // Check if a required property is specified. Also, if provided, check to see
  161. // if the required property contains a specific value.
  162. // description:
  163. // If a value is undefined for a property, specified with
  164. // 'required', this method returns false.
  165. // If the value for a property is defined, but there isn't a requiredValue for it
  166. // then any non-false value will cause the method to return true.
  167. // if requiredValue is set, then filter compares that value with the value from
  168. // the required property and returns true if and only if they match.
  169. // The type option just allows for a way to convert the required property values
  170. // into a proper form for comparison (boolean, number, etc).
  171. // If 'message' is specified, it is set to a proeprty specified
  172. // with 'error' or shown with alert().
  173. // If 'required' starts with "arguments", a property of
  174. // the method arguments are checked.
  175. // returns:
  176. // True if a required property is specified (and if requiredValue is specified,
  177. // that they match), otherwise false
  178. if(this.required === ""){
  179. return true; //Boolean
  180. }else{
  181. var value = dojox.wire.ml._getValue(this.required, arguments);
  182. if(this.requiredValue === ""){
  183. //Just see if there's a value, nothing to compare it to.
  184. if(value){
  185. return true; //Boolean
  186. }
  187. }else{
  188. //See if we need to type convert.
  189. var reqValue = this.requiredValue;
  190. if(this.type !== ""){
  191. var lType = this.type.toLowerCase();
  192. if(lType === "boolean"){
  193. if(reqValue.toLowerCase() === "false"){
  194. reqValue = false;
  195. }else{
  196. reqValue = true;
  197. }
  198. }else if(lType === "number"){
  199. reqValue = parseInt(reqValue, 10);
  200. }
  201. }
  202. if(value === reqValue){
  203. return true; //boolean
  204. }
  205. }
  206. }
  207. if(this.message){
  208. if(this.error){
  209. dojox.wire.ml._setValue(this.error, this.message);
  210. }else{
  211. alert(this.message);
  212. }
  213. }
  214. return false; //Boolean
  215. }
  216. });
  217. }