From 95418cc665ebd643bef90bb229abe8a2bd3e0dcf Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Wed, 4 Nov 2020 19:13:33 +0100 Subject: [PATCH] `StringUtil` no longer has a circular dependency on `Language` --- .../files/js/WoltLabSuite/Core/Bootstrap.js | 58 +++--- .../files/js/WoltLabSuite/Core/StringUtil.js | 29 ++- .../files/ts/WoltLabSuite/Core/Bootstrap.js | 167 ++++++++++-------- .../files/ts/WoltLabSuite/Core/StringUtil.ts | 35 ++-- 4 files changed, 162 insertions(+), 127 deletions(-) diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Bootstrap.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Bootstrap.js index 401e705ae1..d9b4029283 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Bootstrap.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Bootstrap.js @@ -3,18 +3,32 @@ * It defines globals needed for backwards compatibility * and runs modules that are needed on page load. * - * @author Tim Duesterhus - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/Bootstrap + * @author Tim Duesterhus + * @copyright 2001-2019 WoltLab GmbH + * @license GNU Lesser General Public License + * @module WoltLabSuite/Core/Bootstrap */ define([ - 'favico', 'enquire', 'perfect-scrollbar', 'WoltLabSuite/Core/Date/Time/Relative', - 'Ui/SimpleDropdown', 'WoltLabSuite/Core/Ui/Mobile', 'WoltLabSuite/Core/Ui/TabMenu', 'WoltLabSuite/Core/Ui/FlexibleMenu', - 'Ui/Dialog', 'WoltLabSuite/Core/Ui/Tooltip', 'WoltLabSuite/Core/Language', 'WoltLabSuite/Core/Environment', - 'WoltLabSuite/Core/Date/Picker', 'EventHandler', 'Core', 'WoltLabSuite/Core/Ui/Page/Action', - 'Devtools', 'Dom/ChangeListener' -], function (favico, enquire, perfectScrollbar, DateTimeRelative, UiSimpleDropdown, UiMobile, UiTabMenu, UiFlexibleMenu, UiDialog, UiTooltip, Language, Environment, DatePicker, EventHandler, Core, UiPageAction, Devtools, DomChangeListener) { + "favico", + "enquire", + "perfect-scrollbar", + "WoltLabSuite/Core/Date/Time/Relative", + "Ui/SimpleDropdown", + "WoltLabSuite/Core/Ui/Mobile", + "WoltLabSuite/Core/Ui/TabMenu", + "WoltLabSuite/Core/Ui/FlexibleMenu", + "Ui/Dialog", + "WoltLabSuite/Core/Ui/Tooltip", + "WoltLabSuite/Core/Language", + "WoltLabSuite/Core/Environment", + "WoltLabSuite/Core/Date/Picker", + "EventHandler", + "Core", + "WoltLabSuite/Core/Ui/Page/Action", + "Devtools", + "Dom/ChangeListener", + "StringUtil" +], function (favico, enquire, perfectScrollbar, DateTimeRelative, UiSimpleDropdown, UiMobile, UiTabMenu, UiFlexibleMenu, UiDialog, UiTooltip, Language, Environment, DatePicker, EventHandler, Core, UiPageAction, Devtools, DomChangeListener, StringUtil) { "use strict"; // perfectScrollbar does not need to be bound anywhere, it just has to be loaded for WCF.js window.Favico = favico; @@ -30,7 +44,7 @@ define([ // WCF.System.Event compatibility window.__wcf_bc_eventHandler = EventHandler; /** - * @exports WoltLabSuite/Core/Bootstrap + * @exports WoltLabSuite/Core/Bootstrap */ return { /** @@ -42,6 +56,10 @@ define([ options = Core.extend({ enableMobileMenu: true }, options); + StringUtil.setupI18n({ + decimalPoint: Language.get("wcf.global.decimalPoint"), + thousandsSeparator: Language.get("wcf.global.thousandsSeparator") + }); //noinspection JSUnresolvedVariable if (window.ENABLE_DEVELOPER_TOOLS) Devtools._internal_.enable(); @@ -57,18 +75,18 @@ define([ UiDialog.setup(); UiTooltip.setup(); // convert method=get into method=post - var forms = elBySelAll('form[method=get]'); + var forms = elBySelAll("form[method=get]"); for (var i = 0, length = forms.length; i < length; i++) { - forms[i].setAttribute('method', 'post'); + forms[i].setAttribute("method", "post"); } - if (Environment.browser() === 'microsoft') { + if (Environment.browser() === "microsoft") { window.onbeforeunload = function () { /* Prevent "Back navigation caching" (http://msdn.microsoft.com/en-us/library/ie/dn265017%28v=vs.85%29.aspx) */ }; } var interval = 0; interval = window.setInterval(function () { - if (typeof window.jQuery === 'function') { + if (typeof window.jQuery === "function") { window.clearInterval(interval); // the 'jump to top' button triggers style recalculation/layout, // putting it at the end of the jQuery queue avoids trashing the @@ -80,14 +98,14 @@ define([ } }, 20); this._initA11y(); - DomChangeListener.add('WoltLabSuite/Core/Bootstrap', this._initA11y.bind(this)); + DomChangeListener.add("WoltLabSuite/Core/Bootstrap", this._initA11y.bind(this)); }, _initA11y: function () { - elBySelAll('nav:not([aria-label]):not([aria-labelledby]):not([role])', undefined, function (element) { - elAttr(element, 'role', 'presentation'); + elBySelAll("nav:not([aria-label]):not([aria-labelledby]):not([role])", undefined, function (element) { + elAttr(element, "role", "presentation"); }); - elBySelAll('article:not([aria-label]):not([aria-labelledby]):not([role])', undefined, function (element) { - elAttr(element, 'role', 'presentation'); + elBySelAll("article:not([aria-label]):not([aria-labelledby]):not([role])", undefined, function (element) { + elAttr(element, "role", "presentation"); }); } }; diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/StringUtil.js b/wcfsetup/install/files/js/WoltLabSuite/Core/StringUtil.js index 78f7aca3b5..a940cc2b6e 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/StringUtil.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/StringUtil.js @@ -7,24 +7,20 @@ * @module StringUtil (alias) * @module WoltLabSuite/Core/StringUtil */ -define(["require", "exports", "tslib", "./Language", "./NumberUtil"], function (require, exports, tslib_1, Language, NumberUtil) { +define(["require", "exports", "tslib", "./NumberUtil"], function (require, exports, tslib_1, NumberUtil) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - exports.shortUnit = exports.unescapeHTML = exports.ucfirst = exports.lcfirst = exports.formatNumeric = exports.escapeRegExp = exports.escapeHTML = exports.addThousandsSeparator = void 0; - Language = tslib_1.__importStar(Language); + exports.setupI18n = 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 = ","; /** * Adds thousands separators to a given number. * * @see http://stackoverflow.com/a/6502556/782822 */ function addThousandsSeparator(number) { - // Fetch Language, as it cannot be provided because of a circular dependency - if (Language === undefined) { - // @ts-expect-error: This is required due to a circular dependency. - Language = require("./Language"); - } - return String(number).replace(/(^-?\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, "$1" + Language.get("wcf.global.thousandsSeparator")); + return String(number).replace(/(^-?\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, "$1" + _thousandsSeparator); } exports.addThousandsSeparator = addThousandsSeparator; /** @@ -47,16 +43,12 @@ define(["require", "exports", "tslib", "./Language", "./NumberUtil"], function ( * Rounds number to given count of floating point digits, localizes decimal-point and inserts thousands separators. */ function formatNumeric(number, decimalPlaces) { - // Fetch Language, as it cannot be provided because of a circular dependency - if (Language === undefined) { - // @ts-expect-error: This is required due to a circular dependency. - Language = require("./Language"); - } let tmp = NumberUtil.round(number, decimalPlaces || -2).toString(); const numberParts = tmp.split("."); tmp = addThousandsSeparator(+numberParts[0]); - if (numberParts.length > 1) - tmp += Language.get("wcf.global.decimalPoint") + numberParts[1]; + if (numberParts.length > 1) { + tmp += _decimalPoint + numberParts[1]; + } tmp = tmp.replace("-", "\u2212"); return tmp; } @@ -114,4 +106,9 @@ define(["require", "exports", "tslib", "./Language", "./NumberUtil"], function ( return formatNumeric(number) + unitSuffix; } exports.shortUnit = shortUnit; + function setupI18n(values) { + _decimalPoint = values.decimalPoint; + _thousandsSeparator = values.thousandsSeparator; + } + exports.setupI18n = setupI18n; }); diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.js b/wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.js index 401e705ae1..30b6d3f74b 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.js +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.js @@ -3,92 +3,113 @@ * It defines globals needed for backwards compatibility * and runs modules that are needed on page load. * - * @author Tim Duesterhus - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/Bootstrap + * @author Tim Duesterhus + * @copyright 2001-2019 WoltLab GmbH + * @license GNU Lesser General Public License + * @module WoltLabSuite/Core/Bootstrap */ -define([ - 'favico', 'enquire', 'perfect-scrollbar', 'WoltLabSuite/Core/Date/Time/Relative', - 'Ui/SimpleDropdown', 'WoltLabSuite/Core/Ui/Mobile', 'WoltLabSuite/Core/Ui/TabMenu', 'WoltLabSuite/Core/Ui/FlexibleMenu', - 'Ui/Dialog', 'WoltLabSuite/Core/Ui/Tooltip', 'WoltLabSuite/Core/Language', 'WoltLabSuite/Core/Environment', - 'WoltLabSuite/Core/Date/Picker', 'EventHandler', 'Core', 'WoltLabSuite/Core/Ui/Page/Action', - 'Devtools', 'Dom/ChangeListener' -], function (favico, enquire, perfectScrollbar, DateTimeRelative, UiSimpleDropdown, UiMobile, UiTabMenu, UiFlexibleMenu, UiDialog, UiTooltip, Language, Environment, DatePicker, EventHandler, Core, UiPageAction, Devtools, DomChangeListener) { +define( + [ + "favico", + "enquire", + "perfect-scrollbar", + "WoltLabSuite/Core/Date/Time/Relative", + "Ui/SimpleDropdown", + "WoltLabSuite/Core/Ui/Mobile", + "WoltLabSuite/Core/Ui/TabMenu", + "WoltLabSuite/Core/Ui/FlexibleMenu", + "Ui/Dialog", + "WoltLabSuite/Core/Ui/Tooltip", + "WoltLabSuite/Core/Language", + "WoltLabSuite/Core/Environment", + "WoltLabSuite/Core/Date/Picker", + "EventHandler", + "Core", + "WoltLabSuite/Core/Ui/Page/Action", + "Devtools", + "Dom/ChangeListener", + "StringUtil" + ], + function(favico, enquire, perfectScrollbar, DateTimeRelative, UiSimpleDropdown, UiMobile, UiTabMenu, UiFlexibleMenu, UiDialog, UiTooltip, Language, Environment, DatePicker, EventHandler, Core, UiPageAction, Devtools, DomChangeListener, StringUtil) { "use strict"; // perfectScrollbar does not need to be bound anywhere, it just has to be loaded for WCF.js window.Favico = favico; window.enquire = enquire; // non strict equals by intent - if (window.WCF == null) - window.WCF = {}; - if (window.WCF.Language == null) - window.WCF.Language = {}; + if (window.WCF == null) window.WCF = {}; + if (window.WCF.Language == null) window.WCF.Language = {}; window.WCF.Language.get = Language.get; window.WCF.Language.add = Language.add; window.WCF.Language.addObject = Language.addObject; // WCF.System.Event compatibility window.__wcf_bc_eventHandler = EventHandler; + /** - * @exports WoltLabSuite/Core/Bootstrap + * @exports WoltLabSuite/Core/Bootstrap */ return { - /** - * Initializes the core UI modifications and unblocks jQuery's ready event. - * - * @param {Object=} options initialization options - */ - setup: function (options) { - options = Core.extend({ - enableMobileMenu: true - }, options); - //noinspection JSUnresolvedVariable - if (window.ENABLE_DEVELOPER_TOOLS) - Devtools._internal_.enable(); - Environment.setup(); - DateTimeRelative.setup(); - DatePicker.init(); - UiSimpleDropdown.setup(); - UiMobile.setup({ - enableMobileMenu: options.enableMobileMenu - }); - UiTabMenu.setup(); - //UiFlexibleMenu.setup(); - UiDialog.setup(); - UiTooltip.setup(); - // convert method=get into method=post - var forms = elBySelAll('form[method=get]'); - for (var i = 0, length = forms.length; i < length; i++) { - forms[i].setAttribute('method', 'post'); - } - if (Environment.browser() === 'microsoft') { - window.onbeforeunload = function () { - /* Prevent "Back navigation caching" (http://msdn.microsoft.com/en-us/library/ie/dn265017%28v=vs.85%29.aspx) */ - }; - } - var interval = 0; - interval = window.setInterval(function () { - if (typeof window.jQuery === 'function') { - window.clearInterval(interval); - // the 'jump to top' button triggers style recalculation/layout, - // putting it at the end of the jQuery queue avoids trashing the - // layout too early and thus delaying the page initialization - window.jQuery(function () { - UiPageAction.setup(); - }); - window.jQuery.holdReady(false); - } - }, 20); - this._initA11y(); - DomChangeListener.add('WoltLabSuite/Core/Bootstrap', this._initA11y.bind(this)); - }, - _initA11y: function () { - elBySelAll('nav:not([aria-label]):not([aria-labelledby]):not([role])', undefined, function (element) { - elAttr(element, 'role', 'presentation'); - }); - elBySelAll('article:not([aria-label]):not([aria-labelledby]):not([role])', undefined, function (element) { - elAttr(element, 'role', 'presentation'); - }); + /** + * Initializes the core UI modifications and unblocks jQuery's ready event. + * + * @param {Object=} options initialization options + */ + setup: function(options) { + options = Core.extend({ + enableMobileMenu: true + }, options); + + StringUtil.setupI18n({ + decimalPoint: Language.get("wcf.global.decimalPoint"), + thousandsSeparator: Language.get("wcf.global.thousandsSeparator") + }); + + //noinspection JSUnresolvedVariable + if (window.ENABLE_DEVELOPER_TOOLS) Devtools._internal_.enable(); + Environment.setup(); + DateTimeRelative.setup(); + DatePicker.init(); + UiSimpleDropdown.setup(); + UiMobile.setup({ + enableMobileMenu: options.enableMobileMenu + }); + UiTabMenu.setup(); + //UiFlexibleMenu.setup(); + UiDialog.setup(); + UiTooltip.setup(); + // convert method=get into method=post + var forms = elBySelAll("form[method=get]"); + for (var i = 0, length = forms.length; i < length; i++) { + forms[i].setAttribute("method", "post"); } + if (Environment.browser() === "microsoft") { + window.onbeforeunload = function() { + /* Prevent "Back navigation caching" (http://msdn.microsoft.com/en-us/library/ie/dn265017%28v=vs.85%29.aspx) */ + }; + } + var interval = 0; + interval = window.setInterval(function() { + if (typeof window.jQuery === "function") { + window.clearInterval(interval); + // the 'jump to top' button triggers style recalculation/layout, + // putting it at the end of the jQuery queue avoids trashing the + // layout too early and thus delaying the page initialization + window.jQuery(function() { + UiPageAction.setup(); + }); + window.jQuery.holdReady(false); + } + }, 20); + this._initA11y(); + DomChangeListener.add("WoltLabSuite/Core/Bootstrap", this._initA11y.bind(this)); + }, + _initA11y: function() { + elBySelAll("nav:not([aria-label]):not([aria-labelledby]):not([role])", undefined, function(element) { + elAttr(element, "role", "presentation"); + }); + elBySelAll("article:not([aria-label]):not([aria-labelledby]):not([role])", undefined, function(element) { + elAttr(element, "role", "presentation"); + }); + } }; -}); + } +); diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/StringUtil.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/StringUtil.ts index 6a1fbf7cf6..407c5d60cd 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/StringUtil.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/StringUtil.ts @@ -8,25 +8,18 @@ * @module WoltLabSuite/Core/StringUtil */ -import * as Language from "./Language"; import * as NumberUtil from "./NumberUtil"; +let _decimalPoint = "."; +let _thousandsSeparator = ","; + /** * Adds thousands separators to a given number. * * @see http://stackoverflow.com/a/6502556/782822 */ export function addThousandsSeparator(number: number): string { - // Fetch Language, as it cannot be provided because of a circular dependency - if (Language === undefined) { - // @ts-expect-error: This is required due to a circular dependency. - Language = require("./Language"); - } - - return String(number).replace( - /(^-?\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, - "$1" + Language.get("wcf.global.thousandsSeparator"), - ); + return String(number).replace(/(^-?\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, "$1" + _thousandsSeparator); } /** @@ -49,17 +42,13 @@ export function escapeRegExp(string: string): string { * Rounds number to given count of floating point digits, localizes decimal-point and inserts thousands separators. */ export function formatNumeric(number: number, decimalPlaces?: number): string { - // Fetch Language, as it cannot be provided because of a circular dependency - if (Language === undefined) { - // @ts-expect-error: This is required due to a circular dependency. - Language = require("./Language"); - } - let tmp = NumberUtil.round(number, decimalPlaces || -2).toString(); const numberParts = tmp.split("."); tmp = addThousandsSeparator(+numberParts[0]); - if (numberParts.length > 1) tmp += Language.get("wcf.global.decimalPoint") + numberParts[1]; + if (numberParts.length > 1) { + tmp += _decimalPoint + numberParts[1]; + } tmp = tmp.replace("-", "\u2212"); @@ -121,3 +110,13 @@ export function shortUnit(number: number): string { return formatNumeric(number) + unitSuffix; } + +interface I18nValues { + decimalPoint: string; + thousandsSeparator: string; +} + +export function setupI18n(values: I18nValues): void { + _decimalPoint = values.decimalPoint; + _thousandsSeparator = values.thousandsSeparator; +} -- 2.20.1