Create preview avatar via DOM API instead of hidden template element.

Browsers do not render images inside display:none containers and
re-assigning src does not reliably trigger re-render. Store the
avatar URL in a data attribute and create the img element via
document.createElement after the container is already visible.
This commit is contained in:
russell@unturf.com 2026-02-08 06:00:08 -05:00
parent 3c4f5998f2
commit 14379cc364
2 changed files with 42 additions and 28 deletions

View file

@ -3,27 +3,41 @@
var previewTimer = null;
function updatePreviewAuthor(previewDiv) {
// Show the persistent .preview-author header when preview has content.
// For anonymous users, sync the displayed name from the input field.
// Show the preview-author header and build the avatar via DOM API.
// The avatar img is created dynamically (not in the template) because
// browsers skip rendering images inside display:none containers.
var author = previewDiv.querySelector('.preview-author');
if (!author) return;
var authorName = previewDiv.dataset.authorName;
if (!authorName) return;
// Show the header first.
author.style.display = '';
// Force avatar re-render: browsers skip images in display:none containers.
var img = author.querySelector('img');
if (img) {
var src = img.getAttribute('src');
img.removeAttribute('src');
img.setAttribute('src', src);
}
var form = previewDiv.closest('form');
if (form) {
var nameInput = form.querySelector('[name="anonymous_name"]');
if (nameInput) {
var name = nameInput.value.trim() || 'Anonymous';
var strong = author.querySelector('.preview-anon-name');
if (strong) strong.textContent = name;
// Set author name.
var strong = author.querySelector('.preview-anon-name');
if (strong) {
var form = previewDiv.closest('form');
if (form && previewDiv.dataset.authorAnon) {
var nameInput = form.querySelector('[name="anonymous_name"]');
var name = (nameInput && nameInput.value.trim()) || 'Anonymous';
strong.textContent = name;
} else {
strong.textContent = authorName;
}
}
// Create avatar img once, via DOM API on visible parent.
if (previewDiv.dataset.avatarSrc && !author.querySelector('img.avatar')) {
var img = document.createElement('img');
img.className = 'avatar nested-avatar';
img.align = 'left';
img.width = parseInt(previewDiv.dataset.avatarSize) || 35;
img.height = parseInt(previewDiv.dataset.avatarSize) || 35;
img.src = previewDiv.dataset.avatarSrc;
author.insertBefore(img, author.firstChild);
}
}
function previewAjax(textarea, div, show_raw, mathjax) {

View file

@ -28,20 +28,20 @@
<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 class="preview-author" style="display:none">
<div id='preview-{{ node.id }}' name='preview' class='preview js-only'
{% 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>
data-avatar-src="{{ request.user.avatar_uri(size=request.avatar_size) }}"
data-avatar-size="{{ request.avatar_size }}"
data-author-name="{{ request.user.name }}"
{% 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 %}
data-author-name="Anonymous"
data-author-anon="1"
{% endif %}>
<div class="preview-author" style="display:none">
<span class="author-and-date">
<strong class="preview-anon-name"></strong>
<span class="date">just now</span>
</span>
</div>
<div class="preview-content node-data"></div>
</div>