Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions com.woltlab.wcf/templates/shared_fontAwesomeJavaScript.tpl
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
<script>
require(['Language', 'WoltLabSuite/Core/Ui/Style/FontAwesome'], (Language, UiStyleFontAwesome) => {
Language.addObject({
'wcf.global.filter.button.clear': '{jslang}wcf.global.filter.button.clear{/jslang}',
'wcf.global.filter.error.noMatches': '{jslang}wcf.global.filter.error.noMatches{/jslang}',
'wcf.global.filter.placeholder': '{jslang}wcf.global.filter.placeholder{/jslang}',
'wcf.global.fontAwesome.selectIcon': '{jslang}wcf.global.fontAwesome.selectIcon{/jslang}'
});

UiStyleFontAwesome.setup();
});
{jsphrase name='wcf.global.filter.button.clear'}
{jsphrase name='wcf.global.filter.error.noMatches'}
{jsphrase name='wcf.global.filter.placeholder'}
{jsphrase name='wcf.global.fontAwesome.selectIcon'}
</script>
165 changes: 82 additions & 83 deletions ts/WoltLabSuite/Core/Ui/Style/FontAwesome.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,94 +7,86 @@
* @woltlabExcludeBundle tiny
*/

import { DialogCallbackObject, DialogCallbackSetup } from "../Dialog/Data";
import * as Language from "../../Language";
import UiDialog from "../Dialog";
import { getPhrase } from "WoltLabSuite/Core/Language";
import UiItemListFilter from "../ItemList/Filter";
import { dialogFactory } from "WoltLabSuite/Core/Component/Dialog";

type CallbackSelect = (icon: string, forceSolid: boolean) => void;
type IconData = { icon: string; forceSolid: boolean };

function createIconList(): HTMLElement {
const ul = document.createElement("ul");
ul.classList.add("fontAwesome__icons");
ul.id = "fontAwesomeIcons";

const icons: string[] = [];
window.getFontAwesome7Metadata().forEach(([, hasRegular], name) => {
if (hasRegular) {
icons.push(
`<li><button type="button" class="fontAwesome__icon"><fa-icon size="48" name="${name}" solid></fa-icon><small class="fontAwesome__icon__name">${name}</small></button></li>`,
);
}

icons.push(
`<li><button type="button" class="fontAwesome__icon"><fa-icon size="48" name="${name}"></fa-icon><small class="fontAwesome__icon__name">${name}</small></button></li>`,
);
});

class UiStyleFontAwesome implements DialogCallbackObject {
private callback?: CallbackSelect = undefined;
private iconList?: HTMLElement = undefined;
private itemListFilter?: UiItemListFilter = undefined;

open(callback: CallbackSelect): void {
this.callback = callback;

UiDialog.open(this);
}

/**
* Selects an icon, notifies the callback and closes the dialog.
*/
protected click(event: MouseEvent): void {
event.preventDefault();
ul.innerHTML = icons.join("");

const target = event.target as HTMLElement;
const item = target.closest("li") as HTMLLIElement;
const icon = item.querySelector("fa-icon")!;
return ul;
}

UiDialog.close(this);
let content: HTMLElement | undefined = undefined;
function getContent(): HTMLElement {
if (content === undefined) {
const iconList = createIconList();
iconList.addEventListener("click", (event) => {
event.preventDefault();

const { target } = event;
if (!(target instanceof HTMLButtonElement)) {
return;
}

const icon = target.querySelector("fa-icon")!;
const selectedEvent = new CustomEvent<IconData>("font-awesome:selected", {
bubbles: true,
detail: {
icon: icon.name,
forceSolid: icon.solid,
},
});
iconList.dispatchEvent(selectedEvent);
});

this.callback!(icon.name, icon.solid);
content = document.createElement("div");
content.id = "fontAwesomeSelection";
content.append(iconList);
}

_dialogSetup(): ReturnType<DialogCallbackSetup> {
return {
id: "fontAwesomeSelection",
options: {
onSetup: () => {
this.iconList = document.getElementById("fontAwesomeIcons") as HTMLElement;

const icons: string[] = [];
window.getFontAwesome7Metadata().forEach(([, hasRegular], name) => {
if (hasRegular) {
icons.push(`<li><fa-icon size="48" name="${name}" solid></fa-icon><small>${name}</small></li>`);
}

icons.push(`<li><fa-icon size="48" name="${name}"></fa-icon><small>${name}</small></li>`);
});

// build icons
this.iconList.innerHTML = icons.join("");

this.iconList.addEventListener("click", (ev) => this.click(ev));

this.itemListFilter = new UiItemListFilter("fontAwesomeIcons", {
callbackPrepareItem: (item) => {
const small = item.querySelector("small") as HTMLElement;
const text = small.textContent.trim();

return {
item,
span: small,
text,
};
},
enableVisibilityFilter: false,
filterPosition: "top",
});
},
onShow: () => {
this.itemListFilter!.reset();
},
title: Language.get("wcf.global.fontAwesome.selectIcon"),
},
source: '<ul class="fontAwesomeIcons" id="fontAwesomeIcons"></ul>',
};
}
return content;
}

let uiStyleFontAwesome: UiStyleFontAwesome;

/**
* Sets the list of available icons, must be invoked prior to any call
* to the `open()` method.
*/
export function setup(): void {
if (!uiStyleFontAwesome) {
uiStyleFontAwesome = new UiStyleFontAwesome();
let itemListFilter: UiItemListFilter | undefined = undefined;
function setupListeners(): void {
if (itemListFilter === undefined) {
itemListFilter = new UiItemListFilter("fontAwesomeIcons", {
callbackPrepareItem: (item) => {
const small = item.querySelector("small") as HTMLElement;
const text = small.textContent.trim();

return {
item,
span: small,
text,
};
},
enableVisibilityFilter: false,
filterPosition: "top",
});
} else {
itemListFilter.reset();
}
}

Expand All @@ -103,11 +95,18 @@ export function setup(): void {
* invoked with the selection icon's name as the only argument.
*/
export function open(callback: CallbackSelect): void {
if (!uiStyleFontAwesome) {
throw new Error(
"Missing icon data, please include the template before calling this method using `{include file='shared_fontAwesomeJavaScript'}`.",
);
}
const dialog = dialogFactory().fromElement(getContent()).asConfirmation();
dialog.addEventListener(
"font-awesome:selected",
(event: CustomEvent<IconData>) => {
dialog.close();

callback(event.detail.icon, event.detail.forceSolid);
},
{ once: true },
);

dialog.show(getPhrase("wcf.global.fontAwesome.selectIcon"));

uiStyleFontAwesome.open(callback);
setupListeners();
}
135 changes: 64 additions & 71 deletions wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Style/FontAwesome.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading