]> git.pond.sub.org Git - eow/blobdiff - static/dojo-release-1.1.1/dijit/_Widget.js
add Dojo 1.1.1
[eow] / static / dojo-release-1.1.1 / dijit / _Widget.js
diff --git a/static/dojo-release-1.1.1/dijit/_Widget.js b/static/dojo-release-1.1.1/dijit/_Widget.js
new file mode 100644 (file)
index 0000000..361b6bf
--- /dev/null
@@ -0,0 +1,407 @@
+if(!dojo._hasResource["dijit._Widget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._Widget"] = true;
+dojo.provide("dijit._Widget");
+
+dojo.require( "dijit._base" );
+
+dojo.declare("dijit._Widget", null, {
+       //      summary:
+       //              The foundation of dijit widgets.        
+       //
+       //      id: String
+       //              a unique, opaque ID string that can be assigned by users or by the
+       //              system. If the developer passes an ID which is known not to be
+       //              unique, the specified ID is ignored and the system-generated ID is
+       //              used instead.
+       id: "",
+
+       //      lang: String
+       //              Rarely used.  Overrides the default Dojo locale used to render this widget,
+       //              as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute.
+       //              Value must be among the list of locales specified during by the Dojo bootstrap,
+       //              formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us).
+       lang: "",
+
+       //      dir: String
+       //              Unsupported by Dijit, but here for completeness.  Dijit only supports setting text direction on the
+       //              entire document.
+       //              Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir)
+       //              attribute. Either left-to-right "ltr" or right-to-left "rtl".
+       dir: "",
+
+       // class: String
+       //              HTML class attribute
+       "class": "",
+
+       // style: String
+       //              HTML style attribute
+       style: "",
+
+       // title: String
+       //              HTML title attribute
+       title: "",
+
+       // srcNodeRef: DomNode
+       //              pointer to original dom node
+       srcNodeRef: null,
+
+       // domNode: DomNode
+       //              this is our visible representation of the widget! Other DOM
+       //              Nodes may by assigned to other properties, usually through the
+       //              template system's dojoAttachPonit syntax, but the domNode
+       //              property is the canonical "top level" node in widget UI.
+       domNode: null,
+
+       // attributeMap: Object
+       //              A map of attributes and attachpoints -- typically standard HTML attributes -- to set
+       //              on the widget's dom, at the "domNode" attach point, by default.
+       //              Other node references can be specified as properties of 'this'
+       attributeMap: {id:"", dir:"", lang:"", "class":"", style:"", title:""},  // TODO: add on* handlers?
+
+       //////////// INITIALIZATION METHODS ///////////////////////////////////////
+//TODOC: params and srcNodeRef need docs.  Is srcNodeRef optional?
+//TODOC: summary needed for postscript
+       postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
+               this.create(params, srcNodeRef);
+       },
+
+       create: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
+               //      summary:
+               //              Kick off the life-cycle of a widget
+               //      description:
+               //              To understand the process by which widgets are instantiated, it
+               //              is critical to understand what other methods create calls and
+               //              which of them you'll want to override. Of course, adventurous
+               //              developers could override create entirely, but this should
+               //              only be done as a last resort.
+               //
+               //              Below is a list of the methods that are called, in the order
+               //              they are fired, along with notes about what they do and if/when
+               //              you should over-ride them in your widget:
+               //
+               // * postMixInProperties:
+               //      |       * a stub function that you can over-ride to modify
+               //              variables that may have been naively assigned by
+               //              mixInProperties
+               // * widget is added to manager object here
+               // * buildRendering:
+               //      |       * Subclasses use this method to handle all UI initialization
+               //              Sets this.domNode.  Templated widgets do this automatically
+               //              and otherwise it just uses the source dom node.
+               // * postCreate:
+               //      |       * a stub function that you can over-ride to modify take
+               //              actions once the widget has been placed in the UI
+
+               // store pointer to original dom tree
+               this.srcNodeRef = dojo.byId(srcNodeRef);
+
+               // For garbage collection.  An array of handles returned by Widget.connect()
+               // Each handle returned from Widget.connect() is an array of handles from dojo.connect()
+               this._connects=[];
+
+               // _attaches: String[]
+               //              names of all our dojoAttachPoint variables
+               this._attaches=[];
+
+               //mixin our passed parameters
+               if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
+               if(params){
+                       this.params = params;
+                       dojo.mixin(this,params);
+               }
+               this.postMixInProperties();
+
+               // generate an id for the widget if one wasn't specified
+               // (be sure to do this before buildRendering() because that function might
+               // expect the id to be there.
+               if(!this.id){
+                       this.id=dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
+               }
+               dijit.registry.add(this);
+
+               this.buildRendering();
+
+               // Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
+               // The placement of these attributes is according to the property mapping in attributeMap.
+               // Note special handling for 'style' and 'class' attributes which are lists and can
+               // have elements from both old and new structures, and some attributes like "type"
+               // cannot be processed this way as they are not mutable.
+               if(this.domNode){
+                       for(var attr in this.attributeMap){
+                               var value = this[attr];
+                               if(typeof value != "object" && ((value !== "" && value !== false) || (params && params[attr]))){
+                                       this.setAttribute(attr, value);
+                               }
+                       }
+               }
+
+               if(this.domNode){
+                       this.domNode.setAttribute("widgetId", this.id);
+               }
+               this.postCreate();
+
+               // If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
+               if(this.srcNodeRef && !this.srcNodeRef.parentNode){
+                       delete this.srcNodeRef;
+               }       
+       },
+
+       postMixInProperties: function(){
+               // summary
+               //      Called after the parameters to the widget have been read-in,
+               //      but before the widget template is instantiated.
+               //      Especially useful to set properties that are referenced in the widget template.
+       },
+
+       buildRendering: function(){
+               // summary:
+               //              Construct the UI for this widget, setting this.domNode.
+               //              Most widgets will mixin TemplatedWidget, which overrides this method.
+               this.domNode = this.srcNodeRef || dojo.doc.createElement('div');
+       },
+
+       postCreate: function(){
+               // summary:
+               //              Called after a widget's dom has been setup
+       },
+
+       startup: function(){
+               // summary:
+               //              Called after a widget's children, and other widgets on the page, have been created.
+               //              Provides an opportunity to manipulate any children before they are displayed.
+               //              This is useful for composite widgets that need to control or layout sub-widgets.
+               //              Many layout widgets can use this as a wiring phase.
+               this._started = true;
+       },
+
+       //////////// DESTROY FUNCTIONS ////////////////////////////////
+
+       destroyRecursive: function(/*Boolean*/ finalize){
+               // summary:
+               //              Destroy this widget and it's descendants. This is the generic
+               //              "destructor" function that all widget users should call to
+               //              cleanly discard with a widget. Once a widget is destroyed, it's
+               //              removed from the manager object.
+               // finalize: Boolean
+               //              is this function being called part of global environment
+               //              tear-down?
+
+               this.destroyDescendants();
+               this.destroy();
+       },
+
+       destroy: function(/*Boolean*/ finalize){
+               // summary:
+               //              Destroy this widget, but not its descendants
+               // finalize: Boolean
+               //              is this function being called part of global environment
+               //              tear-down?
+
+               this.uninitialize();
+               dojo.forEach(this._connects, function(array){
+                       dojo.forEach(array, dojo.disconnect);
+               });
+
+               // destroy widgets created as part of template, etc.
+               dojo.forEach(this._supportingWidgets || [], function(w){ w.destroy(); });
+               
+               this.destroyRendering(finalize);
+               dijit.registry.remove(this.id);
+       },
+
+       destroyRendering: function(/*Boolean*/ finalize){
+               // summary:
+               //              Destroys the DOM nodes associated with this widget
+               // finalize: Boolean
+               //              is this function being called part of global environment
+               //              tear-down?
+
+               if(this.bgIframe){
+                       this.bgIframe.destroy();
+                       delete this.bgIframe;
+               }
+
+               if(this.domNode){
+                       dojo._destroyElement(this.domNode);
+                       delete this.domNode;
+               }
+
+               if(this.srcNodeRef){
+                       dojo._destroyElement(this.srcNodeRef);
+                       delete this.srcNodeRef;
+               }
+       },
+
+       destroyDescendants: function(){
+               // summary:
+               //              Recursively destroy the children of this widget and their
+               //              descendants.
+
+               // TODO: should I destroy in the reverse order, to go bottom up?
+               dojo.forEach(this.getDescendants(), function(widget){ widget.destroy(); });
+       },
+
+       uninitialize: function(){
+               // summary:
+               //              stub function. Override to implement custom widget tear-down
+               //              behavior.
+               return false;
+       },
+
+       ////////////////// MISCELLANEOUS METHODS ///////////////////
+
+       onFocus: function(){
+               // summary:
+               //              stub function. Override or connect to this method to receive
+               //              notifications for when the widget moves into focus.
+       },
+
+       onBlur: function(){
+               // summary:
+               //              stub function. Override or connect to this method to receive
+               //              notifications for when the widget moves out of focus.
+       },
+
+       _onFocus: function(e){
+               this.onFocus();
+       },
+
+       _onBlur: function(){
+               this.onBlur();
+       },
+
+       setAttribute: function(/*String*/ attr, /*anything*/ value){
+               // summary
+               //              Set native HTML attributes reflected in the widget,
+               //              such as readOnly, disabled, and maxLength in TextBox widgets.
+               // description
+               //              In general, a widget's "value" is controlled via setValue()/getValue(), 
+               //              rather than this method.  The exception is for widgets where the
+               //              end user can't adjust the value, such as Button and CheckBox;
+               //              in the unusual case that you want to change the value attribute of
+               //              those widgets, use setAttribute().
+               var mapNode = this[this.attributeMap[attr]||'domNode'];
+               this[attr] = value;
+               switch(attr){
+                       case "class":
+                               dojo.addClass(mapNode, value);
+                               break;
+                       case "style":
+                               if(mapNode.style.cssText){
+                                       mapNode.style.cssText += "; " + value;// FIXME: Opera
+                               }else{
+                                       mapNode.style.cssText = value;
+                               }
+                               break;
+                       default:
+                               if(/^on[A-Z]/.test(attr)){ // eg. onSubmit needs to be onsubmit
+                                       attr = attr.toLowerCase();
+                               }
+                               if(typeof value == "function"){ // functions execute in the context of the widget
+                                       value = dojo.hitch(this, value);
+                               }
+                               dojo.attr(mapNode, attr, value);
+               }
+       },
+
+       toString: function(){
+               // summary:
+               //              returns a string that represents the widget. When a widget is
+               //              cast to a string, this method will be used to generate the
+               //              output. Currently, it does not implement any sort of reversable
+               //              serialization.
+               return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
+       },
+
+       getDescendants: function(){
+               // summary:
+               //      Returns all the widgets that contained by this, i.e., all widgets underneath this.containerNode.
+               if(this.containerNode){
+                       var list= dojo.query('[widgetId]', this.containerNode);
+                       return list.map(dijit.byNode);          // Array
+               }else{
+                       return [];
+               }
+       },
+
+//TODOC
+       nodesWithKeyClick: ["input", "button"],
+
+       connect: function(
+                       /*Object|null*/ obj,
+                       /*String*/ event,
+                       /*String|Function*/ method){
+               //      summary:
+               //              Connects specified obj/event to specified method of this object
+               //              and registers for disconnect() on widget destroy.
+               //              Special event: "ondijitclick" triggers on a click or enter-down or space-up
+               //              Similar to dojo.connect() but takes three arguments rather than four.
+               var handles =[];
+               if(event == "ondijitclick"){
+                       // add key based click activation for unsupported nodes.
+                       if(!this.nodesWithKeyClick[obj.nodeName]){
+                               handles.push(dojo.connect(obj, "onkeydown", this,
+                                       function(e){
+                                               if(e.keyCode == dojo.keys.ENTER){
+                                                       return (dojo.isString(method))?
+                                                               this[method](e) : method.call(this, e);
+                                               }else if(e.keyCode == dojo.keys.SPACE){
+                                                       // stop space down as it causes IE to scroll
+                                                       // the browser window
+                                                       dojo.stopEvent(e);
+                                               }
+                                       }));
+                               handles.push(dojo.connect(obj, "onkeyup", this,
+                                       function(e){
+                                               if(e.keyCode == dojo.keys.SPACE){
+                                                       return dojo.isString(method) ?
+                                                               this[method](e) : method.call(this, e);
+                                               }
+                                       }));
+                       }
+                       event = "onclick";
+               }
+               handles.push(dojo.connect(obj, event, this, method));
+
+               // return handles for FormElement and ComboBox
+               this._connects.push(handles);
+               return handles;
+       },
+
+       disconnect: function(/*Object*/ handles){
+               // summary:
+               //              Disconnects handle created by this.connect.
+               //              Also removes handle from this widget's list of connects
+               for(var i=0; i<this._connects.length; i++){
+                       if(this._connects[i]==handles){
+                               dojo.forEach(handles, dojo.disconnect);
+                               this._connects.splice(i, 1);
+                               return;
+                       }
+               }
+       },
+
+       isLeftToRight: function(){
+               // summary:
+               //              Checks the DOM to for the text direction for bi-directional support
+               // description:
+               //              This method cannot be used during widget construction because the widget
+               //              must first be connected to the DOM tree.  Parent nodes are searched for the
+               //              'dir' attribute until one is found, otherwise left to right mode is assumed.
+               //              See HTML spec, DIR attribute for more information.
+
+               if(!("_ltr" in this)){
+                       this._ltr = dojo.getComputedStyle(this.domNode).direction != "rtl";
+               }
+               return this._ltr; //Boolean
+       },
+
+       isFocusable: function(){
+               // summary:
+               //              Return true if this widget can currently be focused
+               //              and false if not
+               return this.focus && (dojo.style(this.domNode, "display") != "none");
+       }
+});
+
+}