Use server-rendered template for preview avatar and author header.

Replace data-attribute approach with a <template> element inside the
reply form. The server renders the avatar img and author name once;
JS clones the HTML for each preview update. This fixes the missing
avatar in the live preview and handles anonymous name updates.
This commit is contained in:
russell@unturf.com 2026-02-07 19:29:53 -05:00
parent 56163ffda3
commit 18cd870956
2 changed files with 32 additions and 30 deletions

View file

@ -60,34 +60,26 @@ function isReplyForm(form) {
function wrapPreviewAsNode(html, form) {
// Wrap preview HTML in node-like markup so it looks like a live comment.
var name = '';
var avatarHtml = '';
// Uses server-rendered <template> for the avatar + author header.
var template = form.querySelector('.preview-header-template');
if (!template || !template.innerHTML.trim()) return html;
if (form.hasAttribute('data-author-name')) {
// Authenticated user.
name = form.getAttribute('data-author-name');
var avatarSrc = form.getAttribute('data-author-avatar');
if (avatarSrc) {
avatarHtml = '<img src="' + avatarSrc + '" class="avatar nested-avatar" align="left" />';
}
} else {
// Anonymous user — read name from input.
var nameInput = form.querySelector('[name="anonymous_name"]');
if (nameInput && nameInput.value.trim()) {
name = nameInput.value.trim();
} else {
name = 'Anonymous';
var headerHtml = template.innerHTML;
// For anonymous users, update name from the input field.
var nameInput = form.querySelector('[name="anonymous_name"]');
if (nameInput) {
var name = nameInput.value.trim() || 'Anonymous';
var anonEl = template.content.querySelector('.preview-anon-name');
if (anonEl) {
headerHtml = headerHtml.replace(
'>' + anonEl.textContent + '<',
'>' + escapeHtml(name) + '<'
);
}
}
if (!name) return html;
return avatarHtml
+ '<span class="author-and-date">'
+ '<strong>' + escapeHtml(name) + '</strong> '
+ '<span class="date">just now</span>'
+ '</span>'
+ '<div class="node-data">' + html + '</div>';
return headerHtml + '<div class="node-data">' + html + '</div>';
}
// CSS-based toggle for smoother animations.

View file

@ -5,12 +5,7 @@
<p>This thread was locked to prevent additional comments.</p>
{% else %}
<form method="post" action="{{ request.link_prefix }}/{{ node.id }}/reply"
{% if request.user and request.user.authenticated %}
data-author-name="{{ request.user.name }}"
data-author-avatar="{{ request.user.avatar_uri(size=request.avatar_size) }}"
{% endif %}
onsubmit="submit.disabled = true; return true;">
<form method="post" action="{{ request.link_prefix }}/{{ node.id }}/reply" onsubmit="submit.disabled = true; return true;">
{# the first if statement gaurds the 2nd and is an optimization #}
{% if node.id == request.node.id %}
@ -31,6 +26,21 @@
{% set submit_button_value = request.namespace.submit_button_text or 'save message' %}
{% include 'submit.j2' %}
<template class="preview-header-template">
{% if request.user and request.user.authenticated %}
<img src="{{ request.user.avatar_uri(size=request.avatar_size) }}" class="avatar nested-avatar" align="left" />
<span class="author-and-date">
<strong>{{ request.user.name }}</strong>
<span class="date">just now</span>
</span>
{% elif request.namespace.allow_anonymous %}
<span class="author-and-date">
<strong class="preview-anon-name">Anonymous</strong>
<span class="date">just now</span>
</span>
{% endif %}
</template>
<details class="preview-details js-only" open>
<summary class="action link preview-toggle"><span class="when-open">hide preview ▲</span><span class="when-closed">show preview ▼</span></summary>
<div id='preview-{{ node.id }}' name='preview' class='preview js-only'></div>