From 8c9a527fdf9a54699a596e0a6579cc95fb9b4314 Mon Sep 17 00:00:00 2001 From: bfabiszewski Date: Fri, 21 Jun 2013 11:15:09 +0200 Subject: OpenLayers API --- README | 13 ++-- api_gmaps.js | 173 ++++++++++++++++++++++++++++++++++++++++++++++ api_openlayers.js | 169 +++++++++++++++++++++++++++++++++++++++++++++ config.php | 17 +++-- index.php | 64 ++++++----------- lang.php | 2 + main.css | 16 +++-- main.js | 200 ++++++++++++++++++------------------------------------ 8 files changed, 463 insertions(+), 191 deletions(-) create mode 100755 api_gmaps.js create mode 100755 api_openlayers.js diff --git a/README b/README index fb83fd3..397c2e9 100755 --- a/README +++ b/README @@ -1,15 +1,15 @@ This is a simple web viewer for GPS tracks uploaded with mobile client. It is designed to work with Android version of great app TrackMe (http://www.luisespinosa.com/trackme_eng.html), -but it should be easy to adjust it for other clients. +but it should be easy to adjust it for other clients (other database tables). Interface "look and feel" is based on TrackMe Display (http://forum.xda-developers.com/showthread.php?t=477394). -It currently uses Google Maps API, but work on OpenStreetMap is in progress. +It is possible to switch between Google Maps API and OpenLayers API with OpenStreetMap (any other base layer should be easy to add). Live demo: - http://flaa.fabiszewski.net/phptrackme/ Requirements: -- php 5 -- mysql +- PHP 5.1.2 +- MYSQL 4.1 - browser with javascript enabled, cookies for authentication Features: @@ -20,12 +20,13 @@ Features: - multiple users - user authentication - Google Maps API v3 +- OpenLayers 2.13 - ajax - server based configuration Todo -- OpenStreetMap API -- client based configuration +- install script +- user level customization, storing settings in cookies? - write opensource client? License diff --git a/api_gmaps.js b/api_gmaps.js new file mode 100755 index 0000000..d4132ce --- /dev/null +++ b/api_gmaps.js @@ -0,0 +1,173 @@ +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +// google maps +var map; +var polies = new Array(); +var markers = new Array(); +var popups = new Array(); +var polyOptions; +var mapOptions; +var loadedAPI = 'gmaps'; +function init() { +google.maps.visualRefresh = true; + polyOptions = { + strokeColor: '#FF0000', + strokeOpacity: 1.0, + strokeWeight: 2 + } + mapOptions = { + center: new google.maps.LatLng(52.23, 21.01), + zoom: 8, + mapTypeId: google.maps.MapTypeId.ROADMAP, + scaleControl: true + }; + map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions); +} + +function displayTrack(xml,update) { + altitudes.length = 0; + var totalMeters = 0; + var totalSeconds = 0; + // init polyline + var poly = new google.maps.Polyline(polyOptions); + poly.setMap(map); + var path = poly.getPath(); + var latlngbounds = new google.maps.LatLngBounds( ); + var positions = xml.getElementsByTagName('position'); + var posLen = positions.length; + for (var i=0; i'+lang_user+': '+p.username.toUpperCase()+'
'+lang_track+': '+p.trackname.toUpperCase()+ + ''+ + '
'+ + '
'+lang_time+': '+p.dateoccured+'
'+ + ((p.speed != null)?''+lang_speed+': '+(p.speed.toKmH()*factor_kmh)+' '+unit_kmh+'
':'')+ + ((p.altitude != null)?''+lang_altitude+': '+(p.altitude*factor_m).toFixed()+' '+unit_m+'
':'')+'
'+ + ((latest==0)? + ('
'+lang_ttime+': '+p.totalSeconds.toHMS()+'
'+ + ''+lang_aspeed+': '+((p.totalSeconds>0)?((p.totalMeters/p.totalSeconds).toKmH()*factor_kmh).toFixed():0)+' '+unit_kmh+'
'+ + ''+lang_tdistance+': '+(p.totalMeters.toKm()*factor_km).toFixed(2)+' '+unit_km+'
'+'
'):'')+ + '
'+lang_point+' '+(i+1)+' '+lang_of+' '+(posLen)+'
'+ + '
'; + popup = new google.maps.InfoWindow(); + popup.listener = google.maps.event.addListener(marker, 'click', (function(marker,content) { + return function() { + popup.setContent(content); + popup.open(map, marker); + if (document.getElementById('bottom').style.display=='block') { + chart.setSelection([{row:i,column:null}]); + } + } + })(marker,content)); + markers.push(marker); + popups.push(popup); +} + +function addChartEvent(chart) { + google.visualization.events.addListener(chart, 'select', function() { + if (popup) {popup.close(); clearTimeout(altTimeout);} + var selection = chart.getSelection()[0]; + if (selection) { + var id = selection.row; + var icon = markers[id].getIcon(); + markers[id].setIcon('http://maps.google.com/mapfiles/marker_orange.png'); + //var contentString = '
'+Math.round(altitudes[id]*factor_m)+' '+unit_m+'
'; + //popup = new google.maps.InfoWindow({ + // content: contentString + //}); + //popup.open(map,markers[id]); + //altTimeout = setTimeout(function() { if (popup) {popup.close();} },2000); + altTimeout = setTimeout(function() { markers[id].setIcon(icon); },2000); + } + }); +} diff --git a/api_openlayers.js b/api_openlayers.js new file mode 100755 index 0000000..434c8e6 --- /dev/null +++ b/api_openlayers.js @@ -0,0 +1,169 @@ +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +// openlayers +var map; +var layerTrack; +var layerMarkers; +var lineStyle = {strokeColor: '#FF0000', strokeOpacity: 1, strokeWidth: 2}; +var wgs84; +var mercator; +var loadedAPI = 'openlayers'; +function init() { + wgs84 = new OpenLayers.Projection('EPSG:4326'); // from WGS 1984 + mercator = new OpenLayers.Projection('EPSG:900913'); // to Mercator + var options = { controls: [ + new OpenLayers.Control.ArgParser(), // default + new OpenLayers.Control.Attribution(), // default + new OpenLayers.Control.LayerSwitcher({'ascending':false}), + new OpenLayers.Control.Navigation(), // default + new OpenLayers.Control.PanZoomBar(),// do we need it? + new OpenLayers.Control.ScaleLine() + ] + }; + map = new OpenLayers.Map('map-canvas', options); + map.addLayer(new OpenLayers.Layer.OSM()); + var position = new OpenLayers.LonLat(21.01,52.23).transform(wgs84, mercator); + var zoom = 8; + map.setCenter(position, zoom); +} +function displayTrack(xml,update) { + altitudes.length = 0; + var totalMeters = 0; + var totalSeconds = 0; + // init layer + layerTrack = new OpenLayers.Layer.Vector( 'Track' ); + layerMarkers = new OpenLayers.Layer.Markers( 'Markers' ); + var points = new Array(); + var latlngbounds = new OpenLayers.Bounds(); + var positions = xml.getElementsByTagName('position'); + var posLen = positions.length; + for (var i=0; i'+lang_user+': '+p.username.toUpperCase()+'
'+lang_track+': '+p.trackname.toUpperCase()+ + ''+ + '
'+ + '
'+lang_time+': '+p.dateoccured+'
'+ + ((p.speed != null)?''+lang_speed+': '+(p.speed.toKmH()*factor_kmh)+' '+unit_kmh+'
':'')+ + ((p.altitude != null)?''+lang_altitude+': '+(p.altitude*factor_m).toFixed()+' '+unit_m+'
':'')+'
'+ + ((latest==0)? + ('
'+lang_ttime+': '+p.totalSeconds.toHMS()+'
'+ + ''+lang_aspeed+': '+((p.totalSeconds>0)?((p.totalMeters/p.totalSeconds).toKmH()*factor_kmh).toFixed():0)+' '+unit_kmh+'
'+ + ''+lang_tdistance+': '+(p.totalMeters.toKm()*factor_km).toFixed(2)+' '+unit_km+'
'+'
'):'')+ + '
'+lang_point+' '+(i+1)+' '+lang_of+' '+(posLen)+'
'+ + '
'; + marker.events.register("mousedown", marker, (function() { + return function() { + // remove popups + if (map.popups.length>0) { + for (var i = map.popups.length-1; i>=0; i-- ) { + map.removePopup(map.popups[i]) + }; + } + // show popup + var popup = new OpenLayers.Popup.FramedCloud("id "+(i+1),lonLat,null,content,icon,true); + map.addPopup(popup); + if (document.getElementById('bottom').style.display=='block') { + chart.setSelection([{row:i,column:null}]); + } + } + })()); + +} + +function addChartEvent(chart) { + google.visualization.events.addListener(chart, 'select', function() { + var selection = chart.getSelection()[0]; + if (selection) { + var id = selection.row; + var marker = layerMarkers.markers[id]; + var url = marker.icon.url; + marker.setUrl('http://www.openstreetmap.org/openlayers/img/marker-gold.png'); + altTimeout = setTimeout(function() { marker.setUrl(url); },2000); + } + }); +} diff --git a/config.php b/config.php index 344efd6..513ab1f 100755 --- a/config.php +++ b/config.php @@ -17,15 +17,18 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -$version = "1.0"; +$version = "2.0"; + // map drawing framework -// (gmaps = google maps, osm = openstreetmap (not supported yet)) +// (gmaps = google maps, openlayers = openlayers/osm) $mapapi = "gmaps"; +//$mapapi = "openlayers"; + // you may add your google maps api key // this is not obligatory by now //$gkey = -// db +// MySQL config $dbhost = ""; // mysql host, eg. localhost $dbuser = ""; // database user $dbpass = ""; // database pass @@ -35,17 +38,23 @@ $salt = ""; // fill in random string here, it will increase security of password // other // require login/password authentication // (0 = no, 1 = yes) -$require_authentication = 0; +$require_authentication = 1; + // allow automatic registration of new users // (0 = no, 1 = yes) $allow_registration = 0; + // Default interval in seconds for live auto reload $interval = 10; + // Default language // (en, pl) $lang = "en"; +//$lang = "pl"; + // units // (metric, imperial) $units = "metric"; +//$units = "imperial"; ?> diff --git a/index.php b/index.php index c50a06d..a2a4d9b 100755 --- a/index.php +++ b/index.php @@ -67,6 +67,17 @@ $track_form .= ' '; +// map api select form +$api_form = ' +'.$lang_api.'
+
+ +
+'; + print ' @@ -74,7 +85,7 @@ print '.$lang_title.' - + - + '; if ($mapapi == "gmaps") { print -' - +' + '; } else { print -' - +' + '; } print ' @@ -163,7 +140,10 @@ print '
+
+ '.$api_form.'
'.$lang_download.'
diff --git a/lang.php b/lang.php index bd508c9..9a7070a 100755 --- a/lang.php +++ b/lang.php @@ -47,6 +47,7 @@ switch($lang) { $lang_password = "Password"; $lang_language = "Language"; $lang_newinterval = "Enter new interval value (seconds)"; + $lang_api = "Map API"; break; case "pl": @@ -77,6 +78,7 @@ switch($lang) { $lang_password = "Hasło"; $lang_language = "Język"; $lang_newinterval = "Podaj częstotliwość odświeżania (w sekundach)"; + $lang_api = "Map API"; break; } ?> diff --git a/main.css b/main.css index 747b837..7cee9d1 100755 --- a/main.css +++ b/main.css @@ -78,7 +78,7 @@ input[type = "checkbox"] { background-color: #666; color: lightgray; } -#user, #trip, #summary, #export, #other { +#user, #trip, #summary, #export, #other, #api { padding-bottom: 10px; } #login { @@ -107,8 +107,12 @@ input[type = "checkbox"] { color: yellow; } #popup { - width:350px; - height:150px; + width:370px; + height:130px; +} +#popup * { + font-family: Roboto, Verdana, sans-serif; + font-size: 12px; } #pheader { font-weight: bolder; @@ -129,6 +133,8 @@ input[type = "checkbox"] { } #bottom { display: none; + position: absolute; + z-index: 10000; } #chart { position: fixed; @@ -139,10 +145,10 @@ input[type = "checkbox"] { opacity: 0.8; } #close { - position: absolute; + position: fixed; bottom: 175px; right: 175px; - z-index: 100; + z-index: 10001; font-family: Verdana, sans-serif; font-size: 0.8em; } diff --git a/main.js b/main.js index ab4e094..5fa8d19 100755 --- a/main.js +++ b/main.js @@ -16,126 +16,8 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -// google maps -function displayTrack(xml,update) { - altitudes.length = 0; - var totalMeters = 0; - var totalSeconds = 0; - // init polyline - var poly = new google.maps.Polyline(polyOptions); - poly.setMap(map); - var path = poly.getPath(); - var latlngbounds = new google.maps.LatLngBounds( ); - var positions = xml.getElementsByTagName('position'); - var posLen = positions.length; - for (var i=0; i'+lang_user+': '+p.username.toUpperCase()+'
'+lang_track+': '+p.trackname.toUpperCase()+ - '
'+ - '
'+ - '
'+lang_time+': '+p.dateoccured+'
'+ - ((p.speed != null)?''+lang_speed+': '+(p.speed.toKmH()*factor_kmh)+' '+unit_kmh+'
':'')+ - ((p.altitude != null)?''+lang_altitude+': '+(p.altitude*factor_m).toFixed()+' '+unit_m+'
':'')+'
'+ - ((latest==0)? - ('
'+lang_ttime+': '+p.totalSeconds.toHMS()+'
'+ - ''+lang_aspeed+': '+((p.totalSeconds>0)?((p.totalMeters/p.totalSeconds).toKmH()*factor_kmh).toFixed():0)+' '+unit_kmh+'
'+ - ''+lang_tdistance+': '+(p.totalMeters.toKm()*factor_km).toFixed(2)+' '+unit_km+'
'+'
'):'')+ - '
'+lang_point+' '+(i+1)+' '+lang_of+' '+(posLen)+'
'+ - '
'; - popup = new google.maps.InfoWindow(); - popup.listener = google.maps.event.addListener(marker, 'click', (function(marker,content) { - return function() { - popup.setContent(content); - popup.open(map, marker); - if (document.getElementById('bottom').style.display=='block') { - chart.setSelection([{row:i,column:null}]); - } - } - })(marker,content)); - markers.push(marker); - popups.push(popup); -} - - - -// openstreetmaps -// TODO - - -// general stuff + + // general stuff if (units=='imperial') { factor_kmh = 0.62; //to mph unit_kmh = 'mph'; @@ -177,19 +59,7 @@ function displayChart() { chart = new google.visualization.LineChart(document.getElementById('chart')); chart.draw(data, options); - google.visualization.events.addListener(chart, 'select', function() { - if (popup) {popup.close(); clearTimeout(altTimeout);} - var selection = chart.getSelection()[0]; - if (selection) { - var id = selection.row; - var contentString = '
'+Math.round(altitudes[id]*factor_m)+' '+unit_m+'
'; - popup = new google.maps.InfoWindow({ - content: contentString - }); - popup.open(map,markers[id]); - altTimeout = setTimeout(function() { if (popup) {popup.close();} },2000); - } - }); + addChartEvent(chart); } function toggleChart(i) { @@ -408,5 +278,67 @@ function setTime() { clearInterval(auto); autoReload(); } - } + } +} + +// dynamic change of map api +function loadMapAPI(api) { + document.getElementById("map-canvas").innerHTML = ''; + var url = new Array(); + if (api=='gmaps') { + url.push('api_gmaps.js'); + url.push('https://maps.googleapis.com/maps/api/js?sensor=false&callback=init'); + } + else { + url.push('api_openlayers.js'); + url.push('http://openlayers.org/api/OpenLayers.js'); + } + addScript(url[0]); + waitAndLoad(api,url); +} +var loadTime = 0; +function waitAndLoad(api,url) { + // wait till first script loaded + if (loadTime>5000) { loadTime = 0; alert('Sorry, can\'t load '+api+' API'); return; } + if (loadedAPI!==api) { + setTimeout(function() { loadTime += 50; waitAndLoad(api,url); }, 50); + return; + } + if(!isScriptLoaded(url[1])){ + addScript(url[1]); + } + loadTime = 0; + waitAndInit(api); +} + +function waitAndInit(api) { + // wait till main api loads + if (loadTime>10000) { loadTime = 0; alert('Sorry, can\'t load '+api+' API'); return; } + try { + init(); + } + catch(e) { + setTimeout(function() { loadTime += 50; waitAndInit(api); }, 50); + return; + } + loadTime = 0; + loadTrack(userid,trackid,1); +} + +function addScript(url) { + var tag = document.createElement('script'); + tag.setAttribute('type','text/javascript'); + tag.setAttribute('src', url); + if (typeof tag!='undefined') { + document.getElementsByTagName('head')[0].appendChild(tag); + } +} + +function isScriptLoaded(url) { + scripts = document.getElementsByTagName('script'); + for (var i = scripts.length; i--;) { + // check if url matches src + if (scripts[i].src != '' && url.indexOf(scripts[i].src) !== -1) return true; + } + return false; } -- cgit v1.2.3