I'm building a store locator type of page. The user types in his/her zip code and then is taken to the results page.
On the results page, I first run geoencode to get the LatLng of the zip code and center the map to it. Then I go through the results div (which is populated from the database) and run geoencode for each of them and set markers for each. All the distance calculations are done on the database side, so I don't have to deal with them here. Then I set an info window and a click event so that when they open they get the appropriate info on their info window. This part all works fine.
The problem I'm having is dealing with when I get more than 10 results from the database. Google maps has a maximum of 10 api calls per second. So I tried creating a more results button, then when click, would display the next 10 results on the page and on the map.
$('#more-results').click(function(){
var $elements = $('#dealer-results-dev li[data-index='+base+']').nextUntil( '#dealer-results-dev li[data-index='+(base + 11)+']' );
$elements.slideDown();
$elements.each(function(index, element){
$element = $(element);
var address = $element.find('span.address').html() + ' ' +$element.find('span.address2').html();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
markers.push(marker);
google.maps.event.addListener(marker, 'click', function() {
var $element = $('#dealer-results li:nth-child('+(index +1)+')')
var contentString = '<div class="content">'+
'<h3>'+ $element.find('h3').html()+'</h3>'+
'<span>' + $element.find('span.distance').html() +'</span><br>'+
'<span>' + $element.find('span.address').html() +'</span><br>'+
'<span>' + $element.find('span.address2').html() +'</span><br>'+
'<span>' + $element.find('span.phone').html() + '</span><br>'+
'<span>Link</span>'+
'</div>';
infowindow.setContent(contentString);
infowindow.open(map,marker);
map.setCenter(results[0].geometry.location);
});
}else{
alert("Geocode was not successful for the following reason: " + status);
}
});
});
base += 10;
});
I tried setting it to 5, but I was still getting the error at the 4th element.
Related
I am trying to combine these three things into one.
http://jsfiddle.net/Dansker/hk5fgbzr/3/ (fiddle 1)
http://jsfiddle.net/Dansker/rnrba8so/10/ (fiddle 2)
data.illinois.gov/resource/wsms-teqm.json (data source)
I want to add pins like I did in fiddle 1 two the code I have in fiddle 2. However I need to use the data different data source. The way I made it work in fiddle 1 was with the latitude and longitude. But because I can not do that with the new data source I need to find a new way. That is why I am trying to add it to fiddle one. Will that work? If so how can I do it? If it wont work what would you suggest using the google maps api?
$.getJSON(URL, function(data, textstatus) {
$.each(data, function(i, entry) {
var contentString = '<div id="content">'+
'<div id="siteNotice">'+
'</div>'+
'<h1 id="firstHeading" class="firstHeading">' + entry.name_ + " Library" + '</h1>'+ '<hr>' +
'<div id="bodyContent">'+
'<p>' + entry.address + " " + entry.zip + '.<br>' +
'<p>' + '' + entry.website.url + '' + '</p>'+
'<p>' + entry.hours_of_operation + '</p>'+
'</div>'+
'</div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: new google.maps.LatLng(entry.location.latitude,
entry.location.longitude),
map: map,
title: entry["dba_name"] + "\n" + entry["address"]
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
});
});
Since you have 2 callback functions, the correct way to do this is to first finish work for first callback, in this case, downloading the JSON and parse them, also I would store all the entry into entries just so that we can use the data when we add the markers, which is called at the end of the first callback.
about the API access limit, sadly I think you have to use the paid google maps geocoding API, or other services like openStreetmaps.
I also have a jsfiddle setup, hope this help.
while generating google map i am sending address to a java script function.sample code:--
java script function code:--
function codeAddress(address) {
// var address = document.getElementById("address").value;
var address;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
`"
cs code :--
"
string addrs= "New York,USA";
Page.ClientScript.RegisterStartupScript(this.GetType(), "a", "codeAddress(" + addrs + ");", true);
"
i am using proper API Key and url. in html its working. but when i pass address from cs file its not working. why? how can i execute above java script function by passing address value.. is there any wrong in code... Thanks
Try
Page.ClientScript.RegisterStartupScript(this.GetType(), "a", "codeAddress('" + addrs + "');", true);
My guess is that it's not interpreted as a string without ''.
I have a leaflet map showing points for public art pieces, rendered from GeoJSON. Next to the map, I created a list of the pieces from the same GeoJSON data and want to be able to click on an item from the list outside of the map and have the related marker's popup come up on the map.
How can I link the list of items to their respective markers through a click event?
My map.js file looks like this:
var map;
var pointsLayer;
$(document).ready(function () {
map = new L.Map('mapContainer');
var url = 'http://{s}.tiles.mapbox.com/v3/mapbox.mapbox-streets/{z}/{x}/{y}.png';
var copyright = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade';
var tileLayer = new L.TileLayer(url, {
attribution: copyright
});
var startPosition = new L.LatLng(41.883333, - 87.633333);
map.on('load', function (e) {
requestUpdatedPoints(e.target.getBounds())
});
map.setView(startPosition, 13).addLayer(tileLayer);
map.on('moveend', function (e) {
requestUpdatedPoints(e.target.getBounds())
})
});
function requestUpdatedPoints(bounds) {
$.ajax({
type: 'GET',
url: '/SeeAll',
dataType: 'json',
data: JSON.stringify(bounds),
contentType: 'application/json; charset=utf-8',
success: function (result) {
parseNewPoints(result);
addToList(result)
},
error: function (req, status, error) {
alert('what happen? did you lose conn. to server ?')
}
})
}
function addToList(data) {
for (var i = 0; i < data.features.length; i++) {
var art = data.features[i];
$('div#infoContainer').append('<div class="info-list-item">' + '<div class="info-list-txt">' + '<div class="title">' + art.properties.wrknm + '</div>' + '<br />' + art.properties.location + '</div>' + '<div class="info-list-img">' + art.properties.img_src + '</div>' + '<br />' + '</div>')
}
$('a.list-link').click(function (e) {
alert('now you see what happens when you click a list item!');
e.preventDefault()
})
}
function parseNewPoints(data) {
if (pointsLayer != undefined) {
map.removeLayer(pointsLayer)
}
pointsLayer = new L.GeoJSON();
var geojsonMarkerOptions = {
radius: 8,
fillColor: "#FF6788",
color: "YELLOW",
weight: 1,
opacity: 1,
fillOpacity: 0.5
};
L.geoJson(data, {
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, geojsonMarkerOptions)
},
onEachFeature: function (feature, pointsLayer) {
pointsLayer.bindPopup(feature.properties.img_src + "<br />" + feature.properties.wrknm + "<br />" + feature.properties.artist + "<br />" + feature.properties.location + '<div class="description">' + feature.properties.descfin + '</div>')
}
}).addTo(map)
}
Felix Kling is right but I'll expand on his comment a little bit...
Since L.LayerGroup and L.FeatureGroup (which L.GeoJSON extends from) don't have methods to retrieve individual layers you will need to either extend from L.GeoJSON and add such a method or keep your own seperate mapping from unique ID to CircleMarker from GeoJSON.
GeoJSON does not require a unique ID but I'll assume that markers in your feed have a unique ID attribute called "id". You will need to add this unique ID to the links that the user can click on so that the links can select the right marker on the map. Then you'll need to store a map of ids to markers in order to retrieve the marker to select it on the map.
markerMap = {}; // a global variable unless you extend L.GeoJSON
// Add the marker id as a data item (called "data-artId") to the "a" element
function addToList(data) {
for (var i = 0; i < data.features.length; i++) {
var art = data.features[i];
$('div#infoContainer').append('<div class="info-list-item">' + '<div class="info-list-txt">' + '<div class="title">' + art.properties.wrknm + '</div>' + '<br />' + art.properties.location + '</div>' + '<div class="info-list-img">' + art.properties.img_src + '</div>' + '<br />' + '</div>')
}
$('a.list-link').click(function (e) {
alert('now you see what happens when you click a list item!');
//Get the id of the element clicked
var artId = $(this).data( 'artId' );
var marker = markerMap[artId];
//since you're using CircleMarkers the OpenPopup method requires
//a latlng so I'll just use the center of the circle
marker.openPopup(marker.getLatLng());
e.preventDefault()
})
}
You need to build the markerMap when you get the data from the server. Your pointToLayer method could be modified to do that:
L.geoJson(data, {
pointToLayer: function (feature, latlng) {
var marker = new L.CircleMarker( latlng, geojsonMarkerOptions );
markerMap[feature.id] = marker;
return marker;
},...
I know this is an older question but Leaflet is on it's way to providing a built-in solution and there is a (somewhat) built-in way to achieve it now...
The approach would be use the layerGroup interface. It provides a method, getLayer, that sounds like it would be perfect get our markers using an ID. However, at this time, Leaflet does not provide any way to specify a custom ID or name.
This issue on Github discusses how this should be done. With that said, you can get and save the auto-generated ID of any Marker (or iLayer for that matter) like so:
let people = [...],
group = L.layerGroup()
people.forEach(person => {
let marker = // ... create marker
group.addLayer( marker );
person.marker_id = group.getLayerId(marker)
})
Now that we have every marker's ID saved with each backing object in our array of data we can easily get the marker later on like so:
group.getLayer(person.marker_id)
See this pen for a full example and this question for more options...
The address I have is a concatenated results[1].formatted_address retrieved from a database containing 6 numbers e.g 530456. I then geocoded it and placed a marker on a google map. This part is successful.
I now want to display the full address, results[0].formatted_address in a infowindow of the marker, so what I did was to reverse geocode the latLng of the marker to obtain the full address but caused the entire map to disappear. The way I did it is as such:
var address;
var eventwindow;
function codeAddress(postal) {
geocoder.geocode( {'address': postal + ", Singapore"}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
eventwindow = new google.maps.InfoWindow();
var markerE = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
});
address = getMarkerAddress(results[0].geometry.location);
google.maps.event.addListener(marker, 'click', function(){
if(eventwindow)
eventwindow.close();
eventwindow = new google.maps.InfoWindow({
content: address,
});
eventwindow.open(map,marker);
});
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
function getMarkerAddress(location) {
geocoder.geocode({'latLng': location}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if(results[0])
{
address = results[1].formatted_address.substring(10);
}
}
else {
alert("Geocoder failed due to: " + status);
}
});
I don't know if I'm doing this right and and not sure where I went wrong. Is there another way to this problem? If so how?
I don't know if I'm doing this right and and not sure where I went wrong. Is there another way to this problem? If so how?
If you know the "correct" address, use that. You haven't provided enough details of your application to make suggestions on how to do that. You can avoid the uncertainty of the geocoder by storing the coordinates that are returned from the geocoder in your database along with the address, then if you find an error, you can fix it.
This article on geocoding strategies might help.
I have a Javascript form where a user inputs an address, city, and state. When this form is submitted, I want the address to be converted into latitude and longitude, and to store those two values to a database. Any help at all is greatly appreciated!
Check this out:
http://batchgeo.com/lookup/
You can use the Google Maps API v3, example:
//get the input from user, in a normal looking address string
var add = this.ListingAddress + ', ' + this.ListingCity + ', ' + this.ListingZipCode;
var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'address': add }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var LatLong = results[0].geometry.location; //here is the LatLong
} else {
alert("Address not found! Error Code: " + status);
}
});