Primo Post Italiano 2
Contenuto italiano qui…
Sezione 2
Altro contenuto italiano. 2
// 2. Click Event Listener
document.addEventListener('click', (e) => {
const btn = e.target.closest('[data-target]');
if (btn) revealContent(btn);
});
Your href="/#about?show=about" has malformed URL structure (/#about? confuses pathname/query)—the redirect happens, but ?show=about gets lost or timing fails to activate the target. Fix href + use sessionStorage for reliable target passing across redirects. stackoverflow
Fix Menu Link
Simplify href to just the query param (no hash/path needed):
<a class="w3-bar-item w3-button w3-padding-large w3-hide-small"
href="/?show=about" data-target="about">ABOUT</a>
Reliable Delegated Click Handler
Replace your click listener with this—stores target in sessionStorage (survives redirect), clears after use:
document.addEventListener('click', (e) => {
const btn = e.target.closest('a[data-target]');
if (btn) {
e.preventDefault();
const targetId = btn.dataset.target;
if (window.location.pathname !== '/') {
// Store target, redirect to /
sessionStorage.setItem('pendingTarget', targetId);
window.location.href = '/';
return;
}
// On /, reveal now
revealContent(btn);
}
});
Updated Deep Linking (Replaces Your ?show Logic)
Handle both URL param and sessionStorage in DOMContentLoaded:
// In DOMContentLoaded, after loadComponent...
const urlParams = new URLSearchParams(window.location.search);
let autoOpen = urlParams.get('show') || sessionStorage.getItem('pendingTarget');
if (autoOpen) {
sessionStorage.removeItem('pendingTarget'); // Clear after use
setTimeout(() => {
const btn = document.querySelector(`[data-target="${autoOpen}"]`);
if (btn) {
revealContent(btn); // Your fetch/decode/animate function
}
window.history.replaceState({}, document.title, window.location.pathname);
}, 1000); // Slightly longer for menu fetch
}
Why This Works
- Click “ABOUT” anywhere: Stores “about” →
/→ sessionStorage triggersrevealContent→ fetches/aboutbase64 → animates#about. - Direct
/?show=about: Same flow. - No param loss—sessionStorage reliable across pages/404.html.
revealContentunchanged—handles bot checks, fetch, decode perfectly. perplexity
404.html Reminder
Repo root 404.html = copy of index.html. GitHub serves it everywhere, running your full JS. Deploy, test /wrong → click ABOUT → target activates! stackoverflow
🛠️
<a href="/" class="w3-bar-item w3-button w3-padding-large">HOME</a> <a class="w3-bar-item w3-button w3-padding-large w3-hide-small" data-target="contact" href="/?show=contact" >CONTACT</a> <a class="w3-bar-item w3-button w3-padding-large w3-hide-small" href="/?show=about" data-target="about">
ABOUT
</a>
// 1. Core Reveal Function
async function revealContent(btn) {
const targetId = btn.getAttribute('data-target');
const targetEl = document.getElementById(targetId);
// const ledto = btn.getAttribute('rq-section-name');
// FIX: if the button points to a target that doesn't exist, stop here.
if (!targetEl) {
console.warn(`Target element #${targetId} not found.`);
return;
}
var ensource = "";
if (targetId === "about") { // Use === for strict equality; define ledto first
ensource = LTO1; // Define LTO1 first, e.g., const LTO1 = "/about";
} else if (targetId === "contact") { // Use === for strict equality; define ledto first
ensource = LTO2; // Define LTO1 first, e.g., const LTO1 = "/about";
}
// Bot Checks
const trap = btn.parentElement.querySelector('.required-field-if input');
if (trap && trap.value !== "") return; // Honeypot fail
if (Date.now() - PAGE_START < 1000) return; // Timing fail (1s)
// ... inside revealContent ...
if (targetEl.innerHTML.trim() === "") {
targetEl.innerHTML = "Loading..."; // Optional: Quick placeholder
try {
const path = atob(ensource);
const res = await fetch(path);
const base64Content = await res.text();
// Inject content
targetEl.innerHTML = decodeURIComponent(escape(atob(base64Content.trim())));
// NOW trigger the animation
targetEl.classList.add('active');
requestAnimationFrame(() => {
requestAnimationFrame(() => { // Double frame ensures display:block is rendered
targetEl.classList.add('visible');
});
});
// Scroll to target + trigger animation targetEl.scrollIntoView({
behavior: 'smooth',
block: 'start' // Top of viewport });
} catch (e) {
targetEl.innerHTML = "Error loading content.";
}
} else {
// If already loaded, just toggle
const isVisible = targetEl.classList.contains('visible');
if (!isVisible) {
targetEl.classList.add('active');
setTimeout(() => targetEl.classList.add('visible'), 10);
} else {
targetEl.classList.remove('visible');
setTimeout(() => targetEl.classList.remove('active'), 600);
}
}
}
document.addEventListener(‘click’, (e) => { const btn = e.target.closest(‘a[data-target]’); if (btn) { e.preventDefault(); const targetId = btn.dataset.target;
// CRITICAL: Clear any pending target first
sessionStorage.removeItem('pendingTarget');
if (window.location.pathname !== '/') {
// Store ONLY this click's target, then redirect
sessionStorage.setItem('pendingTarget', targetId);
window.location.href = '/';
return;
}
// On /, reveal immediately (no storage)
revealContent(btn);
} });
document.addEventListener(‘click’, function (event) { // Check if the clicked element is a menu link or a toggle button if (event.target.hasAttribute(‘data-loc’)) { const targetId = event.target.getAttribute(‘data-loc’); const targetEl = document.getElementById(targetId);
if (targetEl) {
// 1. Make it active (display: block)
targetEl.classList.add('active');
// 2. Trigger animation in next frame
requestAnimationFrame(() => {
targetEl.classList.add('visible');
});
// 3. Scroll to the element smoothly
targetEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
} } });
// 3. Deep Linking + Language Logic window.addEventListener(‘DOMContentLoaded’, () => { // Get language first const lang = getPreferredLang(); document.documentElement.lang = lang; // Update <html lang>
// Load language-specific menu
loadComponent('menu-container', `/parts/static_beans/menu_${lang}.html`);
loadComponent('right-bar-container', `/parts/static_beans/sidebar-right.html`);
// Language dropdown setup (if you have it)
if (document.querySelector('.lang-dropdown')) {
document.getElementById('current-lang').textContent = langNames[lang];
}
// In DOMContentLoaded, after loadComponent... const urlParams = new URLSearchParams(window.location.search); let autoOpen = urlParams.get('show') || sessionStorage.getItem('pendingTarget');
if (autoOpen) {
setTimeout(() => {
const btn = document.querySelector([data-target="${autoOpen}"]);
if (btn) {
revealContent(btn);
// Scroll after revealContent
const targetEl = document.getElementById(autoOpen);
if (targetEl) {
targetEl.scrollIntoView({ behavior: ‘smooth’, block: ‘start’ });
}
}
window.history.replaceState({}, document.title, window.location.pathname);
}, 1000);
}
});
The reason it broke is that you are clearing the storage before you actually use the value. When the browser redirects to /, the script runs from the top; if removeItem happens before you read the value into autoOpen, the data is gone forever. To fix this, you must read it first, then clear it. Here is the correct order for your DOMContentLoaded logic:
window.addEventListener(‘DOMContentLoaded’, () => {
// 1. Setup language and components
const lang = getPreferredLang();
loadComponent(‘menu-container’, /parts/static_beans/menu_${lang}.html);
// 2. READ the target first
const urlParams = new URLSearchParams(window.location.search);
let autoOpen = urlParams.get('show') || sessionStorage.getItem('pendingTarget');
// 3. NOW clear the storage (it's safe because the value is saved in the variable 'autoOpen')
sessionStorage.removeItem('pendingTarget');
// 4. Proceed with logic
if (autoOpen) {
setTimeout(() => {
const btn = document.querySelector(`[data-target="${autoOpen}"]`);
if (btn) {
revealContent(btn); // Your function to show content
const targetEl = document.getElementById(autoOpen);
if (targetEl) {
targetEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
// Clean URL
window.history.replaceState({}, document.title, window.location.pathname);
}, 1000);
}
// 5. Global listener for buttons (for when you are on other pages)
document.addEventListener('click', (e) => {
const btn = e.target.closest('[data-target]');
if (btn && window.location.pathname !== '/' && window.location.pathname !== '/index.html') {
e.preventDefault();
const target = btn.getAttribute('data-target');
sessionStorage.setItem('pendingTarget', target); // Set it here
window.location.href = '/'; // Redirect
}
}); });
Why yours broke vs why this works:
- Your broken version: Clear Storage -> Read Storage (Result: Null).
- This version: Read Storage into Variable -> Clear Storage -> Use Variable.
Even though the storage is cleared, the variable autoOpen still holds the string “about”, so your setTimeout logic can finish the job. Does your revealContent function correctly handle the case where the button might still be loading inside the component, or should we consider a small check to see if btn exists before clicking?
No, you do not need that separate if (!autoOpen) block. You can handle it all in one clean line using the OR (||) operator. This looks for the URL parameter first, and if it’s missing, it checks sessionStorage.
The “Clean” Way
Use this single line at the start of your logic:
// Get from URL OR Storage in one golet autoOpen = urlParams.get(‘show’) || sessionStorage.getItem(‘pendingTarget’); // Clear it immediately AFTER reading so it doesn’t trigger on the next refresh sessionStorage.removeItem(‘pendingTarget’); if (autoOpen) { // … your setTimeout logic … }
Why the extra if is unnecessary:
- urlParams.get(‘show’) returns null if the parameter isn’t in the URL.
-
In JavaScript, null “something” evaluates to “something”. - Therefore, if show is missing from the URL, the variable autoOpen automatically tries to take the value from sessionStorage.
One Warning
Make sure your Click Listener (on other pages) actually sets the sessionStorage before redirecting, otherwise autoOpen will be empty:
// Inside your click listener for buttons on other pages:const target = btn.getAttribute(‘data-target’); sessionStorage.setItem(‘pendingTarget’, target); // Store the intent window.location.href = ‘/’; // Go home to trigger the auto-open logic
Since you mentioned you’re on GitHub Pages, are you finding that window.location.pathname sometimes includes your repository name (e.g., /my-repo/)?
Your logic is almost perfect, but there is one small logic “trap” to be aware of: the root path on GitHub Pages. On GitHub Pages, window.location.pathname is often /your-repo-name/ instead of just /. If your check !== ‘/’ fails because the path is actually /my-project/, the redirect won’t trigger. Here is the refined version of your listener to ensure it works on GitHub Pages and handles the state cleanly:
document.addEventListener(‘click’, (e) => { const btn = e.target.closest(‘a[data-target]’); if (btn) { e.preventDefault(); const targetId = btn.dataset.target;
closeMobileMenu();
// 1. Get the current path and normalize it
// This handles both "://domain.com" and "user.github.io/repo/"
const path = window.location.pathname;
const isRoot = path === '/' || path === '/index.html' || path.endsWith('/my-repo-name/'); // Change to your repo name if needed
if (!isRoot) {
// 2. We are on a sub-page: Save and Redirect
sessionStorage.setItem('pendingTarget', targetId);
// Redirect to the base URL of your site
window.location.href = window.location.origin + (path.startsWith('/my-repo-name') ? '/my-repo-name/' : '/');
return;
}
// 3. We are ALREADY on the root: Just reveal
// Ensure no leftover storage interferes
sessionStorage.removeItem('pendingTarget');
revealContent(btn);
} });
Key Improvements:
- Normalization: Added a check for /index.html and a note about your repo name. If you don’t check for the repo name, the browser will think /my-repo/ is a “sub-page” and will keep refreshing the home page.
- Origin Redirect: Using window.location.origin ensures the redirect goes back to the very top of your domain.
- Storage Cleanup: By moving removeItem into the isRoot block, you ensure that a “fresh” click on the home page clears any old state before showing the new content.
Quick Check: When you look at your site in the browser, does the URL look like username.github.io/ or username.github.io/project-name/? (If it’s the latter, we should adjust the isRoot check to match your project-name exactly).
// 1. Core Reveal Function
async function revealContent(btn) {
const targetId = btn.getAttribute('data-target');
const targetEl = document.getElementById(targetId);
// const ledto = btn.getAttribute('rq-section-name');
// FIX: if the button points to a target that doesn't exist, stop here.
if (!targetEl) {
console.warn(`Target element #${targetId} not found.`);
return;
}
console.warn(Target element #${targetId} not found.);
Error on cklick Homw from Home