You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
332 lines
14 KiB
HTML
332 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>FixPhrase</title>
|
|
<link rel="icon" href="img/favicon.png" />
|
|
<link rel=“canonical” href=“https://fixphrase.com” />
|
|
<link rel="stylesheet" href="https://static.netsyms.net/bootstrap/5/bootstrap.quartz.min.css" />
|
|
<link rel="stylesheet" href="js/maplibre-gl/dist/mapbox-gl.css" />
|
|
<meta property="og:title" content="FixPhrase">
|
|
<meta property="og:description" content="Describe and locate any place on Earth with just four words.">
|
|
<meta property="og:image" content="https://fixphrase.com/img/socialcard.png">
|
|
<meta property="og:url" content="https://fixphrase.com">
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<script src="https://static.netsyms.net/jquery/jquery.min.js"></script>
|
|
<script src="https://static.netsyms.net/bootstrap/5/bootstrap.bundle.min.js"></script>
|
|
<script src="js/fixphrase.js"></script>
|
|
<script src="js/map.js"></script>
|
|
<script src="js/maplibre-gl/dist/mapbox-gl.js"></script>
|
|
<script src="js/map_maplibre.js"></script>
|
|
<script src="js/map.js"></script>
|
|
<style>
|
|
|
|
body {
|
|
background-attachment: fixed;
|
|
}
|
|
|
|
@media (min-width: 1200px) and (max-width: 1499px) {
|
|
#page-container {
|
|
padding-left: 10rem;
|
|
padding-right: 10rem;
|
|
}
|
|
}
|
|
|
|
@media (min-width: 1500px) {
|
|
#page-container {
|
|
padding-left: 15rem;
|
|
padding-right: 15rem;
|
|
}
|
|
}
|
|
|
|
#mapcard {
|
|
flex-grow: 9999;
|
|
max-height: 90vh;
|
|
height: 800px;
|
|
}
|
|
|
|
#mapbox .mapboxgl-user-location-dot, #mapbox .mapboxgl-user-location-accuracy-circle {
|
|
pointer-events: none;
|
|
}
|
|
|
|
#header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
flex-grow: 1;
|
|
padding: 1em;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip {
|
|
border-top-color: rgba(255, 255, 255, 0.4);
|
|
border-width: 0.5rem 0.5rem 0;
|
|
}
|
|
.mapboxgl-popup-content {
|
|
background-image: linear-gradient(125deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.3) 70%);
|
|
box-shadow: inset 1px 1px rgba(255, 255, 255, 0.2), inset -1px -1px rgba(255, 255, 255, 0.1), 1px 3px 24px -1px rgba(0, 0, 0, 0.15);
|
|
background-color: transparent;
|
|
border: none;
|
|
border-radius: 0.5rem;
|
|
background-clip: border-box;
|
|
color: black;
|
|
}
|
|
.mapboxgl-ctrl-attrib, .mapboxgl-ctrl-attrib-inner a {
|
|
color: black !important;
|
|
}
|
|
|
|
.nav-pills .nav-link {
|
|
background-color: rgba(50,50,50,0.7);
|
|
|
|
}
|
|
.nav-pills .nav-link.active {
|
|
background-color: rgba(0,0,0,0.9);
|
|
}
|
|
|
|
#page-container {
|
|
height: 100%;
|
|
width: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
}
|
|
.copyonclick {
|
|
cursor: pointer;
|
|
}
|
|
.clicktext {
|
|
display: none;
|
|
}
|
|
@media (pointer:fine) {
|
|
.taptext {
|
|
display: none;
|
|
}
|
|
.clicktext {
|
|
display: initial;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<!-- Matomo -->
|
|
<script type="text/javascript">
|
|
var _paq = window._paq = window._paq || [];
|
|
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
|
_paq.push(['trackPageView']);
|
|
_paq.push(['enableLinkTracking']);
|
|
(function () {
|
|
var u = "https://analytics.netsyms.net/";
|
|
_paq.push(['setTrackerUrl', u + 'matomo.php']);
|
|
_paq.push(['setSiteId', '35']);
|
|
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
|
|
g.type = 'text/javascript';
|
|
g.async = true;
|
|
g.src = u + 'matomo.js';
|
|
s.parentNode.insertBefore(g, s);
|
|
})();
|
|
</script>
|
|
<!-- End Matomo Code -->
|
|
|
|
</head>
|
|
<body>
|
|
<nav class="navbar navbar-expand-sm navbar-dark bg-dark">
|
|
<div class="container-fluid">
|
|
<a class="navbar-brand" href=".">
|
|
<img src="img/logo.128.png" alt="" width="48" height="48" class="d-inline-block align-text-middle">
|
|
FixPhrase
|
|
</a>
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
|
|
<div class="collapse navbar-collapse" id="navbarNav">
|
|
<ul class="navbar-nav ms-auto">
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="https://source.netsyms.com/Netsyms/fixphrase.com/wiki/How-It-Works">How it Works</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="https://source.netsyms.com/Netsyms/fixphrase.com">Open Source</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<div class="container mw-100" id="page-container">
|
|
<div class="card mb-2 mt-2 border-secondary">
|
|
<div class="card-header text-dark">
|
|
Locate any place on Earth with just four words.
|
|
<span class="taptext">Tap</span><span class="clicktext">Click</span> the map to
|
|
get the unique FixPhrase for that spot. Type a FixPhrase into the search box to
|
|
pinpoint it on the map.
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="input-group d-none d-md-flex">
|
|
<input class="form-control" type="text" placeholder="Enter FixPhrase or Address" id="wordbox"/>
|
|
<button class="btn btn-secondary" onclick="dolookup($('#wordbox').val());">Find on Map</button>
|
|
</div>
|
|
<div class="d-grid d-md-none gap-2">
|
|
<input class="form-control" type="text" placeholder="Enter FixPhrase or Address" id="wordbox-mobile"/>
|
|
<button class="btn btn-secondary btn-block" onclick="dolookup($('#wordbox-mobile').val());">Find on Map</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card mb-2 border-secondary" id="mapcard">
|
|
<a name="map"></a>
|
|
<div class="card-body p-2">
|
|
<div id="mapbox" class="w-100"></div>
|
|
<ul class="nav nav-pills pt-2" id="map-style-switcher">
|
|
<li class="nav-item p-1">
|
|
<a class="nav-link active" href="" data-style="street">Light</a>
|
|
</li>
|
|
<li class="nav-item p-1">
|
|
<a class="nav-link" href="" data-style="dark">Dark</a>
|
|
</li>
|
|
<li class="nav-item p-1">
|
|
<a class="nav-link" href="" data-style="terrain">Topo</a>
|
|
</li>
|
|
<li class="nav-item p-1">
|
|
<a class="nav-link" href="" data-style="satellite">Satellite</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
window.onload = function () {
|
|
$("#mapbox").css("height", "calc(100% - " + $("#map-style-switcher").css("height") + ")");
|
|
|
|
createMap();
|
|
|
|
var bgs = [
|
|
"dale-nibbe-GR09HcWwP-w-unsplash.jpg",
|
|
"hide-obara-VzWx1l2LuIA-unsplash.jpg",
|
|
"john-fowler-jcbq3qWpKoo-unsplash.jpg",
|
|
"mark-harpur-K2s_YE031CA-unsplash.jpg",
|
|
"renns-art-TXhxOXHN1EE-unsplash.jpg",
|
|
"solotravelgoals-7kLufxYoqWk-unsplash.jpg"
|
|
];
|
|
var bgimg = bgs[Math.floor(Math.random() * bgs.length)];
|
|
$("body").css("background-image", "url(./img/bg/" + bgimg + ")");
|
|
|
|
map.resize();
|
|
|
|
// Load style preference from cookie
|
|
var cookies = decodeURIComponent(document.cookie).split("; ");
|
|
cookies.forEach(val => {
|
|
if (val.indexOf("mapstyle") === 0) {
|
|
var style = val.substring(9);
|
|
setMapStyle(style);
|
|
$("#map-style-switcher a.nav-link").removeClass("active");
|
|
$("#map-style-switcher a.nav-link[data-style=" + style + "]").addClass("active");
|
|
}
|
|
});
|
|
|
|
$("body").on("click", ".copyonclick", function () {
|
|
var copyitem = $(this);
|
|
var copytext = copyitem.text();
|
|
if (copytext == "Copied to clipboard!") {
|
|
// prevent copying copied text if double-clicked
|
|
return;
|
|
}
|
|
navigator.clipboard.writeText(copytext).then(() => {
|
|
copyitem.text("Copied to clipboard!");
|
|
setTimeout(function () {
|
|
copyitem.text(copytext);
|
|
}, 1000);
|
|
});
|
|
});
|
|
|
|
$("body").on("keypress", "#wordbox,#wordbox-mobile", function (e) {
|
|
if (e.which == 13) {
|
|
dolookup($(this).val());
|
|
}
|
|
});
|
|
|
|
$("#map-style-switcher").on("click", "a.nav-link", function (e) {
|
|
e.preventDefault();
|
|
$("#map-style-switcher a.nav-link").removeClass("active");
|
|
setMapStyle($(this).data("style"));
|
|
$(this).addClass("active");
|
|
|
|
// Save style preference in cookie
|
|
var date = new Date();
|
|
date.setTime(date.getTime() + (90 * 24 * 60 * 60 * 1000));
|
|
document.cookie = "mapstyle=" + $(this).data("style") + "; expires=" + date.toUTCString();
|
|
});
|
|
|
|
// Read URL hash and try to parse it
|
|
window.addEventListener('hashchange', function () {
|
|
parseWindowHash();
|
|
}, false);
|
|
// Don't try to read hash until map is loaded, this prevents errors
|
|
var checkIfMapLoaded = function () {
|
|
if (map.isStyleLoaded()) {
|
|
parseWindowHash();
|
|
} else {
|
|
setTimeout(checkIfMapLoaded, 200);
|
|
}
|
|
};
|
|
checkIfMapLoaded();
|
|
};
|
|
|
|
function dolookup(words) {
|
|
try {
|
|
words = words.trim().toLowerCase().replace(/\s+/g, ' ');
|
|
|
|
if (!/^[a-z ]+?$/i.test(words)) {
|
|
// Not a FixPhrase, run a search
|
|
$.getJSON("lookup.php", {
|
|
search: words
|
|
}, function (resp) {
|
|
if (resp.status == "OK") {
|
|
lookupAndShowCoords(resp.coords[0], resp.coords[1]);
|
|
} else {
|
|
alert("Error: " + resp.msg);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
var coords = FixPhrase.decode(words);
|
|
|
|
showLocationPopup(coords[0], coords[1], coords[3], coords[2]);
|
|
$("#wordbox").val(coords[3]);
|
|
$("#wordbox-mobile").val(coords[3]);
|
|
|
|
var zoomlevel = 18;
|
|
switch (coords[2]) {
|
|
case 0.1:
|
|
zoomlevel = 10;
|
|
break;
|
|
case 0.01:
|
|
zoomlevel = 13;
|
|
break;
|
|
}
|
|
map.animateMapIn(coords[0], coords[1], zoomlevel);
|
|
} catch (e) {
|
|
alert(e);
|
|
}
|
|
}
|
|
|
|
function parseWindowHash() {
|
|
var hash = window.location.hash.substr(1);
|
|
if (/^-?[0-9]{1,2}\.?[0-9]*,-?[0-9]{1,3}\.?[0-9]*$/.test(hash)) {
|
|
var lat = hash.split(",")[0];
|
|
var lon = hash.split(",")[1];
|
|
lat = (Math.round(lat * 10000) / 10000);
|
|
lon = (Math.round(lon * 10000) / 10000);
|
|
lookupAndShowCoords(lat, lon);
|
|
} else if (/^[a-z]+\-[a-z]+\-?[a-z]+?\-?[a-z]+?$/.test(hash)) {
|
|
var words = hash.replaceAll("-", " ");
|
|
dolookup(words);
|
|
$("#wordbox").val(words);
|
|
$("#wordbox-mobile").val(words);
|
|
} else if (/^[a-z]+\ [a-z]+\ ?[a-z]+?\ ?[a-z]+?$/.test(decodeURI(hash))) {
|
|
var words = decodeURI(hash);
|
|
dolookup(words);
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|