Skip to content

Commit 6c87579

Browse files
committed
Reduce the jittery of the live preview of label badges
See https://www.woltlab.com/community/thread/314429/
1 parent b47b120 commit 6c87579

File tree

5 files changed

+81
-61
lines changed

5 files changed

+81
-61
lines changed

com.woltlab.wcf/templates/shared_badgeColorFormField.tpl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<ul class="labelSelection{if !$field->getClasses()|empty} {implode from=$field->getClasses() item=class glue=' '}{$class}{/implode}{/if}">
22
{foreach from=$field->getOptions() item=color}
3-
<li{if $color == 'custom'} class="custom"{/if}>
3+
<li{if $color === 'custom'} class="labelSelection__custom custom"{/if}>
44
<label class="labelSelection__label">
55
<input {*
66
*}type="radio" {*
@@ -11,8 +11,8 @@
1111
*}{if $field->isImmutable()} disabled{/if}{*
1212
*}{foreach from=$field->getFieldAttributes() key=attributeName item=attributeValue} {$attributeName}="{$attributeValue}"{/foreach}{*
1313
*}>
14-
{if $color == 'custom'}
15-
<span class="labelSelection__span">
14+
{if $color === 'custom'}
15+
<span class="labelSelection__span labelSelection__span--custom">
1616
<input type="text" id="{$field->getPrefixedId()}Custom" {*
1717
*}name="{$field->getPrefixedId()}customCssClassName" {*
1818
*}value="{$field->getCustomClassName()}" {*
@@ -30,8 +30,8 @@
3030

3131
<script data-relocate="true">
3232
{if $field->getTextReferenceNodeId()}
33-
require(["WoltLabSuite/Core/Form/Builder/Field/Controller/BadgeColor"], ({ BadgeColorPreview }) => {
34-
new BadgeColorPreview(
33+
require(["WoltLabSuite/Core/Form/Builder/Field/Controller/BadgeColor"], ({ setup }) => {
34+
setup(
3535
'{unsafe:$field->getPrefixedId()|encodeJS}Container',
3636
'{unsafe:$field->getTextReferenceNodeId()|encodeJS}',
3737
'{unsafe:$field->getDefaultLabelText()|encodeJS}',
Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,45 @@
11
/**
2-
* @author Olaf Braun
3-
* @copyright 2001-2024 WoltLab GmbH
2+
* @author Alexander Ebert
3+
* @copyright 2001-2025 WoltLab GmbH
44
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
55
* @since 6.2
66
* @woltlabExcludeBundle all
77
*/
88

9-
export class BadgeColorPreview {
10-
readonly #container: HTMLElement | null;
11-
readonly #referenceField: HTMLInputElement | null;
12-
readonly #defaultLabelText: string;
13-
14-
constructor(fieldId: string, referenceFieldId: string, defaultLabelText: string) {
15-
this.#defaultLabelText = defaultLabelText;
16-
this.#container = document.getElementById(fieldId);
17-
18-
if (this.#container === null) {
19-
throw new Error("Unknown field with id '" + fieldId + "'.");
20-
}
21-
this.#referenceField = document.getElementById(referenceFieldId) as HTMLInputElement | null;
22-
if (this.#referenceField === null) {
23-
throw new Error("Unknown reference element '" + referenceFieldId + "'.");
9+
function updatePreview(inputField: HTMLInputElement, fields: HTMLElement[], placeholder: string): void {
10+
window.requestAnimationFrame(() => {
11+
const value = inputField.value.trim() || placeholder;
12+
for (const field of fields) {
13+
field.textContent = value;
2414
}
15+
});
16+
}
2517

26-
this.#referenceField.addEventListener("input", () => this.#updatePreview());
27-
this.#updatePreview();
18+
export function setup(containerId: string, inputFieldId: string, placeholder: string): void {
19+
const container = document.getElementById(containerId);
20+
if (container === null) {
21+
throw new Error(`Unknown container with id '${containerId}'.`);
2822
}
2923

30-
#updatePreview(): void {
31-
const value = this.#referenceField!.value.trim() || this.#defaultLabelText;
32-
this.#container!.querySelectorAll(".labelSelection__span.badge").forEach((span: HTMLSpanElement) => {
33-
span.textContent = value;
34-
});
24+
const inputField = document.getElementById(inputFieldId);
25+
if (inputField === null) {
26+
throw new Error(`Unknown input field with id '${inputFieldId}'.`);
27+
} else if (!(inputField instanceof HTMLInputElement)) {
28+
throw new Error("Expected the input field to be an <input> element.", { cause: { inputField } });
3529
}
30+
31+
const fields = Array.from(
32+
container.querySelectorAll<HTMLElement>(".labelSelection__span:not(.labelSelection__span--custom)"),
33+
);
34+
if (fields.length === 0) {
35+
throw new Error("The container does not contain any fields.", { cause: { container } });
36+
}
37+
38+
inputField.addEventListener(
39+
"input",
40+
() => {
41+
updatePreview(inputField, fields, placeholder);
42+
},
43+
{ passive: true },
44+
);
3645
}

wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Controller/BadgeColor.js

Lines changed: 27 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wcfsetup/install/files/lib/system/form/builder/field/BadgeColorFormField.class.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ final class BadgeColorFormField extends RadioButtonFormField implements IPattern
4848
public function __construct()
4949
{
5050
$this
51-
->addClass('inlineList')
5251
->addFieldClass('labelSelection__radio')
5352
->defaultLabelText(WCF::getLanguage()->get('wcf.acp.label.defaultValue'))
5453
->options(\array_combine(self::AVAILABLE_CSS_CLASSNAMES, self::AVAILABLE_CSS_CLASSNAMES))

wcfsetup/install/files/style/ui/label.scss

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,11 @@
5151
cursor: pointer;
5252
}
5353

54-
.labelSelection.inlineList > li {
55-
flex-basis: 30%;
56-
}
57-
58-
.labelSelection > li.custom {
59-
display: flex;
54+
.labelSelection {
55+
column-gap: 10px;
56+
display: grid;
57+
grid-auto-flow: row;
58+
grid-template-columns: repeat(3, 1fr);
6059
}
6160

6261
.labelSelection__label {
@@ -71,6 +70,16 @@
7170
margin-right: 7px;
7271
}
7372

74-
.labelSelection > li.custom .labelSelection__span {
73+
.labelSelection__span {
74+
overflow: hidden;
75+
text-overflow: ellipsis;
76+
white-space: nowrap;
77+
}
78+
79+
.labelSelection__custom {
80+
display: flex;
81+
}
82+
83+
.labelSelection__custom .labelSelection__span {
7584
flex: 1 1 auto;
7685
}

0 commit comments

Comments
 (0)