Welcome to Advanced GIS, Lecture 8

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

→ to move forward

← to go back

Advanced GIS

Class 8

Please fill out this form while we settle in

no class next week (March 18): spring break

no class the week after (March 25)

class online after that (April 1)

Morgane
Natalia

functions?

function sayHi(name) {
  console.log('hi ' + name);
}
source

three steps:

  1. create a button
  2. listen for a click on the button
  3. change the layer's SQL

1. create a button

<button class="juvenile-button">
  just show Juvenile habitat
</button>

2. listen for a click on the button

juvenileButton.addEventListener('click', function (e) {
  ...
});

3. change the layer's SQL

juvenileButton.addEventListener('click', function (e) {
  source.setQuery("SELECT * FROM hms_efh_2009tiger_shark WHERE life_stage = 'Juvenile'");
});

events

most of the time, code happens sequentially

(you get the idea)

events give the user a way to interrupt the program

you can use this pattern with any other kind of input

  1. Add the HTML for the input to the page
  2. Listen for the input to change
  3. Update your data layer's SQL

you could make a button for each type of feature

SELECT * 
FROM hms_efh_2009tiger_shark 
WHERE life_stage = 'Adult'

SELECT * 
FROM hms_efh_2009tiger_shark 
WHERE life_stage = 'Neonate'

but that's kinda what dropdowns are for

livinglotsnyc.org
source

1. create a dropdown

<select class="type-picker">
  <option value="all">Show all life stages</option>
  <option value="Adult">Adult</option>
  <option value="Juvenile">Juvenile</option>
  <option value="Neonate">Neonate</option>
</select>

2. listen for a change to the dropdown

layerPicker.addEventListener('change', function (e) {
  ...
});

with a dropdown, you want to vary the SQL by the option selected

SELECT * 
FROM hms_efh_2009tiger_shark 
WHERE life_stage = 'Adult'

SELECT * 
FROM hms_efh_2009tiger_shark 
WHERE life_stage = 'Neonate'
var lifeStage = e.target.value;
var lifeStage = e.target.value;
var sql = "SELECT * FROM hms_efh_2009tiger_shark WHERE life_stage = " + lifeStage;
var lifeStage = e.target.value;
var sql = "SELECT * FROM hms_efh_2009tiger_shark WHERE life_stage = '" + lifeStage + "'";

the event listeners we just looked at are standard browser events

there are also map-specific events

listening for leaflet events

source

map events

source
map.on('moveend', function () {
  console.log('done moving');
});
source

in-class exercise, part 1

popups

source
source

1. when creating the layer, tell Carto which fields are allowed in the popup

source

like when you tell Carto which fields are in the popup

source

make an HTML string that goes into the popup

source

this can be basically any HTML you can imagine, including video, images, and audio

source

start simple and add to it

source
source

the process is very similar for putting data in a sidebar (or elsewhere on a page)

source

gathering data

source
source
source
source
source
source
NYPL Building Inspector
NYPL Building Inspector
source
source

I'd suggest starting with Google Forms

source

easiest case, with the least code

source

you have to manually enter the latitude and longitude

source

but we can customize this a bit if we copy the way Google Forms are submitted

1. find the form's action attribute

make your own form in HTML with the same action

2. for each form input, find the name attribute

add a form input with the same name

source

this is a pretty good walkthrough

source
source

hmm but you still have to enter the latitude and longitude somehow

source
source

using an event listener to set the latitude and longitude

source
source

hiding the latitude and longitude

source
source
source

same thing, with a redirect

source

when customizing a Google Form this way, you gain control over how it looks and adding a map input

but you also lose some features:

but you also lose some features:

but you also lose some features:

you will need to make these yourself (similarly to making the map input)

once your form is working, create a Google Sheet for the responses

and sync that sheet up with a Carto dataset

as long as there are fields called Latitude and Longitude, this will be fine

source

filter features to the area around a clicked point

source
SELECT *
FROM nypd_motor_vehicle_collisions
WHERE ST_Within(
  ST_Transform(the_geom, 2263),
  ST_Buffer(
    ST_Transform(CDB_LatLng(40.732, -73.986), 2263),
    10000
  )
)
SELECT *
FROM nypd_motor_vehicle_collisions
SELECT *
FROM nypd_motor_vehicle_collisions
WHERE ST_Within(
  smaller geometry,
  larger geometry
)
SELECT *
FROM nypd_motor_vehicle_collisions
WHERE ST_Within(
  the_geom,
  larger geometry
)
SELECT *
FROM nypd_motor_vehicle_collisions
WHERE ST_Within(
  ST_Transform(the_geom, 2263),
  larger geometry
)
SELECT *
FROM nypd_motor_vehicle_collisions
WHERE ST_Within(
  ST_Transform(the_geom, 2263),
  ST_Buffer(
    input point,
    10000
  )
)
SELECT *
FROM nypd_motor_vehicle_collisions
WHERE ST_Within(
  ST_Transform(the_geom, 2263),
  ST_Buffer(
    CDB_LatLng(40.732, -73.986),
    10000
  )
)
SELECT *
FROM nypd_motor_vehicle_collisions
WHERE ST_Within(
  ST_Transform(the_geom, 2263),
  ST_Buffer(
    ST_Transform(CDB_LatLng(40.732, -73.986), 2263),
    10000
  )
)
source

you can look at relationships between layers, too

SELECT collisions.*
FROM collisions
JOIN ny_boroughs ON 
  ST_Within(collisions.the_geom, ny_boroughs.the_geom)
WHERE ny_boroughs.boroname = 'Bronx'

leaflet plugins

source
source
leaflet-control-geocoder
leaflet-control-geocoder
Leaflet.MiniMap
Leaflet.MiniMap
leaflet-markercluster
leaflet-markercluster
Leaflet.draw
Leaflet.draw
Leaflet.MapPaint
Leaflet.MapPaint