Skip to content

Commit 6986d31

Browse files
refactor: Wrap script in DOMContentLoaded, simplify cursor effects from magnetic pull to fluid hover, add localStorage error handling, and initialize configurator code on load.
1 parent d747731 commit 6986d31

1 file changed

Lines changed: 107 additions & 109 deletions

File tree

docs/assets/js/main.js

Lines changed: 107 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,110 @@
1-
// Initialize Animate On Scroll
2-
AOS.init({
3-
once: true,
4-
offset: 50,
5-
duration: 1000,
6-
easing: 'ease-out-cubic',
7-
});
8-
9-
// Theme System
10-
const themeToggle = document.getElementById('themeToggle');
11-
const html = document.documentElement;
12-
const icon = themeToggle ? themeToggle.querySelector('span') : null;
13-
14-
// Check saved preference or default to dark
15-
const savedTheme = localStorage.getItem('theme') || 'dark';
16-
html.setAttribute('data-theme', savedTheme);
17-
updateThemeIcon(savedTheme);
18-
19-
if (themeToggle) {
20-
themeToggle.addEventListener('click', () => {
21-
const currentTheme = html.getAttribute('data-theme');
22-
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
23-
24-
html.setAttribute('data-theme', newTheme);
25-
localStorage.setItem('theme', newTheme);
26-
updateThemeIcon(newTheme);
1+
document.addEventListener('DOMContentLoaded', () => {
2+
// Initialize Animate On Scroll
3+
AOS.init({
4+
once: true,
5+
offset: 50,
6+
duration: 1000,
7+
easing: 'ease-out-cubic',
278
});
28-
}
29-
30-
function updateThemeIcon(theme) {
31-
if (!icon) return;
32-
icon.textContent = theme === 'light' ? '🌙' : '☀️';
33-
}
349

35-
// Gravity Cursor Logic
36-
const cursorDot = document.querySelector('.cursor-dot');
37-
const cursorOutline = document.querySelector('.cursor-outline');
38-
39-
let mouseX = 0;
40-
let mouseY = 0;
41-
let cursorX = 0;
42-
let cursorY = 0;
43-
44-
document.addEventListener('mousemove', (e) => {
45-
mouseX = e.clientX;
46-
mouseY = e.clientY;
47-
48-
// Instant follow for dot
49-
cursorDot.style.left = mouseX + 'px';
50-
cursorDot.style.top = mouseY + 'px';
51-
});
52-
53-
function animateCursor() {
54-
// Heavy Lerp for "Gravity" feel
55-
const speed = 0.1;
56-
cursorX += (mouseX - cursorX) * speed;
57-
cursorY += (mouseY - cursorY) * speed;
58-
59-
cursorOutline.style.left = cursorX + 'px';
60-
cursorOutline.style.top = cursorY + 'px';
61-
62-
requestAnimationFrame(animateCursor);
63-
}
64-
65-
animateCursor();
66-
67-
// Magnetic Pull Effect
68-
const magnets = document.querySelectorAll('a, button, .feature-card, .config-input');
69-
70-
magnets.forEach(magnet => {
71-
magnet.addEventListener('mousemove', (e) => {
72-
const rect = magnet.getBoundingClientRect();
73-
const centerX = rect.left + rect.width / 2;
74-
const centerY = rect.top + rect.height / 2;
10+
// Theme System
11+
const themeToggle = document.getElementById('themeToggle');
12+
const html = document.documentElement;
13+
const icon = themeToggle ? themeToggle.querySelector('span') : null;
14+
15+
// Check saved preference or default to dark
16+
let savedTheme = 'dark';
17+
try {
18+
savedTheme = localStorage.getItem('theme') || 'dark';
19+
} catch (e) {
20+
console.warn('LocalStorage access denied', e);
21+
}
7522

76-
// Calculate distance from center
77-
const distX = e.clientX - centerX;
78-
const distY = e.clientY - centerY;
23+
html.setAttribute('data-theme', savedTheme);
24+
updateThemeIcon(savedTheme);
7925

80-
// Pull the element towards the mouse (Magnetic effect)
81-
// Divide by a factor to control strength (higher = weaker)
82-
magnet.style.transform = `translate(${distX / 5}px, ${distY / 5}px)`;
26+
if (themeToggle) {
27+
themeToggle.addEventListener('click', () => {
28+
const currentTheme = html.getAttribute('data-theme');
29+
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
8330

84-
// Expand cursor
85-
cursorOutline.style.width = '60px';
86-
cursorOutline.style.height = '60px';
87-
cursorOutline.style.backgroundColor = 'rgba(255, 255, 255, 0.05)';
88-
});
31+
html.setAttribute('data-theme', newTheme);
32+
try {
33+
localStorage.setItem('theme', newTheme);
34+
} catch (e) { }
35+
updateThemeIcon(newTheme);
36+
});
37+
}
8938

90-
magnet.addEventListener('mouseleave', () => {
91-
// Reset position
92-
magnet.style.transform = 'translate(0, 0)';
39+
function updateThemeIcon(theme) {
40+
if (!icon) return;
41+
icon.textContent = theme === 'light' ? '🌙' : '☀️';
42+
}
9343

94-
// Reset cursor
95-
cursorOutline.style.width = '40px';
96-
cursorOutline.style.height = '40px';
97-
cursorOutline.style.backgroundColor = 'transparent';
98-
});
99-
});
44+
// Fluid Cursor Logic (Reverted to Phase 12 - Lighter, No Magnet)
45+
const cursorDot = document.querySelector('.cursor-dot');
46+
const cursorOutline = document.querySelector('.cursor-outline');
47+
48+
if (cursorDot && cursorOutline) {
49+
let mouseX = 0;
50+
let mouseY = 0;
51+
let cursorX = 0;
52+
let cursorY = 0;
53+
54+
document.addEventListener('mousemove', (e) => {
55+
mouseX = e.clientX;
56+
mouseY = e.clientY;
57+
58+
// Instant follow for dot
59+
cursorDot.style.left = mouseX + 'px';
60+
cursorDot.style.top = mouseY + 'px';
61+
});
62+
63+
function animateCursor() {
64+
// Lighter Lerp (Phase 12 feel)
65+
const speed = 0.2;
66+
cursorX += (mouseX - cursorX) * speed;
67+
cursorY += (mouseY - cursorY) * speed;
68+
69+
cursorOutline.style.left = cursorX + 'px';
70+
cursorOutline.style.top = cursorY + 'px';
71+
72+
requestAnimationFrame(animateCursor);
73+
}
74+
75+
animateCursor();
76+
77+
// Simple Hover Effect (No Magnetic Pull)
78+
const interactiveElements = document.querySelectorAll('a, button, .feature-card, .config-input, select, label');
79+
80+
interactiveElements.forEach(el => {
81+
el.addEventListener('mouseenter', () => {
82+
cursorOutline.style.width = '60px';
83+
cursorOutline.style.height = '60px';
84+
cursorOutline.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
85+
});
86+
87+
el.addEventListener('mouseleave', () => {
88+
cursorOutline.style.width = '40px';
89+
cursorOutline.style.height = '40px';
90+
cursorOutline.style.backgroundColor = 'transparent';
91+
});
92+
});
93+
}
10094

101-
// Interactive Configurator
102-
const configName = document.getElementById('configName');
103-
const configSecurity = document.getElementById('configSecurity');
104-
const configLogging = document.getElementById('configLogging');
105-
const codeBlock = document.getElementById('generatedCode');
95+
// Interactive Configurator
96+
const configName = document.getElementById('configName');
97+
const configSecurity = document.getElementById('configSecurity');
98+
const configLogging = document.getElementById('configLogging');
99+
const codeBlock = document.getElementById('generatedCode');
106100

107-
if (configName && configSecurity && configLogging && codeBlock) {
108-
function updateCode() {
109-
const name = configName.value || 'My-ESP32';
110-
const security = configSecurity.value;
111-
const logging = configLogging.checked;
101+
if (configName && configSecurity && configLogging && codeBlock) {
102+
function updateCode() {
103+
const name = configName.value || 'My-ESP32';
104+
const security = configSecurity.value;
105+
const logging = configLogging.checked;
112106

113-
const code = `#include <WiBLE.h>
107+
const code = `#include <WiBLE.h>
114108
115109
WiBLE provisioner;
116110
@@ -128,10 +122,14 @@ void setup() {
128122
void loop() {
129123
provisioner.loop();
130124
}`;
131-
codeBlock.textContent = code;
132-
}
125+
codeBlock.textContent = code;
126+
}
133127

134-
configName.addEventListener('input', updateCode);
135-
configSecurity.addEventListener('change', updateCode);
136-
configLogging.addEventListener('change', updateCode);
137-
}
128+
configName.addEventListener('input', updateCode);
129+
configSecurity.addEventListener('change', updateCode);
130+
configLogging.addEventListener('change', updateCode);
131+
132+
// Run once to set initial state
133+
updateCode();
134+
}
135+
});

0 commit comments

Comments
 (0)