2 * jQuery UI Dialog 1.7.1
4 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT (MIT-LICENSE.txt)
6 * and GPL (GPL-LICENSE.txt) licenses.
8 * http://docs.jquery.com/UI/Dialog
18 dragStart
: "start.draggable",
19 drag
: "drag.draggable",
20 dragStop
: "stop.draggable",
21 maxHeight
: "maxHeight.resizable",
22 minHeight
: "minHeight.resizable",
23 maxWidth
: "maxWidth.resizable",
24 minWidth
: "minWidth.resizable",
25 resizeStart
: "start.resizable",
26 resize
: "drag.resizable",
27 resizeStop
: "stop.resizable"
33 'ui-widget-content ' +
36 $.widget("ui.dialog", {
39 this.originalTitle
= this.element
.attr('title');
42 options
= this.options
,
44 title
= options
.title
|| this.originalTitle
|| ' ',
45 titleId
= $.ui
.dialog
.getTitleId(this.element
),
47 uiDialog
= (this.uiDialog
= $('<div/>'))
48 .appendTo(document
.body
)
50 .addClass(uiDialogClasses
+ options
.dialogClass
)
54 zIndex
: options
.zIndex
56 // setting tabIndex makes the div focusable
57 // setting outline to 0 prevents a border on focus in Mozilla
58 .attr('tabIndex', -1).css('outline', 0).keydown(function(event
) {
59 (options
.closeOnEscape
&& event
.keyCode
60 && event
.keyCode
== $.ui
.keyCode
.ESCAPE
&& self
.close(event
));
64 'aria-labelledby': titleId
66 .mousedown(function(event
) {
67 self
.moveToTop(false, event
);
70 uiDialogContent
= this.element
74 'ui-dialog-content ' +
78 uiDialogTitlebar
= (this.uiDialogTitlebar
= $('<div></div>'))
80 'ui-dialog-titlebar ' +
87 uiDialogTitlebarClose
= $('<a href="#"/>')
89 'ui-dialog-titlebar-close ' +
92 .attr('role', 'button')
95 uiDialogTitlebarClose
.addClass('ui-state-hover');
98 uiDialogTitlebarClose
.removeClass('ui-state-hover');
102 uiDialogTitlebarClose
.addClass('ui-state-focus');
105 uiDialogTitlebarClose
.removeClass('ui-state-focus');
107 .mousedown(function(ev
) {
108 ev
.stopPropagation();
110 .click(function(event
) {
114 .appendTo(uiDialogTitlebar
),
116 uiDialogTitlebarCloseText
= (this.uiDialogTitlebarCloseText
= $('<span/>'))
121 .text(options
.closeText
)
122 .appendTo(uiDialogTitlebarClose
),
124 uiDialogTitle
= $('<span/>')
125 .addClass('ui-dialog-title')
128 .prependTo(uiDialogTitlebar
);
130 uiDialogTitlebar
.find("*").add(uiDialogTitlebar
).disableSelection();
132 (options
.draggable
&& $.fn
.draggable
&& this._makeDraggable());
133 (options
.resizable
&& $.fn
.resizable
&& this._makeResizable());
135 this._createButtons(options
.buttons
);
136 this._isOpen
= false;
138 (options
.bgiframe
&& $.fn
.bgiframe
&& uiDialog
.bgiframe());
139 (options
.autoOpen
&& this.open());
143 destroy: function() {
144 (this.overlay
&& this.overlay
.destroy());
145 this.uiDialog
.hide();
148 .removeData('dialog')
149 .removeClass('ui-dialog-content ui-widget-content')
150 .hide().appendTo('body');
151 this.uiDialog
.remove();
153 (this.originalTitle
&& this.element
.attr('title', this.originalTitle
));
156 close: function(event
) {
159 if (false === self
._trigger('beforeclose', event
)) {
163 (self
.overlay
&& self
.overlay
.destroy());
164 self
.uiDialog
.unbind('keypress.ui-dialog');
167 ? self
.uiDialog
.hide(self
.options
.hide
, function() {
168 self
._trigger('close', event
);
170 : self
.uiDialog
.hide() && self
._trigger('close', event
));
172 $.ui
.dialog
.overlay
.resize();
174 self
._isOpen
= false;
181 // the force parameter allows us to move modal dialogs to their correct
183 moveToTop: function(force
, event
) {
185 if ((this.options
.modal
&& !force
)
186 || (!this.options
.stack
&& !this.options
.modal
)) {
187 return this._trigger('focus', event
);
190 if (this.options
.zIndex
> $.ui
.dialog
.maxZ
) {
191 $.ui
.dialog
.maxZ
= this.options
.zIndex
;
193 (this.overlay
&& this.overlay
.$el
.css('z-index', $.ui
.dialog
.overlay
.maxZ
= ++$.ui
.dialog
.maxZ
));
195 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
196 // http://ui.jquery.com/bugs/ticket/3193
197 var saveScroll
= { scrollTop
: this.element
.attr('scrollTop'), scrollLeft
: this.element
.attr('scrollLeft') };
198 this.uiDialog
.css('z-index', ++$.ui
.dialog
.maxZ
);
199 this.element
.attr(saveScroll
);
200 this._trigger('focus', event
);
204 if (this._isOpen
) { return; }
206 var options
= this.options
,
207 uiDialog
= this.uiDialog
;
209 this.overlay
= options
.modal
? new $.ui
.dialog
.overlay(this) : null;
210 (uiDialog
.next().length
&& uiDialog
.appendTo('body'));
212 this._position(options
.position
);
213 uiDialog
.show(options
.show
);
214 this.moveToTop(true);
216 // prevent tabbing out of modal dialogs
217 (options
.modal
&& uiDialog
.bind('keypress.ui-dialog', function(event
) {
218 if (event
.keyCode
!= $.ui
.keyCode
.TAB
) {
222 var tabbables
= $(':tabbable', this),
223 first
= tabbables
.filter(':first')[0],
224 last
= tabbables
.filter(':last')[0];
226 if (event
.target
== last
&& !event
.shiftKey
) {
227 setTimeout(function() {
230 } else if (event
.target
== first
&& event
.shiftKey
) {
231 setTimeout(function() {
237 // set focus to the first tabbable element in the content area or the first button
238 // if there are no tabbable elements, set focus on the dialog itself
240 .add(uiDialog
.find('.ui-dialog-content :tabbable:first'))
241 .add(uiDialog
.find('.ui-dialog-buttonpane :tabbable:first'))
246 this._trigger('open');
250 _createButtons: function(buttons
) {
253 uiDialogButtonPane
= $('<div></div>')
255 'ui-dialog-buttonpane ' +
256 'ui-widget-content ' +
260 // if we already have a button pane, remove it
261 this.uiDialog
.find('.ui-dialog-buttonpane').remove();
263 (typeof buttons
== 'object' && buttons
!== null &&
264 $.each(buttons
, function() { return !(hasButtons
= true); }));
266 $.each(buttons
, function(name
, fn
) {
267 $('<button type="button"></button>')
269 'ui-state-default ' +
273 .click(function() { fn
.apply(self
.element
[0], arguments
); })
276 $(this).addClass('ui-state-hover');
279 $(this).removeClass('ui-state-hover');
283 $(this).addClass('ui-state-focus');
286 $(this).removeClass('ui-state-focus');
288 .appendTo(uiDialogButtonPane
);
290 uiDialogButtonPane
.appendTo(this.uiDialog
);
294 _makeDraggable: function() {
296 options
= this.options
,
299 this.uiDialog
.draggable({
300 cancel
: '.ui-dialog-content',
301 handle
: '.ui-dialog-titlebar',
302 containment
: 'document',
304 heightBeforeDrag
= options
.height
;
305 $(this).height($(this).height()).addClass("ui-dialog-dragging");
306 (options
.dragStart
&& options
.dragStart
.apply(self
.element
[0], arguments
));
309 (options
.drag
&& options
.drag
.apply(self
.element
[0], arguments
));
312 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag
);
313 (options
.dragStop
&& options
.dragStop
.apply(self
.element
[0], arguments
));
314 $.ui
.dialog
.overlay
.resize();
319 _makeResizable: function(handles
) {
320 handles
= (handles
=== undefined ? this.options
.resizable
: handles
);
322 options
= this.options
,
323 resizeHandles
= typeof handles
== 'string'
325 : 'n,e,s,w,se,sw,ne,nw';
327 this.uiDialog
.resizable({
328 cancel
: '.ui-dialog-content',
329 alsoResize
: this.element
,
330 maxWidth
: options
.maxWidth
,
331 maxHeight
: options
.maxHeight
,
332 minWidth
: options
.minWidth
,
333 minHeight
: options
.minHeight
,
335 $(this).addClass("ui-dialog-resizing");
336 (options
.resizeStart
&& options
.resizeStart
.apply(self
.element
[0], arguments
));
339 (options
.resize
&& options
.resize
.apply(self
.element
[0], arguments
));
341 handles
: resizeHandles
,
343 $(this).removeClass("ui-dialog-resizing");
344 options
.height
= $(this).height();
345 options
.width
= $(this).width();
346 (options
.resizeStop
&& options
.resizeStop
.apply(self
.element
[0], arguments
));
347 $.ui
.dialog
.overlay
.resize();
350 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
353 _position: function(pos
) {
354 var wnd
= $(window
), doc
= $(document
),
355 pTop
= doc
.scrollTop(), pLeft
= doc
.scrollLeft(),
358 if ($.inArray(pos
, ['center','top','right','bottom','left']) >= 0) {
360 pos
== 'right' || pos
== 'left' ? pos
: 'center',
361 pos
== 'top' || pos
== 'bottom' ? pos
: 'middle'
364 if (pos
.constructor != Array
) {
365 pos
= ['center', 'middle'];
367 if (pos
[0].constructor == Number
) {
375 pLeft
+= wnd
.width() - this.uiDialog
.outerWidth();
379 pLeft
+= (wnd
.width() - this.uiDialog
.outerWidth()) / 2;
382 if (pos
[1].constructor == Number
) {
390 pTop
+= wnd
.height() - this.uiDialog
.outerHeight();
394 pTop
+= (wnd
.height() - this.uiDialog
.outerHeight()) / 2;
398 // prevent the dialog from being too high (make sure the titlebar
400 pTop
= Math
.max(pTop
, minTop
);
401 this.uiDialog
.css({top
: pTop
, left
: pLeft
});
404 _setData: function(key
, value
){
405 (setDataSwitch
[key
] && this.uiDialog
.data(setDataSwitch
[key
], value
));
408 this._createButtons(value
);
411 this.uiDialogTitlebarCloseText
.text(value
);
415 .removeClass(this.options
.dialogClass
)
416 .addClass(uiDialogClasses
+ value
);
420 ? this._makeDraggable()
421 : this.uiDialog
.draggable('destroy'));
424 this.uiDialog
.height(value
);
427 this._position(value
);
430 var uiDialog
= this.uiDialog
,
431 isResizable
= this.uiDialog
.is(':data(resizable)');
433 // currently resizable, becoming non-resizable
434 (isResizable
&& !value
&& uiDialog
.resizable('destroy'));
436 // currently resizable, changing handles
437 (isResizable
&& typeof value
== 'string' &&
438 uiDialog
.resizable('option', 'handles', value
));
440 // currently non-resizable, becoming resizable
441 (isResizable
|| this._makeResizable(value
));
444 $(".ui-dialog-title", this.uiDialogTitlebar
).html(value
|| ' ');
447 this.uiDialog
.width(value
);
451 $.widget
.prototype._setData
.apply(this, arguments
);
455 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
456 * divs will both have width and height set, so we need to reset them
458 var options
= this.options
;
460 // reset content sizing
467 // reset wrapper sizing
468 // determine the height of all the non-content elements
469 var nonContentHeight
= this.uiDialog
.css({
477 minHeight
: Math
.max(options
.minHeight
- nonContentHeight
, 0),
478 height
: options
.height
== 'auto'
480 : Math
.max(options
.height
- nonContentHeight
, 0)
485 $.extend($.ui
.dialog
, {
516 getTitleId: function($el
) {
517 return 'ui-dialog-title-' + ($el
.attr('id') || ++this.uuid
);
520 overlay: function(dialog
) {
521 this.$el
= $.ui
.dialog
.overlay
.create(dialog
);
525 $.extend($.ui
.dialog
.overlay
, {
528 events
: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
529 function(event
) { return event
+ '.dialog-overlay'; }).join(' '),
530 create: function(dialog
) {
531 if (this.instances
.length
=== 0) {
532 // prevent use of anchors and inputs
533 // we use a setTimeout in case the overlay is created from an
534 // event that we're going to be cancelling (see #2804)
535 setTimeout(function() {
536 $(document
).bind($.ui
.dialog
.overlay
.events
, function(event
) {
537 var dialogZ
= $(event
.target
).parents('.ui-dialog').css('zIndex') || 0;
538 return (dialogZ
> $.ui
.dialog
.overlay
.maxZ
);
542 // allow closing by pressing the escape key
543 $(document
).bind('keydown.dialog-overlay', function(event
) {
544 (dialog
.options
.closeOnEscape
&& event
.keyCode
545 && event
.keyCode
== $.ui
.keyCode
.ESCAPE
&& dialog
.close(event
));
548 // handle window resize
549 $(window
).bind('resize.dialog-overlay', $.ui
.dialog
.overlay
.resize
);
552 var $el
= $('<div></div>').appendTo(document
.body
)
553 .addClass('ui-widget-overlay').css({
555 height
: this.height()
558 (dialog
.options
.bgiframe
&& $.fn
.bgiframe
&& $el
.bgiframe());
560 this.instances
.push($el
);
564 destroy: function($el
) {
565 this.instances
.splice($.inArray(this.instances
, $el
), 1);
567 if (this.instances
.length
=== 0) {
568 $([document
, window
]).unbind('.dialog-overlay');
576 if ($.browser
.msie
&& $.browser
.version
< 7) {
577 var scrollHeight
= Math
.max(
578 document
.documentElement
.scrollHeight
,
579 document
.body
.scrollHeight
581 var offsetHeight
= Math
.max(
582 document
.documentElement
.offsetHeight
,
583 document
.body
.offsetHeight
586 if (scrollHeight
< offsetHeight
) {
587 return $(window
).height() + 'px';
589 return scrollHeight
+ 'px';
591 // handle "good" browsers
593 return $(document
).height() + 'px';
599 if ($.browser
.msie
&& $.browser
.version
< 7) {
600 var scrollWidth
= Math
.max(
601 document
.documentElement
.scrollWidth
,
602 document
.body
.scrollWidth
604 var offsetWidth
= Math
.max(
605 document
.documentElement
.offsetWidth
,
606 document
.body
.offsetWidth
609 if (scrollWidth
< offsetWidth
) {
610 return $(window
).width() + 'px';
612 return scrollWidth
+ 'px';
614 // handle "good" browsers
616 return $(document
).width() + 'px';
621 /* If the dialog is draggable and the user drags it past the
622 * right edge of the window, the document becomes wider so we
623 * need to stretch the overlay. If the user then drags the
624 * dialog back to the left, the document will become narrower,
625 * so we need to shrink the overlay to the appropriate size.
626 * This is handled by shrinking the overlay before setting it
627 * to the full document size.
629 var $overlays
= $([]);
630 $.each($.ui
.dialog
.overlay
.instances
, function() {
631 $overlays
= $overlays
.add(this);
638 width
: $.ui
.dialog
.overlay
.width(),
639 height
: $.ui
.dialog
.overlay
.height()
644 $.extend($.ui
.dialog
.overlay
.prototype, {
645 destroy: function() {
646 $.ui
.dialog
.overlay
.destroy(this.$el
);