From e25d020f6cf5dd6f164639061690afadcdd56755 Mon Sep 17 00:00:00 2001 From: ashley Date: Sun, 17 Aug 2025 22:22:10 +0200 Subject: [PATCH] Update html/map.ejs --- html/map.ejs | 1125 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 815 insertions(+), 310 deletions(-) diff --git a/html/map.ejs b/html/map.ejs index 248cf974..c5b66fc2 100644 --- a/html/map.ejs +++ b/html/map.ejs @@ -1,182 +1,102 @@ +can u like remove the desktop ui? make a new unified ui for mobile + desktop. i want u to split it between two messages so first just send the html for it then the js. please? (NOTE:MAKE SURE EVERYTHING WORKS IN MOBILE AND DESKTOP AT THE SAME TIME) + PokeMaps Public Beta - + - + @@ -184,180 +104,765 @@
- - + +
- -
+ +
PokeMaps Public Beta
- - - + + +
- - + S("#form").addEventListener("submit",async e=>{ e.preventDefault(); await searchNow(q.value); hideSuggest(true) }); + + // Quick actions (Menu) + quickNear && (quickNear.onclick=locate); + quickClear && (quickClear.onclick=()=>{ q.value=""; searchPlaces(""); q.focus() }); + + locateBtn.onclick=locate; + layerSel && (layerSel.onchange=()=>setLayer(layerSel.value)); + followBtn && (followBtn.onclick=toggleFollow); + resetBtn && (resetBtn.onclick=reset); + shareBtn && (shareBtn.onclick=shareLink); + copyBtn && (copyBtn.onclick=copyLink); + copyCoordsBtn && (copyCoordsBtn.onclick=copyCoords); + openBtn && (openBtn.onclick=()=>window.open(osmViewURL(state), "_blank")); + openGmapsBtn && (openGmapsBtn.onclick=()=>window.open(gmapsURL(state), "_blank")); + + // Pins + const loadPins=()=>{ try{ return JSON.parse(localStorage.getItem(LS_PINS)||"[]") }catch{ return [] } }; + const savePins=(pins)=>{ localStorage.setItem(LS_PINS, JSON.stringify(pins.slice(0,100))) }; + const renderPins=()=>{ + const pins=loadPins(); + pinlist.innerHTML=""; + if(!pins.length){ const li=document.createElement("li"); li.textContent="No pins yet."; pinlist.appendChild(li); return } + pins.forEach((p,idx)=>{ + const li=document.createElement("li"); + const head=document.createElement("div"); + head.innerHTML=`${p.name}
${p.lat.toFixed(5)}, ${p.lon.toFixed(5)} Β· ${p.layer}
`; + const actions=document.createElement("div"); actions.className="row"; + const go=button("Go",()=>{ pinsPane.style.display="none"; state.lat=p.lat; state.lon=p.lon; state.delta=p.delta; state.layer=p.layer; layerSel && (layerSel.value=p.layer); apply(true) }); + const share=button("Share",async()=>{ const url=appURL(p); if(navigator.share){ try{ await navigator.share({title:"PokeMaps Public Beta",url}) }catch{} } else { try{ await navigator.clipboard.writeText(url); alert("Link copied!") }catch{} } }); + const copyc=button("Copy Coords",()=>navigator.clipboard.writeText(`${p.lat.toFixed(6)},${p.lon.toFixed(6)}`).then(()=>alert("Copied!"))); + const ren=button("Rename",()=>{ const nv=prompt("New name:", p.name||""); if(nv!==null){ const arr=loadPins(); arr[idx].name=(nv||"").trim()||new Date().toLocaleString(); savePins(arr); renderPins() } }); + const del=button("Del",()=>{ if(confirmDeleteEl.checked){ if(!confirm("Delete pin?")) return } const arr=loadPins(); arr.splice(idx,1); savePins(arr); renderPins() }); + actions.append(go,share,copyc,ren,del); + li.append(head,actions); pinlist.appendChild(li); + }); + }; + function button(t,fn){ const b=document.createElement("button"); b.textContent=t; b.className="iconbtn"; b.onclick=fn; return b } + const nameFromState=()=> q.value?.trim() || new Date().toLocaleString(); + savepin.onclick=()=>{ const pins=loadPins(); pins.unshift({name:nameFromState(), lat:state.lat, lon:state.lon, delta:state.delta, layer:state.layer}); savePins(pins); renderPins(); pinsPane.style.display="block" }; + showpins.onclick=()=>{ renderPins(); pinsPane.style.display="block" }; + closepins.onclick=()=>{ pinsPane.style.display="none" }; + + // Panels (mobile/tablet only; desktop has sidebar) + menuBtn.onclick=()=>{ if(isDesktop()) return; menu.style.display="block" }; + closeMenu && (closeMenu.onclick=()=>{ menu.style.display="none" }); + opensettings.onclick=()=>{ if(isDesktop()) return; settings.style.display="block" }; + closesettings.onclick=()=>{ settings.style.display="none" }; + + // Prefs -> UI + toggleCoords.checked = !!prefs.showCoords; + coordsEl.style.display = prefs.showCoords ? "block" : "none"; + coordFmtEl.value = prefs.coordFmt || "dec"; + coordPrecEl.value = prefs.prec ?? 6; + coordPrecVal.textContent = String(prefs.prec ?? 6); + themeModeEl.value = prefs.theme || "auto"; + + autoFollowEl.checked = !!prefs.autoFollow; + shareDeltaEl.checked = prefs.includeDelta!==false; + confirmDeleteEl.checked = prefs.confirmDelete!==false; + + markerVisibleEl.checked = !prefs.markerHidden; + markerSizeEl.value = prefs.markerSize || 20; + markerSizeVal.textContent = markerSizeEl.value + "px"; + markerColorEl.value = prefs.markerColor || "#e53935"; + markerRingEl.checked = prefs.markerRing !== false; + ringWidthEl.value = prefs.ringWidth != null ? prefs.ringWidth : 3; + ringWidthVal.textContent = ringWidthEl.value + "px"; + markerStyleEl.value = prefs.markerStyle || "dot"; + applyMarkerStyle(markerStyleEl.value); + + accentColorEl.value = prefs.accent || "#0ea5e9"; + setAccent(prefs.accent || "#0ea5e9"); + + customCSSEl.value = prefs.userCSS || ""; + applyUserCSS(prefs.userCSS||""); + + document.querySelectorAll(".settings .ghead button").forEach(b=>{ + b.onclick=()=>{ const t=b.getAttribute("data-t"); const sec=document.querySelector(`.settings .section[data-sec="${t}"]`); sec.style.display=sec.style.display==="block"?"none":"block" } + }); + + // Pref listeners + markerVisibleEl.onchange=()=>{ markerEl.classList.toggle("hidden", !markerVisibleEl.checked); prefs.markerHidden = !markerVisibleEl.checked; savePrefs() }; + markerSizeEl.oninput=()=>{ document.documentElement.style.setProperty("--marker-size", markerSizeEl.value+"px"); markerSizeVal.textContent=markerSizeEl.value+"px"; prefs.markerSize=+markerSizeEl.value; savePrefs() }; + markerColorEl.oninput=()=>{ document.documentElement.style.setProperty("--marker-color", markerColorEl.value); prefs.markerColor=markerColorEl.value; savePrefs() }; + markerRingEl.onchange=()=>{ document.documentElement.style.setProperty("--marker-ring", markerRingEl.checked ? "rgba(229,57,53,.35)" : "transparent"); prefs.markerRing = markerRingEl.checked; savePrefs() }; + ringWidthEl.oninput=()=>{ document.documentElement.style.setProperty("--ring-width", ringWidthEl.value+"px"); ringWidthVal.textContent=ringWidthEl.value+"px"; prefs.ringWidth=+ringWidthEl.value; savePrefs() }; + markerStyleEl.onchange=()=>{ applyMarkerStyle(markerStyleEl.value); prefs.markerStyle=markerStyleEl.value; savePrefs() }; + + toggleCoords.onchange=()=>{ prefs.showCoords = toggleCoords.checked; coordsEl.style.display = prefs.showCoords ? "block" : "none"; savePrefs() }; + coordFmtEl.onchange=()=>{ prefs.coordFmt = coordFmtEl.value; savePrefs() }; + coordPrecEl.oninput=()=>{ prefs.prec = +coordPrecEl.value; coordPrecVal.textContent=String(prefs.prec); savePrefs() }; + autoFollowEl.onchange=()=>{ prefs.autoFollow = autoFollowEl.checked; savePrefs() }; + shareDeltaEl.onchange=()=>{ prefs.includeDelta = shareDeltaEl.checked; savePrefs() }; + confirmDeleteEl.onchange=()=>{ prefs.confirmDelete = confirmDeleteEl.checked; savePrefs() }; + themeModeEl.onchange=()=>{ prefs.theme = themeModeEl.value; applyTheme(prefs.theme); savePrefs() }; + + accentColorEl.oninput=()=>{ setAccent(accentColorEl.value); prefs.accent=accentColorEl.value; savePrefs() }; + accentResetEl.onclick=()=>{ const def="#0ea5e9"; accentColorEl.value=def; setAccent(def); prefs.accent=def; savePrefs() }; + + applyCSSEl.onclick=()=>{ const css=customCSSEl.value||""; prefs.userCSS=css; applyUserCSS(css); savePrefs() }; + clearCSSEl.onclick=()=>{ customCSSEl.value=""; prefs.userCSS=""; applyUserCSS(""); savePrefs() }; + + addEventListener("keydown",(e)=>{ + if(e.target.matches("input, textarea")) return; + if(e.key.toLowerCase()==="l"){ e.preventDefault(); locate() } + if(e.key.toLowerCase()==="s"){ e.preventDefault(); savepin.click() } + if(e.key.toLowerCase()==="h"){ e.preventDefault(); toggleFollow() } + if(e.key.toLowerCase()==="r"){ e.preventDefault(); reset() } + if(e.key.toLowerCase()==="1"){ e.preventDefault(); setLayer("mapnik") } + if(e.key.toLowerCase()==="2"){ e.preventDefault(); setLayer("cyclemap") } + if(e.key.toLowerCase()==="3"){ e.preventDefault(); setLayer("transportmap") } + if(e.key.toLowerCase()==="4"){ e.preventDefault(); setLayer("hot") } + if(e.key==="/"){ e.preventDefault(); q.focus() } + if(e.key==="Escape"){ menu.style.display="none"; settings.style.display="none"; pinsPane.style.display="none"; hideSuggest(true) } + }); + + addEventListener("popstate",e=>{ + stopFollow(); + if(e.state && typeof e.state.lat==="number"){ state=e.state; layerSel && (layerSel.value=state.layer); apply(false) } + else { parseURL(); layerSel && (layerSel.value=state.layer); apply(false) } + }); + + function loadPrefs(){ try{ return JSON.parse(localStorage.getItem(PREFS_KEY)||"{}") }catch{ return {} } } + function savePrefs(){ localStorage.setItem(PREFS_KEY, JSON.stringify(prefs)) } + + function applyPrefs(){ + if(prefs.markerSize) document.documentElement.style.setProperty("--marker-size", prefs.markerSize+"px"); + if(prefs.markerColor) document.documentElement.style.setProperty("--marker-color", prefs.markerColor); + document.documentElement.style.setProperty("--marker-ring", (prefs.markerRing===false) ? "transparent" : "rgba(229,57,53,.35)"); + document.documentElement.style.setProperty("--ring-width", (prefs.ringWidth!=null?prefs.ringWidth:3)+"px"); + if(prefs.markerHidden) markerEl.classList.add("hidden"); + applyMarkerStyle(prefs.markerStyle||"dot"); + setAccent(prefs.accent||"#0ea5e9"); + applyTheme(prefs.theme||"auto"); + // apply pro mode class on body + document.body.classList.toggle("pro-enabled", !!prefs.proMode); + } + function applyMarkerStyle(style){ markerEl.classList.toggle("crosshair", style==="crosshair") } + function setAccent(hex){ document.documentElement.style.setProperty("--accent",hex); themeColorMeta?.setAttribute("content",hex) } + + function applyTheme(mode){ + if(mode==="dark"){ document.documentElement.style.colorScheme="dark" } + else if(mode==="light"){ document.documentElement.style.colorScheme="light" } + else { document.documentElement.style.colorScheme="" } + } + + // PWA manifest (runtime-injected, no service worker) + (function injectManifest(){ + const manifest={ + name:"PokeMaps Public Beta", + short_name:"PokeMaps", + start_url: location.pathname, + display:"standalone", + background_color:"#000000", + theme_color:getComputedStyle(document.documentElement).getPropertyValue("--accent").trim() || "#0ea5e9", + icons:[ { src:"/css/yt-ukraine.svg", sizes:"any", type:"image/svg+xml", purpose:"any" } ] + }; + const blob=new Blob([JSON.stringify(manifest)],{type:"application/manifest+json"}); + const url=URL.createObjectURL(blob); + const link=document.createElement("link"); + link.rel="manifest"; link.href=url; + document.head.appendChild(link); + })(); + + // Custom CSS injector + function applyUserCSS(css){ + let tag=document.getElementById("user-css"); + if(!tag){ tag=document.createElement("style"); tag.id="user-css"; document.head.appendChild(tag) } + tag.textContent=css||""; + } + + // Init navigation + parseURL(); apply(false); + const urlHasLat = new URLSearchParams(location.search).has("lat"); + if(!urlHasLat){ locate() } + if(prefs.autoFollow) startFollow(); + + // Desktop sidebar builder (clean, with Pro toggle) + if(isDesktop()) buildDesktopSidebar(); + function buildDesktopSidebar(){ + const side=document.createElement("div"); side.className="sidebar"; + side.innerHTML=` +
+
+ Overview + +
+
+
+
+
+
+
Tip: / to focus search β€’ 1–4 change layers β€’ S save pin β€’ R reset
+
+ +
+
Marker
+
+
+
+
+
+
+
+ +
+
Pins
+
+
+ Recent: +
+
+
+ +
+
Display
+
+
+
+
+
+
+ +
+
Custom CSS
+
+ +
+ + +
+
+
+ +
+
About
+
Powered by openstreetmap.org β€’ Data Β© OSM contributors β€’ Public Beta
+
+ `; + document.body.appendChild(side); + + // Mirror search + const d_searchmirror=side.querySelector("#d_searchmirror"); + d_searchmirror.value=q.value||""; + d_searchmirror.addEventListener("input",()=>{ q.value=d_searchmirror.value; q.dispatchEvent(new Event("input",{bubbles:true})) }); + + // Pro toggle + const proToggle=side.querySelector("#pro_toggle"); + const updatePro=()=>{ prefs.proMode = proToggle.checked; savePrefs(); document.body.classList.toggle("pro-enabled", !!prefs.proMode) }; + proToggle.addEventListener("change",updatePro); + document.body.classList.toggle("pro-enabled", !!prefs.proMode); + + const d_layer=side.querySelector("#d_layer"); + side.querySelector("#d_osm").onclick=()=>window.open(osmViewURL(state),"_blank"); + side.querySelector("#d_copy").onclick=copyLink; + side.querySelector("#d_copy2").onclick=copyLink; + side.querySelector("#d_share").onclick=shareLink; + side.querySelector("#d_locate").onclick=locate; + side.querySelector("#d_follow").onclick=toggleFollow; + side.querySelector("#d_reset").onclick=reset; + side.querySelector("#d_gmaps").onclick=()=>window.open(gmapsURL(state), "_blank"); + d_layer.value=state.layer; + d_layer.onchange=()=>setLayer(d_layer.value); + + // Marker group + const d_markerv=side.querySelector("#d_markerv"); + const d_style=side.querySelector("#d_style"); + const d_ms=side.querySelector("#d_ms"), d_msv=side.querySelector("#d_msv"); + const d_mc=side.querySelector("#d_mc"); + const d_mr=side.querySelector("#d_mr"); + const d_rw=side.querySelector("#d_rw"), d_rwv=side.querySelector("#d_rwv"); + + d_markerv.checked=!prefs.markerHidden; + d_style.value=prefs.markerStyle||"dot"; + d_ms.value=markerSizeEl.value; d_msv.textContent=d_ms.value+"px"; + d_mc.value=markerColorEl.value; + d_mr && (d_mr.checked=markerRingEl.checked); + d_rw && (d_rw.value=ringWidthEl.value, d_rwv.textContent=d_rw.value+"px"); + + d_markerv.onchange=()=>{ markerVisibleEl.checked=d_markerv.checked; markerVisibleEl.onchange() }; + d_style.onchange=()=>{ markerStyleEl.value=d_style.value; markerStyleEl.onchange() }; + d_ms.oninput=()=>{ markerSizeEl.value=d_ms.value; markerSizeEl.oninput(); d_msv.textContent=d_ms.value+"px" }; + d_mc.oninput=()=>{ markerColorEl.value=d_mc.value; markerColorEl.oninput() }; + d_mr && (d_mr.onchange=()=>{ markerRingEl.checked=d_mr.checked; markerRingEl.onchange() }); + d_rw && (d_rw.oninput=()=>{ ringWidthEl.value=d_rw.value; ringWidthEl.oninput(); d_rwv.textContent=d_rw.value+"px" }); + + // Pins mini + const d_save=side.querySelector("#d_save"); + const d_showpins=side.querySelector("#d_showpins"); + const d_pinlistmini=side.querySelector("#d_pinlistmini"); + d_save.onclick=()=>savepin.click(); + d_showpins.onclick=()=>{ renderPins(); pinsPane.style.display="block" }; + + const renderPinsMini=()=>{ + d_pinlistmini.innerHTML=""; + const pins=loadPins().slice(0,6); + if(!pins.length){ d_pinlistmini.innerHTML='No pins yet.'; return } + pins.forEach((p,idx)=>{ + const row=document.createElement("div"); + row.style.display="flex"; row.style.gap="6px"; row.style.alignItems="center"; row.style.justifyContent="space-between"; + const txt=document.createElement("div"); + txt.innerHTML=`${p.name}
${p.lat.toFixed(5)}, ${p.lon.toFixed(5)}`; + const go=document.createElement("button"); go.className="iconbtn"; go.textContent="Go"; go.onclick=()=>{ state.lat=p.lat; state.lon=p.lon; state.delta=p.delta; state.layer=p.layer; layerSel && (layerSel.value=p.layer); apply(true) }; + row.append(txt,go); d_pinlistmini.appendChild(row); + }); + }; + renderPinsMini(); + + // Display group + const d_showc=side.querySelector("#d_showc"); + const d_fmt=side.querySelector("#d_fmt"); + const d_prec=side.querySelector("#d_prec"), d_precv=side.querySelector("#d_precv"); + const d_accent=side.querySelector("#d_accent"), d_accent_reset=side.querySelector("#d_accent_reset"); + d_showc.checked=!!prefs.showCoords; + d_fmt.value=prefs.coordFmt||"dec"; + d_prec && (d_prec.value=prefs.prec??6, d_precv.textContent=String(prefs.prec??6)); + d_accent.value=prefs.accent||"#0ea5e9"; + d_showc.onchange=()=>{ toggleCoords.checked=d_showc.checked; toggleCoords.onchange() }; + d_fmt.onchange=()=>{ coordFmtEl.value=d_fmt.value; coordFmtEl.onchange() }; + d_prec && (d_prec.oninput=()=>{ coordPrecEl.value=d_prec.value; coordPrecEl.oninput(); d_precv.textContent=d_prec.value }); + d_accent.oninput=()=>{ accentColorEl.value=d_accent.value; accentColorEl.oninput() }; + d_accent_reset.onclick=()=>{ accentResetEl.click(); d_accent.value=accentColorEl.value }; + + // Custom CSS + const d_usercss=side.querySelector("#d_usercss"); + const d_applycss=side.querySelector("#d_applycss"); + const d_clearcss=side.querySelector("#d_clearcss"); + if(d_usercss){ d_usercss.value=prefs.userCSS||""; d_applycss.onclick=()=>applyCSSEl.onclick(); d_clearcss.onclick=()=>clearCSSEl.onclick() } + } + + function tickCoords(){ updateCoordsFast(); setTimeout(tickCoords,120) } + tickCoords(); + })(); + + + + + \ No newline at end of file