Bez popisu

dialog.js 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
  1. /*!
  2. * jQuery UI Dialog 1.12.1
  3. * http://jqueryui.com
  4. *
  5. * Copyright jQuery Foundation and other contributors
  6. * Released under the MIT license.
  7. * http://jquery.org/license
  8. */
  9. //>>label: Dialog
  10. //>>group: Widgets
  11. //>>description: Displays customizable dialog windows.
  12. //>>docs: http://api.jqueryui.com/dialog/
  13. //>>demos: http://jqueryui.com/dialog/
  14. //>>css.structure: ../../themes/base/core.css
  15. //>>css.structure: ../../themes/base/dialog.css
  16. //>>css.theme: ../../themes/base/theme.css
  17. ( function( factory ) {
  18. if ( typeof define === "function" && define.amd ) {
  19. // AMD. Register as an anonymous module.
  20. define( [
  21. "jquery",
  22. "./button",
  23. "./draggable",
  24. "./mouse",
  25. "./resizable",
  26. "./core"
  27. ], factory );
  28. } else {
  29. // Browser globals
  30. factory( jQuery );
  31. }
  32. }( function( $ ) {
  33. $.widget( "ui.dialog", {
  34. version: "1.12.1",
  35. options: {
  36. appendTo: "body",
  37. autoOpen: true,
  38. buttons: [],
  39. classes: {
  40. "ui-dialog": "ui-corner-all",
  41. "ui-dialog-titlebar": "ui-corner-all"
  42. },
  43. closeOnEscape: true,
  44. closeText: "Close",
  45. draggable: true,
  46. hide: null,
  47. height: "auto",
  48. maxHeight: null,
  49. maxWidth: null,
  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 the titlebar is always visible
  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. title: null,
  69. width: 300,
  70. // Callbacks
  71. beforeClose: null,
  72. close: null,
  73. drag: null,
  74. dragStart: null,
  75. dragStop: null,
  76. focus: null,
  77. open: null,
  78. resize: null,
  79. resizeStart: null,
  80. resizeStop: null
  81. },
  82. sizeRelatedOptions: {
  83. buttons: true,
  84. height: true,
  85. maxHeight: true,
  86. maxWidth: true,
  87. minHeight: true,
  88. minWidth: true,
  89. width: true
  90. },
  91. resizableRelatedOptions: {
  92. maxHeight: true,
  93. maxWidth: true,
  94. minHeight: true,
  95. minWidth: true
  96. },
  97. _create: function() {
  98. this.originalCss = {
  99. display: this.element[ 0 ].style.display,
  100. width: this.element[ 0 ].style.width,
  101. minHeight: this.element[ 0 ].style.minHeight,
  102. maxHeight: this.element[ 0 ].style.maxHeight,
  103. height: this.element[ 0 ].style.height
  104. };
  105. this.originalPosition = {
  106. parent: this.element.parent(),
  107. index: this.element.parent().children().index( this.element )
  108. };
  109. this.originalTitle = this.element.attr( "title" );
  110. if ( this.options.title == null && this.originalTitle != null ) {
  111. this.options.title = this.originalTitle;
  112. }
  113. // Dialogs can't be disabled
  114. if ( this.options.disabled ) {
  115. this.options.disabled = false;
  116. }
  117. this._createWrapper();
  118. this.element
  119. .show()
  120. .removeAttr( "title" )
  121. .appendTo( this.uiDialog );
  122. this._addClass( "ui-dialog-content", "ui-widget-content" );
  123. this._createTitlebar();
  124. this._createButtonPane();
  125. if ( this.options.draggable && $.fn.draggable ) {
  126. this._makeDraggable();
  127. }
  128. if ( this.options.resizable && $.fn.resizable ) {
  129. this._makeResizable();
  130. }
  131. this._isOpen = false;
  132. this._trackFocus();
  133. },
  134. _init: function() {
  135. if ( this.options.autoOpen ) {
  136. this.open();
  137. }
  138. },
  139. _appendTo: function() {
  140. var element = this.options.appendTo;
  141. if ( element && ( element.jquery || element.nodeType ) ) {
  142. return $( element );
  143. }
  144. return this.document.find( element || "body" ).eq( 0 );
  145. },
  146. _destroy: function() {
  147. var next,
  148. originalPosition = this.originalPosition;
  149. this._untrackInstance();
  150. this._destroyOverlay();
  151. this.element
  152. .removeUniqueId()
  153. .css( this.originalCss )
  154. // Without detaching first, the following becomes really slow
  155. .detach();
  156. this.uiDialog.remove();
  157. if ( this.originalTitle ) {
  158. this.element.attr( "title", this.originalTitle );
  159. }
  160. next = originalPosition.parent.children().eq( originalPosition.index );
  161. // Don't try to place the dialog next to itself (#8613)
  162. if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
  163. next.before( this.element );
  164. } else {
  165. originalPosition.parent.append( this.element );
  166. }
  167. },
  168. widget: function() {
  169. return this.uiDialog;
  170. },
  171. disable: $.noop,
  172. enable: $.noop,
  173. close: function( event ) {
  174. var that = this;
  175. if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
  176. return;
  177. }
  178. this._isOpen = false;
  179. this._focusedElement = null;
  180. this._destroyOverlay();
  181. this._untrackInstance();
  182. if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
  183. // Hiding a focused element doesn't trigger blur in WebKit
  184. // so in case we have nothing to focus on, explicitly blur the active element
  185. // https://bugs.webkit.org/show_bug.cgi?id=47182
  186. $.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
  187. }
  188. this._hide( this.uiDialog, this.options.hide, function() {
  189. that._trigger( "close", event );
  190. } );
  191. },
  192. isOpen: function() {
  193. return this._isOpen;
  194. },
  195. moveToTop: function() {
  196. this._moveToTop();
  197. },
  198. _moveToTop: function( event, silent ) {
  199. var moved = false,
  200. zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
  201. return +$( this ).css( "z-index" );
  202. } ).get(),
  203. zIndexMax = Math.max.apply( null, zIndices );
  204. if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
  205. this.uiDialog.css( "z-index", zIndexMax + 1 );
  206. moved = true;
  207. }
  208. if ( moved && !silent ) {
  209. this._trigger( "focus", event );
  210. }
  211. return moved;
  212. },
  213. open: function() {
  214. var that = this;
  215. if ( this._isOpen ) {
  216. if ( this._moveToTop() ) {
  217. this._focusTabbable();
  218. }
  219. return;
  220. }
  221. this._isOpen = true;
  222. this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
  223. this._size();
  224. this._position();
  225. this._createOverlay();
  226. this._moveToTop( null, true );
  227. // Ensure the overlay is moved to the top with the dialog, but only when
  228. // opening. The overlay shouldn't move after the dialog is open so that
  229. // modeless dialogs opened after the modal dialog stack properly.
  230. if ( this.overlay ) {
  231. this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
  232. }
  233. this._show( this.uiDialog, this.options.show, function() {
  234. that._focusTabbable();
  235. that._trigger( "focus" );
  236. } );
  237. // Track the dialog immediately upon openening in case a focus event
  238. // somehow occurs outside of the dialog before an element inside the
  239. // dialog is focused (#10152)
  240. this._makeFocusTarget();
  241. this._trigger( "open" );
  242. },
  243. _focusTabbable: function() {
  244. // Set focus to the first match:
  245. // 1. An element that was focused previously
  246. // 2. First element inside the dialog matching [autofocus]
  247. // 3. Tabbable element inside the content element
  248. // 4. Tabbable element inside the buttonpane
  249. // 5. The close button
  250. // 6. The dialog itself
  251. var hasFocus = this._focusedElement;
  252. if ( !hasFocus ) {
  253. hasFocus = this.element.find( "[autofocus]" );
  254. }
  255. if ( !hasFocus.length ) {
  256. hasFocus = this.element.find( ":tabbable" );
  257. }
  258. if ( !hasFocus.length ) {
  259. hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
  260. }
  261. if ( !hasFocus.length ) {
  262. hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
  263. }
  264. if ( !hasFocus.length ) {
  265. hasFocus = this.uiDialog;
  266. }
  267. hasFocus.eq( 0 ).trigger( "focus" );
  268. },
  269. _keepFocus: function( event ) {
  270. function checkFocus() {
  271. var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
  272. isActive = this.uiDialog[ 0 ] === activeElement ||
  273. $.contains( this.uiDialog[ 0 ], activeElement );
  274. if ( !isActive ) {
  275. this._focusTabbable();
  276. }
  277. }
  278. event.preventDefault();
  279. checkFocus.call( this );
  280. // support: IE
  281. // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
  282. // so we check again later
  283. this._delay( checkFocus );
  284. },
  285. _createWrapper: function() {
  286. this.uiDialog = $( "<div>" )
  287. .hide()
  288. .attr( {
  289. // Setting tabIndex makes the div focusable
  290. tabIndex: -1,
  291. role: "dialog"
  292. } )
  293. .appendTo( this._appendTo() );
  294. this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
  295. this._on( this.uiDialog, {
  296. keydown: function( event ) {
  297. if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
  298. event.keyCode === $.ui.keyCode.ESCAPE ) {
  299. event.preventDefault();
  300. this.close( event );
  301. return;
  302. }
  303. // Prevent tabbing out of dialogs
  304. if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
  305. return;
  306. }
  307. var tabbables = this.uiDialog.find( ":tabbable" ),
  308. first = tabbables.filter( ":first" ),
  309. last = tabbables.filter( ":last" );
  310. if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
  311. !event.shiftKey ) {
  312. this._delay( function() {
  313. first.trigger( "focus" );
  314. } );
  315. event.preventDefault();
  316. } else if ( ( event.target === first[ 0 ] ||
  317. event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
  318. this._delay( function() {
  319. last.trigger( "focus" );
  320. } );
  321. event.preventDefault();
  322. }
  323. },
  324. mousedown: function( event ) {
  325. if ( this._moveToTop( event ) ) {
  326. this._focusTabbable();
  327. }
  328. }
  329. } );
  330. // We assume that any existing aria-describedby attribute means
  331. // that the dialog content is marked up properly
  332. // otherwise we brute force the content as the description
  333. if ( !this.element.find( "[aria-describedby]" ).length ) {
  334. this.uiDialog.attr( {
  335. "aria-describedby": this.element.uniqueId().attr( "id" )
  336. } );
  337. }
  338. },
  339. _createTitlebar: function() {
  340. var uiDialogTitle;
  341. this.uiDialogTitlebar = $( "<div>" );
  342. this._addClass( this.uiDialogTitlebar,
  343. "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
  344. this._on( this.uiDialogTitlebar, {
  345. mousedown: function( event ) {
  346. // Don't prevent click on close button (#8838)
  347. // Focusing a dialog that is partially scrolled out of view
  348. // causes the browser to scroll it into view, preventing the click event
  349. if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
  350. // Dialog isn't getting focus when dragging (#8063)
  351. this.uiDialog.trigger( "focus" );
  352. }
  353. }
  354. } );
  355. // Support: IE
  356. // Use type="button" to prevent enter keypresses in textboxes from closing the
  357. // dialog in IE (#9312)
  358. this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
  359. .button( {
  360. label: $( "<a>" ).text( this.options.closeText ).html(),
  361. icon: "ui-icon-closethick",
  362. showLabel: false
  363. } )
  364. .appendTo( this.uiDialogTitlebar );
  365. this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
  366. this._on( this.uiDialogTitlebarClose, {
  367. click: function( event ) {
  368. event.preventDefault();
  369. this.close( event );
  370. }
  371. } );
  372. uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
  373. this._addClass( uiDialogTitle, "ui-dialog-title" );
  374. this._title( uiDialogTitle );
  375. this.uiDialogTitlebar.prependTo( this.uiDialog );
  376. this.uiDialog.attr( {
  377. "aria-labelledby": uiDialogTitle.attr( "id" )
  378. } );
  379. },
  380. _title: function( title ) {
  381. if ( this.options.title ) {
  382. title.text( this.options.title );
  383. } else {
  384. title.html( "&#160;" );
  385. }
  386. },
  387. _createButtonPane: function() {
  388. this.uiDialogButtonPane = $( "<div>" );
  389. this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
  390. "ui-widget-content ui-helper-clearfix" );
  391. this.uiButtonSet = $( "<div>" )
  392. .appendTo( this.uiDialogButtonPane );
  393. this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
  394. this._createButtons();
  395. },
  396. _createButtons: function() {
  397. var that = this,
  398. buttons = this.options.buttons;
  399. // If we already have a button pane, remove it
  400. this.uiDialogButtonPane.remove();
  401. this.uiButtonSet.empty();
  402. if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) {
  403. this._removeClass( this.uiDialog, "ui-dialog-buttons" );
  404. return;
  405. }
  406. $.each( buttons, function( name, props ) {
  407. var click, buttonOptions;
  408. props = $.isFunction( props ) ?
  409. { click: props, text: name } :
  410. props;
  411. // Default to a non-submitting button
  412. props = $.extend( { type: "button" }, props );
  413. // Change the context for the click callback to be the main element
  414. click = props.click;
  415. buttonOptions = {
  416. icon: props.icon,
  417. iconPosition: props.iconPosition,
  418. showLabel: props.showLabel,
  419. // Deprecated options
  420. icons: props.icons,
  421. text: props.text
  422. };
  423. delete props.click;
  424. delete props.icon;
  425. delete props.iconPosition;
  426. delete props.showLabel;
  427. // Deprecated options
  428. delete props.icons;
  429. if ( typeof props.text === "boolean" ) {
  430. delete props.text;
  431. }
  432. $( "<button></button>", props )
  433. .button( buttonOptions )
  434. .appendTo( that.uiButtonSet )
  435. .on( "click", function() {
  436. click.apply( that.element[ 0 ], arguments );
  437. } );
  438. } );
  439. this._addClass( this.uiDialog, "ui-dialog-buttons" );
  440. this.uiDialogButtonPane.appendTo( this.uiDialog );
  441. },
  442. _makeDraggable: function() {
  443. var that = this,
  444. options = this.options;
  445. function filteredUi( ui ) {
  446. return {
  447. position: ui.position,
  448. offset: ui.offset
  449. };
  450. }
  451. this.uiDialog.draggable( {
  452. cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
  453. handle: ".ui-dialog-titlebar",
  454. containment: "document",
  455. start: function( event, ui ) {
  456. that._addClass( $( this ), "ui-dialog-dragging" );
  457. that._blockFrames();
  458. that._trigger( "dragStart", event, filteredUi( ui ) );
  459. },
  460. drag: function( event, ui ) {
  461. that._trigger( "drag", event, filteredUi( ui ) );
  462. },
  463. stop: function( event, ui ) {
  464. var left = ui.offset.left - that.document.scrollLeft(),
  465. top = ui.offset.top - that.document.scrollTop();
  466. options.position = {
  467. my: "left top",
  468. at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
  469. "top" + ( top >= 0 ? "+" : "" ) + top,
  470. of: that.window
  471. };
  472. that._removeClass( $( this ), "ui-dialog-dragging" );
  473. that._unblockFrames();
  474. that._trigger( "dragStop", event, filteredUi( ui ) );
  475. }
  476. } );
  477. },
  478. _makeResizable: function() {
  479. var that = this,
  480. options = this.options,
  481. handles = options.resizable,
  482. // .ui-resizable has position: relative defined in the stylesheet
  483. // but dialogs have to use absolute or fixed positioning
  484. position = this.uiDialog.css( "position" ),
  485. resizeHandles = typeof handles === "string" ?
  486. handles :
  487. "n,e,s,w,se,sw,ne,nw";
  488. function filteredUi( ui ) {
  489. return {
  490. originalPosition: ui.originalPosition,
  491. originalSize: ui.originalSize,
  492. position: ui.position,
  493. size: ui.size
  494. };
  495. }
  496. this.uiDialog.resizable( {
  497. cancel: ".ui-dialog-content",
  498. containment: "document",
  499. alsoResize: this.element,
  500. maxWidth: options.maxWidth,
  501. maxHeight: options.maxHeight,
  502. minWidth: options.minWidth,
  503. minHeight: this._minHeight(),
  504. handles: resizeHandles,
  505. start: function( event, ui ) {
  506. that._addClass( $( this ), "ui-dialog-resizing" );
  507. that._blockFrames();
  508. that._trigger( "resizeStart", event, filteredUi( ui ) );
  509. },
  510. resize: function( event, ui ) {
  511. that._trigger( "resize", event, filteredUi( ui ) );
  512. },
  513. stop: function( event, ui ) {
  514. var offset = that.uiDialog.offset(),
  515. left = offset.left - that.document.scrollLeft(),
  516. top = offset.top - that.document.scrollTop();
  517. options.height = that.uiDialog.height();
  518. options.width = that.uiDialog.width();
  519. options.position = {
  520. my: "left top",
  521. at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
  522. "top" + ( top >= 0 ? "+" : "" ) + top,
  523. of: that.window
  524. };
  525. that._removeClass( $( this ), "ui-dialog-resizing" );
  526. that._unblockFrames();
  527. that._trigger( "resizeStop", event, filteredUi( ui ) );
  528. }
  529. } )
  530. .css( "position", position );
  531. },
  532. _trackFocus: function() {
  533. this._on( this.widget(), {
  534. focusin: function( event ) {
  535. this._makeFocusTarget();
  536. this._focusedElement = $( event.target );
  537. }
  538. } );
  539. },
  540. _makeFocusTarget: function() {
  541. this._untrackInstance();
  542. this._trackingInstances().unshift( this );
  543. },
  544. _untrackInstance: function() {
  545. var instances = this._trackingInstances(),
  546. exists = $.inArray( this, instances );
  547. if ( exists !== -1 ) {
  548. instances.splice( exists, 1 );
  549. }
  550. },
  551. _trackingInstances: function() {
  552. var instances = this.document.data( "ui-dialog-instances" );
  553. if ( !instances ) {
  554. instances = [];
  555. this.document.data( "ui-dialog-instances", instances );
  556. }
  557. return instances;
  558. },
  559. _minHeight: function() {
  560. var options = this.options;
  561. return options.height === "auto" ?
  562. options.minHeight :
  563. Math.min( options.minHeight, options.height );
  564. },
  565. _position: function() {
  566. // Need to show the dialog to get the actual offset in the position plugin
  567. var isVisible = this.uiDialog.is( ":visible" );
  568. if ( !isVisible ) {
  569. this.uiDialog.show();
  570. }
  571. this.uiDialog.position( this.options.position );
  572. if ( !isVisible ) {
  573. this.uiDialog.hide();
  574. }
  575. },
  576. _setOptions: function( options ) {
  577. var that = this,
  578. resize = false,
  579. resizableOptions = {};
  580. $.each( options, function( key, value ) {
  581. that._setOption( key, value );
  582. if ( key in that.sizeRelatedOptions ) {
  583. resize = true;
  584. }
  585. if ( key in that.resizableRelatedOptions ) {
  586. resizableOptions[ key ] = value;
  587. }
  588. } );
  589. if ( resize ) {
  590. this._size();
  591. this._position();
  592. }
  593. if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
  594. this.uiDialog.resizable( "option", resizableOptions );
  595. }
  596. },
  597. _setOption: function( key, value ) {
  598. var isDraggable, isResizable,
  599. uiDialog = this.uiDialog;
  600. if ( key === "disabled" ) {
  601. return;
  602. }
  603. this._super( key, value );
  604. if ( key === "appendTo" ) {
  605. this.uiDialog.appendTo( this._appendTo() );
  606. }
  607. if ( key === "buttons" ) {
  608. this._createButtons();
  609. }
  610. if ( key === "closeText" ) {
  611. this.uiDialogTitlebarClose.button( {
  612. // Ensure that we always pass a string
  613. label: $( "<a>" ).text( "" + this.options.closeText ).html()
  614. } );
  615. }
  616. if ( key === "draggable" ) {
  617. isDraggable = uiDialog.is( ":data(ui-draggable)" );
  618. if ( isDraggable && !value ) {
  619. uiDialog.draggable( "destroy" );
  620. }
  621. if ( !isDraggable && value ) {
  622. this._makeDraggable();
  623. }
  624. }
  625. if ( key === "position" ) {
  626. this._position();
  627. }
  628. if ( key === "resizable" ) {
  629. // currently resizable, becoming non-resizable
  630. isResizable = uiDialog.is( ":data(ui-resizable)" );
  631. if ( isResizable && !value ) {
  632. uiDialog.resizable( "destroy" );
  633. }
  634. // Currently resizable, changing handles
  635. if ( isResizable && typeof value === "string" ) {
  636. uiDialog.resizable( "option", "handles", value );
  637. }
  638. // Currently non-resizable, becoming resizable
  639. if ( !isResizable && value !== false ) {
  640. this._makeResizable();
  641. }
  642. }
  643. if ( key === "title" ) {
  644. this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
  645. }
  646. },
  647. _size: function() {
  648. // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
  649. // divs will both have width and height set, so we need to reset them
  650. var nonContentHeight, minContentHeight, maxContentHeight,
  651. options = this.options;
  652. // Reset content sizing
  653. this.element.show().css( {
  654. width: "auto",
  655. minHeight: 0,
  656. maxHeight: "none",
  657. height: 0
  658. } );
  659. if ( options.minWidth > options.width ) {
  660. options.width = options.minWidth;
  661. }
  662. // Reset wrapper sizing
  663. // determine the height of all the non-content elements
  664. nonContentHeight = this.uiDialog.css( {
  665. height: "auto",
  666. width: options.width
  667. } )
  668. .outerHeight();
  669. minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
  670. maxContentHeight = typeof options.maxHeight === "number" ?
  671. Math.max( 0, options.maxHeight - nonContentHeight ) :
  672. "none";
  673. if ( options.height === "auto" ) {
  674. this.element.css( {
  675. minHeight: minContentHeight,
  676. maxHeight: maxContentHeight,
  677. height: "auto"
  678. } );
  679. } else {
  680. this.element.height( Math.max( 0, options.height - nonContentHeight ) );
  681. }
  682. if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
  683. this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
  684. }
  685. },
  686. _blockFrames: function() {
  687. this.iframeBlocks = this.document.find( "iframe" ).map( function() {
  688. var iframe = $( this );
  689. return $( "<div>" )
  690. .css( {
  691. position: "absolute",
  692. width: iframe.outerWidth(),
  693. height: iframe.outerHeight()
  694. } )
  695. .appendTo( iframe.parent() )
  696. .offset( iframe.offset() )[ 0 ];
  697. } );
  698. },
  699. _unblockFrames: function() {
  700. if ( this.iframeBlocks ) {
  701. this.iframeBlocks.remove();
  702. delete this.iframeBlocks;
  703. }
  704. },
  705. _allowInteraction: function( event ) {
  706. if ( $( event.target ).closest( ".ui-dialog" ).length ) {
  707. return true;
  708. }
  709. // TODO: Remove hack when datepicker implements
  710. // the .ui-front logic (#8989)
  711. return !!$( event.target ).closest( ".ui-datepicker" ).length;
  712. },
  713. _createOverlay: function() {
  714. if ( !this.options.modal ) {
  715. return;
  716. }
  717. // We use a delay in case the overlay is created from an
  718. // event that we're going to be cancelling (#2804)
  719. var isOpening = true;
  720. this._delay( function() {
  721. isOpening = false;
  722. } );
  723. if ( !this.document.data( "ui-dialog-overlays" ) ) {
  724. // Prevent use of anchors and inputs
  725. // Using _on() for an event handler shared across many instances is
  726. // safe because the dialogs stack and must be closed in reverse order
  727. this._on( this.document, {
  728. focusin: function( event ) {
  729. if ( isOpening ) {
  730. return;
  731. }
  732. if ( !this._allowInteraction( event ) ) {
  733. event.preventDefault();
  734. this._trackingInstances()[ 0 ]._focusTabbable();
  735. }
  736. }
  737. } );
  738. }
  739. this.overlay = $( "<div>" )
  740. .appendTo( this._appendTo() );
  741. this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
  742. this._on( this.overlay, {
  743. mousedown: "_keepFocus"
  744. } );
  745. this.document.data( "ui-dialog-overlays",
  746. ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
  747. },
  748. _destroyOverlay: function() {
  749. if ( !this.options.modal ) {
  750. return;
  751. }
  752. if ( this.overlay ) {
  753. var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
  754. if ( !overlays ) {
  755. this._off( this.document, "focusin" );
  756. this.document.removeData( "ui-dialog-overlays" );
  757. } else {
  758. this.document.data( "ui-dialog-overlays", overlays );
  759. }
  760. this.overlay.remove();
  761. this.overlay = null;
  762. }
  763. }
  764. } );
  765. // DEPRECATED
  766. // TODO: switch return back to widget declaration at top of file when this is removed
  767. if ( $.uiBackCompat !== false ) {
  768. // Backcompat for dialogClass option
  769. $.widget( "ui.dialog", $.ui.dialog, {
  770. options: {
  771. dialogClass: ""
  772. },
  773. _createWrapper: function() {
  774. this._super();
  775. this.uiDialog.addClass( this.options.dialogClass );
  776. },
  777. _setOption: function( key, value ) {
  778. if ( key === "dialogClass" ) {
  779. this.uiDialog
  780. .removeClass( this.options.dialogClass )
  781. .addClass( value );
  782. }
  783. this._superApply( arguments );
  784. }
  785. } );
  786. }
  787. return $.ui.dialog;
  788. } ) );