|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Leaflet Draw</title> |
|
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.15/themes/css/cartodb.css" /> |
|
<script src="http://libs.cartocdn.com/cartodb.js/v3/3.15/cartodb.js"></script> |
|
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.3/leaflet.draw.css" /> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.3/leaflet.draw.js"></script> |
|
|
|
</head> |
|
<body> |
|
<div id="map" style="position: absolute; top: 0; left: 0; width: 80%; height: 80%;"></div> |
|
|
|
<script> |
|
//initialize the map with Leaflet |
|
var map = new L.Map('map', {center: new L.LatLng(40.7, -74), zoom: 11}); |
|
|
|
//add a carto basemap tile layer |
|
var carto = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}@2x.png', { |
|
maxZoom: 18, |
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, © <a href="https://carto.com/attributions">CARTO</a>' |
|
}).addTo(map); |
|
|
|
//prep the draw FeatureGroup and add Leaflet.draw controls to map |
|
var drawnItems = new L.FeatureGroup(); |
|
var drawControl = new L.Control.Draw({ |
|
position: 'topright', |
|
draw: { |
|
polyline: false, |
|
polygon: false, |
|
circle: false, |
|
rectangle: false, |
|
marker: true |
|
}, |
|
edit: { |
|
featureGroup: drawnItems, |
|
remove: true |
|
} |
|
}); |
|
map.addControl(drawControl); |
|
|
|
//create cartodb.SQL object to grab geojson of table |
|
//see here https://carto.com/blog/the-versatility-of-retreiving-and-rendering-geospatial |
|
var sql = new cartodb.SQL({ user: 'athompson', format:'GeoJSON'}); |
|
sql.execute("SELECT * FROM areas_of_interest_newyork_nycsanitation") |
|
.done(function(data) { |
|
|
|
//add geojson features to the drawnItems FeatureGroup |
|
//console.log(data);//optional/debugging |
|
geojsonLayer = L.geoJson(data, { |
|
onEachFeature: function (feature, layer) { |
|
layer.cartodb_id=feature.properties.cartodb_id; |
|
drawnItems.addLayer(layer); |
|
} |
|
}); |
|
//add the drawnItems FeatureGroup, populated with geojson from carto table, to the map |
|
map.addLayer(drawnItems); |
|
}) |
|
.error(function(errors) { |
|
// errors contains a list of errors |
|
console.log("errors:" + errors); |
|
}); |
|
|
|
function persistOnCartoDB(action, layers) { |
|
/* |
|
this function interacts with the Security Definer |
|
function previously defined in our CARTO account. |
|
Gets an action (update, insert, or delete) and a list |
|
of GeoJSON objects (the geometry objects only, to work |
|
with ST_GeomFromGeojson()) with which to change the table. |
|
see http://gis.stackexchange.com/questions/169219/invalid-geojson-when-inserting-data-to-a-cartodb-postgis-table-from-leaflet |
|
*/ |
|
var cartodb_ids = []; |
|
var geojsons = []; |
|
//console.log(action + " persistOnCartoDB"); |
|
|
|
switch (action) { |
|
case "UPDATE": |
|
//console.log(layers.getLayers().length); |
|
if (layers.getLayers().length < 1) return; |
|
|
|
layers.eachLayer(function(layer) { |
|
cartodb_ids.push(layer.cartodb_id); |
|
geojsons.push("'" + JSON.stringify(layer.toGeoJSON().geometry) + "'"); |
|
}); |
|
break; |
|
|
|
case "INSERT": |
|
cartodb_ids.push(-1); |
|
//console.log("here is the geojsons"); |
|
//console.log(geojsons); |
|
//console.log("'" + JSON.stringify(layers.toGeoJSON().geometry) + "'"); |
|
geojsons.push("'" + JSON.stringify(layers.toGeoJSON().geometry) + "'"); |
|
break; |
|
|
|
case "DELETE": |
|
layers.eachLayer(function(layer) { |
|
cartodb_ids.push(layer.cartodb_id); |
|
geojsons.push("''"); |
|
}); |
|
break; |
|
} |
|
|
|
//constructs the SQL statement |
|
var sql = "SELECT nyc_sanitation_example_upsert_areas_of_interest_newyork_nycsanitation(ARRAY["; |
|
sql += cartodb_ids.join(","); |
|
sql += "],ARRAY["; |
|
sql += geojsons.join(","); |
|
sql += "]);"; |
|
|
|
console.log("persisting... " + sql);//optional/debugging |
|
//POST the SQL up to CARTO |
|
$.ajax({ |
|
type: 'POST', |
|
url: 'https://athompson.carto.com/api/v2/sql', |
|
crossDomain: true, |
|
data: { |
|
"q": sql |
|
}, |
|
dataType: 'json', |
|
success: function(responseData, textStatus, jqXHR) { |
|
console.log("Data saved"); |
|
|
|
if (action == "INSERT") |
|
layers.cartodb_id = responseData.rows[0].cartodb_id; |
|
}, |
|
error: function(responseData, textStatus, errorThrown) { |
|
console.log("Problem saving the data " + responseData); |
|
} |
|
}); |
|
} |
|
|
|
//bind drawing events to fire the persistOnCartoDB() function |
|
|
|
map.on('draw:created', function (e) { |
|
//console.log("draw:created fired"); |
|
var layers = e.layer;//was e.layers not layer |
|
drawnItems.addLayer(layers); |
|
//console.log(e); |
|
persistOnCartoDB("INSERT", layers); |
|
//console.log("draw:created:insert persistOnCartoDB fired"); |
|
}); |
|
|
|
map.on('draw:edited', function (e) { |
|
//console.log("draw:edited fired"); |
|
var layers = e.layers; |
|
persistOnCartoDB("UPDATE", layers); |
|
//console.log("draw:edited:update persistOnCartoDB fired"); |
|
}); |
|
|
|
map.on('draw:deleted', function (e) { |
|
//console.log("draw:deleted fired"); |
|
var layers = e.layers; |
|
persistOnCartoDB("DELETE", layers); |
|
//console.log("draw:deleted:delete persistOnCartoDB fired"); |
|
}); |
|
|
|
</script> |
|
</body> |
|
</html> |