/*
* jQuery UI Dialog @VERSION
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Dialog
*
* Depends:
* jquery.ui.core.js
* jquery.ui.widget.js
* jquery.ui.button.js
* jquery.ui.draggable.js
* jquery.ui.mouse.js
* jquery.ui.position.js
* jquery.ui.resizable.js
*/
(function( $, undefined ) {
var uiDialogClasses = "ui-dialog ui-widget ui-widget-content ui-corner-all ",
sizeRelatedOptions = {
buttons: true,
height: true,
maxHeight: true,
maxWidth: true,
minHeight: true,
minWidth: true,
width: true
},
resizableRelatedOptions = {
maxHeight: true,
maxWidth: true,
minHeight: true,
minWidth: true
};
$.widget("ui.dialog", {
version: "@VERSION",
options: {
autoOpen: true,
buttons: {},
closeOnEscape: true,
closeText: "close",
dialogClass: "",
draggable: true,
hide: null,
height: "auto",
maxHeight: false,
maxWidth: false,
minHeight: 150,
minWidth: 150,
modal: false,
position: {
my: "center",
at: "center",
of: window,
collision: "fit",
// ensure that the titlebar is never outside the document
using: function( pos ) {
var topOffset = $( this ).css( pos ).offset().top;
if ( topOffset < 0 ) {
$( this ).css( "top", pos.top - topOffset );
}
}
},
resizable: true,
show: null,
stack: true,
title: "",
width: 300,
zIndex: 1000
},
_create: function() {
this.originalTitle = this.element.attr( "title" );
// #5742 - .attr() might return a DOMElement
if ( typeof this.originalTitle !== "string" ) {
this.originalTitle = "";
}
this.options.title = this.options.title || this.originalTitle;
var self = this,
options = self.options,
title = options.title || " ",
titleId = $.ui.dialog.getTitleId( self.element ),
uiDialog = ( self.uiDialog = $( "
" ) )
.addClass( uiDialogClasses + options.dialogClass )
.css({
display: "none",
outline: 0, // TODO: move to stylesheet
zIndex: options.zIndex
})
// setting tabIndex makes the div focusable
.attr( "tabIndex", -1)
.keydown(function( event ) {
if ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
event.keyCode === $.ui.keyCode.ESCAPE ) {
self.close( event );
event.preventDefault();
}
})
.attr({
role: "dialog",
"aria-labelledby": titleId
})
.mousedown(function( event ) {
self.moveToTop( false, event );
})
.appendTo( "body" ),
uiDialogContent = self.element
.show()
.removeAttr( "title" )
.addClass( "ui-dialog-content ui-widget-content" )
.appendTo( uiDialog ),
uiDialogTitlebar = ( self.uiDialogTitlebar = $( "
" ) )
.addClass( "ui-dialog-titlebar ui-widget-header " +
"ui-corner-all ui-helper-clearfix" )
.prependTo( uiDialog ),
uiDialogTitlebarClose = $( "
" )
.addClass( "ui-dialog-titlebar-close ui-corner-all" )
.attr( "role", "button" )
.click(function( event ) {
event.preventDefault();
self.close( event );
})
.appendTo( uiDialogTitlebar ),
uiDialogTitlebarCloseText = ( self.uiDialogTitlebarCloseText = $( "
" ) )
.addClass( "ui-icon ui-icon-closethick" )
.text( options.closeText )
.appendTo( uiDialogTitlebarClose ),
uiDialogTitle = $( "" )
.addClass( "ui-dialog-title" )
.attr( "id", titleId )
.html( title )
.prependTo( uiDialogTitlebar );
uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection();
this._hoverable( uiDialogTitlebarClose );
this._focusable( uiDialogTitlebarClose );
if ( options.draggable && $.fn.draggable ) {
self._makeDraggable();
}
if ( options.resizable && $.fn.resizable ) {
self._makeResizable();
}
self._createButtons( options.buttons );
self._isOpen = false;
if ( $.fn.bgiframe ) {
uiDialog.bgiframe();
}
},
_init: function() {
if ( this.options.autoOpen ) {
this.open();
}
},
_destroy: function() {
var self = this;
if ( self.overlay ) {
self.overlay.destroy();
}
self.uiDialog.hide();
self.element
.removeClass( "ui-dialog-content ui-widget-content" )
.hide()
.appendTo( "body" );
self.uiDialog.remove();
if ( self.originalTitle ) {
self.element.attr( "title", self.originalTitle );
}
},
widget: function() {
return this.uiDialog;
},
close: function( event ) {
if ( !this._isOpen ) {
return self;
}
var self = this,
maxZ, thisZ;
if ( false === self._trigger( "beforeClose", event ) ) {
return;
}
self._isOpen = false;
if ( self.overlay ) {
self.overlay.destroy();
}
self.uiDialog.unbind( "keypress.ui-dialog" );
if ( self.options.hide ) {
self.uiDialog.hide( self.options.hide, function() {
self._trigger( "close", event );
});
} else {
self.uiDialog.hide();
self._trigger( "close", event );
}
$.ui.dialog.overlay.resize();
// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
if ( self.options.modal ) {
maxZ = 0;
$( ".ui-dialog" ).each(function() {
if ( this !== self.uiDialog[0] ) {
thisZ = $( this ).css( "z-index" );
if ( !isNaN( thisZ ) ) {
maxZ = Math.max( maxZ, thisZ );
}
}
});
$.ui.dialog.maxZ = maxZ;
}
return self;
},
isOpen: function() {
return this._isOpen;
},
// the force parameter allows us to move modal dialogs to their correct
// position on open
moveToTop: function( force, event ) {
var self = this,
options = self.options,
saveScroll;
if ( ( options.modal && !force ) ||
( !options.stack && !options.modal ) ) {
return self._trigger( "focus", event );
}
if ( options.zIndex > $.ui.dialog.maxZ ) {
$.ui.dialog.maxZ = options.zIndex;
}
if ( self.overlay ) {
$.ui.dialog.maxZ += 1;
$.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ;
self.overlay.$el.css( "z-index", $.ui.dialog.overlay.maxZ );
}
// Save and then restore scroll
// Opera 9.5+ resets when parent z-index is changed.
// http://bugs.jqueryui.com/ticket/3193
saveScroll = {
scrollTop: self.element.scrollTop(),
scrollLeft: self.element.scrollLeft()
};
$.ui.dialog.maxZ += 1;
self.uiDialog.css( "z-index", $.ui.dialog.maxZ );
self.element.attr( saveScroll );
self._trigger( "focus", event );
return self;
},
open: function() {
if ( this._isOpen ) {
return;
}
var self = this,
options = self.options,
uiDialog = self.uiDialog;
self._size();
self._position( options.position );
uiDialog.show( options.show );
self.overlay = options.modal ? new $.ui.dialog.overlay( self ) : null;
self.moveToTop( true );
// prevent tabbing out of modal dialogs
if ( options.modal ) {
uiDialog.bind( "keydown.ui-dialog", function( event ) {
if ( event.keyCode !== $.ui.keyCode.TAB ) {
return;
}
var tabbables = $( ":tabbable", this ),
first = tabbables.filter( ":first" ),
last = tabbables.filter( ":last" );
if ( event.target === last[0] && !event.shiftKey ) {
first.focus( 1 );
return false;
} else if ( event.target === first[0] && event.shiftKey ) {
last.focus( 1 );
return false;
}
});
}
// set focus to the first tabbable element in the content area or the first button
// if there are no tabbable elements, set focus on the dialog itself
var hasFocus = self.element.find( ":tabbable" );
if ( !hasFocus.length ) {
hasFocus = uiDialog.find( ".ui-dialog-buttonpane :tabbable" );
if ( !hasFocus.length ) {
hasFocus = uiDialog;
}
}
hasFocus.eq( 0 ).focus();
self._isOpen = true;
self._trigger( "open" );
return self;
},
_createButtons: function( buttons ) {
var self = this,
hasButtons = false;
// if we already have a button pane, remove it
self.uiDialog.find( ".ui-dialog-buttonpane" ).remove();
if ( typeof buttons === "object" && buttons !== null ) {
$.each( buttons, function() {
return !(hasButtons = true);
});
}
if ( hasButtons ) {
var uiDialogButtonPane = $( "" )
.addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ),
uiButtonSet = $( "
" )
.addClass( "ui-dialog-buttonset" )
.appendTo( uiDialogButtonPane );
$.each( buttons, function( name, props ) {
props = $.isFunction( props ) ?
{ click: props, text: name } :
props;
var button = $( "