balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

dialog.js (23055B)


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