jquery.ui.dialog.js 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859
  1. /*!
  2. * jQuery UI Dialog v1.9 stable
  3. * http://jqueryui.com
  4. *
  5. * Copyright 2012 jQuery Foundation and other contributors
  6. * Released under the MIT license.
  7. * http://jquery.org/license
  8. *
  9. * http://api.jqueryui.com/dialog/
  10. *
  11. * Depends:
  12. * jquery.ui.core.js
  13. * jquery.ui.widget.js
  14. * jquery.ui.button.js
  15. * jquery.ui.draggable.js
  16. * jquery.ui.mouse.js
  17. * jquery.ui.position.js
  18. * jquery.ui.resizable.js
  19. */
  20. (function( $, undefined ) {
  21. var uiDialogClasses = "ui-dialog ui-widget ui-widget-content ui-corner-all ",
  22. sizeRelatedOptions = {
  23. buttons: true,
  24. height: true,
  25. maxHeight: true,
  26. maxWidth: true,
  27. minHeight: true,
  28. minWidth: true,
  29. width: true
  30. },
  31. resizableRelatedOptions = {
  32. maxHeight: true,
  33. maxWidth: true,
  34. minHeight: true,
  35. minWidth: true
  36. };
  37. $.widget("ui.dialog", {
  38. version: "@VERSION",
  39. options: {
  40. autoOpen: true,
  41. buttons: {},
  42. closeOnEscape: true,
  43. closeText: "close",
  44. dialogClass: "",
  45. draggable: true,
  46. hide: null,
  47. height: "auto",
  48. maxHeight: false,
  49. maxWidth: false,
  50. minHeight: 150,
  51. minWidth: 150,
  52. modal: false,
  53. position: {
  54. my: "center",
  55. at: "center",
  56. of: window,
  57. collision: "fit",
  58. // ensure that the titlebar is never outside the document
  59. using: function( pos ) {
  60. var topOffset = $( this ).css( pos ).offset().top;
  61. if ( topOffset < 0 ) {
  62. $( this ).css( "top", pos.top - topOffset );
  63. }
  64. }
  65. },
  66. resizable: true,
  67. show: null,
  68. stack: true,
  69. title: "",
  70. width: 300,
  71. zIndex: 1000
  72. },
  73. _create: function() {
  74. this.originalTitle = this.element.attr( "title" );
  75. // #5742 - .attr() might return a DOMElement
  76. if ( typeof this.originalTitle !== "string" ) {
  77. this.originalTitle = "";
  78. }
  79. this.oldPosition = {
  80. parent: this.element.parent(),
  81. index: this.element.parent().children().index( this.element )
  82. };
  83. this.options.title = this.options.title || this.originalTitle;
  84. var that = this,
  85. options = this.options,
  86. title = options.title || "&#160;",
  87. uiDialog,
  88. uiDialogTitlebar,
  89. uiDialogTitlebarClose,
  90. uiDialogTitle,
  91. uiDialogButtonPane;
  92. uiDialog = ( this.uiDialog = $( "<div>" ) )
  93. .addClass( uiDialogClasses + options.dialogClass )
  94. .css({
  95. display: "none",
  96. outline: 0, // TODO: move to stylesheet
  97. zIndex: options.zIndex
  98. })
  99. // setting tabIndex makes the div focusable
  100. .attr( "tabIndex", -1)
  101. .keydown(function( event ) {
  102. if ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
  103. event.keyCode === $.ui.keyCode.ESCAPE ) {
  104. that.close( event );
  105. event.preventDefault();
  106. }
  107. })
  108. .mousedown(function( event ) {
  109. that.moveToTop( false, event );
  110. })
  111. .appendTo( "body" );
  112. this.element
  113. .show()
  114. .removeAttr( "title" )
  115. .addClass( "ui-dialog-content ui-widget-content" )
  116. .appendTo( uiDialog );
  117. uiDialogTitlebar = ( this.uiDialogTitlebar = $( "<div>" ) )
  118. .addClass( "ui-dialog-titlebar ui-widget-header " +
  119. "ui-corner-all ui-helper-clearfix" )
  120. .bind( "mousedown", function() {
  121. // Dialog isn't getting focus when dragging (#8063)
  122. uiDialog.focus();
  123. })
  124. .prependTo( uiDialog );
  125. uiDialogTitlebarClose = $( "<a href='#'></a>" )
  126. .addClass( "ui-dialog-titlebar-close ui-corner-all" )
  127. .attr( "role", "button" )
  128. .click(function( event ) {
  129. event.preventDefault();
  130. that.close( event );
  131. })
  132. .appendTo( uiDialogTitlebar );
  133. ( this.uiDialogTitlebarCloseText = $( "<span>" ) )
  134. .addClass( "ui-icon ui-icon-closethick" )
  135. .text( options.closeText )
  136. .appendTo( uiDialogTitlebarClose );
  137. uiDialogTitle = $( "<span>" )
  138. .uniqueId()
  139. .addClass( "ui-dialog-title" )
  140. .html( title )
  141. .prependTo( uiDialogTitlebar );
  142. uiDialogButtonPane = ( this.uiDialogButtonPane = $( "<div>" ) )
  143. .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
  144. ( this.uiButtonSet = $( "<div>" ) )
  145. .addClass( "ui-dialog-buttonset" )
  146. .appendTo( uiDialogButtonPane );
  147. uiDialog.attr({
  148. role: "dialog",
  149. "aria-labelledby": uiDialogTitle.attr( "id" )
  150. });
  151. uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection();
  152. this._hoverable( uiDialogTitlebarClose );
  153. this._focusable( uiDialogTitlebarClose );
  154. if ( options.draggable && $.fn.draggable ) {
  155. this._makeDraggable();
  156. }
  157. if ( options.resizable && $.fn.resizable ) {
  158. this._makeResizable();
  159. }
  160. this._createButtons( options.buttons );
  161. this._isOpen = false;
  162. if ( $.fn.bgiframe ) {
  163. uiDialog.bgiframe();
  164. }
  165. // prevent tabbing out of modal dialogs
  166. this._on( uiDialog, { keydown: function( event ) {
  167. if ( !options.modal || event.keyCode !== $.ui.keyCode.TAB ) {
  168. return;
  169. }
  170. var tabbables = $( ":tabbable", uiDialog ),
  171. first = tabbables.filter( ":first" ),
  172. last = tabbables.filter( ":last" );
  173. if ( event.target === last[0] && !event.shiftKey ) {
  174. first.focus( 1 );
  175. return false;
  176. } else if ( event.target === first[0] && event.shiftKey ) {
  177. last.focus( 1 );
  178. return false;
  179. }
  180. }});
  181. },
  182. _init: function() {
  183. if ( this.options.autoOpen ) {
  184. this.open();
  185. }
  186. },
  187. _destroy: function() {
  188. var next,
  189. oldPosition = this.oldPosition;
  190. if ( this.overlay ) {
  191. this.overlay.destroy();
  192. }
  193. this.uiDialog.hide();
  194. this.element
  195. .removeClass( "ui-dialog-content ui-widget-content" )
  196. .hide()
  197. .appendTo( "body" );
  198. this.uiDialog.remove();
  199. if ( this.originalTitle ) {
  200. this.element.attr( "title", this.originalTitle );
  201. }
  202. next = oldPosition.parent.children().eq( oldPosition.index );
  203. // Don't try to place the dialog next to itself (#8613)
  204. if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
  205. next.before( this.element );
  206. } else {
  207. oldPosition.parent.append( this.element );
  208. }
  209. },
  210. widget: function() {
  211. return this.uiDialog;
  212. },
  213. close: function( event ) {
  214. var that = this,
  215. maxZ, thisZ;
  216. if ( !this._isOpen ) {
  217. return;
  218. }
  219. if ( false === this._trigger( "beforeClose", event ) ) {
  220. return;
  221. }
  222. this._isOpen = false;
  223. if ( this.overlay ) {
  224. this.overlay.destroy();
  225. }
  226. if ( this.options.hide ) {
  227. this._hide( this.uiDialog, this.options.hide, function() {
  228. that._trigger( "close", event );
  229. });
  230. } else {
  231. this.uiDialog.hide();
  232. this._trigger( "close", event );
  233. }
  234. $.ui.dialog.overlay.resize();
  235. // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
  236. if ( this.options.modal ) {
  237. maxZ = 0;
  238. $( ".ui-dialog" ).each(function() {
  239. if ( this !== that.uiDialog[0] ) {
  240. thisZ = $( this ).css( "z-index" );
  241. if ( !isNaN( thisZ ) ) {
  242. maxZ = Math.max( maxZ, thisZ );
  243. }
  244. }
  245. });
  246. $.ui.dialog.maxZ = maxZ;
  247. }
  248. return this;
  249. },
  250. isOpen: function() {
  251. return this._isOpen;
  252. },
  253. // the force parameter allows us to move modal dialogs to their correct
  254. // position on open
  255. moveToTop: function( force, event ) {
  256. var options = this.options,
  257. saveScroll;
  258. if ( ( options.modal && !force ) ||
  259. ( !options.stack && !options.modal ) ) {
  260. return this._trigger( "focus", event );
  261. }
  262. if ( options.zIndex > $.ui.dialog.maxZ ) {
  263. $.ui.dialog.maxZ = options.zIndex;
  264. }
  265. if ( this.overlay ) {
  266. $.ui.dialog.maxZ += 1;
  267. $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ;
  268. this.overlay.$el.css( "z-index", $.ui.dialog.overlay.maxZ );
  269. }
  270. // Save and then restore scroll
  271. // Opera 9.5+ resets when parent z-index is changed.
  272. // http://bugs.jqueryui.com/ticket/3193
  273. saveScroll = {
  274. scrollTop: this.element.scrollTop(),
  275. scrollLeft: this.element.scrollLeft()
  276. };
  277. $.ui.dialog.maxZ += 1;
  278. this.uiDialog.css( "z-index", $.ui.dialog.maxZ );
  279. this.element.attr( saveScroll );
  280. this._trigger( "focus", event );
  281. return this;
  282. },
  283. open: function() {
  284. if ( this._isOpen ) {
  285. return;
  286. }
  287. var hasFocus,
  288. options = this.options,
  289. uiDialog = this.uiDialog;
  290. this._size();
  291. this._position( options.position );
  292. uiDialog.show( options.show );
  293. this.overlay = options.modal ? new $.ui.dialog.overlay( this ) : null;
  294. this.moveToTop( true );
  295. // set focus to the first tabbable element in the content area or the first button
  296. // if there are no tabbable elements, set focus on the dialog itself
  297. hasFocus = this.element.find( ":tabbable" );
  298. if ( !hasFocus.length ) {
  299. hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
  300. if ( !hasFocus.length ) {
  301. hasFocus = uiDialog;
  302. }
  303. }
  304. hasFocus.eq( 0 ).focus();
  305. this._isOpen = true;
  306. this._trigger( "open" );
  307. return this;
  308. },
  309. _createButtons: function( buttons ) {
  310. var that = this,
  311. hasButtons = false;
  312. // if we already have a button pane, remove it
  313. this.uiDialogButtonPane.remove();
  314. this.uiButtonSet.empty();
  315. if ( typeof buttons === "object" && buttons !== null ) {
  316. $.each( buttons, function() {
  317. return !(hasButtons = true);
  318. });
  319. }
  320. if ( hasButtons ) {
  321. $.each( buttons, function( name, props ) {
  322. var button, click;
  323. props = $.isFunction( props ) ?
  324. { click: props, text: name } :
  325. props;
  326. // Default to a non-submitting button
  327. props = $.extend( { type: "button" }, props );
  328. // Change the context for the click callback to be the main element
  329. click = props.click;
  330. props.click = function() {
  331. click.apply( that.element[0], arguments );
  332. };
  333. button = $( "<button></button>", props )
  334. .appendTo( that.uiButtonSet );
  335. if ( $.fn.button ) {
  336. button.button();
  337. }
  338. });
  339. this.uiDialog.addClass( "ui-dialog-buttons" );
  340. this.uiDialogButtonPane.appendTo( this.uiDialog );
  341. } else {
  342. this.uiDialog.removeClass( "ui-dialog-buttons" );
  343. }
  344. },
  345. _makeDraggable: function() {
  346. var that = this,
  347. options = this.options;
  348. function filteredUi( ui ) {
  349. return {
  350. position: ui.position,
  351. offset: ui.offset
  352. };
  353. }
  354. this.uiDialog.draggable({
  355. cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
  356. handle: ".ui-dialog-titlebar",
  357. containment: "document",
  358. start: function( event, ui ) {
  359. $( this )
  360. .addClass( "ui-dialog-dragging" );
  361. that._trigger( "dragStart", event, filteredUi( ui ) );
  362. },
  363. drag: function( event, ui ) {
  364. that._trigger( "drag", event, filteredUi( ui ) );
  365. },
  366. stop: function( event, ui ) {
  367. options.position = [
  368. ui.position.left - that.document.scrollLeft(),
  369. ui.position.top - that.document.scrollTop()
  370. ];
  371. $( this )
  372. .removeClass( "ui-dialog-dragging" );
  373. that._trigger( "dragStop", event, filteredUi( ui ) );
  374. $.ui.dialog.overlay.resize();
  375. }
  376. });
  377. },
  378. _makeResizable: function( handles ) {
  379. handles = (handles === undefined ? this.options.resizable : handles);
  380. var that = this,
  381. options = this.options,
  382. // .ui-resizable has position: relative defined in the stylesheet
  383. // but dialogs have to use absolute or fixed positioning
  384. position = this.uiDialog.css( "position" ),
  385. resizeHandles = typeof handles === 'string' ?
  386. handles :
  387. "n,e,s,w,se,sw,ne,nw";
  388. function filteredUi( ui ) {
  389. return {
  390. originalPosition: ui.originalPosition,
  391. originalSize: ui.originalSize,
  392. position: ui.position,
  393. size: ui.size
  394. };
  395. }
  396. this.uiDialog.resizable({
  397. cancel: ".ui-dialog-content",
  398. containment: "document",
  399. alsoResize: this.element,
  400. maxWidth: options.maxWidth,
  401. maxHeight: options.maxHeight,
  402. minWidth: options.minWidth,
  403. minHeight: this._minHeight(),
  404. handles: resizeHandles,
  405. start: function( event, ui ) {
  406. $( this ).addClass( "ui-dialog-resizing" );
  407. that._trigger( "resizeStart", event, filteredUi( ui ) );
  408. },
  409. resize: function( event, ui ) {
  410. that._trigger( "resize", event, filteredUi( ui ) );
  411. },
  412. stop: function( event, ui ) {
  413. $( this ).removeClass( "ui-dialog-resizing" );
  414. options.height = $( this ).height();
  415. options.width = $( this ).width();
  416. that._trigger( "resizeStop", event, filteredUi( ui ) );
  417. $.ui.dialog.overlay.resize();
  418. }
  419. })
  420. .css( "position", position )
  421. .find( ".ui-resizable-se" )
  422. .addClass( "ui-icon ui-icon-grip-diagonal-se" );
  423. },
  424. _minHeight: function() {
  425. var options = this.options;
  426. if ( options.height === "auto" ) {
  427. return options.minHeight;
  428. } else {
  429. return Math.min( options.minHeight, options.height );
  430. }
  431. },
  432. _position: function( position ) {
  433. var myAt = [],
  434. offset = [ 0, 0 ],
  435. isVisible;
  436. if ( position ) {
  437. // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
  438. // if (typeof position == 'string' || $.isArray(position)) {
  439. // myAt = $.isArray(position) ? position : position.split(' ');
  440. if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
  441. myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ];
  442. if ( myAt.length === 1 ) {
  443. myAt[ 1 ] = myAt[ 0 ];
  444. }
  445. $.each( [ "left", "top" ], function( i, offsetPosition ) {
  446. if ( +myAt[ i ] === myAt[ i ] ) {
  447. offset[ i ] = myAt[ i ];
  448. myAt[ i ] = offsetPosition;
  449. }
  450. });
  451. position = {
  452. my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
  453. myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
  454. at: myAt.join( " " )
  455. };
  456. }
  457. position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
  458. } else {
  459. position = $.ui.dialog.prototype.options.position;
  460. }
  461. // need to show the dialog to get the actual offset in the position plugin
  462. isVisible = this.uiDialog.is( ":visible" );
  463. if ( !isVisible ) {
  464. this.uiDialog.show();
  465. }
  466. this.uiDialog.position( position );
  467. if ( !isVisible ) {
  468. this.uiDialog.hide();
  469. }
  470. },
  471. _setOptions: function( options ) {
  472. var that = this,
  473. resizableOptions = {},
  474. resize = false;
  475. $.each( options, function( key, value ) {
  476. that._setOption( key, value );
  477. if ( key in sizeRelatedOptions ) {
  478. resize = true;
  479. }
  480. if ( key in resizableRelatedOptions ) {
  481. resizableOptions[ key ] = value;
  482. }
  483. });
  484. if ( resize ) {
  485. this._size();
  486. }
  487. if ( this.uiDialog.is( ":data(resizable)" ) ) {
  488. this.uiDialog.resizable( "option", resizableOptions );
  489. }
  490. },
  491. _setOption: function( key, value ) {
  492. var isDraggable, isResizable,
  493. uiDialog = this.uiDialog;
  494. switch ( key ) {
  495. case "buttons":
  496. this._createButtons( value );
  497. break;
  498. case "closeText":
  499. // ensure that we always pass a string
  500. this.uiDialogTitlebarCloseText.text( "" + value );
  501. break;
  502. case "dialogClass":
  503. uiDialog
  504. .removeClass( this.options.dialogClass )
  505. .addClass( uiDialogClasses + value );
  506. break;
  507. case "disabled":
  508. if ( value ) {
  509. uiDialog.addClass( "ui-dialog-disabled" );
  510. } else {
  511. uiDialog.removeClass( "ui-dialog-disabled" );
  512. }
  513. break;
  514. case "draggable":
  515. isDraggable = uiDialog.is( ":data(draggable)" );
  516. if ( isDraggable && !value ) {
  517. uiDialog.draggable( "destroy" );
  518. }
  519. if ( !isDraggable && value ) {
  520. this._makeDraggable();
  521. }
  522. break;
  523. case "position":
  524. this._position( value );
  525. break;
  526. case "resizable":
  527. // currently resizable, becoming non-resizable
  528. isResizable = uiDialog.is( ":data(resizable)" );
  529. if ( isResizable && !value ) {
  530. uiDialog.resizable( "destroy" );
  531. }
  532. // currently resizable, changing handles
  533. if ( isResizable && typeof value === "string" ) {
  534. uiDialog.resizable( "option", "handles", value );
  535. }
  536. // currently non-resizable, becoming resizable
  537. if ( !isResizable && value !== false ) {
  538. this._makeResizable( value );
  539. }
  540. break;
  541. case "title":
  542. // convert whatever was passed in o a string, for html() to not throw up
  543. $( ".ui-dialog-title", this.uiDialogTitlebar )
  544. .html( "" + ( value || "&#160;" ) );
  545. break;
  546. }
  547. this._super( key, value );
  548. },
  549. _size: function() {
  550. /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
  551. * divs will both have width and height set, so we need to reset them
  552. */
  553. var nonContentHeight, minContentHeight, autoHeight,
  554. options = this.options,
  555. isVisible = this.uiDialog.is( ":visible" );
  556. // reset content sizing
  557. this.element.show().css({
  558. width: "auto",
  559. minHeight: 0,
  560. height: 0
  561. });
  562. if ( options.minWidth > options.width ) {
  563. options.width = options.minWidth;
  564. }
  565. // reset wrapper sizing
  566. // determine the height of all the non-content elements
  567. nonContentHeight = this.uiDialog.css({
  568. height: "auto",
  569. width: options.width
  570. })
  571. .outerHeight();
  572. minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
  573. if ( options.height === "auto" ) {
  574. // only needed for IE6 support
  575. if ( $.support.minHeight ) {
  576. this.element.css({
  577. minHeight: minContentHeight,
  578. height: "auto"
  579. });
  580. } else {
  581. this.uiDialog.show();
  582. autoHeight = this.element.css( "height", "auto" ).height();
  583. if ( !isVisible ) {
  584. this.uiDialog.hide();
  585. }
  586. this.element.height( Math.max( autoHeight, minContentHeight ) );
  587. }
  588. } else {
  589. this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
  590. }
  591. if (this.uiDialog.is( ":data(resizable)" ) ) {
  592. this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
  593. }
  594. }
  595. });
  596. $.extend($.ui.dialog, {
  597. uuid: 0,
  598. maxZ: 0,
  599. getTitleId: function($el) {
  600. var id = $el.attr( "id" );
  601. if ( !id ) {
  602. this.uuid += 1;
  603. id = this.uuid;
  604. }
  605. return "ui-dialog-title-" + id;
  606. },
  607. overlay: function( dialog ) {
  608. this.$el = $.ui.dialog.overlay.create( dialog );
  609. }
  610. });
  611. $.extend( $.ui.dialog.overlay, {
  612. instances: [],
  613. // reuse old instances due to IE memory leak with alpha transparency (see #5185)
  614. oldInstances: [],
  615. maxZ: 0,
  616. events: $.map(
  617. "focus,mousedown,mouseup,keydown,keypress,click".split( "," ),
  618. function( event ) {
  619. return event + ".dialog-overlay";
  620. }
  621. ).join( " " ),
  622. create: function( dialog ) {
  623. if ( this.instances.length === 0 ) {
  624. // prevent use of anchors and inputs
  625. // we use a setTimeout in case the overlay is created from an
  626. // event that we're going to be cancelling (see #2804)
  627. setTimeout(function() {
  628. // handle $(el).dialog().dialog('close') (see #4065)
  629. if ( $.ui.dialog.overlay.instances.length ) {
  630. $( document ).bind( $.ui.dialog.overlay.events, function( event ) {
  631. // stop events if the z-index of the target is < the z-index of the overlay
  632. // we cannot return true when we don't want to cancel the event (#3523)
  633. if ( $( event.target ).zIndex() < $.ui.dialog.overlay.maxZ ) {
  634. return false;
  635. }
  636. });
  637. }
  638. }, 1 );
  639. // handle window resize
  640. $( window ).bind( "resize.dialog-overlay", $.ui.dialog.overlay.resize );
  641. }
  642. var $el = ( this.oldInstances.pop() || $( "<div>" ).addClass( "ui-widget-overlay" ) );
  643. // allow closing by pressing the escape key
  644. $( document ).bind( "keydown.dialog-overlay", function( event ) {
  645. var instances = $.ui.dialog.overlay.instances;
  646. // only react to the event if we're the top overlay
  647. if ( instances.length !== 0 && instances[ instances.length - 1 ] === $el &&
  648. dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
  649. event.keyCode === $.ui.keyCode.ESCAPE ) {
  650. dialog.close( event );
  651. event.preventDefault();
  652. }
  653. });
  654. $el.appendTo( document.body ).css({
  655. width: this.width(),
  656. height: this.height()
  657. });
  658. if ( $.fn.bgiframe ) {
  659. $el.bgiframe();
  660. }
  661. this.instances.push( $el );
  662. return $el;
  663. },
  664. destroy: function( $el ) {
  665. var indexOf = $.inArray( $el, this.instances ),
  666. maxZ = 0;
  667. if ( indexOf !== -1 ) {
  668. this.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] );
  669. }
  670. if ( this.instances.length === 0 ) {
  671. $( [ document, window ] ).unbind( ".dialog-overlay" );
  672. }
  673. $el.height( 0 ).width( 0 ).remove();
  674. // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
  675. $.each( this.instances, function() {
  676. maxZ = Math.max( maxZ, this.css( "z-index" ) );
  677. });
  678. this.maxZ = maxZ;
  679. },
  680. height: function() {
  681. var scrollHeight,
  682. offsetHeight;
  683. // handle IE
  684. if ( $.ui.ie ) {
  685. scrollHeight = Math.max(
  686. document.documentElement.scrollHeight,
  687. document.body.scrollHeight
  688. );
  689. offsetHeight = Math.max(
  690. document.documentElement.offsetHeight,
  691. document.body.offsetHeight
  692. );
  693. if ( scrollHeight < offsetHeight ) {
  694. return $( window ).height() + "px";
  695. } else {
  696. return scrollHeight + "px";
  697. }
  698. // handle "good" browsers
  699. } else {
  700. return $( document ).height() + "px";
  701. }
  702. },
  703. width: function() {
  704. var scrollWidth,
  705. offsetWidth;
  706. // handle IE
  707. if ( $.ui.ie ) {
  708. scrollWidth = Math.max(
  709. document.documentElement.scrollWidth,
  710. document.body.scrollWidth
  711. );
  712. offsetWidth = Math.max(
  713. document.documentElement.offsetWidth,
  714. document.body.offsetWidth
  715. );
  716. if ( scrollWidth < offsetWidth ) {
  717. return $( window ).width() + "px";
  718. } else {
  719. return scrollWidth + "px";
  720. }
  721. // handle "good" browsers
  722. } else {
  723. return $( document ).width() + "px";
  724. }
  725. },
  726. resize: function() {
  727. /* If the dialog is draggable and the user drags it past the
  728. * right edge of the window, the document becomes wider so we
  729. * need to stretch the overlay. If the user then drags the
  730. * dialog back to the left, the document will become narrower,
  731. * so we need to shrink the overlay to the appropriate size.
  732. * This is handled by shrinking the overlay before setting it
  733. * to the full document size.
  734. */
  735. var $overlays = $( [] );
  736. $.each( $.ui.dialog.overlay.instances, function() {
  737. $overlays = $overlays.add( this );
  738. });
  739. $overlays.css({
  740. width: 0,
  741. height: 0
  742. }).css({
  743. width: $.ui.dialog.overlay.width(),
  744. height: $.ui.dialog.overlay.height()
  745. });
  746. }
  747. });
  748. $.extend( $.ui.dialog.overlay.prototype, {
  749. destroy: function() {
  750. $.ui.dialog.overlay.destroy( this.$el );
  751. }
  752. });
  753. }( jQuery ) );