source: Dev/trunk/src/client/dojox/layout/ExpandoPane.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 8.5 KB
Line 
1define([
2        "dojo/_base/kernel",
3        "dojo/_base/lang",
4        "dojo/_base/declare",
5        "dojo/_base/array",
6        "dojo/_base/connect",
7        "dojo/_base/event",
8        "dojo/_base/fx",
9        "dojo/dom-style",
10        "dojo/dom-class",
11        "dojo/dom-geometry",
12        "dojo/text!./resources/ExpandoPane.html",
13        "dijit/layout/ContentPane",
14        "dijit/_TemplatedMixin",
15        "dijit/_Contained",
16        "dijit/_Container"
17], function(kernel,lang,declare,arrayUtil,connectUtil,eventUtil,baseFx,domStyle,domClass,domGeom,
18                template,ContentPane,TemplatedMixin,Contained,Container) {
19kernel.experimental("dojox.layout.ExpandoPane"); // just to show it can be done?
20
21return declare("dojox.layout.ExpandoPane", [ContentPane, TemplatedMixin, Contained, Container],{
22        // summary:
23        //              An experimental collapsing-pane for dijit.layout.BorderContainer
24        // description:
25        //              Works just like a ContentPane inside of a borderContainer. Will expand/collapse on
26        //              command, and supports having Layout Children as direct descendants
27
28        //maxHeight: "",
29        //maxWidth: "",
30        //splitter: false,
31        attributeMap: lang.delegate(ContentPane.prototype.attributeMap, {
32                title: { node: "titleNode", type: "innerHTML" }
33        }),
34       
35        templateString: template,
36
37        // easeOut: String|Function
38        //              easing function used to hide pane
39        easeOut: "dojo._DefaultEasing", // FIXME: This won't work with globalless AMD
40       
41        // easeIn: String|Function
42        //              easing function use to show pane
43        easeIn: "dojo._DefaultEasing", // FIXME: This won't work with globalless AMD
44       
45        // duration: Integer
46        //              duration to run show/hide animations
47        duration: 420,
48
49        // startExpanded: Boolean
50        //              Does this widget start in an open (true) or closed (false) state
51        startExpanded: true,
52
53        // previewOpacity: Float
54        //              A value from 0 .. 1 indicating the opacity to use on the container
55        //              when only showing a preview
56        previewOpacity: 0.75,
57       
58        // previewOnDblClick: Boolean
59        //              If true, will override the default behavior of a double-click calling a full toggle.
60        //              If false, a double-click will cause the preview to popup
61        previewOnDblClick: false,
62
63        // tabIndex: String
64        //              Order fields are traversed when user hits the tab key
65        tabIndex: "0",
66        _setTabIndexAttr: "iconNode",
67
68        baseClass: "dijitExpandoPane",
69
70        postCreate: function(){
71                this.inherited(arguments);
72                this._animConnects = [];
73
74                this._isHorizontal = true;
75               
76                if(lang.isString(this.easeOut)){
77                        this.easeOut = lang.getObject(this.easeOut);
78                }
79                if(lang.isString(this.easeIn)){
80                        this.easeIn = lang.getObject(this.easeIn);
81                }
82       
83                var thisClass = "", rtl = !this.isLeftToRight();
84                if(this.region){
85                        switch(this.region){
86                                case "trailing" :
87                                case "right" :
88                                        thisClass = rtl ? "Left" : "Right";
89                                        this._needsPosition = "left";
90                                        break;
91                                case "leading" :
92                                case "left" :
93                                        thisClass = rtl ? "Right" : "Left";
94                                        break;
95                                case "top" :
96                                        thisClass = "Top";
97                                        break;
98                                case "bottom" :
99                                        this._needsPosition = "top";
100                                        thisClass = "Bottom";
101                                        break;
102                        }
103                        domClass.add(this.domNode, "dojoxExpando" + thisClass);
104                        domClass.add(this.iconNode, "dojoxExpandoIcon" + thisClass);
105                        this._isHorizontal = /top|bottom/.test(this.region);
106                }
107                domStyle.set(this.domNode, {
108                        overflow: "hidden",
109                        padding:0
110                });
111               
112                this.connect(this.domNode, "ondblclick", this.previewOnDblClick ? "preview" : "toggle");
113               
114                this.iconNode.setAttribute("aria-controls", this.id);
115               
116                if(this.previewOnDblClick){
117                        this.connect(this.getParent(), "_layoutChildren", lang.hitch(this, function(){
118                                this._isonlypreview = false;
119                        }));
120                }
121               
122        },
123       
124        _startupSizes: function(){
125               
126                this._container = this.getParent();
127                this._closedSize = this._titleHeight = domGeom.getMarginBox(this.titleWrapper).h;
128               
129                if(this.splitter){
130                        // find our splitter and tie into it's drag logic
131                        var myid = this.id;
132                        arrayUtil.forEach(dijit.registry.toArray(), function(w){
133                                if(w && w.child && w.child.id == myid){
134                                        this.connect(w,"_stopDrag","_afterResize");
135                                }
136                        }, this);
137                }
138               
139                this._currentSize = domGeom.getContentBox(this.domNode);        // TODO: can compute this from passed in value to resize(), see _LayoutWidget for example
140                this._showSize = this._currentSize[(this._isHorizontal ? "h" : "w")];
141                this._setupAnims();
142
143                if(this.startExpanded){
144                        this._showing = true;
145                }else{
146                        this._showing = false;
147                        this._hideWrapper();
148                        this._hideAnim.gotoPercent(99,true);
149                }
150               
151                this.domNode.setAttribute("aria-expanded", this._showing);
152                this._hasSizes = true;
153        },
154       
155        _afterResize: function(e){
156                var tmp = this._currentSize;                                            // the old size
157                this._currentSize = domGeom.getMarginBox(this.domNode); // the new size
158                var n = this._currentSize[(this._isHorizontal ? "h" : "w")];
159                if(n > this._titleHeight){
160                        if(!this._showing){
161                                this._showing = !this._showing;
162                                this._showEnd();
163                        }
164                        this._showSize = n;
165                        this._setupAnims();
166                }else{
167                        this._showSize = tmp[(this._isHorizontal ? "h" : "w")];
168                        this._showing = false;
169                        this._hideWrapper();
170                        this._hideAnim.gotoPercent(89,true);
171                }
172               
173        },
174       
175        _setupAnims: function(){
176                // summary:
177                //              Create the show and hide animations
178                arrayUtil.forEach(this._animConnects, connectUtil.disconnect);
179               
180                var _common = {
181                                node:this.domNode,
182                                duration:this.duration
183                        },
184                        isHorizontal = this._isHorizontal,
185                        showProps = {},
186                        showSize = this._showSize,
187                        hideSize = this._closedSize,
188                        hideProps = {},
189                        dimension = isHorizontal ? "height" : "width",
190                        also = this._needsPosition
191                ;
192
193                showProps[dimension] = {
194                        end: showSize
195                };
196                hideProps[dimension] = {
197                        end: hideSize
198                };
199               
200                if(also){
201                        showProps[also] = {
202                                end: function(n){
203                                        var c = parseInt(n.style[also], 10);
204                                        return c - showSize + hideSize;
205                                }
206                        }
207                        hideProps[also] = {
208                                end: function(n){
209                                        var c = parseInt(n.style[also], 10);
210                                        return c + showSize - hideSize;
211                                }
212                        }
213                }
214               
215                this._showAnim = baseFx.animateProperty(lang.mixin(_common,{
216                        easing:this.easeIn,
217                        properties: showProps
218                }));
219                this._hideAnim = baseFx.animateProperty(lang.mixin(_common,{
220                        easing:this.easeOut,
221                        properties: hideProps
222                }));
223
224                this._animConnects = [
225                        connectUtil.connect(this._showAnim, "onEnd", this, "_showEnd"),
226                        connectUtil.connect(this._hideAnim, "onEnd", this, "_hideEnd")
227                ];
228        },
229       
230        preview: function(){
231                // summary:
232                //              Expand this pane in preview mode (does not affect surrounding layout)
233
234                if(!this._showing){
235                        this._isonlypreview = !this._isonlypreview;
236                }
237                this.toggle();
238        },
239
240        toggle: function(){
241                // summary:
242                //              Toggle this pane's visibility
243                if(this._showing){
244                        this._hideWrapper();
245                        this._showAnim && this._showAnim.stop();
246                        this._hideAnim.play();
247                }else{
248                        this._hideAnim && this._hideAnim.stop();
249                        this._showAnim.play();
250                }
251                this._showing = !this._showing;
252                this.domNode.setAttribute("aria-expanded", this._showing);
253        },
254       
255        _hideWrapper: function(){
256                // summary:
257                //              Set the Expando state to "closed"
258                domClass.add(this.domNode, "dojoxExpandoClosed");
259               
260                domStyle.set(this.cwrapper,{
261                        visibility: "hidden",
262                        opacity: "0",
263                        overflow: "hidden"
264                });
265        },
266       
267        _showEnd: function(){
268                // summary:
269                //              Common animation onEnd code - "unclose"
270                domStyle.set(this.cwrapper, {
271                        opacity: 0,
272                        visibility:"visible"
273                });
274                baseFx.anim(this.cwrapper, {
275                        opacity: this._isonlypreview ? this.previewOpacity : 1
276                }, 227);
277                domClass.remove(this.domNode, "dojoxExpandoClosed");
278                if(!this._isonlypreview){
279                        setTimeout(lang.hitch(this._container, "layout"), 15);
280                }else{
281                        this._previewShowing = true;
282                        this.resize();
283                }
284        },
285       
286        _hideEnd: function(){
287                // summary:
288                //              Callback for the hide animation - "close"
289
290                // every time we hide, reset the "only preview" state
291                if(!this._isonlypreview){
292                        setTimeout(lang.hitch(this._container, "layout"), 25);
293                }else{
294                        this._previewShowing = false;
295                }
296                this._isonlypreview = false;
297               
298        },
299       
300        resize: function(/*Object?*/newSize){
301                // summary:
302                //              we aren't a layout widget, but need to act like one.
303                // newSize: Object
304                //              The size object to resize to
305
306                if(!this._hasSizes){ this._startupSizes(newSize); }
307               
308                // compute size of container (ie, size left over after title bar)
309                var currentSize = domGeom.getMarginBox(this.domNode);
310                this._contentBox = {
311                        w: newSize && "w" in newSize ? newSize.w : currentSize.w,
312                        h: (newSize && "h" in newSize ? newSize.h : currentSize.h) - this._titleHeight
313                };
314                domStyle.set(this.containerNode, "height", this._contentBox.h + "px");
315
316                if(newSize){
317                        domGeom.setMarginBox(this.domNode, newSize);
318                }
319
320                this._layoutChildren();
321                this._setupAnims();
322        },
323       
324        _trap: function(/*Event*/ e){
325                // summary:
326                //              Trap stray events
327                eventUtil.stop(e);
328        }
329});
330});
Note: See TracBrowser for help on using the repository browser.