SSbits - Home page
Site by Carbon Crayon
Submit a Post >

Tutorials - Big bits of code to help you do more

Leaflet with SS3

screencapture

Leaflet is a good open-source alternative to Google Maps. I followed the instructions given in the Leaflet quick start guide (http://leafletjs.com/examples/quick-start.html), with a few adaptations to Silverstripe CMS. No custom icon, no additional layer, no customized css, no fancy feature : only the basic options to plot several locations on an interactive map.

The idea is to create a dedicated page for the interactive map (MapPage.php), a dataobject for the locations (Point.php), and a template (MapPage.ss) to display the map and loop trough the locations to call the relevant javascript files.

MapPage.php

<?php

class MapPage extends Page {

	static $singular_name = "Page avec carte interactive";

	public static $db = array(
		'MapCenter'=>'Text',
		'MapZoom'=>'Int'
	);
	
	static $defaults = array(
		'MapCenter'=>'47.390041,0.688925',
		'MapZoom'=>'10'
	);
	
	public static $has_many = array(
		'Points'=>'Point'
	);

	function getCMSFields() {
		
		// Internationalization
		$MapTab = _t("MAPPAGE.MapTab","InteractiveMap");
		$CenterMap = _t("MAPPAGE.CenterMap","Initial geographical center of the map (lat.,long.)");
		$ZoomFactor =  _t("MAPPAGE.ZoomFactor","Initial map zoom (5 to 18)");
		$Locations =  _t("MAPPAGE.Locations","Locations");
		
		$fields = parent::getCMSFields();
		$fields->addFieldToTab('Root.'.$MapTab, new TextField('MapCenter',$CenterMap));
		$fields->addFieldToTab('Root.'.$MapTab, new TextField('MapZoom',$ZoomFactor));
		$fields->addFieldToTab('Root.'.$MapTab, new GridField('Points', $Locations, $this->Points(), GridFieldConfig_RecordEditor::create()));
		return $fields;
	}

}

class MapPage_Controller extends Page_Controller {

	public function init() {
		parent::init();
		Requirements::javascriptTemplate("leaflet/javascript/leaflet.config.js",
			array(
			'MapCenter'=>Convert::raw2js($this->MapCenter),
			'MapZoom'=>Convert::raw2js($this->MapZoom)
			)
		);
	}

}

The fields created in the model enable you to configure the map (initial zoom, geographical center of the map) and to add locations. The init function of the controller passes the db values to a javascript file to avoid inline scripts in the template (see "templated javascript" ). The code is far cleaner like this !

Point.php

<?php

class Point extends DataObject {

	static $db = array(
		'Title'=>'Text',
		'GPS'=>'Text',
		'Content'=>'Text'
	);

	public static $has_one = array(
		'MapPage'=>'MapPage'
	);
	
	function spotLocalisation() {
		Requirements::javascriptTemplate("leaflet/javascript/leaflet.spots.js",
			array(
			'Title'=>Convert::raw2js($this->Title),
			'GPS'=>Convert::raw2js($this->GPS),
			'Content'=>Convert::raw2js($this->Content)
			)
		);
	}
	
	static $summary_fields = array (
		'Title',
		'GPS',
		'Content'
	);
	
	function getCMSFields() {
		$fields = parent::getCMSFields();
		
		// Internationalization
		$PointTitle = _t("GEOPOINT.PointTitle","Name");
		$Coordinates = _t("GEOPOINT.Coordinates","Position (lat.,long.)");
		$PointDescription =  _t("GEOPOINT.PointDescription","Description");
		
		$fields->removeByName("MapPageID");
		$fields->addFieldToTab('Root.Main', new TextField('Title',$PointTitle));
		$fields->addFieldToTab('Root.Main', new TextField('Content',$PointDescription));
		$fields->addFieldToTab('Root.Main', new TextField('GPS',$Coordinates));

		return $fields;
	}
	
}

The dataobject for the locations to plot. Apart from the GPS coordinates, you can add a name and a description to each location. The spotLocalisation function will include templated javascript when the locations are looped through.

Escaping $Title and $Content for javascript (the Convert::raw2js function) may be very useful if there are special characters in your text (such as apostrophes).

leaflet.config.js

var map = L.map('LeafletMap').setView([$MapCenter], $MapZoom);

L.tileLayer('http://otile1.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg', {
    attribution: 'Tiles Courtesy of <a href="http://www.mapquest.com/">MapQuest</a> | © <a href="http://www.openstreetmap.org/copyright/">OpenStreetMap</a> contributors',
    minZoom: 5,
    maxZoom: 18
}).addTo(map);

This js file sets the ID, the initial zoom and the geographical center of the interactive map. And most important, it calls the map tiles to be dispayed. My script integrates MapQuest tiles (based on OpenStreetMap), but you could choose any other tile provider (such as Cloudmade).

leaflet.spots.js

L.marker([$GPS]).addTo(map).bindPopup('<p><strong>$Title</strong><br />$Content</p>');This file uses the parameters passed from the given dataobject to plot the location on the map and set the popup content.

This file uses the parameters passed from the given dataobject to plot the location on the map and set the popup content.

MapPage.ss

<% require css(http://cdn.leafletjs.com/leaflet-0.4/leaflet.css) %>
<!--[if lte IE 8]>
	<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.4/leaflet.ie.css" />
<![endif]-->

<div id="LeafletMap">
</div>

<% require javascript(http://cdn.leafletjs.com/leaflet-0.4/leaflet.js) %>

<% loop Points %>
	$spotLocalisation
<% end_loop %>

It contains the requirements to css and js files and the div wrapping the map. The loop calls a new js script for every location.

The final touch : Layout.css

#LeafletMap {
height: 300px;
}

The map container has to be given a height value.

  • Mountain Tiger
    20/11/2012 11:49am (2 years ago)

    LOL, you are just writing tutorial. I don't know what URL to write and I can see this page. I copy / paste the code as it is but don't know what URL to type? Is that http://example.com/map? or http://example.com/mappage?

  • Cumquat
    05/12/2012 9:34am (2 years ago)

    Thanks for this, I never new this existed, so much easier to work with than Google Maps. Nice tut.

    Mick

  • jcwacky
    12/03/2013 4:21pm (1 year ago)

    Thanks for this tutorial, just made this map using it: www.ciderview.com/map

Post a comment ...

You cannot post comments until you have logged in. Login Here.

Advertisement

Site of the Month

Find SSbits on

Top Contributers

Rank Avatar Name
1 article image Aram Balakjian
2 article image Daniel Hensby
3 article image Marcus Dalgren
4 article image Hamish Campbell
5 article image njorndare
6 article image Ty Barho
7 article image Martijn van Nieuwenhoven
8 article image Darren-Lee
9 article image Roman Schmid
10 article image Matt Clegg

View full leaderboard


Advertisement