I have updated my code so now the Map remains in tact when I add the script to place the markers. Unfortunately, The add markers instruction isn't working. The data containing the coordinates is pulled from SQL and converted to JSON using C# and stored as a Hidden Field. This in itself works as it should but I can't seem to get my Script to read the data and pass the info to the map and drop the marker. Here is my code as it stands right now.
<body>
<form id="form1" runat="server">
<asp:HiddenField runat="server" ID="locationData" /> H<%--IDDEN FIELD CONTAINING DATA--%>
</form>
<div class="header">
</div>
<div id="map"></div>
<script type="text/javascript">
function initMap() {
var options = { //MAP LOAD OPTIONS
zoom: 5.8,
center: { lat: 54.251186, lng: -4.463196 }
}
var map = new
google.maps.Map(document.getElementById('map'), options); //LOOADS MAP
// Add Markers
var markers;
var arr = document.getElementById("LocationData"); //CALLS HIDDEN FIELD AND SETS RULES FOR ADDING MARKERS TO THE MAP
if (arr == "") {
markers = {};
}
else {
markers = $.parseJSON(arr.Latitude, arr.Longitude);
};
for (i = 0; i < markers.length; i++) { //LOOPS THROUGH THE DATA AND ADDS MARKER AS PER LAT AND LONG
var data = markers[0];
var myLatlng = new google.maps.LatLng(data.Latitude, data.Longitude);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: data.building
});
}
}
</script>
Mike
I am assuming you are viewing the above html response from asp on a web browser (Google Chrome), so I can help you debug the issue. On the Google chrome at the top right corner click on the '3 dots' (menu) then click on 'More Tools' then click on 'Developer Tools', which would by default open the 'Console' tab window and you can find the error(s) from your html code in 'red' color text. Try to analyze the error and also you can add more çonsole.log() or console.log('') in your JavaScript code, which can provide you more information and help you resolve the issue.
Related
Here's my situation: I have a google sheet of coordinates that I want to map on a simple map. This map I want to put on a sidebar within google sheets. It will get more complex as I go but I'm struggling with the basics.
So I want to import the coordinates of C2:D2 into my HTML so I used this: google.script.run.withSuccessHandler(initMap).selectAddress().
It seems to work for most things but when I use it for the coordinates of the marker, nothing no marker shows up. If I replace
"var lat = CoordArray[0]; var lng = CoordArray[1];"
with
"var lat =51.0366961; var lng = -114.0744921;"
in the HTML, the marker shows up.
Even if I make "var CoordArray= [51.0366961,-114.0744921]" in the JS code, the marker still doesn't show. So the problem has something to do with transferring the information between the two pages.
I just want an interactive map sidebar that's based on coordinates from the sheet that I can kind of understand and modify.
So my JS code page looks like this:
function mapSidebar(){
var html = HtmlService.createHtmlOutputFromFile('Map.html')
.setTitle("Map Sidebar");
SpreadsheetApp.getUi().showSidebar(html);
};
//------------------------------------------------------------------------------------------------
function selectAddress(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("maps?");
var CoordArray = sheet.getRange("C2:D2").getValues(); // C2:D2 = 51.0366961,-114.0744921
return CoordArray;
};
//----------------------------------------------------------------------------------------------
My Html page (Map.html) looks like this:
and yes, I replaced put my API key in the 'https://maps.googleapis.com/' link
<!DOCTYPE html>
<html>
<head>
<style>
#map {
height: 400px; /* The height is 400 pixels */
width: 100%; /* The width is the width of the web page */
}
</style>
</head>
<body>
<h3>My Google Maps Demo</h3>
<div id="map"></div>
<script>
function initMap(CoordArray) {
var lat = CoordArray[0];
var lng = CoordArray[1];
var markerPosition = {lat: lat,lng: lng}
var map = new google.maps.Map(document.getElementById('map'), {
center:{lat: 51.0366961,lng: -114.0744921},
zoom: 8,
});
var marker = new google.maps.Marker({position: markerPosition, map: map});
}
google.script.run.withSuccessHandler(initMap).selectAddress();
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=MY_API_KEY=initMap">
</script>
</body>
</html>
It appears you may be having an issue with the Range.getValues() method in your code. This method returns a 2D array indexed by rows, then by columns.
Try in your initMap() function to get the "lat" and "lng" like so:
function initMap(CoordArray) {
var lat = CoordArray[0][0];
var lng = CoordArray[0][1];
var markerPosition = {
lat: lat,
lng: lng
}
var map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: 51.0366961,
lng: -114.0744921
},
zoom: 8,
});
var marker = new google.maps.Marker({
position: markerPosition,
map: map
});
}
References:
Apps script docs Range.getValues()
I have a HAML file that renders partial that contains map
show.html.haml:
.row
.col-xs-12
.panel-group(style="margin-bottom: 0")
.stat-panel(style="padding: 5px; height:88.89px; margin:0")
.stat-cell.bg.col-md-1.col-sm-3.col-xs-3
%i.fa.fa-map-marker.bg-icon.bg-icon-left{:style => "font-size:60px;line-height:80px;height:80px;"}
.stat-cell.bg.valign-middle(style="padding-left: 40px;")
Geographic Summary
.panel.no-border.no-padding
= render partial: 'map_content', locals: {demographics: #demographics, listicle: #listicle}
And that partial _map_content.html.haml contains map:
.panel-body.no-border.no-padding{:style => "position:relative;height: 600px;"}
#map-container.widget-maps
/%script{:src => "assets/javascripts/bootstrap.min.js"}
/%script{:src => "assets/javascripts/pixel-admin.min.js"}
/%script{:src => "http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"}
/%script{:src => "http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/js/bootstrap.min.js"}
/%script{:src => "http://maps.google.com/maps/api/js?sensor=false"}
:javascript
var map;
var markers=[];
var coord = #{#coordinates};
var la = #{#current_lat};
var lo = #{#current_long};
function setMarkers(locations, lat, lon) {
if (coord.length !=0){
for (var i = 0; i < locations.length; i++) {
var myLatLng = new google.maps.LatLng(locations[i][0], locations[i][1]);
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
animation: google.maps.Animation.DROP
});
markers.push(marker);
}}
var curLatLong = new google.maps.LatLng(lat, lon);
var current_marker = new google.maps.Marker({
position: curLatLong,
map: map,
animation: google.maps.Animation.DROP,
title: 'You are here'
});
markers.push(current_marker);
}
function reloadMarkers() {
for (var i=0; i<markers.length; i++) {
markers[i].setMap(null);
}
markers = [];
setMarkers(coord, la, lo);
}
function init_map() {
var var_mapoptions = {
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: new google.maps.LatLng(39.5202922,-96.2318707),
zoom: 5
}
map = new google.maps.Map(document.getElementById("map-container"),
var_mapoptions);
setMarkers(coord, la, lo);
var mc = new MarkerClusterer(map, markers);
document.getElementById('q-itm').addEventListener('click', reloadMarkers);
}
%script{:src=>"http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/src/markerclusterer.js"}
%script{:src => "https://maps.googleapis.com/maps/api/js?key=AIzaSyCi93_Ajfvl-ZwxPRwqVI98hcqfu2LF3Ic&callback=init_map"}
:cdata
The logic is:
the show.haml has another partial, that has Submit button. After a user enters info in that partial and clicks Submit, only the maps_content partial gets updated (not the whole page). However, I'm getting this error in console (though, everything works fine and I'm just afraid of possible run times errors if someone maybe will click on submit many times):
You have included the Google Maps API multiple times on this page. This may cause unexpected errors.
I understand that this happens because src=>... gets loaded multiple times in the same DIV, after Submit is clicked.
I tried to move src=> upper, to the show file. But then the map would load on the whole page refresh only, but when I would click Submit, it won't load and DIV stands white without a map.
Any suggestions? Thank you
I have been involved in writing a small gem to handle this type of issues:
https://github.com/trialbee/assets_ledger
The basic idea is that your partials register their dependencies in a "ledger" and then the layout asks the ledger what dependencies it should include. And it is up to the ledger to make sure that all dependencies only are included once.
(The easiest version of this is a globally accessible hash)
I have a script that:
pulls results from a database in the form of an XML file
parses those results
creates a marker for each result and places it on a map (a single map for all markers)
at the same times, builds a clickable HTML list (sidebar) containing all those results.
When the user clicks on a place name in the sidebar, the info window from the corresponding marker on the map is automatically displayed. Of course the user can also click directly on a marker on the map, and the same info window is also displayed.
This code has been working fine for several years, but last week I noticed that its behavior was now bugged. When viewing some given results, the first click (either on the map or in the sidebar) works fine (the info window opens and displays the correct information), but the following clicks all show the same information from the first click, all in their respective info window. (To be clear: the information shown is the one from the very first click, not from the previous click.)
I've been trying to debug that for hours but I don't understand why it doesn't work anymore. As you can see in my code below, I tried adding a console.log in the google.maps.event.addListener function, to see what data is being worked with when the marker is clicked, but even there, I don't see anything wrong.
Here is my code (simplified to be more readable):
var side_bar_html = '\n';
var gmarkers = []; // array for created markers
var infoWindow;
var center_lat = <?php echo $position_lat; ?>;
var center_lng = <?php echo $position_lng; ?>;
function createMarker(point, name, html, place_id, map) {
var marker, markerOptions;
markerOptions = {
map: map,
position: point,
dataId: place_id,
icon : 'theme/marker.png',
shadow: 'theme/marker_shadow.png'
};
marker = new google.maps.Marker(markerOptions);
infoWindow = new google.maps.InfoWindow({content: html});
google.maps.event.addListener(marker, 'click', function() {
console.log(this, marker, html);
infoWindow.content = html;
infoWindow.open(map, this);
});
gmarkers.push(marker);
side_bar_html += '\n<li>' + name + '</li>';
return marker;
}
function showPlace(i) {
google.maps.event.trigger(gmarkers[i], 'click');
}
function loadEarth(opt, zoom) {
var map, point, mapCenter, mapOptions;
if (zoom === null) {zoom = 7;}
mapCenter = new google.maps.LatLng(center_lat, center_lng);
mapOptions = {
zoom: zoom,
center: mapCenter,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
point = new google.maps.LatLng(parseFloat(center_lat), parseFloat(center_lng));
if (opt != 0) {
map.setMap(new google.maps.Marker(point));
}
}
// receiving results via XML
function go() {
var map, bounds;
var mapOptions = {
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
bounds = new google.maps.LatLngBounds();
$.ajax({
url : 'url/to/data.xml',
type : 'GET',
dataType : 'xml',
success : function(xml) {
var markers, lat, lng, place_id, point, label, html, marker;
markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
// extract data for each marker
lat = parseFloat(markers[i].getAttribute("lat"));
lng = parseFloat(markers[i].getAttribute("lng"));
place_id = parseFloat(markers[i].getAttribute("place_id"));
point = new google.maps.LatLng(lat,lng);
label = $(markers[i]).find('label').eq(0).text();
html = $(markers[i]).find('infowindow').eq(0).text();
// marker creation
marker = createMarker(point, label, html, place_id, map);
// extend visible zone to newly added marker
bounds.extend(point);
}
map.setCenter(new google.maps.LatLng(center_lat, center_lng), 7);
bounds.extend(point);
if (markers.length>0) {
document.getElementById("side_results").innerHTML = side_bar_html;
map.fitBounds(bounds);
map.setCenter(bounds.getCenter());
} else {
loadEarth();
}
} // end AJAX success
}); // end AJAX
} // end go()
if ($('#places_page').is('.empty')) {
loadEarth(0,8);
} else go();
Any help would be greatly appreciated.
Edit:
As requested, here's a sample of the XML received. In this case, the PHP variables at the start of the script would receive the following values:
$position_lat: 46.9479222
$position_lng: 7.4446085
<?xml version="1.0" encoding="UTF-8"?><markers>
<marker place_id="955" lat="46.950218" lng="7.442429">
<label><![CDATA[<em>Place 955</em><strong>3011 Bern</strong>]]></label>
<infowindow>
<![CDATA[<p><em>Place 955</em><br />Speichergasse 35<br />3011 <ins>Bern</ins></p>]]>
</infowindow>
</marker>
<marker place_id="985" lat="46.942032" lng="7.389993">
<label><![CDATA[<em>Place 985</em><strong>3018 Bern</strong>]]></label>
<infowindow>
<![CDATA[<p><em>Place 985</em><br />Brünnenstrasse 106A<br />3018 <ins>Bern</ins></p>]]>
</infowindow>
</marker>
</markers>
The Google Maps API is included via this line:
<script src="http://maps.google.com/maps/api/js?v=3&sensor=true&language=fr&key=..."></script>
Edit 2:
Changing the API call to force it to use version 3.18 does fix the problem:
<script src="http://maps.google.com/maps/api/js?v=3.18&sensor=true&language=fr&key=..."></script>
Obviously this is a temporary fix, since v. 3.18 won't always be available. Now I need to understand what change in the 3.19 version made this bug appear. Any suggestion is still appreciated. :)
This undocumented usage:
infoWindow.content = html;
May be the issue. Should be:
infoWindow.setContent(html);
The .content property went away or is no longer supported issue
I'm working on a javascript Google map where I have marked the location of each of the state capitals with a custom marker and a title of that capital and state. Right now when you view the map you see the whole US with each marker. I want to keep that but add a sidebar where you click the name of a state and the map zooms to the state and capital. I would also like to add a link that zooms out view the full map. Does anyone have a tutorial on how to do this? I found several examples of Google maps with sidebars but none that zooms to a specific location.
Edit:
This is what I am trying to achieve: http://econym.org.uk/gmap/example_map2.htm
Here is the code I am working with:
<script>
function init() {
var myOptions = {
zoom: 4,
center: new google.maps.LatLng(38.781494, -96.064453),
mapTypeId: google.maps.MapTypeId.ROAD
};
var map = new google.maps.Map(document.getElementById("map"), myOptions);
var image = 'Alabama.png';
var myLatLng = new google.maps.LatLng(32.366805, -86.299969);
var AlabamaMarker = new google.maps.Marker({
position: myLatLng,
map: map,
icon: image,
title:"Montgomery, Alabana"
});
}
google.maps.event.addDomListener(window, 'load', init);
</script>
You need to associate listeners (for example, using jquery) with the click event on your state names. Provided they had an id attribute with the USPS code, it would be something like
jQuery(document).on('click','#RESET',function() {
map.setZoom(5);
map.setCenter({lat:41, lng:-89.5});
});
jQuery(document).on('click','#CA',function() {
map.setZoom(7);
map.setCenter({lat:36.4, lng:-120.9});
});
jQuery(document).on('click','#FA',function() {
map.setZoom(7);
map.setCenter({lat:28, lng:-81});
});
You see, I included one link with id RESET that allows me to reset to the initial state.
Here you can see it at work
http://bl.ocks.org/amenadiel/38e0541592bf331cb298
I have a database of locations which I want to be able to print on a map. Ideally there should be one map with multiple pins for each location you have toggled on. So click a button for location X and it shows up on the map. Click the button for location Y and it shows up on the same map. Click X again and it hides from the map.
Currently I have it so I click on X and the map gets redrawn centered around point X.
Here is the HTML for each button:
<input type='button' data-lat='38.89864400' data-long='-77.05283400'
data-when='20 Aug at 2:00am' value='Location X' class='click' />
The jQuery I'm using is:
jQuery(document).ready(
function initialize() {
jQuery("input.click").click(function() {
showOnMap(jQuery(this).data('lat'), jQuery(this).data('long'), jQuery(this).data('when'));
});
}
);
function showOnMap(lat, long, message) {
var myLatlng = new google.maps.LatLng(lat, long);
var mapOptions = {
zoom: 13,
center: myLatlng
}
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: message
});
google.maps.event.addDomListener(window, 'load', showOnMap);
}
Is there an easy way to switch from what I have to what I want? I've searched for a while but no one seems to be asking this use case in a browser, just Android (which I'm not doing).
Thanks!
There is an example in the documentation on how to hide/show markers. In short, a marker is:
hidden by setting its map to null
showed by setting its map to map
To do so, you will need to access each marker individually. If you have a definite number of locations, it can be done by naming them with different names (eg var markerLocationX, var markerLocationY, etc). Otherwise, the markers need to be stored in an array.
Supposing you have a definite number of known locations to toggle the markers, your javascript code may look like this:
function toggleMarker(markerName) {
if (markerName.getMap() == null) {
markerName.setMap(map);
} else {
markerName.setMap(null);
}
}