From 25763f41681a535e7874e271ad03fafbedef3ebd Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Thu, 24 Nov 2011 21:57:27 +0100 Subject: [PATCH] Written an own dialog implementation. Please be aware, that the old-broken jQuery UI dialog is still being used, this will be changed within the upcoming days. AJAX support should be working, but I haven't tried it yet. --- wcfsetup/install/files/acp/style/style.css | 37 ++- wcfsetup/install/files/js/WCF.js | 284 ++++++++++++++++++++- 2 files changed, 304 insertions(+), 17 deletions(-) diff --git a/wcfsetup/install/files/acp/style/style.css b/wcfsetup/install/files/acp/style/style.css index 2eaab6f490..3479284bc1 100644 --- a/wcfsetup/install/files/acp/style/style.css +++ b/wcfsetup/install/files/acp/style/style.css @@ -2790,7 +2790,8 @@ p.error { /* ############## ToDo: Overlay ############## */ -.ui-dialog { +.ui-dialog, +.wcfDialogContainer { border: 23px solid transparent; border-radius: 15px; background-color: rgba(0, 0, 0, .4); @@ -2807,7 +2808,8 @@ p.error { @media screen and (min-width: 480px), screen and (min-device-width: 480px) { - .ui-dialog { + .ui-dialog, + .wcfDialogContainer { min-width: 500px !important; max-width: 780px !important; } @@ -2816,7 +2818,8 @@ p.error { @media screen and (max-width: 480px), screen and (max-device-width: 480px) { - .ui-dialog { + .ui-dialog, + .wcfDialogContainer { min-width: 200px !important; max-width: 380px !important; } @@ -2825,7 +2828,8 @@ p.error { /* Dialog Titlebar */ -.ui-dialog-titlebar { +.ui-dialog-titlebar, +.wcfDialogTitlebar { border-bottom: 1px solid #036; border-top-left-radius: 7px; border-top-right-radius: 7px; @@ -2838,10 +2842,11 @@ p.error { padding: 10px 20px; position: relative; display: block; - cursor: move; + /*cursor: move;*/ } -.ui-dialog-title { +.ui-dialog-title, +.wcfDialogTitle { font-size: 170%; font-weight: bold; text-shadow: 0 -1px 0 #000; @@ -2849,7 +2854,8 @@ p.error { display: block; } -a.ui-dialog-titlebar-close { +a.ui-dialog-titlebar-close, +a.wcfDialogCloseButton { background-image: url('../../icon/delete2.svg'); background-size: 32px; background-position: top left; @@ -2859,9 +2865,11 @@ a.ui-dialog-titlebar-close { height: 32px; top: 5px; right: 10px; + cursor: pointer; } -a.ui-dialog-titlebar-close span { +a.ui-dialog-titlebar-close span, +a.wcfDialogCloseButton span { /* Removes the button-caption */ position: absolute; left: -9000px; @@ -2871,17 +2879,21 @@ a.ui-dialog-titlebar-close span { /* Dialog Content */ -.ui-dialog-content { +.ui-dialog-content, +.wcfDialogContent { background-color: #333; + overflow: auto; } -.ui-dialog > .ui-dialog-content { +.ui-dialog > .ui-dialog-content, +.wcfDialogContainer > .wcfDialogContent { border-radius: 7px; padding: 0; width: auto !important; } -.ui-dialog-titlebar ~ .ui-dialog-content { +.ui-dialog-titlebar ~ .ui-dialog-content, +.wcfDialogTitlebar ~ .wcfDialogContent { border-top-left-radius: 0; border-top-right-radius: 0; border-bottom-left-radius: 7px; @@ -2943,7 +2955,8 @@ div#ajaxExceptionStacktrace { /* ############## ToDo: Overlay Spinner ############## */ -.ui-widget-overlay { +.ui-widget-overlay, +.wcfDialogOverlay { background-color: #000; opacity: .5; position: fixed; diff --git a/wcfsetup/install/files/js/WCF.js b/wcfsetup/install/files/js/WCF.js index 52a95062af..0cbe16c0db 100644 --- a/wcfsetup/install/files/js/WCF.js +++ b/wcfsetup/install/files/js/WCF.js @@ -369,6 +369,32 @@ $.fn.extend({ */ wcfHighlight: function(options, callback) { return this.effect('highlight', options, 600, callback); + }, + + /** + * Shows an element by fading it in. + * + * @param object callback + * @param integer duration + * @returns jQuery + */ + wcfFadeIn: function(callback, duration) { + if (!duration || !parseInt(duration)) duration = 200; + + return this.show(WCF.getEffect(this.getTagName(), 'fade'), { }, duration, callback); + }, + + /** + * Hides an element by fading it out. + * + * @param object callback + * @param integer duration + * @returns jQuery + */ + wcfFadeOut: function(callback, duration) { + if (!duration || !parseInt(duration)) duration = 200; + + return this.hide(WCF.getEffect(this.getTagName(), 'fade'), { }, duration, callback); } }); @@ -3104,7 +3130,7 @@ $.widget('ui.wcfPersistentSidebar', $.ui.wcfSidebar, { return; } - $.ui.dialog.prototype._init.apply(this, arguments); + $.ui.wcfSidebar.prototype._init.apply(this, arguments); // collapse on init if (this.options.collapsed) { @@ -3124,7 +3150,7 @@ $.widget('ui.wcfPersistentSidebar', $.ui.wcfSidebar, { return; } - $.ui.dialog.prototype._init.apply(this, arguments); + $.ui.wcfSidebar.prototype._init.apply(this, arguments); // save state this._save(); @@ -3138,7 +3164,7 @@ $.widget('ui.wcfPersistentSidebar', $.ui.wcfSidebar, { return; } - $.ui.dialog.prototype._init.apply(this, arguments); + $.ui.wcfSidebar.prototype._init.apply(this, arguments); // save state this._save(); @@ -3166,10 +3192,258 @@ $.widget('ui.wcfPersistentSidebar', $.ui.wcfSidebar, { } }); +/** + * WCF implementation for dialogs, based upon ideas by jQuery UI. + */ +$.widget('ui.wcfDialog', { + /** + * close button + * @var jQuery + */ + _closeButton: null, + + /** + * dialog container + * @var jQuery + */ + _container: null, + + /** + * dialog content + * @var jQuery + */ + _content: null, + + /** + * modal overlay + * @var jQuery + */ + _overlay: null, + + /** + * plain html for title + * @var string + */ + _title: null, + + /** + * title bar + * @var jQuery + */ + _titlebar: null, + + /** + * dialog visibility state + * @var boolean + */ + _isOpen: false, + + /** + * option list + * @var object + */ + options: { + // dialog + autoOpen: true, + closable: true, + closeButtonLabel: null, + hideTitle: false, + modal: true, + title: '', + zIndex: 1000, + + // AJAX support + ajax: false, + data: { }, + success: null, + type: 'POST', + url: 'index.php/AJAXProxy/?t=' + SECURITY_TOKEN + SID_ARG_2ND + }, + + /** + * Initializes a new dialog. + */ + _init: function() { + if (this.options.closeButtonLabel === null) { + this.options.closeButtonLabel = WCF.Language.get('wcf.global.close'); + } + + if (this.options.ajax) { + new WCF.Action.Proxy({ + autoSend: true, + data: this.options.data, + success: $.proxy(this._success, this), + type: this.options.type, + url: this.options.url + }); + + // force open if using AJAX + this.options.autoOpen = true; + } + + if (this.options.autoOpen) { + this.open(); + } + + // act on resize + $(window).resize($.proxy(this.render, this)); + }, + + /** + * Creates a new dialog instance. + */ + _create: function() { + // create dialog container + this._container = $('
').hide().css({ zIndex: this.options.zIndex }).appendTo(document.body); + + // create title + if (!this.options.hideTitle && this.options.title != '') { + this._titlebar = $('
').appendTo(this._container); + this._title = $('').html(this.options.title).appendTo(this._titlebar); + } + + // create close button + if (this.options.closable) { + this._closeButton = $('TODO: close').click($.proxy(this.close, this)) + + if (!this.options.hideTitle && this.options.title != '') { + this._closeButton.appendTo(this._titlebar); + } + else { + this._closeButton.appendTo(this._container); + } + } + + // create content container + this._content = $('
').appendTo(this._container); + + // move target element into content + var $content = this.element.remove(); + this._content.html($content); + + // create modal view + if (this.options.modal) { + this._overlay = $('
').css({ height: '100%', zIndex: 900 }).appendTo(document.body); + + if (this.options.closable) { + this._overlay.click($.proxy(this.close, this)); + + $(document).keyup($.proxy(function(event) { + if (event.keyCode && event.keyCode === $.ui.keyCode.ESCAPE) { + this.close(); + event.preventDefault(); + } + }, this)); + } + } + }, + + /** + * Handles successful AJAX requests. + * + * @param object data + * @param string textStatus + * @param jQuery jqXHR + */ + _success: function(data, textStatus, jqXHR) { + if (this.options.success !== null && $.isFunction(this.options.success)) { + this.options.success(data, textStatus, jqXHR); + } + }, + + /** + * Opens this dialog. + */ + open: function() { + if (this.isOpen()) { + return; + } + + this.render(); + this._isOpen = true; + }, + + /** + * Returns true, if dialog is visible. + * + * @return boolean + */ + isOpen: function() { + return this._isOpen; + }, + + /** + * Closes this dialog. + */ + close: function() { + if (!this.isOpen()) { + return; + } + + this._isOpen = false; + this._container.wcfFadeOut(); + + if (this._overlay !== null) { + this._overlay.hide(); + } + }, + + /** + * Renders this dialog, should be called whenever content is updated. + */ + render: function() { + if (!this.isOpen()) { + // temporarily display container + this._container.show(); + } + + // calculate dimensions + var $windowDimensions = $(window).getDimensions(); + var $containerDimensions = this._container.getDimensions('outer'); + var $contentDimensions = this._content.getDimensions('outer'); + + // move container + var $leftOffset = Math.round(($windowDimensions.width - $containerDimensions.width) / 2); + var $topOffset = Math.round(($windowDimensions.height - $containerDimensions.height) / 2); + + // place container at 20% height if possible + var $desiredTopOffset = Math.round(($windowDimensions.height / 100) * 20); + if ($desiredTopOffset < $topOffset) { + $topOffset = $desiredTopOffset; + } + + // calculate maximum content height + var $heightDifference = $containerDimensions.height - $contentDimensions.height; + var $maximumHeight = $windowDimensions.height - $heightDifference - 60; + this._content.css({ maxHeight: $maximumHeight + 'px' }); + + if (!this.isOpen()) { + // hide container again + this._container.hide(); + + // apply offset + this._container.css({ + left: $leftOffset + 'px', + top: $topOffset + 'px' + }); + + // fade in container + this._container.wcfFadeIn(undefined, 600); + } + else { + this._container.animate({ + left: $leftOffset + 'px', + top: $topOffset + 'px' + }, 200); + } + } +}); + + /** * Basic implementation for WCF dialogs. */ -$.widget('ui.wcfDialog', $.ui.dialog, { +$.widget('ui.wcfDialog_old', $.ui.dialog, { _init: function() { this.options.autoOpen = true; this.options.hide = { @@ -3224,7 +3498,7 @@ $.widget('ui.wcfDialog', $.ui.dialog, { * Basic implementation for WCF dialogs loading content * via AJAX before calling dialog itself. */ -$.widget('ui.wcfAJAXDialog', $.ui.dialog, { +$.widget('ui.wcfAJAXDialog_old', $.ui.dialog, { /** * Indicates wether callback was already executed * -- 2.20.1