Related
I have a google map on my website created in codeigniter. Now I want to move the markers with data from my sql database. The data in my database will be updated. I can draw markers on the map by biostall. Now I want to move them.
So I load all the markers and pass them to my view to draw them with a ajax/javascript script. I get no errors but also no markers.. I'm not a pro in ajax and javascript so the problem needs to be there but I can't fix it.. Here's my code. The map should be updated each 3 seconds.
My controller :
function render_maps() {
$userid = $this->uri->segment(3);
$userlevel = $this->user_model->get_user_level($userid);
if ($userlevel > 2) {
$this->load->library('googlemaps');
$this->googlemaps->initialize();
#$this->marks();
$config['zoom'] = 'auto';
$data['map'] = $this->googlemaps->create_map();
$data['markers'] = json_encode($this->user_model->get_marks());
$data['userdata'] = $this->session->userdata;
$this->load->view('header', $data);
$this->load->view('dashboard_maps', $data);
$this->load->view('wrapper', $data);
}
}
My view :
<head>
<?php echo $map['js']; ?>
<script type="text/javascript">
function refreshMarkers() {
$.ajax({
url: "<?php site_url('User/render_maps/'. $this->session->userdata('user_id')) ?>",
type: "POST",
data: ({value: $markers}),
dataType: "json", //retrieved Markers Lat/lng in Json, thus using this dataType
success: function(data){
//Removing already Added Markers//////////
for (var i = 0; i < $markers.length; i++) {
$markers[i].setMap(null);
}
$markers = new Array();
//////////////////////////////////////////
// Adding New Markers////////////////////
for (var i = 0, len = data.length; i < len; ++i) { // Iterating the Json Array
var d = data[i];
var lat = parseFloat(d.lat);
var lng = parseFloat(d.lng);
var myLatlng = new google.maps.LatLng(lat, lng);
var marker = {
map: map,
position: myLatlng // These are the minimal Options, you can add others too
};
createMarker(marker);
}
}
}
);
</script>
Your function refreshMarkers() is missing a closing } bracket. Please also include all dependencies such as jquery and other functions.
You don't have to be a pro in ajax or javascript to achieve that. Make sure you retrieve the data successfully using your browser's console.
Here's a vanilla example for Google Map JS API with multiple markers which shows different earthquake locations. Try running the code snippet below.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style type="text/css">
html, body { height: 100%; margin: 0; padding: 0; }
#map { height: 100%; }
</style>
</head>
<body>
Click Here >> <button id="earthquakes">Show Earthquakes</button>
<div id="map"></div>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDrhmCE5YeH0r9Kkeq-v4ZXBd87UvwCOrw&callback=initMap">
</script>
<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 4.8259171, lng: 63.3691405},
zoom: 1
});
}
function createMarker(latlng, name) {
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: name
});
}
function displayMarkers() {
console.log('displayMarkers:'+latitd+':'+longtd+'\n');
var latlng = new google.maps.LatLng(latitd, longtd);
var name = titleName;
createMarker(latlng, name);
}
var latitd;
var longtd;
var titleName;
var nowDate = new Date();
var displayDate = nowDate.toJSON().slice(0,10);
nowDate.setDate(nowDate.getDate() - 1);
var yesterDate = nowDate.toJSON().slice(0,10);
$(document).ready(function() {
$('#earthquakes').click(function() {
getQuakes();
});
function getQuakes() {
console.log('yesterDate:'+yesterDate+', displayDate:'+displayDate+'\n');
$.ajax({
url: 'http://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=' + yesterDate + '&endtime=' + displayDate,
dataType : 'json'
})
.done(function(data) {
console.log('data.features:'+data.features);
$.each(data.features, function(key, val) {
var coord = val.geometry.coordinates;
locationD = {
latd: coord[0],
lngd: coord[1]
};
latitd = locationD.latd;
longtd = locationD.lngd;
titleName = val.properties.title;
console.log(latitd, longtd);
console.log(titleName);
displayMarkers();
});
})
.fail(function(e){
console.log(e);
})
.always(function(){
console.log('ajax executed');
});
}
});
</script>
</body>
</html>
I already have a working map where it generates a valid xml and can generate a marker on my map. Now what I want to do is to upon generating of maps for each loop in the xml I can create asynchronously a check box for each name. here is the code that generates the xml
function searchNearLocations(radius){
clearLocations();
var searchUrl = './designIncludes/phpLogicIncludes/searchMarkers.php?lat=' + userLat +'&lng=' + userLng + '&radius=' + radius;
downloadUrl(searchUrl, function(data) {
var xml = parseXml(data);
var markerNodes = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markerNodes.length; i++) {
var name = markerNodes[i].getAttribute("name");
var address = markerNodes[i].getAttribute("address");
var info = markerNodes[i].getAttribute("info");
var tts = markerNodes[i].getAttribute("tts");
var latlng = new google.maps.LatLng(
parseFloat(markerNodes[i].getAttribute("lat")),
parseFloat(markerNodes[i].getAttribute("lng")));
createMarker(latlng, name, address,info,tts);
createCheckboxes(name);
bounds.extend(latlng);
}
map.fitBounds(bounds);
});
}
My createMarker()
function createMarker(latlng, name, address,info,tts) {
var html = "<b>" + name + "</b></br><u>" + address + "</u></br>" + info + "</br>" + "Time allowance to spend: " + tts;
var marker = new google.maps.Marker({
map: map,
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
markers.push(marker);
}
I'm not that good in javascript but I have a marker=[] array global variable. Can I use that variable to generate a checkbox with it?by the way I also have a pre made marker before invoking the searchNearLocations function and I want to add it on the latlng bounds. Is it possible to insert it on the loop?
Okay
Everything not having to do with the checkboxes, I ignored. You'll have to put it back in your code.
I wrote a functioning example, you can copy/paste this as is.
<script src="http://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script type="text/javascript">
var markers = [];
var map;
/* I don't have that XML. I'll just insert a few locations hard coded. You can ignore this; it doesn't affect your question */
var markerNodes = [
{latlng: new google.maps.LatLng(50.896328544032805,4.4825010816688), name: 'Brussels Airport', address: 'A201, 1930 Zaventem', info: 'National airport of Brussels', tts: 'foo'},
{latlng: new google.maps.LatLng(50.8957080950929,4.334064952575659), name: 'Football stadion', address: 'Marathonlaan', info: 'Football stadion of the Red Devils', tts: 'foo'},
{latlng: new google.maps.LatLng(50.82302545625156,4.39255052014533), name: 'VUB campus', address: 'Pleinlaan 2', info: 'University of Brussels', tts: 'foo'}
];
function initialize() {
var position = new google.maps.LatLng(50.84499325563654,4.349978498661017);
var myOptions = {
zoom: 11,
center: position
};
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
searchNearLocations(null); // I ignore the radius part. I presume this searches for locations in a DB, or something...
}
/* never mind most of the changes I made here, it's just to ignore the xml part of the code */
function searchNearLocations(radius) {
clearLocations();
var bounds = new google.maps.LatLngBounds();
for (var i=0; i<markerNodes.length; i++) {
var latlng = markerNodes[i].latlng,
name = markerNodes[i].name,
address = markerNodes[i].address,
info = markerNodes[i].info,
tts = markerNodes[i].tts;
createMarker(latlng, name, address, info, tts);
createCheckbox(name, i); // the most important thing is to pass the i; then markers[i] corresponds with checkboxes[i]
bounds.extend(latlng);
}
map.fitBounds(bounds);
}
function createMarker(latlng, name, address, info, tts) {
// var html = "<b>" + name + "</b></br><u>" + address + "</u></br>" + info + "</br>" + "Time allowance to spend: " + tts;
var marker = new google.maps.Marker({
map: map,
title: name, // You should add this
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
/* I'll ignore the infoWindow */
});
markers.push(marker);
}
function clearLocations() {
for (var i=0; i<markers.length; i++) {
markers[i].setMap(null);
}
markers=[];
}
function checkboxChanged(i, checked) {
if(checked) {
markers[i].setMap(map);
}
else {
markers[i].setMap(null);
}
}
function createCheckbox(name, i) {
document.getElementById('checkboxes').innerHTML +=
'<input type="checkbox" checked="checked" onclick="checkboxChanged(' + i + ', this.checked);"> ' + name + '<br>';
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<style>
#map-canvas {
width: 500px;
height: 400px;
}
</style>
<div id="map-canvas"></div>
<div id="checkboxes"></div>
Can you manage to include this in your code?
EDIT:
Here is an example of locations in a DB; I bypass xml and communicate through JSON.
It gives you (kind of) a combination of your questions;
I have a different table on my DB, but that shouldn't be a problem.
I add jQuery, just for ajax.
CREATE TABLE IF NOT EXISTS stations (
id bigint(15) NOT NULL AUTO_INCREMENT,
lat decimal(12,10) DEFAULT NULL,
lng decimal(12,10) DEFAULT NULL,
name varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
INSERT INTO stations (id, lat, lng, name) VALUES
(1, '50.8456035000', '4.3568658000', 'Brussel-Centraal'),
(2, '50.8413140000', '4.3490830000', 'Brussel-Kapellekerk'),
(3, '50.8517507000', '4.3623635000', 'Brussel-Congres'),
(4, '50.8604931000', '4.3607035000', 'Brussel-Noord'),
(5, '50.8348278000', '4.3365303000', 'Brussel-Zuid');
index.php
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script type="text/javascript">
var markers = [];
var map;
// settings, to pass to the DB
var lat = 50.84499325563654;
var lng = 4.349978498661017;
var radius = 1.5; /* set this to more than 1.5 to see more locations */
function initialize() {
var position = new google.maps.LatLng(50.84499325563654, 4.349978498661017);
var myOptions = {
zoom: 11,
center: position
};
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
searchNearLocations(lat, lng, radius);
}
function searchNearLocations(lat, lng, radius) {
document.getElementById('checkboxes').innerHTML = '';
// we start an Ajax call.
$.ajax({
url: 'ajax.php',
data: {lat: lat, lng: lng, radius: radius},
dataType: 'json',
success: function(data) {
// the request has returned data. Now we can proceed
clearLocations();
var bounds = new google.maps.LatLngBounds();
for (var i=0; i<data.length; i++) {
var latlng = new google.maps.LatLng(data[i].lat, data[i].lng),
name = data[i].name;
/* add what ever extra data you need */
createMarker(latlng, name, null, null, null);
createCheckbox(name, i); // the most important thing is to pass the i; then markers[i] corresponds with checkboxes[i]
bounds.extend(latlng);
}
map.fitBounds(bounds);
}
});
}
function createMarker(latlng, name, address, info, tts) {
/* var html = "<b>" + name + "</b></br><u>" + address + "</u></br>" + info + "</br>" + "Time allowance to spend: " + tts; */
var marker = new google.maps.Marker({
map: map,
title: name, // You should add this
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
/* I'll ignore the infoWindow */
});
markers.push(marker);
}
function clearLocations() {
for (var i=0; i<markers.length; i++) {
markers[i].setMap(null);
}
markers=[];
}
function checkboxChanged(i, checked) {
if(checked) {
markers[i].setMap(map);
}
else {
markers[i].setMap(null);
}
}
function createCheckbox(name, i) {
document.getElementById('checkboxes').innerHTML +=
'<input type="checkbox" checked="checked" onclick="checkboxChanged(' + i + ', this.checked);"> ' + name + '<br>';
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<style>
#map-canvas {
width: 500px;
height: 400px;
}
</style>
<div id="map-canvas"></div>
<div id="checkboxes"></div>
ajax.php
<?php
$link = mysqli_connect('localhost', 'root', '', 'stackoverflow'); /* put your settings back */
if(!$link) {
die ('unable to connect to the database' . mysqli_connect_error());
}
//Get parameters from URL
$myLat = (isset ($_GET['lat']) ? $_GET['lat'] : 0.0); // give it some default
$myLng = (isset ($_GET['lng']) ? $_GET['lng'] : 0.0);
$calcDistance = (isset ($_GET['radius']) ? $_GET['radius'] : 1.0);
//Search the rows in the markers table
/* I have a slightly different table; I'll continue with mine; it's easy to put everything back */
// $query = sprintf("SELECT siteName,address,lat,lng,info,tts, (6371 * acos(cos(radians('%s')) * cos(radians(lat)) * cos(radians(lng) - radians ('%s')) + sin(radians('%s')) * sin(radians(lat))))AS distance FROM mapTable HAVING distance < '%s' ORDER BY distance LIMIT 0, 50",
$query = sprintf("SELECT id, lat, lng, name, (6371 * acos(cos(radians('%s')) * cos(radians(lat)) * cos(radians(lng) - radians ('%s')) + sin(radians('%s')) * sin(radians(lat)))) AS distance FROM stations HAVING distance < '%s' ORDER BY distance LIMIT 0, 50",
mysqli_real_escape_string($link, $myLat),
mysqli_real_escape_string($link, $myLng),
mysqli_real_escape_string($link,$myLat),
mysqli_real_escape_string($link, $calcDistance));
$result = mysqli_query($link, $query);
$row_cnt = mysqli_num_rows($result);
if(!$result) {
die("Invalid query: " . mysqli_error());
}
header("content-type: application/json; charset=utf-8");
$items = array();
//iterate through the rows,
while($row = mysqli_fetch_assoc($result)) {
$items[] = $row;
}
echo json_encode($items); // this can immediatly be read by javascript
exit;
?>
You can add links/buttons, whith something like
<div onclick="searchNearLocations(50.80, 4.35, 20)">click: 20 km radius from (50.80, 4.35)</div>
To add the position of the client, check out my answer here
google getLocation function not work in my script
I am working on a new project and I am new to the Google maps API.
I need your help to mark only one marker on the map. Our clients would indicate their location with a right click and only if they remove the existing marker they reinsert their location.
I have tried if and else and the only result is that the map does not load.
I have created a fiddle with the code hope it helps: http://jsfiddle.net/JG9bG/
$(document).ready(function () {
var mapCenter = new google.maps.LatLng(39.39987199999999, -8.224454000000037); //Google map Coordinates
var map;
map_initialize(); // initialize google map
//############### Google Map Initialize ##############
function map_initialize() {
var googleMapOptions = {
center: mapCenter, // map center
zoom: 7, //zoom level, 0 = earth view to higher value
maxZoom: 18,
minZoom: 7,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL //zoom control size
},
scaleControl: true, // enable scale control
mapTypeId: google.maps.MapTypeId.ROADMAP // google map type
};
map = new google.maps.Map(document.getElementById("google_map"), googleMapOptions);
//Load Markers from the XML File, Check (map_process.php)
$.get("map_process.php", function (data) {
$(data).find("marker").each(function () {
var name = $(this).attr('name');
var address = '<p>' + $(this).attr('address') + '</p>';
var type = $(this).attr('type');
var point = new google.maps.LatLng(parseFloat($(this).attr('lat')), parseFloat($(this).attr('lng')));
create_marker(point, name, address, false, false, false, "http://google.com/mapfiles/ms/micons/blue.png");
});
});
//Right Click to Drop a New Marker
myListener = google.maps.event.addListener(map, 'rightclick', function (event) {
//Edit form to be displayed with new marker
var EditForm = '<p><div class="marker-edit">' +
'<form action="ajax-save.php" method="POST" name="SaveMarker" id="SaveMarker">' +
'<label for="pid"><span> Property Id: </span><input type="text" readonly name="pid" class="save-propid" value="<?php echo $prop_id;?>" maxlength="40" /></label>' +
'<label for="pName"><span>Place Name :</span><input type="text" name="pName" class="save-name" placeholder="Enter Title" maxlength="40" /></label>' +
'<label for="pDesc"><span>Description :</span><textarea name="pDesc" class="save-desc" placeholder="Enter Address" maxlength="150"></textarea></label>' +
//'<label for="pType"><span>Type :</span> <select name="pType" class="save-type"><option value="Rent">Rent</option><option value="Sell">Sell</option><option value="Holiday Rentals">Holiday Rentals</option></select></label>'+
'</form>' +
'</div></p><button name="save-marker" class="save-marker">Save Marker Details</button>';
//Drop a new Marker with our Edit Form
create_marker(event.latLng, 'Insert your Property Location', EditForm, true, true, true, "http://google.com/mapfiles/ms/micons/green.png");
});
}
//############### Create Marker Function ##############
function create_marker(MapPos, MapTitle, MapDesc, InfoOpenDefault, DragAble, Removable, iconPath) {
//new marker
var marker = new google.maps.Marker({
position: MapPos,
map: map,
draggable: DragAble,
animation: google.maps.Animation.DROP,
title: "Hello World!",
icon: iconPath
});
//Content structure of info Window for the Markers
var contentString = $('<div class="marker-info-win">' +
'<div class="marker-inner-win"><span class="info-content">' +
'<h1 class="marker-heading">' + MapTitle + '</h1>' + MapDesc +
'</span><button name="remove-marker" class="remove-marker" title="Remove Marker">Remove Marker</button>' +
'</div></div>');
//Create an infoWindow
var infowindow = new google.maps.InfoWindow();
//set the content of infoWindow
infowindow.setContent(contentString[0]);
//Find remove button in infoWindow
var removeBtn = contentString.find('button.remove-marker')[0];
var saveBtn = contentString.find('button.save-marker')[0];
//add click listner to remove marker button
google.maps.event.addDomListener(removeBtn, "click", function (event) {
remove_marker(marker);
});
if (typeof saveBtn !== 'undefined') //continue only when save button is present
{
//add click listner to save marker button
google.maps.event.addDomListener(saveBtn, "click", function (event) {
var mReplace = contentString.find('span.info-content'); //html to be replaced after success
var mName = contentString.find('input.save-name')[0].value; //name input field value
var mDesc = contentString.find('textarea.save-desc')[0].value; //description input field value
//var mType = contentString.find('select.save-type')[0].value; //type of marker
var mpid = contentString.find('input.save-propid')[0].value; //prop id
if (mName == '' || mDesc == '') {
alert("Please enter Name and Description!");
} else {
save_marker(marker, mName, mDesc, /*mType, */ mpid, mReplace); //call save marker function
}
});
}
//add click listner to save marker button
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker); // click on marker opens info window
});
if (InfoOpenDefault) //whether info window should be open by default
{
infowindow.open(map, marker);
}
}
//############### Remove Marker Function ##############
function remove_marker(Marker) {
/* determine whether marker is draggable
new markers are draggable and saved markers are fixed */
if (Marker.getDraggable()) {
Marker.setMap(null); //just remove new marker
} else {
//Remove saved marker from DB and map using jQuery Ajax
var mLatLang = Marker.getPosition().toUrlValue(); //get marker position
var myData = {
del: 'true',
latlang: mLatLang
}; //post variables
$.ajax({
type: "POST",
url: "http://.../.../.../cpanel.php?exe=client_properties/google/map_process",
data: myData,
success: function (data) {
Marker.setMap(null);
alert(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(thrownError); //throw any errors
}
});
}
}
//############### Save Marker Function ##############
function save_marker(Marker, mName, mAddress, /*mType, */ mpid, replaceWin) {
//Save new marker using jQuery Ajax
var mLatLang = Marker.getPosition().toUrlValue(); //get marker position
var myData = {
name: mName,
address: mAddress,
latlang: mLatLang,
/*type : mType, */
propid: mpid
}; //post variables
console.log(replaceWin);
$.ajax({
type: "POST",
url: "http://.../.../.../cpanel.php?exe=client_properties/google/map_process",
data: myData,
success: function (data) {
replaceWin.html(data); //replace info window with new html
Marker.setDraggable(false); //set marker to fixed
Marker.setIcon('http://google.com/mapfiles/ms/micons/blue.png'); //replace icon
},
error: function (xhr, ajaxOptions, thrownError) {
alert(thrownError); //throw any errors
}
});
}
});
Thanks for your help
Backend:
<?php
//PHP 5 +
// database settings
$db_username = '';
$db_password = '';
$db_name = '';
$db_host = 'localhost';
//mysqli
$mysqli = new mysqli($db_host, $db_username, $db_password, $db_name);
if (mysqli_connect_errno())
{
header('HTTP/1.1 500 Error: Could not connect to db!');
exit();
}
################ Save & delete markers #################
if($_POST) //run only if there's a post data
{
//make sure request is comming from Ajax
$xhr = $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
if (!$xhr){
header('HTTP/1.1 500 Error: Request must come from Ajax!');
exit();
}
// get marker position and split it for database
$mLatLang = explode(',',$_POST["latlang"]);
$mLat = filter_var($mLatLang[0], FILTER_VALIDATE_FLOAT);
$mLng = filter_var($mLatLang[1], FILTER_VALIDATE_FLOAT);
//Delete Marker
if(isset($_POST["del"]) && $_POST["del"]==true)
{
$results = $mysqli->query("DELETE FROM tblmarkers WHERE geo_lat=$mLat AND geo_lng=$mLng");
if (!$results) {
header('HTTP/1.1 500 Error: Could not delete Marker!');
exit();
}
exit("Done!");
}
$mName = filter_var($_POST["name"], FILTER_SANITIZE_STRING);
$mAddress = filter_var($_POST["address"], FILTER_SANITIZE_STRING);
/* $mType = filter_var($_POST["type"], FILTER_SANITIZE_STRING);*/
$mpid = filter_var($_POST["propid"], FILTER_SANITIZE_STRING);
$results = $mysqli->query("INSERT INTO tblmarkers (geo_name, geo_address, geo_lat, geo_lng, prop_id) VALUES ('$mName','$mAddress',$mLat, $mLng, '$mpid')");
/* $results = $mysqli->query("INSERT INTO tblmarkers (geo_name, geo_address, geo_lat, geo_lng, geo_type, prop_id) VALUES ('$mName','$mAddress',$mLat, $mLng, '$mType', '$mpid')");*/
if (!$results) {
header('HTTP/1.1 500 Error: Could not create marker!');
exit();
}
$output = '<h1 class="marker-heading">'.$mName.'</h1><p>'.$mAddress.'</p>';
exit($output);
}
################ Continue generating Map XML #################
//Create a new DOMDocument object
$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers"); //Create new element node
$parnode = $dom->appendChild($node); //make the node show up
// Select all the rows in the markers table
$results = $mysqli->query("SELECT * FROM tblmarkers WHERE 1");
if (!$results) {
header('HTTP/1.1 500 Error: Could not get markers!');
exit();
}
//set document header to text/xml
header("Content-type: text/xml");
// Iterate through the rows, adding XML nodes for each
while($obj = $results->fetch_object())
{
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("geo_name",$obj->name);
$newnode->setAttribute("geo_address", $obj->address);
$newnode->setAttribute("geo_lat", $obj->lat);
$newnode->setAttribute("geo_lng", $obj->lng);
$newnode->setAttribute("geo_type", $obj->type);
}
echo $dom->saveXML();
Try this :
google.maps.event.addListener(map, "rightclick",function(event){
marker = new google.maps.Marker({
position: event.latLng,
title: 'Changer la position',
map: map,
draggable: true
});
this is an example : http://jsfiddle.net/hweb/M7K4L/
One option:
declare the marker globally (outside of any function definition):
var marker = null;
check to see if it exists, if it does delete it before creating one at the new location:
function create_marker(MapPos, MapTitle, MapDesc, InfoOpenDefault, DragAble, Removable, iconPath) {
if ((marker != null) && marker.setMap) {
marker.setMap(null);
marker = null;
}
//new marker
marker = new google.maps.Marker({
position: MapPos,
map: map,
draggable: DragAble,
animation: google.maps.Animation.DROP,
title: "Hello World!",
icon: iconPath
});
working fiddle
My first aplication about distance matrix to calculate distance. The first If load script are text box auto input by postcode after identify my ISP location. That textbox can input address or postcode to put my realy location after klick button submit query. Marker for my addres or my postcode show. And then with Parse xml with jQuery can show distance every destination.
Now I wil make change how to put my location by mouse over and then If klick in map I will get latlng and location address to process distance matrik AS origin.
This my First code: ( THANKS BEFORE )
(function ($) {
$.fn.storeLocator = function (options) {
var settings = $.extend({
'mapDiv': 'map',
'listDiv': 'list',
'formID': 'user-location',
'pinColor': 'fe7569',
'startPinColor': '66bd4a',
'pinTextColor': '000000',
'storeLimit': 10,
'distanceAlert': 500,
'xmlLocation': 'data/suplier.xml',
'addressErrorMsg': 'Please enter valid address address or postcode',
'googleDistanceMatrixDestinationLimit': 25,
'defaultLat': 49.719330,
'defaultLng': -2.214539,
'defaultLocationName': 'Northampton, United Kingdom'
}, options);
return this.each(function () {
var $this = $(this);
// global array of shop objects
var _locationset = new Array();
var geocoder;
// Calculate distances from passed in origin to all locations in the [_locationset] array
// using Google Maps Distance Matrix Service https://developers.google.com/maps/documentation/javascript/reference#DistanceMatrixService
var GeoCodeCalc = {};
GeoCodeCalc.CalcDistanceGoogle = function (origin, callback) {
var destCoordArr = new Array();
var subFunctionTokens = [];
$.each(_locationset, function (ix, loc) {
destCoordArr.push(loc.LatLng);
});
for (var i = 0; i < destCoordArr.length; i = i + settings.googleDistanceMatrixDestinationLimit) { // Google Distance Matrix allows up to 25 destinations to be passed in
var tempArr = destCoordArr.slice(i, Math.min(i + settings.googleDistanceMatrixDestinationLimit));
subFunctionTokens.push(this.CallGoogleDistanceMatrix(i, origin, tempArr));
}
$.when.apply($, subFunctionTokens)
.then(function () {
callback(true);
});
};
GeoCodeCalc.CallGoogleDistanceMatrix = function (startIndex, origin, destinations) {
var token = $.Deferred();
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin],
destinations: destinations,
travelMode: google.maps.DirectionsTravelMode.DRIVING,
unitSystem: google.maps.DirectionsUnitSystem.IMPERIAL
}, function (response, status) {
if (response && response.rows.length) {
var results = response.rows[0].elements;
$.each(results, function (j, val) {
if (results[j].status != "ZERO_RESULTS") {
_locationset[startIndex + j].Distance = GoogleMapDistanceTextToNumber(results[j].distance.text);
}
});
token.resolve();
}
});
return token.promise();
};
// Converts "123.45 mi" into 123.45
function GoogleMapDistanceTextToNumber(str) {
return Number(str.replace(/[^0-9.]/g, ""));
}
// removes Google Maps URL unfriendly chars from a string
function formatGoogleMapUrlString(str) {
return str.replace("&", "%26").replace(" ", "+");
}
//Geocode function for the origin location
geocoder = new google.maps.Geocoder();
function GoogleGeocode() {
this.geocode = function (address, callbackFunction) {
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var result = {};
result.latitude = results[0].geometry.location.lat();
result.longitude = results[0].geometry.location.lng();
result.formatted_address = results[0].formatted_address;
result.address_components = results[0].address_components;
callbackFunction(result);
} else {
handleError("Geocode was not successful for the following reason: " + status);
callbackFunction(null);
}
});
};
this.geocodeLatLng = function (LatLng, callbackFunction) {
geocoder.geocode({ 'location': LatLng }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK && results.length) {
callbackFunction(results[0]);
} else {
handleError("Geocode was not successful for the following reason: " + status);
callbackFunction(null);
}
});
};
}
//Process form input
$(function () {
$(document).on('submit', '#' + settings.formID, function (e) {
$("#lblError").html("");
//Stop the form submission
e.preventDefault();
//Get the user input and use it
var userinput = $('form').serialize();
userinput = userinput.replace("address=", "");
if (userinput == "") {
handleError(settings.addressErrorMsg);
}
var g = new GoogleGeocode();
var address = userinput;
g.geocode(address, function (data) {
if (data != null) {
showAddress(data);
mapping(data.latitude, data.longitude);
} else {
//Unable to geocode
handleError(settings.addressErrorMsg);
}
});
//Replace spaces in user input
userinput = formatGoogleMapUrlString(userinput);
});
});
$(document).ready(function () {
// Try HTML5 geolocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
//map.setCenter(pos);
var g = new GoogleGeocode();
var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
g.geocodeLatLng(latlng, function (address) {
if (address) {
showAddress(address);
} else {
//Unable to geocode
handleNoGeolocation('Error: Unable to geocode address');
}
});
// do the mapping stuff
mapping(position.coords.latitude, position.coords.longitude);
}, function () {
handleNoGeolocation("Tracking of location was not allowed.");
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
});
function showAddress(address) {
$("#lblAddress").html(address.formatted_address);
// find a postcode and show it in the address textbox
$.each(address.address_components, function (i, val) {
if (val.types[0] == "postal_code") {
$("#address").val(val.short_name);
return false; // breaks the each() loop
}
});
}
function handleNoGeolocation(error) {
if (error) {
var content = error;
} else {
var content = 'Error: Your browser doesn\'t support geolocation.';
}
handleError(content + " Using default location.");
mapping(settings.defaultLat, settings.defaultLng);
$("#lblAddress").html(settings.defaultLocationName);
}
function handleError(error) {
$("#lblError").html(error);
}
//Now all the mapping stuff
function mapping(orig_lat, orig_lng) {
$(function () {
//Parse xml with jQuery
$.ajax({
type: "GET",
url: settings.xmlLocation,
dataType: "xml",
success: function (xml) {
_locationset = new Array();
$(xml).find('Placemark').each(function (i) {
var shop = {
Name: $(this).find('name').text(),
//Take the lat lng from the user, geocoded above
LatLng: new google.maps.LatLng(
$(this).find('coordinates').text().split(",")[1],
$(this).find('coordinates').text().split(",")[0]),
Description: $(this).find('description').text(),
Ongkir:$(this).find('ongkir').text(),
Muat:$(this).find('muat').text(),
Item:$(this).find('item').text(),
Kirim: (($(this).find('item').text())/($(this).find('muat').text())),
Marker: null,
Distance: null
};
_locationset.push(shop);
});
// Calc Distances from user's location
GeoCodeCalc.CalcDistanceGoogle(new google.maps.LatLng(orig_lat, orig_lng), function (success) {
if (!success) { //something went wrong
handleError("Unable to calculate distances at this time");
}
else {
//Sort the multi-dimensional array numerically
_locationset.sort(function (a, b) {
return ((a.Distance < b.Distance) ? -1 : ((a.Distance > b.Distance) ? 1 : 0));
});
// take "N" closest shops
_locationset = _locationset.slice(0, settings.storeLimit);
//Check the closest marker
if (_locationset[0].Distance > settings.distanceAlert) {
handleError("Unfortunately, our closest location is more than " + settings.distanceAlert + " miles away.");
}
//Create the map with jQuery
$(function () {
var orig_LatLng = new google.maps.LatLng(orig_lat, orig_lng);
//Google maps settings
var myOptions = {
center: orig_LatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById(settings.mapDiv), myOptions);
//Create one infowindow to fill later
var infowindow = new google.maps.InfoWindow();
//Add user location marker
var marker = createMarker(orig_LatLng, "0", settings.startPinColor);
marker.setAnimation(google.maps.Animation.DROP);
var bounds = new google.maps.LatLngBounds();
bounds.extend(orig_LatLng);
$("#" + settings.listDiv).empty();
$(_locationset).each(function (i, location) {
bounds.extend(location.LatLng);
letter = String.fromCharCode("A".charCodeAt(0) + i);
location.Marker = createMarker(location.LatLng, letter, settings.pinColor);
create_infowindow(location);
listClick(letter, location);
});
// zoom in/out to show all markers
map.fitBounds(bounds);
function listClick(letter, shop) {
$('<li />').html("<div class=\"list-details\"><div class=\"list-content\">"
+ "<div class=\"list-label\">" + letter + "<\/div>"
+ "<div class=\"loc-name\">" + shop.Name + "<\/div> <div class=\"loc-addr\">" + shop.Description + "<\/div>Muat " + shop.Muat + " <div class=\"loc-addr\">Rp." + shop.Ongkir + " per Km<\/div> "
+ (shop.Distance ? "<div class=\"loc-addr2\"><i>Jarak Tempuh. "+Math.ceil(shop.Distance*1.6) + "Km</i><\/br>"+ Math.ceil(shop.Kirim) + " Kali Angkut <\/br><\/br>ONGKOS KIRIM <input type=\"text\" readonly=\"readonly\" size=\"20\" name=\"jarak\" value=\"Rp. "+Math.ceil((shop.Distance * shop.Ongkir*1.6) * Math.ceil(shop.Kirim)) + "\" /><\/div>" : "")
+ "<div class=\"loc-web\"><a href=\"http://maps.google.co.uk/maps?saddr="
+ formatGoogleMapUrlString($("#address").val()) + "+%40" + orig_lat + "," + orig_lng
+ "&daddr=" + formatGoogleMapUrlString(shop.Name) + "+%40" + shop.LatLng.lat() + "," + shop.LatLng.lng()
+ "&hl=en" + "\" target=\"_blank\">>Get directions</a><\/div><\/div><\/div>")
.click(function () {
create_infowindow(shop, "left");
}).appendTo("#" + settings.listDiv);
};
//Custom marker function - aplhabetical
function createMarker(point, letter, pinColor) {
//Set up pin icon with the Google Charts API for all of our markers
var pinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=" + letter + "|" + pinColor + "|" + settings.pinTextColor,
new google.maps.Size(21, 34),
new google.maps.Point(0, 0),
new google.maps.Point(10, 34));
var pinShadow = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_shadow",
new google.maps.Size(40, 37),
new google.maps.Point(0, 0),
new google.maps.Point(12, 35));
//Create the markers
return new google.maps.Marker({
position: point,
map: map,
icon: pinImage,
shadow: pinShadow,
draggable: false
});
};
//Infowindows
function create_infowindow(shop, listLocation) {
var formattedAddress = "<div class=\"infoWindow\"><b>" + shop.Name + "<\/b>"
+ "<div>" + shop.Description + "<\/div>"
+ (shop.Distance ? "<div><i>" + shop.Distance + " miles<\/i><\/div><\/div>" : "<\/div>");
//Opens the infowindow when list item is clicked
if (listLocation == "left") {
infowindow.setContent(formattedAddress);
infowindow.open(shop.Marker.get(settings.mapDiv), shop.Marker);
}
//Opens the infowindow when the marker is clicked
else {
google.maps.event.addListener(shop.Marker, 'click', function () {
infowindow.setContent(formattedAddress);
infowindow.open(shop.Marker.get(settings.mapDiv), shop.Marker);
})
}
};
});
}
});
}
});
});
}
});
};
})(jQuery);
I'm not sure to understand your question, but if what you want is to be able to add a marker by clicking the map and then lunch the distance calculation what you have to do is to add a click event listener to the map and do what you have to do there.
Consider the following exemple (change YOUR_GOOGLE_MAPS_API_KEY for your own key in order to be able to run the demo):
<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<title></title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_MAPS_API_KEY&sensor=false">
</script>
<style type="text/css">
html
{
height: 100%;
}
body
{
height: 100%;
margin: 0;
padding: 0;
}
#map-container
{
height: 100%;
width: 100%;
min-width:500px;
min-height:300px;
}
</style>
</head>
<body>
<div id="map-container">
Div map
</div>
<script type="text/javascript" language="javascript">
var map;
$(document).ready(function () {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(-34.397, 150.644),
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map($("#map-container")[0], mapOptions);
google.maps.event.addListener(map, 'click', function (mouseEvent) {
var origin = mouseEvent.latLng;
var marker = new google.maps.Marker({ position: origin });
marker.setMap(map);
//console.log("map clicked");
// your logic ......
// returnFromCalcDistanceGoogle(origin, callback);
// your logic ......
});
});
function returnFromCalcDistanceGoogle() {
// your logic ......
}
</script>
</body>
</html>
If this is not what your trying to do, please clarify your question.
Like that Mr.sabotero . .. but i will use this in my first application that. When I klick the map LatLng can input in my textbox with id="address" to submit query. Before the textbox with id="address" just work if input by addres and postcode. Now I want LatLang can input and process in textbox with id="address"
<div id="form-input">
<label for="address">
Masukan Lokasi Anda</label>
<input type="text" id="address" name="address" value="" class="input-medium search-query" />
</div>
<div id="submit-btn">
<input type="submit" id="submit" name="submit" class="btn btn-warning" /></div>
input postscode or address
Klick submit Query
Marker Origin show with color green
NOW I wont,
1. klick map
2. textbox get latlng or addres
3. submit query
I've set up google map API that loads data from mysql database and display markers. the problem I am facing is that all the markers shows up at once no matter whatever I input in search location field.............. I want to show only the searched area and markers in that area. It shouldn't display all the markers at once but only the marker in the searched area.
I mean I want to zoom the map to the searched area. Currently if I've only one marker map zoom in to show that but if I've many markers the map zoom out to show all the markers. Here is the map I'm working on "http://funfeat.com/clients/gmap/gmap3.html" NOW I've set markers very very far and the map is still showing all the markers by zooming out.
The gmap.php is the file that provide xml results from mysql database. and the below code is what I am using to display map
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<title>Google Maps AJAX + mySQL/PHP Example</title>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"
type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
var map;
var markers = [];
var infoWindow;
var locationSelect;
function load() {
map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(40, -100),
zoom: 10,
mapTypeId: 'roadmap',
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}
});
infoWindow = new google.maps.InfoWindow();
locationSelect = document.getElementById("locationSelect");
locationSelect.onchange = function() {
var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
if (markerNum != "none"){
google.maps.event.trigger(markers[markerNum], 'click');
}
};
}
function searchLocations() {
var address = document.getElementById("addressInput").value;
var geocoder = new google.maps.Geocoder();
geocoder.geocode({address: address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
searchLocationsNear(results[0].geometry.location);
} else {
alert(address + ' not found');
}
});
}
function clearLocations() {
infoWindow.close();
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers.length = 0;
locationSelect.innerHTML = "";
var option = document.createElement("option");
option.value = "none";
option.innerHTML = "See all results:";
locationSelect.appendChild(option);
}
function searchLocationsNear(center) {
clearLocations();
var radius = document.getElementById('radiusSelect').value;
var searchUrl = 'gmap.php?lat=' + center.lat() + '&lng=' + center.lng() + '&radius=' + radius;
downloadUrl(searchUrl, function(data) {
var xml = parseXml(data);
var markerNodes = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markerNodes.length; i++) {
var name = markerNodes[i].getAttribute("name");
var address = markerNodes[i].getAttribute("address");
var distance = parseFloat(markerNodes[i].getAttribute("distance"));
var latlng = new google.maps.LatLng(
parseFloat(markerNodes[i].getAttribute("lat")),
parseFloat(markerNodes[i].getAttribute("lng")));
createOption(name, distance, i);
createMarker(latlng, name, address);
bounds.extend(latlng);
}
map.fitBounds(bounds);
locationSelect.style.visibility = "visible";
locationSelect.onchange = function() {
var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
google.maps.event.trigger(markers[markerNum], 'click');
};
});
}
function createMarker(latlng, name, address) {
var html = "<b>" + name + "</b> <br/>" + address;
var marker = new google.maps.Marker({
map: map,
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
markers.push(marker);
}
function createOption(name, distance, num) {
var option = document.createElement("option");
option.value = num;
option.innerHTML = name + "(" + distance.toFixed(1) + ")";
locationSelect.appendChild(option);
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request.responseText, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function parseXml(str) {
if (window.ActiveXObject) {
var doc = new ActiveXObject('Microsoft.XMLDOM');
doc.loadXML(str);
return doc;
} else if (window.DOMParser) {
return (new DOMParser).parseFromString(str, 'text/xml');
}
}
function doNothing() {}
//]]>
</script>
</head>
<body style="margin:0px; padding:0px;" onLoad="load()">
<div>
<input type="text" id="addressInput" size="10"/>
<select id="radiusSelect">
<option value="25" selected>25mi</option>
<option value="100">100mi</option>
<option value="200">200mi</option>
</select>
<input type="button" onClick="searchLocations()" value="Search"/>
</div>
<div><select id="locationSelect" style="width:100%;visibility:hidden"></select></div>
<div id="map" style="width: 100%; height: 80%"></div>
</body>
</html>
http://funfeat.com/clients/gmap/gmap.php?lat=47&lng=-122&radius=2 produces valid XML but your query must be wrong .It pulls out 10 markers, 9 of which are correct but the 10th produces <marker name="Pakistan" address="Chowk Azam, Layyah" lat="31.008364" lng="71.224342" type="cITY"/> which is certainly not within 2 miles of the coordinates. Your query should not pick up the last marker from the database.
As the use of mysql_ functions are discouraged the following code uses PDO can be used
//dependant on your setup
$host= "WWW";
$username="XXX";
$password="YYY";
$database="ZZZ";
// Get parameters from URL
$center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"];
// Start XML file, create parent node
$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node);
//Connect to database
$dbh = new PDO("mysql:host=$host;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
// Prepare statement
$stmt = $dbh->prepare("SELECT name, lat, lng, ( 3959 * acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ) AS distance FROM gbstn HAVING distance < ? ORDER BY distance ASC LIMIT 0 , 20");
// Assign parameters
$stmt->bindParam(1,$center_lat);
$stmt->bindParam(2,$center_lng);
$stmt->bindParam(3,$center_lat);
$stmt->bindParam(4,$radius);
//Execute query
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();
EDIT Added to catch error if no records found
if ($stmt->rowCount()==0) {
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("name", "No Records Found");
$newnode->setAttribute("lat", $center_lat);//Sends marker to search location
$newnode->setAttribute("lng", $center_lng);
$newnode->setAttribute("distance", 0);
}
else {
End of EDIT
// Iterate through the rows, adding XML nodes for each
while($row = $stmt->fetch()) {
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("name", $row['name']);
$newnode->setAttribute("address", $row['address']);
$newnode->setAttribute("lat", $row['lat']);
$newnode->setAttribute("lng", $row['lng']);
$newnode->setAttribute("distance", $row['distance']);
}
}
echo $dom->saveXML();
}
catch(PDOException $e) {
echo "I'm sorry I'm afraid you can't do that.". $e->getMessage() ;// Remove or modify after testing
file_put_contents('PDOErrors.txt',date('[Y-m-d H:i:s]').", gmap.php, ". $e->getMessage()."\r\n", FILE_APPEND);
}
//Close the connection
$dbh = null;
The part of the query above HAVING distance < '%s' is the part that should weed out the last marker.
I have added Error catch if no records are found in search and Map sent to lat/lng 0,0. See My Implementation Here