Bug 20489 Configure illegal file characters https://bugzilla.wikimedia.org/show_bug...
[mediawiki.git] / js2 / mwEmbed / jquery / jquery.ui / ui / ui.dialog.js
blob9f4f5e512b8cefe18a0789a756b24fa5d6a7b47a
1 /*
2  * jQuery UI Dialog 1.7.1
3  *
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.
7  *
8  * http://docs.jquery.com/UI/Dialog
9  *
10  * Depends:
11  *      ui.core.js
12  *      ui.draggable.js
13  *      ui.resizable.js
14  */
15 (function($) {
17 var setDataSwitch = {
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"
28         },
29         
30         uiDialogClasses =
31                 'ui-dialog ' +
32                 'ui-widget ' +
33                 'ui-widget-content ' +
34                 'ui-corner-all ';
36 $.widget("ui.dialog", {
38         _init: function() {
39                 this.originalTitle = this.element.attr('title');
41                 var self = this,
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)
49                                 .hide()
50                                 .addClass(uiDialogClasses + options.dialogClass)
51                                 .css({
52                                         position: 'absolute',
53                                         overflow: 'hidden',
54                                         zIndex: options.zIndex
55                                 })
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));
61                                 })
62                                 .attr({
63                                         role: 'dialog',
64                                         'aria-labelledby': titleId
65                                 })
66                                 .mousedown(function(event) {
67                                         self.moveToTop(false, event);
68                                 }),
70                         uiDialogContent = this.element
71                                 .show()
72                                 .removeAttr('title')
73                                 .addClass(
74                                         'ui-dialog-content ' +
75                                         'ui-widget-content')
76                                 .appendTo(uiDialog),
78                         uiDialogTitlebar = (this.uiDialogTitlebar = $('<div></div>'))
79                                 .addClass(
80                                         'ui-dialog-titlebar ' +
81                                         'ui-widget-header ' +
82                                         'ui-corner-all ' +
83                                         'ui-helper-clearfix'
84                                 )
85                                 .prependTo(uiDialog),
87                         uiDialogTitlebarClose = $('<a href="#"/>')
88                                 .addClass(
89                                         'ui-dialog-titlebar-close ' +
90                                         'ui-corner-all'
91                                 )
92                                 .attr('role', 'button')
93                                 .hover(
94                                         function() {
95                                                 uiDialogTitlebarClose.addClass('ui-state-hover');
96                                         },
97                                         function() {
98                                                 uiDialogTitlebarClose.removeClass('ui-state-hover');
99                                         }
100                                 )
101                                 .focus(function() {
102                                         uiDialogTitlebarClose.addClass('ui-state-focus');
103                                 })
104                                 .blur(function() {
105                                         uiDialogTitlebarClose.removeClass('ui-state-focus');
106                                 })
107                                 .mousedown(function(ev) {
108                                         ev.stopPropagation();
109                                 })
110                                 .click(function(event) {
111                                         self.close(event);
112                                         return false;
113                                 })
114                                 .appendTo(uiDialogTitlebar),
116                         uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('<span/>'))
117                                 .addClass(
118                                         'ui-icon ' +
119                                         'ui-icon-closethick'
120                                 )
121                                 .text(options.closeText)
122                                 .appendTo(uiDialogTitlebarClose),
124                         uiDialogTitle = $('<span/>')
125                                 .addClass('ui-dialog-title')
126                                 .attr('id', titleId)
127                                 .html(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());
140                 
141         },
143         destroy: function() {
144                 (this.overlay && this.overlay.destroy());
145                 this.uiDialog.hide();
146                 this.element
147                         .unbind('.dialog')
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));
154         },
156         close: function(event) {
157                 var self = this;
158                 
159                 if (false === self._trigger('beforeclose', event)) {
160                         return;
161                 }
163                 (self.overlay && self.overlay.destroy());
164                 self.uiDialog.unbind('keypress.ui-dialog');
166                 (self.options.hide
167                         ? self.uiDialog.hide(self.options.hide, function() {
168                                 self._trigger('close', event);
169                         })
170                         : self.uiDialog.hide() && self._trigger('close', event));
172                 $.ui.dialog.overlay.resize();
174                 self._isOpen = false;
175         },
177         isOpen: function() {
178                 return this._isOpen;
179         },
181         // the force parameter allows us to move modal dialogs to their correct
182         // position on open
183         moveToTop: function(force, event) {
185                 if ((this.options.modal && !force)
186                         || (!this.options.stack && !this.options.modal)) {
187                         return this._trigger('focus', event);
188                 }
189                 
190                 if (this.options.zIndex > $.ui.dialog.maxZ) {
191                         $.ui.dialog.maxZ = this.options.zIndex;
192                 }
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);
201         },
203         open: function() {
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'));
211                 this._size();
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) {
219                                 return;
220                         }
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() {
228                                         first.focus();
229                                 }, 1);
230                         } else if (event.target == first && event.shiftKey) {
231                                 setTimeout(function() {
232                                         last.focus();
233                                 }, 1);
234                         }
235                 }));
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
239                 $([])
240                         .add(uiDialog.find('.ui-dialog-content :tabbable:first'))
241                         .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first'))
242                         .add(uiDialog)
243                         .filter(':first')
244                         .focus();
246                 this._trigger('open');
247                 this._isOpen = true;
248         },
250         _createButtons: function(buttons) {
251                 var self = this,
252                         hasButtons = false,
253                         uiDialogButtonPane = $('<div></div>')
254                                 .addClass(
255                                         'ui-dialog-buttonpane ' +
256                                         'ui-widget-content ' +
257                                         'ui-helper-clearfix'
258                                 );
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); }));
265                 if (hasButtons) {
266                         $.each(buttons, function(name, fn) {
267                                 $('<button type="button"></button>')
268                                         .addClass(
269                                                 'ui-state-default ' +
270                                                 'ui-corner-all'
271                                         )
272                                         .text(name)
273                                         .click(function() { fn.apply(self.element[0], arguments); })
274                                         .hover(
275                                                 function() {
276                                                         $(this).addClass('ui-state-hover');
277                                                 },
278                                                 function() {
279                                                         $(this).removeClass('ui-state-hover');
280                                                 }
281                                         )
282                                         .focus(function() {
283                                                 $(this).addClass('ui-state-focus');
284                                         })
285                                         .blur(function() {
286                                                 $(this).removeClass('ui-state-focus');
287                                         })
288                                         .appendTo(uiDialogButtonPane);
289                         });
290                         uiDialogButtonPane.appendTo(this.uiDialog);
291                 }
292         },
294         _makeDraggable: function() {
295                 var self = this,
296                         options = this.options,
297                         heightBeforeDrag;
299                 this.uiDialog.draggable({
300                         cancel: '.ui-dialog-content',
301                         handle: '.ui-dialog-titlebar',
302                         containment: 'document',
303                         start: function() {
304                                 heightBeforeDrag = options.height;
305                                 $(this).height($(this).height()).addClass("ui-dialog-dragging");
306                                 (options.dragStart && options.dragStart.apply(self.element[0], arguments));
307                         },
308                         drag: function() {
309                                 (options.drag && options.drag.apply(self.element[0], arguments));
310                         },
311                         stop: function() {
312                                 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
313                                 (options.dragStop && options.dragStop.apply(self.element[0], arguments));
314                                 $.ui.dialog.overlay.resize();
315                         }
316                 });
317         },
319         _makeResizable: function(handles) {
320                 handles = (handles === undefined ? this.options.resizable : handles);
321                 var self = this,
322                         options = this.options,
323                         resizeHandles = typeof handles == 'string'
324                                 ? handles
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,
334                         start: function() {
335                                 $(this).addClass("ui-dialog-resizing");
336                                 (options.resizeStart && options.resizeStart.apply(self.element[0], arguments));
337                         },
338                         resize: function() {
339                                 (options.resize && options.resize.apply(self.element[0], arguments));
340                         },
341                         handles: resizeHandles,
342                         stop: function() {
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();
348                         }
349                 })
350                 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
351         },
353         _position: function(pos) {
354                 var wnd = $(window), doc = $(document),
355                         pTop = doc.scrollTop(), pLeft = doc.scrollLeft(),
356                         minTop = pTop;
358                 if ($.inArray(pos, ['center','top','right','bottom','left']) >= 0) {
359                         pos = [
360                                 pos == 'right' || pos == 'left' ? pos : 'center',
361                                 pos == 'top' || pos == 'bottom' ? pos : 'middle'
362                         ];
363                 }
364                 if (pos.constructor != Array) {
365                         pos = ['center', 'middle'];
366                 }
367                 if (pos[0].constructor == Number) {
368                         pLeft += pos[0];
369                 } else {
370                         switch (pos[0]) {
371                                 case 'left':
372                                         pLeft += 0;
373                                         break;
374                                 case 'right':
375                                         pLeft += wnd.width() - this.uiDialog.outerWidth();
376                                         break;
377                                 default:
378                                 case 'center':
379                                         pLeft += (wnd.width() - this.uiDialog.outerWidth()) / 2;
380                         }
381                 }
382                 if (pos[1].constructor == Number) {
383                         pTop += pos[1];
384                 } else {
385                         switch (pos[1]) {
386                                 case 'top':
387                                         pTop += 0;
388                                         break;
389                                 case 'bottom':
390                                         pTop += wnd.height() - this.uiDialog.outerHeight();
391                                         break;
392                                 default:
393                                 case 'middle':
394                                         pTop += (wnd.height() - this.uiDialog.outerHeight()) / 2;
395                         }
396                 }
398                 // prevent the dialog from being too high (make sure the titlebar
399                 // is accessible)
400                 pTop = Math.max(pTop, minTop);
401                 this.uiDialog.css({top: pTop, left: pLeft});
402         },
404         _setData: function(key, value){
405                 (setDataSwitch[key] && this.uiDialog.data(setDataSwitch[key], value));
406                 switch (key) {
407                         case "buttons":
408                                 this._createButtons(value);
409                                 break;
410                         case "closeText":
411                                 this.uiDialogTitlebarCloseText.text(value);
412                                 break;
413                         case "dialogClass":
414                                 this.uiDialog
415                                         .removeClass(this.options.dialogClass)
416                                         .addClass(uiDialogClasses + value);
417                                 break;
418                         case "draggable":
419                                 (value
420                                         ? this._makeDraggable()
421                                         : this.uiDialog.draggable('destroy'));
422                                 break;
423                         case "height":
424                                 this.uiDialog.height(value);
425                                 break;
426                         case "position":
427                                 this._position(value);
428                                 break;
429                         case "resizable":
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));
442                                 break;
443                         case "title":
444                                 $(".ui-dialog-title", this.uiDialogTitlebar).html(value || '&nbsp;');
445                                 break;
446                         case "width":
447                                 this.uiDialog.width(value);
448                                 break;
449                 }
451                 $.widget.prototype._setData.apply(this, arguments);
452         },
454         _size: function() {
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
457                  */
458                 var options = this.options;
460                 // reset content sizing
461                 this.element.css({
462                         height: 0,
463                         minHeight: 0,
464                         width: 'auto'
465                 });
467                 // reset wrapper sizing
468                 // determine the height of all the non-content elements
469                 var nonContentHeight = this.uiDialog.css({
470                                 height: 'auto',
471                                 width: options.width
472                         })
473                         .height();
475                 this.element
476                         .css({
477                                 minHeight: Math.max(options.minHeight - nonContentHeight, 0),
478                                 height: options.height == 'auto'
479                                         ? 'auto'
480                                         : Math.max(options.height - nonContentHeight, 0)
481                         });
482         }
485 $.extend($.ui.dialog, {
486         version: "1.7.1",
487         defaults: {
488                 autoOpen: true,
489                 bgiframe: false,
490                 buttons: {},
491                 closeOnEscape: true,
492                 closeText: 'close',
493                 dialogClass: '',
494                 draggable: true,
495                 hide: null,
496                 height: 'auto',
497                 maxHeight: false,
498                 maxWidth: false,
499                 minHeight: 150,
500                 minWidth: 150,
501                 modal: false,
502                 position: 'center',
503                 resizable: true,
504                 show: null,
505                 stack: true,
506                 title: '',
507                 width: 300,
508                 zIndex: 1000
509         },
511         getter: 'isOpen',
513         uuid: 0,
514         maxZ: 0,
516         getTitleId: function($el) {
517                 return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid);
518         },
520         overlay: function(dialog) {
521                 this.$el = $.ui.dialog.overlay.create(dialog);
522         }
525 $.extend($.ui.dialog.overlay, {
526         instances: [],
527         maxZ: 0,
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);
539                                 });
540                         }, 1);
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));
546                         });
548                         // handle window resize
549                         $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
550                 }
552                 var $el = $('<div></div>').appendTo(document.body)
553                         .addClass('ui-widget-overlay').css({
554                                 width: this.width(),
555                                 height: this.height()
556                         });
558                 (dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe());
560                 this.instances.push($el);
561                 return $el;
562         },
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');
569                 }
571                 $el.remove();
572         },
574         height: function() {
575                 // handle IE 6
576                 if ($.browser.msie && $.browser.version < 7) {
577                         var scrollHeight = Math.max(
578                                 document.documentElement.scrollHeight,
579                                 document.body.scrollHeight
580                         );
581                         var offsetHeight = Math.max(
582                                 document.documentElement.offsetHeight,
583                                 document.body.offsetHeight
584                         );
586                         if (scrollHeight < offsetHeight) {
587                                 return $(window).height() + 'px';
588                         } else {
589                                 return scrollHeight + 'px';
590                         }
591                 // handle "good" browsers
592                 } else {
593                         return $(document).height() + 'px';
594                 }
595         },
597         width: function() {
598                 // handle IE 6
599                 if ($.browser.msie && $.browser.version < 7) {
600                         var scrollWidth = Math.max(
601                                 document.documentElement.scrollWidth,
602                                 document.body.scrollWidth
603                         );
604                         var offsetWidth = Math.max(
605                                 document.documentElement.offsetWidth,
606                                 document.body.offsetWidth
607                         );
609                         if (scrollWidth < offsetWidth) {
610                                 return $(window).width() + 'px';
611                         } else {
612                                 return scrollWidth + 'px';
613                         }
614                 // handle "good" browsers
615                 } else {
616                         return $(document).width() + 'px';
617                 }
618         },
620         resize: function() {
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.
628                  */
629                 var $overlays = $([]);
630                 $.each($.ui.dialog.overlay.instances, function() {
631                         $overlays = $overlays.add(this);
632                 });
634                 $overlays.css({
635                         width: 0,
636                         height: 0
637                 }).css({
638                         width: $.ui.dialog.overlay.width(),
639                         height: $.ui.dialog.overlay.height()
640                 });
641         }
644 $.extend($.ui.dialog.overlay.prototype, {
645         destroy: function() {
646                 $.ui.dialog.overlay.destroy(this.$el);
647         }
650 })(jQuery);