Skip to content

Instantly share code, notes, and snippets.

@CamKem
Created July 13, 2024 12:01
Show Gist options
  • Save CamKem/042ca4cbac70bf3c7f6ecada5a792b33 to your computer and use it in GitHub Desktop.
Save CamKem/042ca4cbac70bf3c7f6ecada5a792b33 to your computer and use it in GitHub Desktop.
playing around
const copyCode = () => ({
codeElements: [],
init() {
this.codeElements = this.$el.querySelectorAll('code');
this.addCopyButtons();
this.mutate();
},
mutate() {
// mutation observer to reinit buttons when new code elements are added
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
// if this.el is the target, reinit buttons
if (mutation.target === this.$el) {
this.reinitButtons();
}
});
})
observer.observe(this.$el, { childList: true, subtree: true });
},
copyToClipboard(item) {
this.$clipboard(item)
this.$notify('Copied to clipboard.', {
wrapperId: 'flashMessageWrapper',
templateId: 'flashMessageTemplate',
autoClose: 3000,
autoRemove: 4000
})
},
reinitButtons() {
this.codeElements = this.$el.querySelectorAll('code');
this.addCopyButtons();
},
addCopyButtons() {
const copyIconOutline = new DOMParser().parseFromString(
`<svg xmlns="http://www.w3.org/2000/svg" class="size-5" viewBox="0 0 24 24" fill="currentColor" fill-opacity="50%"><path d="M20 2H10c-1.103 0-2 .897-2 2v4H4c-1.103 0-2 .897-2 2v10c0 1.103.897 2 2 2h10c1.103 0 2-.897 2-2v-4h4c1.103 0 2-.897 2-2V4c0-1.103-.897-2-2-2zM4 20V10h10l.002 10H4zm16-6h-4v-4c0-1.103-.897-2-2-2h-4V4h10v10z"></path><path d="M6 12h6v2H6zm0 4h6v2H6z"></path></svg>`
, 'image/svg+xml').documentElement;
const copyIconSolid = new DOMParser().parseFromString(
`<svg xmlns="http://www.w3.org/2000/svg" class="size-5" viewBox="0 0 24 24" fill="currentColor" fill-opacity="50%"><path d="M20 2H10a2 2 0 0 0-2 2v2h8a2 2 0 0 1 2 2v8h2a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z"></path><path d="M4 22h10c1.103 0 2-.897 2-2V10c0-1.103-.897-2-2-2H4c-1.103 0-2 .897-2 2v10c0 1.103.897 2 2 2zm2-10h6v2H6v-2zm0 4h6v2H6v-2z"></path></svg>`
, 'image/svg+xml').documentElement;
const toggleIcon = (button) => {
if (button.contains(copyIconOutline)) {
button.removeChild(copyIconOutline);
button.appendChild(copyIconSolid);
} else if (button.contains(copyIconSolid)) {
button.removeChild(copyIconSolid);
button.appendChild(copyIconOutline);
} else {
button.appendChild(copyIconOutline);
}
}
const positionButton = (button, el) => {
const rect = el.getBoundingClientRect();
const m = 8;
button.style.position = 'sticky';
button.style.left = `${rect.width - button.offsetWidth - (m * 2)}px`;
button.style.top = `-${m * 5}px`;
button.style.bottom = `100%`;
button.style.margin = `-${m}px`;
}
this.codeElements.forEach((codeElement) => {
codeElement.classList.add('group/code');
const button = document.createElement('button');
const setupButton = () => {
// to make it appear on hover
button.classList.add(
'opacity-0',
'group-hover/code:opacity-100',
'text-xs',
'text-pink-400',
'cursor-pointer',
'focus:outline-none',
'transition-colors',
'hover:text-white',
'z-10',
'p-1',
'rounded-md',
'bg-pink-900',
'bg-opacity-50',
'transition-opacity',
'duration-200',
);
button.title = 'Copy';
button.setAttribute(
'data-navigate-ignore',
'true'
);
toggleIcon(button);
positionButton(button, codeElement);
}
this.$nextTick(() => {
setupButton();
});
window.addEventListener(
'resize',
positionButton.bind(null, button, codeElement)
);
button.addEventListener('click', () => {
this.copyToClipboard(codeElement.innerText);
toggleIcon(button);
positionButton(button, codeElement);
setTimeout(() => {
toggleIcon(button);
positionButton(button, codeElement);
}, 1000);
});
codeElement.appendChild(button);
});
}
});
export {copyCode}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment