Dialog.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource['dojox.widget.Dialog']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource['dojox.widget.Dialog'] = true;
  8. dojo.provide('dojox.widget.Dialog');
  9. dojo.experimental('dojox.widget.Dialog');
  10. dojo.require("dojo.window");
  11. dojo.require('dojox.fx');
  12. dojo.require("dojox.widget.DialogSimple");
  13. dojo.declare('dojox.widget.Dialog', dojox.widget.DialogSimple,
  14. {
  15. // summary:
  16. // A Lightbox-like Modal-dialog for HTML Content
  17. //
  18. // description:
  19. // An HTML-capable Dialog widget with advanced sizing
  20. // options, animated show/hide and other useful options.
  21. //
  22. // This Dialog is also very easy to apply custom styles to.
  23. //
  24. // It works identically to a `dijit.Dialog` with several
  25. // additional parameters.
  26. templateString: dojo.cache("dojox.widget", "Dialog/Dialog.html", "<div class=\"dojoxDialog\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"${id}_title\">\n\t<div dojoAttachPoint=\"titleBar\" class=\"dojoxDialogTitleBar\">\n\t\t<span dojoAttachPoint=\"titleNode\" class=\"dojoxDialogTitle\" id=\"${id}_title\">${title}</span>\n\t</div>\n\t<div dojoAttachPoint=\"dojoxDialogWrapper\">\n\t\t<div dojoAttachPoint=\"containerNode\" class=\"dojoxDialogPaneContent\"></div>\n\t</div>\n\t<div dojoAttachPoint=\"closeButtonNode\" class=\"dojoxDialogCloseIcon\" dojoAttachEvent=\"onclick: onCancel\">\n\t\t\t<span dojoAttachPoint=\"closeText\" class=\"closeText\">x</span>\n\t</div>\n</div>\n"),
  27. // sizeToViewport: Boolean
  28. // If true, fix the size of the dialog to the Viewport based on
  29. // viewportPadding value rather than the calculated or natural
  30. // stlye. If false, base the size on a passed dimension attribute.
  31. // Eitherway, the viewportPadding value is used if the the content
  32. // extends beyond the viewport size for whatever reason.
  33. sizeToViewport: false,
  34. // viewportPadding: Integer
  35. // If sizeToViewport="true", this is the amount of padding in pixels to leave
  36. // between the dialog border and the viewport edge.
  37. // This value is also used when sizeToViewport="false" and dimensions exceeded
  38. // by dialog content to ensure dialog does not go outside viewport boundary
  39. viewportPadding: 35,
  40. // dimensions: Array
  41. // A two-element array of [widht,height] to animate the Dialog to if sizeToViewport="false"
  42. // Defaults to [300,300]
  43. dimensions: null,
  44. // easing: Function?|String?
  45. // An easing function to apply to the sizing animation.
  46. easing: null,
  47. // sizeDuration: Integer
  48. // Time (in ms) to use in the Animation for sizing.
  49. sizeDuration: dijit._defaultDuration,
  50. // sizeMethod: String
  51. // To be passed to dojox.fx.sizeTo, one of "chain" or "combine" to effect
  52. // the animation sequence.
  53. sizeMethod: "chain",
  54. // showTitle: Boolean
  55. // Toogle to show or hide the Title area. Can only be set at startup.
  56. showTitle: false,
  57. // draggable: Boolean
  58. // Make the pane draggable. Differs from dijit.Dialog by setting default to false
  59. draggable: false, // simply over-ride the default from dijit.Dialog
  60. // modal: Boolean
  61. // If true, this Dialog instance will be truly modal and prevent closing until
  62. // explicitly told to by calling hide() - Defaults to false to preserve previous
  63. // behaviors.
  64. modal: false,
  65. constructor: function(props, node){
  66. this.easing = props.easing || dojo._defaultEasing;
  67. this.dimensions = props.dimensions || [300, 300];
  68. },
  69. _setup: function(){
  70. // summary: Piggyback on dijit.Dialog's _setup for load-time options, deferred to
  71. this.inherited(arguments);
  72. if(!this._alreadyInitialized){
  73. this._navIn = dojo.fadeIn({ node: this.closeButtonNode });
  74. this._navOut = dojo.fadeOut({ node: this.closeButtonNode });
  75. if(!this.showTitle){
  76. dojo.addClass(this.domNode,"dojoxDialogNoTitle");
  77. }
  78. }
  79. },
  80. layout: function(e){
  81. this._setSize();
  82. this.inherited(arguments);
  83. },
  84. _setSize: function(){
  85. // summary: cache and set our desired end position
  86. this._vp = dojo.window.getBox();
  87. var tc = this.containerNode,
  88. vpSized = this.sizeToViewport
  89. ;
  90. return this._displaysize = {
  91. w: vpSized ? tc.scrollWidth : this.dimensions[0],
  92. h: vpSized ? tc.scrollHeight : this.dimensions[1]
  93. }; // Object
  94. },
  95. show: function(){
  96. if(this.open){ return; }
  97. this._setSize();
  98. dojo.style(this.closeButtonNode,"opacity", 0);
  99. dojo.style(this.domNode, {
  100. overflow: "hidden",
  101. opacity: 0,
  102. width: "1px",
  103. height: "1px"
  104. });
  105. dojo.style(this.containerNode, {
  106. opacity: 0,
  107. overflow: "hidden"
  108. });
  109. this.inherited(arguments);
  110. if(this.modal){
  111. // prevent escape key from closing dialog
  112. // connect to body to trap this event from the Dialog a11y code, and stop escape key
  113. // from doing anything in the modal:true case:
  114. this._modalconnects.push(dojo.connect(dojo.body(), "onkeypress", function(e){
  115. if(e.charOrCode == dojo.keys.ESCAPE){
  116. dojo.stopEvent(e);
  117. }
  118. }));
  119. }else{
  120. // otherwise, allow clicking on the underlay to close
  121. this._modalconnects.push(dojo.connect(dijit._underlay.domNode, "onclick", this, "onCancel"));
  122. }
  123. this._modalconnects.push(dojo.connect(this.domNode,"onmouseenter",this,"_handleNav"));
  124. this._modalconnects.push(dojo.connect(this.domNode,"onmouseleave",this,"_handleNav"));
  125. },
  126. _handleNav: function(e){
  127. // summary: Handle's showing or hiding the close icon
  128. var navou = "_navOut",
  129. navin = "_navIn",
  130. animou = (e.type == "mouseout" ? navin : navou),
  131. animin = (e.type == "mouseout" ? navou : navin)
  132. ;
  133. this[animou].stop();
  134. this[animin].play();
  135. },
  136. // an experiment in a quicksilver-like hide. too choppy for me.
  137. /*
  138. hide: function(){
  139. // summary: Hide the dialog
  140. // if we haven't been initialized yet then we aren't showing and we can just return
  141. if(!this._alreadyInitialized){
  142. return;
  143. }
  144. this._fadeIn && this._fadeIn.stop();
  145. if (this._scrollConnected){
  146. this._scrollConnected = false;
  147. }
  148. dojo.forEach(this._modalconnects, dojo.disconnect);
  149. this._modalconnects = [];
  150. if(this.refocus){
  151. this.connect(this._fadeOut,"onEnd",dojo.hitch(dijit,"focus",this._savedFocus));
  152. }
  153. if(this._relativePosition){
  154. delete this._relativePosition;
  155. }
  156. dojox.fx.sizeTo({
  157. node: this.domNode,
  158. duration:this.sizeDuration || this.duration,
  159. width: this._vp.w - 1,
  160. height: 5,
  161. onBegin: dojo.hitch(this,function(){
  162. this._fadeOut.play(this.sizeDuration / 2);
  163. })
  164. }).play();
  165. this.open = false;
  166. }, */
  167. _position: function(){
  168. if(!this._started){ return; } // prevent content: from firing this anim #8914
  169. if(this._sizing){
  170. this._sizing.stop();
  171. this.disconnect(this._sizingConnect);
  172. delete this._sizing;
  173. }
  174. this.inherited(arguments);
  175. if(!this.open){ dojo.style(this.containerNode, "opacity", 0); }
  176. var pad = this.viewportPadding * 2;
  177. var props = {
  178. node: this.domNode,
  179. duration: this.sizeDuration || dijit._defaultDuration,
  180. easing: this.easing,
  181. method: this.sizeMethod
  182. };
  183. var ds = this._displaysize || this._setSize();
  184. props['width'] = ds.w = (ds.w + pad >= this._vp.w || this.sizeToViewport)
  185. ? this._vp.w - pad : ds.w;
  186. props['height'] = ds.h = (ds.h + pad >= this._vp.h || this.sizeToViewport)
  187. ? this._vp.h - pad : ds.h;
  188. this._sizing = dojox.fx.sizeTo(props);
  189. this._sizingConnect = this.connect(this._sizing,"onEnd","_showContent");
  190. this._sizing.play();
  191. },
  192. _showContent: function(e){
  193. // summary: Show the inner container after sizing animation
  194. var container = this.containerNode;
  195. dojo.style(this.domNode, {
  196. overflow: "visible",
  197. opacity: 1
  198. });
  199. dojo.style(this.closeButtonNode,"opacity",1);
  200. dojo.style(container, {
  201. height: this._displaysize.h - this.titleNode.offsetHeight + "px",
  202. width: this._displaysize.w + "px",
  203. overflow:"auto"
  204. });
  205. dojo.anim(container, { opacity:1 });
  206. }
  207. });
  208. }