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.
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 = ",";
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;
* 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);
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @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.
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);
});
}
/**
* 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}'`);
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);
}
* 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);
}
/**
* 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) {
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;
canEditInline: boolean;
className: string;
- containerId: number;
+ containerId: string;
dropdownIdentifier: string;
editorPrefix: string;
/**
* 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}`;
}
/**
* 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 {
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;
type StringableValue = boolean | number | string;
class UiMessageManager implements AjaxCallbackObject {
- protected readonly _elements = new Map<number, HTMLElement>();
+ protected readonly _elements = new Map<string, HTMLElement>();
protected readonly _options: MessageManagerOptions;
/**
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);
});
}
* 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}'`);
/**
* 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);
/**
* 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 || {},
* 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];
}
/**
* 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}'`);
* 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";
/**
* 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) {