Clean up code style and types for existing TypeScript modules
authorTim Düsterhus <duesterhus@woltlab.com>
Thu, 29 Oct 2020 13:41:49 +0000 (14:41 +0100)
committerTim Düsterhus <duesterhus@woltlab.com>
Thu, 29 Oct 2020 13:41:49 +0000 (14:41 +0100)
46 files changed:
wcfsetup/install/files/js/WoltLabSuite/Core/Ajax/Jsonp.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ajax/Request.js
wcfsetup/install/files/js/WoltLabSuite/Core/CallbackList.js
wcfsetup/install/files/js/WoltLabSuite/Core/Image/Resizer.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Confirmation.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Dialog.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Dropdown/Builder.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Dropdown/Simple.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/JumpTo.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Search.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Pagination.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Screen.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Search/Input.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Smiley/Insert.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Suggestion.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/TabMenu.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/TabMenu/Simple.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Toggle/Input.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Tooltip.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Editor.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Trophy/List.js
wcfsetup/install/files/ts/WoltLabSuite/Core/Ajax/Jsonp.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ajax/Request.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/CallbackList.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Date/Time/Relative.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Date/Util.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Image/Resizer.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Confirmation.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Dialog.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Dropdown/Builder.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Dropdown/Simple.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Page/JumpTo.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Page/Search.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Pagination.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Screen.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Search/Input.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Smiley/Insert.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Suggestion.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/TabMenu.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/TabMenu/Simple.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Toggle/Input.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Tooltip.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/User/Editor.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/User/Search/Input.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/User/Trophy/List.ts
wcfsetup/install/files/ts/WoltLabSuite/Core/User.ts

index 571c7f60b8b9257ab306409669ca50609206735a..dc2bae753eb8b0e4c4d9ea8bff53bcb1a17ffb24 100644 (file)
@@ -34,13 +34,13 @@ define(["require", "exports", "tslib", "../Core"], function (require, exports, t
                 failure();
             }
             window[callbackName] = undefined;
-            script.parentNode.removeChild(script);
+            script.remove();
         }, (~~options.timeout || 10) * 1000);
         window[callbackName] = (...args) => {
             window.clearTimeout(timeout);
             success.apply(null, args);
             window[callbackName] = undefined;
-            script.parentNode.removeChild(script);
+            script.remove();
         };
         url += (url.indexOf('?') === -1) ? '?' : '&';
         url += options.parameterName + '=' + callbackName;
index 83f5235ce042fd4fdbddfa6911534f32cedc0bf4..5c2cb0b4967df92783a6c3cb4499c644cb290beb 100644 (file)
@@ -284,7 +284,7 @@ define(["require", "exports", "tslib", "./Status", "../Core", "../Dom/Change/Lis
             this._previousXhr = undefined;
             Listener_1.default.trigger();
             // fix anchor tags generated through WCF::getAnchor()
-            document.querySelectorAll('a[href*="#"]').forEach(link => {
+            document.querySelectorAll('a[href*="#"]').forEach((link) => {
                 let href = link.href;
                 if (href.indexOf('AJAXProxy') !== -1 || href.indexOf('ajax-proxy') !== -1) {
                     href = href.substr(href.indexOf('#'));
index 04d5ba7fccd5c43cc566be686bdb6226abf0b822..26cdf99eb78f16e965d31276409cec9d5d284515 100644 (file)
@@ -37,7 +37,7 @@ define(["require", "exports"], function (require, exports) {
         forEach(identifier, callback) {
             var _a;
             if (identifier === null) {
-                this._callbacks.forEach(function (callbacks, identifier) {
+                this._callbacks.forEach((callbacks, identifier) => {
                     callbacks.forEach(callback);
                 });
             }
index 6136663f9f96d6334906291b9ea891a48de28b6e..9b9443c841d3e67bdb741f21652551d56ee03601 100644 (file)
@@ -82,18 +82,18 @@ define(["require", "exports", "tslib", "../FileUtil", "./ExifUtil", "pica"], fun
                 // Strip EXIF data
                 fileData = await ExifUtil.removeExifData(fileData);
             }
-            const imageLoader = new Promise(function (resolve, reject) {
+            const imageLoader = new Promise((resolve, reject) => {
                 const reader = new FileReader();
                 const image = new Image();
-                reader.addEventListener("load", function () {
+                reader.addEventListener("load", () => {
                     image.src = reader.result;
                 });
-                reader.addEventListener("error", function () {
+                reader.addEventListener("error", () => {
                     reader.abort();
                     reject(reader.error);
                 });
                 image.addEventListener("error", reject);
-                image.addEventListener("load", function () {
+                image.addEventListener("load", () => {
                     resolve(image);
                 });
                 reader.readAsDataURL(fileData);
index b800e9b232ab071df7815533569461562b98596b..09e2d61dddef65080bbb8f7d678ebc80c7e69d67 100644 (file)
@@ -31,7 +31,7 @@ define(["require", "exports", "tslib", "../Core", "../Language", "./Dialog"], fu
             this.confirmButton = document.createElement('button');
             this.confirmButton.classList.add('buttonPrimary');
             this.confirmButton.textContent = Language.get('wcf.global.confirmation.confirm');
-            this.confirmButton.addEventListener('click', this._confirm.bind(this));
+            this.confirmButton.addEventListener('click', (ev) => this._confirm());
             formSubmit.appendChild(this.confirmButton);
             const cancelButton = document.createElement('button');
             cancelButton.textContent = Language.get('wcf.global.confirmation.cancel');
index aec10acfe2eb2efb7ed055495648fb33f2e1f43c..25a422559677dc0bc292376121c798b6d0ba7cc4 100644 (file)
@@ -53,7 +53,7 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "./S
             _container = document.createElement('div');
             _container.classList.add('dialogOverlay');
             _container.setAttribute('aria-hidden', 'true');
-            _container.addEventListener('mousedown', this._closeOnBackdrop.bind(this));
+            _container.addEventListener('mousedown', (ev) => this._closeOnBackdrop(ev));
             _container.addEventListener('wheel', event => {
                 if (event.target === _container) {
                     event.preventDefault();
@@ -82,7 +82,9 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "./S
                 },
             });
             this._initStaticDialogs();
-            Listener_1.default.add('Ui/Dialog', this._initStaticDialogs.bind(this));
+            Listener_1.default.add('Ui/Dialog', () => {
+                this._initStaticDialogs();
+            });
             UiScreen.setDialogContainer(_container);
             window.addEventListener('resize', () => {
                 _dialogs.forEach(dialog => {
@@ -93,7 +95,7 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "./S
             });
         },
         _initStaticDialogs() {
-            document.querySelectorAll('.jsStaticDialog').forEach(button => {
+            document.querySelectorAll('.jsStaticDialog').forEach((button) => {
                 button.classList.remove('jsStaticDialog');
                 const id = button.dataset.dialogId || '';
                 if (id) {
@@ -306,7 +308,7 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "./S
                 closeButton.tabIndex = 0;
                 closeButton.title = options.closeButtonLabel;
                 closeButton.setAttribute('aria-label', options.closeButtonLabel);
-                closeButton.addEventListener('click', this._close.bind(this));
+                closeButton.addEventListener('click', (ev) => this._close(ev));
                 header.appendChild(closeButton);
                 const span = document.createElement('span');
                 span.className = 'icon icon24 fa-times';
index dd1708d2762247cfb00258071d9faf687a2a726e..a12491e47b952988c565b96833118428bd4a18d3 100644 (file)
@@ -150,9 +150,6 @@ define(["require", "exports", "tslib", "../../Core", "./Simple"], function (requ
      * Attaches the list to a button, visibility is from then on controlled through clicks
      * on the provided button element. Internally calls `Ui/SimpleDropdown.initFragment()`
      * to delegate the DOM management.
-     *
-     * @param       {Element}               list
-     * @param       {Element}               button
      */
     function attach(list, button) {
         validateList(list);
index 8ca05bf7ac00723b1bb8b87cd7132e320f49f240..3833c56b35a3d1e74329d9abbd39394c3e0a343a 100644 (file)
@@ -266,8 +266,9 @@ define(["require", "exports", "tslib", "../../CallbackList", "../../Core", "../.
             button = dropdown.querySelector('.dropdownToggle');
             const mouseEvent = dropdown.dataset.a11yMouseEvent || 'click';
             Core.triggerEvent(target, mouseEvent);
-            if (button)
+            if (button) {
                 button.focus();
+            }
         }
         else if (event.key === 'Escape' || event.key === 'Tab') {
             event.preventDefault();
index 473114031c02d0634ca27c1cc9066bddcec6e498..bfd4f4e23661e3fd81f55f61b7a86efd158ed76c 100644 (file)
@@ -36,8 +36,8 @@ define(["require", "exports", "tslib", "../../Language", "../Dialog"], function
                 throw new TypeError("Expected a valid function for parameter 'callback'.");
             }
             if (!this.elements.has(element)) {
-                element.querySelectorAll('.jumpTo').forEach(jumpTo => {
-                    jumpTo.addEventListener('click', this.click.bind(this, element));
+                element.querySelectorAll('.jumpTo').forEach((jumpTo) => {
+                    jumpTo.addEventListener('click', (ev) => this.click(element, ev));
                     this.elements.set(element, callback);
                 });
             }
@@ -92,10 +92,10 @@ define(["require", "exports", "tslib", "../../Language", "../Dialog"], function
                 options: {
                     onSetup: content => {
                         this.input = content.querySelector('input');
-                        this.input.addEventListener('keyup', this._keyUp.bind(this));
+                        this.input.addEventListener('keyup', (ev) => this._keyUp(ev));
                         this.description = content.querySelector('small');
                         this.submitButton = content.querySelector('button');
-                        this.submitButton.addEventListener('click', this.submit.bind(this));
+                        this.submitButton.addEventListener('click', () => this.submit());
                     },
                     title: Language.get('wcf.global.page.pagination'),
                 },
index 6ef6a9fe3503d1fb12a618b96abe0fe35419e2e9..6879401c10698e1d1caa01988a479e0ee5494eed 100644 (file)
@@ -58,8 +58,8 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Dom/Util", "../../La
             this.resultList.innerHTML = html;
             Util_1.default[html ? 'show' : 'hide'](this.resultContainer);
             if (html) {
-                this.resultList.querySelectorAll('.containerHeadline').forEach(item => {
-                    item.addEventListener('click', this.click.bind(this));
+                this.resultList.querySelectorAll('.containerHeadline').forEach((item) => {
+                    item.addEventListener('click', (ev) => this.click(ev));
                 });
             }
             else {
@@ -85,7 +85,7 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Dom/Util", "../../La
                                 this.search(event);
                             }
                         });
-                        this.searchInput.nextElementSibling.addEventListener('click', this.search.bind(this));
+                        this.searchInput.nextElementSibling.addEventListener('click', (ev) => this.search(ev));
                         this.resultContainer = document.getElementById('wcfUiPageSearchResultContainer');
                         this.resultList = document.getElementById('wcfUiPageSearchResultList');
                     },
index 157b31e9a83d2eafb3dec07dd07c7996521344eb..f57020c3adcd065b120a52a33404f27969189369 100644 (file)
@@ -53,7 +53,7 @@ define(["require", "exports", "tslib", "../Core", "../Language", "../StringUtil"
                 link.title = Language.get('wcf.global.page.previous');
                 link.rel = 'prev';
                 listItem.appendChild(link);
-                link.addEventListener('click', this.switchPage.bind(this, this.activePage - 1));
+                link.addEventListener('click', (ev) => this.switchPage(this.activePage - 1, ev));
             }
             else {
                 listItem.innerHTML = '<span class="' + iconClassNames + '"></span>';
@@ -153,7 +153,7 @@ define(["require", "exports", "tslib", "../Core", "../Language", "../StringUtil"
                 link.title = Language.get('wcf.global.page.next');
                 link.rel = 'next';
                 listItem.appendChild(link);
-                link.addEventListener('click', this.switchPage.bind(this, this.activePage + 1));
+                link.addEventListener('click', (ev) => this.switchPage(this.activePage + 1, ev));
             }
             else {
                 listItem.innerHTML = '<span class="' + iconClassNames + '"></span>';
@@ -173,7 +173,7 @@ define(["require", "exports", "tslib", "../Core", "../Language", "../StringUtil"
             if (pageNo !== this.activePage) {
                 const link = document.createElement('a');
                 link.textContent = StringUtil.addThousandsSeparator(pageNo);
-                link.addEventListener('click', this.switchPage.bind(this, pageNo));
+                link.addEventListener('click', (ev) => this.switchPage(pageNo, ev));
                 listItem.appendChild(link);
             }
             else {
index e2f4c984ac04de222c50926caa469ff2ebcfffef..09d912638aa9e38f6069b171a29b745592a63cad 100644 (file)
@@ -205,20 +205,20 @@ define(["require", "exports", "tslib", "../Core", "../Environment"], function (r
         const queryObject = _getQueryObject(event.media);
         if (event.matches) {
             if (queryObject.callbacksSetup.size) {
-                queryObject.callbacksSetup.forEach(function (callback) {
+                queryObject.callbacksSetup.forEach((callback) => {
                     callback();
                 });
                 // discard all setup callbacks after execution
                 queryObject.callbacksSetup = new Map();
             }
             else {
-                queryObject.callbacksMatch.forEach(function (callback) {
+                queryObject.callbacksMatch.forEach((callback) => {
                     callback();
                 });
             }
         }
         else {
-            queryObject.callbacksUnmatch.forEach(function (callback) {
+            queryObject.callbacksUnmatch.forEach((callback) => {
                 callback();
             });
         }
index e0b4999bfabcfb9c97345f085e834da36af4ef28..10b814bef91dfe456160fa540c62f8d3760ad960 100644 (file)
@@ -64,8 +64,8 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ut
             this.preventSubmit = options.preventSubmit;
             // Disable auto-complete because it collides with the suggestion dropdown.
             this.element.autocomplete = 'off';
-            this.element.addEventListener('keydown', this.keydown.bind(this));
-            this.element.addEventListener('keyup', this.keyup.bind(this));
+            this.element.addEventListener('keydown', (ev) => this.keydown(ev));
+            this.element.addEventListener('keyup', (ev) => this.keyup(ev));
         }
         /**
          * Adds an excluded search value.
index cd258f523ac6c050370c6521962d3bfc46dc92b0..d54656304217056fccaa63d43860d4031f5337ea 100644 (file)
@@ -21,8 +21,8 @@ define(["require", "exports", "tslib", "../../Event/Handler"], function (require
                 }
             }
             this.container = container;
-            this.container.addEventListener('keydown', this.keydown.bind(this));
-            this.container.addEventListener('mousedown', this.mousedown.bind(this));
+            this.container.addEventListener('keydown', (ev) => this.keydown(ev));
+            this.container.addEventListener('mousedown', (ev) => this.mousedown(ev));
         }
         keydown(event) {
             const activeButton = document.activeElement;
@@ -64,8 +64,9 @@ define(["require", "exports", "tslib", "../../Event/Handler"], function (require
             if (listItem && this.container.contains(listItem)) {
                 event.preventDefault();
                 const img = listItem.querySelector('img');
-                if (img)
+                if (img) {
                     this.insert(img);
+                }
             }
         }
         insert(img) {
index 9a474ffc9e6fc08eec15e71bab8fcad30e529db4..a8858d03a37464724c137549a972a5e66d83eb3e 100644 (file)
@@ -37,9 +37,9 @@ define(["require", "exports", "tslib", "../Ajax", "../Core", "./Dropdown/Simple"
             this.callbackSelect = options.callbackSelect;
             this.excludedSearchValues = new Set(Array.isArray(options.excludedSearchValues) ? options.excludedSearchValues : []);
             this.threshold = options.threshold === undefined ? 3 : options.threshold;
-            this.element.addEventListener('click', event => event.preventDefault());
-            this.element.addEventListener('keydown', this.keyDown.bind(this));
-            this.element.addEventListener('keyup', this.keyUp.bind(this));
+            this.element.addEventListener('click', (ev) => ev.preventDefault());
+            this.element.addEventListener('keydown', (ev) => this.keyDown(ev));
+            this.element.addEventListener('keyup', (ev) => this.keyUp(ev));
         }
         /**
          * Adds an excluded search value.
@@ -109,9 +109,6 @@ define(["require", "exports", "tslib", "../Ajax", "../Core", "./Dropdown/Simple"
             event.preventDefault();
             return false;
         }
-        /**
-         * Selects an item from the list.
-         */
         select(event, item) {
             if (event instanceof MouseEvent) {
                 const target = event.currentTarget;
@@ -185,7 +182,7 @@ define(["require", "exports", "tslib", "../Ajax", "../Core", "./Dropdown/Simple"
                     if (item.type) {
                         anchor.dataset.type = item.type;
                     }
-                    anchor.addEventListener('click', this.select.bind(this));
+                    anchor.addEventListener('click', (ev) => this.select(ev));
                     const listItem = document.createElement('li');
                     if (index === 0) {
                         listItem.className = 'active';
index c18ac91a521a82aa463df45a3d6f52aa4412915b..86d28bfa932f6d214fc5e33eda29a2282daa9f4c 100644 (file)
@@ -63,7 +63,7 @@ define(["require", "exports", "tslib", "../Dom/Change/Listener", "../Dom/Util",
                     rebuildMenuOverflow(menu);
                 }
                 let timeout = null;
-                menu.querySelector('ul').addEventListener('scroll', function () {
+                menu.querySelector('ul').addEventListener('scroll', () => {
                     if (timeout !== null) {
                         window.clearTimeout(timeout);
                     }
index b58e6433f7bf3c01b7f37631f0e40d8bb425540d..05ba0ca20967e3c271ad04488778709549054491 100644 (file)
@@ -95,7 +95,8 @@ define(["require", "exports", "tslib", "../../Dom/Traverse", "../../Dom/Util", "
             // bind listeners
             this.tabs.forEach(tab => {
                 if (!oldTabs || oldTabs.get(tab.dataset.name || '') !== tab) {
-                    tab.children[0].addEventListener('click', this._onClick.bind(this));
+                    const firstChild = tab.children[0];
+                    firstChild.addEventListener('click', (ev) => this._onClick(ev));
                     // iOS 13 changed the behavior for click events after scrolling the menu. It prevents
                     // the synthetic mouse events like "click" from triggering for a short duration after
                     // a scrolling has occurred. If the user scrolls to the end of the list and immediately
@@ -108,13 +109,13 @@ define(["require", "exports", "tslib", "../../Dom/Traverse", "../../Dom/Util", "
                     // tapping a menu item.
                     if (Environment.platform() === 'ios') {
                         let isClick = false;
-                        tab.children[0].addEventListener('touchstart', () => {
+                        firstChild.addEventListener('touchstart', () => {
                             isClick = true;
                         });
-                        tab.children[0].addEventListener('touchmove', () => {
+                        firstChild.addEventListener('touchmove', () => {
                             isClick = false;
                         });
-                        tab.children[0].addEventListener('touchend', (event) => {
+                        firstChild.addEventListener('touchend', (event) => {
                             if (isClick) {
                                 isClick = false;
                                 // This will block the regular click event from firing.
index 0a05dda5aeb83b7c8fee67a2793b5a43fda1ca95..35edb88db67b06d04e34c1fab25c8e536f43ea1a 100644 (file)
@@ -39,7 +39,7 @@ define(["require", "exports", "tslib", "../../Dom/Util"], function (require, exp
             this.element = element;
             this.hide = this.getElements('hide', Array.isArray(options.hide) ? options.hide : []);
             this.hide = this.getElements('show', Array.isArray(options.show) ? options.show : []);
-            this.element.addEventListener('change', this.change.bind(this));
+            this.element.addEventListener('change', (ev) => this.change(ev));
             this.updateVisibility(this.show, this.element.checked);
             this.updateVisibility(this.hide, !this.element.checked);
         }
index 3f07f0fa295232d0cc06149c5afbc45b452fa6ba..4ab5e9568b4cffd6abc93c701be028a571523c2f 100644 (file)
@@ -90,7 +90,7 @@ define(["require", "exports", "tslib", "../Dom/Change/Listener", "../Environment
      * Initializes tooltip elements.
      */
     function init() {
-        document.querySelectorAll('.jsTooltip').forEach(element => {
+        document.querySelectorAll('.jsTooltip').forEach((element) => {
             element.classList.remove('jsTooltip');
             const title = element.title.trim();
             if (title.length) {
index e8da4135855fd0f74cc7da93b388b9f3459fc52f..4bb60a6aa0a88d8fcc1617e2c972dd17c729a541 100644 (file)
@@ -26,7 +26,7 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ut
                 // The button is missing if the current user lacks the permission.
                 if (button) {
                     button.dataset.action = action;
-                    button.addEventListener('click', this._click.bind(this));
+                    button.addEventListener('click', (ev) => this._click(ev));
                 }
             });
         }
index 9c6c9500ed537c105059a16099f963857446ceee..70d4eae019facedcfafda8173c76859bf069c27b 100644 (file)
@@ -46,7 +46,7 @@ define(["require", "exports", "tslib", "../../../Ajax", "../../../Dom/Change/Lis
         rebuild() {
             document.querySelectorAll('.userTrophyOverlayList').forEach((element) => {
                 if (!this.knownElements.has(element)) {
-                    element.addEventListener('click', this.open.bind(this, element));
+                    element.addEventListener('click', (ev) => this.open(element, ev));
                     this.knownElements.add(element);
                 }
             });
index dbd34f60cf73a332c389049c5ef3da0b82f952d1..35bdce673f75cf6967cd2919945f9f09295b736b 100644 (file)
@@ -37,7 +37,7 @@ export function send(url: string, success: (...args: unknown[]) => void, failure
     }
 
     window[callbackName] = undefined;
-    script.parentNode.removeChild(script);
+    script.remove();
   }, (~~options.timeout || 10) * 1_000);
 
   window[callbackName] = (...args: any[]) => {
@@ -46,7 +46,7 @@ export function send(url: string, success: (...args: unknown[]) => void, failure
     success.apply(null, args);
 
     window[callbackName] = undefined;
-    script.parentNode.removeChild(script);
+    script.remove();
   };
 
   url += (url.indexOf('?') === -1) ? '?' : '&';
index 8f71a152572fb3e057608377330a3725b48f81f4..536795e35ae1182a127206ca91e737477de67d4f 100644 (file)
@@ -330,7 +330,7 @@ class AjaxRequest {
     DomChangeListener.trigger();
 
     // fix anchor tags generated through WCF::getAnchor()
-    document.querySelectorAll<HTMLAnchorElement>('a[href*="#"]').forEach(link => {
+    document.querySelectorAll('a[href*="#"]').forEach((link: HTMLAnchorElement) => {
       let href = link.href;
       if (href.indexOf('AJAXProxy') !== -1 || href.indexOf('ajax-proxy') !== -1) {
         href = href.substr(href.indexOf('#'));
index d888ecd374fb7df10b686b9d5376761011e12bc5..1ddefeff12cd66b999278a15cc89ae576e0acc54 100644 (file)
@@ -38,7 +38,7 @@ class CallbackList {
    */
   forEach(identifier: string | null, callback: Callback): void {
     if (identifier === null) {
-      this._callbacks.forEach(function (callbacks, identifier) {
+      this._callbacks.forEach((callbacks, identifier) => {
         callbacks.forEach(callback);
       });
     } else {
index 7797305058bc2f1eb02801100ddb2d6fe09d093d..85f545527539670011365b73269b9b0d97387c3b 100644 (file)
@@ -42,7 +42,7 @@ function refresh() {
   }
 
   const date = new Date();
-  const timestamp = (date.getTime() - date.getMilliseconds()) / 1000;
+  const timestamp = (date.getTime() - date.getMilliseconds()) / 1_000;
   if (_offset === null) _offset = timestamp - window.TIME_NOW;
 
   document.querySelectorAll('time').forEach(element => {
@@ -100,7 +100,7 @@ function rebuild(element: HTMLTimeElement, date: Date, timestamp: number): void
  * Transforms <time> elements on init and binds event listeners.
  */
 export function setup(): void {
-  new RepeatingTimer(refresh, 60000);
+  new RepeatingTimer(refresh, 60_000);
 
   DomChangeListener.add('WoltLabSuite/Core/Date/Time/Relative', refresh);
 
index 7373b10beb4cb0dc55baeea38493c9071c29976b..656319783e7b7a324fc411adf0ac11ce4a0ce666 100644 (file)
@@ -221,7 +221,7 @@ export function getTimeElement(date: Date): HTMLElement {
   const formattedTime = formatTime(date);
 
   time.setAttribute('datetime', format(date, 'c'));
-  time.dataset.timestamp = ((date.getTime() - date.getMilliseconds()) / 1000).toString();
+  time.dataset.timestamp = ((date.getTime() - date.getMilliseconds()) / 1_000).toString();
   time.dataset.date = formattedDate;
   time.dataset.time = formattedTime;
   time.dataset.offset = (date.getTimezoneOffset() * 60).toString(); // PHP returns minutes, JavaScript returns seconds
@@ -242,7 +242,7 @@ export function getTimeElement(date: Date): HTMLElement {
  */
 export function getTimezoneDate(timestamp: number, offset: number): Date {
   const date = new Date(timestamp);
-  const localOffset = date.getTimezoneOffset() * 60000;
+  const localOffset = date.getTimezoneOffset() * 60_000;
 
   return new Date((timestamp + localOffset + offset));
 }
index a96ed336bcb3c3d15e5df794ae9591449b747c9f..f542fd1c4401f9982fe06f44e29ed5b2d05cf584 100644 (file)
@@ -99,22 +99,22 @@ class ImageResizer {
       fileData = await ExifUtil.removeExifData(fileData);
     }
 
-    const imageLoader: Promise<HTMLImageElement> = new Promise(function (resolve, reject) {
+    const imageLoader: Promise<HTMLImageElement> = new Promise((resolve, reject) => {
       const reader = new FileReader();
       const image = new Image();
 
-      reader.addEventListener("load", function () {
+      reader.addEventListener("load", () => {
         image.src = reader.result! as string;
       });
 
-      reader.addEventListener("error", function () {
+      reader.addEventListener("error", () => {
         reader.abort();
         reject(reader.error);
       });
 
       image.addEventListener("error", reject);
 
-      image.addEventListener("load", function () {
+      image.addEventListener("load", () => {
         resolve(image);
       });
 
index 15359d475a8bede385f12aa508801cee06f520bd..3321ca0827a3c2afd516294a6aeb298849a5805a 100644 (file)
@@ -44,7 +44,7 @@ class UiConfirmation implements DialogCallbackObject {
     this.confirmButton = document.createElement('button');
     this.confirmButton.classList.add('buttonPrimary');
     this.confirmButton.textContent = Language.get('wcf.global.confirmation.confirm');
-    this.confirmButton.addEventListener('click', this._confirm.bind(this));
+    this.confirmButton.addEventListener('click', (ev) => this._confirm());
     formSubmit.appendChild(this.confirmButton);
 
     const cancelButton = document.createElement('button');
index aa756cd18f4a3bd227b8b9cfddb5007305e1357d..7361be0695e3df8b6dc8e1d1fdc351a8be85d165 100644 (file)
@@ -64,7 +64,7 @@ const UiDialog = {
     _container = document.createElement('div');
     _container.classList.add('dialogOverlay');
     _container.setAttribute('aria-hidden', 'true');
-    _container.addEventListener('mousedown', this._closeOnBackdrop.bind(this));
+    _container.addEventListener('mousedown', (ev) => this._closeOnBackdrop(ev));
     _container.addEventListener('wheel', event => {
       if (event.target === _container) {
         event.preventDefault();
@@ -99,7 +99,9 @@ const UiDialog = {
     });
 
     this._initStaticDialogs();
-    DomChangeListener.add('Ui/Dialog', this._initStaticDialogs.bind(this));
+    DomChangeListener.add('Ui/Dialog', () => {
+      this._initStaticDialogs();
+    });
 
     UiScreen.setDialogContainer(_container);
 
@@ -113,7 +115,7 @@ const UiDialog = {
   },
 
   _initStaticDialogs(): void {
-    document.querySelectorAll<HTMLElement>('.jsStaticDialog').forEach(button => {
+    document.querySelectorAll('.jsStaticDialog').forEach((button: HTMLElement) => {
       button.classList.remove('jsStaticDialog');
 
       const id = button.dataset.dialogId || '';
@@ -357,7 +359,7 @@ const UiDialog = {
       closeButton.tabIndex = 0;
       closeButton.title = options.closeButtonLabel;
       closeButton.setAttribute('aria-label', options.closeButtonLabel);
-      closeButton.addEventListener('click', this._close.bind(this));
+      closeButton.addEventListener('click', (ev) => this._close(ev));
       header.appendChild(closeButton);
 
       const span = document.createElement('span');
index 1fc7d77b07ee200f84bf52d05a429a1aa27e7a6f..76053ed82a973600c76737c7959e336f06700643 100644 (file)
@@ -171,9 +171,6 @@ export function setItems(list: HTMLUListElement, items: DropdownBuilderItemData[
  * Attaches the list to a button, visibility is from then on controlled through clicks
  * on the provided button element. Internally calls `Ui/SimpleDropdown.initFragment()`
  * to delegate the DOM management.
- *
- * @param       {Element}               list
- * @param       {Element}               button
  */
 export function attach(list: HTMLUListElement, button: HTMLElement): void {
   validateList(list);
index d2b40222330c989abef877dbf5fa905c1ee07d47..f210e8ed6cc90f97f537ef22e2b38d1962bc0a43 100644 (file)
@@ -304,7 +304,9 @@ function dropdownMenuKeyDown(event: KeyboardEvent): void {
     const mouseEvent = dropdown.dataset.a11yMouseEvent || 'click';
     Core.triggerEvent(target, mouseEvent);
 
-    if (button) button.focus();
+    if (button) {
+      button.focus();
+    }
   } else if (event.key === 'Escape' || event.key === 'Tab') {
     event.preventDefault();
 
index 17adb65c492ce0015f50328490910f99a555867a..36be6b9587c73668154ac9c15da535fb3d4eb63b 100644 (file)
@@ -37,8 +37,8 @@ class UiPageJumpTo implements DialogCallbackObject {
     }
 
     if (!this.elements.has(element)) {
-      element.querySelectorAll('.jumpTo').forEach(jumpTo => {
-        jumpTo.addEventListener('click', this.click.bind(this, element));
+      element.querySelectorAll('.jumpTo').forEach((jumpTo: HTMLElement) => {
+        jumpTo.addEventListener('click', (ev) => this.click(element, ev));
         this.elements.set(element, callback!);
       });
     }
@@ -104,12 +104,12 @@ class UiPageJumpTo implements DialogCallbackObject {
       options: {
         onSetup: content => {
           this.input = content.querySelector('input')!;
-          this.input.addEventListener('keyup', this._keyUp.bind(this));
+          this.input.addEventListener('keyup', (ev) => this._keyUp(ev));
 
           this.description = content.querySelector('small')!;
 
           this.submitButton = content.querySelector('button')!;
-          this.submitButton.addEventListener('click', this.submit.bind(this));
+          this.submitButton.addEventListener('click', () => this.submit());
         },
         title: Language.get('wcf.global.page.pagination'),
       },
index c56a85a2c409f874653facf5b83eb31b0d688c54..b2e1e7ed00d00c0541a446510018d39c6ac45bf0 100644 (file)
@@ -30,7 +30,7 @@ class UiPageSearch implements AjaxCallbackObject, DialogCallbackObject {
     UiDialog.open(this);
   }
 
-  private search(event: KeyboardEvent): void {
+  private search(event: Event): void {
     event.preventDefault();
 
     const inputContainer = this.searchInput!.parentNode as HTMLElement;
@@ -81,8 +81,8 @@ class UiPageSearch implements AjaxCallbackObject, DialogCallbackObject {
     DomUtil[html ? 'show' : 'hide'](this.resultContainer!);
 
     if (html) {
-      this.resultList!.querySelectorAll('.containerHeadline').forEach(item => {
-        item.addEventListener('click', this.click.bind(this));
+      this.resultList!.querySelectorAll('.containerHeadline').forEach((item: HTMLElement) => {
+        item.addEventListener('click', (ev) => this.click(ev));
       });
     } else {
       DomUtil.innerError(this.searchInput!.parentElement!, Language.get('wcf.page.search.error.noResults'));
@@ -110,7 +110,7 @@ class UiPageSearch implements AjaxCallbackObject, DialogCallbackObject {
             }
           });
 
-          this.searchInput.nextElementSibling!.addEventListener('click', this.search.bind(this));
+          this.searchInput.nextElementSibling!.addEventListener('click', (ev) => this.search(ev));
 
           this.resultContainer = document.getElementById('wcfUiPageSearchResultContainer') as HTMLElement;
           this.resultList = document.getElementById('wcfUiPageSearchResultList') as HTMLOListElement;
@@ -154,5 +154,3 @@ function getUiPageSearch(): UiPageSearch {
 export function open(callbackSelect) {
   getUiPageSearch().open(callbackSelect);
 }
-
-  
index 033d73ad34489478fe345d02e2efc2e0ccb5666f..fe5fc77c81cf6f6d597379921813bed5504808d0 100644 (file)
@@ -69,7 +69,7 @@ class UiPagination {
       link.title = Language.get('wcf.global.page.previous');
       link.rel = 'prev';
       listItem.appendChild(link);
-      link.addEventListener('click', this.switchPage.bind(this, this.activePage - 1));
+      link.addEventListener('click', (ev) => this.switchPage(this.activePage - 1, ev));
     } else {
       listItem.innerHTML = '<span class="' + iconClassNames + '"></span>';
       listItem.classList.add('disabled');
@@ -176,7 +176,7 @@ class UiPagination {
       link.title = Language.get('wcf.global.page.next');
       link.rel = 'next';
       listItem.appendChild(link);
-      link.addEventListener('click', this.switchPage.bind(this, this.activePage + 1));
+      link.addEventListener('click', (ev) => this.switchPage(this.activePage + 1, ev));
     } else {
       listItem.innerHTML = '<span class="' + iconClassNames + '"></span>';
       listItem.classList.add('disabled');
@@ -198,7 +198,7 @@ class UiPagination {
     if (pageNo !== this.activePage) {
       const link = document.createElement('a');
       link.textContent = StringUtil.addThousandsSeparator(pageNo);
-      link.addEventListener('click', this.switchPage.bind(this, pageNo));
+      link.addEventListener('click', (ev) => this.switchPage(pageNo, ev));
       listItem.appendChild(link);
     } else {
       listItem.classList.add('active');
index d250bd23cdaf91574a98c894220e9058df0be53a..adf36aafa9d55f88e3ba454e088487e1b17d728b 100644 (file)
@@ -223,19 +223,19 @@ function _mqlChange(event: MediaQueryListEvent): void {
   const queryObject = _getQueryObject(event.media);
   if (event.matches) {
     if (queryObject.callbacksSetup.size) {
-      queryObject.callbacksSetup.forEach(function (callback) {
+      queryObject.callbacksSetup.forEach((callback) => {
         callback();
       });
 
       // discard all setup callbacks after execution
       queryObject.callbacksSetup = new Map<string, Callback>();
     } else {
-      queryObject.callbacksMatch.forEach(function (callback) {
+      queryObject.callbacksMatch.forEach((callback) => {
         callback();
       });
     }
   } else {
-    queryObject.callbacksUnmatch.forEach(function (callback) {
+    queryObject.callbacksUnmatch.forEach((callback) => {
       callback();
     });
   }
index 94cde1b080a3e5ea507d75e66dccff678d748eca..ecbfebff69f7f45c126c6a34f54d8608ddc8340b 100644 (file)
@@ -77,8 +77,8 @@ class UiSearchInput {
     // Disable auto-complete because it collides with the suggestion dropdown.
     this.element.autocomplete = 'off';
 
-    this.element.addEventListener('keydown', this.keydown.bind(this));
-    this.element.addEventListener('keyup', this.keyup.bind(this));
+    this.element.addEventListener('keydown', (ev) => this.keydown(ev));
+    this.element.addEventListener('keyup', (ev) => this.keyup(ev));
   }
 
   /**
index c1d242d220e600b0d4880d4b650487fdafb5b276..e3fe5593b948647559ebf0a2c9a89f34e3857c94 100644 (file)
@@ -27,8 +27,8 @@ class UiSmileyInsert {
 
     this.container = container;
 
-    this.container.addEventListener('keydown', this.keydown.bind(this));
-    this.container.addEventListener('mousedown', this.mousedown.bind(this));
+    this.container.addEventListener('keydown', (ev) => this.keydown(ev));
+    this.container.addEventListener('mousedown', (ev) => this.mousedown(ev));
   }
 
   keydown(event: KeyboardEvent): void {
@@ -76,7 +76,9 @@ class UiSmileyInsert {
       event.preventDefault();
 
       const img = listItem.querySelector('img');
-      if (img) this.insert(img);
+      if (img) {
+        this.insert(img);
+      }
     }
   }
 
index 6917d8a0b3d9d5e288ec47a85a5d36186a35ced5..2667e22c2f03a196b4219185fcaec26f0d5f2cb9 100644 (file)
@@ -51,12 +51,12 @@ class UiSuggestion implements AjaxCallbackObject {
     }
     this.callbackSelect = options.callbackSelect;
 
-    this.excludedSearchValues = new Set<string>(Array.isArray(options.excludedSearchValues) ? options.excludedSearchValues : []);
+    this.excludedSearchValues = new Set(Array.isArray(options.excludedSearchValues) ? options.excludedSearchValues : []);
     this.threshold = options.threshold === undefined ? 3 : options.threshold;
 
-    this.element.addEventListener('click', event => event.preventDefault());
-    this.element.addEventListener('keydown', this.keyDown.bind(this));
-    this.element.addEventListener('keyup', this.keyUp.bind(this));
+    this.element.addEventListener('click', (ev) => ev.preventDefault());
+    this.element.addEventListener('keydown', (ev) => this.keyDown(ev));
+    this.element.addEventListener('keyup', (ev) => this.keyUp(ev));
   }
 
   /**
@@ -134,6 +134,8 @@ class UiSuggestion implements AjaxCallbackObject {
   /**
    * Selects an item from the list.
    */
+  private select(event: MouseEvent): void;
+  private select(event: undefined, item: HTMLElement): void;
   private select(event: MouseEvent | undefined, item?: HTMLElement): void {
     if (event instanceof MouseEvent) {
       const target = event.currentTarget as HTMLElement;
@@ -213,7 +215,7 @@ class UiSuggestion implements AjaxCallbackObject {
         if (item.type) {
           anchor.dataset.type = item.type;
         }
-        anchor.addEventListener('click', this.select.bind(this));
+        anchor.addEventListener('click', (ev) => this.select(ev));
 
         const listItem = document.createElement('li');
         if (index === 0) {
index 314cfb40f45acb6ecba66c15c3ea1a78a544bb83..9f0f67a3366dccc11fb4dcd85177ff7e0d9b700a 100644 (file)
@@ -67,7 +67,7 @@ function init() {
       }
 
       let timeout: number | null = null;
-      menu.querySelector('ul')!.addEventListener('scroll', function () {
+      menu.querySelector('ul')!.addEventListener('scroll', () => {
         if (timeout !== null) {
           window.clearTimeout(timeout);
         }
index 7691fc38e10d663820b25ea1af20b461547ac354..effbaf7370853446563956416d7b5f4365ac36db 100644 (file)
@@ -111,7 +111,8 @@ class TabMenuSimple {
     // bind listeners
     this.tabs.forEach(tab => {
       if (!oldTabs || oldTabs.get(tab.dataset.name || '') !== tab) {
-        tab.children[0].addEventListener('click', this._onClick.bind(this));
+        const firstChild = tab.children[0] as HTMLElement;
+        firstChild.addEventListener('click', (ev) => this._onClick(ev));
 
         // iOS 13 changed the behavior for click events after scrolling the menu. It prevents
         // the synthetic mouse events like "click" from triggering for a short duration after
@@ -125,13 +126,13 @@ class TabMenuSimple {
         // tapping a menu item.
         if (Environment.platform() === 'ios') {
           let isClick = false;
-          tab.children[0].addEventListener('touchstart', () => {
+          firstChild.addEventListener('touchstart', () => {
             isClick = true;
           });
-          tab.children[0].addEventListener('touchmove', () => {
+          firstChild.addEventListener('touchmove', () => {
             isClick = false;
           });
-          tab.children[0].addEventListener('touchend', (event: MouseEvent) => {
+          firstChild.addEventListener('touchend', (event) => {
             if (isClick) {
               isClick = false;
 
@@ -366,7 +367,7 @@ class TabMenuSimple {
   /**
    * Handles clicks on a tab.
    */
-  _onClick(event: MouseEvent): void {
+  _onClick(event: MouseEvent | TouchEvent): void {
     event.preventDefault();
 
     const target = event.currentTarget as HTMLElement;
index c91fd779cdb1fb8ded504172074e81ff0340975e..bf7fe8dab9a0229bed8b1baf6c1fff0a67076c9a 100644 (file)
@@ -47,7 +47,7 @@ class UiToggleInput {
     this.hide = this.getElements('hide', Array.isArray(options.hide) ? options.hide : []);
     this.hide = this.getElements('show', Array.isArray(options.show) ? options.show : []);
 
-    this.element.addEventListener('change', this.change.bind(this));
+    this.element.addEventListener('change', (ev) => this.change(ev));
 
     this.updateVisibility(this.show, this.element.checked);
     this.updateVisibility(this.hide, !this.element.checked);
index dd52c4ec77a4f9e687a0ad066fdeb64777d023b1..76d10649c64796721474f55273a08e5e99a1409d 100644 (file)
@@ -101,7 +101,7 @@ export function setup(): void {
  * Initializes tooltip elements.
  */
 export function init(): void {
-  document.querySelectorAll<HTMLElement>('.jsTooltip').forEach(element => {
+  document.querySelectorAll('.jsTooltip').forEach((element: HTMLElement) => {
     element.classList.remove('jsTooltip');
 
     const title = element.title.trim();
index 314954e7c0cd452ec0bd0785a37af486f2d6304c..3eeb3d994c169546d6249f4bbd7f2d557befbc42 100644 (file)
@@ -30,7 +30,7 @@ class UserEditor implements AjaxCallbackObject, DialogCallbackObject {
       // The button is missing if the current user lacks the permission.
       if (button) {
         button.dataset.action = action;
-        button.addEventListener('click', this._click.bind(this));
+        button.addEventListener('click', (ev) => this._click(ev));
       }
     });
   }
@@ -246,5 +246,3 @@ class UserEditor implements AjaxCallbackObject, DialogCallbackObject {
 export function init() {
   new UserEditor();
 }
-               
-               
index 28e0180d13bc58e34336e77e01879defa4069d6c..2a4ca126c5bcd76e7e8d083f38fa184212600f53 100644 (file)
@@ -29,7 +29,7 @@ class UiUserSearchInput extends UiSearchInput {
     super(element, options);
   }
 
-  protected createListItem(item): HTMLLIElement {
+  protected createListItem(item: UserListItemData): HTMLLIElement {
     const listItem = super.createListItem(item);
     listItem.dataset.type = item.type;
 
@@ -44,3 +44,12 @@ class UiUserSearchInput extends UiSearchInput {
 }
 
 export = UiUserSearchInput
+
+// https://stackoverflow.com/a/50677584/782822
+// This is a dirty hack, because the ListItemData cannot be exported for compatibility reasons.
+type FirstArgument<T> = T extends (arg1: infer U, ...args: any[]) => any ? U : never;
+
+interface UserListItemData extends FirstArgument<UiSearchInput["createListItem"]> {
+  type: "user" | "group";
+  icon: string;
+}
index f07fee2218099fa8e048e4b243d1cfd3556b06bc..ddc4d6559a25bfb31bd2e03b7623ee145f14b8f9 100644 (file)
@@ -54,7 +54,7 @@ class UiUserTrophyList implements AjaxCallbackObject, DialogCallbackObject {
   private rebuild(): void {
     document.querySelectorAll('.userTrophyOverlayList').forEach((element: HTMLElement) => {
       if (!this.knownElements.has(element)) {
-        element.addEventListener('click', this.open.bind(this, element));
+        element.addEventListener('click', (ev) => this.open(element, ev));
 
         this.knownElements.add(element);
       }
index 5676fb218378f73c3381859d69720ae623d0908f..7c5788d3ecd9659ca465226ecc630f5ae20c1052 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 class User {
-  constructor(readonly userId, readonly username, readonly link) {
+  constructor(readonly userId: number, readonly username: string, readonly link: string) {
   }
 }