Google Maps API V3 usage in addon - google-maps

I have learned to use the API V3 making use of HTML + JavaScript, as I did here: http://jsfiddle.net/hCymP/4/
HTML:
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
JAVASCRIPT:
var mapContainer = document.createElement('div');
mapContainer.setAttribute('style',"width: 500px; height: 300px");
document.body.appendChild(mapContainer);
var mapOptions = {
center: new google.maps.LatLng(-35.000009, -58.197645),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(mapContainer,mapOptions);
but now I need to move it to a firefox addon (it's a "Firefox for Android" addon but I think this problem can be applied to desktop addon too and chrome addons).
The problem is you need to do everything via javascript in addons, so I can not include the following line:
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
SO I try to resolve that with loadSubScript, but it returned an empty div:
Components.utils.import("resource://gre/modules/Services.jsm");
Services.scriptloader.loadSubScript("https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false", window, "utf8");
var mapContainer = window.content.document.createElement('div');
mapContainer.setAttribute('id', "map");
mapContainer.setAttribute('style',"width: 250px; height: 250px");
var mapOptions = {
center: new window.google.maps.LatLng(latitude, longitude),
zoom: 5,
mapTypeId: window.google.maps.MapTypeId.ROADMAP
}
var map = new window.google.maps.Map(mapContainer,mapOptions);
return mapContainer;
So I tryed looking inside https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false to "copy" that code and call it from my addon. And I downloaded the Google Maps Api file and I included into my project to be able to retrieve the catch errors... But returned me an empty div too:
Components.utils.import("resource://gre/modules/Services.jsm");
// Same as HTML <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
window.google = window.google || {};
window.google.maps = window.google.maps || {};
var modules = window.google.maps.modules = {};
window.google.maps.__gjsload__ = function(name, text) { modules[name] = text;};
window.google.maps.Load = function(apiLoad) {
delete window.google.maps.Load;
apiLoad([0.009999999776482582,[[["https://mts0.googleapis.com/vt?lyrs=m#227000000\u0026src=api\u0026hl=en-US\u0026","https://mts1.googleapis.com/vt?lyrs=m#227000000\u0026src=api\u0026hl=en-US\u0026"],null,null,null,null,"m#227000000"],[["https://khms0.googleapis.com/kh?v=134\u0026hl=en-US\u0026","https://khms1.googleapis.com/kh?v=134\u0026hl=en-US\u0026"],null,null,null,1,"134"],[["https://mts0.googleapis.com/vt?lyrs=h#227000000\u0026src=api\u0026hl=en-US\u0026","https://mts1.googleapis.com/vt?lyrs=h#227000000\u0026src=api\u0026hl=en-US\u0026"],null,null,null,null,"h#227000000"],[["https://mts0.googleapis.com/vt?lyrs=t#131,r#227000000\u0026src=api\u0026hl=en-US\u0026","https://mts1.googleapis.com/vt?lyrs=t#131,r#227000000\u0026src=api\u0026hl=en-US\u0026"],null,null,null,null,"t#131,r#227000000"],null,null,[["https://cbks0.googleapis.com/cbk?","https://cbks1.googleapis.com/cbk?"]],[["https://khms0.googleapis.com/kh?v=80\u0026hl=en-US\u0026","https://khms1.googleapis.com/kh?v=80\u0026hl=en-US\u0026"],null,null,null,null,"80"],[["https://mts0.googleapis.com/mapslt?hl=en-US\u0026","https://mts1.googleapis.com/mapslt?hl=en-US\u0026"]],[["https://mts0.googleapis.com/mapslt/ft?hl=en-US\u0026","https://mts1.googleapis.com/mapslt/ft?hl=en-US\u0026"]],[["https://mts0.googleapis.com/vt?hl=en-US\u0026","https://mts1.googleapis.com/vt?hl=en-US\u0026"]],[["https://mts0.googleapis.com/mapslt/loom?hl=en-US\u0026","https://mts1.googleapis.com/mapslt/loom?hl=en-US\u0026"]],[["https://mts0.googleapis.com/mapslt?hl=en-US\u0026","https://mts1.googleapis.com/mapslt?hl=en-US\u0026"]],[["https://mts0.googleapis.com/mapslt/ft?hl=en-US\u0026","https://mts1.googleapis.com/mapslt/ft?hl=en-US\u0026"]]],["en-US","US",null,0,null,null,"https://maps.gstatic.com/mapfiles/","https://csi.gstatic.com","https://maps.googleapis.com","https://maps.googleapis.com"],["https://maps.gstatic.com/intl/en_us/mapfiles/api-3/13/11","3.13.11"],[2256293068],1.0,null,null,null,null,0,"",null,null,1,"https://khms.googleapis.com/mz?v=134\u0026",null,"https://earthbuilder.googleapis.com","https://earthbuilder.googleapis.com",null,"https://mts.googleapis.com/vt/icon"], loadScriptTime);
};
var loadScriptTime = (new window.Date).getTime();
//I can't use document.write but use loadSubScript insthead
Services.scriptloader.loadSubScript("chrome://googleMaps/content/Google-Maps-V3.js", window, "utf8"); //chrome://MoWA/content/Google-Maps-V3.js", window, "utf8");
var mapContainer = window.content.document.createElement('div');
mapContainer.setAttribute('id', "map");
mapContainer.setAttribute('style',"width: 500px; height: 300px");
mapContainer.style.backgroundColor = "red";
var mapOptions = {
center: new window.google.maps.LatLng(latitude, longitude),
zoom: 5,
mapTypeId: window.google.maps.MapTypeId.ROADMAP
}
var map = new window.google.maps.Map(mapContainer,mapOptions);
return mapContainer;
Any idea?
Project source code: https://www.dropbox.com/sh/zhsyhebsygh74nw/RV4CxPiK8d

Using the Addon SDK, you can use a pagemod to modify the contents of a page (looks like you're injecting the maps on a page). There, you can specify contentScriptFiles, where one can be your local version of the google maps JS API, and the other your specific addon code that will run on the page. This will save you from having to deal with sandboxed/scope madness with loadSubScript.
let { url: getLocal } = require("sdk/self").data;
let { PageMod } = require("sdk/page-mod");
pageMod.PageMod({
include: "*.mozilla.org",
contentScriptFile: [
getLocal("googlemaps.js"),
getLocal("my-script.js")
]
});

Related

google maps api findplace request not working properly

I want to display on my webpage the location from a JSON that has displayed a pharmacy name. The point is that google maps API is a little bit over my power of knowledge. I did a find-place request into the google maps API, but the location that is displayed is the one from my current location.
Here is the part of the code that would interest you
<div id="map"></div>
<script src="./keys.js"></script>
<script>
let map;
document.addEventListener("DOMContentLoaded", () => {
let s = document.createElement("script");
document.head.appendChild(s);
s.addEventListener("load", () =>
{
console.log("script has loaded");
x = navigator.geolocation;
x.getCurrentPosition(success, failure)
function success(position){
var myLat = position.coords.latitude;
var myLong = position.coords.longitude;
var coords = new google.maps.LatLng(myLat,myLong);
map = new google.maps.Map(document.getElementById("map"), {
center: coords,
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var marker = new google.maps.Marker({
map: map,
position: coords,
})
}
function failure(){}
});
s.src = `https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=<%= "#{#medicament['farmacies'].first['name']}"%>&inputtype=textquery&fields=formatted_address,name,rating,opening_hours,geometry&key=**************`;
});
</script>
</div>
where <%= "#{#medicament['farmacies'].first['name']}"%> represents the name of the pharmacy from the html erb file.
What I found strange is that if I inspect the page where the location is the s.src takes me to a JSON that has all the right address information for the pharmacy.
Here you can see an image with the response from the API:
What I want is to point to the address of that pharmacy on google map. Any tips&tricks are very welcome!
Use google.maps.places.PlacesService.findPlaceFromQueryinstead.
Also see this tutorial.
var service = new google.maps.places.PlacesService();
var request = {
query: 'Museum of Contemporary Art Australia',
fields: ['name', 'geometry'],
};
const {results} = service.findPlaceFromQuery(request);

google map api eliminate calling twice

I'm just starting json and google maps api using this video tutorial on youtube from 2013 as the example. I've got the demo map to display but it's giving me a
You have included the Google Maps API multiple times on this page. This may cause unexpected errors.
The original code didn't have an api key call, which I added, but I guess that calls the api twice. How do I not call the api twice?
<head>
<script src="https://maps.google.com/maps/api/js?sensor=false"></script>
<script>
// The web service URL from Drive 'Deploy as web app' dialog.
var DATA_SERVICE_URL = "https://script.google.com/macros/s/SPREADSHEET_ID/exec=?jsonp=callback";
var map;
function initialize() {
map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(0, 0),
zoom: 2,
maxZoom: 20,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var scriptElement = document.createElement('script');
scriptElement.src = DATA_SERVICE_URL;
document.getElementsByTagName('head')[0].appendChild(scriptElement);
}
function callback(data) {
for (var i = 0; i < data.length; i++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(data[i][3], data[i][2]),
map: map
});
}
}
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=#######&callback=jsonp"></script>
</head>
Oh, apparently the sensor parameter is no longer needed so I can just
<head>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=#######&callback=jsonp"></script>
<script>
// The web service URL from Drive 'Deploy as web app' dialog.
var DATA_SERVICE_URL = "https://script.google.com/macros/s/SPREADSHEET_ID/exec=?jsonp=callback";
var map;
function initialize() {
map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(0, 0),
zoom: 2,
maxZoom: 20,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var scriptElement = document.createElement('script');
scriptElement.src = DATA_SERVICE_URL;
document.getElementsByTagName('head')[0].appendChild(scriptElement);
}
function callback(data) {
for (var i = 0; i < data.length; i++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(data[i][3], data[i][2]),
map: map
});
}
}
</script>
</head>

Reassign google map var to new div

I'm using react and I have a component that renders a google map view when it mounts.
I'd like to save the google map var globally and when so that when the component is unmounted then remounted I can just reassign the map to a div instead of recreating it. Is this possible?
So Something like this
/** #jsx React.DOM */
var React = require('react');
window.coverage_map = null;
var CoverageMap = React.createClass({
componentDidMount: function(){
if(window.coverage_map == null){
var ele = React.findDOMNode(this.refs.map);
window.coverage_map = new google.maps.Map(ele, {
center: {lat: 37.7833, lng: -122.4167},
mapTypeControlOptions: {
mapTypeIds: [google.maps.MapTypeId.ROADMAP, 'map_style']
}
});
}
else{
//reassign google map
}
},
render(){
// render code
},
})
No - the root element of a map cannot be changed once instantiated.

How to display image from my kml file onto a Google map in a sidebar

I am editing my question after spending 3 days unable to figure this out:
I have had a website of all stairs in Seattle that showed a description and image when a marker was clicked. It has been working well for a couple of years.
(http://seattlestairs.home.comcast.net/~seattlestairs)
Then google changed the format of their kml files and if I substitute the NEW kml for the OLD one, I no longer can see the image. You can see this at:
(http://seattlestairs.home.comcast.net/~seattlestairs/index2.html)
However, if I just embed my map into a webpage and click on the marker, the info window pops up and shows the image and description.
However, I don't like that because the images are too small to see details.
I want my sidebar images back and was hoping somebody could tell me how to change the code to make that happen. (I am just an amateur programmer). The comments suggested using a parser and I am able to get the gist of that but I can not figure out exactly how to do it.
Here is the structure of a placemark in the OLD kml file:
<Placemark>
<name>#176 John St</name>
<description><![CDATA[<div ><img style="width:400px" src="http://lh6.ggpht.com/_izunqcjpHto/TIx-yqN7PdI/AAAAAAAADXw/lt7xzoZ1ivI/s720/%23176%20side.jpg"><br>67 steps</div>]]></description>
<styleUrl>#ordinary</styleUrl>
<Point>
<coordinates>-122.282104,47.618984,0.000000</coordinates>
</Point>
Here it is in the NEW kml file:
<Placemark>
<styleUrl>#icon-ci-1</styleUrl>
<name>#176 John St</name>
<ExtendedData>
<Data name='gx_media_links'>
<value>http://lh6.ggpht.com/_izunqcjpHto/TIx-yqN7PdI/AAAAAAAADXw/lt7xzoZ1ivI/s720/%23176%20side.jpg</value>
</Data>
</ExtendedData>
<description><![CDATA[67 steps]]></description>
<Point>
<coordinates>-122.282104,47.618984,0.0</coordinates>
</Point>
</Placemark>
I previously used a sample java script to do this and just put the "description" into the infowindow. Now with the new kml files the source of the image is in a "extended data" and I don't know the right way to access that image information. I can get the name and description but not the image.
My old script looked like this:
<script type="text/javascript">
function initialize() {
var latlng = new google.maps.LatLng(47.605, -122.333);
var myOptions = {
zoom: 12,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
var stairLayer = new google.maps.KmlLayer('http://seattlestairs.home.comcast.net/~seattlestairs/SeattleStairs97.kml',
{preserveViewport: true, suppressInfoWindows:true});
stairLayer.setMap(map);
google.maps.event.addListener(stairLayer, 'click', function(kmlEvent) {
var text = kmlEvent.featureData.description;
text = kmlEvent.featureData.name + text;
showInContentWindow(text);
});
function showInContentWindow(text) {
var sidediv = document.getElementById('content_window');
sidediv.innerHTML = text;
}
}
</script>
So where is said "text = kmlEvent.featureData.description" there needs to be some code that will allow me to get the src of the image, and then to put that into html into the sidediv, but I don't know how.
KmlLayer (API Reference) does not let you access any of the data from the KML except on a click. If you use a 3rd party KML parser (like geoxml3 or geoxml-v3) you can use whatever information you want from the KML
One option is to use a third party parser (like the KMZ branch of geoxml3) which allows you to access the <ExtendedData> in the KML.
var map;
var geoXmlDoc;
function initialize() {
var latlng = new google.maps.LatLng(47.605, -122.333);
var myOptions = {
zoom: 12,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
var myParser = new geoXML3.parser({
map:map,
afterParse: useTheData,
suppressInfoWindows: true,
suppressDirections: true
});
google.maps.event.addListenerOnce(map, 'idle', function() {
for (var i = 0; i < geoXmlDoc.placemarks.length; i++) {
var placemark = geoXmlDoc.placemarks[i];
if (placemark.marker) {
createClickableMarker(placemark);
}
}
});
myParser.parse("http://www.geocodezip.com/geoxml3_test/kml/newSeattleStairs.kml");
}
function showInContentWindow(text) {
var sidediv = document.getElementById('content_window');
sidediv.innerHTML = text;
}
function createClickableMarker(placemark) {
google.maps.event.addListener(placemark.marker,'click',function(e){
var htmlString =placemark.name+"<br>"+placemark.description;
var media_imgs = placemark.vars.val.gx_media_links.split(" ");
for (var i=0; i < media_imgs.length; i++) {
htmlString += "<br><img src='"+placemark.vars.val.gx_media_links+"' width='400'/>";
}
showInContentWindow(htmlString)
});
}
function useTheData(doc){
geoXmlDoc = doc[0];
};
google.maps.event.addDomListener(window, 'load', initialize);
proof of concept (there seem to be issues with the click targets for the icons, but it can be made to work). Note that third party parsers render the KML as native Google Maps Javascript API v3 objects, so will not have the performance of the tile based rendering of KmlLayer.
This way works on Chrome and Firefox and Safari, can't tell about IE:
I altered the kml file from Google Maps into an xml file by deleting the "kml" tags and icon info, and I read about xml path from the W3 online teaching, and then modified their example.
So, first I used the Google-maps event feature to get the name of the stairway.
Then I loaded the xml file and used the "evaluate" function to get the source for my images (called value" in the kml file):
<script>
var smoname = " ";
var smodev = " ";
// this will set up the google map in the right location
function initialize() {
var myLatlng = new google.maps.LatLng(47.605, -122.333);
var mapOptions = {
zoom: 13,
center: myLatlng
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
//Here is the raw kml file as exported from google maps
var kmlLayer = new google.maps.KmlLayer({
url: 'http://seattlestairs.home.comcast.net/~seattlestairs/newSeattleStairs.kml',
suppressInfoWindows: true,
map: map
});
google.maps.event.addListener(kmlLayer, 'click', function(kmlEvent) {
//gets the name of the stairway when the icon is clicked
smoname = kmlEvent.featureData.name;
smodef = kmlEvent.featureData.description;
smoin = smoname +"<br>"+ smodef;
showInContentWindow(smoin);
//looks up the url of the image from the name
function loadXMLDoc(dname)
{
if (window.XMLHttpRequest)
{
xhttp=new XMLHttpRequest();
}
else
{
xhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.open("GET",dname,false);
try {xhttp.responseType="msxml-document"} catch(err) {} // Helping IE
xhttp.send("");
return xhttp;
}
var x=loadXMLDoc("AllSeattleStairs.xml");
var xml=x.responseXML;
path="/Document/Placemark[name= '" + smoname + "']/ExtendedData/Data/value";
// code for IE
if (window.ActiveXObject || xhttp.responseType=="msxml-document")
{
xml.setProperty("SelectionLanguage","XPath");
nodes=xml.selectNodes(path);
document.getElementById("showme").innerHTML = "<img width = 400px src =' " + nodes.childNodes[0].nodeValue + " ' ></src>";}
// code for Chrome, Firefox, Opera, etc.
else if (document.implementation && document.implementation.createDocument)
{
var nodes=xml.evaluate(path, xml, null, XPathResult.ANY_TYPE, null);
var result=nodes.iterateNext();
document.getElementById("showme").innerHTML = "<img width = 400px src =' " + result.childNodes[0].nodeValue + " ' ></src>";
}
});
function showInContentWindow(smoin) {
var sidediv = document.getElementById('content-window');
sidediv.innerHTML = smoin; }
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>

Geo-location added to standard custom google map

I am trying to add geo-location to a custom public google map, I can't manage to get it to work. For example here is a custom public google map.
Lets say I wanted to add geo-targeting to that map. I have the following on the site which is directly off the google maps API website:
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true"></script>
as well as the following which I just changed '.getElementsById' to '.getElementsByClassName':
<script type="text/javascript">
var map;
function initialize() {
var mapOptions = {
zoom: 3,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementsByClassName('map-canvas'),
mapOptions);
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: 'Location found using HTML5.'
});
map.setCenter(pos);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
}
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = 'Error: The Geolocation service failed.';
} else {
var content = 'Error: Your browser doesn\'t support geolocation.';
}
var options = {
map: map,
position: new google.maps.LatLng(60, 105),
content: content
};
var infowindow = new google.maps.InfoWindow(options);
map.setCenter(options.position);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
Then I call for the map which is in a lightbox:
<h2 class="dis">Where can I<br />get Rumble?</h2>
It displays the map fine, and asks to geo-target but I assume the reason its not working on this map is because its not included in the API.
I was hoping someone had a solution for this.
This is not an API based map. You can display the KML from that map on an API based map
Then use your geolocation code to center the map (depending on the ordering, you might need to use the preserveViewport:true option on the KmlLayer). Relevant code below, see the documenation for more examples and information.
This is in your existing page (leave your version)
var myOptions = {
zoom: 5,
center: new google.maps.LatLng(0,0),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
Add this to display the data from your "custom map":
var kmlLayer = new google.maps.KmlLayer("https://maps.google.ca/maps/ms?ie=UTF8&msa=0&output=kml&msid=202458571791405992786.0004b9061a3fcd9461d42");
kmlLayer.setMap(map);