]> git.wh0rd.org - tt-rss.git/blame - lib/dijit/_Widget.js
upgrade Dojo to 1.6.1
[tt-rss.git] / lib / dijit / _Widget.js
CommitLineData
2f01fe57 1/*
81bea17a 2 Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
2f01fe57
AD
3 Available via Academic Free License >= 2.1 OR the modified BSD license.
4 see: http://dojotoolkit.org/license for details
5*/
6
7
81bea17a
AD
8if(!dojo._hasResource["dijit._Widget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9dojo._hasResource["dijit._Widget"] = true;
2f01fe57 10dojo.provide("dijit._Widget");
81bea17a 11dojo.require("dijit._WidgetBase");
2f01fe57 12dojo.require("dijit._base");
81bea17a
AD
13
14
15
16////////////////// DEFERRED CONNECTS ///////////////////
17
18// This code is to assist deferring dojo.connect() calls in widgets (connecting to events on the widgets'
19// DOM nodes) until someone actually needs to monitor that event.
20dojo.connect(dojo, "_connect",
21 function(/*dijit._Widget*/ widget, /*String*/ event){
22 if(widget && dojo.isFunction(widget._onConnect)){
23 widget._onConnect(event);
24 }
25 });
26
27dijit._connectOnUseEventHandler = function(/*Event*/ event){};
28
29////////////////// ONDIJITCLICK SUPPORT ///////////////////
30
31// Keep track of where the last keydown event was, to help avoid generating
32// spurious ondijitclick events when:
33// 1. focus is on a <button> or <a>
34// 2. user presses then releases the ENTER key
35// 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
36// 4. onkeyup event fires, causing the ondijitclick handler to fire
37dijit._lastKeyDownNode = null;
2f01fe57 38if(dojo.isIE){
81bea17a
AD
39 (function(){
40 var keydownCallback = function(evt){
41 dijit._lastKeyDownNode = evt.srcElement;
42 };
43 dojo.doc.attachEvent('onkeydown', keydownCallback);
44 dojo.addOnWindowUnload(function(){
45 dojo.doc.detachEvent('onkeydown', keydownCallback);
46 });
47 })();
2f01fe57 48}else{
81bea17a
AD
49 dojo.doc.addEventListener('keydown', function(evt){
50 dijit._lastKeyDownNode = evt.target;
51 }, true);
2f01fe57 52}
81bea17a 53
2f01fe57 54(function(){
81bea17a
AD
55
56dojo.declare("dijit._Widget", dijit._WidgetBase, {
57 // summary:
58 // Base class for all Dijit widgets.
59 //
60 // Extends _WidgetBase, adding support for:
61 // - deferred connections
62 // A call like dojo.connect(myWidget, "onMouseMove", func)
63 // will essentially do a dojo.connect(myWidget.domNode, "onMouseMove", func)
64 // - ondijitclick
65 // Support new dojoAttachEvent="ondijitclick: ..." that is triggered by a mouse click or a SPACE/ENTER keypress
66 // - focus related functions
67 // In particular, the onFocus()/onBlur() callbacks. Driven internally by
68 // dijit/_base/focus.js.
69 // - deprecated methods
70 // - onShow(), onHide(), onClose()
71 //
72 // Also, by loading code in dijit/_base, turns on:
73 // - browser sniffing (putting browser id like .dj_ie on <html> node)
74 // - high contrast mode sniffing (add .dijit_a11y class to <body> if machine is in high contrast mode)
75
76
77 ////////////////// DEFERRED CONNECTS ///////////////////
78
79 // _deferredConnects: [protected] Object
80 // attributeMap addendum for event handlers that should be connected only on first use
81 _deferredConnects: {
82 onClick: "",
83 onDblClick: "",
84 onKeyDown: "",
85 onKeyPress: "",
86 onKeyUp: "",
87 onMouseMove: "",
88 onMouseDown: "",
89 onMouseOut: "",
90 onMouseOver: "",
91 onMouseLeave: "",
92 onMouseEnter: "",
93 onMouseUp: ""
94 },
95
96 onClick: dijit._connectOnUseEventHandler,
97 /*=====
98 onClick: function(event){
99 // summary:
100 // Connect to this function to receive notifications of mouse click events.
101 // event:
102 // mouse Event
103 // tags:
104 // callback
105 },
106 =====*/
107 onDblClick: dijit._connectOnUseEventHandler,
108 /*=====
109 onDblClick: function(event){
110 // summary:
111 // Connect to this function to receive notifications of mouse double click events.
112 // event:
113 // mouse Event
114 // tags:
115 // callback
116 },
117 =====*/
118 onKeyDown: dijit._connectOnUseEventHandler,
119 /*=====
120 onKeyDown: function(event){
121 // summary:
122 // Connect to this function to receive notifications of keys being pressed down.
123 // event:
124 // key Event
125 // tags:
126 // callback
127 },
128 =====*/
129 onKeyPress: dijit._connectOnUseEventHandler,
130 /*=====
131 onKeyPress: function(event){
132 // summary:
133 // Connect to this function to receive notifications of printable keys being typed.
134 // event:
135 // key Event
136 // tags:
137 // callback
138 },
139 =====*/
140 onKeyUp: dijit._connectOnUseEventHandler,
141 /*=====
142 onKeyUp: function(event){
143 // summary:
144 // Connect to this function to receive notifications of keys being released.
145 // event:
146 // key Event
147 // tags:
148 // callback
149 },
150 =====*/
151 onMouseDown: dijit._connectOnUseEventHandler,
152 /*=====
153 onMouseDown: function(event){
154 // summary:
155 // Connect to this function to receive notifications of when the mouse button is pressed down.
156 // event:
157 // mouse Event
158 // tags:
159 // callback
160 },
161 =====*/
162 onMouseMove: dijit._connectOnUseEventHandler,
163 /*=====
164 onMouseMove: function(event){
165 // summary:
166 // Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget.
167 // event:
168 // mouse Event
169 // tags:
170 // callback
171 },
172 =====*/
173 onMouseOut: dijit._connectOnUseEventHandler,
174 /*=====
175 onMouseOut: function(event){
176 // summary:
177 // Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget.
178 // event:
179 // mouse Event
180 // tags:
181 // callback
182 },
183 =====*/
184 onMouseOver: dijit._connectOnUseEventHandler,
185 /*=====
186 onMouseOver: function(event){
187 // summary:
188 // Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget.
189 // event:
190 // mouse Event
191 // tags:
192 // callback
193 },
194 =====*/
195 onMouseLeave: dijit._connectOnUseEventHandler,
196 /*=====
197 onMouseLeave: function(event){
198 // summary:
199 // Connect to this function to receive notifications of when the mouse moves off of this widget.
200 // event:
201 // mouse Event
202 // tags:
203 // callback
204 },
205 =====*/
206 onMouseEnter: dijit._connectOnUseEventHandler,
207 /*=====
208 onMouseEnter: function(event){
209 // summary:
210 // Connect to this function to receive notifications of when the mouse moves onto this widget.
211 // event:
212 // mouse Event
213 // tags:
214 // callback
215 },
216 =====*/
217 onMouseUp: dijit._connectOnUseEventHandler,
218 /*=====
219 onMouseUp: function(event){
220 // summary:
221 // Connect to this function to receive notifications of when the mouse button is released.
222 // event:
223 // mouse Event
224 // tags:
225 // callback
226 },
227 =====*/
228
229 create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){
230 // To avoid double-connects, remove entries from _deferredConnects
231 // that have been setup manually by a subclass (ex, by dojoAttachEvent).
232 // If a subclass has redefined a callback (ex: onClick) then assume it's being
233 // connected to manually.
234 this._deferredConnects = dojo.clone(this._deferredConnects);
235 for(var attr in this.attributeMap){
236 delete this._deferredConnects[attr]; // can't be in both attributeMap and _deferredConnects
237 }
238 for(attr in this._deferredConnects){
239 if(this[attr] !== dijit._connectOnUseEventHandler){
240 delete this._deferredConnects[attr]; // redefined, probably dojoAttachEvent exists
241 }
242 }
243
244 this.inherited(arguments);
245
246 if(this.domNode){
247 // If the developer has specified a handler as a widget parameter
248 // (ex: new Button({onClick: ...})
249 // then naturally need to connect from DOM node to that handler immediately,
250 for(attr in this.params){
251 this._onConnect(attr);
252 }
253 }
254 },
255
256 _onConnect: function(/*String*/ event){
257 // summary:
258 // Called when someone connects to one of my handlers.
259 // "Turn on" that handler if it isn't active yet.
260 //
261 // This is also called for every single initialization parameter
262 // so need to do nothing for parameters like "id".
263 // tags:
264 // private
265 if(event in this._deferredConnects){
266 var mapNode = this[this._deferredConnects[event] || 'domNode'];
267 this.connect(mapNode, event.toLowerCase(), event);
268 delete this._deferredConnects[event];
269 }
270 },
271
272 ////////////////// FOCUS RELATED ///////////////////
273 // _onFocus() and _onBlur() are called by the focus manager
274
275 // focused: [readonly] Boolean
276 // This widget or a widget it contains has focus, or is "active" because
277 // it was recently clicked.
278 focused: false,
279
280 isFocusable: function(){
281 // summary:
282 // Return true if this widget can currently be focused
283 // and false if not
284 return this.focus && (dojo.style(this.domNode, "display") != "none");
285 },
286
287 onFocus: function(){
288 // summary:
289 // Called when the widget becomes "active" because
290 // it or a widget inside of it either has focus, or has recently
291 // been clicked.
292 // tags:
293 // callback
294 },
295
296 onBlur: function(){
297 // summary:
298 // Called when the widget stops being "active" because
299 // focus moved to something outside of it, or the user
300 // clicked somewhere outside of it, or the widget was
301 // hidden.
302 // tags:
303 // callback
304 },
305
306 _onFocus: function(e){
307 // summary:
308 // This is where widgets do processing for when they are active,
309 // such as changing CSS classes. See onFocus() for more details.
310 // tags:
311 // protected
312 this.onFocus();
313 },
314
315 _onBlur: function(){
316 // summary:
317 // This is where widgets do processing for when they stop being active,
318 // such as changing CSS classes. See onBlur() for more details.
319 // tags:
320 // protected
321 this.onBlur();
322 },
323
324 ////////////////// DEPRECATED METHODS ///////////////////
325
326 setAttribute: function(/*String*/ attr, /*anything*/ value){
327 // summary:
328 // Deprecated. Use set() instead.
329 // tags:
330 // deprecated
331 dojo.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0");
332 this.set(attr, value);
333 },
334
335 attr: function(/*String|Object*/name, /*Object?*/value){
336 // summary:
337 // Set or get properties on a widget instance.
338 // name:
339 // The property to get or set. If an object is passed here and not
340 // a string, its keys are used as names of attributes to be set
341 // and the value of the object as values to set in the widget.
342 // value:
343 // Optional. If provided, attr() operates as a setter. If omitted,
344 // the current value of the named property is returned.
345 // description:
346 // This method is deprecated, use get() or set() directly.
347
348 // Print deprecation warning but only once per calling function
349 if(dojo.config.isDebug){
350 var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}),
351 caller = (arguments.callee.caller || "unknown caller").toString();
352 if(!alreadyCalledHash[caller]){
353 dojo.deprecated(this.declaredClass + "::attr() is deprecated. Use get() or set() instead, called from " +
354 caller, "", "2.0");
355 alreadyCalledHash[caller] = true;
356 }
357 }
358
359 var args = arguments.length;
360 if(args >= 2 || typeof name === "object"){ // setter
361 return this.set.apply(this, arguments);
362 }else{ // getter
363 return this.get(name);
364 }
365 },
366
367 ////////////////// ONDIJITCLICK SUPPORT ///////////////////
368
369 // nodesWithKeyClick: [private] String[]
370 // List of nodes that correctly handle click events via native browser support,
371 // and don't need dijit's help
372 nodesWithKeyClick: ["input", "button"],
373
374 connect: function(
375 /*Object|null*/ obj,
376 /*String|Function*/ event,
377 /*String|Function*/ method){
378 // summary:
379 // Connects specified obj/event to specified method of this object
380 // and registers for disconnect() on widget destroy.
381 // description:
382 // Provide widget-specific analog to dojo.connect, except with the
383 // implicit use of this widget as the target object.
384 // This version of connect also provides a special "ondijitclick"
385 // event which triggers on a click or space or enter keyup.
386 // Events connected with `this.connect` are disconnected upon
387 // destruction.
388 // returns:
389 // A handle that can be passed to `disconnect` in order to disconnect before
390 // the widget is destroyed.
391 // example:
392 // | var btn = new dijit.form.Button();
393 // | // when foo.bar() is called, call the listener we're going to
394 // | // provide in the scope of btn
395 // | btn.connect(foo, "bar", function(){
396 // | console.debug(this.toString());
397 // | });
398 // tags:
399 // protected
400
401 var d = dojo,
402 dc = d._connect,
403 handles = this.inherited(arguments, [obj, event == "ondijitclick" ? "onclick" : event, method]);
404
405 if(event == "ondijitclick"){
406 // add key based click activation for unsupported nodes.
407 // do all processing onkey up to prevent spurious clicks
408 // for details see comments at top of this file where _lastKeyDownNode is defined
409 if(d.indexOf(this.nodesWithKeyClick, obj.nodeName.toLowerCase()) == -1){ // is NOT input or button
410 var m = d.hitch(this, method);
411 handles.push(
412 dc(obj, "onkeydown", this, function(e){
413 //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
414 if((e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
415 !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
416 // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
417 dijit._lastKeyDownNode = e.target;
418
419 // Stop event to prevent scrolling on space key in IE.
420 // But don't do this for _HasDropDown because it surpresses the onkeypress
421 // event needed to open the drop down when the user presses the SPACE key.
422 if(!("openDropDown" in this && obj == this._buttonNode)){
423 e.preventDefault();
424 }
425 }
426 }),
427 dc(obj, "onkeyup", this, function(e){
428 //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
429 if( (e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
430 e.target == dijit._lastKeyDownNode && // === breaks greasemonkey
431 !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
432 //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
433 dijit._lastKeyDownNode = null;
434 return m(e);
435 }
436 })
437 );
438 }
439 }
440
441 return handles; // _Widget.Handle
442 },
443
444 ////////////////// MISCELLANEOUS METHODS ///////////////////
445
446 _onShow: function(){
447 // summary:
448 // Internal method called when this widget is made visible.
449 // See `onShow` for details.
450 this.onShow();
451 },
452
453 onShow: function(){
454 // summary:
455 // Called when this widget becomes the selected pane in a
456 // `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
457 // `dijit.layout.AccordionContainer`, etc.
458 //
459 // Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
460 // tags:
461 // callback
462 },
463
464 onHide: function(){
465 // summary:
466 // Called when another widget becomes the selected pane in a
467 // `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
468 // `dijit.layout.AccordionContainer`, etc.
469 //
470 // Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
471 // tags:
472 // callback
473 },
474
475 onClose: function(){
476 // summary:
477 // Called when this widget is being displayed as a popup (ex: a Calendar popped
478 // up from a DateTextBox), and it is hidden.
479 // This is called from the dijit.popup code, and should not be called directly.
480 //
481 // Also used as a parameter for children of `dijit.layout.StackContainer` or subclasses.
482 // Callback if a user tries to close the child. Child will be closed if this function returns true.
483 // tags:
484 // extension
485
486 return true; // Boolean
487 }
2f01fe57 488});
81bea17a 489
2f01fe57 490})();
81bea17a 491
2f01fe57 492}