Geodata in ABS ============== The Model API of ABS lets us display information in various ways. This example shows how to display geo-annotated ABS data on a map. To display the map in a browser, we use `OpenStreetmap `__ via the `Leaflet `__ library. The complete code for this example is at ``__. In OpenStreetmap, coordinates are expressed as a ``(lat, long)`` pair of floating point numbers. We model map data as ``MapData(Float lat, Float long, String description)``, which is then returned from the Model API. The complete code of the ABS part is as follows:: module MapObjects; data MapData = MapData(Float lat, Float long, String description); interface OMap { [HTTPCallable] Pair getInitialCoordinates(); [HTTPCallable] List getMapObjects(); } class OMap implements OMap { Pair getInitialCoordinates() { return Pair(59.90, 10.73); } List getMapObjects() { return list[MapData(59.91115, 10.7357, "City Hall"), MapData(59.90758, 10.75197, "Opera House")]; } } { [HTTPName: "map"] OMap m = new OMap(); } Accessing and displaying coordinates ------------------------------------ When the running model is accessed from a browser, the ``createMap`` function in the model's `index.html `__ file is called. This function creates a map, sets its initial location according to the ``getInitialCoordinates`` method (Lines 6-12), then adds the objects returned by the ``getMapObjects`` method (Lines 14-17). Both of these ABS methods are called from JavaScript code in ``createMap`` (Lines 2, 3): .. code:: javascript function createMap() { Promise.all([fetch("/call/map/getInitialCoordinates"), fetch("/call/map/getMapObjects")]) .then((values) => values.map(p => p.json())).then((p) => Promise.all(p)) .then(([coords, objects]) => { var mymap = L.map('mapid').setView([coords.result.fst, coords.result.snd], 13); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '© OpenStreetMap contributors' }).addTo(mymap); L.control.scale().addTo(mymap); objects.result.forEach(item => L.marker([item.lat, item.long]) .addTo(mymap) .bindPopup(item.description)); var popup = L.popup(); function onMapClick(e) { popup.setLatLng(e.latlng) .setContent("You clicked the map at " + e.latlng.toString()) .openOn(mymap); } mymap.on('click', onMapClick); }); } Running the example ------------------- Because the model includes a custom html page and support library, the compiler needs to run with the ``--modelapi-index-file`` and ``--modelapi-static-dir`` arguments. See the `Makefile `__ for the commands to compile and run the example on the Erlang or Java backend. After starting the model, the map can be accessed at ``http://localhost:8080``. .. figure:: images/geo-abs.png :alt: A map of Oslo with two points of interest A map of Oslo with two points of interest