123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- 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 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
- // ///////////////////////////////////////
- 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 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) {
- 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 widgets
- var 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 window
- dojo.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 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 (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 not
- return this.focus
- && (dojo.style(this.domNode, "display") != "none");
- }
- });
- }
|