-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscripts.js
More file actions
179 lines (149 loc) · 5.75 KB
/
scripts.js
File metadata and controls
179 lines (149 loc) · 5.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// scripts.js
// Dark-only site. Handles proximity glow, clipboard copy with icon toggle, check icon pop,
// and neon grid mouse hotspot.
(function () {
"use strict";
// ===== Utilities =====
function raf(fn) { return window.requestAnimationFrame(fn); }
function copyToClipboard(text) {
if (navigator.clipboard && navigator.clipboard.writeText) {
return navigator.clipboard.writeText(text);
}
return new Promise(function (resolve, reject) {
try {
var ta = document.createElement("textarea");
ta.value = text;
ta.style.position = "fixed";
ta.style.left = "-9999px";
document.body.appendChild(ta);
ta.focus();
ta.select();
var ok = document.execCommand("copy");
document.body.removeChild(ta);
ok ? resolve() : reject(new Error("execCommand failed"));
} catch (err) { reject(err); }
});
}
function announce(msg) {
var live = document.getElementById("live");
if (!live) return;
live.textContent = "";
setTimeout(function () { live.textContent = msg; }, 10);
}
// Retrigger CSS animation on an element (always resets after end)
function playCheckPop(el) {
if (!el) return;
el.classList.remove("copy-check-pop");
void el.offsetWidth; // force reflow to restart
el.classList.add("copy-check-pop");
el.addEventListener("animationend", function handler() {
el.classList.remove("copy-check-pop");
el.removeEventListener("animationend", handler);
});
}
// Bind copy behavior to a container that has data-copy and two svg icons
function bindCopy(container, copiedText, announceMsg) {
if (!container) return;
var iconCopy = container.querySelector('[data-icon="copy"]');
var iconCheck = container.querySelector('[data-icon="check"]');
if (!iconCopy || !iconCheck) return;
// Overlap both icons and fade between them (no display:none)
var iconWrap = iconCopy.parentElement;
iconWrap.classList.add("icon-swap");
iconCopy.classList.remove("hidden");
iconCheck.classList.remove("hidden");
iconCopy.classList.add("is-visible");
iconCheck.classList.remove("is-visible");
var revertTimer = null;
function showCheck() {
iconCopy.classList.remove("is-visible");
iconCheck.classList.add("is-visible");
playCheckPop(iconCheck);
}
function showCopy() {
iconCheck.classList.remove("is-visible");
iconCopy.classList.add("is-visible");
requestAnimationFrame(function () { playCheckPop(iconCopy); });
}
function runCopy() {
copyToClipboard(copiedText).then(function () {
showCheck();
if (announceMsg) announce(announceMsg);
if (revertTimer) clearTimeout(revertTimer);
revertTimer = setTimeout(showCopy, 1200);
}).catch(function () { /* noop */ });
}
container.addEventListener("click", runCopy);
container.addEventListener("keypress", function (e) {
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); runCopy(); }
});
}
// ===== Proximity Glow for cards =====
function setupProximityGlow() {
var cards = Array.prototype.slice.call(document.querySelectorAll(".glow-card"));
if (!cards.length) return;
var rects = [];
var ticking = false;
function refreshRects() {
rects = cards.map(function (el) { return el.getBoundingClientRect(); });
}
function onMove(e) {
var mx = e.clientX, my = e.clientY;
if (ticking) return;
ticking = true;
raf(function () {
for (var i = 0; i < cards.length; i++) {
var el = cards[i], r = rects[i];
if (!r) continue;
var cx = Math.max(r.left, Math.min(mx, r.right));
var cy = Math.max(r.top, Math.min(my, r.bottom));
var dx = (mx < r.left) ? (r.left - mx) : (mx > r.right ? mx - r.right : 0);
var dy = (my < r.top) ? (r.top - my) : (my > r.bottom ? my - r.bottom : 0);
var dist = Math.hypot(dx, dy);
var thresholdAttr = parseFloat(el.getAttribute("data-glow-threshold"));
var threshold = isNaN(thresholdAttr) ? 220 : thresholdAttr;
var inside = (dx === 0 && dy === 0);
var t = inside ? 1 : Math.max(0, 1 - (dist / threshold));
var opacity = t > 0 ? (inside ? 0.9 : t * 0.75) : 0;
var alpha = t > 0 ? (inside ? 0.50 : t * 0.40) : 0;
var px = ((cx - r.left) / r.width) * 100;
var py = ((cy - r.top) / r.height) * 100;
el.style.setProperty("--glow-x", px.toFixed(2) + "%");
el.style.setProperty("--glow-y", py.toFixed(2) + "%");
el.style.setProperty("--glow-o", opacity.toFixed(3));
el.style.setProperty("--glow-a", alpha.toFixed(3));
}
ticking = false;
});
}
refreshRects();
window.addEventListener("mousemove", onMove, { passive: true });
window.addEventListener("resize", function () {
refreshRects();
}, { passive: true });
var scrollTick = false;
window.addEventListener("scroll", function () {
if (!scrollTick) {
scrollTick = true;
raf(function () {
refreshRects();
scrollTick = false;
});
}
}, { passive: true });
}
// ===== Init =====
document.addEventListener("DOMContentLoaded", function () {
setupProximityGlow();
var discordBtn = document.getElementById("discord-copy-btn");
if (discordBtn) {
var discordTag = discordBtn.getAttribute("data-copy") || "ThrowTop";
bindCopy(discordBtn, discordTag, "Discord copied.");
}
var backupCard = document.getElementById("backup-copy-card");
if (backupCard) {
var cmd = backupCard.getAttribute("data-copy") || "irm backup.throwtop.dev | iex";
bindCopy(backupCard, cmd, "Backup command copied.");
}
});
})();