fusion table with sidebar - error in query - google-maps-api-3

I tried to make a map with a sidebar by using a fusion table. I adapted the codes I found on stackoverflows.com but I see an error message : Error in query: Could not parse query.
What is wrong ? The codes are as below:
<!DOCTYPE html>
<html>
<head>
<title>Google Maps JavaScript API v3 Example: Map Simple</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map {
margin: 0;
padding: 0;
height: 100%;
}
</style>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<!--Load the AJAX API-->
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript" >
var tableId = "1zELV0V48On-5c8aqKM_PD2cMQtfy4hByyR5o8sQ";
google.load('visualization', '1', {'packages':['table']});
var map;
var markers = [];
var infoWindow = new google.maps.InfoWindow();
function initialize() {
var istanbul = new google.maps.LatLng(41.049, 28.991);
map = new google.maps.Map(document.getElementById('map_canvas'), {
center: istanbul,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var FTlayer = new google.maps.FusionTablesLayer({query:{from:tableId}, map:map});
var queryStr = "SELECT hotels, location, phone, url FROM "+tableId+" ORDER BY hotels";
document.getElementById('info').innerHTML += queryStr +"<br>";
var queryText = encodeURIComponent(queryStr);
var query = new google.visualization.Query('http://www.google.com/fusiontables/gvizdata?tq=' + queryText);
query.send(getData);
}
function getData(response) {
if (!response) {
alert('no response');
return;
}
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var dt = response.getDataTable();
var side_html = '<table style="border-collapse: collapse" border="1" \
cellpadding="5"> \
<thead> \
<tr style="background-color:#e0e0e0"> \
<th>Hotels</th> \
</tr> \
</thead> \
<tbody>';
document.getElementById('info').innerHTML += "rows="+dt.getNumberOfRows()+"<br>";
for (var i = 0; i < dt.getNumberOfRows(); i++) {
var location = dt.getValue(i,1);
var phone = dt.getValue(i,2);
var hotels = dt.getValue(i,0);
var url = dt.getValue(i,3);
var pt = new google.maps.LatLng(lat, lng);
var html = "<strong>" + hotels + "</strong><br />";
side_html += '<tr> \
<td>' + hotels + '</td> \
</tr>';
createMarker(pt, html);
}
side_html += '</tbody> \
</table>';
document.getElementById("side_bar").innerHTML = side_html;
}
function createMarker(point,info) {
var iconURL = 'tools/pinred.png'; var iconSize = new google.maps.Size(29,60);
var iconOrigin = new google.maps.Point(0,0); var iconAnchor = new google.maps.Point(15,60);
var myIcon = new google.maps.MarkerImage(iconURL, iconSize, iconOrigin, iconAnchor);
var shadowURL = 'tools/pinred.png'; var shadowSize = new google.maps.Size(63, 60);
var shadowOrigin = new google.maps.Point(0, 0); var shadowAnchor = new google.maps.Point(15, 60);
var myShadow = new google.maps.MarkerImage(shadowURL, shadowSize, shadowOrigin, shadowAnchor);
var iconShape = [18,0,20,1,22,2,23,3,24,4,25,5,26,6,27,7,27,8,28,9,28,10,28,11,28,12,28,13,28,14,28,15,28,16,28,17,28,18,28,19,27,20,27,21,26,22,26,23,25,24,24,25,23,26,21,27,20,28,16,29,21,31,21,32,21,33,21,34,21,35,20,36,20,37,20,38,19,39,19,40,19,41,18,42,18,43,18,44,18,45,17,46,17,47,17,48,17,49,16,50,16,51,16,52,15,53,15,54,15,55,14,56,14,57,14,58,14,59,13,59,13,58,13,57,13,56,12,55,12,54,12,53,12,52,11,51,11,50,11,49,11,48,11,47,10,46,10,45,10,44,10,43,9,42,9,41,9,40,9,39,9,38,8,37,8,36,8,35,8,34,8,33,7,32,7,31,12,29,9,28,7,27,6,26,4,25,3,24,3,23,2,22,1,21,1,20,0,19,0,18,0,17,0,16,0,15,0,14,0,13,0,12,0,11,0,10,1,9,1,8,2,7,2,6,3,5,4,4,5,3,6,2,8,1,10,0,18,0];
var myMarkerShape = {
coord: iconShape,
type: 'poly'
};
var myMarkerOpts = {
position: point,
map: map,
icon: myIcon,
shadow: myShadow,
shape: myMarkerShape
};
var marker = new google.maps.Marker(myMarkerOpts);
markers.push(marker);
google.maps.event.addListener(marker, 'click', function() {
infoWindow.close();
infoWindow.setContent(info);
infoWindow.open(map,marker);
});
}
function myclick(num) {
google.maps.event.trigger(markers[num], "click");
}
</script>
<body onload="initialize();">
<table border="1"><tr><td>
<div id="map_canvas" style="width:600px;height:500px;"></div>
</td><td>
<div id="side_bar" style="width:200px;height:300px; overflow: auto;"></div>
</td></tr></table>
<div id="info"></div>
</body>
</html>

Your query is wrong, you are querying for:
var queryStr = "SELECT hotels, location, phone, url FROM "+tableId+" ORDER BY hotels";
The columns in your table have different names (the first character is upper case).
This works for me:
var queryStr = "SELECT Hotels, Location, Phone, Url FROM "+tableId+" ORDER BY Hotels";
But then you will have other problems as your locations don't have coordinates (lat and lng are undefined), you will need to geocode them externally and add a column or two for the geographic coordinates for this to work (you can try geocoding the location on click, but that is not the best way to do it).
proof of concept for geocoding on click - issue: some of the addresses geocode to different locations than are in the FusionTable or don't geocode at all.
The phone number is null because in your table you have that column defined to be of type number, but it contains text.
proof of concept using lat/lng columns in (a copy of) your new table (changed the "phone" column from number to text).

Related

Google Maps API V3 Z-index Not Working

I have a map with about 20 markers on it representing the birthplaces of ancestors. The markers are created from XML. I want the later generations at the front and the earlier generations behind, but Google Maps defaults to the most southerly markers in front. In its simplest form the code looks like this:
<!DOCTYPE html >
<head>
<link rel="stylesheet" href="css/style.css" type="text/css">
<script src="https://maps.googleapis.com/maps/api/js?key=MYKEY" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
var map = null;
var thisLatLng = {lat: 51, lng: -3.5};
function load() {
var map = new google.maps.Map(document.getElementById("map"), {
center: thisLatLng,
zoom: 9,
mapTypeId: 'roadmap'
});
// Change this depending on the name of your PHP file
downloadUrl("php-to-xml.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("person");
var gender = markers[i].getAttribute("gender");
var z_index = markers[i].getAttribute("z_index");
var lat = parseFloat(markers[i].getAttribute("lat"));
var lng = parseFloat(markers[i].getAttribute("lng"));
var point = new google.maps.LatLng(lat,lng);
var comment = markers[i].getAttribute("comment");
var colour = markers[i].getAttribute("colour");
var html = "<b>" + name + "</b> <br/>" + comment;
var icon = "images/" + gender + "_" + colour + ".png";
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon,
optimized: false,
zIndex: z_index
});
}
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
//]]>
</script>
</head>
<body onload="load()">
<div id="map"></div>
</body>
</html>
Values of z-index vary from 100 to 200 in increments of 10, depending on the generation. However I've also tried making them 9100 to 9200, and various other things.
I've seen it suggested that the icons need to have a CSS "position" in order to make z-index work. However I've tried
#map img[src^='/myfamilyroots/images'] {position:relative!important;}
and many variations on that theme without success.
This driving me mad. As far as I can see I have followed the Google Maps reference guide, yet nothing I do will change the way the markers are displayed.
zIndex is expected to be of type Number, but getAttribute() always returns strings.
Convert the string into a Number before you assign the zIndex
var z_index = Number(markers[i].getAttribute("z_index"));

Centering Google Maps from a marker

Im triying to create a map with a marker from a position taken from a database. I succeed creating the map using this tutorial. The problem is that i have to enter manually the center position when i create the map.
¿Is there a way to center the map using the marker?. The code that im using is the following:
<!DOCTYPE html >
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>PHP/MySQL & Google Maps Example</title>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js"></script>
<script type="text/javascript">
//<![CDATA[
var customIcons = {
restaurant: {
icon: 'http://labs.google.com/ridefinder/images/mm_20_blue.png'
},
bar: {
icon: 'http://labs.google.com/ridefinder/images/mm_20_red.png'
}
};
function load() {
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(47.6145, -122.3418),
zoom: 13,
mapTypeId: 'roadmap'
});
var infoWindow = new google.maps.InfoWindow;
// Change this depending on the name of your PHP file
downloadUrl("loadposition.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("address");
var type = markers[i].getAttribute("type");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("Latitud")),
parseFloat(markers[i].getAttribute("Longitud")));
var html = "<b>" + name + "</b> <br/>" + address;
var icon = customIcons[type] || {};
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon
});
bindInfoWindow(marker, map, infoWindow, html);
}
});
}
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
//]]>
</script>
</head>
<body onload="load()">
<div id="map" style="width: 500px; height: 300px"></div>
</body>
</html>
Also my XML generated file looks like this:
<markers>
<marker Latitud="-33.449148" Longitud="-70.552886"/>
</markers>
Thanks a lot!
I used this in an app after adding the marker. Might help you.
bounds = new google.maps.LatLngBounds();
bounds.extend(marker.position);
if (!bounds.isEmpty())
map.panTo(bounds.getCenter());
Original idea was to find the center of a bunch of markers, so this might be overkill.

CEFSharp modifies or truncates geocode address data from Google Maps v3 api

To reproduce, download CefSharp from here:
https://github.com/cefsharp/CefSharp
And run the CefSharp.WinForms.Example
Now run my fiddle on your browser and the CefSharp browser:
http://jsfiddle.net/bjmL9/
I added an alert displaying full address data on click (street_number, route, neighborhood, locality, administrative_area_level_2, administrative_area_level_1, country, postal_code).
Compare the data displayed on your browser to the one on the CefSharp browser.
The problem:
In my browser, the locality shows as "Culiacán Rosales", but on the Cef browser it gets truncated to "Culiacán". The country behaves weird too with Cef displaying "Mexico" instead of "México" (unaccented).
I am on the edge of quitting cef cuz i can't get a google match on this problem and no idea how to fix it...
This is the code of the fiddle since it won't last for ever:
<!DOCTYPE html>
<html>
<head>
<title>Google Map</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<link href="MapStyle.css" rel="stylesheet" type="text/css" media="all"/>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places"></script>
<script>
var map;
var geocoder;
function initialize() {
var placeMarkers = [];
geocoder = new google.maps.Geocoder();
var aquamiller = new google.maps.LatLng(
24.832956,
-107.389775);
var mapOptions = {
zoom: 16,
center: aquamiller,
};
map = new google.maps.Map(
document.getElementById('map-canvas'),
mapOptions);
createSearchBar(map, placeMarkers);
google.maps.event.addListener(
map,
'click',
function(e) {
getAddress(e.latLng, function(address) {
alert(
address.street_number + ', ' +
address.route + ', ' +
address.neighborhood + ', ' +
address.locality + ', ' +
address.administrative_area_level_2 + ', ' +
address.administrative_area_level_1 + ', ' +
address.country + ', ' +
address.postal_code);
});
});
}
function getAddress(latLng, callBack)
{
geocoder.geocode({'latLng': latLng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
var address = {};
var components = results[0].address_components;
for (var i = 0 ; i< components.length ; i++) {
address[components[i].types[0]] = components[i].long_name;
}
callBack(address);
}
else {
alert('No results found');
}
}
else {
alert('Geocoder failed due to: ' + status);
}
});
}
function createSearchBar(map, markers)
{
var input = /** #type {HTMLInputElement} */(document.getElementById('pac-input'));
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
var searchBox = new google.maps.places.SearchBox(/** #type {HTMLInputElement} */(input));
google.maps.event.addListener(searchBox, 'places_changed', function() {
var places = searchBox.getPlaces();
console.log(places);
for (var i = 0, marker; marker = markers[i]; i++) {
marker.setMap(null);
}
markers = [];
var bounds = new google.maps.LatLngBounds();
for (var i = 0, place; place = places[i]; i++) {
var image = {
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
};
// Create a marker for each place.
var marker = new google.maps.Marker({
map: map,
icon: image,
title: place.name,
position: place.geometry.location
});
markers.push(marker);
bounds.extend(place.geometry.location);
console.log(place.geometry.location);
}
map.fitBounds(bounds);
map.setZoom(16);
});
google.maps.event.addListener(map, 'bounds_changed', function() {
var bounds = map.getBounds();
searchBox.setBounds(bounds);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<style>
#target {
width: 345px;
}
</style>
</head>
<body>
<input id="pac-input" class="controls" type="text" placeholder="Search Box">
<div id="map-canvas"></div>
</body>
</html>
Hey wait once more I see the same behavior (missing " Rosales" and accent in "México") with both my standard Chrome 35 and IE 10.
So, maybe it's related to a missing CEF language pack: https://github.com/cefsharp/cef-binary/tree/cef_binary_1.1364.1123/Release/locales .. the NuGet you use probably only has en-US.pak
... Tested a bit more with your fiddle example. Dropping es.pak in my install didn't help. BUT I see similar if I search for "Sønderborg, Denmark" in the search box in the map. (At some locations there it says "S**o**nderborg", no "ø" ) So are you sure its browser related and not just the google API?
update Asking with language=es as in:
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&language=es&libraries=places"></script>
Alters the response from googles API. Currently verified using my iPad and your fiddle!

How to utilize google map MarkerCluster to catch Polygon rather than marker ?

everyone!
How to utilize google map MarkerCluster to catch Polygon rather than Marker ?
My program has about 20,000 markers on Google Map, and it becomes very slow when the data is loading into the map. Then I use JS code to draw one polygon as the replacement of marker. It would run faster. Maybe the PNG image loading for markers exercises negative influence on speed.
Finally, I read this article
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/docs/examples.html
The function 'MarkerCluster' is great. However, it can be only used on the aspect of Google Marker.
var markerClusterer = new MarkerClusterer(map, **markerArray**)
So is there some solution for putting polygon into this cluster mechanism ?
Any help would be greatly appreciated !
I tentatively made an example.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script src="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/src/markerclusterer.js"></script>
<style>
html, body, #map_canvas {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script type='text/javascript'>
var mapCanvas;
function initalize() {
// Creating a map
var mapDiv = document.getElementById("map_canvas");
mapCanvas = new google.maps.Map(mapDiv, {
mapTypeId : google.maps.MapTypeId.ROADMAP
});
// Generate bunch of path data
var sw = new google.maps.LatLng(-19.448292, -152.012329);
var ne = new google.maps.LatLng(76.150236, 58.925171);
var bounds = new google.maps.LatLngBounds(sw, ne);
mapCanvas.setCenter(bounds.getCenter());
mapCanvas.setZoom(3);
var baseLat, baseLng, category, json = [], path;
for (var i = 0; i < 100; i++) {
baseLat = Math.random() * (ne.lat() - sw.lat()) + sw.lat();
baseLng = Math.random() * (ne.lng() - sw.lng()) + sw.lng();
path = [
new google.maps.LatLng(baseLat, baseLng),
new google.maps.LatLng(baseLat + 1, baseLng + 1),
new google.maps.LatLng(baseLat, baseLng + 2)
];
json.push(path);
}
var bounds, polyList = [];
for (var i = 0, length = json.length; i < length; i++) {
var polyline = createPolygon(json[i]);
polyList.push(polyline);
}
var clusterer = new MarkerClusterer(mapCanvas, polyList);
}
function createPolygon(path) {
var polygon = new google.maps.Polygon({
path : path,
strokeOpacity : 1,
strokeColor : "red"
});
var lastPath = null,
lastCenter = null;
polygon.getPosition = function() {
var path = this.getPath();
if (lastPath == path) {
return lastCenter;
}
lastPath = path;
var bounds = new google.maps.LatLngBounds();
path.forEach(function(latlng, i) {
bounds.extend(latlng);
});
lastCenter = bounds.getCenter()
return lastCenter;
};
return polygon;
}
google.maps.event.addDomListener(window, "load", initalize);
</script>
</head>
<body>
<div id="map_canvas"></div>
</body>
</html>

markerclusterer limits

Hi this is my first post here..
I have been playing around with google maps trying to make a list of campsites in France.
I have got to the point of reading an xml file of the data
Loading the map and clustering the results and it all works but very slow.
Q1 Is there a limit on the number of markers you can render even using the clusterer (there are >7000 records at the moment)
Q2
Is there anything obviously wrong with the code I have so far:
<!DOCTYPE html>
<html>
<head>
<title>Read XML in Microsoft Browsers</title>
<script src="http://maps.google.com/maps/api/js?sensor=false&language=en&region=GB" type="text/javascript"></script>
<script src="scripts/markerclusterer.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="stylesheets/style_1024.css" />
<script type="text/javascript">
var xmlDoc;
function loadxml() {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.onreadystatechange = readXML;
xmlDoc.load("xml_files/France_all.xml");
}
function readXML() {
if (xmlDoc.readyState == 4) {
//alert("Loaded");
//set up map
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: new google.maps.LatLng(0, 0),
mapTypeControl: true,
mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU },
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var bounds = new google.maps.LatLngBounds();
var infowindow = new google.maps.InfoWindow({ maxWidth: 100 });
var marker, i
var markers = [];
var html = [];
var x = (xmlDoc.getElementsByTagName("placemark").length);
//for (i = 0; i < x; i++) {
for (i = 0; i < x; i++) {
//document.write(xmlDoc.documentElement.childNodes[1].firstChild.tagName) + '<br>';
desc = xmlDoc.getElementsByTagName("description")[i].text;
lat = parseFloat((xmlDoc.getElementsByTagName("latitude")[i].text));
lon = parseFloat((xmlDoc.getElementsByTagName("longitude")[i].text));
myicon = (xmlDoc.getElementsByTagName("icon")[i].text);
//create new point
var point = new google.maps.LatLng(lat, lon);
//create new marker
marker = new google.maps.Marker({
position: point,
panControl: false,
map: map,
icon: myicon
});
//increae map bounds
bounds.extend(point);
//fit to bounds
map.fitBounds(bounds);
//add reference to arrays
markers.push(marker);
html.push(desc);
//add listener
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
infowindow.setContent(html[i]);
infowindow.open(map, marker);
}
})(marker, i));
//alert(i + " " + desc +" added!");
};
//var mc = new MarkerClusterer(map);
var mcOptions = {gridSize: 50, maxZoom: 15 };
var mc = new MarkerClusterer(map, markers, mcOptions);
}
}
</script>
</head>
<body onload="loadxml()">
<div style="height:100%; width:100%">
<div id="map" style="float:left; width:50%; height:100%">
<!--filled via script-->
</div>
<div style="float:left; width:50%; height:100%">
<h4>Select Region</h4>
<select>
<option value="Alsace" onclick="loadxml()">Alsace</option>
</select>
</div>
</div>
</body>
</html>
This article may help. A tile based solution (FusionTables, KmlLayer, or a server based custom map) will render more quickly than native Google Maps API v3 objects, even with clustering. You may be seeing the transfer and processing time of the xml file.

Resources