views:

50

answers:

3

Hello,

I'm trying to include a GoogleMap v3 (everything was okay with v2) in my HTML pages generated with XLS Transformations. My JS code comes from this page.

Basically, the map works correctly when everything is in plain HTML, as per the example, however when I try to include it in the XSL stylesheet, Firefox (v3.6) complains and doesn't want to load anything:

Error: uncaught exception: [Exception... "Operation is not supported" code: "9" nsresult: "0x80530009 (NS_ERROR_DOM_NOT_SUPPORTED_ERR)" location: "http://maps.google.com/maps/api/js?sensor=false Line: 9"]

Error: google.maps.LatLng is not a constructor Source File: file:///home/kevin/google/data.xml Line: 2

Here is a simplified version of the XSL code I'm using:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE xsl:stylesheet >
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:template match="/">
    <html>
      <head>
         <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
         <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
         <style type="text/css">
      html { height: 100% }
      body { height: 100%; margin: 0px; padding: 0px }
      #map_canvas { height: 100% }
         </style>
         <title>Google Maps JavaScript API v3 Example: Map Simple</title>
         <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"&gt;&lt;/script&gt;
         <script type="text/javascript">
      function initialize() {
      var myLatlng = new google.maps.LatLng(-34.397, 150.644);
      var myOptions = {
      zoom: 8,
      center: myLatlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
      }
      var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
      }
         </script>
      </head>
      <body onload="initialize()">
        <div id="map_canvas"></div>
       </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

and a minimalist XML document to trigger the transformation:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE xsl:stylesheet>
<?xml-stylesheet type="text/xsl" href="Display.xsl"?>
<root />

According to my Google investigations, the problem might come from a wrong Doctype, but I don't really know how to fix it, functions like

<xsl:output method="html"
    indent="yes"
    omit-xml-declaration="yes"
    encoding="utf-8"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" />

don't change anything.

EDIT: my actual DOCTYPE is slightly more comple, for XML:

<!DOCTYPE xsl:stylesheet  [<!ENTITY auml   "&#228;" ><!ENTITY ouml   "&#246;" ><!ENTITY uuml   "&#252;" ><!ENTITY szlig  "&#223;" ><!ENTITY Auml   "&#196;" ><!ENTITY Ouml   "&#214;" ><!ENTITY Uuml   "&#220;" ><!ENTITY euml   "&#235;" ><!ENTITY ocirc  "&#244;" ><!ENTITY nbsp   "&#160;" ><!ENTITY Agrave "&#192;" ><!ENTITY Egrave "&#200;" ><!ENTITY Eacute "&#201;" ><!ENTITY Ecirc  "&#202;" ><!ENTITY egrave "&#232;" ><!ENTITY eacute "&#233;" ><!ENTITY ecirc  "&#234;" ><!ENTITY agrave "&#224;" ><!ENTITY iuml   "&#239;" ><!ENTITY ugrave "&#249;" ><!ENTITY ucirc  "&#251;" ><!ENTITY uuml   "&#252;" ><!ENTITY ccedil "&#231;" ><!ENTITY AElig  "&#198;" ><!ENTITY aelig  "&#330;" ><!ENTITY OElig  "&#338;" ><!ENTITY oelig  "&#339;" ><!ENTITY euro   "&#8364;"><!ENTITY laquo  "&#171;" ><!ENTITY raquo  "&#187;" >]>

and XSL:

<!DOCTYPE xsl:stylesheet  [
  <!ENTITY % xhtml-lat1 SYSTEM
     "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent"&gt;
  <!ENTITY % xhtml-special SYSTEM
     "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent"&gt;
  <!ENTITY % xhtml-symbol SYSTEM
     "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent"&gt;
  %xhtml-lat1;
  %xhtml-special;
  %xhtml-symbol;
  ]>

to handle correctly all my accents and special chars, so I'd like to avoid getting rid of it, if possible

EDIT 2: the problem is actually exactly the same with I try to load an OpenStreetMap though Mapstraction API, document.write is not allowed.

Another thing it that Google Map v2 works correctly when I use a callback function:

http://maps.google.com/maps?file=api&amp;v=2.x&amp;key={myKey}&amp;c&amp;async=2&amp;callback={myInitFunct}

Any clue about what can be wrong?

A: 

The correct way to declare stylesheet DOCTYPE:

<!DOCTYPE xsl:stylesheet [ 
  <!ENTITY % HTMLlat1 PUBLIC
       "-//W3C//ENTITIES Latin 1 for XHTML//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent"&gt;
  %HTMLlat1;
  <!ENTITY % HTMLspecial PUBLIC
        "-//W3C//ENTITIES Special for XHTML//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent"&gt;
  %HTMLspecial;
  <!ENTITY % HTMLsymbol PUBLIC
        "-//W3C//ENTITIES Symbols for XHTML//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent"&gt;
  %HTMLsymbol;
]>
Alejandro
@Alejandro, is 1) my code not working and 2) your code working for you? because I've got the same error when I try your example (and for XSLT v2, don't know where I got this number, I'll change it back to v1, where it belongs!)
Kevin
A: 

the solution is to use the callback parameter of the GoogleMap API:

http://maps.google.com/maps/api/js?sensor=false&amp;callback={myInitFunction}

Indeed, as we can see in the generated JS script, they don't insert their code the same way:

With callback:

function getScript(src) {
    var s = document.createElement('script');

    s.src = src;
    document.body.appendChild(s);
  }

Without callback:

function getScript(src) {
document.write('<' + 'script src="' + src + '"' +
               ' type="text/javascript"><' + '/script>');
}

where document.write might be forbidden ...

(however, I don't really understand why they use two different code for the same action, maybe just to solve our problem :)

thanks to this blog for the tutorial

Kevin
A: 

The issue here is that the XSLT output in FF does not behave like static HTML.

In a static HTML page, the GMap script is loaded synchronously so that, when the body.onload event fires, the script is already loaded.

In the XSLT output, the script is still loading when body.onload fires.

I worked around the issue this way (what follows is the XSLT output):

<html>
<head>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&amp;amp;callback=onLoadCode"&gt;&lt;/script&gt;
    <script type="text/javascript">
        function onLoadMaps()
        {
            /// init the maps here
        }

        var zOnLoadCode = false;
        var zOnLoadBody = false;
        function onLoadCode() { zOnLoadCode = true; }
        function onLoadBody() { zOnLoadBody = true; }
        var onLoadTimer = window.setInterval(function() {
            if(zOnLoadCode && zOnLoadBody) {
                window.clearInterval(onLoadTimer);
                onLoadMaps();
            }
        },100,"javascript");
    </script>
</head>
<body onload="onLoadBody();">
    <!-- put your maps here -->
</body>

That is, I used the GMap callback URL param to signal when the script is loaded and the body.onload event to signal when the page is ready, then I wait until both have been fired.

Alessandro Angeli
thanks for you anwser, but in my case, the callback is enough to bypass the problem, no need to check if everything else is already loaded!
Kevin