Skip to content

Commit

Permalink
make sim selection dropdown click to open (#4234)
Browse files Browse the repository at this point in the history
  • Loading branch information
kayla-glick authored Mar 12, 2024
1 parent e20e1e4 commit 385a461
Show file tree
Hide file tree
Showing 2 changed files with 210 additions and 173 deletions.
242 changes: 127 additions & 115 deletions ui/core/components/sim_title_dropdown.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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 = `
<div class="dropdown sim-link-dropdown">
${rootLink.outerHTML}
<ul class="dropdown-menu"></ul>
</div>
`;
<div class="dropdown sim-link-dropdown">
${rootLink.outerHTML}
<ul class="dropdown-menu"></ul>
</div>
`;

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
Expand All @@ -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 = `
<div class="dropend sim-link-dropdown">
${classLink.outerHTML}
${dropdownMenu.outerHTML}
</div>
`;
<div class="dropend sim-link-dropdown">
${classLink.outerHTML}
${dropdownMenu.outerHTML}
</div>
`;

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 = `
<a href="javascript:void(0)" class="sim-link ${textKlass}" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<div class="sim-link-content">
<img src="${iconPath}" class="sim-link-icon">
<div class="d-flex flex-column">
<span class="sim-link-label text-white">WoWSims - WOTLK</span>
<span class="sim-link-title">${label}</span>
${this.launchStatusLabel(data)}
</div>
</div>
</a>
`;
<a href="javascript:void(0)" class="sim-link ${textKlass}" role="button" data-bs-toggle="dropdown" data-bs-trigger="click" aria-expanded="false">
<div class="sim-link-content">
<img src="${iconPath}" class="sim-link-icon">
<div class="d-flex flex-column">
<span class="sim-link-label text-white">WoWSims - WOTLK</span>
<span class="sim-link-title">${label}</span>
${this.launchStatusLabel(data)}
</div>
</div>
</a>
`;

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 = `
<a href="${raidSimSiteUrl}" class="sim-link ${textKlass}">
<div class="sim-link-content">
<img src="${iconPath}" class="sim-link-icon">
<div class="d-flex flex-column">
<span class="sim-link-title">${label}</span>
${this.launchStatusLabel({ type: 'Raid' })}
</div>
</div>
</a>
`;
<a href="${raidSimSiteUrl}" class="sim-link ${textKlass}">
<div class="sim-link-content">
<img src="${iconPath}" class="sim-link-icon">
<div class="d-flex flex-column">
<span class="sim-link-title">${label}</span>
${this.launchStatusLabel({ type: 'Raid' })}
</div>
</div>
</a>
`;

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 = `
<a href="${href}" class="sim-link ${textKlass}" ${specIndexes.length > 1 ? 'role="button" data-bs-toggle="dropdown" aria-expanded="false"' : ''}>
<div class="sim-link-content">
<img src="${iconPath}" class="sim-link-icon">
<div class="d-flex flex-column">
<span class="sim-link-title">${label}</span>
${specIndexes.length == 1 ? this.launchStatusLabel({ type: 'Spec', index: specIndexes[0] }) : ''}
</div>
</div>
</a>
`;
<a href="${href}" class="sim-link ${textKlass}" ${
specIndexes.length > 1
? 'role="button" data-bs-toggle="dropdown" aria-expanded="false"'
: ''
}>
<div class="sim-link-content">
<img src="${iconPath}" class="sim-link-icon">
<div class="d-flex flex-column">
<span class="sim-link-title">${label}</span>
${specIndexes.length == 1 ? this.launchStatusLabel({ type: 'Spec', index: specIndexes[0] }) : ''}
</div>
</div>
</a>
`;

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 = `
<a href="${href}" class="sim-link ${textKlass}" role="button">
<div class="sim-link-content">
<img src="${iconPath}" class="sim-link-icon">
<div class="d-flex flex-column">
<span class="sim-link-label">${className}</span>
<span class="sim-link-title">${specLabel}</span>
${this.launchStatusLabel({ type: 'Spec', index: specIndex })}
</div>
</div>
</a>
`;
<a href="${href}" class="sim-link ${textKlass}" role="button">
<div class="sim-link-content">
<img src="${iconPath}" class="sim-link-icon">
<div class="d-flex flex-column">
<span class="sim-link-label">${className}</span>
<span class="sim-link-title">${specLabel}</span>
${this.launchStatusLabel({ type: 'Spec', index: specIndex })}
</div>
</div>
</a>
`;

return fragment.children[0] as HTMLElement;
}
Expand All @@ -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;

Expand All @@ -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];
}
Expand All @@ -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);
}
}
Loading

0 comments on commit 385a461

Please sign in to comment.