Replace legacy icons
authorAlexander Ebert <ebert@woltlab.com>
Wed, 17 Aug 2022 11:26:48 +0000 (13:26 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Wed, 17 Aug 2022 11:26:48 +0000 (13:26 +0200)
57 files changed:
extra/migrate-fa-v4.php
ts/WoltLabSuite/Core/Acp/Ui/User/Editor.ts
ts/WoltLabSuite/Core/Bbcode/Code.ts
ts/WoltLabSuite/Core/Date/Picker.ts
ts/WoltLabSuite/Core/Form/Builder/Container/SuffixFormField.ts
ts/WoltLabSuite/Core/Language/Chooser.ts
ts/WoltLabSuite/Core/Media/List/Upload.ts
ts/WoltLabSuite/Core/Media/Manager/Base.ts
ts/WoltLabSuite/Core/Media/Manager/Editor.ts
ts/WoltLabSuite/Core/Media/Manager/Select.ts
ts/WoltLabSuite/Core/Media/Upload.ts
ts/WoltLabSuite/Core/Ui/Comment/Edit.ts
ts/WoltLabSuite/Core/Ui/Dialog.ts
ts/WoltLabSuite/Core/Ui/Dropdown/Builder.ts
ts/WoltLabSuite/Core/Ui/Feed/Dialog.ts
ts/WoltLabSuite/Core/Ui/FlexibleMenu.ts
ts/WoltLabSuite/Core/Ui/ItemList.ts
ts/WoltLabSuite/Core/Ui/ItemList/Static.ts
ts/WoltLabSuite/Core/Ui/Like/Handler.ts
ts/WoltLabSuite/Core/Ui/Message/InlineEditor.ts
ts/WoltLabSuite/Core/Ui/Mobile.ts
ts/WoltLabSuite/Core/Ui/Page/Menu/Main.ts
ts/WoltLabSuite/Core/Ui/Page/Search/Handler.ts
ts/WoltLabSuite/Core/Ui/Pagination.ts
ts/WoltLabSuite/Core/Ui/Redactor/Autosave.ts
ts/WoltLabSuite/Core/Ui/TabMenu.ts
ts/WoltLabSuite/Core/Ui/User/Editor.ts
ts/WoltLabSuite/Core/Ui/User/Menu/View.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/User/Editor.js
wcfsetup/install/files/js/WoltLabSuite/Core/Bbcode/Code.js
wcfsetup/install/files/js/WoltLabSuite/Core/Date/Picker.js
wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Container/SuffixFormField.js
wcfsetup/install/files/js/WoltLabSuite/Core/Language/Chooser.js
wcfsetup/install/files/js/WoltLabSuite/Core/Media/List/Upload.js
wcfsetup/install/files/js/WoltLabSuite/Core/Media/Manager/Base.js
wcfsetup/install/files/js/WoltLabSuite/Core/Media/Manager/Editor.js
wcfsetup/install/files/js/WoltLabSuite/Core/Media/Manager/Select.js
wcfsetup/install/files/js/WoltLabSuite/Core/Media/Upload.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Comment/Edit.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/Feed/Dialog.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/FlexibleMenu.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/ItemList.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/ItemList/Static.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Like/Handler.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Message/InlineEditor.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Mobile.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Main.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Search/Handler.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Pagination.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/Autosave.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/TabMenu.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Editor.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Menu/View.js
wcfsetup/install/files/lib/data/page/PageAction.class.php
wcfsetup/install/files/lib/system/page/handler/TDecoratedCategoryLookupPageHandler.class.php

index 2b34f8ddde1a6a18f35f71f33d57f8fe1ccedfe3..d9672f0de91f9ea064aeae1c411be7da1ebada19 100755 (executable)
@@ -126,7 +126,7 @@ function replaceIcons(string $filename): bool
             // If the icon only ships in `solid` style then we can safely
             // use any other variant too. The `solid` style is therefore
             // only enforced when there is a non-solid variant too.
-            if ($type === 'solid' && !$hasNonSolidStyle[$newIconName]) {
+            if ($type === 'solid' && $newIconName !== 'caret-down' && !$hasNonSolidStyle[$newIconName]) {
                 $type = 'regular';
             }
 
index 62d8d55c666d132f7cdaa5fff53e831b872b5e65..38aab23c75929ab73d8451285b010ba761290b8d 100644 (file)
@@ -157,7 +157,8 @@ class AcpUiUserEditor {
         let iconBanned = userRow.querySelector(".jsUserStatusBanned") as HTMLElement;
         if (banned && iconBanned === null) {
           iconBanned = document.createElement("span");
-          iconBanned.className = "icon icon16 fa-lock jsUserStatusBanned jsTooltip";
+          iconBanned.innerHTML = '<fa-icon size="16" name="lock"></fa-icon>';
+          iconBanned.classList.add("jsUserStatusBanned", "jsTooltip");
           iconBanned.title = Language.get("wcf.user.status.banned");
 
           userStatusIcons.appendChild(iconBanned);
@@ -169,7 +170,8 @@ class AcpUiUserEditor {
         let iconIsDisabled = userRow.querySelector(".jsUserStatusIsDisabled") as HTMLElement;
         if (isDisabled && iconIsDisabled === null) {
           iconIsDisabled = document.createElement("span");
-          iconIsDisabled.className = "icon icon16 fa-power-off jsUserStatusIsDisabled jsTooltip";
+          iconIsDisabled.innerHTML = '<fa-icon size="16" name="power-off"></fa-icon>';
+          iconIsDisabled.classList.add("jsUserStatusIsDisabled", "jsTooltip");
           iconIsDisabled.title = Language.get("wcf.user.status.isDisabled");
           userStatusIcons.appendChild(iconIsDisabled);
         } else if (!isDisabled && iconIsDisabled !== null) {
index 72c4877fa985dd94f1128d41febdc7fab3ed6428..f51aba580f37c84a5992156b7ea14a261a7f1256 100644 (file)
@@ -61,8 +61,9 @@ class Code {
     }
 
     const button = document.createElement("button");
-    button.className = "icon icon24 fa-files-o pointer jsTooltip";
-    button.setAttribute("title", Language.get("wcf.message.bbcode.code.copy"));
+    button.innerHTML = '<fa-icon size="24" name="files"></fa-icon>';
+    button.classList.add("jsTooltip");
+    button.title = Language.get("wcf.message.bbcode.code.copy");
 
     const clickCallback = async () => {
       await Clipboard.copyElementTextToClipboard(this.codeContainer);
@@ -70,7 +71,7 @@ class Code {
       UiNotification.show(Language.get("wcf.message.bbcode.code.copy.success"));
     };
     button.addEventListener("click", () => clickCallback());
-    
+
     header.appendChild(button);
   }
 
index badf4afff656d190f5e3d8c18347dbdfdfad0eb7..deafc707680e3b199a7e188f725ee75209ac3790 100644 (file)
@@ -767,8 +767,9 @@ const DatePicker = {
         });
         container.appendChild(openButton);
 
-        let icon = document.createElement("span");
-        icon.className = "icon icon16 fa-calendar";
+        let icon = document.createElement("fa-icon");
+        icon.size = 16;
+        icon.setIcon("calendar");
         openButton.appendChild(icon);
 
         element.parentNode!.insertBefore(container, element);
@@ -790,8 +791,9 @@ const DatePicker = {
 
           container.appendChild(clearButton);
 
-          icon = document.createElement("span");
-          icon.className = "icon icon16 fa-times";
+          icon = document.createElement("fa-icon");
+          icon.size = 16;
+          icon.setIcon("xmark");
           clearButton.appendChild(icon);
         }
 
index 4bb18d9514967c9a7c15eceee9f6fa600bfa642e..1027f0c240cf38e5498255810e32d0c8d436adce 100644 (file)
@@ -58,7 +58,7 @@ class SuffixFormField {
 
     this._suffixField.value = target.dataset.value!;
     this._suffixDropdownToggle.innerHTML =
-      target.dataset.label! + ' <span class="icon icon16 fa-caret-down pointer"></span>';
+      target.dataset.label! + ' <fa-icon size="16" name="caret-down" solid></fa-icon>';
   }
 
   /**
index 7896fb02f04e0ebd0c5ff1b26aee1c8211095e5c..8743f89e3ddfe297bf27c4745ffca2c7e527e04e 100644 (file)
@@ -152,8 +152,9 @@ function initElement(
     const div = document.createElement("div");
     dropdownToggle.appendChild(div);
 
-    const icon = document.createElement("span");
-    icon.className = "icon icon24 fa-question pointer";
+    const icon = document.createElement("fa-icon");
+    icon.size = 24;
+    icon.setIcon("question");
     div.appendChild(icon);
 
     const span = document.createElement("span");
index 46a45c28e075999e7ab440cca18e1d39709bf2c7..749005da7cd65057efd77d9c5e6171dab3c9202a 100644 (file)
@@ -21,8 +21,9 @@ class MediaListUpload extends MediaUpload<MediaListUploadOptions> {
     const space = document.createTextNode(" ");
     span.insertBefore(space, span.childNodes[0]);
 
-    const icon = document.createElement("span");
-    icon.className = "icon icon16 fa-upload";
+    const icon = document.createElement("fa-icon");
+    icon.size = 16;
+    icon.setIcon("upload");
     span.insertBefore(icon, span.childNodes[0]);
   }
 
index 5f870a81b4de041d4c17800761a7b8570877d54c..aeb2b046262316b17098fc41e00159a3943ba12e 100644 (file)
@@ -523,8 +523,8 @@ abstract class MediaManager<TOptions extends MediaManagerOptions = MediaManagerO
       buttons.appendChild(editButton);
 
       editButton.innerHTML = `
-        <a>
-          <span class="icon icon16 fa-pencil jsTooltip" title="${Language.get("wcf.global.button.edit")}"></span>
+        <a class="jsTooltip" title="${Language.get("wcf.global.button.edit")}">
+          <fa-icon size="16" name="pencil"></fa-icon>
           <span class="invisible">${Language.get("wcf.global.button.edit")}</span>
         </a>`;
 
@@ -542,8 +542,8 @@ abstract class MediaManager<TOptions extends MediaManagerOptions = MediaManagerO
       buttons.appendChild(deleteButton);
 
       deleteButton.innerHTML = `
-        <a>
-          <span class="icon icon16 fa-times jsTooltip" title="${Language.get("wcf.global.button.delete")}"></span>
+        <a class="jsTooltip" title="${Language.get("wcf.global.button.delete")}">
+          <fa-icon size="16" name="xmark"></fa-icon>
           <span class="invisible">${Language.get("wcf.global.button.delete")}</span>
         </a>`;
     }
index 7966eb3d8fbef60a0aeb6cfaec4f8e4dfdd2211f..8b8ab79e7636a231572d4c7f293c0ab432c3ab4e 100644 (file)
@@ -365,8 +365,8 @@ class MediaManagerEditor extends MediaManager<MediaManagerEditorOptions> {
     buttons.appendChild(listItem);
 
     listItem.innerHTML = `
-      <a>
-        <span class="icon icon16 fa-plus jsTooltip" title="${Language.get("wcf.global.button.insert")}"></span>
+      <a class="jsTooltip" title="${Language.get("wcf.global.button.insert")}">
+        <fa-icon size="16" name="plus"></fa-icon>
         <span class="invisible">${Language.get("wcf.global.button.insert")}</span>
       </a>`;
   }
index dd3b5c8c1848899410cda1f97814287a575ad478..11b364d35bb1cd5a491509c025608f2b3966e55d 100644 (file)
@@ -43,8 +43,9 @@ class MediaManagerSelect extends MediaManager<MediaManagerSelectOptions> {
           removeButton.className = "button";
           button.insertAdjacentElement("afterend", removeButton);
 
-          const icon = document.createElement("span");
-          icon.className = "icon icon16 fa-times";
+          const icon = document.createElement("fa-icon");
+          icon.size = 16;
+          icon.setIcon("xmark");
           removeButton.appendChild(icon);
 
           if (!storeElement.value) {
@@ -100,12 +101,14 @@ class MediaManagerSelect extends MediaManager<MediaManagerSelectOptions> {
         } else {
           let fileIcon = FileUtil.getIconNameByFilename(media.filename);
           if (fileIcon) {
-            fileIcon = "-" + fileIcon;
+            fileIcon = "file-" + fileIcon;
+          } else {
+            fileIcon="file"
           }
 
           displayElement.innerHTML = `
             <div class="box48" style="margin-bottom: 10px;">
-              <span class="icon icon48 fa-file${fileIcon}-o"></span>
+              <fa-icon size="48" name="${fileIcon}"></fa-icon>
               <div class="containerHeadline">
                 <h3>${media.filename}</h3>
                 <p>${media.formattedFilesize}</p>
@@ -157,11 +160,12 @@ class MediaManagerSelect extends MediaManager<MediaManagerSelectOptions> {
     buttons.appendChild(listItem);
 
     listItem.innerHTML =
-      '<a><span class="icon icon16 fa-check jsTooltip" title="' +
-      Language.get("wcf.media.button.select") +
-      '"></span> <span class="invisible">' +
-      Language.get("wcf.media.button.select") +
-      "</span></a>";
+      `
+        <a class="jsTooltip" title="${Language.get("wcf.media.button.select")}">
+          <fa-icon size="16" name="check"></fa-icon>
+          <span class="invisible">${Language.get("wcf.media.button.select")}</span>
+        </a>
+      `;
   }
 
   /**
index 267200a0d58019dc4a5b4fa8807f68d51f45b4b1..4d3c845013e960d56ba70f922db6ce67dcd5a6e3 100644 (file)
@@ -11,7 +11,6 @@
 import Upload from "../Upload";
 import * as Core from "../Core";
 import * as DomUtil from "../Dom/Util";
-import * as DomTraverse from "../Dom/Traverse";
 import * as Language from "../Language";
 import User from "../User";
 import * as DateUtil from "../Date/Util";
@@ -100,7 +99,8 @@ class MediaUpload<TOptions extends MediaUploadOptions = MediaUploadOptions> exte
           }
 
           const spinner = document.createElement("span");
-          spinner.className = "icon icon48 fa-spinner mediaThumbnail";
+          spinner.innerHTML = '<fa-icon size="48" name="spinner"></fa-icon>';
+          spinner.classList.add("mediaThumbnail");
 
           DomUtil.replaceElement(image!, spinner);
 
@@ -137,11 +137,12 @@ class MediaUpload<TOptions extends MediaUploadOptions = MediaUploadOptions> exte
     }
 
     const thumbnail = document.createElement("div");
-    thumbnail.className = "mediaThumbnail";
+    thumbnail.classList.add("mediaThumbnail");
     fileElement.appendChild(thumbnail);
 
-    const fileIcon = document.createElement("span");
-    fileIcon.className = "icon icon144 fa-spinner";
+    const fileIcon = document.createElement("fa-icon");
+    fileIcon.size = 144;
+    fileIcon.setIcon("spinner");
     thumbnail.appendChild(fileIcon);
 
     const mediaInformation = document.createElement("div");
@@ -259,10 +260,10 @@ class MediaUpload<TOptions extends MediaUploadOptions = MediaUploadOptions> exte
           p.remove();
         }
       } else {
-        DomTraverse.childByTag(DomTraverse.childByClass(file, "mediaInformation")!, "PROGRESS")!.remove();
+        file.querySelector(".mediaInformation progress")!.remove();
 
         if (media) {
-          const fileIcon = DomTraverse.childByTag(DomTraverse.childByClass(file, "mediaThumbnail")!, "FA-ICON")!;
+          const fileIcon = file.querySelector(".mediaThumbnail fa-icon") as FaIcon;
           this._replaceFileIcon(fileIcon, media, 144);
 
           file.classList.add("jsClipboardObject", "mediaFile", "jsObjectActionObject");
@@ -281,18 +282,15 @@ class MediaUpload<TOptions extends MediaUploadOptions = MediaUploadOptions> exte
             };
           }
 
-          const fileIcon = DomTraverse.childByTag(DomTraverse.childByClass(file, "mediaThumbnail")!, "FA-ICON")!;
+          const fileIcon = file.querySelector(".mediaThumbnail fa-icon") as FaIcon;
           fileIcon.setIcon("xmark");
 
           file.classList.add("uploadFailed", "pointer", "jsTooltip");
           file.title = Language.get("wcf.global.button.delete");
           file.addEventListener("click", () => file.remove());
 
-          const title = DomTraverse.childByClass(
-            DomTraverse.childByClass(file, "mediaInformation")!,
-            "mediaTitle",
-          ) as HTMLElement;
-          title.innerText = Language.get(`wcf.media.upload.error.${error.errorType}`, {
+          const title = file.querySelector(".mediaInformation .mediaTitle") as HTMLElement;
+          title.textContent = Language.get(`wcf.media.upload.error.${error.errorType}`, {
             filename: error.filename,
           });
         }
index e1e9c552139b187263f0099092171ddaadeb145a..c7a3a300c9aee3589ec3238ff93f069f4336cb5d 100644 (file)
@@ -235,8 +235,9 @@ class UiCommentEdit {
     const editorContainer = this._editorContainer!.querySelector(".editorContainer") as HTMLElement;
     DomUtil.hide(editorContainer);
 
-    const icon = document.createElement("span");
-    icon.className = "icon icon48 fa-spinner";
+    const icon = document.createElement("fa-icon");
+    icon.size = 48;
+    icon.setIcon("spinner");
     this._editorContainer!.appendChild(icon);
   }
 
index ec50a08bad3923afd44d22cc3360c103fb4ca249..6b4c2d90ff43e12f5880c5a90621c05e8b0b9dc0 100644 (file)
@@ -389,15 +389,12 @@ const UiDialog = {
 
     if (options.closable) {
       const closeButton = document.createElement("button");
-      closeButton.className = "dialogCloseButton jsTooltip";
+      closeButton.innerHTML = '<fa-icon size="24" name="xmark"></fa-icon>';
+      closeButton.classList.add("dialogCloseButton", "jsTooltip");
       closeButton.title = options.closeButtonLabel;
       closeButton.setAttribute("aria-label", options.closeButtonLabel);
       closeButton.addEventListener("click", () => this._close());
       header.appendChild(closeButton);
-
-      const span = document.createElement("span");
-      span.className = "icon icon24 fa-times";
-      closeButton.appendChild(span);
     }
 
     // Dialogs are positioned using `left: 50%` as a hack to
index 53e65c3064a22bea8e1afb27981dd86ad3ce502a..37c0eda2d436700c3ad1471852c001d79dbe4950 100644 (file)
@@ -75,8 +75,9 @@ function buildItemFromData(data: DropdownBuilderItemData): HTMLLIElement {
       size = ~~data.icon.size;
     }
 
-    const icon = document.createElement("span");
-    icon.className = `icon icon${size} fa-${data.icon.name}`;
+    const icon = document.createElement("fa-icon");
+    icon.size = size as any;
+    icon.setIcon(data.icon.name, data.icon.forceSolid ? true : false);
 
     link.appendChild(icon);
   }
@@ -200,6 +201,7 @@ interface BaseItemData {
   callback?: (link: HTMLAnchorElement) => void;
   href?: string;
   icon?: {
+    forceSolid?: boolean;
     name: string;
     size?: 16 | 24 | 32 | 48 | 64 | 96 | 144;
   };
index 925ed6afe661705d4e5551d453f9d583040c3f23..d090a0f53505487192686ebbc18e25d298a47e78 100644 (file)
@@ -47,9 +47,11 @@ function openDialog(event: Event): void {
   <dd>
     <div class="inputAddon">
       <input type="text" class="long" readonly value="${StringUtil.escapeHTML(linkWithoutAccessToken)}">
-      <a href="#" class="inputSuffix button jsTooltip feedLinkDialogCopyButton" title="${Language.get(
+      <button class="inputSuffix button jsTooltip feedLinkDialogCopyButton" title="${Language.get(
         "wcf.global.rss.copy",
-      )}"><span class="icon icon16 fa-files-o pointer"></span></a>
+      )}">
+        <fa-icon size="16" name="files"></fa-icon>
+      </button>
     </div>
   </dd>
 </dl>
@@ -58,9 +60,11 @@ function openDialog(event: Event): void {
   <dd>
     <div class="inputAddon">
       <input type="text" class="long" readonly value="${StringUtil.escapeHTML(linkWithAccessToken)}">
-      <a href="#" class="inputSuffix button jsTooltip feedLinkDialogCopyButton" title="${Language.get(
+      <button class="inputSuffix button jsTooltip feedLinkDialogCopyButton" title="${Language.get(
         "wcf.global.rss.copy",
-      )}"><span class="icon icon16 fa-files-o pointer"></span></a>
+      )}">
+        <fa-icon size="16" name="files"></fa-icon>
+      </a>
     </div>
   </dd>
 </dl>
index 230cf227cf97193926cdfca396b361792787b863..d7255938dc74259d63d64dbaa386ca97d79a6e13 100644 (file)
@@ -151,7 +151,7 @@ export function rebuild(containerId: string): void {
       dropdown.className = "dropdown jsFlexibleMenuDropdown";
 
       const icon = document.createElement("a");
-      icon.className = "icon icon16 fa-list";
+      icon.innerHTML = '<fa-icon size="16" name="list"></fa-icon>';
       dropdown.appendChild(icon);
 
       dropdownMenu = document.createElement("ul");
index 6807bc1609db307d18fe911c2738ef5ca1007759..c534337c2ca57a788b06f5d0014bca8264fc9e60 100644 (file)
@@ -255,8 +255,8 @@ function addItem(elementId: string, value: ItemData): void {
   listItem.appendChild(content);
 
   if (!data.element.disabled) {
-    const button = document.createElement("a");
-    button.className = "icon icon16 fa-times";
+    const button = document.createElement("button");
+    button.innerHTML = '<fa-icon size="16" name="xmark"></fa-icon>';
     button.addEventListener("click", removeItem);
     listItem.appendChild(button);
   }
index 1b45ab2bded4aceb8bf800e7aee9da8ebf5d8152..6353470801554f756f9d4eb2c478ae3d175fee1c 100644 (file)
@@ -227,8 +227,8 @@ function addItem(elementId: string, value: ItemData, forceRemoveIcon?: boolean):
   listItem.appendChild(content);
 
   if (forceRemoveIcon || !data.element.disabled) {
-    const button = document.createElement("a");
-    button.className = "icon icon16 fa-times";
+    const button = document.createElement("button");
+    button.innerHTML = '<fa-icon size="16" name="xmark"></fa-icon>';
     button.addEventListener("click", (ev) => removeItem(ev));
     listItem.appendChild(button);
   }
index db4d8451785158ec0201aaa7f25eb9d3e7a37662..04e3b9dafee4f9a89e9c25771745f7debda1c058 100644 (file)
@@ -271,8 +271,9 @@ class UiLikeHandler {
     button.href = "#";
     button.title = title;
 
-    const icon = document.createElement("span");
-    icon.className = "icon icon16 fa-smile-o";
+    const icon = document.createElement("fa-icon");
+    icon.size = 16;
+    icon.setIcon("smile");
 
     if (reactionTypeID === undefined || reactionTypeID == 0) {
       icon.dataset.reactionTypeId = "0";
index 096291384b1a1a15bde0f6ceea7deab2da2fe816..68452a5a284e38b7d0e860b7c0017f136638627d 100644 (file)
@@ -357,8 +357,9 @@ class UiMessageInlineEditor implements AjaxCallbackObject {
     messageBodyEditor.className = "messageBody editor";
     data.messageBodyEditor = messageBodyEditor;
 
-    const icon = document.createElement("span");
-    icon.className = "icon icon48 fa-spinner";
+    const icon = document.createElement("fa-icon");
+    icon.size = 48;
+    icon.setIcon("spinner");
     messageBodyEditor.appendChild(icon);
 
     data.messageBody.insertAdjacentElement("afterend", messageBodyEditor);
@@ -605,8 +606,9 @@ class UiMessageInlineEditor implements AjaxCallbackObject {
     const editorContainer = elementData.messageBodyEditor!.querySelector(".editorContainer") as HTMLElement;
     DomUtil.hide(editorContainer);
 
-    const icon = document.createElement("span");
-    icon.className = "icon icon48 fa-spinner";
+    const icon = document.createElement("fa-icon");
+    icon.size = 48;
+    icon.setIcon("spinner");
     elementData.messageBodyEditor!.appendChild(icon);
   }
 
index 2e589d4a77bbbc2844eecf7a3025e06de6588d6c..2e7b8cc2fd8cff905df83185c031819999486404 100644 (file)
@@ -68,11 +68,9 @@ function initButtonGroupNavigation(): void {
 
     navigation.parentElement!.classList.add("hasMobileNavigation");
 
-    const button = document.createElement("a");
-    button.className = "dropdownLabel";
-    const span = document.createElement("span");
-    span.className = "icon icon24 fa-ellipsis-v";
-    button.appendChild(span);
+    const button = document.createElement("button");
+    button.innerHTML = '<fa-icon size="24" name="ellipsis-vertical"></fa-icon>';
+    button.classList.add("dropdownLabel");
     button.addEventListener("click", (event) => {
       event.preventDefault();
       event.stopPropagation();
index 78c67b916108f1fcd3aac2e4c75551af1d5184cf..deed873a1333e496723607b29f9782c3594331fa 100644 (file)
@@ -256,7 +256,7 @@ export class PageMenuMain implements PageMenuProvider {
       button.classList.add("pageMenuMainItemToggle");
       button.setAttribute("aria-expanded", "false");
       button.setAttribute("aria-controls", menuId);
-      button.innerHTML = '<span class="icon icon24 fa-angle-down" aria-hidden="true"></span>';
+      button.innerHTML = '<fa-icon size="24" name="angle-down"></fa-icon>';
 
       let ariaLabel = menuItem.title;
       if (menuItem.link) {
index 3e7a7ddd764fa992535e1d76e64c1f5d9b06b6fe..0f67f9e8882a898e6ab2c3f22e00d7468fc48299 100644 (file)
@@ -21,7 +21,7 @@ type CallbackSelect = (objectId: number) => void;
 
 interface ItemData {
   description?: string;
-  image: string;
+  image: string | string[];
   link: string;
   objectID: number;
   title: string;
@@ -66,10 +66,14 @@ class UiPageSearchHandler implements DialogCallbackObject {
 
     data.returnValues.forEach((item) => {
       let image = item.image;
-      if (/^fa-/.test(image)) {
-        image = `<span class="icon icon48 ${image} pointer jsTooltip" title="${Language.get(
-          "wcf.global.select",
-        )}"></span>`;
+      if (Array.isArray(image)) {
+        const [iconName, forceSolid] = image;
+
+        image = `
+          <button class="jsTooltip" title="${Language.get("wcf.global.select")}">
+            <fa-icon size="48" name="${iconName}"${forceSolid ? " solid" : ""}></fa-icon>
+          </button>
+        `;
       }
 
       const listItem = document.createElement("li");
@@ -81,7 +85,7 @@ class UiPageSearchHandler implements DialogCallbackObject {
         <div>
           <div class="containerHeadline">
             <h3>
-                <a href="#">${StringUtil.escapeHTML(item.title)}</a>
+                <button>${StringUtil.escapeHTML(item.title)}</button>
             </h3>
             ${description}
           </div>
index 7aee1afa72ce4517488d319ad5c6e7fb8fe8a193..c0676dc132c149c5debf28723ebe028ed81e131e 100644 (file)
@@ -61,17 +61,21 @@ class UiPagination {
     listItem.className = "skip";
     list.appendChild(listItem);
 
-    let iconClassNames = "icon icon24 fa-chevron-left";
+    let icon = document.createElement("fa-icon");
+    icon.size = 24;
+    icon.setIcon("chevron-left");
     if (this.activePage > 1) {
       const link = document.createElement("a");
-      link.className = iconClassNames + " jsTooltip";
+      link.className = "jsTooltip";
       link.href = "#";
       link.title = Language.get("wcf.global.page.previous");
       link.rel = "prev";
+      link.setAttribute("role", "button");
+      link.append(icon);
       listItem.appendChild(link);
       link.addEventListener("click", (ev) => this.switchPage(this.activePage - 1, ev));
     } else {
-      listItem.innerHTML = '<span class="' + iconClassNames + '"></span>';
+      listItem.append(icon);
       listItem.classList.add("disabled");
     }
 
@@ -168,17 +172,22 @@ class UiPagination {
     listItem = document.createElement("li");
     listItem.className = "skip";
     list.appendChild(listItem);
-    iconClassNames = "icon icon24 fa-chevron-right";
+
+    icon = document.createElement("fa-icon");
+    icon.size = 24;
+    icon.setIcon("chevron-right");
     if (this.activePage < this.maxPage) {
       const link = document.createElement("a");
-      link.className = iconClassNames + " jsTooltip";
+      link.classList.add("jsTooltip");
       link.href = "#";
       link.title = Language.get("wcf.global.page.next");
       link.rel = "next";
+      link.setAttribute("role", "button");
+      link.append(icon);
       listItem.appendChild(link);
       link.addEventListener("click", (ev) => this.switchPage(this.activePage + 1, ev));
     } else {
-      listItem.innerHTML = '<span class="' + iconClassNames + '"></span>';
+      listItem.append(icon);
       listItem.classList.add("disabled");
     }
 
index 1373020b727e1ec79784c706b690f10ae5ec0312..306800d6536084cc238c25f7419a4b1229808d80 100644 (file)
@@ -202,26 +202,18 @@ class UiRedactorAutosave {
     title.textContent = Language.get("wcf.editor.autosave.restored");
     container.appendChild(title);
 
-    const buttonKeep = document.createElement("a");
-    buttonKeep.className = "jsTooltip";
-    buttonKeep.href = "#";
+    const buttonKeep = document.createElement("button");
+    buttonKeep.innerHTML = '<fa-icon size="16" name="check"></fa-icon>';
+    buttonKeep.classList.add("jsTooltip");
     buttonKeep.title = Language.get("wcf.editor.autosave.keep");
-    buttonKeep.innerHTML = '<span class="icon icon16 fa-check green"></span>';
-    buttonKeep.addEventListener("click", (event) => {
-      event.preventDefault();
-
-      this.hideOverlay();
-    });
+    buttonKeep.addEventListener("click", () => this.hideOverlay());
     container.appendChild(buttonKeep);
 
-    const buttonDiscard = document.createElement("a");
-    buttonDiscard.className = "jsTooltip";
-    buttonDiscard.href = "#";
+    const buttonDiscard = document.createElement("button");
+    buttonDiscard.innerHTML = '<fa-icon size="16" name="xmark"></fa-icon>';
+    buttonDiscard.classList.add("jsTooltip");
     buttonDiscard.title = Language.get("wcf.editor.autosave.discard");
-    buttonDiscard.innerHTML = '<span class="icon icon16 fa-times red"></span>';
-    buttonDiscard.addEventListener("click", (event) => {
-      event.preventDefault();
-
+    buttonDiscard.addEventListener("click", () => {
       // remove from storage
       this.clear();
 
index 24c5291d0052e6753e4b30832baec2beb0e45efd..eeafd516523f2b6986a52d7084e93f0b72151b39 100644 (file)
@@ -207,8 +207,9 @@ function rebuildMenuOverflow(menu: HTMLElement): void {
   let overlayLeft = menu.querySelector(".tabMenuOverlayLeft");
   if (overflowLeft) {
     if (overlayLeft === null) {
-      overlayLeft = document.createElement("span");
-      overlayLeft.className = "tabMenuOverlayLeft icon icon24 fa-angle-left";
+      overlayLeft = document.createElement("button");
+      overlayLeft.innerHTML = '<fa-icon size="24" name="angle-left"></fa-icon>';
+      overlayLeft.className = "tabMenuOverlayLeft";
       overlayLeft.addEventListener("click", () => {
         const listWidth = list.clientWidth;
         scrollMenu(list, list.scrollLeft - ~~(listWidth / 2), list.scrollLeft, list.scrollWidth, listWidth, false);
@@ -225,8 +226,9 @@ function rebuildMenuOverflow(menu: HTMLElement): void {
   let overlayRight = menu.querySelector(".tabMenuOverlayRight");
   if (overflowRight) {
     if (overlayRight === null) {
-      overlayRight = document.createElement("span");
-      overlayRight.className = "tabMenuOverlayRight icon icon24 fa-angle-right";
+      overlayRight = document.createElement("button");
+      overlayRight.innerHTML = '<fa-icon size="24" name="angle-right"></fa-icon>';
+      overlayRight.className = "tabMenuOverlayRight";
       overlayRight.addEventListener("click", () => {
         const listWidth = list.clientWidth;
         scrollMenu(list, list.scrollLeft + ~~(listWidth / 2), list.scrollLeft, list.scrollWidth, listWidth, false);
index 7ea58626ad3b1cf84cce1683f0edd8c663b55b12..a8695e26a71a13037f638d504c1026c7c20b8b38 100644 (file)
@@ -133,7 +133,8 @@ class UserEditor implements AjaxCallbackObject, DialogCallbackObject {
         let banIcon = contentTitle.querySelector(".jsUserBanned") as HTMLElement;
         if (data.actionName === "ban") {
           banIcon = document.createElement("span");
-          banIcon.className = "icon icon24 fa-lock jsUserBanned jsTooltip";
+          banIcon.innerHTML = '<fa-icon size="24" name="lock"></fa-icon>';
+          banIcon.classList.add("jsUserBanned", "jsTooltip");
           banIcon.title = data.returnValues;
           contentTitle.appendChild(banIcon);
         } else if (banIcon) {
index 84e520e83cef6d93d07f30bd3df78afe33173298..bca7f69aff03903b575e8442faea8722bf9e0d44 100644 (file)
@@ -165,8 +165,8 @@ export class UserMenuView {
       </div>
       <div class="userMenuItemMeta"></div>
       <div class="userMenuItemUnread">
-        <button class="userMenuItemMarkAsRead">
-          <span class="icon icon24 fa-check jsTooltip" title="${Language.get("wcf.global.button.markAsRead")}"></span>
+        <button class="userMenuItemMarkAsRead jsTooltip" title="${Language.get("wcf.global.button.markAsRead")}">
+          <fa-icon size="24" name="check"></fa-icon>
         </button>
       </div>
     `;
index c61294a3231eaa868364edd96c7c0904fbceae82..5827ae4012b578560307742c282a20503e497a06 100644 (file)
@@ -132,7 +132,8 @@ define(["require", "exports", "tslib", "./Content/Remove/Handler", "../../../Cor
                     let iconBanned = userRow.querySelector(".jsUserStatusBanned");
                     if (banned && iconBanned === null) {
                         iconBanned = document.createElement("span");
-                        iconBanned.className = "icon icon16 fa-lock jsUserStatusBanned jsTooltip";
+                        iconBanned.innerHTML = '<fa-icon size="16" name="lock"></fa-icon>';
+                        iconBanned.classList.add("jsUserStatusBanned", "jsTooltip");
                         iconBanned.title = Language.get("wcf.user.status.banned");
                         userStatusIcons.appendChild(iconBanned);
                     }
@@ -143,7 +144,8 @@ define(["require", "exports", "tslib", "./Content/Remove/Handler", "../../../Cor
                     let iconIsDisabled = userRow.querySelector(".jsUserStatusIsDisabled");
                     if (isDisabled && iconIsDisabled === null) {
                         iconIsDisabled = document.createElement("span");
-                        iconIsDisabled.className = "icon icon16 fa-power-off jsUserStatusIsDisabled jsTooltip";
+                        iconIsDisabled.innerHTML = '<fa-icon size="16" name="power-off"></fa-icon>';
+                        iconIsDisabled.classList.add("jsUserStatusIsDisabled", "jsTooltip");
                         iconIsDisabled.title = Language.get("wcf.user.status.isDisabled");
                         userStatusIcons.appendChild(iconIsDisabled);
                     }
index e34724427a0cd7b68d341e364621e22935beaf3e..1eb43633762111eb001232f9f93b74ea6de0662f 100644 (file)
@@ -47,8 +47,9 @@ define(["require", "exports", "tslib", "../Language", "../Clipboard", "../Ui/Not
                 return;
             }
             const button = document.createElement("button");
-            button.className = "icon icon24 fa-files-o pointer jsTooltip";
-            button.setAttribute("title", Language.get("wcf.message.bbcode.code.copy"));
+            button.innerHTML = '<fa-icon size="24" name="files"></fa-icon>';
+            button.classList.add("jsTooltip");
+            button.title = Language.get("wcf.message.bbcode.code.copy");
             const clickCallback = async () => {
                 await Clipboard.copyElementTextToClipboard(this.codeContainer);
                 UiNotification.show(Language.get("wcf.message.bbcode.code.copy.success"));
index 79ca064ffeb8dc11d1fe0e3440a5cecae01b23bd..c89405ebc6d8d30c318a989f4e40918a2c2f8e34 100644 (file)
@@ -636,8 +636,9 @@ define(["require", "exports", "tslib", "../Core", "./Util", "../Dom/Change/Liste
                     }
                 });
                 container.appendChild(openButton);
-                let icon = document.createElement("span");
-                icon.className = "icon icon16 fa-calendar";
+                let icon = document.createElement("fa-icon");
+                icon.size = 16;
+                icon.setIcon("calendar");
                 openButton.appendChild(icon);
                 element.parentNode.insertBefore(container, element);
                 container.insertBefore(element, openButton);
@@ -654,8 +655,9 @@ define(["require", "exports", "tslib", "../Core", "./Util", "../Dom/Change/Liste
                         clearButton.style.setProperty("visibility", "hidden", "");
                     }
                     container.appendChild(clearButton);
-                    icon = document.createElement("span");
-                    icon.className = "icon icon16 fa-times";
+                    icon = document.createElement("fa-icon");
+                    icon.size = 16;
+                    icon.setIcon("xmark");
                     clearButton.appendChild(icon);
                 }
                 // check if the date input has one of the following classes set otherwise default to 'short'
index c008b02edaeaf6d4058a8cbe730b03ab6b05a061..feacc36faaf887f4484fc79837663c039d8b3bca 100644 (file)
@@ -41,7 +41,7 @@ define(["require", "exports", "tslib", "../../../Ui/Dropdown/Simple", "../../../
             });
             this._suffixField.value = target.dataset.value;
             this._suffixDropdownToggle.innerHTML =
-                target.dataset.label + ' <span class="icon icon16 fa-caret-down pointer"></span>';
+                target.dataset.label + ' <fa-icon size="16" name="caret-down" solid></fa-icon>';
         }
         /**
          * Destroys the suffix dropdown if the parent form is unregistered.
index 57f1dd8dee484c6b7c299a9cf61a31b3f5540e50..9e1c0ca0e8b9ace08661f22f4ca34c9f94a6f38b 100644 (file)
@@ -106,8 +106,9 @@ define(["require", "exports", "tslib", "../Core", "../Language", "../Dom/Util",
             dropdownToggle.innerHTML = "";
             const div = document.createElement("div");
             dropdownToggle.appendChild(div);
-            const icon = document.createElement("span");
-            icon.className = "icon icon24 fa-question pointer";
+            const icon = document.createElement("fa-icon");
+            icon.size = 24;
+            icon.setIcon("question");
             div.appendChild(icon);
             const span = document.createElement("span");
             span.textContent = Language.get("wcf.global.language.noSelection");
index 1e7398f39b5cae83b34e579380c8fae889c469f0..75f72576bdd0d3ab98588e4d742325cb4d002e6b 100644 (file)
@@ -17,8 +17,9 @@ define(["require", "exports", "tslib", "../Upload", "../../Core"], function (req
             const span = this._button.querySelector("span");
             const space = document.createTextNode(" ");
             span.insertBefore(space, span.childNodes[0]);
-            const icon = document.createElement("span");
-            icon.className = "icon icon16 fa-upload";
+            const icon = document.createElement("fa-icon");
+            icon.size = 16;
+            icon.setIcon("upload");
             span.insertBefore(icon, span.childNodes[0]);
         }
         _getParameters() {
index d27b87776e5d1ab316e27c31bdc77b70879a0164..e7417f80a78ded0a8496fc17e56be63be48072d6 100644 (file)
@@ -422,8 +422,8 @@ define(["require", "exports", "tslib", "../../Core", "../../Language", "../../Pe
                 editButton.dataset.objectId = media.mediaID.toString();
                 buttons.appendChild(editButton);
                 editButton.innerHTML = `
-        <a>
-          <span class="icon icon16 fa-pencil jsTooltip" title="${Language.get("wcf.global.button.edit")}"></span>
+        <a class="jsTooltip" title="${Language.get("wcf.global.button.edit")}">
+          <fa-icon size="16" name="pencil"></fa-icon>
           <span class="invisible">${Language.get("wcf.global.button.edit")}</span>
         </a>`;
                 const deleteButton = document.createElement("li");
@@ -436,8 +436,8 @@ define(["require", "exports", "tslib", "../../Core", "../../Language", "../../Pe
                 })).replace(uuid, StringUtil.escapeHTML(media.filename));
                 buttons.appendChild(deleteButton);
                 deleteButton.innerHTML = `
-        <a>
-          <span class="icon icon16 fa-times jsTooltip" title="${Language.get("wcf.global.button.delete")}"></span>
+        <a class="jsTooltip" title="${Language.get("wcf.global.button.delete")}">
+          <fa-icon size="16" name="xmark"></fa-icon>
           <span class="invisible">${Language.get("wcf.global.button.delete")}</span>
         </a>`;
             }
index 767e2a8ba53c07ff4eace82e51945e1925b2f320..4149a177daf59904f412bf7e7222a8478e543205 100644 (file)
@@ -288,8 +288,8 @@ define(["require", "exports", "tslib", "./Base", "../../Core", "../../Event/Hand
             listItem.dataset.objectId = media.mediaID.toString();
             buttons.appendChild(listItem);
             listItem.innerHTML = `
-      <a>
-        <span class="icon icon16 fa-plus jsTooltip" title="${Language.get("wcf.global.button.insert")}"></span>
+      <a class="jsTooltip" title="${Language.get("wcf.global.button.insert")}">
+        <fa-icon size="16" name="plus"></fa-icon>
         <span class="invisible">${Language.get("wcf.global.button.insert")}</span>
       </a>`;
         }
index 1d7821ee1c11140f0c7df94b1816046b7e6deadf..4515bdedb9eca86a78d756be4e56265478d2668d 100644 (file)
@@ -34,8 +34,9 @@ define(["require", "exports", "tslib", "./Base", "../../Core", "../../Dom/Traver
                         const removeButton = document.createElement("p");
                         removeButton.className = "button";
                         button.insertAdjacentElement("afterend", removeButton);
-                        const icon = document.createElement("span");
-                        icon.className = "icon icon16 fa-times";
+                        const icon = document.createElement("fa-icon");
+                        icon.size = 16;
+                        icon.setIcon("xmark");
                         removeButton.appendChild(icon);
                         if (!storeElement.value) {
                             Util_1.default.hide(removeButton);
@@ -83,11 +84,14 @@ define(["require", "exports", "tslib", "./Base", "../../Core", "../../Dom/Traver
                     else {
                         let fileIcon = FileUtil.getIconNameByFilename(media.filename);
                         if (fileIcon) {
-                            fileIcon = "-" + fileIcon;
+                            fileIcon = "file-" + fileIcon;
+                        }
+                        else {
+                            fileIcon = "file";
                         }
                         displayElement.innerHTML = `
             <div class="box48" style="margin-bottom: 10px;">
-              <span class="icon icon48 fa-file${fileIcon}-o"></span>
+              <fa-icon size="48" name="${fileIcon}"></fa-icon>
               <div class="containerHeadline">
                 <h3>${media.filename}</h3>
                 <p>${media.formattedFilesize}</p>
@@ -129,11 +133,12 @@ define(["require", "exports", "tslib", "./Base", "../../Core", "../../Dom/Traver
             listItem.dataset.objectId = media.mediaID.toString();
             buttons.appendChild(listItem);
             listItem.innerHTML =
-                '<a><span class="icon icon16 fa-check jsTooltip" title="' +
-                    Language.get("wcf.media.button.select") +
-                    '"></span> <span class="invisible">' +
-                    Language.get("wcf.media.button.select") +
-                    "</span></a>";
+                `
+        <a class="jsTooltip" title="${Language.get("wcf.media.button.select")}">
+          <fa-icon size="16" name="check"></fa-icon>
+          <span class="invisible">${Language.get("wcf.media.button.select")}</span>
+        </a>
+      `;
         }
         /**
          * Handles clicking on the remove button.
index d53f529b07349d1649f76b08f4449f2b4e78c19b..35dbe499676591d9a0ac8f4febd99be4e6ad0e91 100644 (file)
@@ -7,12 +7,11 @@
  * @module  WoltLabSuite/Core/Media/Upload
  * @woltlabExcludeBundle tiny
  */
-define(["require", "exports", "tslib", "../Upload", "../Core", "../Dom/Util", "../Dom/Traverse", "../Language", "../User", "../Date/Util", "../FileUtil", "../Dom/Change/Listener", "../Event/Handler"], function (require, exports, tslib_1, Upload_1, Core, DomUtil, DomTraverse, Language, User_1, DateUtil, FileUtil, DomChangeListener, EventHandler) {
+define(["require", "exports", "tslib", "../Upload", "../Core", "../Dom/Util", "../Language", "../User", "../Date/Util", "../FileUtil", "../Dom/Change/Listener", "../Event/Handler"], function (require, exports, tslib_1, Upload_1, Core, DomUtil, Language, User_1, DateUtil, FileUtil, DomChangeListener, EventHandler) {
     "use strict";
     Upload_1 = tslib_1.__importDefault(Upload_1);
     Core = tslib_1.__importStar(Core);
     DomUtil = tslib_1.__importStar(DomUtil);
-    DomTraverse = tslib_1.__importStar(DomTraverse);
     Language = tslib_1.__importStar(Language);
     User_1 = tslib_1.__importDefault(User_1);
     DateUtil = tslib_1.__importStar(DateUtil);
@@ -76,7 +75,8 @@ define(["require", "exports", "tslib", "../Upload", "../Core", "../Dom/Util", ".
                             image = cell.querySelector(".icon48");
                         }
                         const spinner = document.createElement("span");
-                        spinner.className = "icon icon48 fa-spinner mediaThumbnail";
+                        spinner.innerHTML = '<fa-icon size="48" name="spinner"></fa-icon>';
+                        spinner.classList.add("mediaThumbnail");
                         DomUtil.replaceElement(image, spinner);
                         // replace title and uploading user
                         const ps = cell.querySelectorAll(".box48 > div > p");
@@ -111,10 +111,11 @@ define(["require", "exports", "tslib", "../Upload", "../Core", "../Dom/Util", ".
                 fileElement = document.createElement("p");
             }
             const thumbnail = document.createElement("div");
-            thumbnail.className = "mediaThumbnail";
+            thumbnail.classList.add("mediaThumbnail");
             fileElement.appendChild(thumbnail);
-            const fileIcon = document.createElement("span");
-            fileIcon.className = "icon icon144 fa-spinner";
+            const fileIcon = document.createElement("fa-icon");
+            fileIcon.size = 144;
+            fileIcon.setIcon("spinner");
             thumbnail.appendChild(fileIcon);
             const mediaInformation = document.createElement("div");
             mediaInformation.className = "mediaInformation";
@@ -211,9 +212,9 @@ define(["require", "exports", "tslib", "../Upload", "../Core", "../Dom/Util", ".
                     }
                 }
                 else {
-                    DomTraverse.childByTag(DomTraverse.childByClass(file, "mediaInformation"), "PROGRESS").remove();
+                    file.querySelector(".mediaInformation progress").remove();
                     if (media) {
-                        const fileIcon = DomTraverse.childByTag(DomTraverse.childByClass(file, "mediaThumbnail"), "FA-ICON");
+                        const fileIcon = file.querySelector(".mediaThumbnail fa-icon");
                         this._replaceFileIcon(fileIcon, media, 144);
                         file.classList.add("jsClipboardObject", "mediaFile", "jsObjectActionObject");
                         file.dataset.objectId = media.mediaID.toString();
@@ -230,13 +231,13 @@ define(["require", "exports", "tslib", "../Upload", "../Core", "../Dom/Util", ".
                                 filename: file.dataset.filename,
                             };
                         }
-                        const fileIcon = DomTraverse.childByTag(DomTraverse.childByClass(file, "mediaThumbnail"), "FA-ICON");
+                        const fileIcon = file.querySelector(".mediaThumbnail fa-icon");
                         fileIcon.setIcon("xmark");
                         file.classList.add("uploadFailed", "pointer", "jsTooltip");
                         file.title = Language.get("wcf.global.button.delete");
                         file.addEventListener("click", () => file.remove());
-                        const title = DomTraverse.childByClass(DomTraverse.childByClass(file, "mediaInformation"), "mediaTitle");
-                        title.innerText = Language.get(`wcf.media.upload.error.${error.errorType}`, {
+                        const title = file.querySelector(".mediaInformation .mediaTitle");
+                        title.textContent = Language.get(`wcf.media.upload.error.${error.errorType}`, {
                             filename: error.filename,
                         });
                     }
index 7da1118e98b8d0c34d2245e7038b82012612a89c..7253a62fb2f5eeef290fa4e2dfd66f7e76ec8134 100644 (file)
@@ -182,8 +182,9 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ch
         _hideEditor() {
             const editorContainer = this._editorContainer.querySelector(".editorContainer");
             Util_1.default.hide(editorContainer);
-            const icon = document.createElement("span");
-            icon.className = "icon icon48 fa-spinner";
+            const icon = document.createElement("fa-icon");
+            icon.size = 48;
+            icon.setIcon("spinner");
             this._editorContainer.appendChild(icon);
         }
         /**
index ea27ef1903bf420420978b0775caca83791b068b..ec5965beb38ef845c1d1ac2f23bb3c3926f54a6a 100644 (file)
@@ -319,14 +319,12 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Change/Listener", "./S
             header.appendChild(title);
             if (options.closable) {
                 const closeButton = document.createElement("button");
-                closeButton.className = "dialogCloseButton jsTooltip";
+                closeButton.innerHTML = '<fa-icon size="24" name="xmark"></fa-icon>';
+                closeButton.classList.add("dialogCloseButton", "jsTooltip");
                 closeButton.title = options.closeButtonLabel;
                 closeButton.setAttribute("aria-label", options.closeButtonLabel);
                 closeButton.addEventListener("click", () => this._close());
                 header.appendChild(closeButton);
-                const span = document.createElement("span");
-                span.className = "icon icon24 fa-times";
-                closeButton.appendChild(span);
             }
             // Dialogs are positioned using `left: 50%` as a hack to
             // force long softwrapping of text without causing other
index c4c81497360ec36107d8c7e03ebb0348dd98bd95..e100fc54177c6a80d1df9f4ae2a1f1e5556513e2 100644 (file)
@@ -66,8 +66,9 @@ define(["require", "exports", "tslib", "../../Core", "./Simple"], function (requ
             if (typeof data.icon.size === "number" && _validIconSizes.indexOf(~~data.icon.size) !== -1) {
                 size = ~~data.icon.size;
             }
-            const icon = document.createElement("span");
-            icon.className = `icon icon${size} fa-${data.icon.name}`;
+            const icon = document.createElement("fa-icon");
+            icon.size = size;
+            icon.setIcon(data.icon.name, data.icon.forceSolid ? true : false);
             link.appendChild(icon);
         }
         const label = typeof data.label === "string" ? data.label.trim() : "";
index 70d4077698fe7369ba641d1d9cdbd8ed7629305a..56cf799a3170982b256811e0fb61bef7cac5312e 100644 (file)
@@ -40,7 +40,9 @@ define(["require", "exports", "tslib", "../Dialog", "../../StringUtil", "../../L
   <dd>
     <div class="inputAddon">
       <input type="text" class="long" readonly value="${StringUtil.escapeHTML(linkWithoutAccessToken)}">
-      <a href="#" class="inputSuffix button jsTooltip feedLinkDialogCopyButton" title="${Language.get("wcf.global.rss.copy")}"><span class="icon icon16 fa-files-o pointer"></span></a>
+      <button class="inputSuffix button jsTooltip feedLinkDialogCopyButton" title="${Language.get("wcf.global.rss.copy")}">
+        <fa-icon size="16" name="files"></fa-icon>
+      </button>
     </div>
   </dd>
 </dl>
@@ -49,7 +51,9 @@ define(["require", "exports", "tslib", "../Dialog", "../../StringUtil", "../../L
   <dd>
     <div class="inputAddon">
       <input type="text" class="long" readonly value="${StringUtil.escapeHTML(linkWithAccessToken)}">
-      <a href="#" class="inputSuffix button jsTooltip feedLinkDialogCopyButton" title="${Language.get("wcf.global.rss.copy")}"><span class="icon icon16 fa-files-o pointer"></span></a>
+      <button class="inputSuffix button jsTooltip feedLinkDialogCopyButton" title="${Language.get("wcf.global.rss.copy")}">
+        <fa-icon size="16" name="files"></fa-icon>
+      </a>
     </div>
   </dd>
 </dl>
index 194ea6dc9c3a7829db526789f1a72de600209f69..1e40f84ca80a75a71083fe969b05dfac24a6761e 100644 (file)
@@ -135,7 +135,7 @@ define(["require", "exports", "tslib", "../Dom/Change/Listener", "../Dom/Util",
                 dropdown = document.createElement("li");
                 dropdown.className = "dropdown jsFlexibleMenuDropdown";
                 const icon = document.createElement("a");
-                icon.className = "icon icon16 fa-list";
+                icon.innerHTML = '<fa-icon size="16" name="list"></fa-icon>';
                 dropdown.appendChild(icon);
                 dropdownMenu = document.createElement("ul");
                 dropdownMenu.classList.add("dropdownMenu");
index 0ead64c283a83534a234c17694541ee19cb8497c..693978bfb236e92634bc6b48f5aa10145480b232 100644 (file)
@@ -231,8 +231,8 @@ define(["require", "exports", "tslib", "../Core", "../Dom/Traverse", "../Languag
         content.textContent = value.value;
         listItem.appendChild(content);
         if (!data.element.disabled) {
-            const button = document.createElement("a");
-            button.className = "icon icon16 fa-times";
+            const button = document.createElement("button");
+            button.innerHTML = '<fa-icon size="16" name="xmark"></fa-icon>';
             button.addEventListener("click", removeItem);
             listItem.appendChild(button);
         }
index 7bcc2fd84ba67afc409508d222ac18b12b792d19..27ca9cd5461fb8b772ea5f73e725c3bc33ed4cb9 100644 (file)
@@ -166,8 +166,8 @@ define(["require", "exports", "tslib", "../../Core", "../../Dom/Traverse", "../.
         content.textContent = value.value;
         listItem.appendChild(content);
         if (forceRemoveIcon || !data.element.disabled) {
-            const button = document.createElement("a");
-            button.className = "icon icon16 fa-times";
+            const button = document.createElement("button");
+            button.innerHTML = '<fa-icon size="16" name="xmark"></fa-icon>';
             button.addEventListener("click", (ev) => removeItem(ev));
             listItem.appendChild(button);
         }
index 82b67793203652ae56ab83624e1c19e9a88b3b35..d858c3159dfec09cb76e8db5dc643cc171eb96e4 100644 (file)
@@ -188,8 +188,9 @@ define(["require", "exports", "tslib", "../../Core", "../../Dom/Change/Listener"
             }
             button.href = "#";
             button.title = title;
-            const icon = document.createElement("span");
-            icon.className = "icon icon16 fa-smile-o";
+            const icon = document.createElement("fa-icon");
+            icon.size = 16;
+            icon.setIcon("smile");
             if (reactionTypeID === undefined || reactionTypeID == 0) {
                 icon.dataset.reactionTypeId = "0";
             }
index 9ba294552165e2977ecf34ec0b11579ef920e63e..b8f68c67e88f9c0490c1733771039cc5411e33ea 100644 (file)
@@ -274,8 +274,9 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ch
             const messageBodyEditor = document.createElement("div");
             messageBodyEditor.className = "messageBody editor";
             data.messageBodyEditor = messageBodyEditor;
-            const icon = document.createElement("span");
-            icon.className = "icon icon48 fa-spinner";
+            const icon = document.createElement("fa-icon");
+            icon.size = 48;
+            icon.setIcon("spinner");
             messageBodyEditor.appendChild(icon);
             data.messageBody.insertAdjacentElement("afterend", messageBodyEditor);
             Util_1.default.hide(data.messageBody);
@@ -471,8 +472,9 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ch
             const elementData = this._elements.get(this._activeElement);
             const editorContainer = elementData.messageBodyEditor.querySelector(".editorContainer");
             Util_1.default.hide(editorContainer);
-            const icon = document.createElement("span");
-            icon.className = "icon icon48 fa-spinner";
+            const icon = document.createElement("fa-icon");
+            icon.size = 48;
+            icon.setIcon("spinner");
             elementData.messageBodyEditor.appendChild(icon);
         }
         /**
index fe26e735db981b0ebc825ed734065519f67874b8..9d10772a3ecc82fbe504e6a455a6b44967c5e0cd 100644 (file)
@@ -59,11 +59,9 @@ define(["require", "exports", "tslib", "focus-trap", "../Core", "../Dom/Change/L
                 return;
             }
             navigation.parentElement.classList.add("hasMobileNavigation");
-            const button = document.createElement("a");
-            button.className = "dropdownLabel";
-            const span = document.createElement("span");
-            span.className = "icon icon24 fa-ellipsis-v";
-            button.appendChild(span);
+            const button = document.createElement("button");
+            button.innerHTML = '<fa-icon size="24" name="ellipsis-vertical"></fa-icon>';
+            button.classList.add("dropdownLabel");
             button.addEventListener("click", (event) => {
                 event.preventDefault();
                 event.stopPropagation();
index 913c83e666a190dff42fc59a06bfd9c4d9a2a9ef..1ed76da0a5c862565f9f80795b1c07b00ee853f1 100644 (file)
@@ -196,7 +196,7 @@ define(["require", "exports", "tslib", "./Container", "../../../Language", "../.
                 button.classList.add("pageMenuMainItemToggle");
                 button.setAttribute("aria-expanded", "false");
                 button.setAttribute("aria-controls", menuId);
-                button.innerHTML = '<span class="icon icon24 fa-angle-down" aria-hidden="true"></span>';
+                button.innerHTML = '<fa-icon size="24" name="angle-down"></fa-icon>';
                 let ariaLabel = menuItem.title;
                 if (menuItem.link) {
                     ariaLabel = Language.get("wcf.menu.page.button.toggle", { title: menuItem.title });
index e783b7be7394663c00e2a4e455d03f34c114c818..fcf0233d288cb7d513cad725f152831245be5a6d 100644 (file)
@@ -47,8 +47,13 @@ define(["require", "exports", "tslib", "../../../Language", "../../../StringUtil
             }
             data.returnValues.forEach((item) => {
                 let image = item.image;
-                if (/^fa-/.test(image)) {
-                    image = `<span class="icon icon48 ${image} pointer jsTooltip" title="${Language.get("wcf.global.select")}"></span>`;
+                if (Array.isArray(image)) {
+                    const [iconName, forceSolid] = image;
+                    image = `
+          <button class="jsTooltip" title="${Language.get("wcf.global.select")}">
+            <fa-icon size="48" name="${iconName}"${forceSolid ? " solid" : ""}></fa-icon>
+          </button>
+        `;
                 }
                 const listItem = document.createElement("li");
                 listItem.dataset.objectId = item.objectID.toString();
@@ -58,7 +63,7 @@ define(["require", "exports", "tslib", "../../../Language", "../../../StringUtil
         <div>
           <div class="containerHeadline">
             <h3>
-                <a href="#">${StringUtil.escapeHTML(item.title)}</a>
+                <button>${StringUtil.escapeHTML(item.title)}</button>
             </h3>
             ${description}
           </div>
index 4a47083aba9f0dbd1dab54d76be4d06c03517686..7b467355e5698cff4660edef8eee1674d5655037 100644 (file)
@@ -45,18 +45,22 @@ define(["require", "exports", "tslib", "../Core", "../Language", "../StringUtil"
             let listItem = document.createElement("li");
             listItem.className = "skip";
             list.appendChild(listItem);
-            let iconClassNames = "icon icon24 fa-chevron-left";
+            let icon = document.createElement("fa-icon");
+            icon.size = 24;
+            icon.setIcon("chevron-left");
             if (this.activePage > 1) {
                 const link = document.createElement("a");
-                link.className = iconClassNames + " jsTooltip";
+                link.className = "jsTooltip";
                 link.href = "#";
                 link.title = Language.get("wcf.global.page.previous");
                 link.rel = "prev";
+                link.setAttribute("role", "button");
+                link.append(icon);
                 listItem.appendChild(link);
                 link.addEventListener("click", (ev) => this.switchPage(this.activePage - 1, ev));
             }
             else {
-                listItem.innerHTML = '<span class="' + iconClassNames + '"></span>';
+                listItem.append(icon);
                 listItem.classList.add("disabled");
             }
             // add first page
@@ -145,18 +149,22 @@ define(["require", "exports", "tslib", "../Core", "../Language", "../StringUtil"
             listItem = document.createElement("li");
             listItem.className = "skip";
             list.appendChild(listItem);
-            iconClassNames = "icon icon24 fa-chevron-right";
+            icon = document.createElement("fa-icon");
+            icon.size = 24;
+            icon.setIcon("chevron-right");
             if (this.activePage < this.maxPage) {
                 const link = document.createElement("a");
-                link.className = iconClassNames + " jsTooltip";
+                link.classList.add("jsTooltip");
                 link.href = "#";
                 link.title = Language.get("wcf.global.page.next");
                 link.rel = "next";
+                link.setAttribute("role", "button");
+                link.append(icon);
                 listItem.appendChild(link);
                 link.addEventListener("click", (ev) => this.switchPage(this.activePage + 1, ev));
             }
             else {
-                listItem.innerHTML = '<span class="' + iconClassNames + '"></span>';
+                listItem.append(icon);
                 listItem.classList.add("disabled");
             }
             if (hasHiddenPages) {
index 70973730a0d4c6fd550b7ffe9c3338916af7606d..9f1c7ef39ef93e7468336077d10de77825fd8401 100644 (file)
@@ -158,23 +158,17 @@ define(["require", "exports", "tslib", "../../Core", "../../Devtools", "../../Ev
             const title = document.createElement("span");
             title.textContent = Language.get("wcf.editor.autosave.restored");
             container.appendChild(title);
-            const buttonKeep = document.createElement("a");
-            buttonKeep.className = "jsTooltip";
-            buttonKeep.href = "#";
+            const buttonKeep = document.createElement("button");
+            buttonKeep.innerHTML = '<fa-icon size="16" name="check"></fa-icon>';
+            buttonKeep.classList.add("jsTooltip");
             buttonKeep.title = Language.get("wcf.editor.autosave.keep");
-            buttonKeep.innerHTML = '<span class="icon icon16 fa-check green"></span>';
-            buttonKeep.addEventListener("click", (event) => {
-                event.preventDefault();
-                this.hideOverlay();
-            });
+            buttonKeep.addEventListener("click", () => this.hideOverlay());
             container.appendChild(buttonKeep);
-            const buttonDiscard = document.createElement("a");
-            buttonDiscard.className = "jsTooltip";
-            buttonDiscard.href = "#";
+            const buttonDiscard = document.createElement("button");
+            buttonDiscard.innerHTML = '<fa-icon size="16" name="xmark"></fa-icon>';
+            buttonDiscard.classList.add("jsTooltip");
             buttonDiscard.title = Language.get("wcf.editor.autosave.discard");
-            buttonDiscard.innerHTML = '<span class="icon icon16 fa-times red"></span>';
-            buttonDiscard.addEventListener("click", (event) => {
-                event.preventDefault();
+            buttonDiscard.addEventListener("click", () => {
                 // remove from storage
                 this.clear();
                 // set code
index 1dd751cd00dc814bec37747f49743d0076206331..ca874ac73c8244e0d8257705150b49f14752e7b8 100644 (file)
@@ -178,8 +178,9 @@ define(["require", "exports", "tslib", "../Dom/Change/Listener", "../Dom/Util",
         let overlayLeft = menu.querySelector(".tabMenuOverlayLeft");
         if (overflowLeft) {
             if (overlayLeft === null) {
-                overlayLeft = document.createElement("span");
-                overlayLeft.className = "tabMenuOverlayLeft icon icon24 fa-angle-left";
+                overlayLeft = document.createElement("button");
+                overlayLeft.innerHTML = '<fa-icon size="24" name="angle-left"></fa-icon>';
+                overlayLeft.className = "tabMenuOverlayLeft";
                 overlayLeft.addEventListener("click", () => {
                     const listWidth = list.clientWidth;
                     scrollMenu(list, list.scrollLeft - ~~(listWidth / 2), list.scrollLeft, list.scrollWidth, listWidth, false);
@@ -195,8 +196,9 @@ define(["require", "exports", "tslib", "../Dom/Change/Listener", "../Dom/Util",
         let overlayRight = menu.querySelector(".tabMenuOverlayRight");
         if (overflowRight) {
             if (overlayRight === null) {
-                overlayRight = document.createElement("span");
-                overlayRight.className = "tabMenuOverlayRight icon icon24 fa-angle-right";
+                overlayRight = document.createElement("button");
+                overlayRight.innerHTML = '<fa-icon size="24" name="angle-right"></fa-icon>';
+                overlayRight.className = "tabMenuOverlayRight";
                 overlayRight.addEventListener("click", () => {
                     const listWidth = list.clientWidth;
                     scrollMenu(list, list.scrollLeft + ~~(listWidth / 2), list.scrollLeft, list.scrollWidth, listWidth, false);
index 18e906e55abcdf2b174d5ccbcd739fba9eda3dd8..f12fc0b942dbe707c809c227ca9892a620df9da7 100644 (file)
@@ -112,7 +112,8 @@ define(["require", "exports", "tslib", "../../Ajax", "../../Core", "../../Dom/Ut
                     let banIcon = contentTitle.querySelector(".jsUserBanned");
                     if (data.actionName === "ban") {
                         banIcon = document.createElement("span");
-                        banIcon.className = "icon icon24 fa-lock jsUserBanned jsTooltip";
+                        banIcon.innerHTML = '<fa-icon size="24" name="lock"></fa-icon>';
+                        banIcon.classList.add("jsUserBanned", "jsTooltip");
                         banIcon.title = data.returnValues;
                         contentTitle.appendChild(banIcon);
                     }
index 9774ce04b1272a6550cbeae816fe9b53ad9bf312..dc8507bc124fad626804fe18df769882fb731d0d 100644 (file)
@@ -132,8 +132,8 @@ define(["require", "exports", "tslib", "../../../Date/Util", "../../../StringUti
       </div>
       <div class="userMenuItemMeta"></div>
       <div class="userMenuItemUnread">
-        <button class="userMenuItemMarkAsRead">
-          <span class="icon icon24 fa-check jsTooltip" title="${Language.get("wcf.global.button.markAsRead")}"></span>
+        <button class="userMenuItemMarkAsRead jsTooltip" title="${Language.get("wcf.global.button.markAsRead")}">
+          <fa-icon size="24" name="check"></fa-icon>
         </button>
       </div>
     `;
index 35d9b8e5b92b65cde37bc1a23725c23e451854de..c5abbda8ce3117e53a3ab90759923146adba37f0 100644 (file)
@@ -337,8 +337,11 @@ class PageAction extends AbstractDatabaseObjectAction implements ISearchAction,
      */
     public function getSearchResultList()
     {
-        /** @noinspection PhpUndefinedMethodInspection */
-        return $this->pageEditor->getHandler()->lookup($this->parameters['data']['searchString']);
+        $pageHandler = $this->pageEditor->getHandler();
+
+        \assert($pageHandler instanceof ILookupPageHandler);
+
+        return $pageHandler->lookup($this->parameters['data']['searchString']);
     }
 
     /**
index 4ae33e8d267793adf78590f4cb98314819046427..87089e1f445b142d3b92a6cf89e6fded8e1871aa 100644 (file)
@@ -132,7 +132,7 @@ trait TDecoratedCategoryLookupPageHandler
 
             $results[] = [
                 'description' => $description,
-                'image' => 'fa-folder-open-o',
+                'image' => ['folder', false],
                 'link' => $category->getLink(),
                 'objectID' => $categoryID,
                 'title' => $category->getTitle(),