I have a form that submits a location to Google's Geocoder and returns the lat/long and changes the map. If I use ng-click on the icon it doesn't work unless I click on it twice. If I use ng-submit on the form it appends to the url and doesn't perform the task. I feel like I'm close to getting this to work but I'm lost as to what I'm doing wrong.
Below is the form
<li>
<form action="" class="search-form" ng-submit="convertLatLonToAddress()">
<div class="form-group has-feedback">
<label for="search" class="sr-only">Search</label>
<input type="text" class="form-control" name="search" id="search" placeholder="Search for an address or place name">
<i class="fa fa-search form-control-indicator"></i>
</div>
</form>
</li>
And here is the function
$scope.convertLatLonToAddress = function(){
var address = $('#search').val();
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
// console.log(latitude + ' and ' + longitude);
$scope.center.lat = latitude;
$scope.center.lon = longitude;
}
});
};
Thanks to #PSL it's fixed! See below:
<li>
<form class="search-form" ng-submit="convertLatLonToAddress(searchText)">
<div class="form-group has-feedback">
<label for="search" class="sr-only">Search</label>
<input type="text" class="form-control" name="search" id="search" placeholder="Search for an address or place name" ng-model="searchText">
<button style="visibility: hidden"></button>
<a ng-click="convertLatLonToAddress(searchText)">
<i class="fa fa-search form-control-indicator"></i>
</a>
</div>
</form>
</li>
And
$scope.convertLatLonToAddress = function(searchText){
// var address = $('#search').val();
var address = searchText;
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
// console.log(latitude + ' and ' + longitude);
$scope.center.lat = latitude;
$scope.center.lon = longitude;
$scope.$apply();
}
});
};
You need to invoke the digest cycle manually inside the async call of geocode, since geocode does not run inside angular context.
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
// console.log(latitude + ' and ' + longitude);
$scope.center.lat = latitude;
$scope.center.lon = longitude;
$scope.$apply();
}
});
Everytime you click, ng-click triggers the digest cycle so previous cycle runs the non angular async call and updated scope which angular is unaware, when you click on it again it runs the digest cycle again and does the same but that time the values you set previously will be picked and that is why it takes 2 clicks. For ng-submit to execute you need a form element trigger, ex: a button or input type="submit" that causes submit behavior to happen on the form. You should also remove action from form unless you really intend to do a redirection.
Apart from that you can use ng-model on the textbox and pass the value to your function as well instead of getting value from DOM directly.
<input type="text" class="form-control" name="search" id="search" placeholder="Search for an address or place name" ng-model="searchText">
and pass the value via ng-click as ng-click="convertLatLonToAddress(searchText)" and use it inside your function.
In order to avoid scope.apply(); in your controller you could abstract out geoCoder to an angular service and return a promise (creating deferred object) and use that service in your controller.
myApp.service('geoCoderService', ['$q', function($q){
this.getCoordinates = function(address){
var defer = $q.defer();
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
return defer.resolve({latitude :latitude , longitude :longitude });
}
//faliure
defer.reject(status);
});
return defer.promise;
}
});
inject geoCoderService and get data using:
geoCoderService.getCoordinates(address).then(function(coordinates){
//populate it
}).catch(function(errorStatus){ /*ooops Error*/ })
Try this
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.convertLatLonToAddress = function() {
var address = $('#search').val();
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
'address': address
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
$scope.lat = results[0].geometry.location.lat();
$scope.lon = results[0].geometry.location.lng();
console.log($scope.lat + ' and ' + $scope.lon);
setTimeout(function(){$scope.$apply();},0)
}
});
};
});
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<li>
<div class="form-group has-feedback">
<label for="search" class="sr-only">Search</label>
<input type="text" class="form-control" name="search" id="search" placeholder="Search for an address or place name">
<i class="fa fa-search form-control-indicator"></i>
<button ng-click="convertLatLonToAddress()">Click</button>
<br>
Lat : <input type="text" ng-model="lat"><br>
Lon : <input type="text" ng-model="lon">
</div>
</li>
</div>
</body>
Related
I have got the current location with complete address and shown this in a <span> by ID. But i want to show this address in input type text also. My current code is
<script type="text/javascript">
var positionlatitude;
var positionlongitude;
var address;
google.maps.event.addDomListener(window, 'load', function () {
var places = new google.maps.places.Autocomplete(document.getElementById('location_#item.Name'));
google.maps.event.addListener(places, 'place_changed', function () {
var place = places.getPlace();
address = place.formatted_address;
positionlatitude = place.geometry.location.lat();
positionlongitude = place.geometry.location.lng();
});
});
navigator.geolocation.getCurrentPosition(success);
function success(position) {
var GEOCODING = 'https://maps.googleapis.com/maps/api/geocode/json?latlng=' + position.coords.latitude + '%2C' + position.coords.longitude + '&language=en';
$.getJSON(GEOCODING).done(function (location) {
$('span[id^="address"]').html(location.results[0].formatted_address);
})
}
</script>
<label for="location">Your Location: </label><br />
<span id="address" class="input-form" ></span>
<input type="text" value="" name="address" id="geolocation"/>
Thanks To everyone If you consider this question.
now i got the answer.
document.getElementById("geolocation").value = location.results[0].formatted_address;
<input type="hidden" value="" name="address" id="geolocation"/>
This will set the address in input type hidden
In my server i am using some function to find out pickup and drop lat and lang , direction from google map api services,so limit is crossed some days so i have desiede to go with user side scripting to calculate all google api service using following code this will help me ?
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body onload="geolocate1()">
<input type="text" id="pickup" onFocus="geolocate()" placeholder="Enter your pick up place" />
<input type="text" id="plat" value="" id="plat"/>
<input type="text" id="plang" value="" id="plang"/>
<input type="text" id="pstatuslat" value="error" />
<input type="text" id="km" />
</br>
</br>
<input type="text" id="drop" onFocus="geolocate1()" placeholder="Enter your Drop off place"/>
<input type="text" id="dlat" value="" id="plat"/>
<input type="text" id="dlang" value="" id="plang"/>
<input type="text" id="dstatuslat" value="error" />
<div id="directions_panel" style="margin:20px;background-color:#FFEE77;"></div>
<input type="button" onclick="GetLocation1();GetLocation();calcRoute();" value="Book Now" />
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places"></script>
<script type="text/javascript">
<!--
function GetLocation() {
var geocoder = new google.maps.Geocoder();
var address = document.getElementById("pickup").value;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
document.getElementById('plang').value= longitude;
document.getElementById('plat').value= latitude;
document.getElementById('pstatuslat').value= "ok";
} else {
document.getElementById('pstatuslat').value= "error";
}
});
};
function GetLocation1() {
var geocoder = new google.maps.Geocoder();
var address = document.getElementById("drop").value;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
document.getElementById('dlang').value= longitude;
document.getElementById('dlat').value= latitude;
document.getElementById('dstatuslat').value= "ok";
} else {
document.getElementById('dstatuslat').value= "error";
}
});
};
//-->
// This example displays an address form, using the autocomplete feature
// of the Google Places API to help users fill in the information.
var autocomplete;
function geolocate1() {
// Create the autocomplete object, restricting the search
var input = document.getElementById('pickup');
var options = {types: ["geocode"],componentRestrictions: {country: 'uk'}};
autocomplete = new google.maps.places.Autocomplete(input, options);
// When the user selects an address from the dropdown,
// populate the address fields in the form.
google.maps.event.addListener(autocomplete, 'place_changed', function() {
fillInAddress();
});
}
function geolocate() {
// Create the autocomplete object, restricting the search
// to geographical location types.
var input = document.getElementById('drop');
var options = {types: ["geocode"],componentRestrictions: {country: 'uk'}};
autocomplete = new google.maps.places.Autocomplete(input, options);
// When the user selects an address from the dropdown,
// populate the address fields in the form.
google.maps.event.addListener(autocomplete, 'place_changed', function() {
fillInAddress();
});
}
var directionsService = new google.maps.DirectionsService();
function calcRoute() {
var start = document.getElementById('pickup').value;
var end = document.getElementById('drop').value;
var request = {
origin: start,
destination: end,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
var route = response.routes[0];
var km = parseFloat(route.legs[0].distance.text.replace(" km", ""));
document.getElementById('km').value = km * 0.6214;
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</body>
</html>
Google API is limited with your Key using. Doesnt matter, if you have the same IP or different, each call to the Google API with you registered Key will be counted.
F.e. using Google Elevation API is limited for 2500 calls each day, doesnt matter, who is calling this, its limited to you API Key.
I'm not experienced with Javascript so any help would be very appriciated. For you guys this should be very easy. I posted a lot of code but my problem is just to copy 3 input fields values into a string/variable and use it for geocoding.
I have this inputs in a table:
<table width="580px" cellpadding="0" cellspacing="0">
<tr>
<td width="290"><label for="street">Street:</label></td>
<td width="278"><INPUT type="text" name="obj_object_description_street" id="obj_object_description_street" class="inputField" autocomplete="off" /></td>
<td width="12"></td>
</tr>
<tr>
<td width="290"><label for="streetno">House number:</label></td>
<td width="290"><INPUT type="text" name="obj_object_description_streetno" id="obj_object_description_streetno" class="inputField" autocomplete="off" /></td>
<td width="12"> </td>
</tr>
<tr>
<td width="290"><label for="zipcode">Post number:* </label></td>
<td width="290"><INPUT type="text" name="obj_object_description_zipcode" id="obj_object_description_zipcode" class="inputField" autocomplete="off" /><INPUT TYPE="hidden" name="sys_area_node_id" /></td>
<td width="12"><img src="/img/info.gif" alt="info" width="12" height="11" border="0" onclick="show_info(this,8);" onmouseover="make_pointer();" onmouseout="del_pointer();" /></td>
</tr>
And this code to display a google map with dragable pin:
<script type="text/javascript">
var geox='<%obj_object_description_geox%>'; //Location from DB
var geoy='<%obj_object_description_geoy%>'; //Location from DB
var sgeox='<%sys_area_geox%>';
var sgeoy='<%sys_area_geoy%>';
var telefon = "<%adv_advertiser_phone%>";
var slika = "<%main_media_web_url%>";
var povrsina = "<%area%>";
var cijena = "<%price_str%>";
var naslov = '<%headline%>';
var posta = "<%obj_object_description_zipcode%>";
var ulica = "<%obj_object_description_street%>";
var broj = "<%obj_object_description_streetno%>";
var address = "";
function initialize_map(){
if(geox != 0 && geoy != 0) //we have gps
{
var myLatlng = new google.maps.LatLng(geox, geoy);
show_map(myLatlng);
}
else if(sgeox!=0 && sgeoy !=0)
{
var myLatlng = new google.maps.LatLng(sgeox, sgeoy);
show_map(myLatlng);
}
else //no? we do the old good geocoding
{
var geocoder = new google.maps.Geocoder();
geocoder.geocode( {'address': '<%bc_sys_area_name%>, <%bc_sys_area_name_2%>'}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
show_map(results[0].geometry.location);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
}
</script>
My problem is :
var geocoder = new google.maps.Geocoder();
geocoder.geocode( {'address': '<%bc_sys_area_name%>, <%bc_sys_area_name_2%>'}, function(results, status)
I dont want to geocode <%bc_sys_area_name%>, <%bc_sys_area_name_2%> from the database. I want to geocode with a combined data of inputs(Street + House number + Post number).
Street has name & id obj_object_description_street
House has name & id obj_object_description_streetno
Post number has name & id obj_object_description_zipcode.
I have made a function that put's together all this 3 values:
UPDATED:
My problem is that i use this function for copying 3 inputs in a input with id="geocomplete" and I need this function to copy this values onload(when the page opens/refreshes) to an input not just when i type(keyup event).
<script type="text/javascript">
$('#obj_object_description_street, #obj_object_description_streetno, #obj_object_description_zipcode').bind('keypress blur', function() {
$('#geocomplete').val($('#obj_object_description_street').val() + ' ' +
$('#obj_object_description_streetno').val() + ' ' +
$('#obj_object_description_zipcode').val() );
});
</script>
But I dont know how to put all this 3 data into a string/variable and put it in
geocoder.geocode( {'address': 'HERE IT SHOULD BE'}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
Thanks for the update. I've updated my answer based on your feedback. I would suggest to use jquery ready function. I've created an example here, but you probably need to tweak a little bit. Basically, I've created two functions and I call them in different times, when page loads and when a keypress event happens.
$(function() {
$('#obj_object_description_street, #obj_object_description_streetno, #obj_object_description_zipcode').bind('keypress blur', function() {
$('#geocomplete').val(geoComplete());
updateGeoCoder(); //do this if you want to make a geocode call everytime you have this event
});
function geoComplete() {
return $('#obj_object_description_street').val() + ' ' +
$('#obj_object_description_streetno').val() + ' ' +
$('#obj_object_description_zipcode').val() ;
}
function updateGeoCoder() {
var geocoder = new google.maps.Geocoder();
var geoCompleteVal = $('#geocomplete').val();
geocoder.geocode( {'address': geoCompleteVal}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
show_map(results[0].geometry.location);
} else {
alert('Geocode was not successful for the following reason: '+ status);
}
});
}
//this is to run as soon as the page loads/refresh
$('#geocomplete').val(geoComplete());
updateGeoCoder();
});
Here is my code:
<script type="text/javascript">
var geocoder;
var map;
var latlngstr;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions = {
zoom: 15,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
}
function codeAddress() {
var address = document.getElementById('address').value;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
latlngstr = results[0].geometry.location;
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);
}
});
document.getElementById('lat').value = latlngstr.lat();
document.getElementById('lng').value = latlngstr.lng();
}
</script>
</head>
<body onload="initialize()">
<form id="form1" runat="server">
<div>
<input id="address" type="text" value="sydney" />
<input type="button" value="Geocode" onclick="codeAddress()">
<input id="lat" type="text" />
<input id="lng" type="text" />
</div>
<asp:Button ID="Button1" runat="server"
Text="Button" EnableViewState="False"
ViewStateMode="Disabled" OnClientClick="javascript:return codeAddress();"/>
<div id="map-canvas"></div>
</form>
</body>
</html>
I want to call the function codeAddress. When I call this function with an html button, the button with the value Geocode, it works fine. But when I call that function with an ASP.Net button the 'else' part is executed and it produces no result.
I infer that what you want to do is use the geocoding code to obtain the latitude and longitude and then post back with those.
Rather than make one button do client-side code and (at the same time) post back, I'd keep the HTML button but start a form post from your JavaScript code, once the fields have been set:
document.getElementById('lat').value = latlngstr.lat();
document.getElementById('lng').value = latlngstr.lng();
document.forms[0].submit();
I am working on an app related to addresses.
I tested my function with hardcoded address like this:
var address = "India Gate , Rajpath, New Delhi, Delhi";
It is working fine.
But now when I am using that function to get adderss from user through a form and using address=form.address.value. Then alert(address) is showing right address (string). But function couldn't work on it (for same address as hardcoded).
Basically I'm using Google Maps API. So is there anyhting special about form.name.value that I should know?
geocoder = new google.maps.Geocoder();
var address = form.address.value;
alert(address);
//var address = "India Gate , Rajpath, New Delhi, Delhi";
geocoder.geocode({
'address': address
}, function(results, status) {
if(status == google.maps.GeocoderStatus.OK) {
alert("hi");
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
addpin(latitude, longitude);
}
});
<form>
Your Name: <input type="text" name="name"/><br/>
Your Email:<input type="text" name="email"/><br/>
Company name:<input type="text" name="company"/><br/>
Street address:<input type="text" name="address"/><br/>
<input type="submit" value="submit" onclick="getlatlong(this.form)">
</form>
form.name reflects to the name attribute of the form element
<form name="form1" />
console.assert(form.name == "form1");
You could use form.elements.name which will be that you want. But in this case, you cannot reach the length named element, because that's the form.elements collection's length.