1

I'm using the Java API for KML to create a KML file with several Placemarks, each with a description popup. Within the popup, I'd like to link to my REST API that I have running on localhost.

I've tried using a simple href that calls the API directly, but that opens a new window upon click, which I don't want to happen.

Then, I tried changing the link to a button that should trigger a callAPI JavaScript function to call the API without opening a new window. Here is my Java code:

final Kml kml = new Kml();
Document doc = kml.createAndSetDocument()
    .withName("My KML File")
    .withOpen(true);
BalloonStyle bstyle = doc.createAndAddStyle()
    .withId("balloonstyle")
    .createAndSetBalloonStyle()
    .withId("ID")
    .withText("<font face='Courier' size='3'>$[description]</font><br/>");

Folder folder = doc.createAndAddFolder().withName("Placemark Points").withOpen(true);

Placemark placemark = folder.createAndAddPlacemark()
    .withName("My Placemark")
    .withVisibility(true)
    .withOpen(true)
    .withStyleUrl("#balloonstyle");

placemark.createAndSetPoint()
    .withExtrude(false)
    .withAltitudeMode(AltitudeMode.CLAMP_TO_GROUND)
    .addToCoordinates(0.0, 0.0);    // Using 0,0 as placeholder

placemark.setDescription(
    "<button type=\"button\" onclick=\"callAPI()\"/>Call API</button>" +
    "<script type=\"text/javascript\"> " +
    "function callAPI() { " +
    "var xhttp = new XMLHttpRequest(); " +
    "xhttp.open('GET', '" + apiUrl + "', true); " +    // apiURL = url to my REST API
    "xhttp.send(); }" +
    "</script>"
);

Sidenote: I've seen JAK examples that involve including the <![CDATA[...]]> tags around the description, but this caused some formatting issues and didn't seem necessary (when I import the resulting KML file into Google Earth, the HTML in the description works without the tags/the tags themselves seem to appear automatically). I tried putting the tags back in as well, and it didn't fix the problem.

Here is a sample KML file that results from running my code (I've replaced my URL with the fake API URL https://jsonplaceholder.typicode.com/todos/1 as a placeholder):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:kml xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:ns2="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">
    <ns2:Document>
        <ns2:name>My KML File</ns2:name>
        <ns2:open>1</ns2:open>
        <ns2:Style id="balloonstyle">
            <ns2:BalloonStyle id="ID">
                <ns2:text>&lt;font face='Courier' size='3'&gt;$[description]&lt;/font&gt;</ns2:text>
            </ns2:BalloonStyle>
        </ns2:Style>
        <ns2:Folder>
            <ns2:name>Placemark -- Points</ns2:name>
            <ns2:open>1</ns2:open>
            <ns2:Placemark>
                <ns2:name>My Placemark</ns2:name>
                <ns2:visibility>1</ns2:visibility>
                <ns2:open>1</ns2:open>
                <ns2:description>&lt;button type=&quot;button&quot; onclick=&quot;callAPI()&quot;/&gt;Call API&lt;/button&gt;&lt;script type=&quot;text/javascript&quot;&gt; function callAPI() { var xhttp = new XMLHttpRequest(); xhttp.open('GET', 'https://jsonplaceholder.typicode.com/todos/1', true); xhttp.send(); }&lt;/script&gt;</ns2:description>
                <ns2:styleUrl>#balloonstyle</ns2:styleUrl>
                <ns2:Point>
                    <ns2:extrude>0</ns2:extrude>
                    <ns2:altitudeMode>clampToGround</ns2:altitudeMode>
                    <ns2:coordinates>0.0,0.0</ns2:coordinates>
                </ns2:Point>
            </ns2:Placemark>
        </ns2:Folder>
    </ns2:Document>
</ns2:kml>

When I try importing this into Google Earth on Chrome, I get this error when I click the button:

callAPI is not defined at HTMLButtonElement.onclick

Is there something I'm doing wrong within the formatting of the description so it can't tell that I've created the callAPI function?

Or does JavaScript in the Placemark's description balloon not work on Google Earth?

syim
  • 501
  • 1
  • 4
  • 16
  • Where is the `callAPI` function defined? Please provide a [mcve] that demonstrates your issue. – geocodezip May 07 '19 at 21:25
  • I edited to include the KML setup so the code is more complete. `callAPI` is defined in `placemark.setDescription` – syim May 08 '19 at 13:22

1 Answers1

0

Most JavaScript should work in balloons in Google Earth... both in Earth Pro (v7.x, desktop application), and the new Earth for web & mobile (v9.x). Does your KML and balloon code work when loaded in Google Earth Pro?

Since Earth for web is running in the browser, there are some more limitations on loading external resources (images files, etc.) that you might be hitting, including the requirement for CORS headers to be set correctly. Make sure your local server is set to allow CORS requests. IF that doesn't help, can you share a sample KML?

Christiaan Adams
  • 1,257
  • 1
  • 7
  • 13
  • Thanks for your reply. I don't think using Google Earth Pro is an option (I'd like it to be able to work on just the browser). And yes, CORS is enabled on my localhost, so that doesn't seem to be the problem either. I've added a sample KML file to the question. – syim May 09 '19 at 14:28