×
Namespaces

Variants
Actions
(Difference between revisions)

HERE Maps API - How to create a KML data file

From Nokia Developer Wiki
Jump to: navigation, search
jasfox (Talk | contribs)
m (Jasfox - Update code commentary to reflect 2.2)
jasfox (Talk | contribs)
m (Jasfox - links)
(4 intermediate revisions by 2 users not shown)
Line 2: Line 2:
 
{{Abstract|This article explains how to create and edit a sample '''KML''' file using an online editor }}  
 
{{Abstract|This article explains how to create and edit a sample '''KML''' file using an online editor }}  
 
{{Note| in order to load a KML file successfully, the generated KML file should be hosted on the same domain as the JavaScript or the results may be unpredictable. Some browsers will automatically prohibit cross-domain access.
 
{{Note| in order to load a KML file successfully, the generated KML file should be hosted on the same domain as the JavaScript or the results may be unpredictable. Some browsers will automatically prohibit cross-domain access.
For example, if you are hosting at  ''example.com'', the final line of the JavaScript to load the KML will need to be:  
+
For example, if you are hosting at  {{Icode|example.com}}, the final line of the JavaScript to load the KML will need to be:  
 
<code javascript>
 
<code javascript>
 
kml.parseKML("http://example.com/" + "generated_kml_data_file.kml")
 
kml.parseKML("http://example.com/" + "generated_kml_data_file.kml")
 
</code>
 
</code>
and both the KML loading HTML and the  generated_kml_data_file.kml should be placed on  ''http://example.com/''
+
and both the KML loading HTML and the  generated_kml_data_file.kml should be placed on  {{Icode|http://example.com/}}
 
}}
 
}}
 
{{SeeAlso|<br />
 
{{SeeAlso|<br />
* [http://api.maps.nokia.com/ Nokia Maps API]  
+
* [http://developer.here.net/javascript_api Nokia Maps API]
 
* [[Nokia Maps API - Converting any data file to KML]]
 
* [[Nokia Maps API - Converting any data file to KML]]
 
* [[Nokia Maps API - How to display KML file data on the map]]
 
* [[Nokia Maps API - How to display KML file data on the map]]
* [http://api.maps.nokia.com/en/playground/examples/maps/kml/kmlfile.html Loading a KML file example]
+
* [http://developer.here.net/apiexplorer/examples/api-for-js/data-visualization/map-with-interactive-kml-objects.html Loading a KML file example]
* [http://api.maps.nokia.com/en/playground/examples/maps/services/search.html Search example]
+
* [http://developer.here.net/apiexplorer/examples/api-for-js/places-search/search-by-address.html Search example]
 +
* [http://developer.here.net/apiexplorer/examples/api-for-js/places-search/reverse-geocode.html Reverse Geocode example]
 
}}
 
}}
 
{{ArticleMetaData
 
{{ArticleMetaData
|sourcecode= [[Media:KMLGeneratorExample.zip]]  
+
|sourcecode= [[Media:KMLGeneratorExample.zip|KMLGeneratorExample.zip]]
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 
|devices= Firefox, Internet Explorer, Google Chrome, Opera
 
|devices= Firefox, Internet Explorer, Google Chrome, Opera
Line 22: Line 23:
 
|platform= Web Browser
 
|platform= Web Browser
 
|devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) -->
 
|devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) -->
|dependencies= Nokia Maps API 2.2.0
+
|dependencies= Nokia Maps API 2.2.3
 
|signing=<!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer -->
 
|signing=<!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer -->
 
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
 
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
Line 54: Line 55:
  
 
=== Initialisation ===
 
=== Initialisation ===
After the usual Map set up, we need to get a reference to each of the text boxes on the right of the screen. This is done by using ''document.getElementById()''
+
After the usual Map set up, we need to get a reference to each of the text boxes on the right of the screen. This is done by using {{Icode|document.getElementById()}}
 
<code javascript>
 
<code javascript>
 
var lat = document.getElementById("lat");
 
var lat = document.getElementById("lat");
Line 71: Line 72:
  
 
=== Adding Markers ===
 
=== Adding Markers ===
Markers can be added by pressing and holding down the mouse , this is the ''longpress'' event. An event handler has been added to the map to cope with this. The associated values such as ''&lt;description&gt;'' and ''&lt;name&gt;'' come directly from the text boxes defined above.
+
Markers can be added by pressing and holding down the mouse , this is the {{Icode|longpress}} event. An event handler has been added to the map to cope with this. The associated values such as {{Icode|&lt;description&gt;}} and {{Icode|&lt;name&gt;}} come directly from the text boxes defined above.
 
<code javascript>
 
<code javascript>
 
eventExEl.addListener("longpress", function(evt) {
 
eventExEl.addListener("longpress", function(evt) {
Line 127: Line 128:
 
   };
 
   };
 
</code>
 
</code>
The ''addMarkers()'' method actually adds the marker, which itself contains a copy of its own ''&lt;description&gt;'', ''&lt;address&gt;'', ''&lt;name&gt;'' & etc.  The marker has two events:
+
The {{Icode|addMarkers()}} method actually adds the marker, which itself contains a copy of its own {{Icode|&lt;description&gt;}}, {{Icode|&lt;address&gt;}}, {{Icode|&lt;name&gt;}} & etc.  The marker has two events:
an ''click'' event to display the data in text boxes for editing. This will also display an infobubble if the ''&lt;description&gt;'' field is set. A reference is kept on the ''currentMarker'' i.e. the last one selected.
+
a {{Icode|click}} event to display the data in text boxes for editing. This will also display an infobubble if the {{Icode|&lt;description&gt;}} field is set. A reference is kept on the {{Icode|currentMarker}} i.e. the last one selected.
*  a ''drag'' event to remove the infobubble if a marker is repositioned. All markers are defined as draggable so the user can reposition them as necessary.
+
*  a {{Icode|drag}} event to remove the infobubble if a marker is repositioned. All markers are defined as draggable so the user can reposition them as necessary.
  
 
<code javascript>
 
<code javascript>
Line 166: Line 167:
  
 
=== Editing Marker Data ===
 
=== Editing Marker Data ===
The ''editMarker()'' method, removes the ''currentMarker'' and adds another one with the current data from the text fields.
+
The {{Icode|editMarker()}} method, removes the {{Icode|currentMarker}} and adds another one with the current data from the text fields.
 
<code>
 
<code>
 
function editMarker() {
 
function editMarker() {
Line 185: Line 186:
  
 
=== Adding Polylines ===
 
=== Adding Polylines ===
It is impossible to create Polylines without first having some defined waypoints. The waypoints are merely'' geoCoordinates'', so a button has been added to take the coordinates of the ''currentMarker'' and add them to an array.
+
It is impossible to create {{Icode|Polylines}} without first having some defined {{Icode|waypoints}}. The {{Icode|waypoints}} are merely {{Icode|geo.Coordinates}}, so a button has been added to take the coordinates of the {{Icode|currentMarker}} and add them to an array.
The marker is then removed to  "tidy up" the display. When the create line from Waypoints button is pressed, the Polyline is created.  
+
The marker is then removed to  "tidy up" the display. When the create line from Waypoints button is pressed, the {{Icode|Polyline}} is created.  
  
{{Warning|There is currently no method to delete waypoints or Polylines, this must be done by editing the '''KML''' directly.}}
+
{{Warning|There is currently no method to delete {{Icode|waypoints}} or {{Icode|Polylines}}, this must be done by editing the '''KML''' directly.}}
  
 
<code javascript>
 
<code javascript>
Line 219: Line 220:
  
 
== KML Generator ==
 
== KML Generator ==
The ''saveMapObjects()'' method has been taken from the [[Nokia_Maps_:_Converting_from_JavaScript_to_KML| converting from JavaScript to KML]] article. All the map Objects currently on screen are iterated through and added as '''KML''' equivalents. In order to discourage the use of inline styles, a ''&lt;styleURL&gt;'' element has been added. This should refer to a  ''&lt;Style&gt;'' somewhere else in the document, but obviously the ''&lt;Style&gt;'' has not been created, and must be added manually. An example of how to add a ''&lt;styleURL&gt;'' and an associated ''&lt;Style&gt;'' is shown below:  
+
The {{Icode|saveMapObjects()}} method has been taken from the [[Nokia_Maps_:_Converting_from_JavaScript_to_KML| converting from JavaScript to KML]] article. All the map Objects currently on screen are iterated through and added as '''KML''' equivalents. In order to discourage the use of inline styles, a {{Icode|&lt;styleURL&gt;}} element has been added. This should refer to a  {{Icode|&lt;Style&gt;}} somewhere else in the document, but obviously the {{Icode|&lt;Style&gt;}} has not been created, and must be added manually. An example of how to add a {{Icode|&lt;styleURL&gt;}} and an associated {{Icode|&lt;Style&gt;}} is shown below:  
  
 
<code xml>
 
<code xml>
Line 235: Line 236:
 
</code>
 
</code>
  
Since '''KML''' is just a form of XML, the generated file can be read using jQuery and applying the technique found in the [[Nokia_Maps_API_-_Create_map_markers_from_XML_data|Create map markers from XML data]],  the '''KML''' is in a known format, it is merely an excerise to extract the name from the ''&lt;name&gt;'' element, the address from the ''&lt;address&gt;'' element and so on. Two problems do need to be solved however. Firstly the geocoordinates are held as comma separated text, rather than individual ''&lt;longitude&gt;'' and ''&lt;latittude&gt;'' elements and secondly the description in the ''&lt;description&gt;'' element can contain formatted HTML and is held in a ''CDATA'' section. The first problem is dealt with my splitting the text by using the ''search()'' function:
+
Since '''KML''' is just a form of XML, the generated file can be read using jQuery and applying the technique found in the [[Nokia_Maps_API_-_Create_map_markers_from_XML_data|Create map markers from XML data]],  the '''KML''' is in a known format, it is merely an exercise to extract the name from the {{Icode|&lt;name&gt;}} element, the address from the {{Icode|&lt;address&gt;}} element and so on. Two problems do need to be solved however. Firstly the geocoordinates are held as comma separated text, rather than individual {{Icode|&lt;longitude&gt;}} and {{Icode|&lt;latittude&gt;}} elements and secondly the description in the {{Icode|&lt;description&gt;}} element can contain formatted HTML and is held in a {{Icode|CDATA}} section. The first problem is dealt with by splitting the text using the {{Icode|search()}} function:
  
 
<code javascript>
 
<code javascript>
Line 244: Line 245:
 
</code>
 
</code>
  
The ''CDATA'' section is deal with by stripping out the marker characters, and safely encoding the HTML data within it. The HTML is re-inflated using the ''escape()'' function when it is read.
+
The {{Icode|CDATA}} section is dealt with by stripping out the marker characters, and safely encoding the HTML data within it. The HTML is re-inflated using the {{Icode|escape()}} function when it is read.
 
<code javascript>
 
<code javascript>
 
while ( kml.search ("<!\\[CDATA\\[")  > - 1){
 
while ( kml.search ("<!\\[CDATA\\[")  > - 1){
Line 257: Line 258:
  
 
== Summary ==
 
== Summary ==
It should be easy to create a simple '''KML''' file using the technique described above. Editing can be done either directly on the source '''KML''' or by moving elements around on the map. The generated file is valid '''KML''', and can  be displayed using the standard technique described in the [[Nokia_Maps_API_-_How_to_display_KML_file_data_on_the_map|How to display KML file data on the map]]. The generated '''KML''' could also be added to an existing file (provided that  the header and ''&lt;Document&gt;'' lines are not included.
+
It should be easy to create a simple '''KML''' file using the technique described above. Editing can be done either directly on the source '''KML''' or by moving elements around on the map. The generated file is valid '''KML''', and can  be displayed using the standard technique described in the [[Nokia_Maps_API_-_How_to_display_KML_file_data_on_the_map|How to display KML file data on the map]]. The generated '''KML''' could also be added to an existing file (provided that  the header and {{Icode|&lt;Document&gt;}} lines are not included.

Revision as of 18:33, 3 January 2013

This article explains how to create and edit a sample KML file using an online editor

Note.pngNote: in order to load a KML file successfully, the generated KML file should be hosted on the same domain as the JavaScript or the results may be unpredictable. Some browsers will automatically prohibit cross-domain access.

For example, if you are hosting at example.com, the final line of the JavaScript to load the KML will need to be:

kml.parseKML("http://example.com/" + "generated_kml_data_file.kml")
and both the KML loading HTML and the generated_kml_data_file.kml should be placed on http://example.com/

Article Metadata
Code ExampleTested with
Devices(s): Firefox, Internet Explorer, Google Chrome, Opera
Compatibility
Platform(s): Web Browser
Dependencies: Nokia Maps API 2.2.3
Article
Keywords: Nokia Maps, JavaScript, KML
Created: jasfox (10 Jan 2012)
Last edited: jasfox (03 Jan 2013)


Contents

Introduction

Keyhole Markup Language (KML) is an XML notation for geographic applications. The advantages of using KML are numerous, and have been listed in a previous article. The learning curve for KML is quite steep, requires a thorough understanding of both XML and mapping technologies, and since the reference documentation is written for 3d rather than 2d maps, much of it is irrelevant for simple mapping cases. All this means that some web developers are put off using KML, which is a pity, since KML is a standard data format, and the use of KML would result in the faster porting of a mapping applications to other platforms.

In order to remedy this, it would be useful to have a WYSIWYG point and click KML generator, where a map could be edited on screen, and the resultant KML file generated. The coded example below, attempts to fill this gap as shown.

KMLGenerator.png

WSYIWIG Editor

Initialisation

After the usual Map set up, we need to get a reference to each of the text boxes on the right of the screen. This is done by using document.getElementById()

var lat = document.getElementById("lat");
var lng = document.getElementById("lng");
var waypoints = document.getElementById("waypoints");
 
var title = document.getElementById("title");
var name = document.getElementById("name");
var description = document.getElementById("description");
var address = document.getElementById("address");
var icon = document.getElementById("icon");
var styleURL = document.getElementById("styleURL");
var lineStyleURL = document.getElementById('lineStyleURL');


Adding Markers

Markers can be added by pressing and holding down the mouse , this is the longpress event. An event handler has been added to the map to cope with this. The associated values such as <description> and <name> come directly from the text boxes defined above.

eventExEl.addListener("longpress", function(evt) {
var markerData = new Object();
markerData.coords = map.pixelToGeo(evt.targetX , evt.targetY);
markerData.title = map.objects.getLength() + 1;
markerData.description = description.value;
markerData.name = name.value;
markerData.address = address.value;
if (icon.value != ""){
markerData.icon = icon.value;
} else {
markerData.styleURL = styleURL.value;
}
addMarker(markerData);
 
}, false);

An alternative method of adding a marker is by adding an address. This uses the standard geoCoding service, and picks the first address found on the list. If your address is in the "wrong" format, just try making the address more general for now e.g.try the city only. The handler for geo-coding retrieves most of its information from the text boxes on the right hand side of the screen, but the address comes from the callback function.

var searchManager = nokia.places.search.manager;
searchManager.geoCode({
searchTerm : address.value,
onComplete: onSearchComplete});
  var onSearchComplete = function (data, requestStatus) {
// If the search has finished we can process the results
if (requestStatus == "OK") {
var markerData = new Object();
markerData.coords = data.location.position;
markerData.title = map.objects.getLength() + 1;
markerData.description = description.value;
markerData.name = name.value;
 
var address = data.location.address;
 
markerData.address = "";
markerData.address = markerData.address + address.houseNumber + "\n";
markerData.address = markerData.address + address.street + "\n";
markerData.address = markerData.address + address.district + "\n";
markerData.address = markerData.address + address.city + "\n";
markerData.address = markerData.address + address.postalCode + "\n";
markerData.address = markerData.address + address.country;
 
addMarker(markerData);
map.setCenter(data.location.position);
 
} else if (requestStatus == "ERROR") {
alert("The search request failed.");
}
};

The addMarkers() method actually adds the marker, which itself contains a copy of its own <description>, <address>, <name> & etc. The marker has two events:

  • a click event to display the data in text boxes for editing. This will also display an infobubble if the <description> field is set. A reference is kept on the currentMarker i.e. the last one selected.
  • a drag event to remove the infobubble if a marker is repositioned. All markers are defined as draggable so the user can reposition them as necessary.
function addMarker(markerData) {
var marker;
marker = new nokia.maps.map.StandardMarker(markerData.coords, {
text: markerData.title, //small title
draggable: true, //the marker is marked to be draggable
$data: markerData
 
});
 
marker.addListener("click" , function(evt) {
title.value = evt.target.text;
description.value = evt.target.$data.description;
address.value = evt.target.$data.address;
name.value = evt.target.$data.name;
styleURL.value = evt.target.$data.styleURL;
lat.innerHTML = evt.target.coordinate.latitude;
lng.innerHTML = evt.target.coordinate.longitude;
 
if ( evt.target.$data.description != ""){
infoBubbles.addBubble(evt.target.$data.description, evt.target.coordinate);
} else {
infoBubbles.removeBubble();
}
 
currentMarker = evt.target;
}, false);
 
marker.addListener("drag" , function(evt) { infoBubbles.removeBubble();}, false);
map.objects.add(marker);
}

Editing Marker Data

The editMarker() method, removes the currentMarker and adds another one with the current data from the text fields.

function editMarker() {
map.objects.remove(currentMarker);
infoBubbles.removeBubble();
var markerData = new Object();
markerData.coords = currentMarker.coordinate;
markerData.title = title.value;
markerData.description = description.value;
markerData.name = name.value;
markerData.address = address.value;
addMarker(markerData);
if ( description.value != ""){
infoBubbles.addBubble(markerData.description, markerData.coords );
}
}

Adding Polylines

It is impossible to create Polylines without first having some defined waypoints. The waypoints are merely geo.Coordinates, so a button has been added to take the coordinates of the currentMarker and add them to an array. The marker is then removed to "tidy up" the display. When the create line from Waypoints button is pressed, the Polyline is created.

Warning.pngWarning: There is currently no method to delete waypoints or Polylines, this must be done by editing the KML directly.

var currentWaypoints = new Array();
map.objects.remove(currentMarker);
currentWaypoints.push( currentMarker.coordinate);
function createLineFromWaypoints() {
var lineData = new Object();
lineData.lineNo = map.objects.getLength() + 1;
lineData.waypoints = currentWaypoints ;
if( lineStyleURL.value != ""){
lineData.styleURL = lineStyleURL.value;
}
map.objects.add(new nokia.maps.map.Polyline(
lineData.waypoints,
{
color: "#22CA" ,
width: 5,
$data: lineData
}
));
currentWaypoints = new Array();
waypoints.innerHTML = "";
}

KML Generator

The saveMapObjects() method has been taken from the converting from JavaScript to KML article. All the map Objects currently on screen are iterated through and added as KML equivalents. In order to discourage the use of inline styles, a <styleURL> element has been added. This should refer to a <Style> somewhere else in the document, but obviously the <Style> has not been created, and must be added manually. An example of how to add a <styleURL> and an associated <Style> is shown below:

<Style id='smallIcon'>
<IconStyle>
<Icon>
<href>http:www.example.com/Icon-Small.png</href>
</Icon>
</IconStyle>
</Style>
<Placemark>
<Point><coordinates>-0.12759880162775517,51.50320703163743,0</coordinates></Point>
<styleUrl>#smallIcon</styleUrl>
</Placemark>

Since KML is just a form of XML, the generated file can be read using jQuery and applying the technique found in the Create map markers from XML data, the KML is in a known format, it is merely an exercise to extract the name from the <name> element, the address from the <address> element and so on. Two problems do need to be solved however. Firstly the geocoordinates are held as comma separated text, rather than individual <longitude> and <latittude> elements and secondly the description in the <description> element can contain formatted HTML and is held in a CDATA section. The first problem is dealt with by splitting the text using the search() function:

var lng = coord.substring( 0 , coord.search(","));
coord = coord.substring(coord.search(",")+ 1);
var lat = coord.substring( 0 , coord.search(","));
markerData.coords = new nokia.maps.geo.Coordinate(parseFloat(lat), parseFloat(lng));

The CDATA section is dealt with by stripping out the marker characters, and safely encoding the HTML data within it. The HTML is re-inflated using the escape() function when it is read.

while ( kml.search ("<!\\[CDATA\\[")  > - 1){
var from = kml.search ("<!\\[CDATA\\[");
var to= kml.search ("\\]\\]>");
kml = kml.substring(0, from) + escape(kml.substring(from + 9, to)) + kml.substring(to+ 3);
}
markerData.description =  unescape($(this).find('description').text());

Summary

It should be easy to create a simple KML file using the technique described above. Editing can be done either directly on the source KML or by moving elements around on the map. The generated file is valid KML, and can be displayed using the standard technique described in the How to display KML file data on the map. The generated KML could also be added to an existing file (provided that the header and <Document> lines are not included.

212 page views in the last 30 days.
×