Skip to content

Commit 6d9140d

Browse files
committed
updated the contact button
1 parent b0f5f6c commit 6d9140d

2 files changed

Lines changed: 63 additions & 29 deletions

File tree

_config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ title: Mo Shakiba
22

33
about_content: |
44
**<sub>[CV](https://moneuron.github.io/assets/data/drive/cv.pdf) ·
5-
[CONTACT](#)</sub>**
5+
[CONTACT](#contact)</sub>**
66
77
papers: |
88
> I’m **Mo**, a NeuroAI researcher.

assets/script.js

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -104,22 +104,29 @@ document.addEventListener("DOMContentLoaded", () => {
104104
alternate: 'HOME'
105105
};
106106

107+
const CONTACT_HASH = '#contact';
108+
107109
// --- Selectors ---
108-
const toggleBtn = document.querySelector('sub a[href="#"]');
110+
const toggleBtn = document.querySelector('sub a[href="#contact"]');
109111
const mainBlockquote = document.querySelector('blockquote');
110112
const paperItems = document.querySelectorAll('.paper-item');
111113
const footer = document.querySelector('footer');
112114

115+
// If there's no CONTACT link (or markup changed), skip the contact-view feature.
116+
if (!toggleBtn) {
117+
return;
118+
}
119+
113120
// --- Inject CSS class for hiding elements ---
114121
const style = document.createElement('style');
115122
style.textContent = `.hidden-view { display: none !important; }`;
116123
document.head.appendChild(style);
117124

118125
function escapeHtml(str) {
119-
const div = document.createElement('div');
120-
div.textContent = str;
121-
return div.innerHTML;
122-
}
126+
const div = document.createElement('div');
127+
div.textContent = str;
128+
return div.innerHTML;
129+
}
123130

124131
// --- Build email block from data ---
125132
function createEmailBlockquote({ active, inactive, error = false }) {
@@ -183,15 +190,20 @@ document.addEventListener("DOMContentLoaded", () => {
183190
return emailBlockquote;
184191
}
185192

186-
// --- Toggle view handler ---
187-
async function toggleView(event) {
188-
event.preventDefault();
193+
function isContactViewFromHash() {
194+
return window.location.hash.toLowerCase() === CONTACT_HASH;
195+
}
196+
197+
function setHidden(el, hidden) {
198+
if (!el) return;
199+
el.classList.toggle('hidden-view', hidden);
200+
}
201+
202+
function startEmailFetchIfNeeded() {
203+
if (emailDataPromise) return;
204+
205+
toggleBtn.textContent = '...';
189206

190-
// If we're about to show emails and haven't loaded them yet, fetch now
191-
if (!showingEmails && !emailDataPromise) {
192-
// Show a temporary loading state (optional)
193-
toggleBtn.textContent = '...';
194-
195207
const timeout = new Promise((_, reject) =>
196208
setTimeout(() => reject(new Error('Request timed out')), 3000)
197209
);
@@ -202,32 +214,54 @@ document.addEventListener("DOMContentLoaded", () => {
202214
return response.json();
203215
}),
204216
timeout
205-
])
206-
.catch(error => {
217+
]).catch(error => {
207218
console.error('Could not load emails:', error);
208219
return { active: [], inactive: [], error: true };
209220
});
210-
}
221+
}
211222

212-
// Wait for the data if we're opening the view for the first time
213-
if (!showingEmails && emailDataPromise) {
223+
let viewSyncId = 0;
224+
225+
async function syncContactViewFromHash() {
226+
const syncId = ++viewSyncId;
227+
const shouldShowEmails = isContactViewFromHash();
228+
229+
if (shouldShowEmails) {
230+
startEmailFetchIfNeeded();
214231
const emailData = await emailDataPromise;
215232
insertEmailBlock(emailData);
216233
}
217234

218-
// Toggle visibility
219-
if (emailBlockquote) {
220-
emailBlockquote.classList.toggle('hidden-view');
221-
}
222-
elementsToToggle.forEach(el => el.classList.toggle('hidden-view'));
235+
// If another hash change happened while we were awaiting, ignore this pass.
236+
if (syncId !== viewSyncId) return;
237+
238+
// Apply visibility deterministically (avoid toggle drift)
239+
elementsToToggle.forEach(el => setHidden(el, shouldShowEmails));
240+
setHidden(emailBlockquote, !shouldShowEmails);
241+
242+
toggleBtn.textContent = shouldShowEmails ? toggleText.alternate : toggleText.default;
243+
showingEmails = shouldShowEmails;
244+
}
223245

224-
// Update button text
225-
toggleBtn.textContent = showingEmails ? toggleText.default : toggleText.alternate;
246+
// --- Click handler: drives state via URL hash ---
247+
function onToggleClick(event) {
248+
event.preventDefault();
226249

227-
// Flip state
228-
showingEmails = !showingEmails;
250+
if (isContactViewFromHash()) {
251+
window.location.hash = '';
252+
} else {
253+
window.location.hash = CONTACT_HASH;
254+
}
229255
}
230256

257+
// Keep the view in sync with back/forward and direct links.
258+
window.addEventListener('hashchange', () => {
259+
syncContactViewFromHash();
260+
});
261+
262+
// Initial sync (supports landing on /#contact)
263+
syncContactViewFromHash();
264+
231265
// --- Attach event listener ---
232-
toggleBtn.addEventListener('click', toggleView);
266+
toggleBtn.addEventListener('click', onToggleClick);
233267
});

0 commit comments

Comments
 (0)