⟨
⟩
⟲
NeoBrowser
neo://
🏠
`; } function blackFull(){ return `
`; } function clubPenguinWhite(){ return `
Club Penguin construction penguin
Your text image
`; } function spaceHey(){ return `
SpaceHey
Open SpaceHey β†—
`; } /* Routes: - home -> Google - site/ -> catalog entry - web/ -> arbitrary URL */ function renderHome(){ renderWeb("https://www.google.com", "Google"); addr.value = "web/https://www.google.com"; } function renderSite(id){ const s = SITES.find(x=>x.id===id); if(!s){ content.innerHTML = siteChrome("Not found", `
Unknown site.
`); return; } if(s.mode === "black-full"){ content.innerHTML = siteChrome(s.name, blackFull(), s.live); return; } if(s.mode === "club-white"){ content.innerHTML = siteChrome(s.name, clubPenguinWhite(), s.live); return; } if(s.mode === "spacehey"){ content.innerHTML = spaceHey(); return; } // Default: try to embed live content.innerHTML = siteChrome(s.name, renderLiveEmbed(s.live), s.live); } function renderWeb(url, label){ const safe = ensureHttp(url); const title = label || safe; content.innerHTML = siteChrome(title, renderLiveEmbed(safe), safe); } /* ======= Router ======= */ function go(path){ location.hash = "#" + path; } function parseHash(){ const h = (location.hash || "#home").slice(1); const [route, rest] = h.split("/",2); if(route==="site" && rest){ renderSite(rest); addr.value = `site/${rest}`; } else if(route==="web" && rest){ const url = decodeURIComponent(rest); renderWeb(url); addr.value = `web/${url}`; } else { renderHome(); } } /* ======= Address bar behavior ======= */ addr.addEventListener("keydown", e=>{ if(e.key==="Enter"){ const val = addr.value.trim(); if(!val){ return; } // direct commands if(val==="home"){ go("home"); return; } // site/ route if(val.startsWith("site/")){ go(val); return; } // web/ route if(val.startsWith("web/")){ const raw = val.slice(4); go("web/" + encodeURIComponent(raw)); return; } // If it looks like a URL, load it; else search Google if(isLikelyUrl(val)){ go("web/" + encodeURIComponent(ensureHttp(val))); }else{ const q = encodeURIComponent(val); go("web/" + encodeURIComponent("https://www.google.com/search?q=" + q)); } } }); /* Toolbar buttons */ $("#btnBack").onclick = ()=> history.back(); $("#btnFwd").onclick = ()=> history.forward(); $("#btnRef").onclick = ()=> parseHash(); $("#btnHome").onclick = ()=> go("home"); window.addEventListener("hashchange", parseHash); /* Start at Google home by default */ if(!location.hash){ go("home"); } else { parseHash(); } /* ======= Helpers ======= */ function isLikelyUrl(input){ try{ if(/^https?:\/\//i.test(input)) return true; if(/^[a-z]+:\/\//i.test(input)) return true; // domain.tld[/path] const m = input.match(/^[a-z0-9\-_.]+\.[a-z]{2,}([/:?#].*)?$/i); return !!m; }catch{ return false; } } function ensureHttp(u){ if(/^https?:\/\//i.test(u)) return u; return "https://" + u; } function escapeHtml(s){ return String(s).replace(/[&<>"']/g, c=>({"&":"&","<":"<",">":">",'"':""","'":"'"}[c])); }