Convert `Ui/Confirmation` to TypeScript
authorAlexander Ebert <ebert@woltlab.com>
Wed, 21 Oct 2020 14:07:07 +0000 (16:07 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Wed, 28 Oct 2020 11:35:31 +0000 (12:35 +0100)
wcfsetup/install/files/js/WoltLabSuite/Core/Ajax/Request.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Confirmation.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Dialog.js
wcfsetup/install/files/ts/WoltLabSuite/Core/Ajax/Request.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Confirmation.js [deleted file]
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Confirmation.ts [new file with mode: 0644]
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Dialog.ts

index d96eda3b1d44f7e19663d6d80d2b73dabd50a86d..d9c70d36c9e4f66f57e62b6d53b5e7f3b45d5c0b 100644 (file)
@@ -31,11 +31,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
 var __importDefault = (this && this.__importDefault) || function (mod) {
     return (mod && mod.__esModule) ? mod : { "default": mod };
 };
-define(["require", "exports", "./Status", "../Core", "../Dom/Change/Listener"], function (require, exports, AjaxStatus, Core, Listener_1) {
+define(["require", "exports", "./Status", "../Core", "../Dom/Change/Listener", "../Dom/Util", "../Language"], function (require, exports, AjaxStatus, Core, Listener_1, Util_1, Language) {
     "use strict";
     AjaxStatus = __importStar(AjaxStatus);
     Core = __importStar(Core);
     Listener_1 = __importDefault(Listener_1);
+    Util_1 = __importDefault(Util_1);
+    Language = __importStar(Language);
     let _didInit = false;
     let _ignoreAllErrors = false;
     /**
@@ -250,14 +252,11 @@ define(["require", "exports", "./Status", "../Core", "../Dom/Change/Listener"],
             if (options.ignoreError !== true && showError) {
                 const html = this.getErrorHtml(data, xhr);
                 if (html) {
-                    // TODO
-                    throw new Error('TODO: Yielding dialogs is not yet supported.');
-                    /*
-                    if (UiDialog === undefined) UiDialog = require('Ui/Dialog');
-                    UiDialog.openStatic(DomUtil.getUniqueId(), html, {
-                      title: Language.get('wcf.global.error.title'),
+                    new Promise((resolve_2, reject_2) => { require(['../Ui/Dialog'], resolve_2, reject_2); }).then(__importStar).then(UiDialog => {
+                        UiDialog.openStatic(Util_1.default.getUniqueId(), html, {
+                            title: Language.get('wcf.global.error.title'),
+                        });
                     });
-                     */
                 }
             }
             this._finalize(options);
index 2f78b1a2d42b80e4a5a5cddf31c53d1faf16ead8..e6a477d8487165cf73d68508ccc0085ff2b5ce03 100644 (file)
 /**
  * Provides the confirmation dialog overlay.
  *
- * @author     Alexander Ebert
- * @copyright  2001-2019 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module     Ui/Confirmation (alias)
- * @module     WoltLabSuite/Core/Ui/Confirmation
+ * @author  Alexander Ebert
+ * @copyright  2001-2019 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  Ui/Confirmation (alias)
+ * @module  WoltLabSuite/Core/Ui/Confirmation
  */
-define(['Core', 'Language', 'Ui/Dialog'], function (Core, Language, UiDialog) {
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+    Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+    o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+    if (mod && mod.__esModule) return mod;
+    var result = {};
+    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+    __setModuleDefault(result, mod);
+    return result;
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+    return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+define(["require", "exports", "../Core", "../Language", "./Dialog"], function (require, exports, Core, Language, Dialog_1) {
     "use strict";
-    var _active = false;
-    var _confirmButton = null;
-    var _content = null;
-    var _options = {};
-    var _text = null;
-    /**
-     * Confirmation dialog overlay.
-     *
-     * @exports        WoltLabSuite/Core/Ui/Confirmation
-     */
-    return {
-        /**
-         * Shows the confirmation dialog.
-         *
-         * Possible options:
-         *  - cancel: callback if user cancels the dialog
-         *  - confirm: callback if user confirm the dialog
-         *  - legacyCallback: WCF 2.0/2.1 compatible callback with string parameter
-         *  - message: displayed confirmation message
-         *  - parameters: list of parameters passed to the callback on confirm
-         *  - template: optional HTML string to be inserted below the `message`
-         *
-         * @param      {object<string, *>}     options         confirmation options
-         */
-        show: function (options) {
-            if (UiDialog === undefined)
-                UiDialog = require('Ui/Dialog');
-            if (_active) {
-                return;
-            }
-            _options = Core.extend({
-                cancel: null,
-                confirm: null,
-                legacyCallback: null,
-                message: '',
-                messageIsHtml: false,
-                parameters: {},
-                template: ''
-            }, options);
-            _options.message = (typeof _options.message === 'string') ? _options.message.trim() : '';
-            if (!_options.message.length) {
-                throw new Error("Expected a non-empty string for option 'message'.");
-            }
-            if (typeof _options.confirm !== 'function' && typeof _options.legacyCallback !== 'function') {
-                throw new TypeError("Expected a valid callback for option 'confirm'.");
-            }
-            if (_content === null) {
-                this._createDialog();
-            }
-            _content.innerHTML = (typeof _options.template === 'string') ? _options.template.trim() : '';
-            if (_options.messageIsHtml)
-                _text.innerHTML = _options.message;
-            else
-                _text.textContent = _options.message;
-            _active = true;
-            UiDialog.open(this);
-        },
-        _dialogSetup: function () {
-            return {
-                id: 'wcfSystemConfirmation',
-                options: {
-                    onClose: this._onClose.bind(this),
-                    onShow: this._onShow.bind(this),
-                    title: Language.get('wcf.global.confirmation.title')
-                }
-            };
-        },
-        /**
-         * Returns content container element.
-         *
-         * @return     {Element}       content container element
-         */
-        getContentElement: function () {
-            return _content;
-        },
-        /**
-         * Creates the dialog DOM elements.
-         */
-        _createDialog: function () {
-            var dialog = elCreate('div');
-            elAttr(dialog, 'id', 'wcfSystemConfirmation');
-            dialog.classList.add('systemConfirmation');
-            _text = elCreate('p');
-            dialog.appendChild(_text);
-            _content = elCreate('div');
-            elAttr(_content, 'id', 'wcfSystemConfirmationContent');
-            dialog.appendChild(_content);
-            var formSubmit = elCreate('div');
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.getContentElement = exports.show = void 0;
+    Core = __importStar(Core);
+    Language = __importStar(Language);
+    Dialog_1 = __importDefault(Dialog_1);
+    class UiConfirmation {
+        constructor() {
+            this._active = false;
+            this.dialog = document.createElement('div');
+            this.dialog.id = 'wcfSystemConfirmation';
+            this.dialog.classList.add('systemConfirmation');
+            this.text = document.createElement('p');
+            this.dialog.appendChild(this.text);
+            this._content = document.createElement('div');
+            this._content.id = 'wcfSystemConfirmationContent';
+            this.dialog.appendChild(this._content);
+            const formSubmit = document.createElement('div');
             formSubmit.classList.add('formSubmit');
-            dialog.appendChild(formSubmit);
-            _confirmButton = elCreate('button');
-            _confirmButton.classList.add('buttonPrimary');
-            _confirmButton.textContent = Language.get('wcf.global.confirmation.confirm');
-            _confirmButton.addEventListener(WCF_CLICK_EVENT, this._confirm.bind(this));
-            formSubmit.appendChild(_confirmButton);
-            var cancelButton = elCreate('button');
+            this.dialog.appendChild(formSubmit);
+            this.confirmButton = document.createElement('button');
+            this.confirmButton.classList.add('buttonPrimary');
+            this.confirmButton.textContent = Language.get('wcf.global.confirmation.confirm');
+            this.confirmButton.addEventListener('click', this._confirm.bind(this));
+            formSubmit.appendChild(this.confirmButton);
+            const cancelButton = document.createElement('button');
             cancelButton.textContent = Language.get('wcf.global.confirmation.cancel');
-            cancelButton.addEventListener(WCF_CLICK_EVENT, function () { UiDialog.close('wcfSystemConfirmation'); });
+            cancelButton.addEventListener('click', () => {
+                Dialog_1.default.close(this);
+            });
             formSubmit.appendChild(cancelButton);
-            document.body.appendChild(dialog);
-        },
-        /**
-         * Invoked if the user confirms the dialog.
-         */
-        _confirm: function () {
-            if (typeof _options.legacyCallback === 'function') {
-                _options.legacyCallback('confirm', _options.parameters, _content);
+            document.body.appendChild(this.dialog);
+        }
+        open(options) {
+            this.parameters = options.parameters || {};
+            this._content.innerHTML = (typeof options.template === 'string') ? options.template.trim() : '';
+            this.text[options.messageIsHtml ? 'innerHtml' : 'textContent'] = options.message;
+            if (typeof options.legacyCallback === 'function') {
+                this.callbackCancel = parameters => {
+                    options.legacyCallback('cancel', parameters, this.content);
+                };
+                this.callbackConfirm = parameters => {
+                    options.legacyCallback('confirm', parameters, this.content);
+                };
             }
             else {
-                _options.confirm(_options.parameters, _content);
+                if (typeof options.cancel !== 'function') {
+                    options.cancel = () => {
+                    };
+                }
+                this.callbackCancel = options.cancel;
+                this.callbackConfirm = options.confirm;
             }
-            _active = false;
-            UiDialog.close('wcfSystemConfirmation');
-        },
+            this._active = true;
+            Dialog_1.default.open(this);
+        }
+        get active() {
+            return this._active;
+        }
+        get content() {
+            return this._content;
+        }
+        /**
+         * Invoked if the user confirms the dialog.
+         */
+        _confirm() {
+            this.callbackConfirm(this.parameters, this.content);
+            this._active = false;
+            Dialog_1.default.close('wcfSystemConfirmation');
+        }
         /**
          * Invoked on dialog close or if user cancels the dialog.
          */
-        _onClose: function () {
-            if (_active) {
-                _confirmButton.blur();
-                _active = false;
-                if (typeof _options.legacyCallback === 'function') {
-                    _options.legacyCallback('cancel', _options.parameters, _content);
-                }
-                else if (typeof _options.cancel === 'function') {
-                    _options.cancel(_options.parameters);
-                }
+        _onClose() {
+            if (this.active) {
+                this.confirmButton.blur();
+                this._active = false;
+                this.callbackCancel(this.parameters);
             }
-        },
+        }
         /**
          * Sets the focus on the confirm button on dialog open for proper keyboard support.
          */
-        _onShow: function () {
-            _confirmButton.blur();
-            _confirmButton.focus();
+        _onShow() {
+            this.confirmButton.blur();
+            this.confirmButton.focus();
         }
-    };
+        _dialogSetup() {
+            return {
+                id: 'wcfSystemConfirmation',
+                options: {
+                    onClose: this._onClose.bind(this),
+                    onShow: this._onShow.bind(this),
+                    title: Language.get('wcf.global.confirmation.title'),
+                },
+            };
+        }
+    }
+    let confirmation;
+    function getConfirmation() {
+        if (!confirmation) {
+            confirmation = new UiConfirmation();
+        }
+        return confirmation;
+    }
+    /**
+     * Shows the confirmation dialog.
+     */
+    function show(options) {
+        if (getConfirmation().active) {
+            return;
+        }
+        options = Core.extend({
+            cancel: null,
+            confirm: null,
+            legacyCallback: null,
+            message: '',
+            messageIsHtml: false,
+            parameters: {},
+            template: '',
+        }, options);
+        options.message = (typeof options.message === 'string') ? options.message.trim() : '';
+        if (!options.message) {
+            throw new Error("Expected a non-empty string for option 'message'.");
+        }
+        if (typeof options.confirm !== 'function' && typeof options.legacyCallback !== 'function') {
+            throw new TypeError("Expected a valid callback for option 'confirm'.");
+        }
+        getConfirmation().open(options);
+    }
+    exports.show = show;
+    /**
+     * Returns content container element.
+     */
+    function getContentElement() {
+        return getConfirmation().content;
+    }
+    exports.getContentElement = getContentElement;
 });
index 04848b9c64e9ef2d38e9f3871b8e07541171cb8a..ae0b9ced67a026adf83ebf07d14f1a9665730558 100644 (file)
@@ -135,7 +135,7 @@ define(["require", "exports", "../Core", "../Dom/Change/Listener", "./Screen", "
             let dialogData = _dialogObjects.get(callbackObject);
             if (dialogData && Core.isPlainObject(dialogData)) {
                 // dialog already exists
-                return this.openStatic(dialogData.id, html);
+                return this.openStatic(dialogData.id, typeof html === 'undefined' ? null : html);
             }
             // initialize a new dialog
             if (typeof callbackObject._dialogSetup !== 'function') {
@@ -234,15 +234,14 @@ define(["require", "exports", "../Core", "../Dom/Change/Listener", "./Screen", "
                 if (!options.closable)
                     options.backdropCloseOnClick = false;
                 if (options.closeConfirmMessage) {
-                    // TODO
-                    /*
                     options.onBeforeClose = id => {
-                      UiConfirmation.show({
-                        confirm: this.close.bind(this, id),
-                        message: options.closeConfirmMessage,
-                      });
+                        new Promise((resolve_2, reject_2) => { require(['./Confirmation'], resolve_2, reject_2); }).then(__importStar).then(UiConfirmation => {
+                            UiConfirmation.show({
+                                confirm: this.close.bind(this, id),
+                                message: options.closeConfirmMessage || '',
+                            });
+                        });
                     };
-                    */
                 }
                 this._createDialog(id, html, options, createOnly || false);
             }
index 374a5954bb2a6450238f8309301cdc3d7d1a6f81..8f71a152572fb3e057608377330a3725b48f81f4 100644 (file)
@@ -14,6 +14,8 @@ import * as AjaxStatus from './Status';
 import { ResponseData, RequestOptions, RequestData } from './Data';
 import * as Core from '../Core';
 import DomChangeListener from '../Dom/Change/Listener';
+import DomUtil from '../Dom/Util';
+import * as Language from '../Language';
 
 let _didInit = false;
 let _ignoreAllErrors = false;
@@ -264,14 +266,11 @@ class AjaxRequest {
       const html = this.getErrorHtml(data, xhr);
 
       if (html) {
-        // TODO
-        throw new Error('TODO: Yielding dialogs is not yet supported.');
-        /*
-        if (UiDialog === undefined) UiDialog = require('Ui/Dialog');
-        UiDialog.openStatic(DomUtil.getUniqueId(), html, {
-          title: Language.get('wcf.global.error.title'),
+        import('../Ui/Dialog').then(UiDialog => {
+          UiDialog.openStatic(DomUtil.getUniqueId(), html, {
+            title: Language.get('wcf.global.error.title'),
+          });
         });
-         */
       }
     }
 
diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Confirmation.js b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Confirmation.js
deleted file mode 100644 (file)
index 2f78b1a..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- * Provides the confirmation dialog overlay.
- *
- * @author     Alexander Ebert
- * @copyright  2001-2019 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module     Ui/Confirmation (alias)
- * @module     WoltLabSuite/Core/Ui/Confirmation
- */
-define(['Core', 'Language', 'Ui/Dialog'], function (Core, Language, UiDialog) {
-    "use strict";
-    var _active = false;
-    var _confirmButton = null;
-    var _content = null;
-    var _options = {};
-    var _text = null;
-    /**
-     * Confirmation dialog overlay.
-     *
-     * @exports        WoltLabSuite/Core/Ui/Confirmation
-     */
-    return {
-        /**
-         * Shows the confirmation dialog.
-         *
-         * Possible options:
-         *  - cancel: callback if user cancels the dialog
-         *  - confirm: callback if user confirm the dialog
-         *  - legacyCallback: WCF 2.0/2.1 compatible callback with string parameter
-         *  - message: displayed confirmation message
-         *  - parameters: list of parameters passed to the callback on confirm
-         *  - template: optional HTML string to be inserted below the `message`
-         *
-         * @param      {object<string, *>}     options         confirmation options
-         */
-        show: function (options) {
-            if (UiDialog === undefined)
-                UiDialog = require('Ui/Dialog');
-            if (_active) {
-                return;
-            }
-            _options = Core.extend({
-                cancel: null,
-                confirm: null,
-                legacyCallback: null,
-                message: '',
-                messageIsHtml: false,
-                parameters: {},
-                template: ''
-            }, options);
-            _options.message = (typeof _options.message === 'string') ? _options.message.trim() : '';
-            if (!_options.message.length) {
-                throw new Error("Expected a non-empty string for option 'message'.");
-            }
-            if (typeof _options.confirm !== 'function' && typeof _options.legacyCallback !== 'function') {
-                throw new TypeError("Expected a valid callback for option 'confirm'.");
-            }
-            if (_content === null) {
-                this._createDialog();
-            }
-            _content.innerHTML = (typeof _options.template === 'string') ? _options.template.trim() : '';
-            if (_options.messageIsHtml)
-                _text.innerHTML = _options.message;
-            else
-                _text.textContent = _options.message;
-            _active = true;
-            UiDialog.open(this);
-        },
-        _dialogSetup: function () {
-            return {
-                id: 'wcfSystemConfirmation',
-                options: {
-                    onClose: this._onClose.bind(this),
-                    onShow: this._onShow.bind(this),
-                    title: Language.get('wcf.global.confirmation.title')
-                }
-            };
-        },
-        /**
-         * Returns content container element.
-         *
-         * @return     {Element}       content container element
-         */
-        getContentElement: function () {
-            return _content;
-        },
-        /**
-         * Creates the dialog DOM elements.
-         */
-        _createDialog: function () {
-            var dialog = elCreate('div');
-            elAttr(dialog, 'id', 'wcfSystemConfirmation');
-            dialog.classList.add('systemConfirmation');
-            _text = elCreate('p');
-            dialog.appendChild(_text);
-            _content = elCreate('div');
-            elAttr(_content, 'id', 'wcfSystemConfirmationContent');
-            dialog.appendChild(_content);
-            var formSubmit = elCreate('div');
-            formSubmit.classList.add('formSubmit');
-            dialog.appendChild(formSubmit);
-            _confirmButton = elCreate('button');
-            _confirmButton.classList.add('buttonPrimary');
-            _confirmButton.textContent = Language.get('wcf.global.confirmation.confirm');
-            _confirmButton.addEventListener(WCF_CLICK_EVENT, this._confirm.bind(this));
-            formSubmit.appendChild(_confirmButton);
-            var cancelButton = elCreate('button');
-            cancelButton.textContent = Language.get('wcf.global.confirmation.cancel');
-            cancelButton.addEventListener(WCF_CLICK_EVENT, function () { UiDialog.close('wcfSystemConfirmation'); });
-            formSubmit.appendChild(cancelButton);
-            document.body.appendChild(dialog);
-        },
-        /**
-         * Invoked if the user confirms the dialog.
-         */
-        _confirm: function () {
-            if (typeof _options.legacyCallback === 'function') {
-                _options.legacyCallback('confirm', _options.parameters, _content);
-            }
-            else {
-                _options.confirm(_options.parameters, _content);
-            }
-            _active = false;
-            UiDialog.close('wcfSystemConfirmation');
-        },
-        /**
-         * Invoked on dialog close or if user cancels the dialog.
-         */
-        _onClose: function () {
-            if (_active) {
-                _confirmButton.blur();
-                _active = false;
-                if (typeof _options.legacyCallback === 'function') {
-                    _options.legacyCallback('cancel', _options.parameters, _content);
-                }
-                else if (typeof _options.cancel === 'function') {
-                    _options.cancel(_options.parameters);
-                }
-            }
-        },
-        /**
-         * Sets the focus on the confirm button on dialog open for proper keyboard support.
-         */
-        _onShow: function () {
-            _confirmButton.blur();
-            _confirmButton.focus();
-        }
-    };
-});
diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Confirmation.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Confirmation.ts
new file mode 100644 (file)
index 0000000..db0c289
--- /dev/null
@@ -0,0 +1,212 @@
+/**
+ * Provides the confirmation dialog overlay.
+ *
+ * @author  Alexander Ebert
+ * @copyright  2001-2019 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  Ui/Confirmation (alias)
+ * @module  WoltLabSuite/Core/Ui/Confirmation
+ */
+
+import * as Core from '../Core';
+import * as Language from '../Language';
+import UiDialog from './Dialog';
+import { CallbackObject } from './Dialog/Data';
+
+class UiConfirmation implements CallbackObject {
+  private _active = false;
+  private parameters: CallbackParameters;
+
+  private readonly confirmButton: HTMLElement;
+  private readonly _content: HTMLElement;
+  private readonly dialog: HTMLElement;
+  private readonly text: HTMLElement;
+
+  private callbackCancel: CallbackCancel;
+  private callbackConfirm: CallbackConfirm;
+
+  constructor() {
+    this.dialog = document.createElement('div');
+    this.dialog.id = 'wcfSystemConfirmation';
+    this.dialog.classList.add('systemConfirmation');
+
+    this.text = document.createElement('p');
+    this.dialog.appendChild(this.text);
+
+    this._content = document.createElement('div');
+    this._content.id = 'wcfSystemConfirmationContent';
+    this.dialog.appendChild(this._content);
+
+    const formSubmit = document.createElement('div');
+    formSubmit.classList.add('formSubmit');
+    this.dialog.appendChild(formSubmit);
+
+    this.confirmButton = document.createElement('button');
+    this.confirmButton.classList.add('buttonPrimary');
+    this.confirmButton.textContent = Language.get('wcf.global.confirmation.confirm');
+    this.confirmButton.addEventListener('click', this._confirm.bind(this));
+    formSubmit.appendChild(this.confirmButton);
+
+    const cancelButton = document.createElement('button');
+    cancelButton.textContent = Language.get('wcf.global.confirmation.cancel');
+    cancelButton.addEventListener('click', () => {
+      UiDialog.close(this);
+    });
+    formSubmit.appendChild(cancelButton);
+
+    document.body.appendChild(this.dialog);
+  }
+
+  public open(options: ConfirmationOptions): void {
+    this.parameters = options.parameters || {};
+    
+    this._content.innerHTML = (typeof options.template === 'string') ? options.template.trim() : '';
+    this.text[options.messageIsHtml ? 'innerHtml' : 'textContent'] = options.message;
+
+    if (typeof options.legacyCallback === 'function') {
+      this.callbackCancel = parameters => {
+        options.legacyCallback!('cancel', parameters, this.content);
+      };
+      this.callbackConfirm = parameters => {
+        options.legacyCallback!('confirm', parameters, this.content);
+      };
+    } else {
+      if (typeof options.cancel !== 'function') {
+        options.cancel = () => {
+        };
+      }
+
+      this.callbackCancel = options.cancel;
+      this.callbackConfirm = options.confirm!;
+    }
+
+    this._active = true;
+
+    UiDialog.open(this);
+  }
+
+  get active(): boolean {
+    return this._active;
+  }
+
+  get content(): HTMLElement {
+    return this._content;
+  }
+
+  /**
+   * Invoked if the user confirms the dialog.
+   */
+  _confirm(): void {
+    this.callbackConfirm(this.parameters, this.content);
+    
+    this._active = false;
+
+    UiDialog.close('wcfSystemConfirmation');
+  }
+
+  /**
+   * Invoked on dialog close or if user cancels the dialog.
+   */
+  _onClose(): void {
+    if (this.active) {
+      this.confirmButton.blur();
+
+      this._active = false;
+
+      this.callbackCancel(this.parameters);
+    }
+  }
+
+  /**
+   * Sets the focus on the confirm button on dialog open for proper keyboard support.
+   */
+  _onShow(): void {
+    this.confirmButton.blur();
+    this.confirmButton.focus();
+  }
+
+  _dialogSetup() {
+    return {
+      id: 'wcfSystemConfirmation',
+      options: {
+        onClose: this._onClose.bind(this),
+        onShow: this._onShow.bind(this),
+        title: Language.get('wcf.global.confirmation.title'),
+      },
+    };
+  }
+}
+
+let confirmation: UiConfirmation;
+
+function getConfirmation(): UiConfirmation {
+  if (!confirmation) {
+    confirmation = new UiConfirmation();
+  }
+  return confirmation;
+}
+
+type LegacyResult = 'cancel' | 'confirm';
+
+type CallbackParameters = {
+  [key: string]: any,
+}
+
+interface BasicConfirmationOptions {
+  message: string;
+  messageIsHtml?: boolean;
+  parameters?: CallbackParameters,
+  template?: string;
+}
+
+interface LegacyConfirmationOptions extends BasicConfirmationOptions {
+  cancel?: never;
+  confirm?: never;
+  legacyCallback: (result: LegacyResult, parameters: CallbackParameters, element: HTMLElement) => void;
+}
+
+type CallbackCancel = (parameters: CallbackParameters) => void;
+type CallbackConfirm = (parameters: CallbackParameters, content: HTMLElement) => void;
+
+interface NewConfirmationOptions extends BasicConfirmationOptions {
+  cancel?: CallbackCancel;
+  confirm: CallbackConfirm;
+  legacyCallback?: never;
+}
+
+export type ConfirmationOptions = LegacyConfirmationOptions | NewConfirmationOptions;
+
+/**
+ * Shows the confirmation dialog.
+ */
+export function show(options: ConfirmationOptions): void {
+  if (getConfirmation().active) {
+    return;
+  }
+
+  options = Core.extend({
+    cancel: null,
+    confirm: null,
+    legacyCallback: null,
+    message: '',
+    messageIsHtml: false,
+    parameters: {},
+    template: '',
+  }, options) as ConfirmationOptions;
+  options.message = (typeof (options.message as any) === 'string') ? options.message.trim() : '';
+  if (!options.message) {
+    throw new Error("Expected a non-empty string for option 'message'.");
+  }
+  if (typeof options.confirm !== 'function' && typeof options.legacyCallback !== 'function') {
+    throw new TypeError("Expected a valid callback for option 'confirm'.");
+  }
+
+  getConfirmation().open(options);
+}
+
+/**
+ * Returns content container element.
+ */
+export function getContentElement(): HTMLElement {
+  return getConfirmation().content;
+}
index 20a870d8dc68fa8f64a8c00bc05fcaaa8010ec23..b5e31edb1e56f4a99e0211276f617f13de3b2619 100644 (file)
@@ -129,11 +129,11 @@ export = {
   /**
    * Opens the dialog and implicitly creates it on first usage.
    */
-  open(callbackObject: CallbackObject, html: DialogHtml): DialogData | object {
+  open(callbackObject: CallbackObject, html?: DialogHtml): DialogData | object {
     let dialogData = _dialogObjects.get(callbackObject);
     if (dialogData && Core.isPlainObject(dialogData)) {
       // dialog already exists
-      return this.openStatic(dialogData.id, html);
+      return this.openStatic(dialogData.id, typeof html === 'undefined' ? null : html);
     }
 
     // initialize a new dialog
@@ -183,7 +183,7 @@ export = {
             }
           });
         });
-        
+
         return {};
       }
     } else {
@@ -243,15 +243,14 @@ export = {
 
       if (!options.closable) options.backdropCloseOnClick = false;
       if (options.closeConfirmMessage) {
-        // TODO
-        /*
         options.onBeforeClose = id => {
-          UiConfirmation.show({
-            confirm: this.close.bind(this, id),
-            message: options.closeConfirmMessage,
+          import('./Confirmation').then(UiConfirmation => {
+            UiConfirmation.show({
+              confirm: this.close.bind(this, id),
+              message: options!.closeConfirmMessage || '',
+            });
           });
         };
-        */
       }
 
       this._createDialog(id, html, options as InternalDialogOptions, createOnly || false);