Archive for the ‘Maps’ Category

Google maps, mySQL locations, PHP service

Wednesday, May 4th, 2016

HTML:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
    <link rel="stylesheet" href="dealers.css">
</head>
    <body>
        <div class="row mapSection">
            <div class="col-xs-12">

                <div id="map"></div>
                <div id="panel">
                    <div id="entryRow">
                        <div><select id="locationSelect" style="width:100%;visibility:hidden"></select></div>
                        <input type="text" id="addressInput" />
                        <select id="radiusSelect">
                            <option value="5" selected>5 miles</option>
                            <option value="25" selected>25 miles</option>
                            <option value="100">100 miles</option>
                            <option value="200">200 miles</option>
                            <option value="500">500 miles</option>
                        </select>
                        <input type="text" id="find" value="Search"/>
                        <input type="button" id="refresh" value="redo Search"/>
                    </div>
                    <ul class="resultDealers">
                    </ul>
                </div>

            </div>
        </div>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
        <script src="https://maps.googleapis.com/maps/api/js?key=***YOUR*KEY*HERE***" type="text/javascript"></script>
        <script type="text/javascript" src="Maps.js"></script>
    </body>
</html>

CSS:

body {
  font-family: sans-serif;
  margin: 0px;
  padding: 0px;
}
#map,
#panel {
  height: 500px;
  float: left;
}
#map {
  width: 60%;
}
#entryRow {
  margin: 0 0 0 15px;
}
#panel {
  width: 40%;
}
.resultDealers {
  padding: 0;
  margin: 15px;
  overflow: scroll;
  height: 420px;
}
.resultDealers li {
  list-style-type: none;
  border-left: 1px solid;
  border-top: 1px solid;
  border-right: 1px solid;
  padding: 10px;
}
.resultDealers li:last-child {
  border-bottom: 1px solid;
}
.highlightDealer {
  background: #E8E8E8;
}
.markerBox {
  cursor: pointer;
}
.markerBox:hover {
  background: #E3F4F9;
}
#panel .feature-filter label {
  width: 130px;
}
p.attribution,
p.attribution a {
  color: #666;
}
#find {
  background: #DEDCDC;
  border: 1px solid gray;
  width: 65px;
  padding: 2px;
  text-align: center;
  font-weight: bold;
  cursor: pointer;
  margin-left: 15px;
}
#find:hover {
  background: #F9F4F4;
}
#radiusSelect {
  margin-left: 15px;
}
#addressInput {
  float: left;
  margin-left: 5px;
  padding-left: 10px;
  width: 65px;
}
#locationSelect {
  margin: 10px 5px;
  width: 95% !important;
}

JavaScript:

/* ---------  Start Maps.js  --------- */

Maps Module
//Usage: Maps.init();

Maps = (function ( window, google ) {

	var map,
		markers = [],
		infoWindow,
		locationSelect;

	var load = function load () {
			map = new google.maps.Map(document.getElementById("map"), {
				center: new google.maps.LatLng(40, -100),
				zoom: 4,
				mapTypeId: 'roadmap',
				// scrollWheel: false,
				// zoomControl: false,
				streetViewControl: false,
				rotateControl: false,
				fullscreenControl: false,
				navigationControl: false,
				scaleControl: false,
				// draggable: false,
				mapTypeControl: false,
				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');
			}
		};

		refreshMap();

		google.maps.event.addListener(map, 'zoom_changed', function() {
			//$('#radiusSelect option:selected').next().attr('selected', 'selected');
			//console.log(map.getCenter());
			//searchLocationsNear (map.getCenter());
		});

	}

	var bindInfoWindow = function bindInfoWindow ( marker, map, infoWindow, html ) {
      google.maps.event.addListener(marker, 'click', function() {
        infoWindow.setContent(html);
        infoWindow.open(map, marker);
      });
    }

    var refreshMap = function refreshMap () {
    	if(navigator.geolocation) {
			navigator.geolocation.getCurrentPosition(function(position) {

				var latLng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);

				var geocoder = new google.maps.Geocoder();

				geocoder.geocode({ 'latLng': latLng}, function (results, status) {
					if (status == google.maps.GeocoderStatus.OK) {

						for ( var j = 0; j < results[0].address_components.length; j++ ) {
							for ( var k = 0; k < results[0].address_components[j].types.length; k++ ) {
								if ( results[0].address_components[j].types[k] == "postal_code" ) {
									zipcode = results[0].address_components[j].short_name;
								}
							}
						}

						document.getElementById("addressInput").value = zipcode;
						searchLocations();
					} else {
						console.log("Geocoding failed: " + status);
					}
				});
			});
		}
	}

	var downloadUrl = 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);
	}

	var searchLocations = 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');
			}
		});
	}

	var clearLocations = 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);
	}

	var searchLocationsNear = function searchLocationsNear ( center ) {
		clearLocations();

		var radius = document.getElementById('radiusSelect').value;
		var searchUrl = '/dealers.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 id = markerNodes[i].getAttribute("id");
				var name = markerNodes[i].getAttribute("name");
				var address = markerNodes[i].getAttribute("address");
				var city = markerNodes[i].getAttribute("city");
				var state = markerNodes[i].getAttribute("state");
				var zip = markerNodes[i].getAttribute("zip");
				var url = markerNodes[i].getAttribute("url");
				var email = markerNodes[i].getAttribute("email");
				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(id, latlng, name, address, city, state, zip, url, email);
				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');
			};
		});
	}

	var createMarker = function createMarker ( id, latlng, name, address, city, state, zip, url, email ) {
		var html = "<div class='marker-" + id + "'><b>" + name + "</b> <br/>" + address +  "<br/>" + city + " " + state + ", " + zip + "<br />" + url + "<br /><a href='mailto:" + email + "'>" + email + "</a></div>";
		var marker = new google.maps.Marker({
			map: map,
			position: latlng
		});
		google.maps.event.addListener(marker, 'click', function() {
			//infoWindow.setContent(html);
			//infoWindow.open(map, marker);
			$("li[class*='marker-']").removeClass('highlightDealer');
			$("li.marker-" + id).addClass('highlightDealer');
			window.location.href = "#marker-"+ id;
			window.scrollTo(0, 0);

			map.setZoom(16);
			map.setCenter(marker.getPosition());
		});
		markers.push(marker);

		$("#panel ul").append("<li class='markerBox marker-" + id + "'><a name='marker-" + id + "'></a><b>" + name + "</b><br/>" + address +  "<br/>" + city + " " + state + ", " + zip + "<br />" + url + "<br /><a href='mailto:" + email + "'>" + email + "</a></li>");
		$('.marker-' + id).on('click', function() {
			$("li[class*='marker-']").removeClass('highlightDealer');
			$("li.marker-" + id).addClass('highlightDealer');
			map.setZoom(16);
			map.setCenter(marker.getPosition());
		});
	}

	var createOption = function createOption ( name, distance, num ) {
		var option = document.createElement("option");
		option.value = num;
		option.innerHTML = name + "(" + distance.toFixed(1) + ")";
		locationSelect.appendChild(option);
	}

	var parseXml = 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() {}

	$('#find').on('click', function() {
		$('#panel ul').empty();
		searchLocations();
	});
	$('#addressInput').on('click', function () {
		$(this).val('');
	});
	$('#radiusSelect').on('change', function () {
		$('#panel ul').empty();
		searchLocations();
	});
	$('#refresh').on('click', function () {
		var bounds = map.getBounds();
		var ne = bounds.getNorthEast(); // LatLng of the north-east corner
		var sw = bounds.getSouthWest(); // LatLng of the south-west corder

		var nw = new google.maps.LatLng(ne.lat(), sw.lng());
		var se = new google.maps.LatLng(sw.lat(), ne.lng());
		console.log('nw: ' + nw);
		console.log('se: ' + se);
		//searchLocationsNear();
		//searchLocations();
	});

	return {
		load: load
	}

})( window, google );

$(function(){
    loadModules.start();
})

var loadModules = loadModules || {};
loadModules.start = function(){
    // Maps module init
    Maps.load();
};
/* ---------  End Maps.js --------- */

PHP:

<?php
    header("Access-Control-Allow-Origin: *");
    $servername = "***Your*DB*URL***";
    $username = "***Your*DB*USERNAME***";
    $password = "***Your*DB*PASS***";
    $dbname = "***Your*DB*NAME***";

    // 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);

    // Opens a connection to a mySQL server
    $connection=mysql_connect ($servername, $username, $password);
    if (!$connection) {
      die("Not connected : " . mysql_error());
    }

    // Set the active mySQL database
    $db_selected = mysql_select_db($dbname, $connection);
    if (!$db_selected) {
      die ("Can\'t use db : " . mysql_error());
    }

    // Search the rows in the markers table
    $query = sprintf("SELECT id, name, address, city, state, zip, url, email, lat, lng, ( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance FROM dealers HAVING distance < '%s' ORDER BY distance LIMIT 0 , 20",
      mysql_real_escape_string($center_lat),
      mysql_real_escape_string($center_lng),
      mysql_real_escape_string($center_lat),
      mysql_real_escape_string($radius));
    $result = mysql_query($query);

    $result = mysql_query($query);
    if (!$result) {
      die("Invalid query: " . mysql_error());
    }

    header("Content-type: text/xml");

    // Iterate through the rows, adding XML nodes for each
    while ($row = @mysql_fetch_assoc($result)){
        $node = $dom->createElement("marker");
        $newnode = $parnode->appendChild($node);
        $newnode->setAttribute("id", $row['id']);
        $newnode->setAttribute("name", $row['name']);
        $newnode->setAttribute("address", $row['address']);
        $newnode->setAttribute("city", $row['city']);
        $newnode->setAttribute("state", $row['state']);
        $newnode->setAttribute("zip", $row['zip']);
        $newnode->setAttribute("url", $row['url']);
        $newnode->setAttribute("email", $row['email']);
        $newnode->setAttribute("lat", $row['lat']);
        $newnode->setAttribute("lng", $row['lng']);
        $newnode->setAttribute("distance", $row['distance']);
    }

    echo $dom->saveXML();

?>

Google Maps API v3 load array of locations, detect ip and zoom, generate list by distance to locations

Friday, October 23rd, 2015

In the template or HTML:

<div id="container">
<div class="row mapSubNav">
<div class="col-xs-6">
<div class="mapNavLeft">Find a Store</div>
</div>
<div class="col-xs-6 mapNavRight">
<a id="mapView">Map View</a> | <a id="listView">List View</a>
</div>
</div>
<div class="row">
<div class="col-xs-12 noPad">
<div id="floating-panel">
<input id="findAddress" name="findAddress" type="textbox" value="Find a StoreĀ - City, State, Zip">
<select id="findRadius">
<option value="13" selected="selected">radius</option>
<option value="12">5 miles</option> <!-- 4 miles -->
<option value="11">10 miles</option> <!-- 8 miles -->
<option value="10">15 miles</option> <!-- 16 miles -->
</select>
<input id="findSubmit" type="submit" value="Find a shop" class="btnLeft">
</div>
<div class="sideBar">
<div class="closeBtn">x</div>
<h3>Our Stores:</h3>
</div>
<div id="map"></div>
<div id="outputList"></div>
</div>
</div>
</div><strong>
</strong>

<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&amp;amp;key=**YOUR_KEY_HERE**"</script>;
<script type="text/javascript" src="${sharedResourcePath}/js/locations.js"</script>;
<script type="text/javascript" src="${sharedResourcePath}/js/maps-module.js"</script>;

Locations array example:

var DEALERS = (function() {
var image = '../images/marker.png';

var locations = [
['location name 1',32.215143,-90.151818,map,image,'detailed description'],
['location name 2',47.336401,-116.888100,map,image,'detailed description'],
['location name 3',33.755219,-90.715672,map,image,'detailed description'],
['location name 4',33.646063,-87.058802,map,image,'detailed description'],
['location name 5',48.548468,-117.909399,map,image,'detailed description']
];
})();

 

MAPS MODULE JS:

MAPMOD = (function( window, google, DEALERS ) {

 var gmarkers = [],
 infos = [],
 map = {},
 whichMap = "";

 var init = (function init () {
 
 if( !document.getElementById("map") ) { return; }

 whichMap = $('#map').attr("data-map-type");

 switch( whichMap ) {
 case "dealer":
 var myOptions = {
 //center: new google.maps.LatLng(37.4419, -122.1419),
 zoom: 4,
 mapTypeId: google.maps.MapTypeId.ROADMAP,
 scrollwheel: false,
 disableDefaultUI: true,
 draggable: false,
 scaleControl: false,
 zoomControl: false
 };
 initDealerDetail(myOptions);
 break;

 case "all": 
 var myOptions = {
 zoom: 4,
 mapTypeId: google.maps.MapTypeId.ROADMAP,
 scrollwheel: false
 };
 allDealers(myOptions);
 break;
 }
 });

 var allDealers = (function allDealers (myOptions) {
 
 map = new google.maps.Map( document.getElementById("map"), myOptions );

 setMarkers( map, DEALERS.locations );

 var geocoder = new google.maps.Geocoder();

 var US = {
 NorthEast: {
 lat: 49.38,
 lng: -66.94
 },
 SouthWest: {
 lat: 25.82,
 lng: -124.39
 }
 }
 
 var USbounds = new google.maps.LatLngBounds(new google.maps.LatLng(US.SouthWest.lat, US.SouthWest.lng),
 new google.maps.LatLng(US.NorthEast.lat, US.NorthEast.lng));

 map.fitBounds(USbounds);
 //var USrect = new google.maps.Rectangle({map:map, bounds: USbounds});

 $('#findSubmit').on('click', function() {
 geocodeAddress(geocoder, map);
 });

 $("#findAddress").on("click", function() {
 $(this).val("");
 })

 $("#mapView").on("click", function() {
 $("#outputList").hide();
 $("#map").show();
 })
 
 $("#listView").on("click", function() {
 $("#map").hide();
 $("#outputList").show();
 })
 
 document.onkeydown=function() {
 if(window.event.keyCode=='13') {
 $('#findSubmit').click();
 }
 }

 geolocate(geocoder, map);
 });

 var geolocate = (function geolocate (geocoder, map) {

 // Try HTML5 geolocation.
 if (navigator.geolocation) {

 //var address = document.getElementById('findAddress').value ? document.getElementById('findAddress').value : {};

 navigator.geolocation.getCurrentPosition(function(position) {
 var pos = {
 lat: position.coords.latitude,
 lng: position.coords.longitude
 };

 //infoWindow.setPosition(pos);
 //infoWindow.setContent('Location found.');
 document.getElementById('findAddress').value = pos.lat + " " + pos.lng;
 $('#findRadius').val(8);
 geocodeAddress(geocoder, map);

 //map.setCenter(pos);
 //map.setZoom(9);
 }, function() {
 handleLocationError(true, infoWindow, map.getCenter());
 });
 } else {
 // Browser doesn't support Geolocation
 handleLocationError(false, infoWindow, map.getCenter());
 }
 });

 var initDealerDetail = (function initDealerDetail (myOptions) {

 map = new google.maps.Map( document.getElementById("map"), myOptions );

 setMarkers( map, DEALERS.locations );

 var lat = parseFloat( $('#map').attr("data-map-lat") );
 var lng = parseFloat( $('#map').attr("data-map-lng") );

 var pos = {
 lat: lat,
 lng: lng
 };

 map.setCenter(pos);
 map.setZoom(15);
 map.panBy(-250, 0);
 });
 
 function handleLocationError(browserHasGeolocation, map, pos) {
 map.setPosition(pos);
 map.setContent(browserHasGeolocation ? 'Error: The Geolocation service failed.' : 'Error: Your browser doesn\'t support geolocation.');
 }
 
 function geocodeAddress(geocoder, resultsMap) {
 
 var address = document.getElementById('findAddress').value;
 
 var radius = parseInt($( "#findRadius option:selected" ).val());
 if(isNaN(radius)){ radius = 8; }

 geocoder.geocode({'address': address}, function(results, status) {
 
 if (status === google.maps.GeocoderStatus.OK) {
 resultsMap.setCenter(results[0].geometry.location);

 var marker = new google.maps.Marker({
 map: resultsMap,
 position: results[0].geometry.location,
 });

 closest = findClosestN(results[0].geometry.location,10);

 // get driving distance
 closest = closest.splice(0,10);
 $('#findAddress').val(results[0].formatted_address);

 calculateDistances(results[0].geometry.location, closest,10);
 
 resultsMap.setZoom(radius);
 
 } else {
 $('#findAddress').val("No results. Please try again");
 }
 });
 }
 
 function findClosestN(pt,numberOfResults) {
 var closest = [];

 for (var i=0; i<gmarkers.length;i++) {
 gmarkers[i].distance = google.maps.geometry.spherical.computeDistanceBetween(pt,gmarkers[i].getPosition());
 
 //$('#findAddress').val("process " + i + ":" + gmarkers[i].getPosition().toUrlValue(6) + ":" + gmarkers[i].distance.toFixed(2) + "<br>");
 //gmarkers[i].setMap(null);
 closest.push(gmarkers[i]);
 }
 closest.sort(sortByDist);
 return closest;
 }

 function sortByDist(a,b) {
 return (a.distance- b.distance)
 }

 function calculateDistances(pt,closest,numberOfResults) {
 $('#outputList').html('');
 var service = new google.maps.DistanceMatrixService();
 var request = {
 origins: [pt],
 destinations: [],
 travelMode: google.maps.TravelMode.DRIVING,
 unitSystem: google.maps.UnitSystem.IMPERIAL,
 avoidHighways: false,
 avoidTolls: false
 };
 
 for (var i=0; i<closest.length; i++) request.destinations.push(closest[i].getPosition());
 service.getDistanceMatrix(request, function (response, status) {
 if (status != google.maps.DistanceMatrixStatus.OK) {
 alert('Error was: ' + status);
 } else {
 var origins = response.originAddresses;
 var destinations = response.destinationAddresses;
 
 var results = response.rows[0].elements;
 for (var i = 0; i < numberOfResults; i++) {

 $('#outputList').append('\
 <label for="dealer' + i + '" class="col-xs-8 dealerItem">\
 <input type="radio" value="' + closest[i].title + '" name="dealers" id="dealer' + i + '">\
 <span>' + closest[i].title + '</span>\
 <span class="dealerAddress">' + destinations[i] + '</span>\
 </label>\
 <div class="col-xs-4 distance">' + results[i].distance.text + '</div>');
 }
 }
 });
 }
 
 function setMarkers(map,locations) {
 
 var marker, i
 
 for (i = 0; i < locations.length; i++) { 
 
 var loan = locations[i][0],
 lat = locations[i][1],
 lng = locations[i][2],
 add = locations[i][5];
 
 latlngset = new google.maps.LatLng(lat, lng);

 var marker = new google.maps.Marker({ 
 map: map,
 title: loan ,
 position: latlngset,
 icon: './images/tp.png'
 });

 gmarkers.push(marker);
 
 //console.log(marker.getPosition());
 //map.setCenter(marker.getPosition());
 
 var content = add;
 var infowindow = new google.maps.InfoWindow();
 
 google.maps.event.addListener(marker,'click', (function(marker,content,infowindow){ 
 
 return function() {
 
 /* close the previous info-window */
 closeInfos();
 
 infowindow.setContent(content);
 infowindow.open(map,marker);
 
 /* keep the handle, in order to close it on next click event */
 infos[0]=infowindow;
 
 };

 })(marker,content,infowindow)); 
 
 }
 }
 
 function closeInfos() {
 
 if(infos.length > 0) {
 
 /* detach the info-window from the marker ... undocumented in the API docs */
 infos[0].set("marker", null);
 
 /* and close it */
 infos[0].close();
 
 /* blank the array */
 infos.length = 0;
 }
 }
 
 return {
 init: init
 }

})(window, google, window.DEALERS);
MAPMOD.initMap();