-
Notifications
You must be signed in to change notification settings - Fork 111
/
index.html
229 lines (200 loc) · 7.81 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
<!DOCTYPE html>
<!--Based on https://github.com/mjfoster83/web-map-workshop/blob/master/7_advancedMapping_CartoDB/index-completed.html-->
<html>
<head>
<title>Leaflet to Carto - Point Collection Tool Beta</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@0.7.7/dist/leaflet.css"
integrity="sha384-99ZJFcuBCh9c/V/+8YwDX/TUGG8JWMG+gKFJWzk0BZP3IoDMN+pLGd3/H0yjg4oa"
crossorigin=""/>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.12/leaflet.draw.css"/>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div id="wrapper">
<div id="header">
<h1>Leaflet Draw Collection Tool</h1>
</div>
<div id="map"></div>
<div id="controls">
<p>Click points for more information, or add your own.</br></p>
<input type="button" onclick="startEdits()" value="Click to Start Editing">
<input type="button" onclick="stopEdits()" value="Stop Your Editing Session"><br>
<div id="credits"><p>©2015, Mike Foster and Raphael Dumas</p></div>
</div>
</div>
<div id="dialog" title="Tell us About this Drawing">
<form>
<fieldset style="border: none;">
<ul style="list-style-type: none; padding-left: 0px">
<li><label for="username">Your Name</label></li>
<li><input type="text" name="username" id="username" placeholder="Enter your name" class="text ui-widget-content ui-corner-all"></li>
<li><label for="description">About this</label></li>
<li><input type="text" name="description" id="description" placeholder="Description for this point" class="text ui-widget-content ui-corner-all"></li>
</ul>
<input type="submit" tabindex="-1" style="position:absolute; top:-1000px">
</fieldset>
</form>
</div>
<script src="https://unpkg.com/leaflet@0.7.7/dist/leaflet.js"
integrity="sha384-Lh7SNUss9JoImCvc96eCUnLX3HvY4kb0UZCWZbYWvceJ+o5CJeOJqqNoheaGkNHT"
crossorigin=""></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.12/leaflet.draw.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script>
//TODO: Change to your username, insert function on Carto, and Carto tablename
var config = {
cartoUsername : "raphaeld",
cartoInsertFunction : "insert_crowd_mapping_data",
cartoTablename : "crowdmap_basic",
mapcenter: [43.6525, -79.381667],
drawOptions: {
draw : {
polygon : true,
polyline : true,
rectangle : true,
/*Circles aren't supported by the GeoJSON spec, so won't get sent to the database properly.
*http://stackoverflow.com/a/16944309/4047679
*/
circle : false,
circlemarker : false,
marker: true
},
edit : false,
remove: false
}
};
// Add Data from Carto using the SQL API
// Declare Variables
// Create Global Variable to hold Carto points
var cartoData = null;
// Write SQL Selection Query to be Used on Carto Table
var sqlQuery = "SELECT the_geom, description, name FROM " + config.cartoTablename;
// Create Leaflet map object
var map = L.map('map', { center: config.mapcenter, zoom: 13});
// Add Tile Layer basemap
// Find your own at https://leaflet-extras.github.io/leaflet-providers/preview/
var CartoDB_Positron = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> © <a href="https://cartodb.com/attributions">CartoDB</a>',
subdomains: 'abcd',
maxZoom: 19
});
CartoDB_Positron.addTo(map);
//Fetches
var getData = "https://" + config.cartoUsername + ".carto.com/api/v2/sql?format=GeoJSON&q=" + sqlQuery;
function getGeoJSON() {
$.getJSON(getData, function (data) {
cartoData = L.geoJson(data, {
onEachFeature: function (feature, layer) {
layer.bindPopup('' + feature.properties.description + '<br>Submitted by ' + feature.properties.name + '');
}
}).addTo(map);
});
}
getGeoJSON();
var drawnItems = new L.FeatureGroup();
var drawControl = new L.Control.Draw(config.drawOptions);
var controlOnMap = false;
function startEdits() {
if (controlOnMap === true) {
map.removeControl(drawControl);
controlOnMap = false;
}
map.addControl(drawControl);
controlOnMap = true;
}
function stopEdits() {
map.removeControl(drawControl);
controlOnMap = false;
}
map.on(L.Draw.Event.CREATED, function (e) {
var layer = e.layer;
map.addLayer(drawnItems);
drawnItems.addLayer(layer);
dialog.dialog("open");
});
var dialog = $("#dialog").dialog({
autoOpen: false,
height: 300,
width: 350,
modal: true,
position: {
my: "center center",
at: "center center",
of: "#map"
},
buttons: {
"Add to Database": setData,
Cancel: function () {
dialog.dialog("close");
refreshLayer();
}
},
close: function () {
form[0].reset();
refreshLayer();
console.log("Dialog closed");
}
});
form = dialog.find("form").on("submit", function (event) {
event.preventDefault();
setData();
});
function setData() {
//.replace() doubles each single quote in order to escape them for PostgreSQL
//so that user input containing single quotes doesn't escape the SQL function
//JSON.stringify properly escapes double quotes " so they don't break the SQL function either https://stackoverflow.com/questions/24559625/javascript-escape-double-quotes
//There might be a better way https://stackoverflow.com/questions/57844173/how-can-i-sanitize-user-input-data-to-be-inserted-into-my-carto-table
var enteredUsername = "'" + JSON.stringify(username.value.replace("'", "''")) + "'"
var enteredDescription = "'" + JSON.stringify(description.value.replace("'", "''")) + "'";
drawnItems.eachLayer(function (layer) {
//Convert the drawing to a GeoJSON to pass to the Carto sql database
var drawing = "'" + JSON.stringify(layer.toGeoJSON().geometry) + "'",
//Construct the SQL query to insert data from the three parameters: the drawing, the input username, and the input description of the drawn shape
sql = "SELECT " + config.cartoInsertFunction + "(";
sql += drawing;
sql += "," + enteredDescription;
sql += "," + enteredUsername;
sql += ");";
console.log(drawing);
//Sending the data
$.ajax({
type: 'POST',
url: 'https://' + config.cartoUsername + '.carto.com/api/v2/sql',
crossDomain: true,
data: {"q": sql},
dataType: 'json',
success: function (responseData, textStatus, jqXHR) {
console.log("Data saved");
},
error: function (responseData, textStatus, errorThrown) {
console.log("Problem saving the data");
}
});
/*
* Transfer submitted drawing to the Carto layer, this results in the user's data appearing on the map without
* requerying the database (see the refreshLayer() function for an alternate way of doing this)
*/
var newData = layer.toGeoJSON();
newData.properties.description = description.value;
newData.properties.name = username.value;
cartoData.addData(newData);
});
dialog.dialog("close");
}
function refreshLayer() {
console.log("drawnItems has been cleared");
map.removeLayer(drawnItems);
drawnItems = new L.FeatureGroup();
/*
This would refresh the data-layer to include new data from the Carto table after each drawing is submitted.
*/
// if (map.hasLayer(cartoData)) {
// map.removeLayer(cartoData);
// };
// getGeoJSON();
}
</script>
</body>
</html>