|
838 | 838 |
|
839 | 839 | function closeStation() { const d = dialog(); if (d.open) d.close(); } |
840 | 840 |
|
| 841 | + /* Deep links: #station=<repo> opens that entry, so other team sites (the web book, for one) can link straight to it. */ |
| 842 | + const stationFromHash = () => { |
| 843 | + const m = location.hash.match(/^#station=(.+)$/); |
| 844 | + return m ? decodeURIComponent(m[1]) : null; |
| 845 | + }; |
| 846 | + function openFromHash() { |
| 847 | + const id = stationFromHash(); |
| 848 | + if (!id || !state.repos.has(id)) return; |
| 849 | + const r = state.repos.get(id); |
| 850 | + const lv = r.level && r.kind !== "paid" ? r.level : null; |
| 851 | + $("#curriculum").scrollIntoView({ behavior: "auto" }); |
| 852 | + openStation(id); |
| 853 | + if (lv) dialog().addEventListener("close", () => gotoItem(id), { once: true }); |
| 854 | + } |
| 855 | + |
841 | 856 | function toggleRide(id) { |
842 | 857 | if (state.ridden.has(id)) state.ridden.delete(id); else state.ridden.add(id); |
843 | 858 | saveRidden(); |
|
870 | 885 | if (open) { e.preventDefault(); openStation(open.dataset.open); } |
871 | 886 | }); |
872 | 887 | dialog().addEventListener("click", (e) => { if (e.target === dialog()) closeStation(); }); |
| 888 | + dialog().addEventListener("close", () => { |
| 889 | + if (stationFromHash()) history.replaceState(null, "", location.pathname + location.search); |
| 890 | + }); |
| 891 | + window.addEventListener("hashchange", openFromHash); |
873 | 892 | let t; |
874 | 893 | window.addEventListener("resize", () => { |
875 | 894 | clearTimeout(t); |
|
918 | 937 | renderLegend(); renderMap(); wireTabs(); |
919 | 938 | renderFeatured(); renderPartner(); renderEvents(); renderArticles(); |
920 | 939 | if (location.hash === "#contrib") selectTab("tab-contrib"); |
| 940 | + openFromHash(); |
921 | 941 | navSpy(); |
922 | 942 | refreshStars(); |
923 | 943 | } |
|
0 commit comments