diff --git a/ui/core/components/sim_title_dropdown.ts b/ui/core/components/sim_title_dropdown.ts
index de16cc84a1..a1d1c88bdf 100644
--- a/ui/core/components/sim_title_dropdown.ts
+++ b/ui/core/components/sim_title_dropdown.ts
@@ -1,42 +1,42 @@
-import { Component } from './component.js';
import {
getLaunchedSimsForClass,
LaunchStatus,
raidSimStatus,
- simLaunchStatuses
+ simLaunchStatuses,
} from '../launched_sims.js';
import { Class, Spec } from '../proto/common.js';
import {
classNames,
getSpecSiteUrl,
naturalClassOrder,
- raidSimSiteUrl,
raidSimIcon,
raidSimLabel,
+ raidSimSiteUrl,
specNames,
specToClass,
textCssClassForClass,
textCssClassForSpec,
titleIcons,
} from '../proto_utils/utils.js';
+import { Component } from './component.js';
interface ClassOptions {
- type: 'Class',
- index: Class
+ type: 'Class';
+ index: Class;
}
interface SpecOptions {
- type: 'Spec'
- index: Spec
+ type: 'Spec';
+ index: Spec;
}
interface RaidOptions {
- type: 'Raid'
+ type: 'Raid';
}
type SimTitleDropdownConfig = {
- noDropdown?: boolean,
-}
+ noDropdown?: boolean;
+};
// Dropdown menu for selecting a player.
export class SimTitleDropdown extends Component {
@@ -64,52 +64,59 @@ export class SimTitleDropdown extends Component {
[Spec.SpecProtectionWarrior]: 'Protection',
[Spec.SpecDeathknight]: 'DPS',
[Spec.SpecTankDeathknight]: 'Tank',
- }
+ };
- constructor(parent: HTMLElement, currentSpecIndex: Spec | null, config: SimTitleDropdownConfig = {}) {
+ constructor(
+ parent: HTMLElement,
+ currentSpecIndex: Spec | null,
+ config: SimTitleDropdownConfig = {},
+ ) {
super(parent, 'sim-title-dropdown-root');
- let rootLinkArgs: SpecOptions | RaidOptions = currentSpecIndex === null ? { type: 'Raid' } : { type: 'Spec', index: currentSpecIndex }
- let rootLink = this.buildRootSimLink(rootLinkArgs);
+ const rootLinkArgs: SpecOptions | RaidOptions =
+ currentSpecIndex === null
+ ? { type: 'Raid' }
+ : { type: 'Spec', index: currentSpecIndex };
+ const rootLink = this.buildRootSimLink(rootLinkArgs);
if (config.noDropdown) {
this.rootElem.innerHTML = rootLink.outerHTML;
- return
+ return;
}
this.rootElem.innerHTML = `
-
- ${rootLink.outerHTML}
-
-
- `;
+
+ ${rootLink.outerHTML}
+
+
+ `;
this.dropdownMenu = this.rootElem.getElementsByClassName('dropdown-menu')[0] as HTMLElement;
this.buildDropdown();
// Prevent Bootstrap from closing the menu instead of opening class menus
- this.dropdownMenu.addEventListener('click', (event) => {
- let target = event.target as HTMLElement;
- let link = target.closest('a:not([href="javascript:void(0)"]');
+ this.dropdownMenu.addEventListener('click', event => {
+ const target = event.target as HTMLElement;
+ const link = target.closest('a:not([href="javascript:void(0)"]');
if (!link) {
event.stopPropagation();
event.preventDefault();
}
- })
+ });
}
private buildDropdown() {
if (raidSimStatus >= LaunchStatus.Alpha) {
// Add the raid sim to the top of the dropdown
- let raidListItem = document.createElement('li');
+ const raidListItem = document.createElement('li');
raidListItem.appendChild(this.buildRaidLink());
this.dropdownMenu?.appendChild(raidListItem);
}
naturalClassOrder.forEach(classIndex => {
- let listItem = document.createElement('li');
- let sims = getLaunchedSimsForClass(classIndex);
+ const listItem = document.createElement('li');
+ const sims = getLaunchedSimsForClass(classIndex);
if (sims.length == 1) {
// The class only has one listed sim so make a direct link to the sim
@@ -124,132 +131,134 @@ export class SimTitleDropdown extends Component {
}
private buildClassDropdown(classIndex: Class) {
- let sims = getLaunchedSimsForClass(classIndex);
- let dropdownFragment = document.createElement('fragment');
- let dropdownMenu = document.createElement('ul');
+ const sims = getLaunchedSimsForClass(classIndex);
+ const dropdownFragment = document.createElement('fragment');
+ const dropdownMenu = document.createElement('ul');
dropdownMenu.classList.add('dropdown-menu');
// Generate the class link to act as a dropdown toggle for the spec dropdown
- let classLink = this.buildClassLink(classIndex);
+ const classLink = this.buildClassLink(classIndex);
// Generate links for a class's specs
- sims.forEach((specIndex) => {
- let listItem = document.createElement('li');
- let link = this.buildSpecLink(specIndex);
+ sims.forEach(specIndex => {
+ const listItem = document.createElement('li');
+ const link = this.buildSpecLink(specIndex);
listItem.appendChild(link);
dropdownMenu.appendChild(listItem);
});
dropdownFragment.innerHTML = `
-
- ${classLink.outerHTML}
- ${dropdownMenu.outerHTML}
-
- `;
+
+ ${classLink.outerHTML}
+ ${dropdownMenu.outerHTML}
+
+ `;
return dropdownFragment.children[0] as HTMLElement;
}
private buildRootSimLink(data: SpecOptions | RaidOptions): HTMLElement {
- let iconPath = this.getSimIconPath(data);;
- let textKlass = this.getContextualKlass(data);
+ const iconPath = this.getSimIconPath(data);
+ const textKlass = this.getContextualKlass(data);
let label;
- if (data.type == 'Raid')
- label = raidSimLabel;
+ if (data.type == 'Raid') label = raidSimLabel;
else {
- let classIndex = specToClass[data.index];
+ const classIndex = specToClass[data.index];
if (getLaunchedSimsForClass(classIndex).length > 1)
// If the class has multiple sims, use the spec name
label = specNames[data.index];
- else
- // If the class has only 1 sim, use the class name
- label = classNames[classIndex];
+ // If the class has only 1 sim, use the class name
+ else label = classNames[classIndex];
}
- let fragment = document.createElement('fragment');
+ const fragment = document.createElement('fragment');
fragment.innerHTML = `
-
-
-
-
- WoWSims - WOTLK
- ${label}
- ${this.launchStatusLabel(data)}
-
-
-
- `;
+
+
+
+
+ WoWSims - WOTLK
+ ${label}
+ ${this.launchStatusLabel(data)}
+
+
+
+ `;
return fragment.children[0] as HTMLElement;
}
private buildRaidLink(): HTMLElement {
- let href = raidSimSiteUrl;
- let textKlass = this.getContextualKlass({ type: 'Raid' });
- let iconPath = this.getSimIconPath({ type: 'Raid' });
- let label = raidSimLabel;
+ const href = raidSimSiteUrl;
+ const textKlass = this.getContextualKlass({ type: 'Raid' });
+ const iconPath = this.getSimIconPath({ type: 'Raid' });
+ const label = raidSimLabel;
- let fragment = document.createElement('fragment');
+ const fragment = document.createElement('fragment');
fragment.innerHTML = `
-
-
-
-
- ${label}
- ${this.launchStatusLabel({ type: 'Raid' })}
-
-
-
- `;
+
+
+
+
+ ${label}
+ ${this.launchStatusLabel({ type: 'Raid' })}
+
+
+
+ `;
return fragment.children[0] as HTMLElement;
}
private buildClassLink(classIndex: Class): HTMLElement {
- let specIndexes = getLaunchedSimsForClass(classIndex);
- let href = specIndexes.length > 1 ? 'javascript:void(0)' : getSpecSiteUrl(specIndexes[0]);
- let textKlass = this.getContextualKlass({ type: 'Class', index: classIndex });
- let iconPath = this.getSimIconPath({ type: 'Class', index: classIndex });
- let label = classNames[classIndex];
+ const specIndexes = getLaunchedSimsForClass(classIndex);
+ const href = specIndexes.length > 1 ? 'javascript:void(0)' : getSpecSiteUrl(specIndexes[0]);
+ const textKlass = this.getContextualKlass({ type: 'Class', index: classIndex });
+ const iconPath = this.getSimIconPath({ type: 'Class', index: classIndex });
+ const label = classNames[classIndex];
- let fragment = document.createElement('fragment');
+ const fragment = document.createElement('fragment');
fragment.innerHTML = `
- 1 ? 'role="button" data-bs-toggle="dropdown" aria-expanded="false"' : ''}>
-
-
-
- ${label}
- ${specIndexes.length == 1 ? this.launchStatusLabel({ type: 'Spec', index: specIndexes[0] }) : ''}
-
-
-
- `;
+ 1
+ ? 'role="button" data-bs-toggle="dropdown" aria-expanded="false"'
+ : ''
+ }>
+
+
+
+ ${label}
+ ${specIndexes.length == 1 ? this.launchStatusLabel({ type: 'Spec', index: specIndexes[0] }) : ''}
+
+
+
+ `;
return fragment.children[0] as HTMLElement;
}
private buildSpecLink(specIndex: Spec): HTMLElement {
- let href = getSpecSiteUrl(specIndex);
- let textKlass = this.getContextualKlass({ type: 'Spec', index: specIndex });
- let iconPath = this.getSimIconPath({ type: 'Spec', index: specIndex });
- let className = classNames[specToClass[specIndex]];
- let specLabel = this.specLabels[specIndex];
+ const href = getSpecSiteUrl(specIndex);
+ const textKlass = this.getContextualKlass({ type: 'Spec', index: specIndex });
+ const iconPath = this.getSimIconPath({ type: 'Spec', index: specIndex });
+ const className = classNames[specToClass[specIndex]];
+ const specLabel = this.specLabels[specIndex];
- let fragment = document.createElement('fragment');
+ const fragment = document.createElement('fragment');
fragment.innerHTML = `
-
-
-
-
- ${className}
- ${specLabel}
- ${this.launchStatusLabel({ type: 'Spec', index: specIndex })}
-
-
-
- `;
+
+
+
+
+ ${className}
+ ${specLabel}
+ ${this.launchStatusLabel({ type: 'Spec', index: specIndex })}
+
+
+
+ `;
return fragment.children[0] as HTMLElement;
}
@@ -258,10 +267,14 @@ export class SimTitleDropdown extends Component {
if (
(data.type == 'Raid' && raidSimStatus == LaunchStatus.Launched) ||
(data.type == 'Spec' && simLaunchStatuses[data.index] == LaunchStatus.Launched)
- ) return "";
-
- let label = data.type == 'Raid' ? LaunchStatus[raidSimStatus] : LaunchStatus[simLaunchStatuses[data.index]];
- let elem = document.createElement('span');
+ )
+ return '';
+
+ const label =
+ data.type == 'Raid'
+ ? LaunchStatus[raidSimStatus]
+ : LaunchStatus[simLaunchStatuses[data.index]];
+ const elem = document.createElement('span');
elem.classList.add('launch-status-label', 'text-brand');
elem.textContent = label;
@@ -274,8 +287,8 @@ export class SimTitleDropdown extends Component {
if (data.type == 'Raid') {
iconPath = raidSimIcon;
} else if (data.type == 'Class') {
- let className = classNames[data.index];
- iconPath = `/wotlk/assets/img/${className.toLowerCase().replace(/\s/g, '_')}_icon.png`
+ const className = classNames[data.index];
+ iconPath = `/wotlk/assets/img/${className.toLowerCase().replace(/\s/g, '_')}_icon.png`;
} else {
iconPath = titleIcons[data.index];
}
@@ -290,7 +303,6 @@ export class SimTitleDropdown extends Component {
else if (data.type == 'Class')
// Class links
return textCssClassForClass(data.index);
- else
- return textCssClassForSpec(data.index);
+ else return textCssClassForSpec(data.index);
}
}
diff --git a/ui/shared/bootstrap_overrides.ts b/ui/shared/bootstrap_overrides.ts
index 7769be606b..e3a60143af 100644
--- a/ui/shared/bootstrap_overrides.ts
+++ b/ui/shared/bootstrap_overrides.ts
@@ -1,90 +1,115 @@
import { Dropdown, Popover, Tooltip } from 'bootstrap';
+
import { isDescendant } from './utils';
Dropdown.Default.offset = [0, -1];
//Dropdown.Default.display = "static";
-Tooltip.Default.trigger = "hover";
+Tooltip.Default.trigger = 'hover';
-let body = document.querySelector('body') as HTMLElement;
+const body = document.querySelector('body') as HTMLElement;
function hasTouch() {
- return ('ontouchstart' in window) || (navigator.maxTouchPoints > 0);
+ return 'ontouchstart' in window || navigator.maxTouchPoints > 0;
}
function hasHover() {
- return window.matchMedia("(any-hover: hover)").matches;
+ return window.matchMedia('(any-hover: hover)').matches;
}
// Disable 'mouseover' to avoid needed to double click on mobile
// Leaving 'mouseleave', however still allows dropdown to close when clicking new box
if (!hasTouch() || hasHover()) {
// Custom dropdown event handlers for mouseover dropdowns
- body.addEventListener('mouseover', event => {
- let target = event.target as HTMLElement;
- let toggle = target.closest('[data-bs-toggle=dropdown]');
- if (toggle && !toggle.classList.contains('open-on-click')) {
- let dropdown = Dropdown.getOrCreateInstance(toggle);
- dropdown.show();
- }
- }, true);
+ body.addEventListener(
+ 'mouseover',
+ event => {
+ const target = event.target as HTMLElement;
+ const toggle = target.closest('[data-bs-toggle=dropdown]:not([data-bs-trigger=click])');
+ if (toggle && !toggle.classList.contains('open-on-click')) {
+ const dropdown = Dropdown.getOrCreateInstance(toggle);
+ dropdown.show();
+ }
+ },
+ true,
+ );
}
-body.addEventListener('mouseleave', event => {
- let e = event as MouseEvent;
- let target = event.target as HTMLElement;
- let toggle = target.closest('[data-bs-toggle=dropdown]') as HTMLElement | null;
- // Hide dropdowns when hovering off of the toggle, so long as the new target is not part of the dropdown as well
- if (toggle) {
- let dropdown = Dropdown.getOrCreateInstance(toggle);
- let dropdownMenu = toggle.nextElementSibling as HTMLElement;
- let relatedTarget = e.relatedTarget as HTMLElement;
- if (relatedTarget == null || (!isDescendant(relatedTarget, dropdownMenu) && !isDescendant(relatedTarget, toggle)))
- dropdown.hide();
- }
+body.addEventListener(
+ 'mouseleave',
+ event => {
+ const e = event as MouseEvent;
+ const target = event.target as HTMLElement;
+ const toggle = target.closest(
+ '[data-bs-toggle=dropdown]:not([data-bs-trigger=click])',
+ ) as HTMLElement | null;
+ // Hide dropdowns when hovering off of the toggle, so long as the new target is not part of the dropdown as well
+ if (toggle) {
+ const dropdown = Dropdown.getOrCreateInstance(toggle);
+ const dropdownMenu = toggle.nextElementSibling as HTMLElement;
+ const relatedTarget = e.relatedTarget as HTMLElement;
+ if (
+ relatedTarget == null ||
+ (!isDescendant(relatedTarget, dropdownMenu) && !isDescendant(relatedTarget, toggle))
+ )
+ dropdown.hide();
+ }
- let dropdownMenu = target.closest('.dropdown-menu') as HTMLElement;
- // Hide dropdowns when hovering off of the menu, so long as the new target is not part of the dropdown as well
- if (dropdownMenu) {
- let toggle = dropdownMenu.previousElementSibling as HTMLElement;
- let dropdown = Dropdown.getOrCreateInstance(toggle);
- let relatedTarget = e.relatedTarget as HTMLElement;
- if (relatedTarget == null || (!isDescendant(relatedTarget, dropdownMenu) && e.relatedTarget != toggle))
- dropdown.hide();
- }
-}, true);
+ const dropdownMenu = target.closest('.dropdown-menu') as HTMLElement;
+ // Hide dropdowns when hovering off of the menu, so long as the new target is not part of the dropdown as well
+ if (dropdownMenu) {
+ const toggle = dropdownMenu.previousElementSibling as HTMLElement;
+ const dropdown = Dropdown.getOrCreateInstance(toggle);
+ const relatedTarget = e.relatedTarget as HTMLElement;
+ if (
+ relatedTarget == null ||
+ (!isDescendant(relatedTarget, dropdownMenu) && e.relatedTarget != toggle)
+ )
+ dropdown.hide();
+ }
+ },
+ true,
+);
-let closePopovers = () => {
+const closePopovers = () => {
document.querySelectorAll('[data-bs-toggle="popover"][aria-describedby]').forEach(e => {
- let p = Popover.getOrCreateInstance(e);
+ const p = Popover.getOrCreateInstance(e);
p.hide();
});
-}
-
-body.addEventListener('show.bs.popover', (event) => {
- closePopovers();
+};
- document.querySelectorAll('[data-bs-toggle="tooltip"][aria-describedby]').forEach(e => {
- let t = Tooltip.getOrCreateInstance(e);
- t.hide();
- });
-
- document.querySelectorAll('.tooltip').forEach(e => e.remove());
-}, true);
-
-body.addEventListener('show.bs.tooltip', (event) => {
- document.querySelectorAll('[data-bs-toggle="tooltip"][aria-describedby]').forEach(e => {
- let t = Tooltip.getOrCreateInstance(e);
- t.hide();
- });
-
- document.querySelectorAll('.tooltip').forEach(e => e.remove());
-}, true);
+body.addEventListener(
+ 'show.bs.popover',
+ event => {
+ closePopovers();
-document.onkeydown = (event) => {
+ document.querySelectorAll('[data-bs-toggle="tooltip"][aria-describedby]').forEach(e => {
+ const t = Tooltip.getOrCreateInstance(e);
+ t.hide();
+ });
+
+ document.querySelectorAll('.tooltip').forEach(e => e.remove());
+ },
+ true,
+);
+
+body.addEventListener(
+ 'show.bs.tooltip',
+ event => {
+ document.querySelectorAll('[data-bs-toggle="tooltip"][aria-describedby]').forEach(e => {
+ const t = Tooltip.getOrCreateInstance(e);
+ t.hide();
+ });
+
+ document.querySelectorAll('.tooltip').forEach(e => e.remove());
+ },
+ true,
+);
+
+document.onkeydown = event => {
event = event || window.event;
if (event.key == 'Escape') {
closePopovers();
}
-}
+};