UNPKG

dijit

Version:

Dijit provides a complete collection of user interface controls based on Dojo, giving you the power to create web applications that are highly optimized for usability, performance, internationalization, accessibility, but above all deliver an incredible u

293 lines (247 loc) 9.04 kB
define([ "dojo/_base/array", // array.forEach "dojo/_base/declare", // declare "dojo/dom", // dom.setSelectable "dojo/dom-attr", // domAttr.set or get domAttr.remove "dojo/dom-class", // domClass.replace "dojo/dom-geometry", // domGeometry.setMarginBox domGeometry.getMarginBox "dojo/fx", // fxUtils.wipeIn fxUtils.wipeOut "dojo/has", "dojo/_base/kernel", // kernel.deprecated "dojo/keys", // keys.DOWN_ARROW keys.ENTER "./_CssStateMixin", "./_TemplatedMixin", "./layout/ContentPane", "dojo/text!./templates/TitlePane.html", "./_base/manager", // defaultDuration "./a11yclick" // template uses ondijitclick ], function(array, declare, dom, domAttr, domClass, domGeometry, fxUtils, has, kernel, keys, _CssStateMixin, _TemplatedMixin, ContentPane, template, manager){ // module: // dijit/TitlePane var TitlePane = declare("dijit.TitlePane", [ContentPane, _TemplatedMixin, _CssStateMixin], { // summary: // A pane with a title on top, that can be expanded or collapsed. // // description: // An accessible container with a title Heading, and a content // section that slides open and closed. TitlePane is an extension to // `dijit/layout/ContentPane`, providing all the useful content-control aspects from it. // // example: // | // load a TitlePane from remote file: // | var foo = new dijit.TitlePane({ href: "foobar.html", title:"Title" }); // | foo.startup(); // // example: // | <!-- markup href example: --> // | <div data-dojo-type="dijit/TitlePane" data-dojo-props="href: 'foobar.html', title: 'Title'"></div> // // example: // | <!-- markup with inline data --> // | <div data-dojo-type="dijit/TitlePane" title="Title"> // | <p>I am content</p> // | </div> // title: String // Title of the pane title: "", _setTitleAttr: { node: "titleNode", type: "innerHTML" }, // override default where title becomes a hover tooltip // open: Boolean // Whether pane is opened or closed. open: true, // toggleable: Boolean // Whether pane can be opened or closed by clicking the title bar. toggleable: true, // tabIndex: String // Tabindex setting for the title (so users can tab to the title then // use space/enter to open/close the title pane) tabIndex: "0", // duration: Integer // Time in milliseconds to fade in/fade out duration: manager.defaultDuration, // baseClass: [protected] String // The root className to be placed on this widget's domNode. baseClass: "dijitTitlePane", templateString: template, // doLayout: [protected] Boolean // Don't change this parameter from the default value. // This ContentPane parameter doesn't make sense for TitlePane, since TitlePane // is never a child of a layout container, nor should TitlePane try to control // the size of an inner widget. doLayout: false, // Tooltip is defined in _WidgetBase but we need to handle the mapping to DOM here _setTooltipAttr: {node: "focusNode", type: "attribute", attribute: "title"}, // focusNode spans the entire width, titleNode doesn't buildRendering: function(){ this.inherited(arguments); dom.setSelectable(this.titleNode, false); }, postCreate: function(){ this.inherited(arguments); // Hover and focus effect on title bar, except for non-toggleable TitlePanes // This should really be controlled from _setToggleableAttr() but _CssStateMixin // doesn't provide a way to disconnect a previous _trackMouseState() call if(this.toggleable){ this._trackMouseState(this.titleBarNode, this.baseClass + "Title"); } // setup open/close animations var hideNode = this.hideNode, wipeNode = this.wipeNode; this._wipeIn = fxUtils.wipeIn({ node: wipeNode, duration: this.duration, beforeBegin: function(){ hideNode.style.display = ""; } }); this._wipeOut = fxUtils.wipeOut({ node: wipeNode, duration: this.duration, onEnd: function(){ hideNode.style.display = "none"; } }); }, _setOpenAttr: function(/*Boolean*/ open, /*Boolean*/ animate){ // summary: // Hook to make set("open", boolean) control the open/closed state of the pane. // open: Boolean // True if you want to open the pane, false if you want to close it. array.forEach([this._wipeIn, this._wipeOut], function(animation){ if(animation && animation.status() == "playing"){ animation.stop(); } }); if(animate){ var anim = this[open ? "_wipeIn" : "_wipeOut"]; anim.play(); }else{ this.hideNode.style.display = this.wipeNode.style.display = open ? "" : "none"; } // load content (if this is the first time we are opening the TitlePane // and content is specified as an href, or href was set when hidden) if(this._started){ if(open){ this._onShow(); }else{ this.onHide(); } } this.containerNode.setAttribute("aria-hidden", open ? "false" : "true"); this.focusNode.setAttribute("aria-pressed", open ? "true" : "false"); this._set("open", open); this._setCss(); }, _setToggleableAttr: function(/*Boolean*/ canToggle){ // summary: // Hook to make set("toggleable", boolean) work. // canToggle: Boolean // True to allow user to open/close pane by clicking title bar. this.focusNode.setAttribute("role", canToggle ? "button" : "heading"); if(canToggle){ this.focusNode.setAttribute("aria-controls", this.id + "_pane"); this.focusNode.setAttribute("tabIndex", this.tabIndex); this.focusNode.setAttribute("aria-pressed", this.open); }else{ domAttr.remove(this.focusNode, "aria-controls"); domAttr.remove(this.focusNode, "tabIndex"); domAttr.remove(this.focusNode, "aria-pressed"); } this._set("toggleable", canToggle); this._setCss(); }, _setContentAttr: function(/*String|DomNode|Nodelist*/ content){ // summary: // Hook to make set("content", ...) work. // Typically called when an href is loaded. Our job is to make the animation smooth. if(!this.open || !this._wipeOut || this._wipeOut.status() == "playing"){ // we are currently *closing* the pane (or the pane is closed), so just let that continue this.inherited(arguments); }else{ if(this._wipeIn && this._wipeIn.status() == "playing"){ this._wipeIn.stop(); } // freeze container at current height so that adding new content doesn't make it jump domGeometry.setMarginBox(this.wipeNode, { h: domGeometry.getMarginBox(this.wipeNode).h }); // add the new content (erasing the old content, if any) this.inherited(arguments); // call _wipeIn.play() to animate from current height to new height if(this._wipeIn){ this._wipeIn.play(); }else{ this.hideNode.style.display = ""; } } }, toggle: function(){ // summary: // Switches between opened and closed state // tags: // private this._setOpenAttr(!this.open, true); }, _setCss: function(){ // summary: // Set the open/close css state for the TitlePane // tags: // private var node = this.titleBarNode || this.focusNode; var oldCls = this._titleBarClass; this._titleBarClass = this.baseClass + "Title" + (this.toggleable ? "" : "Fixed") + (this.open ? "Open" : "Closed"); domClass.replace(node, this._titleBarClass, oldCls || ""); // Back compat, remove for 2.0 domClass.replace(node, this._titleBarClass.replace("TitlePaneTitle", ""), (oldCls || "").replace("TitlePaneTitle", "")); this.arrowNodeInner.innerHTML = this.open ? "-" : "+"; }, _onTitleKey: function(/*Event*/ e){ // summary: // Handler for when user hits a key // tags: // private if(e.keyCode == keys.DOWN_ARROW && this.open){ this.containerNode.focus(); e.preventDefault(); } }, _onTitleClick: function(){ // summary: // Handler when user clicks the title bar // tags: // private if(this.toggleable){ this.toggle(); } }, setTitle: function(/*String*/ title){ // summary: // Deprecated. Use set('title', ...) instead. // tags: // deprecated kernel.deprecated("dijit.TitlePane.setTitle() is deprecated. Use set('title', ...) instead.", "", "2.0"); this.set("title", title); } }); if(has("dojo-bidi")){ TitlePane.extend({ _setTitleAttr: function(/*String*/ title){ // Override default where title becomes a hover tooltip this._set("title", title); this.titleNode.innerHTML = title; this.applyTextDir(this.titleNode); }, _setTooltipAttr: function(/*String*/ tooltip){ this._set("tooltip", tooltip); if(this.textDir){ tooltip = this.enforceTextDirWithUcc(null, tooltip); } domAttr.set(this.focusNode, "title", tooltip); // focusNode spans the entire width, titleNode doesn't }, _setTextDirAttr: function(textDir){ if(this._created && this.textDir != textDir){ this._set("textDir", textDir); this.set("title", this.title); this.set("tooltip", this.tooltip); } } }); } return TitlePane; });