summaryrefslogtreecommitdiff
path: root/docs/_static
diff options
context:
space:
mode:
authorYuriy Andamasov <yuriy@vyos.io>2026-05-06 23:46:53 +0300
committerYuriy Andamasov <yuriy@vyos.io>2026-05-06 23:46:53 +0300
commit57e2d2be666f4daca0b19e4f7230d9130713a198 (patch)
tree1240493ad250c7f4db8e9173d73447a633571d5e /docs/_static
parentd1e5b5126af907215708fde817dcd309e579b725 (diff)
downloadvyos-documentation-57e2d2be666f4daca0b19e4f7230d9130713a198.tar.gz
vyos-documentation-57e2d2be666f4daca0b19e4f7230d9130713a198.zip
fix(codecopier): guard UI updates against out-of-order async completions
Rapid re-clicks queue multiple `navigator.clipboard.writeText` promises; without a request token, an older promise resolving later can overwrite the newer click's UI (or have its 2-second timeout fire on the new click's state). Add a per-button `copyRequestId` that each click increments and captures locally; the success/failure UI flip and the revert-timeout body all bail out early if the captured token no longer matches the current one. Addresses CodeRabbit review feedback on PR #1890. \xf0\x9f\xa4\x96 Generated by [robots](https://vyos.io)
Diffstat (limited to 'docs/_static')
-rw-r--r--docs/_static/js/codecopier.js13
1 files changed, 13 insertions, 0 deletions
diff --git a/docs/_static/js/codecopier.js b/docs/_static/js/codecopier.js
index 02143b92..4b0941c9 100644
--- a/docs/_static/js/codecopier.js
+++ b/docs/_static/js/codecopier.js
@@ -54,6 +54,16 @@ $(document).ready(async function () {
}) => {
const id = currentTarget.dataset.identifier
const divWithNeededId = $(`div[data-identifier='${id}']`)
+
+ // Per-click request token. Rapid re-clicks queue multiple writeText
+ // promises; without this guard, an older promise resolving later
+ // can overwrite the newer click's UI (or have its timeout fire on
+ // the new state). Each click increments the token, captures the
+ // local copy, and bails out of any UI/timeout work if the captured
+ // token no longer matches the current one.
+ const requestId = (divWithNeededId.data('copyRequestId') || 0) + 1
+ divWithNeededId.data('copyRequestId', requestId)
+
// Read from the .copyDiv's parentElement (the inner .highlight div it was
// injected into via insertAdjacentHTML('beforeend', ...)) rather than
// currentTarget.offsetParent — offsetParent depends on CSS positioning
@@ -75,17 +85,20 @@ $(document).ready(async function () {
try {
await navigator.clipboard.writeText(textToCopy)
+ if (divWithNeededId.data('copyRequestId') !== requestId) return
// Only flip the button into the success state when the write actually
// resolves — earlier versions showed "Copied!" even on failure.
divWithNeededId.addClass('copiedNotifier')
divWithNeededId.html('<span>Copied!</span>')
} catch (error) {
+ if (divWithNeededId.data('copyRequestId') !== requestId) return
console.error('Copying text failed, please try again', error)
divWithNeededId.addClass('copyFailedNotifier')
divWithNeededId.html('<span>Failed</span>')
}
const revertTimeout = setTimeout(() => {
+ if (divWithNeededId.data('copyRequestId') !== requestId) return
divWithNeededId.html(innersOfCopyDiv)
divWithNeededId.removeClass('copiedNotifier copyFailedNotifier')
divWithNeededId.removeData('revertTimeout')