After making my previous post on how to simply store comments in a jSon file (and the comment from Brian) I decided to write an additional HOWTO create dynamic markers and store them in a jSon file.

It also includes an automatic geo data lockup via Google GeoCoder and generates a detail html file for-each marker created, which then will be loaded dynamic when the marker is clicked.

Check out the working example or download the code on GitHub.

GitHub

So lets get started with the code.

First we need to add jQuery and the Google map API:






The HTML code is very basic and contains a Title, Input field for new markers and the placeholder for the map. Make sure to add “loadMap()” to the html body.

 
 
 


So lets have a look at the JavaScript, first we set some global variables like data path zoom level etc:

// data file with markers (could also be a PHP file for dynamic markers)
var newDate = new Date;
var markerFile = 'markers.json?time=' + newDate.getTime();

// set default map properties
var defaultLatlng = new google.maps.LatLng(49.00,10.00);

// zoom level of the map
var defaultZoom = 2;

// variable for map
var map;

// variable for marker info window
var infowindow

// List with all marker to check if exist
var markerList = {};

// set error handler for jQuery AJAX requests
$.ajaxSetup({"error":function(XMLHttpRequest,textStatus, errorThrown) 
	alert(textStatus);
	alert(errorThrown);
	alert(XMLHttpRequest.responseText);
}});

// option for google map object
var myOptions = {
	zoom: defaultZoom,
	center: defaultLatlng,
	mapTypeId: google.maps.MapTypeId.HYBRID
}

On page load loadMap is fired which which loads the google map to the myMapDIV, and then fires loadMarkers:

/**
 * Load Map
 */
function loadMap(){

	// create new map make sure a DIV with id myMap exist on page
	map = new google.maps.Map(document.getElementById("myMap"), myOptions);

	// create new info window for marker detail pop-up
	infowindow = new google.maps.InfoWindow();

	// load markers
	loadMarkers();
}

Now we need the markers, loadMarkers loads the existing markers via ajax request directly from the data.json fiel (could of course also be a dynamic PHP files which generates jSon).

/**
 * Load markers via ajax request from server
 */
function loadMarkers(){

	// load marker jSon data
	$.getJSON(markerFile, function(data) {

		// loop all the markers
		$.each(data.markers, function(i,item){

			// add marker to map
			loadMarker(item);
		});
	});
}

Once the markers are loaded they somehow have to go on the map:

/**
 * Load marker to map
 */
function loadMarker(markerData){

	// create new marker location
	var myLatlng = new google.maps.LatLng(markerData['lat'],markerData['long']);

	// create new marker
	var marker = new google.maps.Marker({
	    id: markerData['id'],
	    map: map,
	    title: markerData['name'] ,
	    position: myLatlng
	});

	// add marker to list used later to get content and additional marker information
	markerList[marker.id] = marker;

	// add event listener when marker is clicked
	// currently the marker data contain a dataurl field this can of course be done different
	google.maps.event.addListener(marker, 'click', function() {

		// show marker when clicked
		showMarker(marker.id);
	});

	// add event when marker window is closed to reset map location
	google.maps.event.addListener(infowindow,'closeclick', function() {
		map.setCenter(defaultLatlng);
		map.setZoom(defaultZoom);
	});
}

Each marker has an onclick event which loads the detail marker html file into a google infowindow.

/**
 * Show marker info window
 */
function showMarker(markerId){

	// get marker information from marker list
	var marker = markerList[markerId];

	// check if marker was found
	if( marker ){

		// get marker detail information from server
		$.get( 'data/' + marker.id + '.html' , function(data) 

			// show marker window
			infowindow.setContent(data);
			infowindow.open(map,marker);
		});
	}else{
		alert('Error marker not found: ' + markerId);
	}
}

Here the logic for lockup new markers and post them via AJAX jSon request to the server.

 /**
 * Adds new marker to list
 */

function newMarker(){

	// get new city name
	var markerAddress = $('#newMarker').val();

	// create new geocoder for dynamic map lookup
	var geocoder = new google.maps.Geocoder();

	geocoder.geocode( { 'address': markerAddress}, function(results, status) {

		// check response status
		if (status == google.maps.GeocoderStatus.OK) {

			// Fire Google Goal
			_gaq.push(['_trackPageview', '/tracking/marker-submit']);

			// set new maker id via timestamp
			var newDate = new Date;
			var markerId = newDate.getTime();

			// get name of creator
			var markerCreator = prompt("Please enter your name","");

			// create new marker data object
			var markerData = {
				'id': markerId,
				'lat': results[0].geometry.location.lat(),
				'long': results[0].geometry.location.lng(),
				'creator': markerCreator,
				'name': markerAddress,
			};

			// save new marker request to server
			$.ajax({
				type: 'POST',
				url: "data.php",
				data: {
					marker: markerData
				},

				dataType: 'json',
				async: false,
				success: function(result){

					// add marker to map
					loadMarker(result);

					// show marker detail
					showMarker(result['id']);
				}
			});
		}else if( status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT){
			alert("Marker not found:" + status);
		}
	});
}

The PHP code to save the marker is pretty much the same as in my previous post, and returns the newly create marker data:

/* get markes from file */
$dataPath = '/var/www/gmap/data/';
$markerDataFile = 'markers.json';
$markerText = file_get_contents($markerDataFile);

/* create array list from markers */
$markerList = json_decode($markerText,true);

/* check if new marker is posted */
if( !empty($_POST['marker'])  ){

	/* get new marker data */
	$markerData =  $_POST['marker'];

	/* add additional marker information */
	$markerData['ip'] = $_SERVER['REMOTE_ADDR'];
	$markerData['created'] = time();

	/*  create detail marker content file */
	$markerContent = $markerData['creator'] . "-> " . $markerData['name'];

	$markerContent .= date("D M j G:i:s T Y");

	/* save marker file to server */
	$markerFile = $dataPath . $markerData['id'] . ".html";
	file_put_contents($markerFile  , $markerContent);

        /* add new marker to existing list */
        $markerList['markers'][] = $markerData;

        /* convert comments to string */
        $markerText = json_encode($markerList);

        /* save comment to file */
        file_put_contents($markerDataFile, $markerText);

        /* return newly created marker */
	echo json_encode($markerData);
}else{
	echo "Invalid request";
}

This should give a good start on how to dynamically add and display markers via Google map.

The code

Check out the working example or download the code on GitHub.

GitHub

3 responses to “Dynamic google map markers via simple jSon file”

  1. Brian Miller says:

    Bravo on your great work on this. Here is more specific detail about what I am trying to do.

    I use a mobile app called Instamapper http://instamapper.com that can run on any mobile device and upload gps data to their server at specified intervals. In my case I am doing this for long bike rides but it would be good for any type of travel where there was wireless data service available. I had aleady been generating google maps of my routes using service from http://GPSVisualizer.com and generating tracks and or markers from the automatically uploaded tracking information from the data feed from instamapper. An example of this can be viewed at http://theregoesbrian.com . What I would like to add to this is the ability to create additional markers on the map that I create from the browser of my phone while moving along my trip bu having a php form that would have text fields that I could enter a label and comment for a marker and then when the script wrote the data to the text file it would also add data from the instamapper feed such as longitude and latitude to finish off the row of data to create the markers from since that location data would be accurate at the most recent time of sync with the server. So essentially doing what you have done only adding this other source of data. Once this is setup one of the form fields can be an image link that I can create from a photo uploaded from my phone to my dropbox account since it’s easy to do it that way. Example map is using a google docs spreadsheet as the data source for the markers since I could do that manually to create the example.

  2. sofasurfer says:

    In this case, i would keep using http://instamapper.com (it’s a great application i use it as well), to show the route and the full path of the trip.

    If you want to add custom markers i would use twitter. There you can add your current location, images and a description of what’s happening (or any other mobile app which allows you to post you current location).

    To then generate the map you combine the two data files:

    1. instamapper data for the route
    2. twitter api data for custom marker

    Great idea, would be interesting to build an example on how to combine instamapper and twitter into one custom map.

    Hope you got my point and will look into it once i have a bit more time.

  3. Brian says:

    Twitter sounds like an interesting approach to integrate photo, location and message if i could setup a feed with the data i wanted. searching for that I haven’t found anything that is within my capabilities. Do you know of any tutorials on that? The data that I need is right there by accessing http://www.instamapper.com/api?action=getPositions&key=4964919593082806954&num=1&format=json

    and your other post: http://blog.sofasurfer.ch/2011/03/04/php-simple-comments-readwrite-json-data-to-text-file/

    looks like it could use that date to include in the text file it creates.

Leave a Reply

Your email address will not be published. Required fields are marked *