TitlePane.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. if (!dojo._hasResource["dijit.TitlePane"]) { // _hasResource checks added by
  2. // build. Do not use
  3. // _hasResource directly in your
  4. // code.
  5. dojo._hasResource["dijit.TitlePane"] = true;
  6. dojo.provide("dijit.TitlePane");
  7. dojo.require("dojo.fx");
  8. dojo.require("dijit._Templated");
  9. dojo.require("dijit.layout.ContentPane");
  10. dojo.declare("dijit.TitlePane",
  11. [dijit.layout.ContentPane, dijit._Templated], {
  12. // summary
  13. // A pane with a title on top, that can be opened or collapsed.
  14. //
  15. // title: String
  16. // Title of the pane
  17. title : "",
  18. // open: Boolean
  19. // Whether pane is opened or closed.
  20. open : true,
  21. // duration: Integer
  22. // Time in milliseconds to fade in/fade out
  23. duration : 250,
  24. // baseClass: String
  25. // the root className to use for the various states of this
  26. // widget
  27. baseClass : "dijitTitlePane",
  28. templateString : "<div class=\"dijitTitlePane\">\n\t<div dojoAttachEvent=\"onclick:toggle,onkeypress: _onTitleKey,onfocus:_handleFocus,onblur:_handleFocus\" tabindex=\"0\"\n\t\t\twaiRole=\"button\" class=\"dijitTitlePaneTitle\" dojoAttachPoint=\"focusNode\">\n\t\t<div dojoAttachPoint=\"arrowNode\" class=\"dijitInline dijitArrowNode\"><span dojoAttachPoint=\"arrowNodeInner\" class=\"dijitArrowNodeInner\"></span></div>\n\t\t<div dojoAttachPoint=\"titleNode\" class=\"dijitTitlePaneTextNode\"></div>\n\t</div>\n\t<div class=\"dijitTitlePaneContentOuter\" dojoAttachPoint=\"hideNode\">\n\t\t<div class=\"dijitReset\" dojoAttachPoint=\"wipeNode\">\n\t\t\t<div class=\"dijitTitlePaneContentInner\" dojoAttachPoint=\"containerNode\" waiRole=\"region\" tabindex=\"-1\">\n\t\t\t\t<!-- nested divs because wipeIn()/wipeOut() doesn't work right on node w/padding etc. Put padding on inner div. -->\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n",
  29. postCreate : function() {
  30. this.setTitle(this.title);
  31. if (!this.open) {
  32. this.hideNode.style.display = this.wipeNode.style.display = "none";
  33. }
  34. this._setCss();
  35. dojo.setSelectable(this.titleNode, false);
  36. this.inherited("postCreate", arguments);
  37. dijit.setWaiState(this.containerNode, "labelledby",
  38. this.titleNode.id);
  39. dijit.setWaiState(this.focusNode, "haspopup", "true");
  40. // setup open/close animations
  41. var hideNode = this.hideNode, wipeNode = this.wipeNode;
  42. this._wipeIn = dojo.fx.wipeIn({
  43. node : this.wipeNode,
  44. duration : this.duration,
  45. beforeBegin : function() {
  46. hideNode.style.display = "";
  47. }
  48. });
  49. this._wipeOut = dojo.fx.wipeOut({
  50. node : this.wipeNode,
  51. duration : this.duration,
  52. onEnd : function() {
  53. hideNode.style.display = "none";
  54. }
  55. });
  56. },
  57. setContent : function(content) {
  58. // summary
  59. // Typically called when an href is loaded. Our job is to
  60. // make the animation smooth
  61. if (this._wipeOut.status() == "playing") {
  62. // we are currently *closing* the pane, so just let that
  63. // continue
  64. this.inherited("setContent", arguments);
  65. } else {
  66. if (this._wipeIn.status() == "playing") {
  67. this._wipeIn.stop();
  68. }
  69. // freeze container at current height so that adding new
  70. // content doesn't make it jump
  71. dojo.marginBox(this.wipeNode, {
  72. h : dojo.marginBox(this.wipeNode).h
  73. });
  74. // add the new content (erasing the old content, if any)
  75. this.inherited("setContent", arguments);
  76. // call _wipeIn.play() to animate from current height to
  77. // new height
  78. this._wipeIn.play();
  79. }
  80. },
  81. toggle : function() {
  82. // summary: switches between opened and closed state
  83. dojo.forEach([this._wipeIn, this._wipeOut], function(
  84. animation) {
  85. if (animation.status() == "playing") {
  86. animation.stop();
  87. }
  88. });
  89. this[this.open ? "_wipeOut" : "_wipeIn"].play();
  90. this.open = !this.open;
  91. // load content (if this is the first time we are opening
  92. // the TitlePane
  93. // and content is specified as an href, or we have setHref
  94. // when hidden)
  95. this._loadCheck();
  96. this._setCss();
  97. },
  98. _setCss : function() {
  99. // summary: set the open/close css state for the TitlePane
  100. var classes = ["dijitClosed", "dijitOpen"];
  101. var boolIndex = this.open;
  102. dojo.removeClass(this.focusNode, classes[!boolIndex + 0]);
  103. this.focusNode.className += " " + classes[boolIndex + 0];
  104. // provide a character based indicator for images-off mode
  105. this.arrowNodeInner.innerHTML = this.open ? "-" : "+";
  106. },
  107. _onTitleKey : function(/* Event */e) {
  108. // summary: callback when user hits a key
  109. if (e.keyCode == dojo.keys.ENTER
  110. || e.charCode == dojo.keys.SPACE) {
  111. this.toggle();
  112. } else if (e.keyCode == dojo.keys.DOWN_ARROW) {
  113. if (this.open) {
  114. this.containerNode.focus();
  115. e.preventDefault();
  116. }
  117. }
  118. },
  119. _handleFocus : function(/* Event */e) {
  120. // summary: handle blur and focus for this widget
  121. // add/removeClass is safe to call without hasClass in this
  122. // case
  123. dojo[(e.type == "focus" ? "addClass" : "removeClass")](
  124. this.focusNode, this.baseClass + "Focused");
  125. },
  126. setTitle : function(/* String */title) {
  127. // summary: sets the text of the title
  128. this.titleNode.innerHTML = title;
  129. }
  130. });
  131. }