I am working on a google maps API project.
I take lat and long values from a database and display them in HTML rendered by PHP.
I want to draw a route on map when I click the button with the lat&long values. ( check the image http://imgur.com/DkxlFbC )
But there is something going wrong and always taking the same values to draw the route.
I try to use changehandler but does not work.
index.php:
<?php
$test=mysql_query("SELECT lat, lng FROM markers ");
?>
<div class='container'>
<div class='row'>
<center>
<?php
while ($deneme=mysql_fetch_assoc($test)) {
extract($deneme);
echo '<br>';
echo '<h6 id="lat" class="box-design">'.$deneme['lat'].'</h6>';
echo '<h6 id="lng" class="box-design">'.$deneme['lng'].'</h6>';
echo '<br>';
echo '<input id="submit" onclick="myFunction()" type="submit" class="btn btn-primary" value="Button">';
echo '</div>';
}
?>
</center>
</div>
</div>
JS:
function myFunction() {
infoWindow = new google.maps.InfoWindow;
var directionsService = new google.maps.DirectionsService;
var directionsDisplay = new google.maps.DirectionsRenderer({ polylineOptions:{strokeColor:"#4a4a4a",strokeWeight:5}, suppressMarkers:true });
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
infoWindow.setPosition(pos);
infoWindow.setContent('Location found.');
infoWindow.open(map);
map.setCenter(pos);
directionsDisplay.setMap(map);
destLatLng = new google.maps.LatLng(document.getElementById('lat').textContent, document.getElementById('lng').textContent);
directionsService.route({
origin: pos,
destination: destLatLng,
travelMode: 'DRIVING'
}, function(response, status) {
if (status === 'OK') {
directionsDisplay.setDirections(response);
} else {
window.alert('Directions request failed due to ' + status);
}
});
}, function() {
handleLocationError(true, infoWindow, map.getCenter());
});
} else {
handleLocationError(false, infoWindow, map.getCenter());
}
}
Like was mentioned in comments, the id attribute needs to be unique.
The id global attribute defines a unique identifier (ID) which must be unique in the whole document. 1
Use a technique like the one below to add a numeric index to each set of latitude and longitude values with associated buttons. Notice the last reference (i.e. onclick="myFunction('.$index++.')") uses the post-increment operator to increase the index for the next iteration of the while loop.
$index = 1;
while ($deneme=mysql_fetch_assoc($test)) {
extract($deneme);
echo '<br>';
echo '<h6 id="lat'.$index.'" class="box-design">'.$deneme['lat'].'</h6>';
echo '<h6 id="lng'.$index.'" class="box-design">'.$deneme['lng'].'</h6>';
echo '<br>';
echo '<input id="submit" onclick="myFunction('.$index++.')" type="submit" class="btn btn-primary" value="Button">';
echo '</div>';
}
Then since the javascript function myFunction() will now be passed an integer , that argument (e.g. named index) can be used to find the associated latitude and logitude values (or those could be used as arguments to in the function call instead).
So update the function definition to include that argument:
function myFunction() {
becomes:
function myFunction(index) {
and then this line:
destLatLng = new google.maps.LatLng(document.getElementById('lat').textContent, document.getElementById('lng').textContent);
can be updated to use that index:
destLatLng = new google.maps.LatLng(document.getElementById('lat' + index).textContent, document.getElementById('lng' + index).textContent);
Also, to re-use the same directions service and directions renderer, declare those at the start of the javascript, and then initialize them in the function that initializes the map (e.g. initMap()):
var map, pointA, directionsService, directionsDisplay;
function initMap() {
var options = {};
/*
code to setup options
*/
map = new google.maps.Map(document.getElementById('map-canvas'), options);
directionsService = new google.maps.DirectionsService;
directionsDisplay = new google.maps.DirectionsRenderer({ /* ... */});
}
That way the code in myFunction() can just directionsService.route() and directionsDisplay.setDirections() when appropriate.
Putting all of this together, we have something like demonstrated in this phpfiddle.
1https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id
Related
I pass php $var into Javascript from controller. $var has fetched addresses from DB. And i put it in Javascript. Now i can see the addresses in the console. No problem with that, I don't know why syntax error pop up too.
This is how I insert it into JS.
function initMap(){
var options = {
zoom:8,
center:
'{!! $estates[0]->address !!}'
}
var map = new google.maps.Map(document.getElementById("map"), options);
var marker = new google.maps.Marker({
position:
#foreach($estates as $addr)
'{!! $addr->address !!}',
#endforeach
map:map
});
var infoWindow = new google.maps.InfoWindow({
content:'content here'
});
marker.addListener('click', function () {
infoWindow.open(map, marker);
});
}
my foreach running without a problem I can see the addreses in the console but also at this line: '{!! $estates[0]->address !!}' error pops up too. Actually I am seeing the address not this line.
error is this:
Uncaught SyntaxError: Invalid or unexpected token
Do you have any idea? am I making syntax mistake. But if do that then how can I retrieving the addresses at the console?
Also having this error too at the same line:
Undefined variable: estates (View:
/var/www/html/laravel/resources/views/layouts/app.blade.php) (View:
/var/www/html/laravel/resources/views/layouts/app.blade.php)
Controller
public function index()
{
$estates = DB::table("allestates")
->get();
return view("home", compact('estates'));
}
the topic is different the duplicated ones. it's not pure JS i am working with Laravel.
I think one of the addresses contains the ' character. To avoid it use the addslashes function. You could do that in the controller:
public function index()
{
$estates = DB::table("allestates")->get()->map(function($estate) {
$estate->address = addslashes($estate->address);
return $estate;
});
return view("home", compact('estates'));
}
And the according js would be:
var options = {
zoom:8,
center: new google.maps.LatLng({{$estates[0]->lat}}, {{$estates[0]->long}});
}
Because you have multiple addresses, it means you will have multiple markers too. That being said your code should look something like:
function initMap(){
var options = {
zoom:8,
center: new google.maps.LatLng({{$estates[0]->lat}}, {{$estates[0]->long}});
}
var map = new google.maps.Map(document.getElementById("map"), options);
var infoWindow = new google.maps.InfoWindow({
content:'content here'
});
var markers = [];
#foreach ($estates as $key => $estate)
markers[{{$key}}] = new google.maps.Marker({
position: new google.maps.LatLng({{$estate->lat}}, {{$estate->long}});
map: map
});
markers[{{$key}}].addListener('click', function () {
infoWindow.open(map, markers[{{$key}}]);
});
#endforeach
}
You can use php variables inside laravel blade files as
var options = {
zoom:8,
center:
'{{$estates[0]->address}}'
}
Issue is Google Maps API display directions from one location to another is returning error function displayDirections() is not defined.
Unsuccessful with help from other questions so far, ex here, or here
Full code here, been fidgeting with the quotes and single quotes etc but don't think that's the issue. This function is listed where all my other functions are called without issues. When I enter in a destination, then when the infoWindows appear, I select the View Route button, but I still get the error that displayDirections is not defined, I even moved this function up global in App.js, but I still can't figure out why this function is
Just a snip it of the code, if something's missing it's probably in the full code;
function displayDirections(origin) {
hideListings()
let directionsService = new window.google.maps.DirectionsService()
let destinationAddress = document.getElementById('search-within-time-text').value
let mode = document.getElementById('mode').value
directionsService.route({
origin: origin,
destination: destinationAddress,
travelMode: window.google.maps.TravelMode[mode]
}, function(response, status) {
if (status === window.google.maps.DirectionsStatus.OK) {
let directionsDisplay = new window.google.maps.DirectionsRenderer({
map: map,
directions: response,
draggable: true,
polylineOptions: {
strokeColor: 'green'
}
}) } else {window.alert('Directions request failed due to ' + status)
}
})
}
let infowindow = new window.google.maps.InfoWindow({ content: durationText + ' away,
' + distanceText + '<div><input id="route" type="button" value="View Route" onclick
=' + '{displayDirections("origins[i]")}></input></div>'})
Is this supposed to be a template literal:
onclick=displayDirections(`${origins[i]}`)
i have create website on 000webhost. i use map on it and create new google api key but issue is that when i hit the api for first time through message exceeded your 'request quota for this API' how ever i never hit it before i hit the api for the first time with new api key. this is my php script.i need help
function initMap() {
var map = new google.maps.Map(document.getElementById('show_map'), {
center: {lat: 33.6518, lng: 73.1566},
zoom: 13
});
var input = document.getElementById('shopadd');
var options = {
types: ['(cities)'],
componentRestrictions: {country: 'pk'}
};
var autocomplete = new google.maps.places.Autocomplete(input,options);
// Bind the map's bounds (viewport) property to the autocomplete object,
// so that the autocomplete requests use the current map bounds for the
// bounds option in the request.
autocomplete.bindTo('bounds', map);
// Set the data fields to return when the user selects a place.
autocomplete.setFields(['address_components', 'geometry', 'name']);
autocomplete.setOptions({strictBounds: true});
var infowindow = new google.maps.InfoWindow();
var infowindowContent = document.getElementById('infowindow-content');
infowindow.setContent(infowindowContent);
var marker = new google.maps.Marker({
map: map,
anchorPoint: new google.maps.Point(0, -29)
});
autocomplete.addListener('place_changed', function() {
infowindow.close();
marker.setVisible(false);
var place = autocomplete.getPlace();
if (!place.geometry) {
// User entered the name of a Place that was not suggested and
// pressed the Enter key, or the Place Details request failed.
window.alert("No details available for input: '" + place.name + "'");
return;
}
var location = "Address " + place.formatted_address;
location += "Latitude " + place.geometry.location.lat();
location += "Longitude " + place.geometry.location.lng();
var lat = place.geometry.location.lat();
document.getElementById('lat').value = lat;
var lng = place.geometry.location.lng();
document.getElementById('lng').value = lng;
// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
marker.setPosition(place.geometry.location);
marker.setVisible(true);
var add = '';
if (place.address_components.length>0) {
add = add.concat(
(place.address_components[0] && place.address_components[0].short_name || ''),' ',
(place.address_components[1] && place.address_components[1].short_name || ''),' ',
(place.address_components[2] && place.address_components[2].short_name || ''),' ');
}
document.getElementById('add').value = add;
infowindowContent.children['place-icon'].src = place.icon;
infowindowContent.children['place-name'].textContent = place.name;
infowindowContent.children['place-address'].textContent = add;
infowindow.open(map, marker);
});
// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key="my key"&libraries=places&callback=initMap" async defer></script>
Google changed their pricing model. The new plan gives you more flexibility and control over how you use our APIs. You can use as much or as little as you need and only pay for what you use each month.
As of July 16, 2018:
The Google Maps Platform APIs are billed by SKU.
Usage is tracked for each Product SKU, and an API may have more than one Product SKU.
Cost is calculated by: SKU Usage x Price per each use.
For each billing account, for qualifying Google Maps Platform SKUs, a $200 USD Google Maps Platform credit is available each month, and automatically applied to the qualifying SKUs.
For more information, visit this Link
I'm working with Googlemaps now. I use lattitude and longitude stored in the database. To call the data, I use simple ajax and it shows the latt and long as I wish.
However, It takes a long time to show the map based on the latt and long. Otherwise, It does not show anything. I don't know. How can I handle this?
Updated:
It looks there's a problem with the event.key onkeypress. I tried
clean code for that and it doesn't show anything !. ex: jsfiddle But That keyboard works on other code.
Here's the complete code:
JS/Ajax call the database through file inc.php:
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places"></script>
<script>
function strQuery(str) {
if (str.length == 0) {
document.getElementById("valdata").value = "-33.8474, 151.2631";
return;
}
else{
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("valdata").value = xmlhttp.responseText;
script_dkill()
}
}
xmlhttp.open("POST", "inc.php?q="+str, true);
xmlhttp.send(null);
}
}
//start: calling maps
var map;
var strlng;
function script_dkill() {
strlng = document.querySelector("#valdata").value;
if (strlng) {
var latlng = new google.maps.LatLng(strlng);
var myOptions = {
zoom: 12,
center: latlng,
panControl: true,
zoomControl: true,
scaleControl: true,
mapTypeId: google.maps.MapTypeId.SATELLITE
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
addMarker(new google.maps.LatLng(strlng), map);
}
}
function addMarker(latLng, map) {
var marker = new google.maps.Marker({
position: latLng,
map: map,
draggable: true,
animation: google.maps.Animation.DROP
});
return marker;
}
</script>
Here's the target(Output) in HTML:
<input id="qfront" name="qfront" placeholder="Ketik Nama Kampus ..." value="" type="text" onKeyPress="strQuery(this.value)"/>
<input id="valdata" name="valdata" type="text"/>
<div id="map_canvas" style="width:99.8%; height:280px; margin:0px; padding:0px;"></div>
and, here's the PDO the way I grab the data of latt and long (inc.php):
<?php
include('deep/cf/dbbs.php');
error_reporting(E_ALL);
?>
<?php
if(isset($_GET['q'])) {
$q = $_GET['q'];
}
$q = isset($_GET['q']) ? $_GET['q'] : '';
$nsUser="SELECT * FROM cliententry WHERE kampusterdekat=:q";
$uQuery = $mydb->prepare ($nsUser);
$uQuery->execute(array(':q' => $q));
$result = $uQuery->fetch(PDO::FETCH_ASSOC);
if ($result>0){
$googlemap=$result['googlemap'];
echo $googlemap;
}
else{
echo "<script>alert('Rent-house not registered yet');</script>";
}
?>
It's impossible to give you how the code running here. if you don't mind, please check here:
TEST-REAL-PAGE
Use keyword: "Universitas Lampung" since it's already inside the db.
I tends to focus on how the events work which I found it was wrong.
Data from db is interpreted as one value, ex: -2.9549663, 104.6929232
I must convert it into array first before called by JS in googlemap.
So, what makes it gray? It is because it didn't find the correct data format (like: -2.9549663, 104.6929232) in array. That's stupid of me.
Here's the way I convert which makes me stupid in a week:
var strlng = document.querySelector("#valdata").value;
var test1 = strlng.split(',');
var x = test1 [0];
var y = test1 [1];
After that, insert the x and y into the value of latt and long (latt and long is in array value), as follow:
var map;
function script_dkill() {
var strlng = document.querySelector("#valdata").value;
var test1 = strlng.split(',');
var x = test1 [0];
var y = test1 [1];
var latlng = new google.maps.LatLng(x,y);
var myOptions = {
zoom: 12,
center: latlng,
panControl: true,
zoomControl: true,
scaleControl: true,
mapTypeId: google.maps.MapTypeId.SATELLITE
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
addMarker(new google.maps.LatLng(x,y), map);
}
}
function addMarker(latLng, map) {
var marker = new google.maps.Marker({
position: latLng,
map: map,
draggable: true,
animation: google.maps.Animation.DROP
});
return marker;
everything finally goes so amazing! Done.
now I learn one more from JS.
I want users to do the following:
1) Enter their Street Address and Zip Code and hit "Submit", which will trigger Google Maps to geocode the address and place a marker on the map. I'm using the below code for this (which is working fine and getting me all the address info I need):
var geocoder;
var map;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(37.7789, -122.3917);
var mapOptions = {
center: latlng,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
}
function codeAddress() {
var address = document.getElementById('streetAddress').value +", "+document.getElementById('zipCode').value;
geocoder.geocode( { 'address': address, 'region': 'US'}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0].address_components) {
for (var i in results[0].address_components) {
if (typeof(results[0].address_components[i]) === "object" && results[0].address_components[i].types[0] == "street_number") {
var streetNumber= results[0].address_components[i].long_name;
} else if (typeof(results[0].address_components[i]) === "object" && results[0].address_components[i].types[0] == "route") {
var streetName= results[0].address_components[i].short_name;
} else if (typeof(results[0].address_components[i]) === "object" && results[0].address_components[i].types[0] == "neighborhood") {
var neighborhood= results[0].address_components[i].short_name;
} else if (typeof(results[0].address_components[i]) === "object" && results[0].address_components[i].types[0] == "administrative_area_level_1") {
var state= results[0].address_components[i].short_name;
} else if (typeof(results[0].address_components[i]) === "object" && results[0].address_components[i].types[0] == "postal_code") {
var zipCode= results[0].address_components[i].long_name;
}
}
}
console.log(streetNumber+", "+streetName+", "+neighborhood+", "+state+", "+zipCode);
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);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
2) After the user sees the marker, I want them to hit a "Confirm" button to submit this data to my server (I'm using Firebase via their Javascript API). The question I have is how do I best store the variables 'streetNumber', 'streetName', 'city', 'state', 'zipCode', and 'neighborhood' between the time that Google Maps returns the data and when the user hits "Confirm" button? The only thing I can think of is storing it on the browser window (e.g. window.streetName, window.streetNumber, etc), but I know that's not best practice.
You may e.g. store these data as properties of the button, it will be very easy to access them later(but it's also not a good practice).
The best thing you can do is to store all your objects in a single "class" (with all I mean everything that is global, currently also map, geocoder, codeAddress and initialize are global )
Here a sample code(ready to use, it doesn't expose any global property):
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false">
</script>
<script type="text/javascript">
//a self-executing, anonymous function
(function(opts,ns){
//"that" is our object, it holds all properties and methods
//and is only visible within the scope of this function
var that = {geocoder: null,
map: null,
opts: opts,
ns: ns,
postData: null},
goo = google.maps,
byId = function(id){return document.getElementById(id);};
//initialize the map
that.initialize=function() {
var latlng = new goo.LatLng(this.opts.lat,this.opts.lng);
var mapOptions = {
center: latlng,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
this.map = new goo.Map(byId(this.opts.ids.map), mapOptions);
//assign click-handlers to the buttons
goo.event.addDomListener(byId(this.opts.ids.btnGeo),'click',function(){
that.codeAddress.call(that);});
goo.event.addDomListener(byId(this.opts.ids.btnSend),'click',function(){
that.onSubmit.call(that);});
}
//send the data here
that.onSubmit=function(){
alert(JSON.stringify(that.postData));
}
//parse the address-components into an object
that.parseAddressComponents=function(ac){
var components={
street_number: ['streetNumber', 'long_name'],
route: ['streetName', 'short_name'],
administrative_area_level_1:['state', 'short_name'],
neighborhood: ['neighborhood', 'short_name'],
postal_code: ['zipCode', 'long_name']
},o={};
for(var i=0;i<ac.length;++i){
inner:for(var c in components){
if(ac[i].types[0]==c){
o[components[c][0]]=ac[i][components[c][1]];
break inner;
}
}
}
return o;
}
//geocoding-callback
that.geoCallback=function(results, status){
if (status == goo.GeocoderStatus.OK) {
//store the parsed address-components as property of "that"
that.postData=that.parseAddressComponents(results[0].address_components);
that.map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: that.map,
position: results[0].geometry.location
});
} else {
that.postData={};
alert(status);
}
}
//geocoding
that.codeAddress=function() {
var address = [byId(this.opts.ids.uiAddr).value,
byId(this.opts.ids.uiZip).value].join(',');
//initialize geocoder on first run
if(!this.geocoder){this.geocoder=new goo.Geocoder();}
this.geocoder.geocode( { 'address': address, 'region': this.opts.region},
this.geoCallback);
}
//make "that" global when needed
if(ns)window[ns]=that;
//load-handler
goo.event.addDomListener(window, 'load',function(){
that.initialize();});
})
( //some properties for the object
{
lat:37.7789,
lng:-122.3917,
region:'US',
ids:{ map :'map_canvas',
btnGeo :'geobutton',
btnSend :'sendbutton',
uiAddr :'streetAddress',
uiZip :'zipCode'}
},
//supply a name for the object here when you want to make it global
null
);
/*]]>*/
</script>
<fieldset>
streetAddress:<input id="streetAddress" value="paisley park">
zipCode:<input id="zipCode" value="55422">
<input id="geobutton" type="button" value="geocode">
<input id="sendbutton" type="button" value="send">
</fieldset>
<div id="map_canvas" style="height:300px;"></div>