JavaScript Code Snippets

This page provides you with shippets of generic code that is ready to just copy and paste for your own use. I will add to this as the course progresses.

Here is how to add the libraries that we use in this course

<!-- Leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script>
 
<!-- Proj4js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>

<!-- Turf.js -->
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@5/turf.min.js"></script>

<!-- Firebase -->
<script src="https://www.gstatic.com/firebasejs/4.6.1/firebase.js"></script>

A Blank Leaflet Map

This is the basic template with which you can start weeks 1 and 2

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>GIS and the Web</title>
		
		<!-- Load CSS for Leaflet -->
		<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css"/>

		<!-- Load JavaScript for Leaflet -->
		<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script>

		<!-- Add CSS for the page -->
		<style>
		
			/* This is where we can set dimensions of the web page */
			html, body {
				padding: 0;
				margin: 0;
				width: 100%;
				height: 100%;
			}
			
			/* This is where we can set the style of our map div using an id selector (#) */
			#map {
				width: 100%;
				height: 100%;
			}
		</style>
	</head>
	<body>
	
		<!-- Make a division to put the map in -->
		<div id='map'></div>
		
		<!-- Add JavaScript -->
		<script>
			
			// this is a variable that holds the coordinates for our map and marker
			var map = L.map('map');

			// this is a variable that holds the values for the coordinates [latitude, longitude] of the centre of the map
			var mapCentre = [53.466502, -2.235387];

			// set the map to use the above coordinates, and to zoom level 16
			map.setView(mapCentre, 16);

			// this is a variable that holds a reference the tiles that will be used for the basemap
			var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'});

			//add the tiles to the map
			tiles.addTo(map);

		</script>
	</body>
</html>

A Blank Leaflet Map Using Events

This is a better basic template with which you can start weeks 3-12

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>GIS and the Web</title>
		
		<!-- Load CSS for Leaflet -->
		<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css"/>

		<!-- Load JavaScript for Leaflet -->
		<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script>

		<!-- Add CSS for the page -->
		<style>
		
			/* This is where we can set dimensions of the web page */
			html, body {
				padding: 0;
				margin: 0;
				width: 100%;
				height: 100%;
			}
			
			/* This is where we can set the style of our map div using an id selector (#) */
			#map {
				width: 100%;
				height: 100%;
			}
		</style>
	</head>
	<body onload="initMap();">
	
		<!-- Make a division to put the map in -->
		<div id='map'></div>
		
		<!-- Add JavaScript -->
		<script>
			
			//setup global map variable
			var map;
				
			/**
			 * Initialise the Map
			 */
			function initMap(){
				
				// this is a variable that holds the reference to the Leaflet map object
				map = L.map('map').setView([55, -4], 6);   //this will give a map of Great Britain
			
				// this adds the basemap tiles to the map
				L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
					attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
				}).addTo(map);	
			}
		</script>
	</body>
</html>

AJAX (XMLHttpRequest Object)

For accessing JSON data asynchoronously via HTTP…

/**
 * Make a request for JSON over HTTP, pass resulting text to callback when ready
 */
function makeRequest(url, callback) {

	//initialise the XMLHttpRequest object
	var httpRequest = new XMLHttpRequest();

	//set an event listener for when the HTTP state changes
	httpRequest.onreadystatechange = function () {
	
		//a successful HTTP request returns a state of DONE and a status of 200
		if (httpRequest.readyState === XMLHttpRequest.DONE && httpRequest.status === 200) {
				callback(JSON.parse(httpRequest.responseText));
		}
	};

	//prepare and send the request
	httpRequest.open('GET', url);
	httpRequest.send();
}  

You then call that function, passing the URL where the JSON data is located, and a callback function to which the data will be passed when the data is ready:

/**
 * This is a normal function that will be used as the callback
 */
function myCallback(jsonData){

	// jsonData contains the parsed data in JSON format
	// do something with it here
}

//get the journey data and add to the map when ready
makeRequest(url, myCallback);

Comments

As a rule of thumb, well-written code should be roughly one-third code, one-third comments, and one third whitespace. Programmers call this the Rule of Thirds.

Doc comment (should be used at the top of each function):

 /**
  * Everything here is a comment.
  */

Multiline comment (should be used for sections of code):

/*
 Everything in here is a comment.
*/

/* Also works like this */

Single line comment (should be used for every individual line):

// This is a comment

Conditional Statements

Conditional statements allow your code to make decisions about whether or not to run, or what to do based upon different conditions.

if Statements

if statements are the most common variant of conditional statement, and take this form:

if (condition1) {
	// statement 1;
	
} else if (condition2) {
	// statement 2
	
} else if (condition3) {
	// statement 3
	
} else {
	// statement 4
}

else if allows unlimited extra conditions to be tested, whereas else simply allows for a default action in case all of the conditions evaluate to false. Similarly condition2 will only be tested if condition1 evaluates to false, as soon as one evaluates to true the rest of the if statement will be ignored.

Here is a slightly more realiistic example:

// set the language for the website
var language = "English";

// greet the visitor with an alert box
if (language == "German") {
	alert("Guten Tag");
	
} else if (language == "English") {
	alert("Hello");
	
} else if (language == French) {
	alert("Bonjour")
	
} else {
	alert("Sorry, I don't speak" + language);
}

This will open an alert saying “Hello”.


Coordinate Transformation using Proj4js

To use proj4js to transform coordinates, you need to get the proj4 strings for the CRSs that you want to use. You can get them by searching online, from websites like this or this.

// store the proj4 string for the CRS that you are transforming FROM 
// this one is WGS84 (what Leaflet is using)
var p_wgs84 = "+proj=longlat +datum=WGS84 +no_defs";

// store the proj4 string for the CRS that you are transforming TO
// this one is British National Grid
var p_osgb = "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs";

// use those proj4 strings to create a proj4 object
var transformer = proj4(p_wgs84, p_osgb);

Now we have our object, it’s time to use it! proj4 objects contain two functions:

.forward() transform between the first coordinate reference system and the second (wgs84 to osgb in our case)
.inverse() transform between the second coordinate reference system and the first (osgb to wgs84 in our case)

You pass coordinates to the functions as an array in the form [ longitude, latitude ].

The transformation itself is as simple as:

// transform coordinates to OSGB
var xy = transformer.forward([-2.345, 53.456]);

//xy[0] = longitude;
//xy[1] = latitude;

Events

To add an event to an HTML element, you just need to use the relevant attribute in the opening tag:

<!-- Set the listener for the load event -->
<body onload='initMap();'> 

<!-- Set the listener for the click event -->
<button onclick="alert('You clicked my button!');">Go on, give me a click...</button>

To add listeners to a Leaflet Map, simply use the map.on() function:

// add listener for click event on the map
map.on('click', onMapClick);

Then you just need a listener, which is a function that takes a single argument (the event object):

/**
 * Event handler for map click
 */
function onMapClick(e) {
	
	// add a popup to the marker and open it
	console.log( "you clicked at " + e.latlng );
}

You can also add events to other map elements, such as GeoJSON layers (click for example).


Firebase

Firebase is an online nosql database service offered by Google.

Anonymously sign in to Firebase

// sign in anonymously - this helps stop your database being abused
firebase.auth().signInAnonymously().catch(function(error) {
  console.log(error.code);
  console.log(error.message);
});

Get a reference to a particular collection in Firebase

This gets a reference to a collection called "clicks"

// create a global reference to the 'clicks' collection in your database
myDb = firebase.database().ref().child('clicks');

Adding some GeoJson to Firebase

// push the data into the database, set inline callback
myDb.push(data, function(error) {

  //if no error is returned to the callback, then it was loaded successfully
  if (!error) { 
    console.log("successfully added to firebase!");

    // otherwise pass the error to the console
  } else {
    console.error(error);
  }
});

Deleting some data from Firebase

In this example we are updating a marker location based upon a click event

// prepare the data to update in the database (deleting is done by updating to null)
var updates = {};
updates['/clicks/' + snapshot.key] = null;	//snapshot is the database snapshot

// update the point location in the database and callback to console
firebase.database().ref().update(updates, function(error) {
  if (!error) {
    console.log("successfully deleted point!");
  } else {
    console.error(error);
  }
});

Updating some data in Firebase

In this example we are updating some data in firebase

// prepare the data to update in the database
var updates = {};
updates['/clicks/' + snapshot.key] = data;	//snapshot is the database snapshot

// update the point location in the database and callback to console
firebase.database().ref().update(updates, function(error) {
  if (!error) {
    console.log("successfully updated firebase!");
  } else {
    console.error(error);
  }
});

Functions

Functions must first be declared, this tells the browser what they do and what arguments they require, but does not actually do anything else:

/**
 * Add two numbers together
 */
function addUp(arg1, arg2) {
  return arg1 + arg2;
}

To make the function actually run, you must then call it:

//get my name from the function and store it in a variable called result
var result = addup(2, 4);

//result = 6

GeoJSON

GeoJSON is a spatial data format commonly used for web applications.

You can add it to a map like this:

// load the geojson data, style it, set events and add to map
geojson = L.geoJson(countries, { }).addTo(map);

You can add it with a global style like this:

// load the geojson data and style it
geojson = L.geoJson(countries, { 
	style: {
		weight: 0.5,
		color: 'white',
		fillOpacity: 1,
		fillColor: 'lightgrey',
	}
}).addTo(map);

You can add it with a dynamic style (based upon property values) like this:

geojson = L.geoJson(countries, {
	style: style,		//set the style using a function
}).addTo(map);

/**
 * This function styles the data (a single country)
 */
function style(feature) {
	
	//return a style
	return {
		weight: 0.5,
		color: 'white',
		fillOpacity: 1,
		fillColor: getColour(feature.properties.POP_EST)	//the colour is set using a function
	};
}

GeoJSON and Events

Events can be added to each individual feature in a GeoJSON layer using thre onEachFeature option, which calls a specified function once for each feature in the GeoJSON dataset:

// load the geojson data, style it, set events and add to map
geojson = L.geoJson(countries, {
	style: style,			//set the style using your function
	onEachFeature: setEvents,	//set the hover events using your function
}).addTo(map);

You then add events to a GeoJSON layer just as you would the map or anything else in leaflet: using the .on() function.

/**
 * Create a function to tie the mouseover and mouseout events to re-styling the layer
 */
function setEvents(feature, layer) {
	layer.on({
		mouseover: highlightFeature,
		mouseout: resetHighlight,
	});
}

Objects

Objects in JavaScript are created eitehr using object constructors or object literals.

For example, coordinates are stored in Leaflet using a LatLng object, which can be made using a constructor like this:

var latlng = L.latLng(50.5, 30.5);

Where the constructor L.LatLng() takes two arguments, the latitide and the longitude. However, the object that it returns simply looks like this:

{lat: 50, lng: 30}

As a result, if we are dealing with a very simple object such as this then we might as well not bother with a constructor and we can just write the object literal (as in, literally just write the object out manually):

var latlng = {lat: 50, lng: 30};

This is exactly the same as the first example, and can be a little more convenient in the case of very simple objects. In most cases, however, where object are more comples (like L.map, for example), the constructor is the way to go.


Operators

An operator is a mathematical symbol that produces a result based upon two values (which are normally stored in variables). In the following table you can see some of the simplest operators, along with some examples:

Operator Explanation Symbol(s) Example
add/concatenate Used to add two numbers together, or concatenate two strings together. + 6 + 9;

"Hello " + "world!";
subtract, multiply, divide These do what you’d expect them to do in basic maths. -, *, / 9 - 3;

8 * 2;

9 / 3;
assignment operator You’ve seen this already, it assigns a value to a variable. = myVariable = "Bob";
identity operator Does a test to see if two values are equal to one another, and returns a true/false (Boolean) result. === myVariable = 3;

myVariable === 4; (false)
negation, not equal Returns the logically opposite value of what it preceeds; it turns a true into a false, etc.

When it is used alongside the equality operator, the negation operator tests whether two values are not equal.
!, !== myVariable = 3;

!(myVariable === 3); (false)

myVariable = 3;

myVariable !== 3; (false)
greater than, less than these operators compare the operands and determine whether the one to the left is greater than (>) or less than (<) the one on the right.

When combined with an equals (>=, <=), the meaning changes to greater than or equal to or less than or equal to respectively.
>, >=, <, <= var2 > var1

var1 <= var2
increment, decrement ++, -- Adds one to and subtracts one from its operand respectively. If used as a prefix operator (++x), returns the value of its operand after adding one; if used as a postfix operator (x++), returns the value of its operand before adding one. If x is 3, then ++x sets x to 4 and returns 4, whereas x++ returns 3 and, only then, sets x to 4.

Thousands Separators

Covert numbers like 1234567 to more easily readable formats like 1,234,567 with this simple toLocaleString() function.

// add thousands separators to a string representing a number
parseFloat(numberAsString).toLocaleString('en');

// add thousand separators to a number (results in a string)
number.toLocaleString('en');

Variables

var myVariable = "Jonny";

Variable Types:

Variable Explanation Example
String A string of text. To signify that the variable is a string, you should enclose it in quote marks. var myVariable = "Bob";
Number A number. Numbers don’t have quotes around them. var myVariable = 10;
Boolean A True/False value. The words true and false are special keywords in JavaScript, and don’t need quotes. var myVariable = true;

A variable that does not contain a value of one of these types is said to be null.