Dialog.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. require({cache:{
  2. 'url:dijit/templates/Dialog.html':"<div class=\"dijitDialog\" role=\"dialog\" aria-labelledby=\"${id}_title\">\n\t<div data-dojo-attach-point=\"titleBar\" class=\"dijitDialogTitleBar\">\n\t<span data-dojo-attach-point=\"titleNode\" class=\"dijitDialogTitle\" id=\"${id}_title\"></span>\n\t<span data-dojo-attach-point=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" data-dojo-attach-event=\"ondijitclick: onCancel\" title=\"${buttonCancel}\" role=\"button\" tabIndex=\"0\">\n\t\t<span data-dojo-attach-point=\"closeText\" class=\"closeText\" title=\"${buttonCancel}\">x</span>\n\t</span>\n\t</div>\n\t\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n</div>\n"}});
  3. define("dijit/Dialog", [
  4. "require",
  5. "dojo/_base/array", // array.forEach array.indexOf array.map
  6. "dojo/_base/connect", // connect._keypress
  7. "dojo/_base/declare", // declare
  8. "dojo/_base/Deferred", // Deferred
  9. "dojo/dom", // dom.isDescendant
  10. "dojo/dom-class", // domClass.add domClass.contains
  11. "dojo/dom-geometry", // domGeometry.position
  12. "dojo/dom-style", // domStyle.set
  13. "dojo/_base/event", // event.stop
  14. "dojo/_base/fx", // fx.fadeIn fx.fadeOut
  15. "dojo/i18n", // i18n.getLocalization
  16. "dojo/_base/kernel", // kernel.isAsync
  17. "dojo/keys",
  18. "dojo/_base/lang", // lang.mixin lang.hitch
  19. "dojo/on",
  20. "dojo/ready",
  21. "dojo/_base/sniff", // has("ie") has("opera")
  22. "dojo/_base/window", // win.body
  23. "dojo/window", // winUtils.getBox
  24. "dojo/dnd/Moveable", // Moveable
  25. "dojo/dnd/TimedMoveable", // TimedMoveable
  26. "./focus",
  27. "./_base/manager", // manager.defaultDuration
  28. "./_Widget",
  29. "./_TemplatedMixin",
  30. "./_CssStateMixin",
  31. "./form/_FormMixin",
  32. "./_DialogMixin",
  33. "./DialogUnderlay",
  34. "./layout/ContentPane",
  35. "dojo/text!./templates/Dialog.html",
  36. ".", // for back-compat, exporting dijit._underlay (remove in 2.0)
  37. "dojo/i18n!./nls/common"
  38. ], function(require, array, connect, declare, Deferred,
  39. dom, domClass, domGeometry, domStyle, event, fx, i18n, kernel, keys, lang, on, ready, has, win, winUtils,
  40. Moveable, TimedMoveable, focus, manager, _Widget, _TemplatedMixin, _CssStateMixin, _FormMixin, _DialogMixin,
  41. DialogUnderlay, ContentPane, template, dijit){
  42. /*=====
  43. var _Widget = dijit._Widget;
  44. var _TemplatedMixin = dijit._TemplatedMixin;
  45. var _CssStateMixin = dijit._CssStateMixin;
  46. var _FormMixin = dijit.form._FormMixin;
  47. var _DialogMixin = dijit._DialogMixin;
  48. =====*/
  49. // module:
  50. // dijit/Dialog
  51. // summary:
  52. // A modal dialog Widget
  53. /*=====
  54. dijit._underlay = function(kwArgs){
  55. // summary:
  56. // A shared instance of a `dijit.DialogUnderlay`
  57. //
  58. // description:
  59. // A shared instance of a `dijit.DialogUnderlay` created and
  60. // used by `dijit.Dialog`, though never created until some Dialog
  61. // or subclass thereof is shown.
  62. };
  63. =====*/
  64. var _DialogBase = declare("dijit._DialogBase", [_TemplatedMixin, _FormMixin, _DialogMixin, _CssStateMixin], {
  65. // summary:
  66. // A modal dialog Widget
  67. //
  68. // description:
  69. // Pops up a modal dialog window, blocking access to the screen
  70. // and also graying out the screen Dialog is extended from
  71. // ContentPane so it supports all the same parameters (href, etc.)
  72. //
  73. // example:
  74. // | <div data-dojo-type="dijit.Dialog" data-dojo-props="href: 'test.html'"></div>
  75. //
  76. // example:
  77. // | var foo = new dijit.Dialog({ title: "test dialog", content: "test content" };
  78. // | dojo.body().appendChild(foo.domNode);
  79. // | foo.startup();
  80. templateString: template,
  81. baseClass: "dijitDialog",
  82. cssStateNodes: {
  83. closeButtonNode: "dijitDialogCloseIcon"
  84. },
  85. // Map widget attributes to DOMNode attributes.
  86. _setTitleAttr: [
  87. { node: "titleNode", type: "innerHTML" },
  88. { node: "titleBar", type: "attribute" }
  89. ],
  90. // open: [readonly] Boolean
  91. // True if Dialog is currently displayed on screen.
  92. open: false,
  93. // duration: Integer
  94. // The time in milliseconds it takes the dialog to fade in and out
  95. duration: manager.defaultDuration,
  96. // refocus: Boolean
  97. // A Toggle to modify the default focus behavior of a Dialog, which
  98. // is to re-focus the element which had focus before being opened.
  99. // False will disable refocusing. Default: true
  100. refocus: true,
  101. // autofocus: Boolean
  102. // A Toggle to modify the default focus behavior of a Dialog, which
  103. // is to focus on the first dialog element after opening the dialog.
  104. // False will disable autofocusing. Default: true
  105. autofocus: true,
  106. // _firstFocusItem: [private readonly] DomNode
  107. // The pointer to the first focusable node in the dialog.
  108. // Set by `dijit._DialogMixin._getFocusItems`.
  109. _firstFocusItem: null,
  110. // _lastFocusItem: [private readonly] DomNode
  111. // The pointer to which node has focus prior to our dialog.
  112. // Set by `dijit._DialogMixin._getFocusItems`.
  113. _lastFocusItem: null,
  114. // doLayout: [protected] Boolean
  115. // Don't change this parameter from the default value.
  116. // This ContentPane parameter doesn't make sense for Dialog, since Dialog
  117. // is never a child of a layout container, nor can you specify the size of
  118. // Dialog in order to control the size of an inner widget.
  119. doLayout: false,
  120. // draggable: Boolean
  121. // Toggles the moveable aspect of the Dialog. If true, Dialog
  122. // can be dragged by it's title. If false it will remain centered
  123. // in the viewport.
  124. draggable: true,
  125. //aria-describedby: String
  126. // Allows the user to add an aria-describedby attribute onto the dialog. The value should
  127. // be the id of the container element of text that describes the dialog purpose (usually
  128. // the first text in the dialog).
  129. // <div data-dojo-type="dijit.Dialog" aria-describedby="intro" .....>
  130. // <div id="intro">Introductory text</div>
  131. // <div>rest of dialog contents</div>
  132. // </div>
  133. "aria-describedby":"",
  134. postMixInProperties: function(){
  135. var _nlsResources = i18n.getLocalization("dijit", "common");
  136. lang.mixin(this, _nlsResources);
  137. this.inherited(arguments);
  138. },
  139. postCreate: function(){
  140. domStyle.set(this.domNode, {
  141. display: "none",
  142. position:"absolute"
  143. });
  144. win.body().appendChild(this.domNode);
  145. this.inherited(arguments);
  146. this.connect(this, "onExecute", "hide");
  147. this.connect(this, "onCancel", "hide");
  148. this._modalconnects = [];
  149. },
  150. onLoad: function(){
  151. // summary:
  152. // Called when data has been loaded from an href.
  153. // Unlike most other callbacks, this function can be connected to (via `dojo.connect`)
  154. // but should *not* be overridden.
  155. // tags:
  156. // callback
  157. // when href is specified we need to reposition the dialog after the data is loaded
  158. // and find the focusable elements
  159. this._position();
  160. if(this.autofocus && DialogLevelManager.isTop(this)){
  161. this._getFocusItems(this.domNode);
  162. focus.focus(this._firstFocusItem);
  163. }
  164. this.inherited(arguments);
  165. },
  166. _endDrag: function(){
  167. // summary:
  168. // Called after dragging the Dialog. Saves the position of the dialog in the viewport,
  169. // and also adjust position to be fully within the viewport, so user doesn't lose access to handle
  170. var nodePosition = domGeometry.position(this.domNode),
  171. viewport = winUtils.getBox();
  172. nodePosition.y = Math.min(Math.max(nodePosition.y, 0), (viewport.h - nodePosition.h));
  173. nodePosition.x = Math.min(Math.max(nodePosition.x, 0), (viewport.w - nodePosition.w));
  174. this._relativePosition = nodePosition;
  175. this._position();
  176. },
  177. _setup: function(){
  178. // summary:
  179. // Stuff we need to do before showing the Dialog for the first
  180. // time (but we defer it until right beforehand, for
  181. // performance reasons).
  182. // tags:
  183. // private
  184. var node = this.domNode;
  185. if(this.titleBar && this.draggable){
  186. this._moveable = new ((has("ie") == 6) ? TimedMoveable // prevent overload, see #5285
  187. : Moveable)(node, { handle: this.titleBar });
  188. this.connect(this._moveable, "onMoveStop", "_endDrag");
  189. }else{
  190. domClass.add(node,"dijitDialogFixed");
  191. }
  192. this.underlayAttrs = {
  193. dialogId: this.id,
  194. "class": array.map(this["class"].split(/\s/), function(s){ return s+"_underlay"; }).join(" ")
  195. };
  196. },
  197. _size: function(){
  198. // summary:
  199. // If necessary, shrink dialog contents so dialog fits in viewport
  200. // tags:
  201. // private
  202. this._checkIfSingleChild();
  203. // If we resized the dialog contents earlier, reset them back to original size, so
  204. // that if the user later increases the viewport size, the dialog can display w/out a scrollbar.
  205. // Need to do this before the domGeometry.position(this.domNode) call below.
  206. if(this._singleChild){
  207. if(this._singleChildOriginalStyle){
  208. this._singleChild.domNode.style.cssText = this._singleChildOriginalStyle;
  209. }
  210. delete this._singleChildOriginalStyle;
  211. }else{
  212. domStyle.set(this.containerNode, {
  213. width:"auto",
  214. height:"auto"
  215. });
  216. }
  217. var bb = domGeometry.position(this.domNode);
  218. var viewport = winUtils.getBox();
  219. if(bb.w >= viewport.w || bb.h >= viewport.h){
  220. // Reduce size of dialog contents so that dialog fits in viewport
  221. var w = Math.min(bb.w, Math.floor(viewport.w * 0.75)),
  222. h = Math.min(bb.h, Math.floor(viewport.h * 0.75));
  223. if(this._singleChild && this._singleChild.resize){
  224. this._singleChildOriginalStyle = this._singleChild.domNode.style.cssText;
  225. this._singleChild.resize({w: w, h: h});
  226. }else{
  227. domStyle.set(this.containerNode, {
  228. width: w + "px",
  229. height: h + "px",
  230. overflow: "auto",
  231. position: "relative" // workaround IE bug moving scrollbar or dragging dialog
  232. });
  233. }
  234. }else{
  235. if(this._singleChild && this._singleChild.resize){
  236. this._singleChild.resize();
  237. }
  238. }
  239. },
  240. _position: function(){
  241. // summary:
  242. // Position modal dialog in the viewport. If no relative offset
  243. // in the viewport has been determined (by dragging, for instance),
  244. // center the node. Otherwise, use the Dialog's stored relative offset,
  245. // and position the node to top: left: values based on the viewport.
  246. if(!domClass.contains(win.body(), "dojoMove")){ // don't do anything if called during auto-scroll
  247. var node = this.domNode,
  248. viewport = winUtils.getBox(),
  249. p = this._relativePosition,
  250. bb = p ? null : domGeometry.position(node),
  251. l = Math.floor(viewport.l + (p ? p.x : (viewport.w - bb.w) / 2)),
  252. t = Math.floor(viewport.t + (p ? p.y : (viewport.h - bb.h) / 2))
  253. ;
  254. domStyle.set(node,{
  255. left: l + "px",
  256. top: t + "px"
  257. });
  258. }
  259. },
  260. _onKey: function(/*Event*/ evt){
  261. // summary:
  262. // Handles the keyboard events for accessibility reasons
  263. // tags:
  264. // private
  265. if(evt.charOrCode){
  266. var node = evt.target;
  267. if(evt.charOrCode === keys.TAB){
  268. this._getFocusItems(this.domNode);
  269. }
  270. var singleFocusItem = (this._firstFocusItem == this._lastFocusItem);
  271. // see if we are shift-tabbing from first focusable item on dialog
  272. if(node == this._firstFocusItem && evt.shiftKey && evt.charOrCode === keys.TAB){
  273. if(!singleFocusItem){
  274. focus.focus(this._lastFocusItem); // send focus to last item in dialog
  275. }
  276. event.stop(evt);
  277. }else if(node == this._lastFocusItem && evt.charOrCode === keys.TAB && !evt.shiftKey){
  278. if(!singleFocusItem){
  279. focus.focus(this._firstFocusItem); // send focus to first item in dialog
  280. }
  281. event.stop(evt);
  282. }else{
  283. // see if the key is for the dialog
  284. while(node){
  285. if(node == this.domNode || domClass.contains(node, "dijitPopup")){
  286. if(evt.charOrCode == keys.ESCAPE){
  287. this.onCancel();
  288. }else{
  289. return; // just let it go
  290. }
  291. }
  292. node = node.parentNode;
  293. }
  294. // this key is for the disabled document window
  295. if(evt.charOrCode !== keys.TAB){ // allow tabbing into the dialog for a11y
  296. event.stop(evt);
  297. // opera won't tab to a div
  298. }else if(!has("opera")){
  299. try{
  300. this._firstFocusItem.focus();
  301. }catch(e){ /*squelch*/ }
  302. }
  303. }
  304. }
  305. },
  306. show: function(){
  307. // summary:
  308. // Display the dialog
  309. // returns: dojo.Deferred
  310. // Deferred object that resolves when the display animation is complete
  311. if(this.open){ return; }
  312. if(!this._started){
  313. this.startup();
  314. }
  315. // first time we show the dialog, there's some initialization stuff to do
  316. if(!this._alreadyInitialized){
  317. this._setup();
  318. this._alreadyInitialized=true;
  319. }
  320. if(this._fadeOutDeferred){
  321. // There's a hide() operation in progress, so cancel it, but still call DialogLevelManager.hide()
  322. // as though the hide() completed, in preparation for the DialogLevelManager.show() call below.
  323. this._fadeOutDeferred.cancel();
  324. DialogLevelManager.hide(this);
  325. }
  326. if(!has("touch")){
  327. // If the user scrolls the display or resizes the viewport then reposition the Dialog. But don't do it
  328. // for touch devices, because it will counteract when a keyboard pops up and then the browser
  329. // auto-scrolls the focused node into view.
  330. this._modalconnects.push(on(window, "scroll", lang.hitch(this, "layout")));
  331. this._modalconnects.push(on(window, "resize", lang.hitch(this, function(){
  332. // IE gives spurious resize events and can actually get stuck
  333. // in an infinite loop if we don't ignore them
  334. var viewport = winUtils.getBox();
  335. if(!this._oldViewport ||
  336. viewport.h != this._oldViewport.h ||
  337. viewport.w != this._oldViewport.w){
  338. this.layout();
  339. this._oldViewport = viewport;
  340. }
  341. })));
  342. }
  343. this._modalconnects.push(on(this.domNode, connect._keypress, lang.hitch(this, "_onKey")));
  344. domStyle.set(this.domNode, {
  345. opacity:0,
  346. display:""
  347. });
  348. this._set("open", true);
  349. this._onShow(); // lazy load trigger
  350. this._size();
  351. this._position();
  352. // fade-in Animation object, setup below
  353. var fadeIn;
  354. this._fadeInDeferred = new Deferred(lang.hitch(this, function(){
  355. fadeIn.stop();
  356. delete this._fadeInDeferred;
  357. }));
  358. fadeIn = fx.fadeIn({
  359. node: this.domNode,
  360. duration: this.duration,
  361. beforeBegin: lang.hitch(this, function(){
  362. DialogLevelManager.show(this, this.underlayAttrs);
  363. }),
  364. onEnd: lang.hitch(this, function(){
  365. if(this.autofocus && DialogLevelManager.isTop(this)){
  366. // find focusable items each time dialog is shown since if dialog contains a widget the
  367. // first focusable items can change
  368. this._getFocusItems(this.domNode);
  369. focus.focus(this._firstFocusItem);
  370. }
  371. this._fadeInDeferred.callback(true);
  372. delete this._fadeInDeferred;
  373. })
  374. }).play();
  375. return this._fadeInDeferred;
  376. },
  377. hide: function(){
  378. // summary:
  379. // Hide the dialog
  380. // returns: dojo.Deferred
  381. // Deferred object that resolves when the hide animation is complete
  382. // If we haven't been initialized yet then we aren't showing and we can just return.
  383. // Likewise if we are already hidden, or are currently fading out.
  384. if(!this._alreadyInitialized || !this.open){
  385. return;
  386. }
  387. if(this._fadeInDeferred){
  388. this._fadeInDeferred.cancel();
  389. }
  390. // fade-in Animation object, setup below
  391. var fadeOut;
  392. this._fadeOutDeferred = new Deferred(lang.hitch(this, function(){
  393. fadeOut.stop();
  394. delete this._fadeOutDeferred;
  395. }));
  396. // fire onHide when the promise resolves.
  397. this._fadeOutDeferred.then(lang.hitch(this, 'onHide'));
  398. fadeOut = fx.fadeOut({
  399. node: this.domNode,
  400. duration: this.duration,
  401. onEnd: lang.hitch(this, function(){
  402. this.domNode.style.display = "none";
  403. DialogLevelManager.hide(this);
  404. this._fadeOutDeferred.callback(true);
  405. delete this._fadeOutDeferred;
  406. })
  407. }).play();
  408. if(this._scrollConnected){
  409. this._scrollConnected = false;
  410. }
  411. var h;
  412. while(h = this._modalconnects.pop()){
  413. h.remove();
  414. }
  415. if(this._relativePosition){
  416. delete this._relativePosition;
  417. }
  418. this._set("open", false);
  419. return this._fadeOutDeferred;
  420. },
  421. layout: function(){
  422. // summary:
  423. // Position the Dialog and the underlay
  424. // tags:
  425. // private
  426. if(this.domNode.style.display != "none"){
  427. if(dijit._underlay){ // avoid race condition during show()
  428. dijit._underlay.layout();
  429. }
  430. this._position();
  431. }
  432. },
  433. destroy: function(){
  434. if(this._fadeInDeferred){
  435. this._fadeInDeferred.cancel();
  436. }
  437. if(this._fadeOutDeferred){
  438. this._fadeOutDeferred.cancel();
  439. }
  440. if(this._moveable){
  441. this._moveable.destroy();
  442. }
  443. var h;
  444. while(h = this._modalconnects.pop()){
  445. h.remove();
  446. }
  447. DialogLevelManager.hide(this);
  448. this.inherited(arguments);
  449. }
  450. });
  451. var Dialog = declare("dijit.Dialog", [ContentPane, _DialogBase], {});
  452. Dialog._DialogBase = _DialogBase; // for monkey patching
  453. var DialogLevelManager = Dialog._DialogLevelManager = {
  454. // summary:
  455. // Controls the various active "levels" on the page, starting with the
  456. // stuff initially visible on the page (at z-index 0), and then having an entry for
  457. // each Dialog shown.
  458. _beginZIndex: 950,
  459. show: function(/*dijit._Widget*/ dialog, /*Object*/ underlayAttrs){
  460. // summary:
  461. // Call right before fade-in animation for new dialog.
  462. // Saves current focus, displays/adjusts underlay for new dialog,
  463. // and sets the z-index of the dialog itself.
  464. //
  465. // New dialog will be displayed on top of all currently displayed dialogs.
  466. //
  467. // Caller is responsible for setting focus in new dialog after the fade-in
  468. // animation completes.
  469. // Save current focus
  470. ds[ds.length-1].focus = focus.curNode;
  471. // Display the underlay, or if already displayed then adjust for this new dialog
  472. var underlay = dijit._underlay;
  473. if(!underlay || underlay._destroyed){
  474. underlay = dijit._underlay = new DialogUnderlay(underlayAttrs);
  475. }else{
  476. underlay.set(dialog.underlayAttrs);
  477. }
  478. // Set z-index a bit above previous dialog
  479. var zIndex = ds[ds.length-1].dialog ? ds[ds.length-1].zIndex + 2 : Dialog._DialogLevelManager._beginZIndex;
  480. if(ds.length == 1){ // first dialog
  481. underlay.show();
  482. }
  483. domStyle.set(dijit._underlay.domNode, 'zIndex', zIndex - 1);
  484. // Dialog
  485. domStyle.set(dialog.domNode, 'zIndex', zIndex);
  486. ds.push({dialog: dialog, underlayAttrs: underlayAttrs, zIndex: zIndex});
  487. },
  488. hide: function(/*dijit._Widget*/ dialog){
  489. // summary:
  490. // Called when the specified dialog is hidden/destroyed, after the fade-out
  491. // animation ends, in order to reset page focus, fix the underlay, etc.
  492. // If the specified dialog isn't open then does nothing.
  493. //
  494. // Caller is responsible for either setting display:none on the dialog domNode,
  495. // or calling dijit.popup.hide(), or removing it from the page DOM.
  496. if(ds[ds.length-1].dialog == dialog){
  497. // Removing the top (or only) dialog in the stack, return focus
  498. // to previous dialog
  499. ds.pop();
  500. var pd = ds[ds.length-1]; // the new active dialog (or the base page itself)
  501. // Adjust underlay
  502. if(ds.length == 1){
  503. // Returning to original page.
  504. // Hide the underlay, unless the underlay widget has already been destroyed
  505. // because we are being called during page unload (when all widgets are destroyed)
  506. if(!dijit._underlay._destroyed){
  507. dijit._underlay.hide();
  508. }
  509. }else{
  510. // Popping back to previous dialog, adjust underlay
  511. domStyle.set(dijit._underlay.domNode, 'zIndex', pd.zIndex - 1);
  512. dijit._underlay.set(pd.underlayAttrs);
  513. }
  514. // Adjust focus
  515. if(dialog.refocus){
  516. // If we are returning control to a previous dialog but for some reason
  517. // that dialog didn't have a focused field, set focus to first focusable item.
  518. // This situation could happen if two dialogs appeared at nearly the same time,
  519. // since a dialog doesn't set it's focus until the fade-in is finished.
  520. var focus = pd.focus;
  521. if(pd.dialog && (!focus || !dom.isDescendant(focus, pd.dialog.domNode))){
  522. pd.dialog._getFocusItems(pd.dialog.domNode);
  523. focus = pd.dialog._firstFocusItem;
  524. }
  525. if(focus){
  526. // Refocus the button that spawned the Dialog. This will fail in corner cases including
  527. // page unload on IE, because the dijit/form/Button that launched the Dialog may get destroyed
  528. // before this code runs. (#15058)
  529. try{
  530. focus.focus();
  531. }catch(e){}
  532. }
  533. }
  534. }else{
  535. // Removing a dialog out of order (#9944, #10705).
  536. // Don't need to mess with underlay or z-index or anything.
  537. var idx = array.indexOf(array.map(ds, function(elem){return elem.dialog}), dialog);
  538. if(idx != -1){
  539. ds.splice(idx, 1);
  540. }
  541. }
  542. },
  543. isTop: function(/*dijit._Widget*/ dialog){
  544. // summary:
  545. // Returns true if specified Dialog is the top in the task
  546. return ds[ds.length-1].dialog == dialog;
  547. }
  548. };
  549. // Stack representing the various active "levels" on the page, starting with the
  550. // stuff initially visible on the page (at z-index 0), and then having an entry for
  551. // each Dialog shown.
  552. // Each element in stack has form {
  553. // dialog: dialogWidget,
  554. // focus: returnFromGetFocus(),
  555. // underlayAttrs: attributes to set on underlay (when this widget is active)
  556. // }
  557. var ds = Dialog._dialogStack = [
  558. {dialog: null, focus: null, underlayAttrs: null} // entry for stuff at z-index: 0
  559. ];
  560. // Back compat w/1.6, remove for 2.0
  561. if(!kernel.isAsync){
  562. ready(0, function(){
  563. var requires = ["dijit/TooltipDialog"];
  564. require(requires); // use indirection so modules not rolled into a build
  565. });
  566. }
  567. return Dialog;
  568. });