diff options
Diffstat (limited to 'ui/jquery.ui.dialog.js')
-rw-r--r-- | ui/jquery.ui.dialog.js | 158 |
1 files changed, 96 insertions, 62 deletions
diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index c5bd42ab5..7f90908bd 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -86,25 +86,25 @@ $.widget( "ui.dialog", { _create: function() { this.originalCss = { - display: this.element[0].style.display, - width: this.element[0].style.width, - minHeight: this.element[0].style.minHeight, - maxHeight: this.element[0].style.maxHeight, - height: this.element[0].style.height + display: this.element[ 0 ].style.display, + width: this.element[ 0 ].style.width, + minHeight: this.element[ 0 ].style.minHeight, + maxHeight: this.element[ 0 ].style.maxHeight, + height: this.element[ 0 ].style.height }; this.originalPosition = { parent: this.element.parent(), index: this.element.parent().children().index( this.element ) }; - this.originalTitle = this.element.attr("title"); + this.originalTitle = this.element.attr( "title" ); this.options.title = this.options.title || this.originalTitle; this._createWrapper(); this.element .show() - .removeAttr("title") - .addClass("ui-dialog-content ui-widget-content") + .removeAttr( "title" ) + .addClass( "ui-dialog-content ui-widget-content" ) .appendTo( this.uiDialog ); this._createTitlebar(); @@ -118,6 +118,8 @@ $.widget( "ui.dialog", { } this._isOpen = false; + + this._trackFocus(); }, _init: function() { @@ -142,7 +144,7 @@ $.widget( "ui.dialog", { this.element .removeUniqueId() - .removeClass("ui-dialog-content ui-widget-content") + .removeClass( "ui-dialog-content ui-widget-content" ) .css( this.originalCss ) // Without detaching first, the following becomes really slow .detach(); @@ -155,7 +157,7 @@ $.widget( "ui.dialog", { next = originalPosition.parent.children().eq( originalPosition.index ); // Don't try to place the dialog next to itself (#8613) - if ( next.length && next[0] !== this.element[0] ) { + if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { next.before( this.element ); } else { originalPosition.parent.append( this.element ); @@ -178,9 +180,11 @@ $.widget( "ui.dialog", { } this._isOpen = false; + this._focusedElement = null; this._destroyOverlay(); + this._untrackInstance(); - if ( !this.opener.filter(":focusable").focus().length ) { + if ( !this.opener.filter( ":focusable" ).focus().length ) { // support: IE9 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> @@ -240,7 +244,7 @@ $.widget( "ui.dialog", { } this._isOpen = true; - this.opener = $( this.document[0].activeElement ); + this.opener = $( this.document[ 0 ].activeElement ); this._size(); this._position(); @@ -248,28 +252,32 @@ $.widget( "ui.dialog", { this._moveToTop( null, true ); this._show( this.uiDialog, this.options.show, function() { that._focusTabbable(); - that._trigger("focus"); + that._trigger( "focus" ); }); - this._trigger("open"); + this._trigger( "open" ); }, _focusTabbable: function() { // Set focus to the first match: - // 1. First element inside the dialog matching [autofocus] - // 2. Tabbable element inside the content element - // 3. Tabbable element inside the buttonpane - // 4. The close button - // 5. The dialog itself - var hasFocus = this.element.find("[autofocus]"); + // 1. An element that was focused previously + // 2. First element inside the dialog matching [autofocus] + // 3. Tabbable element inside the content element + // 4. Tabbable element inside the buttonpane + // 5. The close button + // 6. The dialog itself + var hasFocus = this._focusedElement; + if ( !hasFocus ) { + hasFocus = this.element.find( "[autofocus]" ); + } if ( !hasFocus.length ) { - hasFocus = this.element.find(":tabbable"); + hasFocus = this.element.find( ":tabbable" ); } if ( !hasFocus.length ) { - hasFocus = this.uiDialogButtonPane.find(":tabbable"); + hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); } if ( !hasFocus.length ) { - hasFocus = this.uiDialogTitlebarClose.filter(":tabbable"); + hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" ); } if ( !hasFocus.length ) { hasFocus = this.uiDialog; @@ -319,9 +327,9 @@ $.widget( "ui.dialog", { if ( event.keyCode !== $.ui.keyCode.TAB ) { return; } - var tabbables = this.uiDialog.find(":tabbable"), - first = tabbables.filter(":first"), - last = tabbables.filter(":last"); + var tabbables = this.uiDialog.find( ":tabbable" ), + first = tabbables.filter( ":first" ), + last = tabbables.filter( ":last" ); if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { first.focus( 1 ); @@ -341,9 +349,9 @@ $.widget( "ui.dialog", { // We assume that any existing aria-describedby attribute means // that the dialog content is marked up properly // otherwise we brute force the content as the description - if ( !this.element.find("[aria-describedby]").length ) { + if ( !this.element.find( "[aria-describedby]" ).length ) { this.uiDialog.attr({ - "aria-describedby": this.element.uniqueId().attr("id") + "aria-describedby": this.element.uniqueId().attr( "id" ) }); } }, @@ -351,15 +359,15 @@ $.widget( "ui.dialog", { _createTitlebar: function() { var uiDialogTitle; - this.uiDialogTitlebar = $("<div>") - .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix") + this.uiDialogTitlebar = $( "<div>" ) + .addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" ) .prependTo( this.uiDialog ); this._on( this.uiDialogTitlebar, { mousedown: function( event ) { // Don't prevent click on close button (#8838) // Focusing a dialog that is partially scrolled out of view // causes the browser to scroll it into view, preventing the click event - if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) { + if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) { // Dialog isn't getting focus when dragging (#8063) this.uiDialog.focus(); } @@ -377,7 +385,7 @@ $.widget( "ui.dialog", { }, text: false }) - .addClass("ui-dialog-titlebar-close") + .addClass( "ui-dialog-titlebar-close" ) .appendTo( this.uiDialogTitlebar ); this._on( this.uiDialogTitlebarClose, { click: function( event ) { @@ -386,30 +394,30 @@ $.widget( "ui.dialog", { } }); - uiDialogTitle = $("<span>") + uiDialogTitle = $( "<span>" ) .uniqueId() - .addClass("ui-dialog-title") + .addClass( "ui-dialog-title" ) .prependTo( this.uiDialogTitlebar ); this._title( uiDialogTitle ); this.uiDialog.attr({ - "aria-labelledby": uiDialogTitle.attr("id") + "aria-labelledby": uiDialogTitle.attr( "id" ) }); }, _title: function( title ) { if ( !this.options.title ) { - title.html(" "); + title.html( " " ); } title.text( this.options.title ); }, _createButtonPane: function() { - this.uiDialogButtonPane = $("<div>") - .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"); + this.uiDialogButtonPane = $( "<div>" ) + .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); - this.uiButtonSet = $("<div>") - .addClass("ui-dialog-buttonset") + this.uiButtonSet = $( "<div>" ) + .addClass( "ui-dialog-buttonset" ) .appendTo( this.uiDialogButtonPane ); this._createButtons(); @@ -424,7 +432,7 @@ $.widget( "ui.dialog", { this.uiButtonSet.empty(); if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { - this.uiDialog.removeClass("ui-dialog-buttons"); + this.uiDialog.removeClass( "ui-dialog-buttons" ); return; } @@ -438,7 +446,7 @@ $.widget( "ui.dialog", { // Change the context for the click callback to be the main element click = props.click; props.click = function() { - click.apply( that.element[0], arguments ); + click.apply( that.element[ 0 ], arguments ); }; buttonOptions = { icons: props.icons, @@ -450,7 +458,7 @@ $.widget( "ui.dialog", { .button( buttonOptions ) .appendTo( that.uiButtonSet ); }); - this.uiDialog.addClass("ui-dialog-buttons"); + this.uiDialog.addClass( "ui-dialog-buttons" ); this.uiDialogButtonPane.appendTo( this.uiDialog ); }, @@ -470,7 +478,7 @@ $.widget( "ui.dialog", { handle: ".ui-dialog-titlebar", containment: "document", start: function( event, ui ) { - $( this ).addClass("ui-dialog-dragging"); + $( this ).addClass( "ui-dialog-dragging" ); that._blockFrames(); that._trigger( "dragStart", event, filteredUi( ui ) ); }, @@ -487,7 +495,7 @@ $.widget( "ui.dialog", { "top" + (top >= 0 ? "+" : "") + top, of: that.window }; - $( this ).removeClass("ui-dialog-dragging"); + $( this ).removeClass( "ui-dialog-dragging" ); that._unblockFrames(); that._trigger( "dragStop", event, filteredUi( ui ) ); } @@ -524,7 +532,7 @@ $.widget( "ui.dialog", { minHeight: this._minHeight(), handles: resizeHandles, start: function( event, ui ) { - $( this ).addClass("ui-dialog-resizing"); + $( this ).addClass( "ui-dialog-resizing" ); that._blockFrames(); that._trigger( "resizeStart", event, filteredUi( ui ) ); }, @@ -544,7 +552,7 @@ $.widget( "ui.dialog", { "top" + (top >= 0 ? "+" : "") + top, of: that.window }; - $( this ).removeClass("ui-dialog-resizing"); + $( this ).removeClass( "ui-dialog-resizing" ); that._unblockFrames(); that._trigger( "resizeStop", event, filteredUi( ui ) ); } @@ -552,6 +560,33 @@ $.widget( "ui.dialog", { .css( "position", position ); }, + _trackFocus: function() { + this._on( this.widget(), { + "focusin": function( event ) { + this._untrackInstance(); + this._trackingInstances().unshift( this ); + this._focusedElement = $( event.target ); + } + }); + }, + + _untrackInstance: function() { + var instances = this._trackingInstances(), + exists = $.inArray( this, instances ); + if ( exists !== -1 ) { + instances.splice( exists, 1 ); + } + }, + + _trackingInstances: function() { + var instances = this.document.data( "ui-dialog-instances" ); + if ( !instances ) { + instances = []; + this.document.data( "ui-dialog-instances", instances ); + } + return instances; + }, + _minHeight: function() { var options = this.options; @@ -562,7 +597,7 @@ $.widget( "ui.dialog", { _position: function() { // Need to show the dialog to get the actual offset in the position plugin - var isVisible = this.uiDialog.is(":visible"); + var isVisible = this.uiDialog.is( ":visible" ); if ( !isVisible ) { this.uiDialog.show(); } @@ -592,7 +627,7 @@ $.widget( "ui.dialog", { this._size(); this._position(); } - if ( this.uiDialog.is(":data(ui-resizable)") ) { + if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { this.uiDialog.resizable( "option", resizableOptions ); } }, @@ -629,9 +664,9 @@ $.widget( "ui.dialog", { } if ( key === "draggable" ) { - isDraggable = uiDialog.is(":data(ui-draggable)"); + isDraggable = uiDialog.is( ":data(ui-draggable)" ); if ( isDraggable && !value ) { - uiDialog.draggable("destroy"); + uiDialog.draggable( "destroy" ); } if ( !isDraggable && value ) { @@ -645,9 +680,9 @@ $.widget( "ui.dialog", { if ( key === "resizable" ) { // currently resizable, becoming non-resizable - isResizable = uiDialog.is(":data(ui-resizable)"); + isResizable = uiDialog.is( ":data(ui-resizable)" ); if ( isResizable && !value ) { - uiDialog.resizable("destroy"); + uiDialog.resizable( "destroy" ); } // currently resizable, changing handles @@ -662,7 +697,7 @@ $.widget( "ui.dialog", { } if ( key === "title" ) { - this._title( this.uiDialogTitlebar.find(".ui-dialog-title") ); + this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) ); } }, @@ -706,7 +741,7 @@ $.widget( "ui.dialog", { this.element.height( Math.max( 0, options.height - nonContentHeight ) ); } - if (this.uiDialog.is(":data(ui-resizable)") ) { + if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); } }, @@ -734,13 +769,13 @@ $.widget( "ui.dialog", { }, _allowInteraction: function( event ) { - if ( $( event.target ).closest(".ui-dialog").length ) { + if ( $( event.target ).closest( ".ui-dialog" ).length ) { return true; } // TODO: Remove hack when datepicker implements // the .ui-front logic (#8989) - return !!$( event.target ).closest(".ui-datepicker").length; + return !!$( event.target ).closest( ".ui-datepicker" ).length; }, _createOverlay: function() { @@ -768,15 +803,14 @@ $.widget( "ui.dialog", { if ( !this._allowInteraction( event ) ) { event.preventDefault(); - this.document.find( ".ui-dialog:visible:last .ui-dialog-content" ) - .data( this.widgetFullName )._focusTabbable(); + this._trackingInstances()[ 0 ]._focusTabbable(); } } }); } - this.overlay = $("<div>") - .addClass("ui-widget-overlay ui-front") + this.overlay = $( "<div>" ) + .addClass( "ui-widget-overlay ui-front" ) .appendTo( this._appendTo() ); this._on( this.overlay, { mousedown: "_keepFocus" @@ -807,4 +841,4 @@ $.widget( "ui.dialog", { } }); -}( jQuery ) ); +}( jQuery )); |