Blame | Last modification | View Log | RSS feed
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// Language to display this widget in (like en-us).// Defaults to brower's specified preferred language (typically the language of the OS)lang: "",// dir: String// Bi-directional support, as defined by the HTML DIR attribute. Either left-to-right "ltr" or right-to-left "rtl".dir: "",// class: String// HTML class attribute"class": "",// style: String// HTML style attributestyle: "",// title: String// HTML title attributetitle: "",// srcNodeRef: DomNode// pointer to original dom nodesrcNodeRef: 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 ///////////////////////////////////////postscript: function(params, srcNodeRef){this.create(params, srcNodeRef);},create: function(params, srcNodeRef){// summary:// 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 treethis.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 variablesthis._attaches=[];//mixin our passed parametersif(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }if(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 mapNode = this[this.attributeMap[attr] || "domNode"];var value = this[attr];if(typeof value != "object" && (value !== "" || (params && params[attr]))){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:mapNode.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},//////////// 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);});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. Over-ride to implement custom widget tear-down// behavior.return false;},////////////////// MISCELLANEOUS METHODS ///////////////////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:// return all the descendant widgetsvar list = dojo.query('[widgetId]', this.domNode);return list.map(dijit.byNode); // Array},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"){var w = this;// 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))?w[method](e) : method.call(w, e);}else if(e.keyCode == dojo.keys.SPACE){// stop space down as it causes IE to scroll// the browser windowdojo.stopEvent(e);}}));handles.push(dojo.connect(obj, "onkeyup", this,function(e){if(e.keyCode == dojo.keys.SPACE){return dojo.isString(method) ?w[method](e) : method.call(w, e);}}));}event = "onclick";}handles.push(dojo.connect(obj, event, this, method));// return handles for FormElement and ComboBoxthis._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 connectsfor(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(typeof this._ltr == "undefined"){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 notreturn this.focus && (dojo.style(this.domNode, "display") != "none");}});}