-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
128 lines (112 loc) · 4.13 KB
/
Copy pathscript.js
File metadata and controls
128 lines (112 loc) · 4.13 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
// Theme toggle
const root = document.documentElement;
const toggle = document.getElementById('theme-toggle');
const saved = localStorage.getItem('theme') || 'light';
root.setAttribute('data-theme', saved);
// Move knob based on theme (CSS also handles this, but keeping initial nudge)
if (saved === 'dark') toggle.querySelector('.knob').style.transform = 'translateX(20px)';
// --- NEW: keep the moon/sun icon in sync with theme ---
const moon = document.querySelector('.moon-icon');
function updateThemeUI() {
const isDark = root.getAttribute('data-theme') === 'dark';
if (!moon) return;
// Swap moon/sun
moon.classList.toggle('fa-moon', !isDark);
moon.classList.toggle('fa-sun', isDark);
// Update title / aria
const label = isDark ? 'Switch to light mode' : 'Switch to dark mode';
moon.title = label;
moon.setAttribute('aria-label', label);
}
updateThemeUI(); // run once on load
toggle.addEventListener('click', () => {
const next = root.getAttribute('data-theme') === 'light' ? 'dark' : 'light';
root.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
updateThemeUI();
});
// Typed line
document.addEventListener('DOMContentLoaded', () => {
new Typed('#typed-text', {
strings: ['PhD Student', 'LLM & dLLM Researcher', 'Teaching Staff', 'Research Assistant'],
typeSpeed: 38,
backSpeed: 18,
backDelay: 1600, // pause a bit longer
loop: true,
smartBackspace: true,
});
});
// Moon/Sun icon also toggles theme
if (moon){
moon.addEventListener('click', () => {
const isDark = root.getAttribute('data-theme') === 'dark';
const next = isDark ? 'light' : 'dark';
root.setAttribute('data-theme', next);
try{ localStorage.setItem('theme', next); }catch(_){}
updateThemeUI();
});
}
try{
const again = localStorage.getItem('theme');
if(again) document.documentElement.setAttribute('data-theme', again);
updateThemeUI();
}catch(_){}
// Interactive background (About) with tsParticles
(async () => {
const dark = () => getComputedStyle(document.documentElement).getPropertyValue('--bg').trim() !== '#f6f7fb';
const colors = () => ({
links: getComputedStyle(document.documentElement).getPropertyValue('--accent-2').trim(),
dots: getComputedStyle(document.documentElement).getPropertyValue('--accent').trim()
});
const loadParticles = async () => {
const c = colors();
await tsParticles.load({
id: 'about-bg',
options: {
fullScreen: { enable: false },
background: { color: { value: 'transparent' } },
particles: {
number: { value: 55, density: { enable: true, area: 800 } },
color: { value: c.dots },
links: { enable: true, distance: 110, color: c.links, opacity: 0.45, width: 1 },
move: { enable: true, speed: 1.0, outModes: { default: 'bounce' } },
size: { value: { min: 1, max: 4 } },
opacity: { value: { min: 0.35, max: 0.8 } }
},
detectRetina: true
}
});
};
await loadParticles();
// Update particles when theme changes
const mo = new MutationObserver(loadParticles);
mo.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
})().catch(() => {
// graceful fallback
});
// Modal for abstracts
const modal = document.getElementById('modal');
const modalTitle = document.getElementById('modal-title');
const modalBody = document.getElementById('modal-body');
const openModal = (title, body) => {
modalTitle.textContent = title || "";
modalBody.textContent = body || "";
modal.classList.add('show');
modal.setAttribute('aria-hidden', 'false');
};
const closeModal = () => {
modal.classList.remove('show');
modal.setAttribute('aria-hidden', 'true');
};
document.addEventListener('click', (e) => {
const openBtn = e.target.closest('.open-abs');
if (openBtn) {
openModal(openBtn.dataset.title, openBtn.dataset.abstract);
}
if (e.target.matches('[data-close]')) closeModal();
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && modal.classList.contains('show')) closeModal();
});
// Year
document.getElementById('year').textContent = new Date().getFullYear();