-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.min.js
More file actions
123 lines (110 loc) · 4.37 KB
/
Copy pathscript.min.js
File metadata and controls
123 lines (110 loc) · 4.37 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
/* script.js — development version (readable)
Handles mobile nav, smooth scroll, active link highlighting, and contact form submission to serverless endpoints.
*/
document.addEventListener('DOMContentLoaded', function () {
const navToggle = document.getElementById('navToggle');
const navList = document.querySelector('.nav-list');
const navLinks = document.querySelectorAll('.nav-link');
const themeToggle = document.getElementById('themeToggle');
// Theme toggle functionality
const currentTheme = localStorage.getItem('theme') || 'dark';
document.documentElement.setAttribute('data-theme', currentTheme);
updateThemeIcon(currentTheme);
themeToggle.addEventListener('click', function () {
const currentTheme = document.documentElement.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
updateThemeIcon(newTheme);
});
function updateThemeIcon(theme) {
const icon = themeToggle.querySelector('i');
if (theme === 'light') {
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
} else {
icon.classList.remove('fa-sun');
icon.classList.add('fa-moon');
}
}
// Mobile nav toggle
navToggle.addEventListener('click', function () {
const isOpen = navList.classList.toggle('open');
navToggle.classList.toggle('open', isOpen);
navToggle.setAttribute('aria-expanded', isOpen);
});
// Close menu when clicking a nav link (mobile)
navLinks.forEach(link => {
link.addEventListener('click', function () {
navList.classList.remove('open');
navToggle.classList.remove('open');
navToggle.setAttribute('aria-expanded', 'false');
});
});
// Smooth-scrolling for internal anchors
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
const href = this.getAttribute('href');
if (href && href.length > 1) {
const target = document.querySelector(href);
if (target) {
e.preventDefault();
target.scrollIntoView({behavior: 'smooth', block: 'start'});
}
}
});
});
// Active link highlighting using IntersectionObserver
const sections = document.querySelectorAll('main section[id]');
const observerOptions = { root: null, rootMargin: '0px', threshold: 0.55 };
function onIntersect(entries) {
entries.forEach(entry => {
const id = entry.target.getAttribute('id');
const link = document.querySelector('.nav-link[href="#' + id + '"]');
if (entry.isIntersecting) {
document.querySelectorAll('.nav-link').forEach(l => l.classList.remove('active'));
if (link) link.classList.add('active');
}
});
}
const observer = new IntersectionObserver(onIntersect, observerOptions);
sections.forEach(sec => observer.observe(sec));
// Contact form: POST to serverless endpoint. Provide a graceful fallback.
const form = document.getElementById('contactForm');
if (form) {
form.addEventListener('submit', async (e) => {
e.preventDefault();
const data = {
name: form.name.value.trim(),
email: form.email.value.trim(),
message: form.message.value.trim()
};
// Choose endpoint: Vercel: /api/sendEmail, Netlify: /.netlify/functions/sendEmail
const endpoints = ['/api/sendEmail', '/.netlify/functions/sendEmail', '/api/send'];
let success = false;
for (const ep of endpoints) {
try {
const res = await fetch(ep, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
});
if (res.ok) {
const json = await res.json().catch(()=>({ok:true}));
alert(json.message || 'Thanks — your message has been sent.');
form.reset();
success = true;
break;
}
} catch (err) {
// try the next endpoint
}
}
if (!success) {
// Fallback: local demo
alert('Thanks — your message has been noted (demo). For real delivery, configure a serverless email function.');
form.reset();
}
});
}
});