/** * copy-code.js - Copy to Clipboard for Code Snippets * * For The Building Coder Archive * Adds copy buttons to all
code blocks
*/
(function() {
'use strict';
// Wait for DOM to be ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initCopyButtons);
} else {
initCopyButtons();
}
function initCopyButtons() {
// Find all elements
const codeBlocks = document.querySelectorAll('pre');
codeBlocks.forEach(function(pre) {
// Skip if already has a copy button
if (pre.querySelector('.tbc-copy-btn')) return;
// Create wrapper div for positioning
const wrapper = document.createElement('div');
wrapper.className = 'tbc-code-wrapper';
// Insert wrapper before pre, then move pre into wrapper
pre.parentNode.insertBefore(wrapper, pre);
wrapper.appendChild(pre);
// Create copy button
const copyBtn = document.createElement('button');
copyBtn.className = 'tbc-copy-btn';
copyBtn.setAttribute('aria-label', 'Copy code to clipboard');
copyBtn.setAttribute('title', 'Copy to clipboard');
copyBtn.innerHTML = '';
// Add click handler
copyBtn.addEventListener('click', function() {
copyToClipboard(pre, copyBtn);
});
// Insert button into wrapper
wrapper.appendChild(copyBtn);
});
}
function copyToClipboard(pre, btn) {
// Get text content, stripping any HTML
const text = pre.textContent || pre.innerText;
// Use modern clipboard API if available
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(function() {
showCopiedFeedback(btn);
}).catch(function(err) {
console.error('Failed to copy:', err);
fallbackCopy(text, btn);
});
} else {
fallbackCopy(text, btn);
}
}
function fallbackCopy(text, btn) {
// Fallback for older browsers
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
textarea.style.top = '0';
document.body.appendChild(textarea);
textarea.focus();
textarea.select();
try {
document.execCommand('copy');
showCopiedFeedback(btn);
} catch (err) {
console.error('Fallback copy failed:', err);
}
document.body.removeChild(textarea);
}
function showCopiedFeedback(btn) {
// Change icon to checkmark
const originalHTML = btn.innerHTML;
btn.innerHTML = '';
btn.classList.add('tbc-copy-success');
// Reset after delay
setTimeout(function() {
btn.innerHTML = originalHTML;
btn.classList.remove('tbc-copy-success');
}, 2000);
}
})();