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);