perf(comments): lazy-render top-level reply forms
The reply form used to render ~13 lines of hidden markup under every
top-level comment, so a 50-comment video shipped roughly 650 lines of
inert DOM to every signed-in viewer. Replaced with a single
<template id="ytc-reply-form-tpl"> plus a per-comment slot div; the
first click on Reply clones the template, wires the IDs
(replyForm{id}, replyBody{id}, data-parent-id, data-video-id) and
appends it, so toggle behavior stays identical from the user's side.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
1 parent
8fdac4b483
commit
8aa08e705a
1 file changed
+46
-16
@@ -156,20 +156,12 @@
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Reply form --}}
|
||||
{{-- Reply form is lazy-cloned from #ytc-reply-form-tpl on
|
||||
first click; the ~13-line markup used to render for
|
||||
every top-level comment (so a 50-comment video shipped
|
||||
~650 lines of hidden form markup to every viewer). --}}
|
||||
@auth
|
||||
<div class="ytc-reply-form" id="replyForm{{ $comment->id }}">
|
||||
<img src="{{ Auth::user()->avatar_url }}" class="ytc-avatar ytc-avatar-sm" alt="{{ Auth::user()->name }}">
|
||||
<div class="ytc-input-wrap">
|
||||
<textarea class="ytc-textarea ytc-reply-textarea" id="replyBody{{ $comment->id }}"
|
||||
placeholder="Add a reply..." rows="1"></textarea>
|
||||
<div class="ytc-form-actions">
|
||||
<button class="ytc-btn ytc-btn-cancel _comment-cancel-reply-trigger" data-comment-id="{{ $comment->id }}">Cancel</button>
|
||||
<button class="ytc-btn ytc-btn-submit _comment-submit-reply-trigger"
|
||||
data-video-id="{{ $video->getRouteKey() }}" data-parent-id="{{ $comment->id }}">Reply</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ytc-reply-slot" data-comment-id="{{ $comment->id }}" data-video-id="{{ $video->getRouteKey() }}"></div>
|
||||
@endauth
|
||||
|
||||
{{-- Replies --}}
|
||||
@@ -1062,10 +1054,29 @@ async function toggleTranslate(btn) {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Reply form ────────────────────────────────────────
|
||||
// ── Reply form (lazy-rendered from a <template>) ──────
|
||||
// Replaces the per-comment inline markup that used to live in the DOM
|
||||
// pre-hidden. First click on "Reply" clones the template into the comment's
|
||||
// .ytc-reply-slot and wires its IDs. Subsequent toggles just show/hide.
|
||||
function toggleReplyForm(commentId) {
|
||||
const form = document.getElementById('replyForm' + commentId);
|
||||
if (!form) return;
|
||||
let form = document.getElementById('replyForm' + commentId);
|
||||
if (!form) {
|
||||
const slot = document.querySelector('.ytc-reply-slot[data-comment-id="' + commentId + '"]');
|
||||
const tpl = document.getElementById('ytc-reply-form-tpl');
|
||||
if (!slot || !tpl) return;
|
||||
const frag = tpl.content.cloneNode(true);
|
||||
const root = frag.querySelector('.ytc-reply-form');
|
||||
const ta = frag.querySelector('.ytc-reply-textarea');
|
||||
const cancel = frag.querySelector('._comment-cancel-reply-trigger');
|
||||
const submit = frag.querySelector('._comment-submit-reply-trigger');
|
||||
root.id = 'replyForm' + commentId;
|
||||
ta.id = 'replyBody' + commentId;
|
||||
cancel.dataset.commentId = commentId;
|
||||
submit.dataset.parentId = commentId;
|
||||
submit.dataset.videoId = slot.dataset.videoId || YTC.videoId;
|
||||
slot.appendChild(frag);
|
||||
form = root;
|
||||
}
|
||||
const isOpen = form.classList.contains('open');
|
||||
document.querySelectorAll('.ytc-reply-form.open').forEach(f => f.classList.remove('open'));
|
||||
if (!isOpen) {
|
||||
@@ -1513,3 +1524,22 @@ window._comment = {
|
||||
|
||||
})();
|
||||
</script>
|
||||
|
||||
@auth
|
||||
{{-- Reply-form template. Cloned into .ytc-reply-slot the first time a user
|
||||
clicks Reply on a given comment. Keeping it here (not in the layout)
|
||||
means the markup travels with the comments component — the only place
|
||||
that uses it. --}}
|
||||
<template id="ytc-reply-form-tpl">
|
||||
<div class="ytc-reply-form">
|
||||
<img src="{{ Auth::user()->avatar_url }}" class="ytc-avatar ytc-avatar-sm" alt="{{ Auth::user()->name }}">
|
||||
<div class="ytc-input-wrap">
|
||||
<textarea class="ytc-textarea ytc-reply-textarea" placeholder="Add a reply..." rows="1"></textarea>
|
||||
<div class="ytc-form-actions">
|
||||
<button class="ytc-btn ytc-btn-cancel _comment-cancel-reply-trigger">Cancel</button>
|
||||
<button class="ytc-btn ytc-btn-submit _comment-submit-reply-trigger">Reply</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@endauth
|
||||
Reference in new issue
Block a user