dojo.provide("dojox.wire.ml.Action"); dojo.provide("dojox.wire.ml.ActionFilter"); dojo.require("dijit._Widget"); dojo.require("dijit._Container"); dojo.require("dojox.wire.Wire"); dojo.require("dojox.wire.ml.util"); dojo.declare("dojox.wire.ml.Action", [dijit._Widget, dijit._Container], { // summary: // A base widget to "run" a task on an event or a topic // description: // This widget represents a controller task to be run when an event // (a function) or a topic is issued. // Sub-classes must implement _run() method to implement their tasks. // 'trigger' specifies an event scope, an ID of a widget or an DOM // element, or its property with the optional dotted notation. // If this widget has child ActionFilter widgets, their filter() // methods are called with the arguments to the event or the topic. // If one of filter() methods returns false, run() won't be invoked. // This widget also can serve as a composite task to run child // Actions on an event or a topic specified to this widget. // trigger: // An event scope // triggerEvent: // An event (function) name // triggerTopic: // A topic name trigger: "", triggerEvent: "", triggerTopic: "", postCreate: function(){ // summary: // Call _connect() // description: // See _connect(). this._connect(); }, _connect: function(){ // summary: // Connect run() method to an event or a topic // description: // If 'triggerEvent' and 'trigger' are specified, connect() is // used to set up run() to be called on the event. // If 'triggerTopic' is specified, subscribe() is used to set up // run() to be called on the topic. if(this.triggerEvent){ if(this.trigger){ var scope = dojox.wire.ml._getValue(this.trigger); if(scope){ if(!scope[this.triggerEvent]){ // set a dummy function for an anonymous object scope[this.triggerEvent] = function(){}; } this._triggerHandle = dojo.connect(scope, this.triggerEvent, this, "run"); } }else{ var event = this.triggerEvent.toLowerCase(); if(event == "onload"){ var self = this; dojo.addOnLoad(function(){ self._run.apply(self, arguments); }); } } }else if(this.triggerTopic){ this._triggerHandle = dojo.subscribe(this.triggerTopic, this, "run"); } }, _disconnect: function(){ // summary: // Disconnect run() method from an event or a topic // description: // If 'triggerEvent' and 'trigger' are specified, disconnect() is // used to set up run() not to be called on the event. // If 'triggerTopic' is specified, unsubscribe() is used to set up // run() not to be called on the topic. if(this._triggerHandle){ if(this.triggerTopic){ dojo.unsubscribe(this.triggerTopic, this._triggerHandle); }else{ dojo.disconnect(this._triggerHandle); } } }, run: function(){ // summary: // Run a task // description: // This method calls filter() method of child ActionFilter // widgets. // If one of them returns false, this method returns. // Otherwise, _run() method is called. var children = this.getChildren(); for(var i in children){ var child = children[i]; if(child instanceof dojox.wire.ml.ActionFilter){ if(!child.filter.apply(child, arguments)){ return; } } } this._run.apply(this, arguments); }, _run: function(){ // summary: // Call run() methods of child Action widgets // description: // If this widget has child Action widgets, their run() methods // are called. var children = this.getChildren(); for(var i in children){ var child = children[i]; if(child instanceof dojox.wire.ml.Action){ child.run.apply(child, arguments); } } }, uninitialize: function(){ // summary: // Over-ride of base widget unitialize function to do some connection cleanup. this._disconnect(); return true; } }); dojo.declare("dojox.wire.ml.ActionFilter", dijit._Widget, { // summary: // A widget to define a filter for the parent Action to run // description: // This base class checks a required property specified with // 'required' attribute. // If 'message' is specified, the message is set to a property // specified with 'error'. // Subclasses may implement their own filter() method. // required: // A property required // requiredValue: // Optional. A specific value the property is required to have. If this isn't provided // than any non-false/non-null value of the required propery will cause this filter // to pass. // type: // Optional. A specific type to compare the values as (if requiredValue is set) // Valid values for type are boolean, int, string. Default is string. // message: // An error message to emit if the filter doesn't execute due to property mismatch. // error: // A property to store an error due to property mismatch. required: "", requiredValue: "", type: "", message: "", error: "", filter: function(){ // summary: // Check if a required property is specified. Also, if provided, check to see // if the required property contains a specific value. // description: // If a value is undefined for a property, specified with // 'required', this method returns false. // If the value for a property is defined, but there isn't a requiredValue for it // then any non-false value will cause the method to return true. // if requiredValue is set, then filter compares that value with the value from // the required property and returns true if and only if they match. // The type option just allows for a way to convert the required property values // into a proper form for comparison (boolean, number, etc). // If 'message' is specified, it is set to a proeprty specified // with 'error' or shown with alert(). // If 'required' starts with "arguments", a property of // the method arguments are checked. // returns: // True if a required property is specified (and if requiredValue is specified, // that they match), otherwise false if(this.required === ""){ return true; //Boolean }else{ var value = dojox.wire.ml._getValue(this.required, arguments); if(this.requiredValue === ""){ //Just see if there's a value, nothing to compare it to. if(value){ return true; //Boolean } }else{ //See if we need to type convert. var reqValue = this.requiredValue; if(this.type !== ""){ var lType = this.type.toLowerCase(); if(lType === "boolean"){ if(reqValue.toLowerCase() === "false"){ reqValue = false; }else{ reqValue = true; } }else if(lType === "number"){ reqValue = parseInt(reqValue, 10); } } if(value === reqValue){ return true; //boolean } } } if(this.message){ if(this.error){ dojox.wire.ml._setValue(this.error, this.message); }else{ alert(this.message); } } return false; //Boolean } });