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;
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('#'));
forEach(identifier, callback) {
var _a;
if (identifier === null) {
- this._callbacks.forEach(function (callbacks, identifier) {
+ this._callbacks.forEach((callbacks, identifier) => {
callbacks.forEach(callback);
});
}
// 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);
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');
_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();
},
});
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 => {
});
},
_initStaticDialogs() {
- document.querySelectorAll('.jsStaticDialog').forEach(button => {
+ document.querySelectorAll('.jsStaticDialog').forEach((button) => {
button.classList.remove('jsStaticDialog');
const id = button.dataset.dialogId || '';
if (id) {
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';
* 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);
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();
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);
});
}
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'),
},
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 {
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');
},
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>';
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>';
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 {
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();
});
}
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.
}
}
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;
if (listItem && this.container.contains(listItem)) {
event.preventDefault();
const img = listItem.querySelector('img');
- if (img)
+ if (img) {
this.insert(img);
+ }
}
}
insert(img) {
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.
event.preventDefault();
return false;
}
- /**
- * Selects an item from the list.
- */
select(event, item) {
if (event instanceof MouseEvent) {
const target = event.currentTarget;
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';
rebuildMenuOverflow(menu);
}
let timeout = null;
- menu.querySelector('ul').addEventListener('scroll', function () {
+ menu.querySelector('ul').addEventListener('scroll', () => {
if (timeout !== null) {
window.clearTimeout(timeout);
}
// 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
// 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.
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);
}
* 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) {
// 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));
}
});
}
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);
}
});
}
window[callbackName] = undefined;
- script.parentNode.removeChild(script);
+ script.remove();
}, (~~options.timeout || 10) * 1_000);
window[callbackName] = (...args: any[]) => {
success.apply(null, args);
window[callbackName] = undefined;
- script.parentNode.removeChild(script);
+ script.remove();
};
url += (url.indexOf('?') === -1) ? '?' : '&';
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('#'));
*/
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 {
}
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 => {
* 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);
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
*/
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));
}
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);
});
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');
_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();
});
this._initStaticDialogs();
- DomChangeListener.add('Ui/Dialog', this._initStaticDialogs.bind(this));
+ DomChangeListener.add('Ui/Dialog', () => {
+ this._initStaticDialogs();
+ });
UiScreen.setDialogContainer(_container);
},
_initStaticDialogs(): void {
- document.querySelectorAll<HTMLElement>('.jsStaticDialog').forEach(button => {
+ document.querySelectorAll('.jsStaticDialog').forEach((button: HTMLElement) => {
button.classList.remove('jsStaticDialog');
const id = button.dataset.dialogId || '';
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');
* 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);
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();
}
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!);
});
}
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'),
},
UiDialog.open(this);
}
- private search(event: KeyboardEvent): void {
+ private search(event: Event): void {
event.preventDefault();
const inputContainer = this.searchInput!.parentNode as HTMLElement;
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'));
}
});
- 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;
export function open(callbackSelect) {
getUiPageSearch().open(callbackSelect);
}
-
-
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');
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');
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');
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();
});
}
// 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));
}
/**
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 {
event.preventDefault();
const img = listItem.querySelector('img');
- if (img) this.insert(img);
+ if (img) {
+ this.insert(img);
+ }
}
}
}
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));
}
/**
/**
* 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;
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) {
}
let timeout: number | null = null;
- menu.querySelector('ul')!.addEventListener('scroll', function () {
+ menu.querySelector('ul')!.addEventListener('scroll', () => {
if (timeout !== null) {
window.clearTimeout(timeout);
}
// 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
// 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;
/**
* Handles clicks on a tab.
*/
- _onClick(event: MouseEvent): void {
+ _onClick(event: MouseEvent | TouchEvent): void {
event.preventDefault();
const target = event.currentTarget as HTMLElement;
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);
* 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();
// 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));
}
});
}
export function init() {
new UserEditor();
}
-
-
super(element, options);
}
- protected createListItem(item): HTMLLIElement {
+ protected createListItem(item: UserListItemData): HTMLLIElement {
const listItem = super.createListItem(item);
listItem.dataset.type = item.type;
}
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;
+}
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);
}
*/
class User {
- constructor(readonly userId, readonly username, readonly link) {
+ constructor(readonly userId: number, readonly username: string, readonly link: string) {
}
}