Javascript to PHP and innerHTML deletion - javascript

I am implementing a script but need some help on two issues that I am unable to figure out. The idea is to allow someone to create a running route and store the route into a database via the coordinates.
The code is as follows:
(credits to: Post 19 Here and This Fiddle here)
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<title>Drawing Tools (B)</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script>
window.onload = function() {
var latlng = new google.maps.LatLng(51.4975941, -0.0803232);
var map = new google.maps.Map(document.getElementById('map'), {
center: latlng,
zoom: 11,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: 'Set lat/lon values for this property',
draggable: true
});
google.maps.event.addListener(marker, 'dragend', function(a) {
console.log(a);
var div = document.createElement('div');
div.innerHTML = a.latLng.lat().toFixed(4) + ', ' + a.latLng.lng().toFixed(4);
document.getElementsByTagName('body')[0].appendChild(div);
});
};
</script>
</head>
<body>
<div id="map" style="height:300px;"></div>
</body>
</html>
First problem I am trying to solve:
div.innerHTML = a.latLng.lat().toFixed(4) + ', ' + a.latLng.lng().toFixed(4);
How can I add each of these lat & long coordinates (as the person creates their route) into a PHP array in order to insert them into a database. I am struggling with this as it is displaying them on the fly.
Second problem I am trying to solve:
div.innerHTML = a.latLng.lat().toFixed(4) + ', ' + a.latLng.lng().toFixed(4);
If the user drops the pin is there a way to delete the latest coords should they make a mistake?
I have tried different methods (I am no good with JS);
div.innerHTML = a.latLng.lat().toFixed(4) + ', ' + a.latLng.lng().toFixed(4) + ', <a onClick="$(this).closest("div").remove();">Delete</a>';
But can't seem to get it working.
Any help on these problems would be appreciated. Many thanks.

It would be easier to hold the co-ordinates in a javascript object/array so they can be added/removed and saved easily.
I would also use a more appropriate html element to display them to the user, eg an unordered/ordered list:
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<title>Drawing Tools (B)</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script>
$(function() {
//Create an object to hold the values and encapsulate adding, removing and saving
function List(ul, save){
this.items = [];
this.ul = ul;
this.save = save;
}
//add item to list
List.prototype.add=function(item){
this.items.push(item);
this.rebuildDom();
};
//remove item from list
List.prototype.removeAt=function(index){
this.items.splice(index, 1);
this.rebuildDom();
};
//update the contents of the <ul> list to display current list items
List.prototype.rebuildDom=function(){
var html='';
for(var i = 0; i < this.items.length; i++){
//note change here, each item is now an array, so it must be
//joined into a string for display
html += '<li>'+this.items[i].join(' , ') +'<span class="remove" data-id="'+i+'">X</span></li>'
}
$('#'+this.ul).html(html);
};
//upload the data via ajax
List.prototype.upload=function(){
var data = {data: this.items};
$.post('/save.php', data, function(response){
console.log(response);
})
};
List.prototype.init = function(){
var _this = this;
//remove items from list when remove is clicked
$('#'+this.ul).on('click', 'span.remove', function(){
var index = $(this).data('id');
_this.removeAt(index);
});
//bind to click event of save button, and upload data
$('#'+this.save).click(function(ev){
ev.preventDefault();
_this.upload();
});
};
var list = new List('items', 'save');
list.init();
var latlng = new google.maps.LatLng(51.4975941, -0.0803232);
var map = new google.maps.Map(document.getElementById('map'), {
center: latlng,
zoom: 11,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: 'Set lat/lon values for this property',
draggable: true
});
google.maps.event.addListener(marker, 'dragend', function(a) {
console.log(a);
//note item is now an array containing both values, not a string
var item = [a.latLng.lat().toFixed(4) , a.latLng.lng().toFixed(4)];
//add item to our list
list.add(item);
});
});
</script>
<style>
body{
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
#map{
height: 400px;
border-bottom: 1px solid #666666;
margin-bottom: 20px;
}
h3{
font-family: inherit;
}
#items{
list-style: none;
width: 300px;
border: 1px solid #d8d8d8;
}
#items li{
background-color: #666666;
padding: 5px;
margin: 5px;
color:#ffffff;
}
#items li span.remove{
float: right;
background-color: red;
color: #ffffff;
margin: -5px;
padding: 5px;
}
</style>
</head>
<body>
<div id="map" ></div>
<button id="save">Save</button>
<h3>Co-ordinates of your route:</h3>
<ul id="items"></ul>
</body>
</html>
Live example:
https://jsfiddle.net/rmsjf5oy/2/
To retrieve the data in php, you can simply access the $_POST super global:
//save.php
if(isset($_POST['data']){
$co-ordinates = $_POST['data'];
// $co-ordinates is now a php array like
// [
// ['51.4886', '-0.0666'],
// ['51.4886', '-0.0666'],
// ['51.4886', '-0.0666']
// ]
//do something with the data then send a message back to the javascript
header('Content-Type: application/json');
echo json_encode(['success'=>true, 'message'=>'Thanks, got the data']);
}
Look in the js console in your browser to see the response, or do something other than console.log(response); in the upload method to do something else with the data, such as show it in a div

First problem
You can't send JS data to PHP unless you make a server call. Once the page is rendered - PHP shuts down and that's it, while JS keeps running in the browser (read about server-side vs client-side programming).
You probably want to make an AJAX call to send the lat/long data back to the server in order to insert them into the database.
Second problem
(please try to have a separate question for each next time)
$(this).parent().remove(); should work.

Related

Confused About Map Updates

I'm very new to using Google Maps and very new to intricate javascript. Bearing this in mind, I'm trying to create a web map, with a feed from USGS. This feed is updated every 5 minutes. I'd like to have my map refresh every 5 minutes using this same feed (which is a geojson file).
My end goal is to have this and at least one other feed displayed/updated on my map. Over the past four days, I've gone through dozens of posts, and am at the point of being overloaded and confused. Will someone please clear my fog?
The code I'm posting is 99% not my code, mostly I've added comments so I can figure out what's going on in the code.
<HTML>
<HEAD>
<TITLE>TEST OF MAP</TITLE>
<STYLE>
/* --------------------------------------------------- */
/* Set the map height explicitly to define the size of */
/* the DIV * element that contains the map. */
/* ----------------------------------------------------*/
#map {
height: 75%;
border: 5px solid green;
}
</STYLE>
</HEAD>
<SCRIPT type="text/javascript">
// --------------------------------------
// Set a refresh interval in milliseconds
// --------------------------------------
setInterval(page_refresh, 1*60000);
google.maps.event.addDomListener(window, 'load', initialize);
</SCRIPT>
<BODY>
<H1><CENTER>MAP Demo</CENTER></H1>
<DIV id="map"></DIV>
<SCRIPT>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: new google.maps.LatLng(35.4437,139.6380),
mapTypeId: 'terrain'
});
// ---------------------------------------------------------
// Create a <SCRIPT> tag and set the USGS URL as the source.
// ---------------------------------------------------------
var script = document.createElement('script');
// -----------------------------------------------------------------------
// Using a local copy of the GeoJSON stored on the USGS server
//
http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_hour.geojsonp
// -----------------------------------------------------------------------
script.src =
'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_hour.geojson
p';
document.getElementsByTagName('head')[0].appendChild(script);
}
// ------------------------------------------------------------------
// Loop through the results array and place a marker for each set of
// coordinates.
// ------------------------------------------------------------------
window.eqfeed_callback = function(results) {
for (var i = 0; i < results.features.length; i++) {
var coords = results.features[i].geometry.coordinates;
var latLng = new google.maps.LatLng(coords[1],coords[0]);
var marker = new google.maps.Marker({
position: latLng,
map: map
});
}
}
</SCRIPT>
<SCRIPT async defer src="https://maps.googleapis.com/maps/api/js?
key=MY_MAP_KEY&callback=initMap">
</SCRIPT>
</BODY>
</HTML>
Though not very elegant, I used the following for the refresh. Since I'm only building a "proof of concept", refreshing the entire page is not a problem.
function timedRefresh(timeoutPeriod) {
setTimeout("location.reload(true);",timeoutPeriod);
}
window.onload = timedRefresh(60*5000);

Plot the route between multiple markers using MapBox

I'm using MapBox API to create different maps. I have around 25 markers with latitude and longitude information for each marker. I'm able to plot the markers on the map. Now I want to draw the road connecting these markers. Can someone let me know how to do this using MapBox API.
Below is the html code that I am using to plot the markers.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<script src='https://api.mapbox.com/mapbox.js/v2.4.0/mapbox.js'></script>
<link href='https://api.mapbox.com/mapbox.js/v2.4.0/mapbox.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
.map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
.my-icon {
border-radius: 100%;
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
color: white;
}
.icon-dc {
background: #3ca0d3;
}
.icon-sf {
background: #63b6e5;
}
</style>
<div id='map-two' class='map'> </div>
<script>
L.mapbox.accessToken = '<your access token>';
var mapTwo = L.mapbox.map('map-two', 'mapbox.light')
.setView([12.9716,77.5946], 20);
var myLayer = L.mapbox.featureLayer().addTo(mapTwo);
var geojson = [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [77.5048747113, 13.0408676171]
},
properties: {
icon: {
className: 'my-icon icon-dc', // class name to style
html: '★', // add content inside the marker
iconSize: null // size of icon, use null to set the size in CSS
}
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [77.5045504332, 13.0386169339]
},
properties: {
icon: {
className: 'my-icon icon-sf', // class name to style
html: '★', // add content inside the marker
iconSize: null // size of icon, use null to set the size in CSS
}
}
}
];
myLayer.on('layeradd', function(e) {
var marker = e.layer,
feature = marker.feature;
marker.setIcon(L.divIcon(feature.properties.icon));
});
myLayer.setGeoJSON(geojson);
mapTwo.scrollWheelZoom.disable();
</script>
</body>
</html>
Please let me know if there is any other way to plot the route between the markers.
Thanks.
You can do this with the mapbox directions API. Via a GET request you are able to calculate a route between two points e.g A and B. The snippet done with jQuery could look like the following:
$.get('https://api.mapbox.com/directions/v5/mapbox/cycling/' + lngA + ',' + latA + ';' + lngB + ',' + latB + '?access_token=<your-access-token>',
function(data) {
var coords = polyline.decode(data.routes[0].geometry); // Get the geometry of the request and convert it from a Google string to coordinates
var line = L.polyline(coords).addTo(mapTwo);
});
Regarding to your question you want to connect each marker with each other! So I have created a function to calculate the route and add this function into a double loop, to rout from each marker to each marker:
function calculateRoute(geomFrom, geomTo) {
var lngFrom = geomFrom.geometry.coordinates[0]
var latFrom = geomFrom.geometry.coordinates[1]
var lngTo = geomTo.geometry.coordinates[0]
var latTo = geomTo.geometry.coordinates[1]
$.get('https://api.mapbox.com/directions/v5/mapbox/cycling/' + lngFrom + ',' + latFrom + ';' + lngTo + ',' + latTo + '?access_token=pk.eyJ1IjoicHJheWVyIiwiYSI6ImI3OGRjZjcyY2JiZTUzODMwZWUxZDdiNjRiMWE4NjI5In0.zETX-x6-XPpAv3zt4MiFwg',
function( data ) {
var coords = polyline.decode(data.routes[0].geometry);
var line = L.polyline(coords).addTo(mapTwo);
});
};
This calculates the route between each markers in a geoJSON. Here you got a little << FIDDLE >>, based on your questions code. I hope this was usefull and I could help you !

Getting javascript variable value into python from QWebView

In my application, I have a form on one side and google maps on the other side. To display google maps, I'm using their javascript api. The javascript is writing as a string and part of the html which gets gets called by QWebView. My objective is for the user to click and drag the pin. After the pin has stopped dragging, it would update 2 text boxes on the right side through qt which will populate with the latitude and longitude of the dropped pin. I am having trouble figuring out how to send the data between javascript and python. I am using python3 with pyside qt bindings.
Here is what I have so far.
webView = QWebView()
webView.setHtml(html)
self.central_widget_grid.addWidget(webView,1,0)
Html is a constant defined in another file
#!/usr/bin/python
jscode = """
var map;
var marker;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.793697, lng: -77.8586},
zoom: 10
});
map.addListener('click', function(e) {
placeMarkerAndPanTo(e.latLng, map);
});
}
function placeMarkerAndPanTo(latLng, map) {
if (marker === undefined) {
marker = new google.maps.Marker({
position: latLng,
map: map,
title: "Station Location",
draggable: true
});
map.panTo(latLng);
marker.addListener('dragend', function() { draggedMarker(); });
}
}
function draggedMarker() {
alert(marker.getPosition());
statLoc.updateLoc(marker.getPosition().lat(), marker.getPosition().lng());
}
"""
html = """<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0px; padding: 0px }
#map_canvas { height: 100% }
</style>
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false&callback=initMap">
</script>
<script type="text/javascript">""" + jscode + """
</script>
</head>
<body onload="initMap();">
<div id="map" style="width:100%; height:100%"></div>
</body>
</html>"""
I have tried creating a class which holds the latitude and longitude and then passing that by calling addToJavaScriptWindowObject.
class StationLocation(QObject):
latitude = 0.0
longitude = 0.0
def __init__(self):
super(StationLocation, self).__init__()
def updateLoc(self,lat,long):
self.latitude = lat
self.longitude = long
print(self.latitude, self.longitude)
With the following changes to my webView
webView = QWebView()
webView.setHtml(html)
frame = webView.page().mainFrame()
frame.addToJavaScriptWindowObject('statLoc', self.station_location)
self.central_widget_grid.addWidget(webView, 1, 0)
With that added. With the print statement inside StationLocations, I expect to see the latitude and longitude printed in the console every time that function is called. I can't find out why this isn't the case.
There are two things you are doing wrong. Firstly, you need to wait until the page is loaded before adding the object. Secondly, the javascript must only call methods of the added object that are decorated as slots.
Below is a working demo. But one caveat: the PySide implementation of addToJavaScriptWindowObject is buggy. It should be possible to use self (i.e. the main window) as the added object, but when I try that with PySide, it hangs on exit for several seconds and then dumps core. For this reason, I used a proxy object in the demo - but with PyQt, the proxy wouldn't be needed.
import sys
from PySide import QtCore, QtGui, QtWebKit
html = '''
<html><head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map { width: 100%; height: 100% }
</style>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script type="text/javascript">
var map, marker
function initialize() {
map = new google.maps.Map(document.getElementById("map"), {
center: {lat: 40.793697, lng: -77.8586},
zoom: 10
})
marker = new google.maps.Marker({
map: map,
position: map.getCenter(),
draggable: true
})
marker.addListener("dragend", function () {
var pos = marker.getPosition()
qt.showLocation(pos.lat(), pos.lng())
console.log("dragend: " + pos.toString())
})
}
google.maps.event.addDomListener(window, "load", initialize)
</script>
</head>
<body><div id="map"/></body>
</html>
'''
class WebPage(QtWebKit.QWebPage):
def javaScriptConsoleMessage(self, message, line, source):
if source:
print('line(%s) source(%s): %s' % (line, source, message))
else:
print(message)
class Proxy(QtCore.QObject):
#QtCore.Slot(float, float)
def showLocation(self, latitude, longitude):
self.parent().edit.setText('%s, %s' % (latitude, longitude))
class MainWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.view = QtWebKit.QWebView(self)
self.view.setPage(WebPage(self))
self.edit = QtGui.QLineEdit(self)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.view)
layout.addWidget(self.edit)
self.map = self.view.page().mainFrame()
self.map.loadFinished.connect(self.handleLoadFinished)
self.view.setHtml(html)
self._proxy = Proxy(self)
def handleLoadFinished(self, ok):
self.map.addToJavaScriptWindowObject('qt', self._proxy)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.setGeometry(500, 300, 800, 600)
window.show()
sys.exit(app.exec_())

JavaScript global variable in Google Maps

I'm making a webapp that allows people to see the location of buses on Google maps. I'm having some problems with global variables in JavaScript. window.variable doesn't work for me. Neither does defining the variable outside the all the functions works. Here is my complete client side code:
<!DOCTYPE html>
<html>
<head>
<title>Geolocation</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
// Note: This example requires that you consent to location sharing when
// prompted by your browser. If you see a blank space instead of the map, this
// is probably because you have denied permission for location sharing.
var old = [];
function getLocation()
{
$.get( "http://54.86.161.214/EC_bus_app/get_location.php", function( data ) {
old=[];
var buses = data;
var number_of_buses = buses.slice(0,1);
buses = buses.slice(2);
buses = buses.slice(0,-1);
var bus_coordinates_and_numbers = buses.split(/[ ]+/);
var length_of_array = bus_coordinates_and_numbers.length;
// Turn a single dimensional array into a multi-dimensional array
for (var index = 0; index < bus_coordinates_and_numbers.length; index+= 3)
old.push( bus_coordinates_and_numbers.slice(index, index + 3) );
console.log(old);
//initialize(old);
});
}
setInterval(getLocation, 10000);
var map;
function initialize() {
var mapOptions = {
zoom: 18
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var image = "icon_97.png";
for (i=0;i<old.length; i = i + 1){
var x = old[i][0];
var y = old[i][1];
var myLatlng = new google.maps.LatLng(x,y);
var busMarker = new google.maps.Marker({
position: myLatlng,
map: map,
icon: image,
title: old[i][2]
});
}
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: 'Your location'
});
map.setCenter(pos);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
}
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = 'Error: The Geolocation service failed.';
} else {
var content = 'Error: Your browser doesn\'t support geolocation.';
}
var options = {
map: map,
position: new google.maps.LatLng(60, 105),
content: content
};
var infowindow = new google.maps.InfoWindow(options);
map.setCenter(options.position);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
The variable in question is old. I can pass it to the initialize function from within the get location function using initialize(old);. However, as you can see, I'm using a timer, and initialize(old); causes the entire map to reload again and again, whereas I only want the location markers to load again and again.
Solved the problem by moving getLocation() inside initialize(). But what #geocodezip said in the comments also answers my question completely.
Your problem is not with global variables. It is with asynchronous functions. You need to initialize the map, then request data (asynchronous request), make markers on the map, then periodically update them.

Google maps infowindow display kml object name and link

I have some working code to display a KML layer on Google maps. When you click on the various parts of the layer their respective name pops up in an info window.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map-canvas { height: 100% }
</style>
<script type="text/javascript"
// Load Google Maps API
src="https://maps.googleapis.com/maps/api/js?key=XXXXXXXXXXX&sensor=false">
</script>
<script type="text/javascript">
function initialize() {
var myLatlng = new google.maps.LatLng(51.875696, -0.624207);
var mapOptions = {
zoom: 6,
center: myLatlng
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var kmlLayer = new google.maps.KmlLayer({
url: 'http://XXXXXXX.org/gliding/grid3.kml',
suppressInfoWindows: false,
map: map
});
google.maps.event.addListener(kmlLayer, 'click', function(kmlEvent) {
var text = kmlEvent.featureData.name;
showInContentWindow(text);
});
function showInContentWindow(text) {
var sidediv = document.getElementById('content-window');
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas" style="width:100%; height:100%; float:left"></div>
</body>
</html>
I would like the info window to also contain a link to a page with the same name as object clicked on. For example if the user clicks on a shape in the KML layer called Tom the info window says Tom Click Here. If the user clicks the link they are taken to www.XYZ.com/Tom.
I'm sure this is quite simple, but I'm new to javascript and can't get it to work.
This is more a hack than a solution (which means google could change a property name and this would stop working.
However, here you go
google.maps.event.addListener(kmlLayer, 'click', function(kmlEvent) {
var text = kmlEvent.featureData.name;
kmlEvent.featureData.infoWindowHtml += 'Click Here';
showInContentWindow(text);
});

Categories

Resources