Geodaten und Application Express: Oracle MAPS!

Dieser Tipp ist eine Fortsetzung der Tutorial-Reihe Geodaten und Oracle Application Express: Während Sie den oben genannten vier Tutorials entnehmen können, wie Sie die frei verfügbaren Geodaten aus dem Oracle Technet installieren und erste Karten in Ihre Application Express-Anwendungen einbauenn, erfahren Sie in diesem Tipp, wie Sie die Karte um Funktionalität erweitern können. Um also den Ausgangspunkt für dieses Tutorial zu erreichen, sollten Sie die anderen 4 Tutorials durchgearbeitet haben.

Ausgangspunkt ist das Ergebnis des letzten Tutorials. Also ist die Karte in eine Application Express-Anwendung integriert, man kann sie per Drag & Drop verschieben, heraus- und hineinzoomen und es ist möglich, die Kunden aus der Tabelle KUNDEN ein- und auszublenden.

Ausgangspunkt: Application Express-Anwendung mit Karte

Abbildung 1: Ausgangspunkt: Application Express-Anwendung mit Karte

Nun werden wir die Karte um etwas Funktionalität erweitern. Da Oracle MAPS vollständig auf der AJAX-Technologie basiert, werden Sie die Oracle MAPS JavaScript API im folgenden recht stark nutzen.

1. Bericht auf Tabelle KUNDEN hinzufügen und Karte bei Klick zentrieren

Erzeugen Sie einen neuen Bericht auf die Tabelle KUNDEN. Stellen Sie diesen rechts neben die Karte (Spalte 2).

Neue Berichtsregion rechts der Karte hinzufügen

Abbildung 2: Neue Berichtsregion rechts der Karte hinzufügen

Sehr wichtig ist nun, dass beim Blättern im Bericht die Anwendungsseite nicht neu aufgebaut wird. Dies stellen Sie bis einschließlich APEX 3.0 dadurch sicher, dass Sie ein sog. PPR-Template (PPR = Partial Page Refresh) verwenden (Abbildung 3). Stellen Sie beim Berichts-SQL sicher, dass die X- und Y-Koordinaten jedes Kunden selektiert werden:

select 
  k.id,
  k.name,
  k.lokation.sdo_point.x x,
  k.lokation.sdo_point.y y
from kunden k
PPR Berichtstemplate verwenden (bis APEX 3.0)

Abbildung 3: PPR Berichtstemplate verwenden (bis APEX 3.0)

Ab APEX 3.1 können Sie den Partial Page Refresh als Eigenschaft in den Berichtsattributen aktivieren. PPR ist wichtig, da bei einem Neuaufbau der gesamten Seite auch die Karte auf die Standardeinstellungen zurückgesetzt wird - wenn der Endanwender also ein anderes Zoom-Level gewählt hat, geht dies verloren. Generell sollte man das Neu-Laden der ganzen Seite bei der Arbeit mit Oracle Maps möglichst unterlassen - zum Übermitteln von Informationen vom Browser an Application Express können AJAX-Technologien zum Einsatz kommen.

Probieren Sie ihren fertigen Bericht zunächst aus - wenn Sie darin blättern, sollte die Karte davon nicht betroffen sein. Funktioniert dies soweit, navigieren Sie wiederum zu den Berichtsattributen.

Bericht auf die Tabelle KUNDEN: Erster Test

Abbildung 4: Bericht auf die Tabelle KUNDEN: Erster Test

Natürlich ist das noch nicht die endgültige Version. Stellen Sie, bevor Sie das Zentrieren eines Kunden auf der Karte hinzufügen, sicher, dass ein Dezimalpunkt als Trennzeichen verwendet wird. Wenn Sie deutsche Spracheinstellungen verwenden, kann es sein, dass der Bericht ein Dezimalkomma enthält. In diesem Fall navigieren Sie wiederum zu den Berichtsattributen, dort zu den Spalten X und Y und hinterlegen Sie als Formatmaske jeweils 999.999999999999999999999999 (achten Sie auf hinreichend viele Nachkommastellen).

Wenn der Bericht in den Spalten X und Y korrekterweise Dezimalpunkte anzeigt, navigieren Sie erneut zu den Berichtsattributen. Die Spalten X und Y brauchen nun nicht mehr angezeigt zu werden - entfernen Sie also das entsprechende Häkchen. Klicken Sie anschließend auf die Eigenschaften der Spalte NAME.

Berichtseigenschaften

Abbildung 5: Berichtseigenschaften

Hinterlegen Sie hier einen Link. Als Link-Ziel verwenden Sie eine JavaScript-Funktion von Oracle Maps: setCenterAndZoomLevel(). Wenn auf einen Namen geklickt wird, soll die Karte nicht nur auf diesem Kunden zentriert werden - sie soll zusätzlich auch noch auf einen bestimmten Zoom Level (hier: 6) gesetzt werden.

javascript:mapview.setCenterAndZoomLevel(MVSdoGeometry.createPoint(#X#,#Y#,8307), 6);
Javascript-Funktion "setCenterAndZoomLevel()" als Link-Ziel hinterlegen

Abbildung 6: Javascript-Funktion "setCenterAndZoomLevel()" als Link-Ziel hinterlegen

Speichern Sie alle Änderungen und starten Sie die Seite neu. Sie können nun wie gewohnt die Karte per Drag & Drop hin- und herschieben, hinein- und herauszoomen und bei Klick auf eine Zeile in der Kundentabelle rechts navigiert die Karte automatisch zu diesem Kunden. Wenn Sie die Stecknadel für den Kunden nicht sehen, klicken Sie auf den Link Kunden ein-/ausblenden, um die Kunden einzublenden.

Das Ergebnis

Abbildung 7: Das Ergebnis

2. Übersichtskarte hinzufügen

Als nächstes werden wir der Karte eine (kleinere) Übersichtskarte hinzufügen; das ist insbesondere nützlich, wenn der Anwender sehr stark in die Karte hineinzoomt. Die Übersichtskarte (Overview Map) zeigt dann an, wo man sich eigentlich befindet. Auch dies wird komplett mit der Oracle Maps JavaScript API gemacht; die JavaScript-Klasse MVOverviewMap stellt die nötige Funktionalität bereit. Navigieren Sie zum Seiten-Header und ändern Sie den bereits vorhandene JavaScript-Block wie folgt um:

<script src="/mapviewer/fsmc/jslib/oraclemaps.js"></script>
<script type="text/javascript">
  var baseURL  = "http://"+document.location.host+"/mapviewer";
  var mapCenterLon = 10;
  var mapCenterLat = 50;
  var mapZoom      = 0;

  var mapview;
  var ovcontainer;

  var mpoint = MVSdoGeometry.createPoint(mapCenterLon,mapCenterLat,8307);

  function show_map() {
    mapview = new MVMapView(document.getElementById("map"),baseURL);      
    var basemap  = new MVBaseMap("WORLD.WELTKARTE");
    mapview.addBaseMapLayer(basemap);
    mapview.setCenter(mpoint);
    mapview.setZoomLevel(mapZoom);
    mapview.addNavigationPanel("WEST");

    ovcontainer = new MVMapDecoration(null,null,null,200,150) ;
    ovcontainer.setCollapsible(true);
    mapview.addMapDecoration(ovcontainer);
    var over=new MVOverviewMap(ovcontainer.getContainerDiv(),4);
    mapview.addOverviewMap(over)

    var foi_kunden = new MVThemeBasedFOI('foi_kunden','world.kunden');
    foi_kunden.setVisible(false);
    mapview.addThemeBasedFOI(foi_kunden);   
  

    mapview.display();
  }
  
  function setVisible(foi_name) {
    var foi = mapview.getThemeBasedFOI(foi_name); 
    foi.setVisible(!foi.isVisible());
  }
</script>

Die rot markierten Abschnitte fügen die Übersichtskarte hinzu. Speichern Sie den Code und starten Sie die Seite neu. Das Ergebnis sollte dann in etwa wie in Abbildung 8 aussehen.

Karte mit "overview Map"

Abbildung 8: Karte mit "Overview Map"

3. "Marquee"- oder auch "Rechteck"-Zoom aktivieren

Eine recht beliebte Funktion in Kartenanwendungen ist der sog. Marquee-Zoom. Das bedeutet, dass der Endanwender mit der Maus ein Rechteck zeichnet und die Karte danach auf diesen Bereich zoomt. Da ein Drag & Drop im Moment die Karte einfach nur verschiebt, müsste die Mausfunktion dazu "umgeschaltet" werden. Und auch hierfür gibt es eine entsprechende JavaScript-Funktion in der Oracle Maps API.

Fügen Sie unterhalb des Links Kunden ein-/ausblenden einen neuen Link namens Marquee-Zoom aktivieren hinzu. Navigieren Sie dazu zur HTML-Quelle der Region Karte und ändern Sie diese wie folgt:

<div id="map" style="left:0px; top:0px; width:600px; height: 400px">
</div>
<div>
<a href="javascript:setVisible('foi_kunden');">Kunden ein/ausblenden</a><br/>
<a href="javascript:mapview.startMarqueeZoom();">Marquee-Zoom aktivieren</a><br/>
</div>

Starten Sie die Seite anschließend neu, klicken Sie auf den frisch erzeugten Link und ziehen Sie mit der Maus ein Rechteck. Sowie Sie die Maustaste loslassen, wird die Karte auf das von Ihnen gezogene Rechteck angepasst.

Marquee-Zoom in Aktion

Abbildung 9: Marquee-Zoom in Aktion

4. "Information Window" für die Kunden anpassen ...

Als nächstes wollen wir das Information Window, welches bei Klick auf einen der Kunden dargestellt wird, anpassen - die Standardausführung gefällt nicht ... Navigieren Sie dazu nochmals zum Seiten-Header und ändern Sie das JavaScript nochmals um:

<script src="/mapviewer/fsmc/jslib/oraclemaps.js"></script>
<script type="text/javascript">
  var baseURL  = "http://"+document.location.host+"/mapviewer";
  var mapCenterLon = 10;
  var mapCenterLat = 50;
  var mapZoom      = 0;

  var mapview;
  var ovcontainer;

  var mpoint = MVSdoGeometry.createPoint(mapCenterLon,mapCenterLat,8307);

  function show_map() {
    mapview = new MVMapView(document.getElementById("map"),baseURL);      
    var basemap  = new MVBaseMap("WORLD.WELTKARTE");
    mapview.addBaseMapLayer(basemap);
    mapview.setCenter(mpoint);
    mapview.setZoomLevel(mapZoom);
    mapview.addNavigationPanel("WEST");

    ovcontainer = new MVMapDecoration(null,null,null,200,150) ;
    ovcontainer.setCollapsible(true);
    mapview.addMapDecoration(ovcontainer);
    var over=new MVOverviewMap(ovcontainer.getContainerDiv(),4);
    mapview.addOverviewMap(over)

    var foi_kunden = new MVThemeBasedFOI('foi_kunden','world.kunden');
    foi_kunden.setVisible(false);
    foi_kunden.addEventListener ("mouse_click", foiClicked);
    mapview.addThemeBasedFOI(foi_kunden);   
  
    mapview.display();
  }

  function foiClicked(p_point, p_foi) {
    mapview.displayInfoWindow(
      p_point,
      '<table style="background-color: #ffff00">'+
      '<tr><td><b>ID</b></td><td>'+p_foi.attrs[0]+'</td></tr>'+
      '<tr><td><b>Name</b></td><td>'+p_foi.attrs[1]+'</td></tr>'+
      '<tr><td><b>Aktionen</b></td><td><a href="javascript:deleteKunde('+p_foi.attrs[0]+')">Kunde l&ouml;schen</td></tr>'+
      '</table>',
      400,
      200
    );
  }
    
  
  function setVisible(foi_name) {
    var foi = mapview.getThemeBasedFOI(foi_name); 
    foi.setVisible(!foi.isVisible());
  }
</script>

Wiederum sind die entscheidenden Stellen rot markiert. Dem FOI wird ein Event Listener hinzugefügt, welcher dafür sorgt, dass bei einem Klick auf einen Kunden die Javascript-Funktion foiClicked() aufgerufen wird. Dasurch wird das "Standard"-Information Window nicht mehr dargestellt; vielmehr stellt foiClicked() ein eigenes Information Window mit eigenem HTML dar. Das Ergebnis sieht dann etwa so aus:

Karte mit speziell formatiertem "Information Window"

Abbildung 10: Karte mit speziell formatiertem "Information Window"

Und was soll nun dieser Link Kunde löschen ...? Dazu im folgenden mehr ...

5. Tabellendaten mit AJAX Requests verändern

Als letzte Erweiterung soll nun dargestellt werden, wie Sie per JavaScript einen AJAX-Request auslösen und damit einen Kunden aus der Tabelle löschen können. Die Änderung oder Neuanlage von Kunden würde dann analog erfolgen. Generell finden Sie im Inhaltsverzeichnis der Community unter AJAX: Bessere Oberflächen zahlreiche Tipps und How To-Dokumente zum Thema AJAX.

Zunächst ist dazu ein Server-Prozeß zum Löschen der Tabellenzeile erforderlich. Navigieren Sie dazu zu den Gemeinsamen Komponenten und dort zu den Anwendungsprozessen. Erstellen Sie einen neuen Anwendungsprozeß, nennen Sie diesen DELETE_KUNDE und legen Sie fest, dass dieser Bedarfsgesteuert (On Demand) ausgeführt werden soll. Hinterlegen Sie dabei folgenden PL/SQL-Code:

begin
  delete from kunden where id = :K_ID;
  htp.p('Erfolg!');
exception 
  when others then
    htp.p('Problem: '||sqlerrm);
end;

Die Bindevariable K_ID enthält dabei die jeweilige ID der Tabellenzeile, die gerade gelöscht werden soll. Dieses Anwendungselement muss allerdings noch erzeugt werden. Navigieren Sie dazu zu den Gemeinsamen Komponenten, dort zu den Anwendungselementen und erzeugen Sie ein neues Anwendungselement namens K_ID.

Nun geht es daran, diesen Anwendungsprozeß aus JavaScript heraus aufzurufen. Der Link im Information Window hierfür wurde im letzten Schritt bereits erzeugt; nun muss nur noch die JavaScript-Funktion deleteKunde() entsprechend ausprogrammiert werden. Fügen Sie also im Seiten-Header folgenden JavaScript-Code hinzu.

function deleteKunde(p_kid) {
  var get = new htmldb_Get(
    null,
    html_GetElement('pFlowId').value,
    "APPLICATION_PROCESS=DELETE_KUNDE",
    0
  );
  get.add("K_ID", p_kid);
  alert(get.get());
  mapview.removeInfoWindow();
  mapview.getThemeBasedFOI("foi_kunden").refresh();
}

Und fertig - Klicken Sie einen Kunden an ... und im Information Window dann auf den Link Kunde löschen. Danach sollte die Stecknadel mitsamt dem Information Window verschwinden - der Eintrag ist aus der Tabelle gelöscht.

Was allerdings noch fehlen würde, wäre das "Auffrischen" der Kundentabelle rechts. Wie man das macht, können Sie im Community Tipp Partial Page Refreshes für APEX Regionen nachlesen.

Zurück zur Community-Seite