Geocode Javascript problem - javascript

I wonder whether someone may be able to help me please.
Because of loading issues, I've moved the map options code to my HTML form, rather than it being in a separate Javascript file.
The problem is that I now can't get the Geocode functionality to work. I've added my code below. I'm sure it must be something simple, but I'm a little perplexed by this. I just wondered whether it would be at all possible please that someone could let me know where I've gone wrong.
Many thanks
function geocode() {
// This is defining the global variables
var geocoder, marker;
// This is making the link with the 'Search For Location' HTML form
var form = document.getElementById('searchforlocationform');
// This is catching the forms submit event
form.onsubmit = function() {
// This is getting the Address from the HTML forms 'Address' text box
var address = document.getElementById('inputaddress').value;
// This is making the Geocoder call
getCoordinates(address);
// This is preventing the form from doing a page submit
return false;
}
}
function geocodePosition(pos) {
geocoder.geocode({
latLng: pos
},
function(responses) {
if (responses && responses.length > 0) {
updateMarkerAddress(responses[0].formatted_address);
} else {
updateMarkerAddress('Cannot determine address at this location.');
}
});
}
//New Code
function updateMarkerStatus(str) {
document.getElementById('markerStatus').innerHTML = str;
}
//Changed 'address' to 'returnedaddress'
function updateMarkerAddress(str) {
document.getElementById('returnedaddress').value= str;
}
// This creates the function that will return the coordinates for the address
function getCoordinates(address) {
// This checks to see if there is already a geocoded object. If not, it creates one
if(!geocoder){geocoder = new google.maps.Geocoder();}
// This is creating a GeocoderRequest object
var geocoderRequest = {address: address}
// This is making the Geocode request
geocoder.geocode(geocoderRequest, function(results, status) {
// Check if status is OK before proceeding
if (status == google.maps.GeocoderStatus.OK) {
// Center the map on the returned location
map.setCenter(results[0].geometry.location);
// Check to see if we've already got a Marker object
if (!marker) {
map.setZoom(16);
marker = new google.maps.Marker({
map: map, draggable:true
});
}
// Setting the position of the marker to the returned location
marker.setPosition(results[0].geometry.location);
// Add dragging event listeners.
google.maps.event.addListener(marker, function() {
updateMarkerAddress;
});
//This fills out the 'Latitude' and 'Longitude' text boxes on the HTML form
document.getElementById('osgb36lat').value= results[0].geometry.location.lat();
document.getElementById('osgb36lon').value= results[0].geometry.location.lng();
//This allows the marker to be draggable and tells the 'Latitude' and 'Longitude' text boxes on the HTML form to update with the new co-ordinates as the marker is dragged
google.maps.event.addListener(marker,'dragend',
function() {
updateMarkerStatus;
geocodePosition(marker.getPosition());
document.getElementById('osgb36lat').value = marker.position.lat();
document.getElementById('osgb36lon').value = marker.position.lng();
});
// Update current position info.
latLng = [marker.position.lat(), marker.position.lng()].join(', ');
geocodePosition(marker.getPosition());
var point = marker.getPosition();
map.panTo(point);
}
}
)
}
<script type="text/javascript">
(function() {
window.onload = function(){
var latlng = new google.maps.LatLng(54.312195845815246,-4.45948481875007);
var options = {
zoom: 6,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.TOP_RIGHT
},
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.ZOOM_PAN,
position: google.maps.ControlPosition.TOP_LEFT
},
scaleControl: true,
scaleControlOptions: {
position: google.maps.ControlPosition.BOTTOM_LEFT
}
};
var map = new google.maps.Map(document.getElementById('map'), options);
}
})();
</script>

You seen to be trying to call updateMarkerAddress with updateMarkerAddress; and updateMarkerStatus with updateMarkerStatus;, here you are missing (/*some param*/).
What are the loading issues? Maybe if you show your html someone could help with that too.

Related

Variable value is undefined in Javascript

I am trying to get the user location by using HTML5 geolocation. The lat and lng value are received successfully and I can show it on the map. I want to save the user location to use it later so I defined origin variable and I concatenated the lat and lng variables and then I assigned the concatenated value to origin. When I am trying to use the origin value later its value is undifined. Could someone please tell me when the problem is in the code. I guess the problem is very silly but I cannot solve it. I don't think the problem is related to variable scope.
Here is the code:
let map ;
// initialize the map and show it on the dashboard.
function initMap()
{
// Map options.
let options =
{
center :
{
lat : 41.015137,
lng : 28.979530
},
zoom : 12
}
// New map.
map = new google.maps.Map
(
document.getElementById('map'),
options
);
};
$(document).ready
(
function()
{
$("#order_and_show").click
(
function()
{
// Change the text of the title and the button when get order from the user.
$('#order_title').text('Cancel the order right now') ;
$('#order_and_show').text('Cancel Now') ;
// Get user location from browser using HTML geolocation.
let origin ;
// HTML5 geolocation.
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition
(
function(position)
{
let pos =
{
lat: position.coords.latitude,
lng: position.coords.longitude
} ;
origin = position.coords.latitude + ',' + position.coords.longitude ;
// Add marker.
let marker = new google.maps.Marker
(
{
position : pos,
map : map,
}
) ;
// Center the map according to user location.
map.setCenter(pos);
// Add popup window for user location information
let infoWindow = new google.maps.InfoWindow
(
{
content : '<h6>Your Location</h6>'
}
) ;
marker.addListener
(
'click',
() =>
{
infoWindow.open(map, marker) ;
}
) ;
},
function()
{
handleLocationError(true, infoWindow, map.getCenter());
}
);
}
else
{
// Browser doesn't support Geolocation
handleLocationError(false, infoWindow, map.getCenter());
}
// Handle Geolocation errors.
function handleLocationError(browserHasGeolocation, infoWindow, pos)
{
infoWindow.setPosition(pos);
infoWindow.setContent
(
browserHasGeolocation ? 'Error: The Geolocation service failed.' : 'Error: Your browser does not support geolocation.'
) ;
infoWindow.open(map);
}
console.log(origin) ;
}
) ;
}
) ;
The problem with your current code is that you try to access origin outside of the callback that sets it. The getCurrentPosition callback is probably executed asynchronously, thus when you try to access origin outside of the callback the callback function is not yet executed resulting in a origin value of undefined. You could use promises or async/await to solve this issue. Such a solution might look like this:
$(document).ready(function () {
const map = new google.maps.Map(
document.getElementById("map"),
{ center: { lat: 41.015137, lng: 28.979530 }, zoom: 12 }
);
function handleLocationError(infoWindow, msg) {
infoWindow.setPosition(map.getCenter());
infoWindow.setContent(msg);
infoWindow.open(map);
}
$("#order_and_show").click(async function () {
// notice the async keyword ^
$('#order_title').text('Cancel the order right now');
$('#order_and_show').text('Cancel Now');
let position, origin;
if (navigator.geolocation) {
try {
// await the position before continuing
position = await new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject);
});
let pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
origin = position.coords.latitude + ',' + position.coords.longitude;
let marker = new google.maps.Marker({position: pos, map: map});
let infoWindow = new google.maps.InfoWindow({
content: '<h6>Your Location</h6>'
});
map.setCenter(position);
marker.addListener('click', () => infoWindow.open(map, marker));
} catch (error) {
// I'm not sure how you are able to access infoWindow here since it's
// created in the try block after the error is thrown.
handleLocationError(infoWindow, 'Error: The Geolocation service failed.')
}
} else {
// Same here, you don't have access to infoWindow, since it's not created
// yet. However both the above and this are present to mimic the question
// structure.
handleLocationError(infoWindow, 'Error: Your browser does not support geolocation.');
}
// origin should be available unless geolocation isn't supported or
// getCurrentPosisiton failed to execute successfully
console.log(origin);
});
});
For more info about working with asynchronous behaviour I recommend checking out the MDN Using Promises guide.
I am not sure but I think problem seems to be with this line:
let infoWindow = new google.maps.InfoWindow({
content: "<h6>Your Location</h6>"
});
You have declared infoWindow using let keyword which is why I think it is scoped within function(position) { .. } block and which is why infoWindow is being passed to handleLocationError function. The same could be said for let pos variable. declaring your variables globally could solve the problem.
declare pos, marker and infoWindow varibles in the same line let origin; like so:
let origin, pos, marker, infoWindow;
Final Code Should look like this, hope it helps:
let map;
// initialize the map and show it on the dashboard.
function initMap() {
// Map options.
let options = {
center: {
lat: 41.015137,
lng: 28.97953
},
zoom: 12
};
// New map.
map = new google.maps.Map(document.getElementById("map"), options);
}
$(document).ready(function() {
$("#order_and_show").click(function() {
// Change the text of the title and the button when get order from the user.
$("#order_title").text("Cancel the order right now");
$("#order_and_show").text("Cancel Now");
// Get user location from browser using HTML geolocation.
let origin, pos, marker, infoWindow;
// HTML5 geolocation.
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position) {
pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
origin = position.coords.latitude + position.coords.longitude;
// Add marker.
marker = new google.maps.Marker({
position: pos,
map: map
});
// Center the map according to user location.
map.setCenter(pos);
// Add popup window for user location information
infoWindow = new google.maps.InfoWindow({
content: "<h6>Your Location</h6>"
});
marker.addListener("click", () => {
infoWindow.open(map, marker);
});
},
function() {
handleLocationError(true, infoWindow, map.getCenter());
}
);
} else {
// Browser doesn't support Geolocation
handleLocationError(false, infoWindow, map.getCenter());
}
// Handle Geolocation errors.
function handleLocationError(browserHasGeolocation, infoWindow, pos) {
infoWindow.setPosition(pos);
infoWindow.setContent(
browserHasGeolocation
? "Error: The Geolocation service failed."
: "Error: Your browser does not support geolocation."
);
infoWindow.open(map);
}
console.log(origin);
});
});

Zoom to search (marker) position Google Maps API

I would like my map to zoom to the search (marker) position, when i search an address.
I have been looking through the forum and found advice but I cant get it to work.
Code sample
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: {lat: 52.0, lng: 1.0}
});
var geocoder = new google.maps.Geocoder();
document.getElementById('submit').addEventListener('click', function() {
geocodeAddress(geocoder, map);
});
}
function geocodeAddress(geocoder, resultsMap) {
var address = document.getElementById('address').value;
geocoder.geocode({'address': address}, function(results, status) {
if (status === 'OK') {
resultsMap.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: resultsMap,
position: results[0].geometry.location
});
map.setZoom(14);
map.panTo(Marker.position);
}
else {
alert('clever text here: ' + status);
}
});
Any ideas would be very much appreciated.
The setZoom(14) inside the geocodeAddress() function is not working since you have called it from an incorrect map object reference. You should call resultsMap.setZoom(14) instead of map.setZoom(14).
The "map" variable is declared inside the function initMap() and is passed as an argument when the geocodeAddress() function is called: geocodeAddress(geocoder, map).
Now in the method definition of geocodeAddress(), the map object reference is changed to "resultsMap" parameter name: function geocodeAddress(geocoder, resultsMap){...}. This is why you'll have to use resultsMap.setZoom(14) inside the geocodeAddress() function.
Here's a working sample in JSFiddle.
Hope this helps!

Triggering Google Maps resize

I have no JavaScript or jQuery knowledge, I have no idea what to do with this Google Maps code.
I need to trigger this Google Maps resize code:
google.maps.event.trigger(map, 'resize');
The resize code above needs to be triggered after this waypoints is triggered below:
// Studio Page
jQuery('.studio-page').waypoint(function() {
jQuery('.kickass-studio').addClass( 'show animated bounceInLeft' );
jQuery('.location').addClass( 'show animated bounceInRight' );
jQuery('.geo-address').addClass( 'show animated bounceInDown' );
},
{
offset: '10%'
});
The above code is waypoints.js. My problem is that Google Maps breaks (you can only see the top left corner of the map). But from what I have found on Stack Overflow and other forums, this is due to the fact that the div is going from display: none to display: block after my waypoints plugin is done (adds class "show"). So I need to then trigger the Google Maps resize after waypoints is done adding those classes.
How would I go about doing this?
EDIT:
I have tried this:
// Studio Page
jQuery('.studio-page').waypoint(function() {
jQuery('.kickass-studio').addClass( 'show animated bounceInLeft' );
jQuery('.location').addClass( 'show animated bounceInRight' );
jQuery('.geo-address').addClass( 'show animated bounceInDown' );
var currCenter = map.getCenter();
google.maps.event.trigger(map, 'resize');
map.setCenter(currCenter);
},
{
offset: '10%'
});
But putting the above resize trigger there throws the Google Maps off my long and lat center point where my marker is?
EDIT:
Here is my maps script:
var directionDisplay;
var directionsService = new google.maps.DirectionsService();
function initialize() {
var latlng = new google.maps.LatLng(-33.8333406,18.6470022);
directionsDisplay = new google.maps.DirectionsRenderer();
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false
};
var map = new google.maps.Map(document.getElementById("map"),myOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById("directionsPanel"));
var marker = new google.maps.Marker({
position: latlng,
map: map,
title:"Get Directions"
});
}
function calcRoute() {
var start = document.getElementById("routeStart").value;
var end = "-33.8333406,18.6470022";
var request = {
origin:start,
destination:end,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
} else {
if (status == 'ZERO_RESULTS') {
alert('No route could be found between the origin and destination.');
} else if (status == 'UNKNOWN_ERROR') {
alert('A directions request could not be processed due to a server error. The request may succeed if you try again.');
} else if (status == 'REQUEST_DENIED') {
alert('This webpage is not allowed to use the directions service.');
} else if (status == 'OVER_QUERY_LIMIT') {
alert('The webpage has gone over the requests limit in too short a period of time.');
} else if (status == 'NOT_FOUND') {
alert('At least one of the origin, destination, or waypoints could not be geocoded.');
} else if (status == 'INVALID_REQUEST') {
alert('The DirectionsRequest provided was invalid.');
} else {
alert("There was an unknown error in your request. Requeststatus: \n\n"+status);
}
}
});
}
Use these lines for centering your google map after resizing:
var currCenter = map.getCenter();
google.maps.event.trigger(map, 'resize');
map.setCenter(currCenter);

Get element ID from url hash and fire it's click handler

I would like to grab an element based on the url hash, and fire the click of that element. I must be missing something, because I get the error:
Uncaught TypeError: Property '$' of object [object Object] is not a function
Here's the code
jQuery(function($){
function doUrl() {
var urlHash = window.location.hash;
if (urlHash != '') {
if ( $(urlHash).length > 0 ) {
$(urlHash).trigger('click');
}
}
}
doUrl();
});
}); // jquery
It seems that the error stems from urlHash not being an appropriate type of element to feed into $(). But the console tells me that the urlHash variable holds what I would expect it to: "#someClickableElement".
When I manually replace the urlHash variable with '#somepageid', the click event still does not fire on page load like I'd expect. So just to clarify, this does not work either:
$(function(){
$('#someClickableElement').click();
});
I can't quite tell where my problem is.
Edit
For those of you who want to see the whole code, here's a lot more of it:
var map;
function initialize() {
var mapOptions = {
zoom: 17,
center: new google.maps.LatLng(xxx,xxx),
mapTypeId: google.maps.MapTypeId.ROADMAP,
panControl: false,
zoomControl: true,
zoomControlOptions: {
position: google.maps.ControlPosition.RIGHT_CENTER
},
scaleControl: false,
mapTypeControl: false,
streetViewControlOptions: {
position: google.maps.ControlPosition.RIGHT_CENTER
}
// navigationControl: true, // (this is the pan and zoom together)
};
map = new google.maps.Map(document.getElementById('map-area'), mapOptions);
}
// init map
google.maps.event.addDomListener(window, 'load', initialize);
function findMapItem(lat,lon) {
var buildingLoc = new google.maps.LatLng(lat,lon);
map.panTo( buildingLoc );
removeAllMarkers();
// add new marker
buildingMarker = new google.maps.Marker({
map: map,
position: buildingLoc,
clickable: true,
icon: pathToAssets + 'bobcatMarker2.png'
//title: ,
})
buildingMarkers.push(buildingMarker);
}
jQuery(function($){
$('.mapItemsControls a').click(function(){
if ( $(this).hasClass('layerOn') ) {
$(this).removeClass('layerOn');
} else {
$('.mapItemsControls a').not(this).removeClass('layerOn');
$(this).addClass('layerOn');
}
doHistory( $(this).attr('href') );
return false;
});
$('#mapNav .findMapItem').click(function(){
var lat = $(this).data('lat');
var lon = $(this).data('lon');
if (lat != '' && lon != '') {
findMapItem(lat,lon);
}
});
function doUrl() {
var urlHash = window.location.hash;
if ( jQuery(urlHash).length > 0 ) {
jQuery(urlHash).trigger('click');
}
}
doUrl();
});
Make sure your click handler declaration comes before the doUrl() function call.
You can also greatly simplify that doUrl() function.
Click here for a working fiddle.
jQuery(function($){
$('#test').click(function() {
alert('No problems.');
});
function doUrl() {
$(window.location.hash).trigger('click');
}
doUrl();
});
I solved the problem by putting calling the function doUrl() inside the Google Maps init block. The functions that the click handler were calling were part of the google maps object and therefore couldn't fire until the Map had been initialized.

Reuse already loaded JavaScript

The goal
Reuse already loaded JavaScript correctly.
The problem
I'm generating a map dynamically using Google Maps API V3 and I need to reuse it. How?
The scenario
On Index.html, there's the following script:
var gMapsLoaded = false;
window.gMapsCallback = function () {
gMapsLoaded = true;
$(window).trigger('gMapsLoaded');
}
window.loadGoogleMaps = function () {
if (gMapsLoaded) return window.gMapsCallback();
var script_tag = document.createElement('script');
script_tag.setAttribute("type", "text/javascript");
script_tag.setAttribute("src",
"http://maps.google.com/maps/api/js?sensor=false&callback=gMapsCallback");
(document.getElementsByTagName("head")[0]
|| document.documentElement).appendChild(script_tag);
}
When I click on some button to show the map, my app invokes this script:
[...]
var geocoder;
var map;
var address = context.address();
function initialize() {
var mapDiv = document.getElementById("map_canvas");
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(-34.397, 150.644);
var myOptions = {
zoom: 15,
center: latlng,
mapTypeControl: true,
mapTypeControlOptions:
{ style: google.maps.MapTypeControlStyle.DROPDOWN_MENU },
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(mapDiv, myOptions);
if (geocoder) {
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
map.setCenter(results[0].geometry.location);
var infowindow = new google.maps.InfoWindow(
{
content: '<b>' + address + '</b>',
size: new google.maps.Size(150, 50)
});
var marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map,
title: address
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
} else {
alert("No results found");
}
} else {
alert
("Geocode was not successful
for the following reason: " + status);
}
});
}
gMapsLoaded = false;
}
$(window).on('gMapsLoaded', initialize);
window.loadGoogleMaps();
As you can see, the application is always calling the loadGoogleMaps(); function that calls the external .js file. If I click in the 5 different maps, I get 5 scripts with the same proposal.
Someone have any idea to solve this?
Duplicated question?
Yes, I think that the essence of the question is duplicated, but the nucleus isn't.
As you can see, the application is always calling the
loadGoogleMaps(); function that calls the external .js file. If I
click in the 5 different maps, I get 5 scripts with the same proposal.
That is incorrect. After the first time it completely loads, the if statement on the first line will return early, preventing you from including it multiple times.
There's nothing wrong with the way that's written.
jsFiddle
var gMapsLoaded = false;
window.gMapsCallback = function () {
gMapsLoaded = true;
$(window).trigger('gMapsLoaded');
}
window.loadGoogleMaps = function () {
if (gMapsLoaded) return window.gMapsCallback();
console.log('Generating new script tag');
var script_tag = document.createElement('script');
script_tag.setAttribute("type", "text/javascript");
script_tag.setAttribute("src",
"http://maps.google.com/maps/api/js?sensor=false&callback=gMapsCallback");
(document.getElementsByTagName("head")[0]
|| document.documentElement).appendChild(script_tag);
}
$(window).on("gMapsLoaded",function(){
console.log("gMapsLoaded");
});
$(function(){
$("button").on("click",window.loadGoogleMaps);
});
Now, if you were to click it 5 times really fast when it isn't already loaded, it could potentially load it multiple times. You should call that function on it's own before a click event would normally happen to prevent that.
Update:
At the end of your initialize() method, you're using gMapsLoaded = false; which causes the above code to once again request a new script tag. Simply remove/comment out that line.

Categories