source: Dev/trunk/src/client/dijit/TitlePane.js @ 493

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

Added Dojo 1.9.3 release.

File size: 8.8 KB
Line 
1define([
2        "dojo/_base/array", // array.forEach
3        "dojo/_base/declare", // declare
4        "dojo/dom", // dom.setSelectable
5        "dojo/dom-attr", // domAttr.set or get domAttr.remove
6        "dojo/dom-class", // domClass.replace
7        "dojo/dom-geometry", // domGeometry.setMarginBox domGeometry.getMarginBox
8        "dojo/fx", // fxUtils.wipeIn fxUtils.wipeOut
9        "dojo/has",
10        "dojo/_base/kernel", // kernel.deprecated
11        "dojo/keys", // keys.DOWN_ARROW keys.ENTER
12        "./_CssStateMixin",
13        "./_TemplatedMixin",
14        "./layout/ContentPane",
15        "dojo/text!./templates/TitlePane.html",
16        "./_base/manager",    // defaultDuration
17        "./a11yclick"   // template uses ondijitclick
18], function(array, declare, dom, domAttr, domClass, domGeometry, fxUtils, has, kernel, keys,
19                        _CssStateMixin, _TemplatedMixin, ContentPane, template, manager){
20
21        // module:
22        //              dijit/TitlePane
23
24        var TitlePane = declare("dijit.TitlePane", [ContentPane, _TemplatedMixin, _CssStateMixin], {
25                // summary:
26                //              A pane with a title on top, that can be expanded or collapsed.
27                //
28                // description:
29                //              An accessible container with a title Heading, and a content
30                //              section that slides open and closed. TitlePane is an extension to
31                //              `dijit/layout/ContentPane`, providing all the useful content-control aspects from it.
32                //
33                // example:
34                //      |       // load a TitlePane from remote file:
35                //      |       var foo = new dijit.TitlePane({ href: "foobar.html", title:"Title" });
36                //      |       foo.startup();
37                //
38                // example:
39                //      |       <!-- markup href example: -->
40                //      |       <div data-dojo-type="dijit/TitlePane" data-dojo-props="href: 'foobar.html', title: 'Title'"></div>
41                //
42                // example:
43                //      |       <!-- markup with inline data -->
44                //      |       <div data-dojo-type="dijit/TitlePane" title="Title">
45                //      |               <p>I am content</p>
46                //      |       </div>
47
48                // title: String
49                //              Title of the pane
50                title: "",
51                _setTitleAttr: { node: "titleNode", type: "innerHTML" }, // override default where title becomes a hover tooltip
52
53                // open: Boolean
54                //              Whether pane is opened or closed.
55                open: true,
56
57                // toggleable: Boolean
58                //              Whether pane can be opened or closed by clicking the title bar.
59                toggleable: true,
60
61                // tabIndex: String
62                //              Tabindex setting for the title (so users can tab to the title then
63                //              use space/enter to open/close the title pane)
64                tabIndex: "0",
65
66                // duration: Integer
67                //              Time in milliseconds to fade in/fade out
68                duration: manager.defaultDuration,
69
70                // baseClass: [protected] String
71                //              The root className to be placed on this widget's domNode.
72                baseClass: "dijitTitlePane",
73
74                templateString: template,
75
76                // doLayout: [protected] Boolean
77                //              Don't change this parameter from the default value.
78                //              This ContentPane parameter doesn't make sense for TitlePane, since TitlePane
79                //              is never a child of a layout container, nor should TitlePane try to control
80                //              the size of an inner widget.
81                doLayout: false,
82
83                // Tooltip is defined in _WidgetBase but we need to handle the mapping to DOM here
84                _setTooltipAttr: {node: "focusNode", type: "attribute", attribute: "title"}, // focusNode spans the entire width, titleNode doesn't
85
86                buildRendering: function(){
87                        this.inherited(arguments);
88                        dom.setSelectable(this.titleNode, false);
89                },
90
91                postCreate: function(){
92                        this.inherited(arguments);
93
94                        // Hover and focus effect on title bar, except for non-toggleable TitlePanes
95                        // This should really be controlled from _setToggleableAttr() but _CssStateMixin
96                        // doesn't provide a way to disconnect a previous _trackMouseState() call
97                        if(this.toggleable){
98                                this._trackMouseState(this.titleBarNode, this.baseClass + "Title");
99                        }
100
101                        // setup open/close animations
102                        var hideNode = this.hideNode, wipeNode = this.wipeNode;
103                        this._wipeIn = fxUtils.wipeIn({
104                                node: wipeNode,
105                                duration: this.duration,
106                                beforeBegin: function(){
107                                        hideNode.style.display = "";
108                                }
109                        });
110                        this._wipeOut = fxUtils.wipeOut({
111                                node: wipeNode,
112                                duration: this.duration,
113                                onEnd: function(){
114                                        hideNode.style.display = "none";
115                                }
116                        });
117                },
118
119                _setOpenAttr: function(/*Boolean*/ open, /*Boolean*/ animate){
120                        // summary:
121                        //              Hook to make set("open", boolean) control the open/closed state of the pane.
122                        // open: Boolean
123                        //              True if you want to open the pane, false if you want to close it.
124
125                        array.forEach([this._wipeIn, this._wipeOut], function(animation){
126                                if(animation && animation.status() == "playing"){
127                                        animation.stop();
128                                }
129                        });
130
131                        if(animate){
132                                var anim = this[open ? "_wipeIn" : "_wipeOut"];
133                                anim.play();
134                        }else{
135                                this.hideNode.style.display = this.wipeNode.style.display = open ? "" : "none";
136                        }
137
138                        // load content (if this is the first time we are opening the TitlePane
139                        // and content is specified as an href, or href was set when hidden)
140                        if(this._started){
141                                if(open){
142                                        this._onShow();
143                                }else{
144                                        this.onHide();
145                                }
146                        }
147
148                        this.containerNode.setAttribute("aria-hidden", open ? "false" : "true");
149                        this.focusNode.setAttribute("aria-pressed", open ? "true" : "false");
150
151                        this._set("open", open);
152
153                        this._setCss();
154                },
155
156                _setToggleableAttr: function(/*Boolean*/ canToggle){
157                        // summary:
158                        //              Hook to make set("toggleable", boolean) work.
159                        // canToggle: Boolean
160                        //              True to allow user to open/close pane by clicking title bar.
161
162                        this.focusNode.setAttribute("role", canToggle ? "button" : "heading");
163                        if(canToggle){
164                                this.focusNode.setAttribute("aria-controls", this.id + "_pane");
165                                this.focusNode.setAttribute("tabIndex", this.tabIndex);
166                                this.focusNode.setAttribute("aria-pressed", this.open);
167                        }else{
168                                domAttr.remove(this.focusNode, "aria-controls");
169                                domAttr.remove(this.focusNode, "tabIndex");
170                                domAttr.remove(this.focusNode, "aria-pressed");
171                        }
172
173                        this._set("toggleable", canToggle);
174
175                        this._setCss();
176                },
177
178                _setContentAttr: function(/*String|DomNode|Nodelist*/ content){
179                        // summary:
180                        //              Hook to make set("content", ...) work.
181                        //              Typically called when an href is loaded.  Our job is to make the animation smooth.
182
183                        if(!this.open || !this._wipeOut || this._wipeOut.status() == "playing"){
184                                // we are currently *closing* the pane (or the pane is closed), so just let that continue
185                                this.inherited(arguments);
186                        }else{
187                                if(this._wipeIn && this._wipeIn.status() == "playing"){
188                                        this._wipeIn.stop();
189                                }
190
191                                // freeze container at current height so that adding new content doesn't make it jump
192                                domGeometry.setMarginBox(this.wipeNode, { h: domGeometry.getMarginBox(this.wipeNode).h });
193
194                                // add the new content (erasing the old content, if any)
195                                this.inherited(arguments);
196
197                                // call _wipeIn.play() to animate from current height to new height
198                                if(this._wipeIn){
199                                        this._wipeIn.play();
200                                }else{
201                                        this.hideNode.style.display = "";
202                                }
203                        }
204                },
205
206                toggle: function(){
207                        // summary:
208                        //              Switches between opened and closed state
209                        // tags:
210                        //              private
211
212                        this._setOpenAttr(!this.open, true);
213                },
214
215                _setCss: function(){
216                        // summary:
217                        //              Set the open/close css state for the TitlePane
218                        // tags:
219                        //              private
220
221                        var node = this.titleBarNode || this.focusNode;
222                        var oldCls = this._titleBarClass;
223                        this._titleBarClass = this.baseClass + "Title" + (this.toggleable ? "" : "Fixed") + (this.open ? "Open" : "Closed");
224                        domClass.replace(node, this._titleBarClass, oldCls || "");
225
226                        // Back compat, remove for 2.0
227                        domClass.replace(node, this._titleBarClass.replace("TitlePaneTitle", ""), (oldCls || "").replace("TitlePaneTitle", ""));
228
229                        this.arrowNodeInner.innerHTML = this.open ? "-" : "+";
230                },
231
232                _onTitleKey: function(/*Event*/ e){
233                        // summary:
234                        //              Handler for when user hits a key
235                        // tags:
236                        //              private
237
238                        if(e.keyCode == keys.DOWN_ARROW && this.open){
239                                this.containerNode.focus();
240                                e.preventDefault();
241                        }
242                },
243
244                _onTitleClick: function(){
245                        // summary:
246                        //              Handler when user clicks the title bar
247                        // tags:
248                        //              private
249                        if(this.toggleable){
250                                this.toggle();
251                        }
252                },
253
254                setTitle: function(/*String*/ title){
255                        // summary:
256                        //              Deprecated.  Use set('title', ...) instead.
257                        // tags:
258                        //              deprecated
259                        kernel.deprecated("dijit.TitlePane.setTitle() is deprecated.  Use set('title', ...) instead.", "", "2.0");
260                        this.set("title", title);
261                }
262        });
263
264        if(has("dojo-bidi")){
265                TitlePane.extend({
266                        _setTitleAttr: function(/*String*/ title){
267                                // Override default where title becomes a hover tooltip
268                                this._set("title", title);
269                                this.titleNode.innerHTML = title;
270                                this.applyTextDir(this.titleNode);
271                        },
272
273                        _setTooltipAttr: function(/*String*/ tooltip){
274                                this._set("tooltip", tooltip);
275                                if(this.textDir){
276                                        tooltip = this.enforceTextDirWithUcc(null, tooltip);
277                                }
278                                domAttr.set(this.focusNode, "title", tooltip);                  // focusNode spans the entire width, titleNode doesn't
279                        },
280
281                        _setTextDirAttr: function(textDir){
282                                if(this._created && this.textDir != textDir){
283                                        this._set("textDir", textDir);
284                                        this.set("title", this.title);
285                                        this.set("tooltip", this.tooltip);
286                                }
287                        }
288                });
289        }
290
291        return TitlePane;
292});
Note: See TracBrowser for help on using the repository browser.