From: Alexander Ebert Date: Fri, 27 Nov 2020 18:51:14 +0000 (+0100) Subject: Resolved a few compatibility issues X-Git-Tag: 5.4.0_Alpha_1~577 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=40d1dbb64df15432f86dc8c9b3c11442760869a6;p=GitHub%2FWoltLab%2FWCF.git Resolved a few compatibility issues The internal ids must remain strings, because the legacy `Dictionary` implementation relied on a plain object. In JavaScript objects, all keys are implicitly converted to strings, but Map treats `1` and `"1"` to be different. --- diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/StringUtil.js b/wcfsetup/install/files/js/WoltLabSuite/Core/StringUtil.js index a940cc2b6e..28e090fadb 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/StringUtil.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/StringUtil.js @@ -10,7 +10,7 @@ define(["require", "exports", "tslib", "./NumberUtil"], function (require, exports, tslib_1, NumberUtil) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - exports.setupI18n = exports.shortUnit = exports.unescapeHTML = exports.ucfirst = exports.lcfirst = exports.formatNumeric = exports.escapeRegExp = exports.escapeHTML = exports.addThousandsSeparator = void 0; + exports.setupI18n = exports.toCamelCase = exports.shortUnit = exports.unescapeHTML = exports.ucfirst = exports.lcfirst = exports.formatNumeric = exports.escapeRegExp = exports.escapeHTML = exports.addThousandsSeparator = void 0; NumberUtil = tslib_1.__importStar(NumberUtil); let _decimalPoint = "."; let _thousandsSeparator = ","; @@ -106,6 +106,25 @@ define(["require", "exports", "tslib", "./NumberUtil"], function (require, expor return formatNumeric(number) + unitSuffix; } exports.shortUnit = shortUnit; + /** + * Converts a lower-case string containing dashed to camelCase for use + * with the `dataset` property. + */ + function toCamelCase(value) { + if (!value.includes("-")) { + return value; + } + return value + .split("-") + .map((part, index) => { + if (index > 0) { + part = ucfirst(part); + } + return part; + }) + .join(""); + } + exports.toCamelCase = toCamelCase; function setupI18n(values) { _decimalPoint = values.decimalPoint; _thousandsSeparator = values.thousandsSeparator; diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Message/InlineEditor.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Message/InlineEditor.js index feae49bcec..45d9899da3 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Message/InlineEditor.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Message/InlineEditor.js @@ -509,7 +509,7 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ch * Returns the element's `data-object-id` value. */ _getObjectId(element) { - return ~~(element.dataset.objectId || ""); + return element.dataset.objectId || ""; } _ajaxFailure(data) { const elementData = this._elements.get(this._activeElement); diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Message/Manager.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Message/Manager.js index ef6e6f0ac8..ca46eb1049 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Message/Manager.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Message/Manager.js @@ -6,12 +6,13 @@ * @license GNU Lesser General Public License * @module WoltLabSuite/Core/Ui/Message/Manager */ -define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Change/Listener", "../../Language"], function (require, exports, tslib_1, Ajax, Core, Listener_1, Language) { +define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Change/Listener", "../../Language", "../../StringUtil"], function (require, exports, tslib_1, Ajax, Core, Listener_1, Language, StringUtil) { "use strict"; Ajax = tslib_1.__importStar(Ajax); Core = tslib_1.__importStar(Core); Listener_1 = tslib_1.__importDefault(Listener_1); Language = tslib_1.__importStar(Language); + StringUtil = tslib_1.__importStar(StringUtil); class UiMessageManager { /** * Initializes a new manager instance. @@ -32,8 +33,7 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ch rebuild() { this._elements.clear(); document.querySelectorAll(this._options.selector).forEach((element) => { - const objectId = ~~(element.dataset.objectId || "0"); - this._elements.set(objectId, element); + this._elements.set(element.dataset.objectId, element); }); } /** @@ -41,7 +41,7 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ch * with "can" or "can-" as this is automatically assumed by this method. */ getPermission(objectId, permission) { - permission = "can-" + this._getAttributeName(permission); + permission = "can" + StringUtil.ucfirst(permission); const element = this._elements.get(objectId); if (element === undefined) { throw new Error(`Unknown object id '${objectId}' for selector '${this._options.selector}'`); @@ -56,8 +56,7 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ch if (element === undefined) { throw new Error(`Unknown object id '${objectId}' for selector '${this._options.selector}'`); } - const attributeName = this._getAttributeName(propertyName); - const value = element.dataset[attributeName] || ""; + const value = element.dataset[StringUtil.toCamelCase(propertyName)] || ""; if (asBool) { return Core.stringToBool(value); } @@ -125,8 +124,7 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ch * Updates a single property of a message element. */ _update(element, propertyName, propertyValue) { - const attributeName = this._getAttributeName(propertyName); - element.dataset[attributeName] = propertyValue.toString(); + element.dataset[propertyName] = propertyValue.toString(); // handle special properties const propertyValueBoolean = propertyValue == 1 || propertyValue === true || propertyValue === "true"; this._updateState(element, propertyName, propertyValue, propertyValueBoolean); @@ -194,6 +192,8 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ch } /** * Transforms camel-cased property names into their attribute equivalent. + * + * @deprecated 5.4 Access the value via `element.dataset` which uses camel-case. */ _getAttributeName(propertyName) { if (propertyName.indexOf("-") !== -1) { diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/StringUtil.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/StringUtil.ts index 407c5d60cd..9c7c3b438b 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/StringUtil.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/StringUtil.ts @@ -111,6 +111,27 @@ export function shortUnit(number: number): string { return formatNumeric(number) + unitSuffix; } +/** + * Converts a lower-case string containing dashed to camelCase for use + * with the `dataset` property. + */ +export function toCamelCase(value: string): string { + if (!value.includes("-")) { + return value; + } + + return value + .split("-") + .map((part, index) => { + if (index > 0) { + part = ucfirst(part); + } + + return part; + }) + .join(""); +} + interface I18nValues { decimalPoint: string; thousandsSeparator: string; diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Message/InlineEditor.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Message/InlineEditor.ts index 0dd0e8ee22..90d0e37304 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Message/InlineEditor.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Message/InlineEditor.ts @@ -24,7 +24,7 @@ interface MessageInlineEditorOptions { canEditInline: boolean; className: string; - containerId: number; + containerId: string; dropdownIdentifier: string; editorPrefix: string; @@ -656,7 +656,7 @@ class UiMessageInlineEditor implements AjaxCallbackObject { /** * Returns the hash added to the url after successfully editing a message. */ - protected _getHash(objectId: number): string { + protected _getHash(objectId: string): string { return `#message${objectId}`; } @@ -678,8 +678,8 @@ class UiMessageInlineEditor implements AjaxCallbackObject { /** * Returns the element's `data-object-id` value. */ - protected _getObjectId(element: HTMLElement): number { - return ~~(element.dataset.objectId || ""); + protected _getObjectId(element: HTMLElement): string { + return element.dataset.objectId || ""; } _ajaxFailure(data: ResponseData): boolean { diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Message/Manager.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Message/Manager.ts index 5d38424c19..f4403ef622 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Message/Manager.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Message/Manager.ts @@ -12,6 +12,7 @@ import { AjaxCallbackObject, AjaxCallbackSetup, ResponseData } from "../../Ajax/ import * as Core from "../../Core"; import DomChangeListener from "../../Dom/Change/Listener"; import * as Language from "../../Language"; +import * as StringUtil from "../../StringUtil"; interface MessageManagerOptions { className: string; @@ -21,7 +22,7 @@ interface MessageManagerOptions { type StringableValue = boolean | number | string; class UiMessageManager implements AjaxCallbackObject { - protected readonly _elements = new Map(); + protected readonly _elements = new Map(); protected readonly _options: MessageManagerOptions; /** @@ -49,8 +50,7 @@ class UiMessageManager implements AjaxCallbackObject { this._elements.clear(); document.querySelectorAll(this._options.selector).forEach((element: HTMLElement) => { - const objectId = ~~(element.dataset.objectId || "0"); - this._elements.set(objectId, element); + this._elements.set(element.dataset.objectId!, element); }); } @@ -58,8 +58,8 @@ class UiMessageManager implements AjaxCallbackObject { * Returns a boolean value for the given permission. The permission should not start * with "can" or "can-" as this is automatically assumed by this method. */ - getPermission(objectId: number, permission: string): boolean { - permission = "can-" + this._getAttributeName(permission); + getPermission(objectId: string, permission: string): boolean { + permission = "can" + StringUtil.ucfirst(permission); const element = this._elements.get(objectId); if (element === undefined) { throw new Error(`Unknown object id '${objectId}' for selector '${this._options.selector}'`); @@ -71,14 +71,13 @@ class UiMessageManager implements AjaxCallbackObject { /** * Returns the given property value from a message, optionally supporting a boolean return value. */ - getPropertyValue(objectId: number, propertyName: string, asBool: boolean): boolean | string { + getPropertyValue(objectId: string, propertyName: string, asBool: boolean): boolean | string { const element = this._elements.get(objectId); if (element === undefined) { throw new Error(`Unknown object id '${objectId}' for selector '${this._options.selector}'`); } - const attributeName = this._getAttributeName(propertyName); - const value = element.dataset[attributeName] || ""; + const value = element.dataset[StringUtil.toCamelCase(propertyName)] || ""; if (asBool) { return Core.stringToBool(value); @@ -90,7 +89,7 @@ class UiMessageManager implements AjaxCallbackObject { /** * Invokes a method for given message object id in order to alter its state or properties. */ - update(objectId: number, actionName: string, parameters?: ArbitraryObject): void { + update(objectId: string, actionName: string, parameters?: ArbitraryObject): void { Ajax.api(this, { actionName: actionName, parameters: parameters || {}, @@ -103,7 +102,7 @@ class UiMessageManager implements AjaxCallbackObject { * not support setting individual properties per message, instead all property changes * are applied to all matching message objects. */ - updateItems(objectIds: number | number[], data: ArbitraryObject): void { + updateItems(objectIds: string | string[], data: ArbitraryObject): void { if (!Array.isArray(objectIds)) { objectIds = [objectIds]; } @@ -132,7 +131,7 @@ class UiMessageManager implements AjaxCallbackObject { /** * Sets or removes a message note identified by its unique CSS class. */ - setNote(objectId: number, className: string, htmlContent: string): void { + setNote(objectId: string, className: string, htmlContent: string): void { const element = this._elements.get(objectId); if (element === undefined) { throw new Error(`Unknown object id '${objectId}' for selector '${this._options.selector}'`); @@ -158,8 +157,7 @@ class UiMessageManager implements AjaxCallbackObject { * Updates a single property of a message element. */ protected _update(element: HTMLElement, propertyName: string, propertyValue: StringableValue): void { - const attributeName = this._getAttributeName(propertyName); - element.dataset[attributeName] = propertyValue.toString(); + element.dataset[propertyName] = propertyValue.toString(); // handle special properties const propertyValueBoolean = propertyValue == 1 || propertyValue === true || propertyValue === "true"; @@ -255,6 +253,8 @@ class UiMessageManager implements AjaxCallbackObject { /** * Transforms camel-cased property names into their attribute equivalent. + * + * @deprecated 5.4 Access the value via `element.dataset` which uses camel-case. */ protected _getAttributeName(propertyName: string): string { if (propertyName.indexOf("-") !== -1) {