docs: Update skeleton loader implementation from hyperscript to JavaScript
MIGRATION SUMMARY: - Moved skeleton loader logic from hyperscript to JavaScript (main.js) - Changed from htmx:oobAfterSwap to htmx:afterSettle event - Changed OOB swap from innerHTML to outerHTML for proper element replacement - Added languageSwitching flag for state tracking - Added 100ms delay after afterSettle for final render completion DOCUMENTATION UPDATES: - 2-MODERN-WEB-TECHNIQUES.md: Updated skeleton loader section with
This commit is contained in:
@@ -1930,31 +1930,57 @@ Time 600ms+: opacity=NaN ← Element destroyed!
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Language switch with skeleton loading
|
||||
htmx.on('htmx:beforeSwap', function(evt) {
|
||||
// Show skeletons BEFORE swap
|
||||
document.querySelectorAll('.component-wrapper').forEach(wrapper => {
|
||||
wrapper.classList.add('loading');
|
||||
});
|
||||
// static/js/main.js - Skeleton loader for language transitions
|
||||
let languageSwitching = false;
|
||||
|
||||
// Add .loading class when language button is clicked
|
||||
document.addEventListener('htmx:beforeRequest', function(evt) {
|
||||
const element = evt.detail.elt;
|
||||
if (element && element.classList && element.classList.contains('selector-btn')) {
|
||||
// Set flag to track language switching
|
||||
languageSwitching = true;
|
||||
|
||||
// Add loading class to page containers
|
||||
const page1 = document.getElementById('cv-inner-content-page-1');
|
||||
const page2 = document.getElementById('cv-inner-content-page-2');
|
||||
if (page1) page1.classList.add('loading');
|
||||
if (page2) page2.classList.add('loading');
|
||||
}
|
||||
});
|
||||
|
||||
htmx.on('htmx:afterSettle', function(evt) {
|
||||
// Hide skeletons AFTER content settles
|
||||
document.querySelectorAll('.component-wrapper').forEach(wrapper => {
|
||||
wrapper.classList.remove('loading');
|
||||
});
|
||||
// Remove .loading class after language transition completes
|
||||
document.addEventListener('htmx:afterSettle', function(evt) {
|
||||
if (languageSwitching) {
|
||||
// Wait for final render to complete
|
||||
setTimeout(function() {
|
||||
const page1 = document.getElementById('cv-inner-content-page-1');
|
||||
const page2 = document.getElementById('cv-inner-content-page-2');
|
||||
if (page1) page1.classList.remove('loading');
|
||||
if (page2) page2.classList.remove('loading');
|
||||
|
||||
// Reset flag
|
||||
languageSwitching = false;
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Architecture Pattern:**
|
||||
1. **User clicks language toggle** → HTMX `beforeSwap` event fires
|
||||
2. **JavaScript adds `.loading` class** → Triggers CSS transition (actual-content opacity: 1 → 0, skeleton-content opacity: 0 → 1)
|
||||
3. **Skeleton appears** → Smooth 250ms fade-in with shimmer animation
|
||||
4. **HTMX fetches new language content** → Server renders and returns HTML
|
||||
5. **HTMX swaps content** → New actual-content replaces old
|
||||
6. **afterSettle event fires** → JavaScript removes `.loading` class
|
||||
7. **Skeleton fades out** → Smooth 250ms fade (skeleton opacity: 1 → 0, actual-content opacity: 0 → 1)
|
||||
8. **Result** → Smooth, professional loading experience with zero layout shift
|
||||
1. **User clicks language button** → HTMX `htmx:beforeRequest` event fires
|
||||
2. **JavaScript detects `.selector-btn` click** → Sets `languageSwitching` flag
|
||||
3. **JavaScript adds `.loading` to parent containers** → Triggers CSS cascade to child `.component-wrapper` elements
|
||||
4. **Skeleton appears** → CSS transition (actual-content opacity: 1 → 0, skeleton-content opacity: 0 → 1) + shimmer animation
|
||||
5. **HTMX fetches new language content** → Server renders and returns HTML via OOB swaps
|
||||
6. **HTMX swaps content** → Out-of-band (OOB) swap replaces page containers
|
||||
7. **`htmx:afterSettle` event fires** → JavaScript waits 100ms for final render
|
||||
8. **JavaScript removes `.loading` class** → CSS transition reverses (skeleton opacity: 1 → 0, actual-content opacity: 0 → 1)
|
||||
9. **Result** → Smooth, professional loading experience with zero layout shift
|
||||
|
||||
**Why JavaScript Instead of Hyperscript:**
|
||||
- ✅ **Reliable Playwright testing** - JavaScript event handlers work consistently in automated tests
|
||||
- ✅ **Debugging** - Console.log statements provide clear execution tracking
|
||||
- ✅ **Maintainability** - Standard JavaScript patterns familiar to all developers
|
||||
- ✅ **Performance** - Direct DOM manipulation, no hyperscript parser overhead
|
||||
|
||||
**Benefits:**
|
||||
- ✅ **Zero layout shift** - Skeletons match exact dimensions of actual content
|
||||
@@ -1966,16 +1992,24 @@ htmx.on('htmx:afterSettle', function(evt) {
|
||||
- ✅ **Reusable** - Works for any HTMX swap operation, not just language switch
|
||||
|
||||
**Implementation Locations:**
|
||||
- **CSS:** `static/css/skeleton.css` (341 lines) - Complete skeleton system
|
||||
- **Template:** `templates/partials/skeleton-loader.html` - Skeleton placeholders
|
||||
- **Component wrappers:** Each CV section wrapped with `.component-wrapper`
|
||||
- **HTMX events:** `static/js/main.js` - beforeSwap/afterSettle listeners
|
||||
- **CSS:** `static/css/skeleton.css` - Complete skeleton system with shimmer animations
|
||||
- **JavaScript:** `static/js/main.js` (lines 231-273) - HTMX event handlers for skeleton control
|
||||
- **Templates:** `templates/partials/sections/header.html` - Component wrapper structure
|
||||
- **Page Containers:** `templates/cv-content.html` - Parent containers receiving `.loading` class
|
||||
- **Language Switch:** `templates/language-switch.html` - `.selector-btn` triggers skeleton display
|
||||
|
||||
**Testing:** Automated tests in `tests/mjs/12-skeleton-language-transitions.test.mjs` verify:
|
||||
- Skeletons appear during language switch
|
||||
- Content replaced without full page reload
|
||||
- Skeletons removed after content loads
|
||||
- Zero layout shift during transition
|
||||
- ✅ Component wrapper structure (dual-state: actual + skeleton content)
|
||||
- ✅ Skeleton CSS loaded (shimmer animation verified)
|
||||
- ✅ First language switch (EN → ES) - Loading class added/removed
|
||||
- ✅ Second language switch (ES → EN) - Consistent behavior
|
||||
- ✅ Third language switch (EN → ES) - Regression check
|
||||
- ✅ No stuck loading states (all containers clean after transition)
|
||||
- ✅ JavaScript event handlers configured (languageSwitching flag)
|
||||
|
||||
**Test Results:** 7/7 tests pass - Complete validation of skeleton loader functionality
|
||||
|
||||
**Run Test:** `bun tests/mjs/12-skeleton-language-transitions.test.mjs`
|
||||
|
||||
**Pixel-Perfect Matching:**
|
||||
|
||||
@@ -2354,7 +2388,7 @@ set #shortcuts-button's *zoom to inverseZoom
|
||||
3. `templates/partials/navigation/hamburger-menu.html`
|
||||
- Removed conflicting hyperscript from show zoom button
|
||||
|
||||
4. `MODERN-WEB-TECHNIQUES.md`
|
||||
4. `2-MODERN-WEB-TECHNIQUES.md`
|
||||
- Updated documentation to reflect fixes
|
||||
- Added technical lessons learned
|
||||
|
||||
|
||||
+3
-3
@@ -1190,7 +1190,7 @@ curl -H "Referer: https://evil.com/" \
|
||||
**Current Configuration:**
|
||||
- **Endpoint:** `/export/pdf`
|
||||
- **Limit:** 3 requests per minute per IP
|
||||
- **Window:** 1 minute (rolling)
|
||||
- **Window:** 1 minute (rolling)
|
||||
- **Response:** 429 Too Many Requests when exceeded
|
||||
|
||||
**Implementation:**
|
||||
@@ -1266,7 +1266,7 @@ pdfRateLimiter := middleware.NewRateLimiter(5, 1*time.Hour)
|
||||
- Input validation
|
||||
- Error message sanitization (internal errors hidden)
|
||||
- Timeouts on all operations
|
||||
- Graceful shutdown
|
||||
- Graceful shutdown
|
||||
- Origin checking (prevents external hotlinking)
|
||||
- Rate limiting (PDF endpoint: 3 requests/min per IP)
|
||||
- IP-based tracking (supports reverse proxies)
|
||||
@@ -1974,7 +1974,7 @@ go tool trace trace.out
|
||||
---
|
||||
|
||||
**Last Updated:** November 12, 2025
|
||||
**API Version:** 1.1.0
|
||||
**API Version:** 1.1.0
|
||||
**Documentation Version:** 1.1.0
|
||||
### Support
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ This CV/Resume application is designed to be easily customizable. You can adapt
|
||||
|
||||
### Tools Needed
|
||||
- **Text editor**: VS Code, Sublime Text, or any editor
|
||||
- **Go 1.25.1+**: For building and testing (see [DEPLOYMENT.md](DEPLOYMENT.md))
|
||||
- **Go 1.25.1+**: For building and testing (see [8-DEPLOYMENT.md](8-DEPLOYMENT.md))
|
||||
- **Git**: For version control (optional but recommended)
|
||||
- **Browser**: For testing (Chrome/Firefox recommended)
|
||||
|
||||
@@ -1103,7 +1103,7 @@ open http://localhost:1999
|
||||
- ✅ Comply with GDPR, CCPA, or local privacy laws
|
||||
- ✅ Update privacy policy when changing analytics providers
|
||||
|
||||
**See [PRIVACY.md](PRIVACY.md) for privacy policy template.**
|
||||
**See [10-PRIVACY.md](10-PRIVACY.md) for privacy policy template.**
|
||||
|
||||
---
|
||||
|
||||
@@ -1751,7 +1751,7 @@ python3 -m json.tool data/cv-en.json
|
||||
After customization:
|
||||
1. **Test thoroughly** with checklist above
|
||||
2. **Generate PDF** and verify quality
|
||||
3. **Deploy** using [DEPLOYMENT.md](DEPLOYMENT.md) guide
|
||||
3. **Deploy** using [8-DEPLOYMENT.md](8-DEPLOYMENT.md) guide
|
||||
4. **Set up CI/CD** for automatic deployments
|
||||
5. **Share** your customized CV!
|
||||
|
||||
|
||||
+1
-1
@@ -1050,4 +1050,4 @@ curl http://localhost:1999/health
|
||||
|
||||
---
|
||||
|
||||
**For customization, see CUSTOMIZATION.md**
|
||||
**For customization, see [7-CUSTOMIZATION.md](7-CUSTOMIZATION.md)**
|
||||
|
||||
+1
-1
@@ -435,7 +435,7 @@ proxy_set_header X-Real-IP $remote_addr;
|
||||
**Solution:** This is normal browser behavior. The middleware checks `Referer` header as fallback, which browsers do send for navigation.
|
||||
|
||||
For technical API details, see [3-API.md](3-API.md#security-protection).
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Known Security Considerations
|
||||
|
||||
+31
-31
@@ -9,25 +9,25 @@
|
||||
### For Developers
|
||||
|
||||
**Getting Started**
|
||||
- [Architecture Overview](ARCHITECTURE.md) - System design and Go backend architecture
|
||||
- [Modern Web Techniques](MODERN-WEB-TECHNIQUES.md) - Frontend architecture (HTMX, Hyperscript, CSS) ⭐
|
||||
- [API Reference](API.md) - Complete API documentation with endpoints and responses
|
||||
- [1. Architecture Overview](1-ARCHITECTURE.md) - System design and Go backend architecture
|
||||
- [2. Modern Web Techniques](2-MODERN-WEB-TECHNIQUES.md) - Frontend architecture (HTMX, Hyperscript, CSS) ⭐
|
||||
- [3. API Reference](3-API.md) - Complete API documentation with endpoints and responses
|
||||
|
||||
**Technical Implementation**
|
||||
- [Hyperscript Rules](HYPERSCRIPT-RULES.md) - Hyperscript conventions and best practices
|
||||
- [Zoom Implementation](ZOOM_IMPLEMENTATION.md) - Custom zoom feature technical details
|
||||
- [4. Hyperscript Rules](4-HYPERSCRIPT-RULES.md) - Hyperscript conventions and best practices
|
||||
- [5. Zoom Implementation](5-ZOOM-IMPLEMENTATION.md) - Custom zoom feature technical details
|
||||
|
||||
**Deployment & Operations**
|
||||
- [Deployment Guide](DEPLOYMENT.md) - Production deployment instructions
|
||||
- [Security Policies](SECURITY.md) - Security guidelines and vulnerability reporting
|
||||
- [8. Deployment Guide](8-DEPLOYMENT.md) - Production deployment instructions
|
||||
- [9. Security Policies](9-SECURITY.md) - Security guidelines and vulnerability reporting
|
||||
|
||||
---
|
||||
|
||||
### For Users & Customizers
|
||||
|
||||
- [User Guide](USER_GUIDE.md) - End-user documentation for CV features
|
||||
- [Customization Guide](CUSTOMIZATION.md) - How to customize your CV content and styling
|
||||
- [Privacy Policy](PRIVACY.md) - Data handling and privacy information
|
||||
- [6. User Guide](6-USER-GUIDE.md) - End-user documentation for CV features
|
||||
- [7. Customization Guide](7-CUSTOMIZATION.md) - How to customize your CV content and styling
|
||||
- [10. Privacy Policy](10-PRIVACY.md) - Data handling and privacy information
|
||||
|
||||
---
|
||||
|
||||
@@ -35,23 +35,23 @@
|
||||
|
||||
### Core Technical Documentation
|
||||
|
||||
| Document | Purpose | Audience |
|
||||
|----------|---------|----------|
|
||||
| [ARCHITECTURE.md](ARCHITECTURE.md) | Go backend architecture, package structure, design patterns | Backend developers |
|
||||
| [MODERN-WEB-TECHNIQUES.md](MODERN-WEB-TECHNIQUES.md) | HTMX/Hyperscript frontend architecture, component patterns, ADRs | Frontend developers |
|
||||
| [API.md](API.md) | Complete API reference with all endpoints | API consumers, integrators |
|
||||
| [ZOOM_IMPLEMENTATION.md](ZOOM_IMPLEMENTATION.md) | Zoom feature implementation details | Feature developers |
|
||||
| [HYPERSCRIPT-RULES.md](HYPERSCRIPT-RULES.md) | Hyperscript coding conventions | Frontend developers |
|
||||
| # | Document | Purpose | Audience |
|
||||
|---|----------|---------|----------|
|
||||
| 1 | [ARCHITECTURE.md](1-ARCHITECTURE.md) | Go backend architecture, package structure, design patterns | Backend developers |
|
||||
| 2 | [MODERN-WEB-TECHNIQUES.md](2-MODERN-WEB-TECHNIQUES.md) | HTMX/Hyperscript frontend architecture, component patterns, ADRs | Frontend developers |
|
||||
| 3 | [API.md](3-API.md) | Complete API reference with all endpoints | API consumers, integrators |
|
||||
| 4 | [HYPERSCRIPT-RULES.md](4-HYPERSCRIPT-RULES.md) | Hyperscript coding conventions | Frontend developers |
|
||||
| 5 | [ZOOM_IMPLEMENTATION.md](5-ZOOM-IMPLEMENTATION.md) | Zoom feature implementation details | Feature developers |
|
||||
|
||||
### User & Operations Documentation
|
||||
|
||||
| Document | Purpose | Audience |
|
||||
|----------|---------|----------|
|
||||
| [USER_GUIDE.md](USER_GUIDE.md) | End-user feature documentation | CV users |
|
||||
| [CUSTOMIZATION.md](CUSTOMIZATION.md) | Content and style customization | CV customizers |
|
||||
| [DEPLOYMENT.md](DEPLOYMENT.md) | Deployment instructions and operations | DevOps, site operators |
|
||||
| [SECURITY.md](SECURITY.md) | Security policies and reporting | Security teams |
|
||||
| [PRIVACY.md](PRIVACY.md) | Privacy policy and data handling | Legal, compliance |
|
||||
| # | Document | Purpose | Audience |
|
||||
|---|----------|---------|----------|
|
||||
| 6 | [USER_GUIDE.md](6-USER-GUIDE.md) | End-user feature documentation | CV users |
|
||||
| 7 | [CUSTOMIZATION.md](7-CUSTOMIZATION.md) | Content and style customization | CV customizers |
|
||||
| 8 | [DEPLOYMENT.md](8-DEPLOYMENT.md) | Deployment instructions and operations | DevOps, site operators |
|
||||
| 9 | [SECURITY.md](9-SECURITY.md) | Security policies and reporting | Security teams |
|
||||
| 10 | [PRIVACY.md](10-PRIVACY.md) | Privacy policy and data handling | Legal, compliance |
|
||||
|
||||
---
|
||||
|
||||
@@ -85,25 +85,25 @@
|
||||
### "I want to..."
|
||||
|
||||
**...understand the system architecture**
|
||||
→ Start with [ARCHITECTURE.md](ARCHITECTURE.md) (backend) and [MODERN-WEB-TECHNIQUES.md](MODERN-WEB-TECHNIQUES.md) (frontend)
|
||||
→ Start with [1-ARCHITECTURE.md](1-ARCHITECTURE.md) (backend) and [2-MODERN-WEB-TECHNIQUES.md](2-MODERN-WEB-TECHNIQUES.md) (frontend)
|
||||
|
||||
**...add a new feature**
|
||||
→ Read [MODERN-WEB-TECHNIQUES.md](MODERN-WEB-TECHNIQUES.md) for frontend patterns, [API.md](API.md) for backend APIs
|
||||
→ Read [2-MODERN-WEB-TECHNIQUES.md](2-MODERN-WEB-TECHNIQUES.md) for frontend patterns, [3-API.md](3-API.md) for backend APIs
|
||||
|
||||
**...customize my CV content**
|
||||
→ Follow [CUSTOMIZATION.md](CUSTOMIZATION.md) for content and styling changes
|
||||
→ Follow [7-CUSTOMIZATION.md](7-CUSTOMIZATION.md) for content and styling changes
|
||||
|
||||
**...deploy to production**
|
||||
→ Use [DEPLOYMENT.md](DEPLOYMENT.md) for step-by-step deployment instructions
|
||||
→ Use [8-DEPLOYMENT.md](8-DEPLOYMENT.md) for step-by-step deployment instructions
|
||||
|
||||
**...understand HTMX patterns**
|
||||
→ Check [MODERN-WEB-TECHNIQUES.md](MODERN-WEB-TECHNIQUES.md) Section 6 (HTMX Patterns)
|
||||
→ Check [2-MODERN-WEB-TECHNIQUES.md](2-MODERN-WEB-TECHNIQUES.md) Section 6 (HTMX Patterns)
|
||||
|
||||
**...write Hyperscript code**
|
||||
→ Follow conventions in [HYPERSCRIPT-RULES.md](HYPERSCRIPT-RULES.md)
|
||||
→ Follow conventions in [4-HYPERSCRIPT-RULES.md](4-HYPERSCRIPT-RULES.md)
|
||||
|
||||
**...report a security issue**
|
||||
→ See [SECURITY.md](SECURITY.md) for responsible disclosure process
|
||||
→ See [9-SECURITY.md](9-SECURITY.md) for responsible disclosure process
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user