0byt3m1n1
Path:
/
data
/
applications
/
aps.bak
/
phprojekt
/
6.0.6-0
/
standard
/
htdocs
/
htdocs
/
dojo
/
dijit
/
[
Home
]
File: _Widget.js
/* Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ 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" ); // This code is to assist deferring dojo.connect() calls in widgets (connecting to events on the widgets' // DOM nodes) until someone actually needs to monitor that event. dojo.connect(dojo, "_connect", function(/*dijit._Widget*/ widget, /*String*/ event){ if(widget && dojo.isFunction(widget._onConnect)){ widget._onConnect(event); } }); dijit._connectOnUseEventHandler = function(/*Event*/ event){}; // Keep track of where the last keydown event was, to help avoid generating // spurious ondijitclick events when: // 1. focus is on a <button> or <a> // 2. user presses then releases the ENTER key // 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler // 4. onkeyup event fires, causing the ondijitclick handler to fire dijit._lastKeyDownNode = null; if(dojo.isIE){ (function(){ var keydownCallback = function(evt){ dijit._lastKeyDownNode = evt.srcElement; }; dojo.doc.attachEvent('onkeydown', keydownCallback); dojo.addOnWindowUnload(function(){ dojo.doc.detachEvent('onkeydown', keydownCallback); }); })(); }else{ dojo.doc.addEventListener('keydown', function(evt){ dijit._lastKeyDownNode = evt.target; }, true); } (function(){ var _attrReg = {}, // cached results from getSetterAttributes getSetterAttributes = function(widget){ // summary: // Returns list of attributes with custom setters for specified widget var dc = widget.declaredClass; if(!_attrReg[dc]){ var r = [], attrs, proto = widget.constructor.prototype; for(var fxName in proto){ if(dojo.isFunction(proto[fxName]) && (attrs = fxName.match(/^_set([a-zA-Z]*)Attr$/)) && attrs[1]){ r.push(attrs[1].charAt(0).toLowerCase() + attrs[1].substr(1)); } } _attrReg[dc] = r; } return _attrReg[dc] || []; // String[] }; dojo.declare("dijit._Widget", null, { // summary: // Base class for all Dijit widgets. // id: [const] 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: [const] 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: [const] String // 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". If undefined, widgets renders in page's // default direction. dir: "", // class: String // HTML class attribute "class": "", // style: String||Object // HTML style attributes as cssText string or name/value hash style: "", // title: String // HTML title attribute. // // For form widgets this specifies a tooltip to display when hovering over // the widget (just like the native HTML title attribute). // // For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer, // etc., it's used to specify the tab label, accordion pane title, etc. title: "", // tooltip: String // When this widget's title attribute is used to for a tab label, accordion pane title, etc., // this specifies the tooltip to appear when the mouse is hovered over that text. tooltip: "", // baseClass: [protected] String // Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate // widget state. baseClass: "", // srcNodeRef: [readonly] DomNode // pointer to original DOM node srcNodeRef: null, // domNode: [readonly] DomNode // This is our visible representation of the widget! Other DOM // Nodes may by assigned to other properties, usually through the // template system's dojoAttachPoint syntax, but the domNode // property is the canonical "top level" node in widget UI. domNode: null, // containerNode: [readonly] DomNode // Designates where children of the source DOM node will be placed. // "Children" in this case refers to both DOM nodes and widgets. // For example, for myWidget: // // | <div dojoType=myWidget> // | <b> here's a plain DOM node // | <span dojoType=subWidget>and a widget</span> // | <i> and another plain DOM node </i> // | </div> // // containerNode would point to: // // | <b> here's a plain DOM node // | <span dojoType=subWidget>and a widget</span> // | <i> and another plain DOM node </i> // // In templated widgets, "containerNode" is set via a // dojoAttachPoint assignment. // // containerNode must be defined for any widget that accepts innerHTML // (like ContentPane or BorderContainer or even Button), and conversely // is null for widgets that don't, like TextBox. containerNode: null, /*===== // _started: Boolean // startup() has completed. _started: false, =====*/ // attributeMap: [protected] Object // attributeMap sets up a "binding" between attributes (aka properties) // of the widget and the widget's DOM. // Changes to widget attributes listed in attributeMap will be // reflected into the DOM. // // For example, calling attr('title', 'hello') // on a TitlePane will automatically cause the TitlePane's DOM to update // with the new title. // // attributeMap is a hash where the key is an attribute of the widget, // and the value reflects a binding to a: // // - DOM node attribute // | focus: {node: "focusNode", type: "attribute"} // Maps this.focus to this.focusNode.focus // // - DOM node innerHTML // | title: { node: "titleNode", type: "innerHTML" } // Maps this.title to this.titleNode.innerHTML // // - DOM node innerText // | title: { node: "titleNode", type: "innerText" } // Maps this.title to this.titleNode.innerText // // - DOM node CSS class // | myClass: { node: "domNode", type: "class" } // Maps this.myClass to this.domNode.className // // If the value is an array, then each element in the array matches one of the // formats of the above list. // // There are also some shorthands for backwards compatibility: // - string --> { node: string, type: "attribute" }, for example: // | "focusNode" ---> { node: "focusNode", type: "attribute" } // - "" --> { node: "domNode", type: "attribute" } attributeMap: {id:"", dir:"", lang:"", "class":"", style:"", title:""}, // _deferredConnects: [protected] Object // attributeMap addendum for event handlers that should be connected only on first use _deferredConnects: { onClick: "", onDblClick: "", onKeyDown: "", onKeyPress: "", onKeyUp: "", onMouseMove: "", onMouseDown: "", onMouseOut: "", onMouseOver: "", onMouseLeave: "", onMouseEnter: "", onMouseUp: "" }, onClick: dijit._connectOnUseEventHandler, /*===== onClick: function(event){ // summary: // Connect to this function to receive notifications of mouse click events. // event: // mouse Event // tags: // callback }, =====*/ onDblClick: dijit._connectOnUseEventHandler, /*===== onDblClick: function(event){ // summary: // Connect to this function to receive notifications of mouse double click events. // event: // mouse Event // tags: // callback }, =====*/ onKeyDown: dijit._connectOnUseEventHandler, /*===== onKeyDown: function(event){ // summary: // Connect to this function to receive notifications of keys being pressed down. // event: // key Event // tags: // callback }, =====*/ onKeyPress: dijit._connectOnUseEventHandler, /*===== onKeyPress: function(event){ // summary: // Connect to this function to receive notifications of printable keys being typed. // event: // key Event // tags: // callback }, =====*/ onKeyUp: dijit._connectOnUseEventHandler, /*===== onKeyUp: function(event){ // summary: // Connect to this function to receive notifications of keys being released. // event: // key Event // tags: // callback }, =====*/ onMouseDown: dijit._connectOnUseEventHandler, /*===== onMouseDown: function(event){ // summary: // Connect to this function to receive notifications of when the mouse button is pressed down. // event: // mouse Event // tags: // callback }, =====*/ onMouseMove: dijit._connectOnUseEventHandler, /*===== onMouseMove: function(event){ // summary: // Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget. // event: // mouse Event // tags: // callback }, =====*/ onMouseOut: dijit._connectOnUseEventHandler, /*===== onMouseOut: function(event){ // summary: // Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget. // event: // mouse Event // tags: // callback }, =====*/ onMouseOver: dijit._connectOnUseEventHandler, /*===== onMouseOver: function(event){ // summary: // Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget. // event: // mouse Event // tags: // callback }, =====*/ onMouseLeave: dijit._connectOnUseEventHandler, /*===== onMouseLeave: function(event){ // summary: // Connect to this function to receive notifications of when the mouse moves off of this widget. // event: // mouse Event // tags: // callback }, =====*/ onMouseEnter: dijit._connectOnUseEventHandler, /*===== onMouseEnter: function(event){ // summary: // Connect to this function to receive notifications of when the mouse moves onto this widget. // event: // mouse Event // tags: // callback }, =====*/ onMouseUp: dijit._connectOnUseEventHandler, /*===== onMouseUp: function(event){ // summary: // Connect to this function to receive notifications of when the mouse button is released. // event: // mouse Event // tags: // callback }, =====*/ // Constants used in templates // _blankGif: [protected] String // Path to a blank 1x1 image. // Used by <img> nodes in templates that really get their image via CSS background-image. _blankGif: (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")).toString(), //////////// INITIALIZATION METHODS /////////////////////////////////////// postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){ // summary: // Kicks off widget instantiation. See create() for details. // tags: // private this.create(params, srcNodeRef); }, create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){ // summary: // Kick off the life-cycle of a widget // params: // Hash of initialization parameters for widget, including // scalar values (like title, duration etc.) and functions, // typically callbacks like onClick. // srcNodeRef: // If a srcNodeRef (DOM node) is specified: // - use srcNodeRef.innerHTML as my contents // - if this is a behavioral widget then apply behavior // to that srcNodeRef // - otherwise, replace srcNodeRef with my generated DOM // tree // description: // Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate, // etc.), some of which of you'll want to override. See http://docs.dojocampus.org/dijit/_Widget // for a discussion of the widget creation lifecycle. // // Of course, adventurous developers could override create entirely, but this should // only be done as a last resort. // tags: // private // 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 = []; // For garbage collection. An array of handles returned by Widget.subscribe() // The handle returned from Widget.subscribe() is the handle returned from dojo.subscribe() this._subscribes = []; // To avoid double-connects, remove entries from _deferredConnects // that have been setup manually by a subclass (ex, by dojoAttachEvent). // If a subclass has redefined a callback (ex: onClick) then assume it's being // connected to manually. this._deferredConnects = dojo.clone(this._deferredConnects); for(var attr in this.attributeMap){ delete this._deferredConnects[attr]; // can't be in both attributeMap and _deferredConnects } for(attr in this._deferredConnects){ if(this[attr] !== dijit._connectOnUseEventHandler){ delete this._deferredConnects[attr]; // redefined, probably dojoAttachEvent exists } } //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(); if(this.domNode){ // Copy attributes listed in attributeMap into the [newly created] DOM for the widget. this._applyAttributes(); var source = this.srcNodeRef; if(source && source.parentNode){ source.parentNode.replaceChild(this.domNode, source); } // If the developer has specified a handler as a widget parameter // (ex: new Button({onClick: ...}) // then naturally need to connect from DOM node to that handler immediately, for(attr in this.params){ this._onConnect(attr); } } 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; } this._created = true; }, _applyAttributes: function(){ // summary: // Step during widget creation to copy all widget attributes to the // DOM as per attributeMap and _setXXXAttr functions. // description: // Skips over blank/false attribute values, unless they were explicitly specified // as parameters to the widget, since those are the default anyway, // and setting tabIndex="" is different than not setting tabIndex at all. // // It processes the attributes in the attribute map first, and then // it goes through and processes the attributes for the _setXXXAttr // functions that have been specified // tags: // private var condAttrApply = function(attr, scope){ if((scope.params && attr in scope.params) || scope[attr]){ scope.set(attr, scope[attr]); } }; // Do the attributes in attributeMap for(var attr in this.attributeMap){ condAttrApply(attr, this); } // And also any attributes with custom setters dojo.forEach(getSetterAttributes(this), function(a){ if(!(a in this.attributeMap)){ condAttrApply(a, this); } }, this); }, 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. // tags: // protected }, buildRendering: function(){ // summary: // Construct the UI for this widget, setting this.domNode // description: // Most widgets will mixin `dijit._Templated`, which implements this // method. // tags: // protected this.domNode = this.srcNodeRef || dojo.create('div'); }, postCreate: function(){ // summary: // Processing after the DOM fragment is created // description: // Called after the DOM fragment has been created, but not necessarily // added to the document. Do not include any operations which rely on // node dimensions or placement. // tags: // protected // baseClass is a single class name or occasionally a space-separated list of names. // Add those classes to the DOMNod. If RTL mode then also add with Rtl suffix. if(this.baseClass){ var classes = this.baseClass.split(" "); if(!this.isLeftToRight()){ classes = classes.concat( dojo.map(classes, function(name){ return name+"Rtl"; })); } dojo.addClass(this.domNode, classes); } }, startup: function(){ // summary: // Processing after the DOM fragment is added to the document // description: // Called after a widget and its children have been created and added to the page, // and all related widgets have finished their create() cycle, up through postCreate(). // 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?*/ preserveDom){ // summary: // Destroy this widget and its descendants // description: // This is the generic "destructor" function that all widget users // should call to cleanly discard with a widget. Once a widget is // destroyed, it is removed from the manager object. // preserveDom: // If true, this method will leave the original DOM structure // alone of descendant Widgets. Note: This will NOT work with // dijit._Templated widgets. this._beingDestroyed = true; this.destroyDescendants(preserveDom); this.destroy(preserveDom); }, destroy: function(/*Boolean*/ preserveDom){ // summary: // Destroy this widget, but not its descendants. // This method will, however, destroy internal widgets such as those used within a template. // preserveDom: Boolean // If true, this method will leave the original DOM structure alone. // Note: This will not yet work with _Templated widgets this._beingDestroyed = true; this.uninitialize(); var d = dojo, dfe = d.forEach, dun = d.unsubscribe; dfe(this._connects, function(array){ dfe(array, d.disconnect); }); dfe(this._subscribes, function(handle){ dun(handle); }); // destroy widgets created as part of template, etc. dfe(this._supportingWidgets || [], function(w){ if(w.destroyRecursive){ w.destroyRecursive(); }else if(w.destroy){ w.destroy(); } }); this.destroyRendering(preserveDom); dijit.registry.remove(this.id); this._destroyed = true; }, destroyRendering: function(/*Boolean?*/ preserveDom){ // summary: // Destroys the DOM nodes associated with this widget // preserveDom: // If true, this method will leave the original DOM structure alone // during tear-down. Note: this will not work with _Templated // widgets yet. // tags: // protected if(this.bgIframe){ this.bgIframe.destroy(preserveDom); delete this.bgIframe; } if(this.domNode){ if(preserveDom){ dojo.removeAttr(this.domNode, "widgetId"); }else{ dojo.destroy(this.domNode); } delete this.domNode; } if(this.srcNodeRef){ if(!preserveDom){ dojo.destroy(this.srcNodeRef); } delete this.srcNodeRef; } }, destroyDescendants: function(/*Boolean?*/ preserveDom){ // summary: // Recursively destroy the children of this widget and their // descendants. // preserveDom: // If true, the preserveDom attribute is passed to all descendant // widget's .destroy() method. Not for use with _Templated // widgets. // get all direct descendants and destroy them recursively dojo.forEach(this.getChildren(), function(widget){ if(widget.destroyRecursive){ widget.destroyRecursive(preserveDom); } }); }, uninitialize: function(){ // summary: // Stub function. Override to implement custom widget tear-down // behavior. // tags: // protected return false; }, ////////////////// MISCELLANEOUS METHODS /////////////////// onFocus: function(){ // summary: // Called when the widget becomes "active" because // it or a widget inside of it either has focus, or has recently // been clicked. // tags: // callback }, onBlur: function(){ // summary: // Called when the widget stops being "active" because // focus moved to something outside of it, or the user // clicked somewhere outside of it, or the widget was // hidden. // tags: // callback }, _onFocus: function(e){ // summary: // This is where widgets do processing for when they are active, // such as changing CSS classes. See onFocus() for more details. // tags: // protected this.onFocus(); }, _onBlur: function(){ // summary: // This is where widgets do processing for when they stop being active, // such as changing CSS classes. See onBlur() for more details. // tags: // protected this.onBlur(); }, _onConnect: function(/*String*/ event){ // summary: // Called when someone connects to one of my handlers. // "Turn on" that handler if it isn't active yet. // // This is also called for every single initialization parameter // so need to do nothing for parameters like "id". // tags: // private if(event in this._deferredConnects){ var mapNode = this[this._deferredConnects[event] || 'domNode']; this.connect(mapNode, event.toLowerCase(), event); delete this._deferredConnects[event]; } }, _setClassAttr: function(/*String*/ value){ // summary: // Custom setter for the CSS "class" attribute // tags: // protected var mapNode = this[this.attributeMap["class"] || 'domNode']; dojo.removeClass(mapNode, this["class"]) this["class"] = value; dojo.addClass(mapNode, value); }, _setStyleAttr: function(/*String||Object*/ value){ // summary: // Sets the style attribut of the widget according to value, // which is either a hash like {height: "5px", width: "3px"} // or a plain string // description: // Determines which node to set the style on based on style setting // in attributeMap. // tags: // protected var mapNode = this[this.attributeMap.style || 'domNode']; // Note: technically we should revert any style setting made in a previous call // to his method, but that's difficult to keep track of. if(dojo.isObject(value)){ dojo.style(mapNode, value); }else{ if(mapNode.style.cssText){ mapNode.style.cssText += "; " + value; }else{ mapNode.style.cssText = value; } } this.style = value; }, setAttribute: function(/*String*/ attr, /*anything*/ value){ // summary: // Deprecated. Use set() instead. // tags: // deprecated dojo.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0"); this.set(attr, value); }, _attrToDom: function(/*String*/ attr, /*String*/ value){ // summary: // Reflect a widget attribute (title, tabIndex, duration etc.) to // the widget DOM, as specified in attributeMap. // // description: // Also sets this["attr"] to the new value. // Note some attributes like "type" // cannot be processed this way as they are not mutable. // // tags: // private var commands = this.attributeMap[attr]; dojo.forEach(dojo.isArray(commands) ? commands : [commands], function(command){ // Get target node and what we are doing to that node var mapNode = this[command.node || command || "domNode"]; // DOM node var type = command.type || "attribute"; // class, innerHTML, innerText, or attribute switch(type){ case "attribute": if(dojo.isFunction(value)){ // functions execute in the context of the widget value = dojo.hitch(this, value); } // Get the name of the DOM node attribute; usually it's the same // as the name of the attribute in the widget (attr), but can be overridden. // Also maps handler names to lowercase, like onSubmit --> onsubmit var attrName = command.attribute ? command.attribute : (/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr); dojo.attr(mapNode, attrName, value); break; case "innerText": mapNode.innerHTML = ""; mapNode.appendChild(dojo.doc.createTextNode(value)); break; case "innerHTML": mapNode.innerHTML = value; break; case "class": dojo.removeClass(mapNode, this[attr]); dojo.addClass(mapNode, value); break; } }, this); this[attr] = value; }, attr: function(/*String|Object*/name, /*Object?*/value){ // summary: // Set or get properties on a widget instance. // name: // The property to get or set. If an object is passed here and not // a string, its keys are used as names of attributes to be set // and the value of the object as values to set in the widget. // value: // Optional. If provided, attr() operates as a setter. If omitted, // the current value of the named property is returned. // description: // This method is deprecated, use get() or set() directly. // Print deprecation warning but only once per calling function if(dojo.config.isDebug){ var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}), caller = (arguments.callee.caller || "unknown caller").toString(); if(!alreadyCalledHash[caller]){ dojo.deprecated(this.declaredClass + "::attr() is deprecated. Use get() or set() instead, called from " + caller, "", "2.0"); alreadyCalledHash[caller] = true; } } var args = arguments.length; if(args >= 2 || typeof name === "object"){ // setter return this.set.apply(this, arguments); }else{ // getter return this.get(name); } }, get: function(name){ // summary: // Get a property from a widget. // name: // The property to get. // description: // Get a named property from a widget. The property may // potentially be retrieved via a getter method. If no getter is defined, this // just retrieves the object's property. // For example, if the widget has a properties "foo" // and "bar" and a method named "_getFooAttr", calling: // | myWidget.get("foo"); // would be equivalent to writing: // | widget._getFooAttr(); // and: // | myWidget.get("bar"); // would be equivalent to writing: // | widget.bar; var names = this._getAttrNames(name); return this[names.g] ? this[names.g]() : this[name]; }, set: function(name, value){ // summary: // Set a property on a widget // name: // The property to set. // value: // The value to set in the property. // description: // Sets named properties on a widget which may potentially be handled by a // setter in the widget. // For example, if the widget has a properties "foo" // and "bar" and a method named "_setFooAttr", calling: // | myWidget.set("foo", "Howdy!"); // would be equivalent to writing: // | widget._setFooAttr("Howdy!"); // and: // | myWidget.set("bar", 3); // would be equivalent to writing: // | widget.bar = 3; // // set() may also be called with a hash of name/value pairs, ex: // | myWidget.set({ // | foo: "Howdy", // | bar: 3 // | }) // This is equivalent to calling set(foo, "Howdy") and set(bar, 3) if(typeof name === "object"){ for(var x in name){ this.set(x, name[x]); } return this; } var names = this._getAttrNames(name); if(this[names.s]){ // use the explicit setter var result = this[names.s].apply(this, Array.prototype.slice.call(arguments, 1)); }else{ // if param is specified as DOM node attribute, copy it if(name in this.attributeMap){ this._attrToDom(name, value); } var oldValue = this[name]; // FIXME: what about function assignments? Any way to connect() here? this[name] = value; } return result || this; }, _attrPairNames: {}, // shared between all widgets _getAttrNames: function(name){ // summary: // Helper function for get() and set(). // Caches attribute name values so we don't do the string ops every time. // tags: // private var apn = this._attrPairNames; if(apn[name]){ return apn[name]; } var uc = name.charAt(0).toUpperCase() + name.substr(1); return (apn[name] = { n: name+"Node", s: "_set"+uc+"Attr", g: "_get"+uc+"Attr" }); }, toString: function(){ // summary: // Returns a string that represents the widget // description: // 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 reversible // serialization. return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String }, getDescendants: function(){ // summary: // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode. // This method should generally be avoided as it returns widgets declared in templates, which are // supposed to be internal/hidden, but it's left here for back-compat reasons. return this.containerNode ? dojo.query('[widgetId]', this.containerNode).map(dijit.byNode) : []; // dijit._Widget[] }, getChildren: function(){ // summary: // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode. // Does not return nested widgets, nor widgets that are part of this widget's template. return this.containerNode ? dijit.findWidgets(this.containerNode) : []; // dijit._Widget[] }, // nodesWithKeyClick: [private] String[] // List of nodes that correctly handle click events via native browser support, // and don't need dijit's help nodesWithKeyClick: ["input", "button"], connect: function( /*Object|null*/ obj, /*String|Function*/ event, /*String|Function*/ method){ // summary: // Connects specified obj/event to specified method of this object // and registers for disconnect() on widget destroy. // description: // Provide widget-specific analog to dojo.connect, except with the // implicit use of this widget as the target object. // This version of connect also provides a special "ondijitclick" // event which triggers on a click or space or enter keyup // returns: // A handle that can be passed to `disconnect` in order to disconnect before // the widget is destroyed. // example: // | var btn = new dijit.form.Button(); // | // when foo.bar() is called, call the listener we're going to // | // provide in the scope of btn // | btn.connect(foo, "bar", function(){ // | console.debug(this.toString()); // | }); // tags: // protected var d = dojo, dc = d._connect, handles = []; if(event == "ondijitclick"){ // add key based click activation for unsupported nodes. // do all processing onkey up to prevent spurious clicks // for details see comments at top of this file where _lastKeyDownNode is defined if(dojo.indexOf(this.nodesWithKeyClick, obj.nodeName.toLowerCase()) == -1){ // is NOT input or button var m = d.hitch(this, method); handles.push( dc(obj, "onkeydown", this, function(e){ //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode)); if((e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){ // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work dijit._lastKeyDownNode = e.target; e.preventDefault(); // stop event to prevent scrolling on space key in IE } }), dc(obj, "onkeyup", this, function(e){ //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode)); if( (e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) && e.target === dijit._lastKeyDownNode && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){ //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert dijit._lastKeyDownNode = null; return m(e); } }) ); } event = "onclick"; } handles.push(dc(obj, event, this, method)); this._connects.push(handles); return handles; // _Widget.Handle }, disconnect: function(/* _Widget.Handle */ handles){ // summary: // Disconnects handle created by `connect`. // Also removes handle from this widget's list of connects. // tags: // protected 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; } } }, subscribe: function( /*String*/ topic, /*String|Function*/ method){ // summary: // Subscribes to the specified topic and calls the specified method // of this object and registers for unsubscribe() on widget destroy. // description: // Provide widget-specific analog to dojo.subscribe, except with the // implicit use of this widget as the target object. // example: // | var btn = new dijit.form.Button(); // | // when /my/topic is published, this button changes its label to // | // be the parameter of the topic. // | btn.subscribe("/my/topic", function(v){ // | this.set("label", v); // | }); var d = dojo, handle = d.subscribe(topic, this, method); // return handles for Any widget that may need them this._subscribes.push(handle); return handle; }, unsubscribe: function(/*Object*/ handle){ // summary: // Unsubscribes handle created by this.subscribe. // Also removes handle from this widget's list of subscriptions for(var i=0; i<this._subscribes.length; i++){ if(this._subscribes[i] == handle){ dojo.unsubscribe(handle); this._subscribes.splice(i, 1); return; } } }, isLeftToRight: function(){ // summary: // Return this widget's explicit or implicit orientation (true for LTR, false for RTL) // tags: // protected return this.dir ? (this.dir == "ltr") : dojo._isBodyLtr(); //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"); }, placeAt: function(/* String|DomNode|_Widget */reference, /* String?|Int? */position){ // summary: // Place this widget's domNode reference somewhere in the DOM based // on standard dojo.place conventions, or passing a Widget reference that // contains and addChild member. // // description: // A convenience function provided in all _Widgets, providing a simple // shorthand mechanism to put an existing (or newly created) Widget // somewhere in the dom, and allow chaining. // // reference: // The String id of a domNode, a domNode reference, or a reference to a Widget posessing // an addChild method. // // position: // If passed a string or domNode reference, the position argument // accepts a string just as dojo.place does, one of: "first", "last", // "before", or "after". // // If passed a _Widget reference, and that widget reference has an ".addChild" method, // it will be called passing this widget instance into that method, supplying the optional // position index passed. // // returns: // dijit._Widget // Provides a useful return of the newly created dijit._Widget instance so you // can "chain" this function by instantiating, placing, then saving the return value // to a variable. // // example: // | // create a Button with no srcNodeRef, and place it in the body: // | var button = new dijit.form.Button({ label:"click" }).placeAt(dojo.body()); // | // now, 'button' is still the widget reference to the newly created button // | dojo.connect(button, "onClick", function(e){ console.log('click'); }); // // example: // | // create a button out of a node with id="src" and append it to id="wrapper": // | var button = new dijit.form.Button({},"src").placeAt("wrapper"); // // example: // | // place a new button as the first element of some div // | var button = new dijit.form.Button({ label:"click" }).placeAt("wrapper","first"); // // example: // | // create a contentpane and add it to a TabContainer // | var tc = dijit.byId("myTabs"); // | new dijit.layout.ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc) if(reference.declaredClass && reference.addChild){ reference.addChild(this, position); }else{ dojo.place(this.domNode, reference, position); } return this; }, _onShow: function(){ // summary: // Internal method called when this widget is made visible. // See `onShow` for details. this.onShow(); }, onShow: function(){ // summary: // Called when this widget becomes the selected pane in a // `dijit.layout.TabContainer`, `dijit.layout.StackContainer`, // `dijit.layout.AccordionContainer`, etc. // // Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`. // tags: // callback }, onHide: function(){ // summary: // Called when another widget becomes the selected pane in a // `dijit.layout.TabContainer`, `dijit.layout.StackContainer`, // `dijit.layout.AccordionContainer`, etc. // // Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`. // tags: // callback }, onClose: function(){ // summary: // Called when this widget is being displayed as a popup (ex: a Calendar popped // up from a DateTextBox), and it is hidden. // This is called from the dijit.popup code, and should not be called directly. // // Also used as a parameter for children of `dijit.layout.StackContainer` or subclasses. // Callback if a user tries to close the child. Child will be closed if this function returns true. // tags: // extension return true; // Boolean } }); })(); }