From 93fdc495d6c8443deb0e7af8d267dc4a2af6c224 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Fri, 1 Jan 2021 12:45:43 +0100 Subject: [PATCH] Convert `Bootstrap` to TypeScript --- global.d.ts | 3 + package-lock.json | 6 + package.json | 1 + .../files/js/WoltLabSuite/Core/Bootstrap.js | 164 +++++++++--------- .../files/ts/WoltLabSuite/Core/Bootstrap.js | 111 ------------ .../files/ts/WoltLabSuite/Core/Bootstrap.ts | 124 +++++++++++++ 6 files changed, 213 insertions(+), 196 deletions(-) delete mode 100644 wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.js create mode 100644 wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.ts diff --git a/global.d.ts b/global.d.ts index 45b8cc9743..d2933f9fb0 100644 --- a/global.d.ts +++ b/global.d.ts @@ -2,6 +2,7 @@ import DatePicker from "./wcfsetup/install/files/ts/WoltLabSuite/Core/Date/Picke import Devtools from "./wcfsetup/install/files/ts/WoltLabSuite/Core/Devtools"; import DomUtil from "./wcfsetup/install/files/ts/WoltLabSuite/Core/Dom/Util"; import * as ColorUtil from "./wcfsetup/install/files/ts/WoltLabSuite/Core/ColorUtil"; +import * as EventHandler from "./wcfsetup/install/files/ts/WoltLabSuite/Core/Event/Handler"; import UiDropdownSimple from "./wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Dropdown/Simple"; import "@woltlab/zxcvbn"; import { Reaction } from "./wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Reaction/Data"; @@ -20,6 +21,7 @@ declare global { WCF_PATH: string; WSC_API_URL: string; + Favico: any; jQuery: JQueryStatic; WCF: any; bc_wcfDomUtil: typeof DomUtil; @@ -27,6 +29,7 @@ declare global { __wcf_bc_colorPickerInit?: () => void; __wcf_bc_colorUtil: typeof ColorUtil; __wcf_bc_datePicker: typeof DatePicker; + __wcf_bc_eventHandler: typeof EventHandler; } interface String { diff --git a/package-lock.json b/package-lock.json index be241647fe..159f6b19cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -131,6 +131,12 @@ "resolved": "https://registry.npmjs.org/@types/facebook-js-sdk/-/facebook-js-sdk-3.3.1.tgz", "integrity": "sha512-jRVPdOu237QxDDoBjc9/xzGsDz75FmdvcwVZdCEg1AjHAQxGmXoHfACUyUVtz7DSWA4E+jgj5MQME4snjGwOng==" }, + "@types/favico.js": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@types/favico.js/-/favico.js-0.0.28.tgz", + "integrity": "sha1-u3t8qhGCFzGNA0Zmkg1oeljWXus=", + "dev": true + }, "@types/jquery": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.4.tgz", diff --git a/package.json b/package.json index 24987ad4c3..2c82ef9421 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "@woltlab/wcf", "version": "5.4.0", "devDependencies": { + "@types/favico.js": "0.0.28", "@types/perfect-scrollbar": "^0.6.1", "@typescript-eslint/eslint-plugin": "^4.6.0", "@typescript-eslint/parser": "^4.6.0", diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Bootstrap.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Bootstrap.js index 6869385597..65bec3ba5e 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Bootstrap.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Bootstrap.js @@ -8,101 +8,95 @@ * @license GNU Lesser General Public License * @module WoltLabSuite/Core/Bootstrap */ -define([ - "favico", - "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, perfectScrollbar, DateTimeRelative, UiSimpleDropdown, UiMobile, UiTabMenu, UiFlexibleMenu, UiDialog, UiTooltip, Language, Environment, DatePicker, EventHandler, Core, UiPageAction, Devtools, DomChangeListener, StringUtil) { +define(["require", "exports", "tslib", "./Core", "./Date/Picker", "./Date/Time/Relative", "./Devtools", "./Dom/Change/Listener", "./Environment", "./Event/Handler", "./Language", "./StringUtil", "./Ui/Dialog", "./Ui/Dropdown/Simple", "./Ui/Mobile", "./Ui/Page/Action", "./Ui/TabMenu", "./Ui/Tooltip", "favico.js"], function (require, exports, tslib_1, Core, Picker_1, DateTimeRelative, Devtools_1, Listener_1, Environment, EventHandler, Language, StringUtil, Dialog_1, Simple_1, UiMobile, UiPageAction, UiTabMenu, UiTooltip) { "use strict"; - // perfectScrollbar does not need to be bound anywhere, it just has to be loaded for WCF.js - window.Favico = favico; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.setup = void 0; + Core = tslib_1.__importStar(Core); + Picker_1 = tslib_1.__importDefault(Picker_1); + DateTimeRelative = tslib_1.__importStar(DateTimeRelative); + Devtools_1 = tslib_1.__importDefault(Devtools_1); + Listener_1 = tslib_1.__importDefault(Listener_1); + Environment = tslib_1.__importStar(Environment); + EventHandler = tslib_1.__importStar(EventHandler); + Language = tslib_1.__importStar(Language); + StringUtil = tslib_1.__importStar(StringUtil); + Dialog_1 = tslib_1.__importDefault(Dialog_1); + Simple_1 = tslib_1.__importDefault(Simple_1); + UiMobile = tslib_1.__importStar(UiMobile); + UiPageAction = tslib_1.__importStar(UiPageAction); + UiTabMenu = tslib_1.__importStar(UiTabMenu); + UiTooltip = tslib_1.__importStar(UiTooltip); // non strict equals by intent - if (window.WCF == null) + if (window.WCF == null) { window.WCF = {}; - if (window.WCF.Language == null) + } + 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; + function initA11y() { + document + .querySelectorAll("nav:not([aria-label]):not([aria-labelledby]):not([role])") + .forEach((element) => { + element.setAttribute("role", "presentation"); + }); + document + .querySelectorAll("article:not([aria-label]):not([aria-labelledby]):not([role])") + .forEach((element) => { + element.setAttribute("role", "presentation"); + }); + } /** - * @exports WoltLabSuite/Core/Bootstrap + * Initializes the core UI modifications and unblocks jQuery's ready event. */ - 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); - 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(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"); - }); + function setup(options) { + options = Core.extend({ + enableMobileMenu: true, + }, options); + StringUtil.setupI18n({ + decimalPoint: Language.get("wcf.global.decimalPoint"), + thousandsSeparator: Language.get("wcf.global.thousandsSeparator"), + }); + if (window.ENABLE_DEVELOPER_TOOLS) { + Devtools_1.default._internal_.enable(); } - }; + Environment.setup(); + DateTimeRelative.setup(); + Picker_1.default.init(); + Simple_1.default.setup(); + UiMobile.setup(options.enableMobileMenu); + UiTabMenu.setup(); + Dialog_1.default.setup(); + UiTooltip.setup(); + // Convert forms with `method="get"` into `method="post"` + document.querySelectorAll("form[method=get]").forEach((form) => { + form.method = "post"; + }); + if (Environment.browser() === "microsoft") { + window.onbeforeunload = () => { + /* Prevent "Back navigation caching" (http://msdn.microsoft.com/en-us/library/ie/dn265017%28v=vs.85%29.aspx) */ + }; + } + let interval = 0; + interval = window.setInterval(() => { + if (typeof window.jQuery === "function") { + window.clearInterval(interval); + // The 'jump to top' button triggers a style recalculation/"layout". + // Placing it at the end of the jQuery queue avoids trashing the + // layout too early and thus delaying the page initialization. + window.jQuery(() => { + UiPageAction.setup(); + }); + window.jQuery.holdReady(false); + } + }, 20); + initA11y(); + Listener_1.default.add("WoltLabSuite/Core/Bootstrap", () => initA11y); + } + exports.setup = setup; }); diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.js b/wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.js deleted file mode 100644 index 2d9bfca818..0000000000 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Bootstraps WCF's JavaScript. - * 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 - */ -define( - [ - "favico", - "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, 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; - // non strict equals by intent - 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 - */ - 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); - - 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(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/Bootstrap.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.ts new file mode 100644 index 0000000000..0bde2bb663 --- /dev/null +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Bootstrap.ts @@ -0,0 +1,124 @@ +/** + * Bootstraps WCF's JavaScript. + * 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 + */ + +import * as Core from "./Core"; +import DatePicker from "./Date/Picker"; +import * as DateTimeRelative from "./Date/Time/Relative"; +import Devtools from "./Devtools"; +import DomChangeListener from "./Dom/Change/Listener"; +import * as Environment from "./Environment"; +import * as EventHandler from "./Event/Handler"; +import * as Language from "./Language"; +import * as StringUtil from "./StringUtil"; +import UiDialog from "./Ui/Dialog"; +import UiDropdownSimple from "./Ui/Dropdown/Simple"; +import * as UiMobile from "./Ui/Mobile"; +import * as UiPageAction from "./Ui/Page/Action"; +import * as UiTabMenu from "./Ui/TabMenu"; +import * as UiTooltip from "./Ui/Tooltip"; + +// Import favico.js into the global namespace. +import "favico.js"; + +// perfectScrollbar does not need to be bound anywhere, it just has to be loaded for WCF.js +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import perfectScrollbar from "perfect-scrollbar"; + +// non strict equals by intent +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; + +interface BoostrapOptions { + enableMobileMenu: boolean; +} + +function initA11y() { + document + .querySelectorAll("nav:not([aria-label]):not([aria-labelledby]):not([role])") + .forEach((element: HTMLElement) => { + element.setAttribute("role", "presentation"); + }); + + document + .querySelectorAll("article:not([aria-label]):not([aria-labelledby]):not([role])") + .forEach((element: HTMLElement) => { + element.setAttribute("role", "presentation"); + }); +} + +/** + * Initializes the core UI modifications and unblocks jQuery's ready event. + */ +export function setup(options: BoostrapOptions): void { + options = Core.extend( + { + enableMobileMenu: true, + }, + options, + ) as BoostrapOptions; + + StringUtil.setupI18n({ + decimalPoint: Language.get("wcf.global.decimalPoint"), + thousandsSeparator: Language.get("wcf.global.thousandsSeparator"), + }); + + if (window.ENABLE_DEVELOPER_TOOLS) { + Devtools._internal_.enable(); + } + + Environment.setup(); + DateTimeRelative.setup(); + DatePicker.init(); + UiDropdownSimple.setup(); + UiMobile.setup(options.enableMobileMenu); + UiTabMenu.setup(); + UiDialog.setup(); + UiTooltip.setup(); + + // Convert forms with `method="get"` into `method="post"` + document.querySelectorAll("form[method=get]").forEach((form: HTMLFormElement) => { + form.method = "post"; + }); + + if (Environment.browser() === "microsoft") { + window.onbeforeunload = () => { + /* Prevent "Back navigation caching" (http://msdn.microsoft.com/en-us/library/ie/dn265017%28v=vs.85%29.aspx) */ + }; + } + + let interval = 0; + interval = window.setInterval(() => { + if (typeof window.jQuery === "function") { + window.clearInterval(interval); + + // The 'jump to top' button triggers a style recalculation/"layout". + // Placing it at the end of the jQuery queue avoids trashing the + // layout too early and thus delaying the page initialization. + window.jQuery(() => { + UiPageAction.setup(); + }); + window.jQuery.holdReady(false); + } + }, 20); + + initA11y(); + + DomChangeListener.add("WoltLabSuite/Core/Bootstrap", () => initA11y); +} -- 2.20.1