Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to use Leaflet instead of MapquestAPI #105

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Aufgabe1/gta_v1/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GeoTagApp</title>
<link rel="stylesheet" href="./stylesheets/style.css" />
<link
rel="stylesheet"
href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css"
/>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>

Expand Down Expand Up @@ -54,7 +61,7 @@ <h2 class="discovery__title">Discovery</h2>
</ul>
</div>

<div class="discovery__map">
<div class="discovery__map" id="map">
<img src="./images/mapview.jpg" alt="a map with locations" id="mapView" />
<span>Result map</span>
</div>
Expand Down
5 changes: 5 additions & 0 deletions Aufgabe1/gta_v1/public/stylesheets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ a {
color: var(--link-color);
}

#map {
height: 500px;
width: 600px;
}

/* ### TODO ### Styles for other HTML elements */

/* ... your code here ... */
Expand Down
13 changes: 6 additions & 7 deletions Aufgabe2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ Rufen sie die neue `updateLocation`-Funktion nach dem Laden des Dokuments automa

### 2. Teilaufgabe: Position auf Karte darstellen

Wir wollen nun die gefundene Position auf einer Karte darstellen. Konkret werden wir zu diesem Zweck *MapQuest* verwenden, ein - für unsere Zwecke - kostenfreier Dienst um statische Karten anzuzeigen. Zunächst benötigen sie einen **API-Schlüssel** für die [MapQuestApi](https://developer.mapquest.com/user/login/sign-up) (kostenlos). Registrieren sie sich dort, erstellen sie eine App ('Callback URL' kann leer bleiben) und notieren sie sich den Key ('Consumer Key').
Wir wollen nun die gefundene Position auf einer Karte darstellen. Konkret werden wir zu diesem Zweck *Leaflet* verwenden, ein - für unsere Zwecke - kostenfreier Dienst um dynamische Karten anzuzeigen.

Die Klasse `MapManager` enthält einige Hilfsfunktionen zur Verwendung von MapQuest. Um eine Instanz zu erzeugen, wird der Konstruktor mit dem MapQuest API-Key aufgerufen. Dann kann die Methode `getMapUrl` verwendet werden, um die URL einer gewünschten Karte abzufragen. Die Karte selbst erhält man schließlich durch einen HTTP Request.
Die Klasse `MapManager` enthält einige Hilfsfunktionen zur Verwendung von MapQuest. Um eine Instanz zu erzeugen, wird der Konstruktor aufgerufen. Dann kann die Methode `initMap` verwendet werden, um die Karte mit der aktuellen Position zu initialisieren. Mit der Funktion `updateMarkers` werden die übergebenen GeoTags auf der Karte als Marker angezeigt. Beim Aufruf der Methode werden die zuvor vorhandenen Marker entfernt.

Ergänzen sie ihre `updateLocation`-Funktion im wie folgt:

- Rufen sie die Funktion `getMapUrl` mit den aktuellen Koordinaten auf. Das Ergebnis ist eine **URL** auf die Karte.
- Rufen sie die Funktionen `initMap` und `updateMarkers` mit den aktuellen Koordinaten auf. Daraufhin wird die Karte in Ihrer App angezeigt.
- Suchen sie im DOM das **Image Element** auf der Webseite.
- Ändern sie per DOM Aufruf das `src`-Attribut auf die neue URL.
- Leeren Sie das `src`-Attribut, sodass das Bild einer Karte, das beim Initialisieren der App hinzugefügt wurde, wieder entfernt wird.

## Checkliste

Expand All @@ -82,7 +82,6 @@ Zur Übersicht folgen noch mal alle Anforderungen in kompakter Form als Checklis

### 2. Teilaufgabe: Karte darstellen

- [ ] MapQuest API-Schlüssel besorgen und eintragen
- [ ] `updateLocation`-Funktion ergänzen
- [ ] Funktion `getMapUrl` aufrufen
- [ ] URL im `src`-Attribut des Image Elements eintragen
- [ ] Funktionen `initMap` und `updateMarkers` aufrufen
- [ ] `src`-Attribut leeren, um Bild zu entfernen
59 changes: 33 additions & 26 deletions Aufgabe2/gta_v2/public/javascripts/geotagging.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,40 +60,47 @@ class LocationHelper {
}

/**
* A class to help using the MapQuest map service.
* A class to help using the Leaflet map service.
*/
class MapManager {
#apiKey = '';

#map
#markers

/**
* Create a new MapManager instance.
* @param {string} apiKey Your MapQuest API Key
*/
constructor(apiKey) {
this.#apiKey = apiKey;
* Initialize a Leaflet map
* @param {number} latitude The map center latitude
* @param {number} longitude The map center longitude
* @param {number} zoom The map zoom, defaults to 18
*/
initMap(latitude, longitude, zoom = 18) {
this.#map = L.map('map').setView([latitude, longitude], 8);
var mapLink = '<a href="http://openstreetmap.org">OpenStreetMap</a>';
L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; ' + mapLink + ' Contributors',
maxZoom: zoom,}).addTo(this.#map);
this.#markers = L.layerGroup().addTo(this.#map);
}

/**
* Generate a MapQuest image URL for the specified parameters.
* @param {number} latitude The map center latitude
* @param {number} longitude The map center longitude
* @param {{latitude, longitude, name}[]} tags The map tags, defaults to just the current location
* @param {number} zoom The map zoom, defaults to 10
* @returns {string} URL of generated map
*/
getMapUrl(latitude, longitude, tags = [], zoom = 10) {
if (this.#apiKey === '') {
console.log("No API key provided.");
return "images/mapview.jpg";
* Update the Markers of a Leaflet map
* @param {number} latitude The map center latitude
* @param {number} longitude The map center longitude
* @param {{latitude, longitude, name}[]} tags The map tags, defaults to just the current location
* @param {number} zoom The map zoom, defaults to 18
*/
updateMarkers(latitude, longitude, tags = [], zoom = 18) {
// delete all markers
this.#markers.clearLayers();
L.marker([latitude, longitude])
.bindPopup("Your Location")
.addTo(this.#markers);
for (const tag of tags) {
L.marker([tag.location.latitude,tag.location.longitude])
.bindPopup(tag.name)
.addTo(this.#markers);
}

let tagList = `${latitude},${longitude}|marker-start`;
tagList += tags.reduce((acc, tag) => `${acc}||${tag.latitude},${tag.longitude}|flag-${tag.name}`, "");

const mapQuestUrl = `https://www.mapquestapi.com/staticmap/v5/map?key=${this.#apiKey}&size=600,400&zoom=${zoom}&center=${latitude},${longitude}&locations=${tagList}`;
console.log("Generated MapQuest URL:", mapQuestUrl);

return mapQuestUrl;
}
}

Expand Down
9 changes: 4 additions & 5 deletions Aufgabe3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ Die Aufgabe besteht nun in der Entwicklung der Serverskripte. Die Clientseite (B
Der Server besteht in dieser Aufgabe aus mehreren **Express.js** Serverskripten zur Verarbeitung von HTTP-Requests und einem **EJS Template** zur dynamischen Erzeugung von neuen HTML-Seitendarstellungen.

Die Serverimplementierung hat die folgende Struktur:

- `bin` (Ordner für ausführbare Skripte)
- `www` (Startskript des Servers)
- `models` (Ordner für JavaScript-Module zur anwendungsspezifischen Datenhaltung und -verarbeitung)
Expand Down Expand Up @@ -109,15 +108,15 @@ Die Lösung haben wir in der letzten Teilaufgabe schon vorbereitet: Der Server s

### 3.2.3 `data-*`-Attribute und Map Marker

Die `getMapUrl`-Methode der `MapManager`-Klasse besitzt einen Parameter, dem man einen Array von GeoTag Objekten übergeben kann. Wenn dieser vorliegt, werden an den Positionen der GeoTags Marker in die Karte eingetragen, d.h. die Tags werden auf der Karte sichtbar.
Die `updateMarkers`-Methode der `MapManager`-Klasse besitzt einen Parameter, dem man einen Array von GeoTag Objekten übergeben kann. Wenn dieser vorliegt, werden an den Positionen der GeoTags Marker in die Karte eingetragen, d.h. die Tags werden auf der Karte sichtbar.

Das Problem ist nun, im Client Skript das Array mit GeoTag Objekten verfügbar zu machen. Diese Information liegt im Server schon vor. Wie aber kommen die Daten zum Client? In der nächsten Aufgabe werden wir zu diesem Zweck AJAX-Abfragen einführen. An dieser Stelle wollen wir noch eine andere Variante kennenlernen:

Der Server kann das Array mit GeoTag Objekten als `data-*`-Attribut einem geeigneten Element beifügen. Erweitern sie dazu das EJS-Template derart, dass es dem `img`-Element der Karte ein `data-tags`-Attribut beifügt. In das Attribut schreiben sie das Array mit GeoTag Objekten als JSON-String. Für ein Array `taglist` erzeugt der Aufruf `JSON.stringify(taglist)` den JSON-String.

Auf der Clientseite können sie dann das Attribut aus dem DOM lesen und den string wieder in ein Array Objekt umwandeln. Für einen JSON-String `taglist_json` erzeugt der Aufruf `JSON.parse(taglist_json)` das korrespondierende JavaScript Array Objekt. Dieses Array Objekt können sie der `getMapUrl`-Methode als Parameter übergeben.
Auf der Clientseite können sie dann das Attribut aus dem DOM lesen und den string wieder in ein Array Objekt umwandeln. Für einen JSON-String `taglist_json` erzeugt der Aufruf `JSON.parse(taglist_json)` das korrespondierende JavaScript Array Objekt. Dieses Array Objekt können sie der `updateMarkers`-Methode als Parameter übergeben.

**Aufgabe:** Erweitern Sie den Aufruf der `getMapUrl`-Methode aus der `updateLocation`-Funktion und übergeben sie neben der aktuellen Position des Clients zusätzlich einen Array von GeoTag Objekten des aktuellen Suchergebnisses im Discovery Widget. Auf der Karte sollen dann für alle Elemente der Ergebnisliste entsprechende Marker angezeigt werden.
**Aufgabe:** Erweitern Sie den Aufruf der `updateMarkers`-Methode aus der `updateLocation`-Funktion und übergeben sie neben der aktuellen Position des Clients zusätzlich einen Array von GeoTag Objekten des aktuellen Suchergebnisses im Discovery Widget. Auf der Karte sollen dann für alle Elemente der Ergebnisliste entsprechende Marker angezeigt werden.

## Checkliste

Expand Down Expand Up @@ -151,5 +150,5 @@ Zur Übersicht folgen noch mal alle Anforderungen in kompakter Form als Checklis

- [ ] EJS-Template mit `data-*`-Attribut erweitern
- [ ] Im `img`-Element ein `data-tags`-Attribut erstellen und **Array mit GeoTag Objekten als JSON-String** einfügen
- [ ] Aufruf von `getMapUrl` aus `updateLocation` erweitern
- [ ] Aufruf von `updateMarkers` aus `updateLocation` erweitern
- [ ] Array mit GeoTag Objekten übergeben und **Map Marker anzeigen**
16 changes: 16 additions & 0 deletions Aufgabe3/gta_v3/public/images/marker-shadow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions Aufgabe3/gta_v3/public/images/marker.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 49 additions & 28 deletions Aufgabe3/gta_v3/public/javascripts/map-manager.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,61 @@
// File origin: VS1LAB A2

/**
* A class to help using the MapQuest map service.
* from VS1LAB A3
*
* A class to help using the Leaflet map service.
*/
// eslint-disable-next-line no-unused-vars
// eslint-disable-next-line no-unused-vars
class MapManager {
#apiKey

#map
#defaultIcon
#markers
constructor() {
// Default Icon of Leaflet can not be loaded in our environment, so it was manually added to the repo
this.#defaultIcon = L.icon({
iconUrl: '/images/marker.svg',
shadowUrl: '/images/marker-shadow.svg',
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
shadowSize: [41, 41]
});
}

/**
* Create a new MapManager instance
* @param {string} apiKey Your MapQuest API Key
*/
constructor(apiKey) {
this.#apiKey = apiKey;
* Initialize a Leaflet map
* @param {number} latitude The map center latitude
* @param {number} longitude The map center longitude
* @param {number} zoom The map zoom, defaults to 18
*/
initMap(latitude, longitude, zoom = 18) {
this.#map = L.map('map').setView([latitude, longitude], 8);
var mapLink = '<a href="http://openstreetmap.org">OpenStreetMap</a>';
L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; ' + mapLink + ' Contributors',
maxZoom: zoom,}).addTo(this.#map);
this.#markers = L.layerGroup().addTo(this.#map);
}

/**
* Generate a MapQuest image URL for the specified parameters
* @param {number} latitude The map center latitude
* @param {number} longitude The map center longitude
* @param {{latitude, longitude, name}[]} tags The map tags, defaults to just the current location
* @param {number} zoom The map zoom, defaults to 11
* @returns {string} URL of generated map
*/
getMapUrl(latitude, longitude, tags = [], zoom = 11) {
if (!this.#apiKey) {
console.log("No API key provided.");
return "images/mapview.jpg";
* Update the Markers of a Leaflet map
* @param {number} latitude The map center latitude
* @param {number} longitude The map center longitude
* @param {{latitude, longitude, name}[]} tags The map tags, defaults to just the current location
* @param {number} zoom The map zoom, defaults to 18
*/
updateMarkers(latitude, longitude, tags = [], zoom = 18) {
// delete all markers
this.#markers.clearLayers();
L.marker([latitude, longitude], { icon: this.#defaultIcon })
.bindPopup("Your Location")
.addTo(this.#markers);
for (const tag of tags) {
L.marker([tag.location.latitude,tag.location.longitude], { icon: this.#defaultIcon })
.bindPopup(tag.name)
.addTo(this.#markers);
}

let tagList = `${latitude},${longitude}|marker-start`;
tagList += tags.reduce((acc, tag) => `${acc}||${tag.latitude},${tag.longitude}|flag-${tag.name}`, "");

const mapQuestUrl = `https://www.mapquestapi.com/staticmap/v5/map?key=${this.#apiKey}&size=600,400&zoom=${zoom}&center=${latitude},${longitude}&locations=${tagList}`;
console.log("Generated MapQuest URL:", mapQuestUrl);

return mapQuestUrl;
}
}
}
16 changes: 16 additions & 0 deletions Aufgabe4/gta_v4_template/public/images/marker-shadow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions Aufgabe4/gta_v4_template/public/images/marker.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.