From: Alexander Ebert Date: Fri, 29 May 2015 12:59:29 +0000 (+0200) Subject: Added missing file for `UI/Confirmation` X-Git-Tag: 3.0.0_Beta_1~2307 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=15a48bb3ed323235f68596b66833fea82ae9e2dc;p=GitHub%2FWoltLab%2FWCF.git Added missing file for `UI/Confirmation` --- diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Ajax.js b/wcfsetup/install/files/js/WoltLab/WCF/Ajax.js index d7337037db..5d6e930df8 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/Ajax.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/Ajax.js @@ -56,9 +56,6 @@ define(['AjaxRequest', 'Core', 'ObjectMap'], function(AjaxRequest, Core, ObjectM } var options = callbackObject._ajaxSetup(); - if (typeof data === 'object') { - options.data = Core.extend(data, options.data); - } options.pinData = true; options.callbackObject = callbackObject; @@ -70,6 +67,10 @@ define(['AjaxRequest', 'Core', 'ObjectMap'], function(AjaxRequest, Core, ObjectM if (typeof success === 'function') request.setOption('success', success); if (typeof failure === 'function') request.setOption('failure', failure); + if (typeof data === 'object') { + request.setData(data); + } + request.sendRequest(); _requests.set(callbackObject, request); diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Ajax/Request.js b/wcfsetup/install/files/js/WoltLab/WCF/Ajax/Request.js index 5159795493..7b12064bed 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/Ajax/Request.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/Ajax/Request.js @@ -53,6 +53,10 @@ define(['Core', 'Language', 'DOM/ChangeListener', 'DOM/Util', 'UI/Dialog', 'Wolt callbackObject: null }, options); + if (typeof options.callbackObject === 'object') { + this._options.callbackObject = options.callbackObject; + } + this._options.url = Core.convertLegacyUrl(this._options.url); if (this._options.pinData) { diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Core.js b/wcfsetup/install/files/js/WoltLab/WCF/Core.js index f64496a865..cd8649a37b 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/Core.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/Core.js @@ -90,6 +90,7 @@ define([], function() { */ extend: function(out) { out = out || {}; + var newObj = this.clone(out); for (var i = 1, length = arguments.length; i < length; i++) { var obj = arguments[i]; @@ -99,16 +100,40 @@ define([], function() { for (var key in obj) { if (obj.hasOwnProperty(key)) { if (!Array.isArray(obj[key]) && typeof obj[key] === 'object') { - this.extend(out[key], obj[key]); + if (this.isPlainObject(obj[key])) { + // object literals have the prototype of Object which in return has no parent prototype + newObj[key] = this.extend(out[key], obj[key]); + } + else { + newObj[key] = obj[key]; + } } else { - out[key] = obj[key]; + newObj[key] = obj[key]; } } } } - return out; + return newObj; + }, + + /** + * Returns true if `obj` is an object literal. + * + * @param {*} obj target object + * @returns {boolean} true if target is an object literal + */ + isPlainObject: function(obj) { + if (obj === window || obj.nodeType) { + return false; + } + + if (obj.constructor && !obj.constructor.prototype.hasOwnProperty('isPrototypeOf')) { + return false; + } + + return true; }, /** @@ -138,29 +163,23 @@ define([], function() { * Recursively serializes an object into an encoded URI parameter string. * * @param {object} obj target object + * @param {string=} prefix parameter prefix * @return encoded parameter string */ - serialize: function(obj) { + serialize: function(obj, prefix) { var parameters = []; for (var key in obj) { if (obj.hasOwnProperty(key)) { + var parameterKey = (prefix) ? prefix + '[' + key + ']' : key; var value = obj[key]; - if (Array.isArray(value)) { - for (var i = 0, length = value.length; i < length; i++) { - parameters.push(key + '[]=' + encodeURIComponent(value[i])); - } - - continue; + if (typeof value === 'object') { + parameters.push(this.serialize(value, parameterKey)); } - else if (this.getType(value) === 'Object') { - parameters.push(this.serialize(value)); - - continue; + else { + parameters.push(encodeURIComponent(parameterKey) + '=' + encodeURIComponent(value)); } - - parameters.push(key + '=' + encodeURIComponent(value)); } } diff --git a/wcfsetup/install/files/js/WoltLab/WCF/UI/Confirmation.js b/wcfsetup/install/files/js/WoltLab/WCF/UI/Confirmation.js new file mode 100644 index 0000000000..e7bf4071b0 --- /dev/null +++ b/wcfsetup/install/files/js/WoltLab/WCF/UI/Confirmation.js @@ -0,0 +1,151 @@ +/** + * Provides the confirmation dialog overlay. + * + * @author Alexander Ebert + * @copyright 2001-2015 WoltLab GmbH + * @license GNU Lesser General Public License + * @module WoltLab/WCF/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 WoltLab/WCF/UI/Confirmation + */ + var UIConfirmation = { + /** + * 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} options confirmation options + */ + show: function(options) { + if (_active) { + return; + } + + _options = Core.extend({ + cancel: null, + confirm: null, + legacyCallback: null, + message: '', + 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() : ''; + _text.textContent = _options.message; + + _active = true; + + UIDialog.open('wcfSystemConfirmation', null, { + onClose: this._onClose.bind(this), + onShow: this._onShow.bind(this), + title: Language.get('wcf.global.confirmation.title') + }); + }, + + /** + * Creates the dialog DOM elements. + */ + _createDialog: function() { + var dialog = document.createElement('div'); + dialog.setAttribute('id', 'wcfSystemConfirmation'); + dialog.classList.add('systemConfirmation'); + + _text = document.createElement('p'); + dialog.appendChild(_text); + + _content = document.createElement('div'); + _content.setAttribute('id', 'wcfSystemConfirmationContent'); + dialog.appendChild(_content); + + var formSubmit = document.createElement('div'); + formSubmit.classList.add('formSubmit'); + dialog.appendChild(formSubmit); + + _confirmButton = document.createElement('button'); + _confirmButton.classList.add('buttonPrimary'); + _confirmButton.textContent = Language.get('wcf.global.confirmation.confirm'); + _confirmButton.addEventListener('click', this._confirm.bind(this)); + formSubmit.appendChild(_confirmButton); + + var cancelButton = document.createElement('button'); + cancelButton.textContent = Language.get('wcf.global.confirmation.cancel'); + cancelButton.addEventListener('click', 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); + } + else { + _options.confirm(_options.parameters); + } + + _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); + } + 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(); + } + }; + + return UIConfirmation; +}); diff --git a/wcfsetup/install/files/js/WoltLab/WCF/UI/Dialog.js b/wcfsetup/install/files/js/WoltLab/WCF/UI/Dialog.js index 1c67cf82e6..b5ae883db5 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/UI/Dialog.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/UI/Dialog.js @@ -365,7 +365,7 @@ define( setTimeout(function() { if (data.dialog.getAttribute('aria-hidden') === 'true') { _container.removeChild(data.dialog); - _dialogs.delete(id); + _dialogs['delete'](id); } }, 5000); } diff --git a/wcfsetup/install/files/lib/data/AbstractDatabaseObjectAction.class.php b/wcfsetup/install/files/lib/data/AbstractDatabaseObjectAction.class.php index 879c5f352c..ddf78a03dc 100644 --- a/wcfsetup/install/files/lib/data/AbstractDatabaseObjectAction.class.php +++ b/wcfsetup/install/files/lib/data/AbstractDatabaseObjectAction.class.php @@ -9,6 +9,7 @@ use wcf\system\WCF; use wcf\util\ClassUtil; use wcf\util\JSON; use wcf\util\StringUtil; +use wcf\util\ArrayUtil; /** * Default implementation for DatabaseObject-related actions. @@ -99,6 +100,9 @@ abstract class AbstractDatabaseObjectAction implements IDatabaseObjectAction, ID const TYPE_BOOLEAN = 3; const TYPE_JSON = 4; + const STRUCT_FLAT = 1; + const STRUCT_ARRAY = 2; + /** * Initialize a new DatabaseObject-related action. * @@ -419,7 +423,18 @@ abstract class AbstractDatabaseObjectAction implements IDatabaseObjectAction, ID * @param string $arrayIndex */ protected function readInteger($variableName, $allowEmpty = false, $arrayIndex = '') { - $this->readValue($variableName, $allowEmpty, $arrayIndex, self::TYPE_INTEGER); + $this->readValue($variableName, $allowEmpty, $arrayIndex, self::TYPE_INTEGER, self::STRUCT_FLAT); + } + + /** + * Reads an integer array and validates it. + * + * @param string $variableName + * @param boolean $allowEmpty + * @param string $arrayIndex + */ + protected function readIntegerArray($variableName, $allowEmpty = false, $arrayIndex = '') { + $this->readValue($variableName, $allowEmpty, $arrayIndex, self::TYPE_INTEGER, self::STRUCT_ARRAY); } /** @@ -430,7 +445,7 @@ abstract class AbstractDatabaseObjectAction implements IDatabaseObjectAction, ID * @param string $arrayIndex */ protected function readString($variableName, $allowEmpty = false, $arrayIndex = '') { - $this->readValue($variableName, $allowEmpty, $arrayIndex, self::TYPE_STRING); + $this->readValue($variableName, $allowEmpty, $arrayIndex, self::TYPE_STRING, self::STRUCT_FLAT); } /** @@ -441,7 +456,7 @@ abstract class AbstractDatabaseObjectAction implements IDatabaseObjectAction, ID * @param string $arrayIndex */ protected function readBoolean($variableName, $allowEmpty = false, $arrayIndex = '') { - $this->readValue($variableName, $allowEmpty, $arrayIndex, self::TYPE_BOOLEAN); + $this->readValue($variableName, $allowEmpty, $arrayIndex, self::TYPE_BOOLEAN, self::STRUCT_FLAT); } /** @@ -452,7 +467,7 @@ abstract class AbstractDatabaseObjectAction implements IDatabaseObjectAction, ID * @param string $arrayIndex */ protected function readJSON($variableName, $allowEmpty = false, $arrayIndex = '') { - $this->readValue($variableName, $allowEmpty, $arrayIndex, self::TYPE_JSON); + $this->readValue($variableName, $allowEmpty, $arrayIndex, self::TYPE_JSON, self::STRUCT_FLAT); } /** @@ -464,8 +479,9 @@ abstract class AbstractDatabaseObjectAction implements IDatabaseObjectAction, ID * @param boolean $allowEmpty * @param string $arrayIndex * @param integer $type + * @param integer $structure */ - protected function readValue($variableName, $allowEmpty, $arrayIndex, $type) { + protected function readValue($variableName, $allowEmpty, $arrayIndex, $type, $structure) { if ($arrayIndex) { if (!isset($this->parameters[$arrayIndex])) { throw new SystemException("Corrupt parameters, index '".$arrayIndex."' is missing"); @@ -481,16 +497,30 @@ abstract class AbstractDatabaseObjectAction implements IDatabaseObjectAction, ID case self::TYPE_INTEGER: if (!isset($target[$variableName])) { if ($allowEmpty) { - $target[$variableName] = 0; + $target[$variableName] = ($structure === self::STRUCT_FLAT) ? 0 : array(); } else { throw new UserInputException($variableName); } } else { - $target[$variableName] = intval($target[$variableName]); - if (!$allowEmpty && !$target[$variableName]) { - throw new UserInputException($variableName); + if ($structure === self::STRUCT_FLAT) { + $target[$variableName] = intval($target[$variableName]); + if (!$allowEmpty && !$target[$variableName]) { + throw new UserInputException($variableName); + } + } + else { + $target[$variableName] = ArrayUtil::toIntegerArray($target[$variableName]); + if (!is_array($target[$variableName])) { + throw new UserInputException($variableName); + } + + for ($i = 0, $length = count($target[$variableName]); $i < $length; $i++) { + if ($target[$variableName][$i] === 0) { + throw new UserInputException($variableName); + } + } } } break;