120 lines
3.2 KiB
JavaScript
120 lines
3.2 KiB
JavaScript
// Single event listener that checks which button's data to use
|
|
document.addEventListener("copy", (event) => {
|
|
const activeButtonData = buttonDataMap.get("active");
|
|
if (activeButtonData) {
|
|
event.preventDefault();
|
|
event.clipboardData.setData(
|
|
"application/json",
|
|
JSON.stringify(activeButtonData)
|
|
);
|
|
event.clipboardData.setData(
|
|
"text/plain",
|
|
JSON.stringify(activeButtonData)
|
|
);
|
|
buttonDataMap.delete("active"); // Clear after copying
|
|
}
|
|
});
|
|
|
|
copybtn.forEach((btn) => {
|
|
const url = btn.getAttribute("data-copy");
|
|
const text = btn.children[0].children[0];
|
|
const icon = btn.querySelector("svg");
|
|
let isAnimating = false;
|
|
|
|
btn.onmouseenter = async () => {
|
|
if (isAnimating) return;
|
|
isAnimating = true;
|
|
|
|
await gsap.to(icon, {
|
|
rotate: "+=360",
|
|
duration: 0.3,
|
|
ease: "expo.out",
|
|
});
|
|
|
|
isAnimating = false;
|
|
};
|
|
|
|
btn.onclick = async (evt) => {
|
|
try {
|
|
const res = await fetch(url);
|
|
let data = await res.text();
|
|
|
|
// Try to parse as JSON in case it's JSON data
|
|
try {
|
|
const jsonData = JSON.parse(data);
|
|
buttonDataMap.set("active", jsonData);
|
|
} catch {
|
|
buttonDataMap.set("active", data);
|
|
}
|
|
|
|
// Trigger the copy command
|
|
document.execCommand("copy");
|
|
|
|
text.textContent = "Copied!";
|
|
console.log("copied successfully");
|
|
|
|
setTimeout(() => {
|
|
text.textContent = "Copy this";
|
|
}, 1000);
|
|
} catch (error) {
|
|
console.error("Failed to copy:", error);
|
|
text.textContent = "Failed to copy";
|
|
|
|
setTimeout(() => {
|
|
text.textContent = "Copy this";
|
|
}, 1000);
|
|
}
|
|
};
|
|
});
|
|
};
|
|
|
|
/** -- Split Text Button */
|
|
const split = (text, type = "chars") => {
|
|
text.setAttribute("aria-label", text.textContent);
|
|
const splits = new SplitText(text, { type });
|
|
splits[type].forEach((char) => char.setAttribute("aria-hidden", "true"));
|
|
return splits[type];
|
|
};
|
|
|
|
const buttons = () => {
|
|
const buttons = [...document.querySelectorAll("[data-module='btn']")];
|
|
|
|
buttons.forEach((btn) => {
|
|
const overflow = btn.children[0];
|
|
const text = overflow.children[0];
|
|
|
|
overflow.appendChild(text.cloneNode(true));
|
|
const splitText1 = split(overflow.children[0], "chars");
|
|
const splitText2 = split(overflow.children[1], "chars");
|
|
|
|
const animation = {
|
|
yPercent: "-=100",
|
|
duration: 0.8,
|
|
ease: "expo.out",
|
|
stagger: 0.02,
|
|
};
|
|
|
|
btn.onmouseenter = () => {
|
|
gsap.to(splitText1, { ...animation, yPercent: -100 });
|
|
gsap.to(splitText2, { ...animation, yPercent: -100 });
|
|
};
|
|
|
|
btn.onmouseleave = () => {
|
|
gsap.to(splitText1, { ...animation, yPercent: 0 });
|
|
gsap.to(splitText2, { ...animation, yPercent: 0 });
|
|
};
|
|
});
|
|
};
|
|
|
|
/** -- Controller */
|
|
addEventListener("GSAPReady", (event) => {
|
|
copybtn();
|
|
|
|
// desktop only animations
|
|
if (window.matchMedia("(min-width: 1024px)").matches) {
|
|
buttons();
|
|
}
|
|
});
|
|
}
|
|
|
|
</div> |