about summary refs log tree commit diff
path: root/v0/map.js
diff options
context:
space:
mode:
Diffstat (limited to 'v0/map.js')
-rw-r--r--v0/map.js204
1 files changed, 204 insertions, 0 deletions
diff --git a/v0/map.js b/v0/map.js
new file mode 100644
index 0000000..7458e07
--- /dev/null
+++ b/v0/map.js
@@ -0,0 +1,204 @@
+// Some Levenshtein-distnace code
+// http://www.merriampark.com/ld.htm, http://www.mgilleland.com/ld/ldjavascript.htm, Damerau–Levenshtein distance (Wikipedia)
+var levDist = function(s, t) {
+    var d = [] //2d matrix
+
+    // Step 1
+    var n = s.length
+    var m = t.length
+
+    if (n == 0) return m
+    if (m == 0) return n
+
+    // Create an array of arrays in javascript (a descending loop is quicker)
+    for (var i = n; i >= 0; i--) d[i] = []
+
+    // Step 2
+    for (var i = n; i >= 0; i--) d[i][0] = i
+    for (var j = m; j >= 0; j--) d[0][j] = j
+
+    // Step 3
+    for (var i = 1; i <= n; i++) {
+        var s_i = s.charAt(i - 1)
+
+        // Step 4
+        for (var j = 1; j <= m; j++) {
+            // Check the jagged ld total so far
+            if (i == j && d[i][j] > 4) return n
+
+            var t_j = t.charAt(j - 1)
+            var cost = s_i == t_j ? 0 : 1 // Step 5
+
+            // Calculate the minimum
+            var mi = d[i - 1][j] + 1
+            var b = d[i][j - 1] + 1
+            var c = d[i - 1][j - 1] + cost
+
+            if (b < mi) mi = b
+            if (c < mi) mi = c
+
+            d[i][j] = mi // Step 6
+
+            // Damerau transposition
+            if (
+                i > 1 &&
+                j > 1 &&
+                s_i == t.charAt(j - 2) &&
+                s.charAt(i - 2) == t_j
+            ) {
+                d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost)
+            }
+        }
+    }
+
+    // Step 7
+    return d[n][m]
+}
+
+var things = {}
+
+$(function() {
+    var marker
+    var Icon = L.icon({
+        iconUrl: "leaflet/images/marker-icon-red.png",
+        iconSize: [25, 41],
+        iconAnchor: [12, 41],
+        popupAnchor: [1, -34],
+        shadowSize: [41, 41],
+        shadowUrl: "leaflet/images/marker-shadow.png",
+    })
+
+    var res = $("#result")
+    var search = $("#searchtext")
+    function performSearch() {
+        var searchstring = search.val().toLowerCase()
+        var searchresult = Object.keys(things).sort(function(a, b) {
+            return (
+                levDist(searchstring, a.toLowerCase()) -
+                levDist(searchstring, b.toLowerCase())
+            )
+        })
+        var html = ""
+        for (var i = 0; i < Math.min(searchresult.length, 10); i++) {
+            html += "<li>" + searchresult[i] + "</li>"
+        }
+
+        if (html != "") res.show()
+        else res.hide()
+        if (things[search]) {
+            addMarker(things[search])
+            $("#btnmarker").addClass("active")
+            setHash()
+        }
+        $("#result ul").html(html)
+        $("#result ul li:first").addClass("selected")
+        $("#result ul li").click(function() {
+            select($(this).text())
+        })
+        res.css({
+            top: search.position().top + search.height() + 10,
+            left: search.position().left,
+        })
+    }
+
+    function select(text) {
+        addMarker(things[text])
+        $("#btnmarker").addClass("active")
+        setHash()
+        res.hide()
+    }
+
+    $("#searchtext").keypress(function(e) {
+        switch (e.keyCode) {
+            case 13: // Enter
+                var selected = $("#result ul li.selected").first()
+                if (selected) selected.click()
+                break
+            default:
+                setTimeout(performSearch, 10)
+        }
+    })
+
+    var map = L.map("map", {
+        minZoom: 0,
+        maxZoom: 4,
+        zoom: 2,
+        center: [0, 0],
+    })
+
+    L.tileLayer("/tiles/{z}/{x}/{y}.jpg", {
+        attribution:
+            'Original project by <a href="https://github.com/blinry/">blinry<a> (<a href="https://github.com/blinry/map.recurse.com">source</a>) | <a href="#">Source</a>',
+        noWrap: false,
+        detectRetina: true,
+    }).addTo(map)
+
+    $("#btnmarker").on("click", function(event) {
+        setTimeout(function() {
+            var button = $(event.currentTarget)
+            if (button.hasClass("active")) {
+                addMarker()
+            } else {
+                removeMarker()
+            }
+        }, 0)
+    })
+
+    setTimeout(getHash, 0)
+
+    function getHash() {
+        var hash = window.location.hash
+        if (hash) {
+            hash = hash.match(/([\-0-9]*)_([\-0-9]*)/)
+            if (hash) {
+                var pos = [
+                    parseInt(hash[1], 10) / 1000,
+                    parseInt(hash[2], 10) / 1000,
+                ]
+                addMarker(pos)
+                $("#btnmarker").addClass("active")
+            }
+        }
+    }
+
+    function addMarker(pos) {
+        removeMarker()
+        if (pos) {
+            map.setView(pos, 2)
+            marker = L.marker(pos, {
+                icon: Icon,
+            })
+            marker.addTo(map)
+        } else {
+            marker = L.marker(map.getCenter(), {
+                draggable: true,
+                opacity: 0.7,
+                icon: Icon,
+            })
+            marker.on("dragend", setHash)
+            setHash()
+            marker.addTo(map)
+        }
+    }
+
+    function removeMarker() {
+        if (marker) {
+            map.removeLayer(marker)
+            marker = false
+            setHash()
+        }
+    }
+
+    function setHash() {
+        if (marker) {
+            var pos = marker.getLatLng()
+            pos = [
+                (1000 * pos.lat).toFixed(0),
+                (1000 * pos.lng).toFixed(0),
+            ].join("_")
+            window.location.hash = pos
+        } else {
+            window.location.hash = ""
+        }
+    }
+})