~clinton-collins/familyproject/trunk

« back to all changes in this revision

Viewing changes to ZendFramework/externals/dojo/dijit/form/Button.js

  • Committer: Clinton Collins
  • Date: 2009-06-26 19:54:58 UTC
  • Revision ID: clinton.collins@gmail.com-20090626195458-5ebba0qcvo15xlpy
Initial Import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
dojo.provide("dijit.form.Button");
 
2
 
 
3
dojo.require("dijit.form._FormWidget");
 
4
dojo.require("dijit._Container");
 
5
 
 
6
dojo.declare("dijit.form.Button",
 
7
        dijit.form._FormWidget,
 
8
        {
 
9
        // summary:
 
10
        //              Basically the same thing as a normal HTML button, but with special styling.
 
11
        // description:
 
12
        //              Buttons can display a label, an icon, or both.
 
13
        //              A label should always be specified (through innerHTML) or the label
 
14
        //              attribute.  It can be hidden via showLabel=false.
 
15
        // example:
 
16
        // |    <button dojoType="dijit.form.Button" onClick="...">Hello world</button>
 
17
        // 
 
18
        // example:
 
19
        // |    var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
 
20
        // |    dojo.body().appendChild(button1.domNode);
 
21
 
 
22
        // label: HTML String
 
23
        //              Text to display in button.
 
24
        //              If the label is hidden (showLabel=false) then and no title has
 
25
        //              been specified, then label is also set as title attribute of icon.
 
26
        label: "",
 
27
 
 
28
        // showLabel: Boolean
 
29
        //              Set this to true to hide the label text and display only the icon.
 
30
        //              (If showLabel=false then iconClass must be specified.)
 
31
        //              Especially useful for toolbars.  
 
32
        //              If showLabel=true, the label will become the title (a.k.a. tooltip/hint) of the icon.
 
33
        //
 
34
        //              The exception case is for computers in high-contrast mode, where the label
 
35
        //              will still be displayed, since the icon doesn't appear.
 
36
        showLabel: true,
 
37
 
 
38
        // iconClass: String
 
39
        //              Class to apply to div in button to make it display an icon
 
40
        iconClass: "",
 
41
 
 
42
        // type: String
 
43
        //              Defines the type of button.  "button", "submit", or "reset".
 
44
        type: "button",
 
45
 
 
46
        baseClass: "dijitButton",
 
47
 
 
48
        templatePath: dojo.moduleUrl("dijit.form", "templates/Button.html"),
 
49
 
 
50
        attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
 
51
                label: { node: "containerNode", type: "innerHTML" },
 
52
                iconClass: { node: "iconNode", type: "class" }
 
53
        }),
 
54
                
 
55
 
 
56
        _onClick: function(/*Event*/ e){
 
57
                // summary:
 
58
                //              Internal function to handle click actions
 
59
                if(this.disabled || this.readOnly){
 
60
                        return false;
 
61
                }
 
62
                this._clicked(); // widget click actions
 
63
                return this.onClick(e); // user click actions
 
64
        },
 
65
 
 
66
        _onButtonClick: function(/*Event*/ e){
 
67
                // summary:
 
68
                //              Handler when the user activates the button portion.
 
69
                //              If is activated via a keystroke, stop the event unless is submit or reset.
 
70
                if(e.type!='click' && !(this.type=="submit" || this.type=="reset")){
 
71
                        dojo.stopEvent(e);
 
72
                }
 
73
                if(this._onClick(e) === false){ // returning nothing is same as true
 
74
                        e.preventDefault(); // needed for checkbox
 
75
                }else if(this.type=="submit" && !this.focusNode.form){ // see if a nonform widget needs to be signalled
 
76
                        for(var node=this.domNode; node.parentNode/*#5935*/; node=node.parentNode){
 
77
                                var widget=dijit.byNode(node);
 
78
                                if(widget && typeof widget._onSubmit == "function"){
 
79
                                        widget._onSubmit(e);
 
80
                                        break;
 
81
                                }
 
82
                        }
 
83
                }
 
84
        },
 
85
 
 
86
        _setValueAttr: function(/*String*/ value){
 
87
                // Verify that value cannot be set for BUTTON elements.
 
88
                var attr = this.attributeMap.value || '';
 
89
                if(this[attr.node||attr||'domNode'].tagName == 'BUTTON'){
 
90
                        // On IE, setting value actually overrides innerHTML, so disallow for everyone for consistency
 
91
                        if(value != this.value){
 
92
                                console.debug('Cannot change the value attribute on a Button widget.');
 
93
                        }
 
94
                }
 
95
        },
 
96
 
 
97
        _fillContent: function(/*DomNode*/ source){
 
98
                // Overrides _Templated._fillcContent().
 
99
                // If button label is specified as srcNodeRef.innerHTML rather than
 
100
                // this.params.label, handle it here.
 
101
                if(source && !("label" in this.params)){
 
102
                        this.attr('label', source.innerHTML);
 
103
                }
 
104
        },
 
105
 
 
106
        postCreate: function(){
 
107
                if (this.showLabel == false){
 
108
                        dojo.addClass(this.containerNode,"dijitDisplayNone");
 
109
                }
 
110
                dojo.setSelectable(this.focusNode, false);
 
111
                this.inherited(arguments);
 
112
        },
 
113
 
 
114
        onClick: function(/*Event*/ e){
 
115
                // summary:
 
116
                //              Callback for when button is clicked.
 
117
                //              If type="submit", return true to perform submit, or false to cancel it.
 
118
                // type:
 
119
                //              callback
 
120
                return true;            // Boolean
 
121
        },
 
122
 
 
123
        _clicked: function(/*Event*/ e){
 
124
                // summary:
 
125
                //              Internal overridable function for when the button is clicked
 
126
        },
 
127
 
 
128
        setLabel: function(/*String*/ content){
 
129
                // summary:
 
130
                //              Deprecated.  Use attr('label', ...) instead.
 
131
                dojo.deprecated("dijit.form.Button.setLabel() is deprecated.  Use attr('label', ...) instead.", "", "2.0");
 
132
                this.attr("label", content);
 
133
        },
 
134
        _setLabelAttr: function(/*String*/ content){
 
135
                // summary:
 
136
                //              Hook for attr('label', ...) to work.
 
137
                // description:
 
138
                //              Set the label (text) of the button; takes an HTML string.
 
139
                this.containerNode.innerHTML = this.label = content;
 
140
                this._layoutHack();
 
141
                if (this.showLabel == false && !this.params.title){
 
142
                        this.titleNode.title = dojo.trim(this.containerNode.innerText || this.containerNode.textContent || '');
 
143
                }
 
144
        }               
 
145
});
 
146
 
 
147
 
 
148
dojo.declare("dijit.form.DropDownButton", [dijit.form.Button, dijit._Container], {
 
149
        // summary:
 
150
        //              A button with a drop down
 
151
        //
 
152
        // example:
 
153
        // |    <button dojoType="dijit.form.DropDownButton" label="Hello world">
 
154
        // |            <div dojotype="dijit.Menu">...</div>
 
155
        // |    </button>
 
156
        //
 
157
        // example:
 
158
        // |    var button1 = new dijit.form.DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) });
 
159
        // |    dojo.body().appendChild(button1);
 
160
        //      
 
161
        
 
162
        baseClass : "dijitDropDownButton",
 
163
 
 
164
        templatePath: dojo.moduleUrl("dijit.form" , "templates/DropDownButton.html"),
 
165
 
 
166
        _fillContent: function(){
 
167
                // Overrides Button._fillContent().
 
168
                //
 
169
                // My inner HTML contains both the button contents and a drop down widget, like
 
170
                // <DropDownButton>  <span>push me</span>  <Menu> ... </Menu> </DropDownButton>
 
171
                // The first node is assumed to be the button content. The widget is the popup.
 
172
 
 
173
                if(this.srcNodeRef){ // programatically created buttons might not define srcNodeRef
 
174
                        //FIXME: figure out how to filter out the widget and use all remaining nodes as button
 
175
                        //      content, not just nodes[0]
 
176
                        var nodes = dojo.query("*", this.srcNodeRef);
 
177
                        dijit.form.DropDownButton.superclass._fillContent.call(this, nodes[0]);
 
178
 
 
179
                        // save pointer to srcNode so we can grab the drop down widget after it's instantiated
 
180
                        this.dropDownContainer = this.srcNodeRef;
 
181
                }
 
182
        },
 
183
 
 
184
        startup: function(){
 
185
                if(this._started){ return; }
 
186
 
 
187
                // the child widget from srcNodeRef is the dropdown widget.  Insert it in the page DOM,
 
188
                // make it invisible, and store a reference to pass to the popup code.
 
189
                if(!this.dropDown){
 
190
                        var dropDownNode = dojo.query("[widgetId]", this.dropDownContainer)[0];
 
191
                        this.dropDown = dijit.byNode(dropDownNode);
 
192
                        delete this.dropDownContainer;
 
193
                }
 
194
                dijit.popup.prepare(this.dropDown.domNode);
 
195
 
 
196
                this.inherited(arguments);
 
197
        },
 
198
 
 
199
        destroyDescendants: function(){
 
200
                if(this.dropDown){
 
201
                        this.dropDown.destroyRecursive();
 
202
                        delete this.dropDown;
 
203
                }
 
204
                this.inherited(arguments);
 
205
        },
 
206
 
 
207
        _onArrowClick: function(/*Event*/ e){
 
208
                // summary:
 
209
                //              Handler for when the user mouse clicks on menu popup node
 
210
                if(this.disabled || this.readOnly){ return; }
 
211
                this._toggleDropDown();
 
212
        },
 
213
 
 
214
        _onDropDownClick: function(/*Event*/ e){
 
215
                // on Firefox 2 on the Mac it is possible to fire onclick
 
216
                // by pressing enter down on a second element and transferring
 
217
                // focus to the DropDownButton;
 
218
                // we want to prevent opening our menu in this situation
 
219
                // and only do so if we have seen a keydown on this button;
 
220
                // e.detail != 0 means that we were fired by mouse
 
221
                var isMacFFlessThan3 = dojo.isFF && dojo.isFF < 3
 
222
                        && navigator.appVersion.indexOf("Macintosh") != -1;
 
223
                if(!isMacFFlessThan3 || e.detail != 0 || this._seenKeydown){
 
224
                        this._onArrowClick(e);
 
225
                }
 
226
                this._seenKeydown = false;
 
227
        },
 
228
 
 
229
        _onDropDownKeydown: function(/*Event*/ e){
 
230
                this._seenKeydown = true;
 
231
        },
 
232
 
 
233
        _onDropDownBlur: function(/*Event*/ e){
 
234
                this._seenKeydown = false;
 
235
        },
 
236
 
 
237
        _onKey: function(/*Event*/ e){
 
238
                // summary:
 
239
                //              Handler when the user presses a key on drop down widget
 
240
                if(this.disabled || this.readOnly){ return; }
 
241
                if(e.charOrCode == dojo.keys.DOWN_ARROW){
 
242
                        if(!this.dropDown || this.dropDown.domNode.style.visibility=="hidden"){
 
243
                                dojo.stopEvent(e);
 
244
                                this._toggleDropDown();
 
245
                        }
 
246
                }
 
247
        },
 
248
 
 
249
        _onBlur: function(){
 
250
                // summary:
 
251
                //              Called magically when focus has shifted away from this widget and it's dropdown
 
252
                this._closeDropDown();
 
253
                // don't focus on button.  the user has explicitly focused on something else.
 
254
                this.inherited(arguments);
 
255
        },
 
256
 
 
257
        _toggleDropDown: function(){
 
258
                // summary:
 
259
                //              Toggle the drop-down widget; if it is up, close it; if not, open it.
 
260
                if(this.disabled || this.readOnly){ return; }
 
261
                dijit.focus(this.popupStateNode);
 
262
                var dropDown = this.dropDown;
 
263
                if(!dropDown){ return; }
 
264
                if(!this._opened){
 
265
                        // If there's an href, then load that first, so we don't get a flicker
 
266
                        if(dropDown.href && !dropDown.isLoaded){
 
267
                                var self = this;
 
268
                                var handler = dojo.connect(dropDown, "onLoad", function(){
 
269
                                        dojo.disconnect(handler);
 
270
                                        self._openDropDown();
 
271
                                });
 
272
                                dropDown.refresh();
 
273
                                return;
 
274
                        }else{
 
275
                                this._openDropDown();
 
276
                        }
 
277
                }else{
 
278
                        this._closeDropDown();
 
279
                }
 
280
        },
 
281
 
 
282
        _openDropDown: function(){
 
283
                var dropDown = this.dropDown;
 
284
                var oldWidth=dropDown.domNode.style.width;
 
285
                var self = this;
 
286
 
 
287
                dijit.popup.open({
 
288
                        parent: this,
 
289
                        popup: dropDown,
 
290
                        around: this.domNode,
 
291
                        orient:
 
292
                                // TODO: add user-defined positioning option, like in Tooltip.js
 
293
                                this.isLeftToRight() ? {'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'}
 
294
                                : {'BR':'TR', 'BL':'TL', 'TR':'BR', 'TL':'BL'},
 
295
                        onExecute: function(){
 
296
                                self._closeDropDown(true);
 
297
                        },
 
298
                        onCancel: function(){
 
299
                                self._closeDropDown(true);
 
300
                        },
 
301
                        onClose: function(){
 
302
                                dropDown.domNode.style.width = oldWidth;
 
303
                                self.popupStateNode.removeAttribute("popupActive");
 
304
                                self._opened = false;
 
305
                        }
 
306
                });
 
307
                if(this.domNode.offsetWidth > dropDown.domNode.offsetWidth){
 
308
                        var adjustNode = null;
 
309
                        if(!this.isLeftToRight()){
 
310
                                adjustNode = dropDown.domNode.parentNode;
 
311
                                var oldRight = adjustNode.offsetLeft + adjustNode.offsetWidth;
 
312
                        }
 
313
                        // make menu at least as wide as the button
 
314
                        dojo.marginBox(dropDown.domNode, {w: this.domNode.offsetWidth});
 
315
                        if(adjustNode){
 
316
                                adjustNode.style.left = oldRight - this.domNode.offsetWidth + "px";
 
317
                        }
 
318
                }
 
319
                this.popupStateNode.setAttribute("popupActive", "true");
 
320
                this._opened=true;
 
321
                if(dropDown.focus){
 
322
                        dropDown.focus();
 
323
                }
 
324
                // TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown
 
325
        },
 
326
        
 
327
        _closeDropDown: function(/*Boolean*/ focus){
 
328
                if(this._opened){
 
329
                        dijit.popup.close(this.dropDown);
 
330
                        if(focus){ this.focus(); }
 
331
                        this._opened = false;                   
 
332
                }
 
333
        }
 
334
});
 
335
 
 
336
dojo.declare("dijit.form.ComboButton", dijit.form.DropDownButton, {
 
337
        // summary:
 
338
        //              A combination button and drop-down button.
 
339
        //              Users can click one side to "press" the button, or click an arrow
 
340
        //              icon to display the drop down.
 
341
        //
 
342
        // example:
 
343
        // |    <button dojoType="dijit.form.ComboButton" onClick="...">
 
344
        // |            <span>Hello world</span>
 
345
        // |            <div dojoType="dijit.Menu">...</div>
 
346
        // |    </button>
 
347
        //
 
348
        // example:
 
349
        // |    var button1 = new dijit.form.ComboButton({label: "hello world", onClick: foo, dropDown: "myMenu"});
 
350
        // |    dojo.body().appendChild(button1.domNode);
 
351
        // 
 
352
 
 
353
        templatePath: dojo.moduleUrl("dijit.form", "templates/ComboButton.html"),
 
354
 
 
355
        attributeMap: dojo.mixin(dojo.clone(dijit.form.Button.prototype.attributeMap), {
 
356
                id:"",
 
357
                tabIndex: ["focusNode", "titleNode"]
 
358
        }),
 
359
 
 
360
        // optionsTitle: String
 
361
        //              Text that describes the options menu (accessibility)
 
362
        optionsTitle: "",
 
363
 
 
364
        baseClass: "dijitComboButton",
 
365
 
 
366
        _focusedNode: null,
 
367
 
 
368
        postCreate: function(){
 
369
                this.inherited(arguments);
 
370
                this._focalNodes = [this.titleNode, this.popupStateNode];
 
371
                dojo.forEach(this._focalNodes, dojo.hitch(this, function(node){
 
372
                        if(dojo.isIE){
 
373
                                this.connect(node, "onactivate", this._onNodeFocus);
 
374
                                this.connect(node, "ondeactivate", this._onNodeBlur);
 
375
                        }else{
 
376
                                this.connect(node, "onfocus", this._onNodeFocus);
 
377
                                this.connect(node, "onblur", this._onNodeBlur);
 
378
                        }
 
379
                }));
 
380
        },
 
381
 
 
382
        focusFocalNode: function(node){
 
383
                // summary:
 
384
                //              Focus the focal node node.
 
385
                // description:
 
386
                //              Called by _KeyNavContainer for (when example) this button is in a toolbar.
 
387
                // tags:
 
388
                //              protected
 
389
                this._focusedNode = node;
 
390
                dijit.focus(node);
 
391
        },
 
392
 
 
393
        hasNextFocalNode: function(){
 
394
                // summary:
 
395
                //              Returns true if this widget has no node currently
 
396
                //              focused or if there is a node following the focused one.
 
397
                //              False is returned if the last node has focus.
 
398
                // description:
 
399
                //              Called by _KeyNavContainer for (when example) this button is in a toolbar.
 
400
                // tags:
 
401
                //              protected
 
402
                return this._focusedNode !== this.getFocalNodes()[1];
 
403
        },
 
404
 
 
405
        focusNext: function(){
 
406
                // summary:
 
407
                //              Focus the focal node following the current node with focus,
 
408
                //              or the first one if no node currently has focus.
 
409
                // description:
 
410
                //              Called by _KeyNavContainer for (when example) this button is in a toolbar.
 
411
                // tags:
 
412
                //              protected
 
413
                this._focusedNode = this.getFocalNodes()[this._focusedNode ? 1 : 0];
 
414
                dijit.focus(this._focusedNode);
 
415
        },
 
416
 
 
417
        hasPrevFocalNode: function(){
 
418
                // summary:
 
419
                //              Returns true if this widget has no node currently
 
420
                //              focused or if there is a node before the focused one.
 
421
                //              False is returned if the first node has focus.
 
422
                // description:
 
423
                //              Called by _KeyNavContainer for (when example) this button is in a toolbar.
 
424
                // tags:
 
425
                //              protected
 
426
                return this._focusedNode !== this.getFocalNodes()[0];
 
427
        },
 
428
 
 
429
        focusPrev: function(){
 
430
                // summary:
 
431
                //              Focus the focal node before the current node with focus
 
432
                //              or the last one if no node currently has focus.
 
433
                // description:
 
434
                //              Called by _KeyNavContainer for (when example) this button is in a toolbar.
 
435
                // tags:
 
436
                //              protected
 
437
                this._focusedNode = this.getFocalNodes()[this._focusedNode ? 0 : 1];
 
438
                dijit.focus(this._focusedNode);
 
439
        },
 
440
 
 
441
        getFocalNodes: function(){
 
442
                // summary:
 
443
                //              Returns an array of focal nodes for this widget.
 
444
                // description:
 
445
                //              Called by _KeyNavContainer for (when example) this button is in a toolbar.
 
446
                // tags:
 
447
                //              protected
 
448
                return this._focalNodes;
 
449
        },
 
450
 
 
451
        _onNodeFocus: function(evt){
 
452
                this._focusedNode = evt.currentTarget;
 
453
                var fnc = this._focusedNode == this.focusNode ? "dijitDownArrowButtonFocused" : "dijitButtonContentsFocused";
 
454
                dojo.addClass(this._focusedNode, fnc);
 
455
        },
 
456
 
 
457
        _onNodeBlur: function(evt){
 
458
                var fnc = evt.currentTarget == this.focusNode ? "dijitDownArrowButtonFocused" : "dijitButtonContentsFocused";
 
459
                dojo.removeClass(evt.currentTarget, fnc);
 
460
        },
 
461
 
 
462
        _onBlur: function(){
 
463
                this.inherited(arguments);
 
464
                this._focusedNode = null;
 
465
        }
 
466
});
 
467
 
 
468
dojo.declare("dijit.form.ToggleButton", dijit.form.Button, {
 
469
        // summary:
 
470
        //              A button that can be in two states (checked or not).
 
471
        //              Can be base class for things like tabs or checkbox or radio buttons
 
472
 
 
473
        baseClass: "dijitToggleButton",
 
474
 
 
475
        // checked: Boolean
 
476
        //              Corresponds to the native HTML <input> element's attribute.
 
477
        //              In markup, specified as "checked='checked'" or just "checked".
 
478
        //              True if the button is depressed, or the checkbox is checked,
 
479
        //              or the radio button is selected, etc.
 
480
        checked: false,
 
481
 
 
482
        attributeMap: dojo.mixin(dojo.clone(dijit.form.Button.prototype.attributeMap),
 
483
                {checked:"focusNode"}),
 
484
 
 
485
        _clicked: function(/*Event*/ evt){
 
486
                this.attr('checked', !this.checked);
 
487
        },
 
488
 
 
489
        _setCheckedAttr: function(/*Boolean*/ value){
 
490
                this.checked = value;
 
491
                dojo.attr(this.focusNode || this.domNode, "checked", value);
 
492
                dijit.setWaiState(this.focusNode || this.domNode, "pressed", value);
 
493
                this._setStateClass();          
 
494
                this._handleOnChange(value, true);
 
495
        },
 
496
 
 
497
        setChecked: function(/*Boolean*/ checked){
 
498
                // summary:
 
499
                //              Deprecated.   Use attr('checked', true/false) instead.
 
500
                dojo.deprecated("setChecked("+checked+") is deprecated. Use attr('checked',"+checked+") instead.", "", "2.0");
 
501
                this.attr('checked', checked);
 
502
        },
 
503
        
 
504
        reset: function(){
 
505
                // summary:
 
506
                //              Reset the widget's value to what it was at initialization time
 
507
 
 
508
                this._hasBeenBlurred = false;
 
509
 
 
510
                // set checked state to original setting
 
511
                this.attr('checked', this.params.checked || false);
 
512
        }
 
513
});