{"id":856,"date":"2008-12-20T15:47:17","date_gmt":"2008-12-20T14:47:17","guid":{"rendered":"http:\/\/blog.ginchen.de\/?p=856"},"modified":"2012-05-06T15:07:00","modified_gmt":"2012-05-06T13:07:00","slug":"google-maps-xhtml-konform-einbinden","status":"publish","type":"post","link":"http:\/\/blog.ginchen.de\/en\/2008\/12\/20\/google-maps-xhtml-konform-einbinden\/","title":{"rendered":"Embedding Google Maps XHTML conform"},"content":{"rendered":"<p>I'm quite glad I can write this post, for it allows me to parenthetically intersperse the news that I did not deem worthy of an own post: I have spent the last three days making this site XHTML valid. First I had started with the Transitional version, because otherwise several things which I wanted to keep wouldn't have worked anymore. But then suddenly, I was struck by thunder and thought: \"What the hell are you doing?!\" - And true to my motto \"Completely or not at all\", I began rewriting this site to XHTML&nbsp;Strict. If anybody wants to convince himself of the success of my work, you are welcome to click <a  rel=\"external\" href=\"http:\/\/validator.w3.org\/check?uri=blog.ginchen.de\">here<\/a>. <del datetime=\"2008-12-26T14:18:32+00:00\">(Only the visitors page has not been adapted yet - I still have to figure out how this can be done.)<\/del><\/p>\r\n\r\n<p>A great problem that took me almost a whole day to solve (including search for solutions:\"Google Maps &#252;ber API einbinden(webmasterpro.de)\":http:\/\/www.webmasterpro.de\/coding\/article\/javascript-google-maps-ueber-api-einbinden.html :\"Google Maps API benutzen(drweb.de)\":http:\/\/www.drweb.de\/magazin\/google-maps-api-benutzen\/ ) were the Google&nbsp;Maps I use here and there. Google itself offers a short, single-line code for quick integration of maps on a website, which embeds the map into the page by means of an IFrame. Well, what a pity that IFrames aren't allowed in XHTML&nbsp;Strict. My attempts to take the map URL from the code and somehow embed it as an object failed miserably as well. So there was only one way left: the Google&nbsp;Maps&nbsp;API. In the following, I will try to explain how that works. But one thing beforehand: It is a little more laborious and requires a bit more work than just copying a code snippet and inserting it somewhere.<\/p>\r\n\r\n\r\n<!--more-->\r\n\r\n\r\n\r\n\r\n<p>First of all, you will need a <a  rel=\"external\" href=\"https:\/\/www.google.com\/accounts\/NewAccount\">Google account<\/a> and a <a  rel=\"external\" href=\"http:\/\/code.google.com\/intl\/de-DE\/apis\/maps\/signup.html\">Google API key<\/a>. That doesn't cost anything, and you don't have to reveal private data either. You only have to specify the domain on which the key shall be used. Then we're ready to go.<\/p>\r\n\r\n<h3>Step 1<\/h3>\r\n\r\n<p>First you need to create a <code>&lt;div&gt;<\/code> with a unique ID in the place where the map should appear:<\/p>\r\n\r\n<pre lang=\"html4strict\">\r\n<div id=\"map\" style=\"width: 500px; height: 300px\"><\/div>\r\n<\/pre>\r\n\r\n<h3>Step 2<\/h3>\r\n\r\n<p>Now you have to insert your API key between <code>&lt;head&gt;<\/code> and <code>&lt;\/head&gt;<\/code> as follows:<\/p>\r\n\r\n<pre lang=\"html4strict\">\r\n<script src=\"http:\/\/maps.google.com\/maps?file=api&amp;v=2&amp;key=YOUR_86_DIGIT_API_KEY_HERE\" \r\ntype=\"text\/javascript\"><\/script>\r\n<\/pre>\r\n\r\n<h3>Step 3<\/h3>\r\n\r\n<p>In step 4, we will write a javascript function which creates our map and displays it inside of our <code>&lt;div&gt;<\/code>. We shall call that function <code>load()<\/code>. In order to activate it when loading the page, you have to extend the <code>&lt;body&gt;<\/code> tag as follows:<\/p>\r\n\r\n<pre lang=\"html4strict\">\r\n<body onload=\"load()\" onunload=\"GUnload()\">\r\n<\/pre>\r\n\r\n<p>The function <code>GUnload()<\/code> belongs to the Google&nbsp;API and is useful to minimize memory problems. It is therefore advisable to implement it here.<\/p>\r\n\r\n<h3>Step 4<\/h3>\r\n\r\n<p>Now for the heart of our code, the <code>load()<\/code> function, which will finally create our map. You can put it in the <code>&lt;head&gt;<\/code> section as well; that's not necessarily needed though - you can also insert it at a later point. If you plan to create a very extensive map with many location markers, you can of course write the script into an own .js file for order's sake, and then integrate it like this:<\/p>\r\n\r\n<pre lang=\"html4strict\">\r\n<script type=\"text\/javascript\" src=\"mapscript.js\"><\/script>\r\n<\/pre>\r\n\r\n<p>Now, as for the map, I think it's easiest and most comprehensible if I post a complete example and then explain it:<\/p>\r\n\r\n<pre lang=\"javascript\" line=\"1\">\r\n<script type=\"text\/javascript\">\r\n\/* <![CDATA[ *\/\r\n\tfunction load() {\r\n\t\tvar map = new GMap2(document.getElementById(\"map\"));\r\n\t\tmap.setMapType(G_HYBRID_MAP);\r\n\r\n\t\t\/\/ Arrows and \"+\" and \"-\" buttons in the upper left\r\n\t\tmap.addControl(new GSmallMapControl());\r\n\r\n\t\t\/\/ Buttons \"Map\", \"Satellite\", \"Hybrid\" in the upper right\r\n\t\tmap.addControl(new GMapTypeControl());\r\n\r\n\t\t\/\/ Set center\r\n\t\tvar center = new GLatLng(51.08268706509852, 7.1428728103637695);\r\n\t\tmap.setCenter(center, 15);\r\n\r\n\t\t\/\/ Set location markers\r\n\t\tvar location1 = new GMarker(new GLatLng(51.08268706509852, 7.1489667892456055));\r\n\t\tGEvent.addListener(location1, \"click\", function() {location1.openInfoWindowHtml('<span style=\"color: black\">Description of 1. marker<span>')});\r\n\t\tmap.addOverlay(location1);\r\n\r\n\t\tvar location2 = new GMarker(new GLatLng(51.08188838771136, 7.1381038427352905));\r\n\t\tGEvent.addListener(location2, \"click\", function() {location2.openInfoWindowHtml('<span style=\"color: black\">Description of 2. marker<span>')});\r\n\t\tmap.addOverlay(location2);\r\n\t}\r\n\/* ]]> *\/\r\n<\/script>\r\n<\/pre>\r\n\r\n<ul>\r\n\t<li><em>Lines 2 and 26:<\/em><br \/>\r\n\tThe script is defined as a CDATA section. That allows us to use characters like <code>&lt;<\/code>, <code>&gt;<\/code> etc. inside of the script without the browser interpreting them as HTML and destroying the layout.<\/li>\r\n\r\n\t<li><em>Line 4:<\/em><br \/>\r\n\tThe map is being created and displayed inside the element with the ID \"map\". And that is our <code>&lt;div&gt;<\/code> which we created earlier and which shall contain the map.<\/li>\r\n\r\n\t<li><em>Line 5:<\/em><br \/>\r\n\tThe display type is chosen. There are three options:\r\n\t\t<ul>\r\n\t\t\t<li><code>G_NORMAL_MAP<\/code> - ordinary vectorized map<\/li>\r\n\t\t\t<li><code>G_SATELLITE_MAP<\/code> - satellite photos<\/li>\r\n\t\t\t<li><code>G_HYBRID_MAP<\/code> - a mixture of the former two: satellite photos which are overlaid with the vector map<\/li>\r\n\t\t<\/ul>\r\n\t<\/li>\r\n\r\n\t<li><em>Line 8:<\/em><br \/>\r\n\tThe buttons for zooming and navigation on the map are created. Again, there are three options:\r\n\t\t<ul>\r\n\t\t\t<li><code>GSmallZoomControl()<\/code> - only two small plus and minus buttons for zooming<\/li>\r\n\t\t\t<li><code>GSmallMapControl()<\/code> - plus and minus buttons as well as four arrows<\/li>\r\n\t\t\t<li><code>GLargeMapControl()<\/code> - four arrows and a zoom scale<\/li>\r\n\t\t<\/ul>\r\n\t<\/li>\r\n\r\n\t<li><em>Line 11:<\/em><br \/>\r\n\tThe buttons in the upper right, which allow the user to switch between vector, satellite and hybrid view, are being implemented.<\/li>\r\n\r\n\t<li><em>Line 14:<\/em><br \/>\r\n\tThe center point, i.&nbsp;e. the centering of the map, is defined. For this purpose, you need to specify an exact location in degrees of longitude and latitude. I will explain below how to obtain these data.<\/li>\r\n\r\n\t<li><em>Line 15:<\/em><br \/>\r\n\tThe map is now centered to the previously defined point. Also, the zoom factor is specified here: The higher the value, the further away you are from earth. The smaller the factor, the closer and more detailed is the view.<\/li>\r\n\r\n\t<li><em>Lines 18-20 and 22-24:<\/em><br \/>\r\n\tHere I have created two exemplary location markers. Based on this pattern, you can insert as many additional markers as you like. In the first line, you specify the desired location in degrees of latitude and longitude again, and in the second line you can design the popup, which appears after a click on the marker, with HTML as you wish. When copy&nbsp;&amp;&nbsp;pasting, please don't forget that the identifiers like \"location1\", \"location2\" etc. always appear four times in every section and must be adapted accordingly.<\/li>\r\n<\/ul>\r\n\r\n<h3>Where do I get the latitudes and longitudes?<\/h3>\r\n\r\n<p>As for the coordinates, there are providers who have specialized in this very subject, e.&nbsp;g <a  rel=\"external\" href=\"http:\/\/itouchmap.com\/latlong.html\">itouchmap.com<\/a>. There you can enter an address or just move the marker to the desired position on the map and then immediately read off latitude and longitude.<\/p>\r\n\r\n<h5>The result of all these efforts can for example look like this:<\/h5>\r\n\r\n<div id=\"map\" style=\"margin-top: 10px; width: 500px; height: 300px\"><\/div><br \/>\r\n\r\n<ins datetime=\"2009-10-12T18:02:42+00:00\"><h3>Update (12. October 2009)<\/h3><\/ins>\r\n\r\n<p>Although it's been quite a while now: I remembered the discussion with commentator \"Peter\" every now and then and think that I should elaborate on that again in a more detailed manner:<br \/>\r\nIf you only want to present the customer a \"This document was successfully checked as XHTML 1.0 Strict!\", but actually don't really care what code the browser has to display in the end, you can of course use the trick and just put the invalid parts inside a Javascript. This way they will be ignored by the validator, the browser, however, will later be forced to embed and display them via <code>document.write()<\/code> anyway. You should just ask yourself if that really was the point of it.<\/p>\r\n\r\n<p>The final HTML that the browser has to display using my method consists almost exclusively of containers and images and is thereby as good as valid. You can have a look at it <a  rel=\"external\" href=\"http:\/\/blog.ginchen.de\/wp-content\/uploads\/2008\/12\/googlemap-valid.html\">here<\/a>. (Only the <code>alt<\/code> attributes of the images are missing - unfortunately, Google didn't think of that.)<br \/>\r\nIf, however, you insert the \"bad\" code delivered by Google itself with the help of Javascript, the browser has to display <a  rel=\"external\" href=\"http:\/\/blog.ginchen.de\/wp-content\/uploads\/2008\/12\/googlemap-invalid.html\">this<\/a> afterwards. So, it's an I-Frame again after all. And those simply don't meet the XHTML specifications.<\/p>\r\n\r\n<p>So, it is of course easy to hide bad\/wrong\/invalid code from the <a  rel=\"external\" href=\"http:\/\/validator.w3.org\/\">W3C validator<\/a>, but that was not my concern here. I wanted to show how to implement a Google Map in a way so that the code that finally arrives at the browser is <em>indeed<\/em> valid code and not an invalid one that has just been cleverly smuggled in.<\/p>\r\n\r\n\r\n<script src=\"http:\/\/maps.google.com\/maps?file=api&amp;v=2&amp;key=ABQIAAAAZ-ekaG1rcJT5AK2312ETpxSnBSfGnXbyDBF_svRVVgyFYeLZdxQSPf4KeN7a7tGC4-Hi0a-eS-rUdQ\" \r\ntype=\"text\/javascript\"><\/script>\r\n<script type=\"text\/javascript\">\r\n\/* <![CDATA[ *\/\r\n\tfunction load() {\r\n\t\tvar map = new GMap2(document.getElementById(\"map\"));\r\n\t\tmap.setMapType(G_HYBRID_MAP);\r\n \r\n\t\t\/\/ Links oben Pfeile und \"+\" und \"-\" Tasten\r\n\t\tmap.addControl(new GSmallMapControl());\r\n \r\n\t\t\/\/ Rechts oben Tasten \"Karte\", \"Satellit\", \"Hybrid\"\r\n\t\tmap.addControl(new GMapTypeControl());\r\n \r\n\t\t\/\/ Mittelpunkt setzen\r\n\t\tvar mittelpunkt = new GLatLng(51.08268706509852, 7.1428728103637695);\r\n\t\tmap.setCenter(mittelpunkt, 15);\r\n \r\n\t\t\/\/ Ortsmarken setzen\r\n\t\tvar ortsmarke1 = new GMarker(new GLatLng(51.08268706509852, 7.1489667892456055));\r\n\t\tGEvent.addListener(ortsmarke1, \"click\", function() {ortsmarke1.openInfoWindowHtml('<span style=\"color: black\">Beschreibung der 1. Marke<span>')});\r\n\t\tmap.addOverlay(ortsmarke1);\r\n \r\n\t\tvar ortsmarke2 = new GMarker(new GLatLng(51.08188838771136, 7.1381038427352905));\r\n\t\tGEvent.addListener(ortsmarke2, \"click\", function() {ortsmarke2.openInfoWindowHtml('<span style=\"color: black\">Beschreibung der 2. Marke<span>')});\r\n\t\tmap.addOverlay(ortsmarke2);\r\n\t}\r\n\tload();\r\n\/* ]]> *\/\r\n<\/script>","protected":false},"excerpt":{"rendered":"I'm quite glad I can write this post, for it allows me to parenthetically intersperse the news that I did not deem worthy of an own post: I have spent the last three days making this site XHTML valid. First I had started with the Transitional version, because otherwise several things which I wanted to [&hellip;]","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[139,76],"tags":[140,150,153,154,152],"_links":{"self":[{"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/posts\/856"}],"collection":[{"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/comments?post=856"}],"version-history":[{"count":5,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/posts\/856\/revisions"}],"predecessor-version":[{"id":944,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/posts\/856\/revisions\/944"}],"wp:attachment":[{"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/media?parent=856"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/categories?post=856"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.ginchen.de\/en\/wp-json\/wp\/v2\/tags?post=856"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}