{* the settings template does not generate direct ouput anymore, but captures it content *}
{include file='messageFormSettings'}
-<div class="messageTabMenu" data-preselect="{if $preselectTabMenu|isset}{$preselectTabMenu}{else}true{/if}" data-wysiwyg-container-id="{if $wysiwygContainerID|isset}{$wysiwygContainerID}{else}text{/if}">
+<div class="messageTabMenu" data-preselect="{if $preselectTabMenu|isset}{$preselectTabMenu}{else}true{/if}"
+ data-wysiwyg-container-id="{if $wysiwygContainerID|isset}{$wysiwygContainerID}{else}text{/if}">
<nav class="messageTabMenuNavigation jsOnly">
<ul>
- {if MODULE_SMILEY && !$smileyCategories|empty}<li data-name="smilies"><button type="button">{icon name='face-smile'} <span>{lang}wcf.message.smilies{/lang}</span></button></li>{/if}
+ {if MODULE_SMILEY && !$smileyCategories|empty}
+ <li data-name="smilies">
+ <button type="button">
+ {icon name='face-smile'}
+ <span>{lang}wcf.message.smilies{/lang}</span>
+ </button>
+ </li>
+ {/if}
{if !$attachmentHandler|empty && $attachmentHandler->canUpload()}
- <li data-name="attachments"><button type="button">{icon name='paperclip'} <span>{lang}wcf.attachment.attachments{/lang}</span></button></li>
+ <li data-name="attachments">
+ <button type="button">
+ {icon name='paperclip'}
+ <span>{lang}wcf.attachment.attachments{/lang}</span>
+ {if $attachmentHandler->count() > 0}
+ <span class="badge badgeUpdate">{#$attachmentHandler->count()}</span>
+ {/if}
+ </button>
+ </li>
+ {/if}
+ {if $__messageFormSettings}
+ <li data-name="settings">
+ <button type="button">
+ {icon name='gear'}
+ <span>{lang}wcf.message.settings{/lang}</span>
+ </button>
+ </li>
+ {/if}
+ {if $__showPoll|isset && $__showPoll}
+ <li data-name="poll">
+ <button type="button">
+ {icon name='chart-bar'}
+ <span>{lang}wcf.poll.management{/lang}</span>
+ </button>
+ </li>
{/if}
- {if $__messageFormSettings}<li data-name="settings"><button type="button">{icon name='gear'} <span>{lang}wcf.message.settings{/lang}</span></button></li>{/if}
- {if $__showPoll|isset && $__showPoll}<li data-name="poll"><button type="button">{icon name='chart-bar'} <span>{lang}wcf.poll.management{/lang}</span></button></li>{/if}
{event name='tabMenuTabs'}
</ul>
</nav>
-
+
{if MODULE_SMILEY && !$smileyCategories|empty}{include file='shared_messageFormSmileyTab'}{/if}
{if !$attachmentHandler|empty && $attachmentHandler->canUpload()}
{include file='shared_messageFormAttachments'}
{/if}
-
+
{if $__messageFormSettings}{unsafe:$__messageFormSettings}{/if}
{include file='__messageFormPoll'}
-
+
{event name='tabMenuContents'}
-</div>
+</div>
\ No newline at end of file
{capture assign='__messageFormSettingsInlineContent'}{include file='messageFormSettingsInline'}{/capture}
{assign var='__messageFormSettingsInlineContent' value=$__messageFormSettingsInlineContent|trim}
-<div class="messageTabMenu"{if $preselectTabMenu|isset} data-preselect="{$preselectTabMenu}"{/if} data-wysiwyg-container-id="{$wysiwygSelector}">
+<div class="messageTabMenu" {if $preselectTabMenu|isset} data-preselect="{$preselectTabMenu}" {/if}
+ data-wysiwyg-container-id="{$wysiwygSelector}">
<nav class="messageTabMenuNavigation jsOnly">
<ul>
- {if MODULE_SMILEY && !$smileyCategories|empty}<li data-name="smilies"><button type="button">{icon name='face-smile'} <span>{lang}wcf.message.smilies{/lang}</span></button></li>{/if}
+ {if MODULE_SMILEY && !$smileyCategories|empty}
+ <li data-name="smilies">
+ <button type="button">
+ {icon name='face-smile'}
+ <span>{lang}wcf.message.smilies{/lang}</span>
+ </button>
+ </li>
+ {/if}
{if !$attachmentHandler|empty && $attachmentHandler->canUpload()}
- <li data-name="attachments"><button type="button">{icon name='paperclip'} <span>{lang}wcf.attachment.attachments{/lang}</span></button></li>
+ <li data-name="attachments">
+ <button type="button">
+ {icon name='paperclip'}
+ <span>{lang}wcf.attachment.attachments{/lang}</span>
+ {if $attachmentHandler->count() > 0}
+ <span class="badge badgeUpdate">{#$attachmentHandler->count()}</span>
+ {/if}
+ </button>
+ </li>
+ {/if}
+ {if $__messageFormSettingsInlineContent}
+ <li data-name="settings"><button type="button">
+ {icon name='gear'}
+ <span>{lang}wcf.message.settings{/lang}</span>
+ </button>
+ </li>
+ {/if}
+ {if $__showPoll|isset && $__showPoll}
+ <li data-name="poll">
+ <button type="button">
+ {icon name='chart-bar'}
+ <span>{lang}wcf.poll.management{/lang}</span>
+ </button>
+ </li>
{/if}
- {if $__messageFormSettingsInlineContent}<li data-name="settings"><button type="button">{icon name='gear'} <span>{lang}wcf.message.settings{/lang}</span></button></li>{/if}
- {if $__showPoll|isset && $__showPoll}<li data-name="poll"><button type="button">{icon name='chart-bar'} <span>{lang}wcf.poll.management{/lang}</span></button></li>{/if}
{event name='tabMenuTabs'}
</ul>
</nav>
-
+
{if MODULE_SMILEY && !$smileyCategories|empty}{include file='shared_messageFormSmileyTab'}{/if}
{if !$attachmentHandler|empty && $attachmentHandler->canUpload()}
{include file='shared_messageFormAttachments'}
{/if}
-
+
{if $__messageFormSettingsInlineContent}{@$__messageFormSettingsInlineContent}{/if}
-
+
{include file='__messageFormPollInline'}
-
+
{event name='tabMenuContents'}
-</div>
+</div>
\ No newline at end of file
throw new Error(`The attachments container for '${editorId}' does not exist.`);
}
+ const tabMenu = getTabMenu(editorId);
+ if (tabMenu === undefined) {
+ throw new Error("Unable to find the corresponding tab menu.");
+ }
+
const editor = document.getElementById(editorId);
if (editor === null) {
throw new Error(`The editor element for '${editorId}' does not exist.`);
existingFiles.remove();
}
+
+ const files = fileList.getElementsByTagName("woltlab-core-file");
+ const observer = new MutationObserver(() => {
+ let counter = 0;
+ for (const file of files) {
+ if (!file.isFailedUpload()) {
+ counter++;
+ }
+ }
+
+ tabMenu.setTabCounter("attachments", counter);
+ });
+ observer.observe(fileList, {
+ childList: true,
+ subtree: true,
+ });
}
this.#activeTabName = tabName;
}
+ setTabCounter(tabName: string, value: number): void {
+ const tab = this.#tabs.find((element) => element.dataset.name === tabName);
+ if (tab === undefined) {
+ throw new Error(`Unknown tab '${tabName}'.`);
+ }
+
+ let badgeUpdate = tab.querySelector(".badgeUpdate");
+ if (value === 0) {
+ badgeUpdate?.remove();
+
+ return;
+ }
+
+ if (badgeUpdate === null) {
+ badgeUpdate = document.createElement("span");
+ badgeUpdate.classList.add("badge", "badgeUpdate");
+ tab.querySelector("a, button")!.append(badgeUpdate);
+ }
+
+ badgeUpdate.textContent = value.toString();
+ }
+
#init(): void {
for (let i = 0; i < this.#tabs.length; i++) {
const tab = this.#tabs[i];
}
export function getTabMenu(identifier: string): TabMenu | undefined {
+ setup();
+
return tabMenus.get(identifier);
}
+let initialized = false;
+
export function setup(): void {
+ if (initialized) {
+ return;
+ }
+
+ initialized = true;
+
wheneverFirstSeen(".messageTabMenu", (tabMenu) => initTabMenu(tabMenu));
}
if (container === null) {
throw new Error(`The attachments container for '${editorId}' does not exist.`);
}
+ const tabMenu = (0, MessageTabMenu_1.getTabMenu)(editorId);
+ if (tabMenu === undefined) {
+ throw new Error("Unable to find the corresponding tab menu.");
+ }
const editor = document.getElementById(editorId);
if (editor === null) {
throw new Error(`The editor element for '${editorId}' does not exist.`);
});
existingFiles.remove();
}
+ const files = fileList.getElementsByTagName("woltlab-core-file");
+ const observer = new MutationObserver(() => {
+ let counter = 0;
+ for (const file of files) {
+ if (!file.isFailedUpload()) {
+ counter++;
+ }
+ }
+ tabMenu.setTabCounter("attachments", counter);
+ });
+ observer.observe(fileList, {
+ childList: true,
+ subtree: true,
+ });
}
});
this.#tabContainers[tabIndex].classList.add("active");
this.#activeTabName = tabName;
}
+ setTabCounter(tabName, value) {
+ const tab = this.#tabs.find((element) => element.dataset.name === tabName);
+ if (tab === undefined) {
+ throw new Error(`Unknown tab '${tabName}'.`);
+ }
+ let badgeUpdate = tab.querySelector(".badgeUpdate");
+ if (value === 0) {
+ badgeUpdate?.remove();
+ return;
+ }
+ if (badgeUpdate === null) {
+ badgeUpdate = document.createElement("span");
+ badgeUpdate.classList.add("badge", "badgeUpdate");
+ tab.querySelector("a, button").append(badgeUpdate);
+ }
+ badgeUpdate.textContent = value.toString();
+ }
#init() {
for (let i = 0; i < this.#tabs.length; i++) {
const tab = this.#tabs[i];
}
}
function getTabMenu(identifier) {
+ setup();
return tabMenus.get(identifier);
}
+ let initialized = false;
function setup() {
+ if (initialized) {
+ return;
+ }
+ initialized = true;
(0, Selector_1.wheneverFirstSeen)(".messageTabMenu", (tabMenu) => initTabMenu(tabMenu));
}
});
> a,
> button {
+ align-items: center;
color: inherit;
- display: block;
+ /* 0.2em matches the width of a space */
+ column-gap: 0.2em;
+ display: flex;
padding: 10px 20px;
@include userSelectNone;
@include wcfFontDefault;
+ .badgeUpdate {
+ font-variant: tabular-nums;
+ margin-left: 0.3em;
+ }
+
@include screen-md-up {
> .icon {
display: none;
display: block;
}
- > span:not(.icon) {
+ > span:not(.badgeUpdate) {
display: none;
}
}