Welcome to Advanced Interactive Web Mapping, Programming, and Design, Class 11

This is a web page that can be viewed as slides.

→ to move forward

← to go back

Advanced Interactive Web Mapping, Programming, and Design

Class 11

templates

templates create HTML for you

templates use variables from your code

template + data = html

Mustache

Mustache is one library for making templates

CartoDB uses Mustache

so can you!

Mustache docs

<p>
    <span>{{name}}</span>:
    <span>{{job}}</span>
</p>
<p>
    <span>{{name}}</span>:
    <span>{{job}}</span>
</p>

anything in {{}} gets replaced by Mustache

<p>
    <span>{{name}}</span>:
    <span>{{job}}</span>
</p>
            
...

var context = {
    name: "Frank",
    job: "milkman"
};
<p>
    <span>Frank</span>:
    <span>milkman</span>
</p>

we'll call the data you pass to the template its context

passing the context to Mustache tells it how to fill your template

please do in-class exercise part 1

it can get ugly having all that HTML-ish code in a string in JavaScript

most people put it in the HTML

most people put it in the HTML in a script tag

$('#template').html()

this is so common that HTML5 supports a new template tag

but until IE supports it we're stuck with our hack

please do in-class exercise part 2

you can loop over arrays in a context

{{#rows}}
    <li>{{name}}</li>
{{/rows}}
{{#rows}}
    <li>{{name}}</li>
{{/rows}}

would work with

var context = {
    rows: [
        { name: 'Frank' },
        { name: 'Jane' }
    ]           
};

    <li>Frank</li>
    <li>Jane</li>

you can also use this to only show some HTML if a value is set

{{#url}}
    <a href="{{url}}">{{name}}</a>
{{/url}}

please do in-class exercise part 3

you can use Mustache templates in Leaflet

jsbin

  1. get the template

jsbin

  1. get the template
  2. render the template with the feature's properties

jsbin

  1. get the template
  2. render the template with the feature's properties
  3. set the popup's html to the rendered template

jsbin

please do in-class exercise part 4

handlebars

if you need a little more power

Turf

turfjs.org

what is it?

yet another library

supplementary to mapping libraries that can use GeoJSON

most mapping libraries focus on getting geometries on a map

and making them look nice

but as soon as you need to do something GIS-like

say, buffer a point and check whether there are any other points in that range

libraries such as Leaflet suddenly feel inadequate

that's okay Leaflet, you never set out to be a GIS

Leaflet was started in 2010

computers and browsers were significantly slower then

so, make the server do GIS

let the browser focus on displaying the data

arcgis server
geoserver
tilestache
geodjango

all ways of saying, "let's make some other computer on the internet do the GIS for us"

for example

with CartoDB you ask the server for the data and can add GIS operations to it


SELECT neighbourhood,
  ST_Convexhull(
    ST_Collect(the_geom_webmercator)
  ) AS the_geom_webmercator 
FROM listings
GROUP BY neighbourhood

and can get the data back in GeoJSON

and Leaflet will happily put the data on the map for us

we can say Leaflet is (intentionally) dumb

this is usually fine, but

there are a few potential issues with this arrangement:

  1. time to make requests

  1. time to make requests
  2. software price

  1. time to make requests
  2. software price
  3. server price

  1. time to make requests
  2. software price
  3. server price
  4. now you have to worry about a server being online

okay so how's it work?

iditarod with turf
dropchop.io

Turf provides functions

turf docs
turf docs
turf docs
turf docs
turf docs

Turf functions often take GeoJSON and return GeoJSON

var feature; // Assuming this exists
var buffered = turf.buffer(feature);
var feature; // Assuming this exists
var buffered = turf.buffer(feature);

// Then we can treat buffered like 
// GeoJSON we got from $.getJSON()
L.geoJson(buffered).addTo(map);
var feature; // Assuming this exists
var turfLayer = L.geoJson(null).addTo(map);
var buffered = turf.buffer(feature);

turfLayer.addData(buffered);

please do in-class exercise part 5

| means "or"

buffer() takes a Feature OR a FeatureCollection

returns a FeatureCollection of Polygons or MultiPolygons or a single Polygon or MultiPolygon

GeoJSON

GeoJSON objects are just JavaScript objects

point

{
    "type": "Feature",
    "geometry": {
        "type": "Point",
        "coordinates": [102.0, 0.5]
    },
    "properties": {"prop0": "value0"}
}

line

{
    "type": "Feature",
    "geometry": {
        "type": "LineString",
        "coordinates": [ /* array */ ]
    },
    "properties": {"prop0": "value0"}
}

polygon

{
    "type": "Feature",
    "geometry": {
        "type": "Polygon",
        "coordinates": [ /* array */ ]
    },
    "properties": {"prop0": "value0"}
}

each of these have Multi-flavors

MultiPoint

MultiLineString

MultiPolygon

FeatureCollection is an array of these features

{
    "type": "FeatureCollection",
    "features": [ /* features */ ]
}
more than you ever wanted to know about geojson

How do you get a GeoJSON object?

How do you get a GeoJSON object?

  1. load it
  2. get it from Leaflet objects
  3. create it

1. loading GeoJSON

$.getJSON(url, function (data) {
    // If the url points to valid GeoJSON,
    // data is a GeoJSON object           
});

2. from Leaflet objects

var dataLayer = L.geoJson(data).addTo(map);
var geojson = dataLayer.toGeoJson();

3. create it

turf.point([-75.343, 39.984]);

please do in-class exercise part 6