83 lines
3.2 KiB
JavaScript
83 lines
3.2 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* This creates a button that can be used to copy text to the clipboard.
|
|
* Whenever the button is pressed the getCopyContentsFn passed into the
|
|
* constructor is called and the resulting text is copied. It uses CSS
|
|
* transitions to perform a short animation.
|
|
*/
|
|
class CopyButton {
|
|
constructor(getCopyContentsFn) {
|
|
const button = document.createElement("span");
|
|
button.textContent = String.fromCodePoint(0x1f4cb);
|
|
button.classList.add("copy-button", "copy-button-base");
|
|
button.onclick = () => {
|
|
if (!button.classList.contains("copy-button")) {
|
|
return;
|
|
}
|
|
|
|
const handleAnimation = async () => {
|
|
const switchFadeDirection = () => {
|
|
if (button.classList.contains("copy-button-fade-out")) {
|
|
// We just faded out so let's fade in
|
|
button.classList.toggle("copy-button-fade-out");
|
|
button.classList.toggle("copy-button-fade-in");
|
|
} else {
|
|
// We just faded in so let's fade out
|
|
button.classList.toggle("copy-button-fade-out");
|
|
button.classList.toggle("copy-button-fade-in");
|
|
}
|
|
};
|
|
|
|
// Fade out clipboard icon
|
|
// Fade out the clipboard character
|
|
button.classList.toggle("copy-button-fade-out");
|
|
// Wait for CSS transition to end
|
|
await new Promise(r => (button.ontransitionend = r));
|
|
|
|
// Fade in checkmark icon
|
|
// This is the start of fade in.
|
|
// Switch to the checkmark character
|
|
button.textContent = String.fromCodePoint(0x2705);
|
|
// Trigger CSS fade in transition
|
|
switchFadeDirection();
|
|
// Wait for CSS transition to end
|
|
await new Promise(r => (button.ontransitionend = r));
|
|
|
|
// Fade out clipboard icon
|
|
// Trigger CSS fade out transition
|
|
switchFadeDirection();
|
|
// Wait for CSS transition to end
|
|
await new Promise(r => (button.ontransitionend = r));
|
|
|
|
// Fade in clipboard icon
|
|
// This is the start of fade in.
|
|
// Switch to the clipboard character
|
|
button.textContent = String.fromCodePoint(0x1f4cb);
|
|
// Trigger CSS fade in transition
|
|
switchFadeDirection();
|
|
// Wait for CSS transition to end
|
|
await new Promise(r => (button.ontransitionend = r));
|
|
|
|
// Remove fade
|
|
button.classList.toggle("copy-button-fade-in");
|
|
// Re-enable clicks and hidding when parent div has lost :hover
|
|
button.classList.add("copy-button");
|
|
};
|
|
|
|
// Note the fade effect is handled in the CSS, we just need to swap
|
|
// between the different CSS classes. This returns a promise that waits
|
|
// for the current fade to end, starts the next fade, then resolves.
|
|
|
|
navigator.clipboard.writeText(getCopyContentsFn());
|
|
// Prevent animation from disappearing when parent div losses :hover,
|
|
// and prevent additional clicks until the animation finishes.
|
|
button.classList.remove("copy-button");
|
|
handleAnimation(); // runs unawaited
|
|
};
|
|
this.element = button;
|
|
}
|
|
}
|
|
export { CopyButton };
|