source: Dev/branches/rest-dojo-ui/client/dojox/layout/RadioGroup.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 8.8 KB
Line 
1define(["dojo/_base/kernel","dojo/_base/declare","dojo/_base/html","dojo/_base/lang","dojo/_base/query",
2                "dijit/_Widget","dijit/_Templated","dijit/_Contained","dijit/layout/StackContainer",
3                "dojo/fx/easing","dojo/_base/fx","dojo/dom-construct","dojo/dom-class"],function(
4        kernel,declare,html,lang,query,Widget,Templated,Contained,StackContainer,easing,baseFx,domConstruct,domClass){
5
6kernel.experimental("dojox.layout.RadioGroup");
7
8//
9//      dojox.layout.RadioGroup - an experimental (probably poorly named) Layout widget extending StackContainer
10//      that accepts ContentPanes as children, and applies aesthetically pleasing responsive transition animations
11//      attached to :hover of the Buttons created.
12//
13//      FIXME: take the Buttons out of the root template, and allow layoutAlign or similar attrib to use a different
14//      template, or build the template dynamically?
15//
16/*=====
17        var StackContainer = dijit.layout.StackContainer,
18                Templated = dijit._Templated,
19                Contained = dijit._Contained,
20                Widget = dijit._Widget;
21=====*/
22
23var RadioGroup = declare("dojox.layout.RadioGroup",[StackContainer,Templated],{
24        // summary: A Container that turns its Layout Children into a single Pane and transitions between states
25        //      onHover of the button
26        //
27
28        // duration: Integer
29        //      used for Fade and Slide RadioGroup's, the duration to run the transition animation. does not affect anything
30        //      in default RadioGroup
31        duration: 750,
32
33        // hasButtons: Boolean
34        //      toggles internal button making on or off
35        hasButtons: false,
36
37        // buttonClass: String
38        //              The full declared className of the Button widget to use for hasButtons
39        buttonClass: "dojox.layout._RadioButton",
40       
41        // templateString: String
42        //      the template for our container
43        templateString: '<div class="dojoxRadioGroup">'
44                        +'      <div dojoAttachPoint="buttonHolder" style="display:none;">'
45                        +'              <table class="dojoxRadioButtons"><tbody><tr class="dojoxRadioButtonRow" dojoAttachPoint="buttonNode"></tr></tbody></table>'
46                        +'      </div>'
47                        +'      <div class="dojoxRadioView" dojoAttachPoint="containerNode"></div>'
48                        +'</div>',
49
50        startup: function(){
51                // summary: scan the container for children, and make "tab buttons" for them
52                this.inherited(arguments);
53                this._children = this.getChildren();
54                this._buttons = this._children.length;
55                this._size = html.coords(this.containerNode);
56                if(this.hasButtons){
57                        html.style(this.buttonHolder, "display", "block");
58                }
59        },
60
61        _setupChild: function(/* dijit._Widget */child){
62                // summary: Creates a hover button for a child node of the RadioGroup
63                html.style(child.domNode, "position", "absolute");
64                if(this.hasButtons){
65                       
66                        var tmp = this.buttonNode.appendChild(domConstruct.create('td'));
67                        var n = domConstruct.create("div", null, tmp),
68                                _Button = lang.getObject(this.buttonClass),
69                                tmpw = new _Button({
70                                        label: child.title,
71                                        page: child
72                                }, n)
73                        ;
74                       
75                        lang.mixin(child, { _radioButton: tmpw });
76                        tmpw.startup();
77                }
78                child.domNode.style.display = "none";
79        },
80       
81        removeChild: function(child){
82                if(this.hasButtons && child._radioButton){
83                        child._radioButton.destroy();
84                        delete child._radioButton;
85                }
86                this.inherited(arguments);
87        },
88       
89        // FIXME: shouldn't have to rewriting these, need to take styling out of _showChild and _hideChild
90        //              and use classes on the domNode in _transition or something similar (in StackContainer)
91        _transition: function(/*dijit._Widget*/ newWidget, /*dijit._Widget*/ oldWidget){
92                // summary: called when StackContainer receives a selectChild call, used to transition the panes.
93                this._showChild(newWidget);
94                if(oldWidget){
95                        this._hideChild(oldWidget);
96                }
97                // Size the new widget, in case this is the first time it's being shown,
98                // or I have been resized since the last time it was shown.
99                // page must be visible for resizing to work
100                if(this.doLayout && newWidget.resize){
101                        newWidget.resize(this._containerContentBox || this._contentBox);
102                }
103        },
104
105        _showChild: function(/*dijit._Widget*/ page){
106                // summary: show the selected child widget
107                var children = this.getChildren();
108                page.isFirstChild = (page == children[0]);
109                page.isLastChild = (page == children[children.length-1]);
110                page.selected = true;
111
112                page.domNode.style.display="";
113
114                if(page._onShow){
115                        page._onShow(); // trigger load in ContentPane
116                }else if(page.onShow){
117                        page.onShow();
118                }
119        },
120
121        _hideChild: function(/*dijit._Widget*/ page){
122                // summary: hide the specified child widget
123                page.selected = false;
124                page.domNode.style.display="none";
125                if(page.onHide){
126                        page.onHide();
127                }
128        }
129
130});
131
132declare("dojox.layout.RadioGroupFade", RadioGroup, {
133        // summary: An extension on a stock RadioGroup, that fades the panes.
134
135        _hideChild: function(page){
136                // summary: hide the specified child widget
137                baseFx.fadeOut({
138                        node:page.domNode,
139                        duration:this.duration,
140                        onEnd: lang.hitch(this,"inherited", arguments, arguments)
141                }).play();
142        },
143
144        _showChild: function(page){
145                // summary: show the specified child widget
146                this.inherited(arguments);
147                html.style(page.domNode, "opacity", 0);
148                baseFx.fadeIn({
149                        node:page.domNode,
150                        duration:this.duration
151                }).play();
152        }
153});
154
155declare("dojox.layout.RadioGroupSlide", RadioGroup, {
156        // summary: A Sliding Radio Group
157        // description:
158        //              An extension on a stock RadioGroup widget, sliding the pane
159        //              into view from being hidden. The entry direction is randomized
160        //              on each view
161        //
162
163        // easing: Function
164        //      A hook to override the default easing of the pane slides.
165        easing: "dojo.fx.easing.backOut",
166
167        // zTop: Integer
168        //              A z-index to apply to the incoming pane
169        zTop: 99,
170       
171        constructor: function(){
172                if(lang.isString(this.easing)){
173                        this.easing = lang.getObject(this.easing);
174                }
175        },
176       
177        _positionChild: function(page){
178                // summary: set the child out of view immediately after being hidden
179
180                // FIXME: is there a real "size" floating around always?
181                if(!this._size){ return; }
182               
183                // there should be a contest: obfuscate this function as best you can.
184                var rA = true, rB = true;
185                switch(page.slideFrom){
186                        case "bottom" : rB = !rB; break;
187                        case "right" :  rA = !rA; rB = !rB; break;
188                        case "top" :    break;
189                        case "left" :   rA = !rA; break;
190                        default:
191                                rA = Math.round(Math.random());
192                                rB = Math.round(Math.random());
193                                break;
194                }
195                var prop = rA ? "top" : "left",
196                        val = (rB ? "-" : "") + (this._size[rA ? "h" : "w" ] + 20) + "px";
197                       
198                html.style(page.domNode, prop, val);
199
200        },
201
202        _showChild: function(page){
203                // summary: Slide in the selected child widget
204               
205                var children = this.getChildren();
206                page.isFirstChild = (page == children[0]);
207                page.isLastChild = (page == children[children.length-1]);
208                page.selected = true;
209
210                html.style(page.domNode,{
211                        zIndex: this.zTop, display:""
212                })
213
214                if(this._anim && this._anim.status()=="playing"){
215                        this._anim.gotoPercent(100,true);
216                }
217               
218                this._anim = baseFx.animateProperty({
219                        node:page.domNode,
220                        properties: {
221                                left: 0,
222                                top: 0
223                        },
224                        duration: this.duration,
225                        easing: this.easing,
226                        onEnd: lang.hitch(page, function(){
227                                if(this.onShow){ this.onShow(); }
228                                if(this._onShow){ this._onShow(); }
229                        }),
230                        beforeBegin: lang.hitch(this, "_positionChild", page)
231                });
232                this._anim.play();
233        },
234
235        _hideChild: function(page){
236                // summary: reset the position of the hidden pane out of sight
237
238                page.selected = false;
239                page.domNode.style.zIndex = this.zTop - 1;
240                if(page.onHide){
241                        page.onHide();
242                }
243
244        }
245       
246});
247
248declare("dojox.layout._RadioButton",[Widget,Templated,Contained],{
249        // summary: The Buttons for a RadioGroup
250        //
251        // description: A private widget used to manipulate the StackContainer (RadioGroup*). Don't create directly.
252        //
253       
254        // label: String
255        //      the Text Label of the button
256        label: "",
257
258        // domNode to tell parent to select
259        page: null,
260
261        templateString: '<div dojoAttachPoint="focusNode" class="dojoxRadioButton"><span dojoAttachPoint="titleNode" class="dojoxRadioButtonLabel">${label}</span></div>',
262       
263        startup: function(){
264                // summary: start listening to mouseOver
265                this.connect(this.domNode, "onmouseenter", "_onMouse");
266        },
267       
268        _onMouse: function(/* Event */e){
269                // summary: set the selected child on hover, and set our hover state class
270                this.getParent().selectChild(this.page);
271                this._clearSelected();
272                domClass.add(this.domNode,"dojoxRadioButtonSelected");
273
274        },
275
276        _clearSelected: function(){
277                // summary: remove hover state class from sibling Buttons. This is easier (and more reliable)
278                //      than setting up an additional connection to onMouseOut
279               
280                // FIXME: this relies on the template being [div][span]node[/span][/div]
281                query(".dojoxRadioButtonSelected", this.domNode.parentNode.parentNode)
282                        .removeClass("dojoxRadioButtonSelected")
283                ;
284        }
285       
286});
287
288lang.extend(Widget,{
289        // slideFrom: String
290        //              A parameter needed by RadioGroupSlide only. An optional paramter to force
291        //              the ContentPane to slide in from a set direction. Defaults
292        //              to "random", or specify one of "top", "left", "right", "bottom"
293        //              to slideFrom top, left, right, or bottom.
294        slideFrom: "random"
295})
296});
Note: See TracBrowser for help on using the repository browser.