Skip to content

Instantly share code, notes, and snippets.

@akbstone
Forked from mapsense-examples/bounds.js
Created June 7, 2016 16:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akbstone/494f9f71f3c69a47ee3e774fbc72bd59 to your computer and use it in GitHub Desktop.
Save akbstone/494f9f71f3c69a47ee3e774fbc72bd59 to your computer and use it in GitHub Desktop.
Drag & drop csv to map
// Hat tip Mike Bostock: https://github.com/mbostock/polymaps/blob/master/examples/bounds/bounds.js
function bounds(features) {
var i = -1,
n = features.length,
geometry,
bounds = [{lon: Infinity, lat: Infinity}, {lon: -Infinity, lat: -Infinity}];
while (++i < n) {
//geometry = features[i].data.geometry;
geometry = features[i].geometry;
boundGeometry[geometry.type](bounds, geometry.coordinates);
}
return bounds;
}
function boundPoint(bounds, coordinate) {
var x = coordinate[0], y = coordinate[1];
if (x < bounds[0].lon) bounds[0].lon = x;
if (x > bounds[1].lon) bounds[1].lon = x;
if (y < bounds[0].lat) bounds[0].lat = y;
if (y > bounds[1].lat) bounds[1].lat = y;
}
function boundPoints(bounds, coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) boundPoint(bounds, coordinates[i]);
}
function boundMultiPoints(bounds, coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) boundPoints(bounds, coordinates[i]);
}
var boundGeometry = {
Point: boundPoint,
MultiPoint: boundPoints,
LineString: boundPoints,
MultiLineString: boundMultiPoints,
Polygon: function(bounds, coordinates) {
boundPoints(bounds, coordinates[0]); // exterior ring
},
MultiPolygon: function(bounds, coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) boundPoints(bounds, coordinates[i][0]);
}
};
document.addEventListener("DOMContentLoaded", function(event) {
var dropzone = document.querySelector('#myMap');
var dragzone = document.querySelector('#myMap');
var filelist;
dropzone.addEventListener('drop', function(event) {
if (event.preventDefault) {
event.preventDefault();
}
var types = event.dataTransfer.types;
filelist = event.dataTransfer.files;
var file = event.dataTransfer.files[0];
if (file.type !== 'text/csv') {
alert('Uploaded file must be a RFC4180-compliant CSV file');
return false;
}
// Init file reader
var fileReader = new FileReader();
fileReader.onload = function (e) {
processCsv(d3.csv.parse(fileReader.result));
};
fileReader.onerror = function (e) {
throw 'Error reading CSV file';
};
// Start reading file
fileReader.readAsText(file);
return false;
}, false);
dragzone.addEventListener('dragstart', function(event) {
return true;
}, true);
dragzone.addEventListener('dragend', function(event) {
return true;
}, true);
dropzone.addEventListener('dragenter', function(event) {
if (event.preventDefault) event.preventDefault();
return false;
}, false);
dropzone.addEventListener('dragover', function(event) {
if (event.preventDefault) event.preventDefault(); // allows us to drop
}, false);
dropzone.addEventListener('dragleave', function(event) {
if (event.preventDefault) event.preventDefault(); // allows us to drop
return false;
}, false);
});
We can make this file beautiful and searchable if this error is corrected: It looks like row 19 should actually have 7 columns, instead of 1. in line 18.
"INPUT","lat","lon","display_name","class","type","importance"
"Acadia National Park","44.28969315","-68.397779592087","Acadia National Park, Audrey's Lane, Seal Cove, Hancock County, Maine, United States of America","leisure","park","0.71914108746201"
"Arches National Park","38.727356","-109.562989344458","Arches National Park, Arches Hiking, Grand County, Utah, United States of America","leisure","nature_reserve","0.8819353381181"
"Biscayne National Park","25.50312235","-80.2348495319876","Biscayne National Park, Miami-Dade County, Florida, United States of America","leisure","nature_reserve","0.75449074108058"
"Badlands National Park","43.52710585","-102.361662795674","Badlands National Park, Oglala Lakota County, South Dakota, United States of America","leisure","park","0.745262970359"
"Big Bend National Park","29.33341","-103.194000319734","Big Bend National Park, Panther Junction, Brewster County, Texas, 79834, United States of America","leisure","park","0.84579082541219"
"Black Canyon of the Gunnison National Park","38.5798065","-107.743696949741","Black Canyon of the Gunnison National Park, Warner Route, Montrose County, Colorado, United States of America","leisure","park","1.1235546632572"
"Bryce Canyon National Park","37.5713588","-112.185656507705","Bryce Canyon National Park, Under the Rim Trail, Garfield County, Utah, United States of America","leisure","nature_reserve","0.87468092975348"
"Capitol Reef National Park","38.06702855","-111.155256098546","Capitol Reef National Park, Garfield County, Utah, United States of America","leisure","nature_reserve","0.98019506526221"
"Canyonlands National Park","38.1666522","-109.984017","Canyonlands National Park, NP 756, Garfield County, Utah, United States of America","leisure","park","0.301"
"Carlsbad Caverns National Park","32.11926425","-104.600826706786","Carlsbad Caverns National Park, Slaughter Canyon Cave Trail, Eddy County, New Mexico, United States of America","leisure","nature_reserve","0.83445767985789"
"Congaree National Park","33.8302322","-80.8243399","Congaree National Park, Caroline Sims Road, Weston, Richland County, South Carolina, 29061, United States of America","leisure","park","0.68844676960817"
"Crater Lake National Park","42.931692","-122.127836406071","Crater Lake National Park, Wizard Island Summit Trail, Rim Village, Klamath County, Oregon, United States of America","leisure","nature_reserve","0.85379433483971"
"Channel Islands National Park","34.0083586","-119.3957895","Channel Islands National Park, Ventura, California, United States of America","leisure","park","0.401"
"Cuyahoga Valley National Park","41.2608304","-81.556429320078","Cuyahoga Valley National Park, Ohio & Erie Canal Towpath Trail, Boston, Boston Township, Summit County, Ohio, 44264, United States of America","leisure","nature_reserve","0.8108263210417"
"Death Valley National Park","36.490621","-117.102029074319","Death Valley National Park, Inyo County, California, United States of America","leisure","nature_reserve","0.8931891212183"
"Dry Tortugas National Park","24.6377223","-82.8767980601244","Dry Tortugas National Park, Monroe County, Florida, United States of America","leisure","park","0.84097789671849"
"Everglades National Park","25.3870275","-80.8802630659629","Everglades National Park, Monroe County, Florida, United States of America","boundary","national_park","0.77882407233632"
"Not found: Gates of the Arctic National Park"
"Glacier National Park","48.61691115","-113.760879457289","Glacier National Park, Sperry Chalets, Flathead County, Montana, United States of America","leisure","nature_reserve","0.78894916366889"
"Grand Teton National Park","43.810789","-110.648591941638","Grand Teton National Park, Jackson Hole, Teton County, Wyoming, United States of America","leisure","nature_reserve","0.88206595135262"
"Great Basin National Park","38.915135","-114.1869029","Great Basin National Park, White Pine County, Nevada, 89311, United States of America","highway","track","0.81271729740322"
"Grand Canyon National Park","36.3044354","-112.29004113377","Grand Canyon National Park, Coconino County, Arizona, United States of America","leisure","nature_reserve","0.87271502047963"
"Denali National Park & Preserve","63.1831737","-151.148363066604","Denali National Park and Preserve, Denali, Alaska, United States of America","leisure","nature_reserve","0.72715694630872"
"Great Sand Dunes National Park and Preserve","37.8092835","-105.581283091798","Great Sand Dunes National Park and Preserve, Saguache County, Colorado, United States of America","leisure","park","1.1214471424681"
"Great Smoky Mountains National Park","35.6079063","-83.5021791546683","Great Smoky Mountains National Park, Fort Harry, Sevier County, Tennessee, United States of America","leisure","park","0.96059389488672"
"Not found: Haleakala National Park"
"Guadalupe Mountains National Park","31.90828235","-104.900320000159","Guadalupe Mountains National Park, Kincaid Trail, Culberson County, Texas, United States of America","leisure","nature_reserve","0.8111207303807"
"Hawaii Volcanoes National Park","19.3031881","-155.240502021651","Hawai'i Volcanoes National Park, Hilo, Hawaiʻi County, Hawaii, United States of America","leisure","park","0.61"
"Hot Springs National Park","34.5167562","-93.0529572","Hot Springs National Park, Fountain Street, Hot Springs, Garland County, Arkansas, 71901, United States of America","leisure","park","0.80481108502374"
"Kenai Fjords National Park","59.311314","-150.7197276","Kenai Fjords National Park, Kenai Peninsula, Alaska, United States of America","leisure","nature_reserve","0.401"
"Kings Canyon National Park","36.91527845","-118.607643757552","Kings Canyon National Park, Fresno County, California, United States of America","leisure","nature_reserve","0.85837881165037"
"Joshua Tree National Park","33.89556375","-115.94731898683","Joshua Tree National Park, Riverside County, California, United States of America","leisure","nature_reserve","0.8630099734438"
"Katmai National Park and Preserve","58.6929377","-156.667593","Katmai National Park and Preserve Headquarters, Boris Boulevard, King Salmon, Bristol Bay, Alaska, 99613, United States of America","tourism","information","0.501"
"Isle Royale National Park","48.0020629","-88.8411052","Isle Royale National Park, Eagle Harbor Township, Keweenaw, Michigan, United States of America","leisure","park","0.401"
"Not found: Kobuk Valley National Park"
"Lassen Volcanic National Park","40.4915974","-121.404609417303","Lassen Volcanic National Park, Lassen Peak Highway, Shasta County, California, United States of America","leisure","nature_reserve","0.85837881165037"
"Mammoth Cave National Park","37.1841693","-86.1229909291288","Mammoth Cave National Park, Green River Ferry Road, Mammoth Cave, Edmonson County, Kentucky, United States of America","leisure","park","0.8371023488262"
"Mesa Verde National Park","37.253776","-108.455596309289","Mesa Verde National Park, Moccasin Mesa Road, Montezuma County, Colorado, United States of America","leisure","park","0.89914501564847"
"Mount Rainier National Park","46.8540872","-121.706319447911","Mount Rainier National Park, United States of America","boundary","national_park","0.85222040055854"
"Olympic National Park","47.656878","-124.3800579","Olympic National Park, US 101, Jefferson County, Washington, United States of America","leisure","nature_reserve","0.75837881165037"
"National Park of American Samoa","-14.2619444","-170.6880556","National Park of American Samoa, Route 001, Alega, Sua, American Samoa, United States of America","leisure","park","0.86704474917533"
"North Cascades National Park","48.5277956","-120.997116604024","North Cascades National Park, Skagit County, Washington, United States of America","leisure","nature_reserve","0.83213550665887"
"Petrified Forest National Park","34.9744769","-109.707994237463","Petrified Forest National Park, Apache County, Arizona, United States of America","boundary","national_park","0.84041063794806"
"Redwood National Park","41.46176695","-124.041044510018","Redwood National Park, Newton B. Drury Scenic Parkway, Humboldt County, California, United States of America","leisure","park","0.77289081775607"
"Saguaro National Park","32.2786864","-111.1826004","Saguaro National Park, Dobe Wash Trail, Pima County, Arizona, United States of America","leisure","park","0.301"
"Rocky Mountain National Park","40.355488","-105.717805293638","Rocky Mountain National Park, Larimer County, Colorado, United States of America","leisure","park","0.85786835123079"
"Sequoia National Park","36.5657034","-118.7730015","Sequoia National Park, Pinewood, Tulare County, California, 93262, United States of America","leisure","nature_reserve","0.76872621020709"
"Shenandoah National Park","38.475313","-78.4547072804979","Shenandoah National Park, Appalachian Trail, Greene County, Virginia, United States of America","leisure","nature_reserve","0.73424986166809"
"Theodore Roosevelt National Park","47.5889496","-103.372036266479","Theodore Roosevelt National Park, Achenbach Trail, McKenzie County, North Dakota, United States of America","leisure","nature_reserve","0.80978559908338"
"Voyageurs National Park","48.446194","-93.0304329","Voyageurs National Park, Kabetogama, Saint Louis County, Minnesota, United States of America","highway","residential","0.4"
"Virgin Islands National Park","18.33688305","-64.740011739034","Virgin Islands National Park, United States of America","boundary","national_park","0.79146640414423"
"Wind Cave National Park","43.5789475","-103.470656720908","Wind Cave National Park, State Highway 87, Custer County, South Dakota, United States of America","leisure","park","0.79784622341982"
"Yellowstone National Park","44.766607","-110.2340824","Yellowstone National Park, Park County, Wyoming, United States of America","leisure","nature_reserve","0.8577723806647"
"Yosemite National Park","37.8406798","-119.516626169942","Yosemite National Park, Mariposa County, California, United States of America","leisure","nature_reserve","0.83563787641991"
"Not found: Wrangell – St. Elias National Park and Preserve"
"Zion National Park","37.3190845","-113.004952668628","Zion National Park, West Rim Trail, Washington County, Utah, United States of America","leisure","nature_reserve","0.77519182185623"
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://d3js.org/topojson.v1.min.js" charset="utf-8"></script>
<script src="https://developer.mapsense.co/mapsense.js" charset="utf-8"></script>
<link type="text/css" href="https://developer.mapsense.co/mapsense.css" rel="stylesheet"/>
<link rel="stylesheet" href="https://developer.mapsense.co/stylesheets/bootstrap.min.css" media="screen" type="text/css">
<link rel="stylesheet" href="nocss.css" media="screen" type="text/css">
<style>
html, body, #myMap{
height: 100%;
width: 100%;
margin: 0; padding: 0;
font-family: sans-serif;
overflow: hidden;
}
#myMap {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
}
circle {
fill: rgba(68, 167, 228, 0.5); /*blue*/
stroke: none;
}
.faint { color: #555; }
.top-left {
position: absolute;
top: 5px;
left: 5px;
}
.btn {
background-color: rgba(255,255,255,0.8);
outline: 1px solid rgba(0,0,0,0.3);
min-width: 60px;
padding: 2px 4px;
margin: 2px;
display: inline-block;
}
.csv_point,
circle {
fill: rgba(152, 78, 163, 0.2);
stroke: rgba(152, 78, 163, 1);
stroke-width: 1;
}
.modal-dialog {
width: 400px;
text-align: center;
font-size: 20px;
}
.modal-body {
margin: 0 auto;
text-align: right;
width: 270px;
}
.lede {
position: absolute;
top: 0;
left: 0;
padding: 5px 10px;
background: rgba(255,255,255,0.5);
width: 100%;
}
.mapsense-attribution {
/* adjusted for less contrast */
background-color: rgba(255, 255, 255, 0.5);
color: #777;
position: absolute;
bottom: 0;
right: 0;
font-size: 12px;
font-family: sans-serif;
padding: 2px;
line-height: 1.2em;
text-decoration: none;
user-select: none;
cursor: default;
}
.mapsense-attribution a {
text-decoration: none;
color: #777;
}
.mapsense-attribution a:hover {
text-decoration: none;
color: #444;
}
.hoverFeature {
stroke-width: 2;
}
.popup {
position: absolute;
font-family: sans-serif;
font-size: 11px;
color: #666;
visibility: hidden;
border-radius: 3px;
pointer-events: none;
border: 1px solid #bbb;
padding: 8px;
background-color: rgba(255, 255, 255, .95);
max-height: 500px;
overflow: normal;
}
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid #ddd;
padding: 7px;
}
.detailKey {
background: #eee;
opacity: .8;
text-transform: uppercase;
font-weight: 600;
}
.detailVal {
background: rgba(255,255,255,0.8);
}
</style>
</head>
<body>
<div id="myMap"></div>
<div class="lede">
<div class="lede">
<p>Have a csv with latitude and longitude columns?
<br/>Drag it onto the map!</p>
<p class="faint">No csv file handy? <a href="example.csv">Sample here.</a></p>
</div>
<!-- Modal -->
<div id="fieldModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Pick fields</h4>
</div>
<div id="pickfields" class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn" data-dismiss="modal">Close</button>
<button type="button" class="btn" id="fields_picked">Map!</button>
</div>
</div>
</div>
</div>
<!-- /Modal -->
<script src='http://code.jquery.com/jquery-1.11.0.min.js' type="text/javascript"></script>
<script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js' type="text/javascript"></script>
<script src='dragdrop_csv.js' type="text/javascript"></script>
<script src='bounds.js' type="text/javascript"></script>
<script>
var my_key = "key-2d5eacd8b924489c8ed5e8418bd883bc";
var us = [ // reverse of NESW
{
lon: -124.85,
lat: 24.40
}, // west, south
{
lon: -66.88,
lat: 49.38
} // east, north
];
var home = [{
lon: -130,
lat: 20
}, {
lon: -60,
lat: 55
}];
var map = mapsense.map("#myMap"); //tell it where to go
map.add(
mapsense.basemap()
.apiKey(my_key)
.style("sketch")
)
.extent(home);
var CSV_LAYER;
// Add custom attribution
var attribution = mapsense.attribution('<a target="_blank" href="https://developer.mapsense.co/tileViewer/?tileset=mapsense.earth">©Mapsense ©OpenStreetMap</a>');
attribution.map(map);
// Process CSV
var processCsv = function(csvData) {
var first_line = csvData[0];
// If no lat, lon fields, then prompt user to pick lat/lon fields:
var latfield, lonfield, sizefield, labelfield;
// TODO: make this fuzzy match better
if (first_line.lat && first_line.lon) {
latfield = 'lat';
lonfield = 'lon';
console.log(latfield, lonfield, sizefield, labelfield);
mapCSV(csvData, latfield, lonfield, sizefield, labelfield);
} else if (first_line.latitude && first_line.longitude) {
latfield = 'latitude';
lonfield = 'longitude';
mapCSV(csvData, latfield, lonfield, sizefield, labelfield);
} else { // otherwise prompt user
var options = '<option value=""></option>';
for (key in first_line) {
options += '<option value="' + key + '">' + key + '</option>';
}
var pickfields = '';
pickfields += '<div>Location <select id="locfield">' + options + '</select></div>';
pickfields += '<div>Latitude: <select id="latfield">' + options + '</select></div>';
pickfields += '<div>Longitude: <select id="lonfield">' + options + '</select></div>';
pickfields += '<div>Size: <select id="sizefield">' + options + '</select></div>';
pickfields += '<div style="display: none;">Label: <select id="labelfield">' + options + '</select></div>';
$('#pickfields').html(pickfields);
$('#fieldModal').modal('show');
var guess_loc = ['zip', 'city', 'name', 'location', 'address'];
for (var i = 0; i < guess_loc.length; i++) {
var field = first_line[guess_loc[i]];
if (guess_loc.indexOf(field) >= 0) {
locfield = field;
}
}
if (first_line.y) locfield = 'y';
if (first_line.lat) locfield = 'lat';
if (first_line.latitude) locfield = 'latitude';
if (locfield) $('#locfield').val(locfield);
if (first_line.y) latfield = 'y';
if (first_line.lat) latfield = 'lat';
if (first_line.latitude) latfield = 'latitude';
if (latfield) $('#latfield').val(latfield);
if (first_line.x) lonfield = 'x';
if (first_line.lng) lonfield = 'lng';
if (first_line.lon) lonfield = 'lon';
if (first_line.longitude) lonfield = 'longitude';
if (lonfield) $('#lonfield').val(lonfield);
$('#fields_picked').click(function() {
latfield = $('#latfield').val();
lonfield = $('#lonfield').val();
sizefield = $('#sizefield').val();
labelfield = $('#labelfield').val();
$('#fieldModal').modal('hide');
mapCSV(csvData, latfield, lonfield, sizefield, labelfield);
});
}
};
function mapCSV(data, lat, lon, size, label) {
var geoJson = {
type: "FeatureCollection",
features: []
}; //init a geojson object
var gid = 0;
var max = -Infinity;
var min = Infinity;
for (var key in data) {
if (+data[key][size] > max) max = +data[key][size];
if (+data[key][size] < min) min = +data[key][size];
}
for (var key in data) {
gid += 1;
var radius = 10;
if (+data[key][size]) {
// convert value to percent(ish)
// and add 10 so visible
var s = +data[key][size];
radius = 10 + (40 * s / max);
console.log(s, radius, max);
}
data[key].label = data[key][label] || "name";
data[key].radius = radius;
data[key].gid = gid;
var feature = {
type: "Feature",
geometry: {
type: "Point",
"coordinates": [+data[key][lon], +data[key][lat]]
},
/*properties: {
label: data[key][label] || "name",
radius: radius
}*/
properties: data[key]
};
geoJson.features.push(feature);
}
CSV_LAYER = mapsense.geoJson()
.features(geoJson.features)
/*.selection(function(d){
d.attr("r", function(d){
console.log(d.properties.radius);
return d.properties.radius;
});
d.attr("class","csv_point");
d.attr("id",function(d){
return d.properties.label ? d.properties.label : "";
});
})*/
.selection(selection_function);
map.add(CSV_LAYER);
//.on("load", zoomBounds)
zoomBounds(geoJson);
}
function zoomBounds(e) {
map.extent(bounds(e.features)).zoomBy(-0.1);
}
var tooltip = d3.select('body')
.append("div")
.attr("class", "popup");
function isFloat(n) {
var r = Number(n) && n % 1 !== 0;
return r;
}
var selection_function = (function() {
var whitelist = [];
var id_field = 'gid';
//whitelist = ['population','female','male','hhi','layer','poverty','unemployment','uninsured','postal_code'];
/* The id of the previously hovered-over feature. */
var hoverId = null;
return function(s) {
s.attr("r", function(d) {
return d.properties.radius || 10;
})
.attr("class", function(d) {
var classes = ["mapFeatures"],
props = d.properties;
if (props) {
if (props.layer) classes.push(props.layer);
if (props.sub_layer) classes.push(props.sub_layer);
}
if (d.properties[id_field] !== null && hoverId !== null && d.properties[id_field] == hoverId) {
console.log(d.properties[id_field], hoverId);
classes.push("hoverFeature");
}
return classes.join(' ');
})
.on("mouseover", function(d) {
console.log(d);
//if ( d.properties.minz >= 5 ) {
d3.select(this).classed("selected", true);
//}
var text = "";
var value;
text += '<div class="detailCard"><table><tbody>';
if (whitelist.length > 0) {
for (var i = 0; i < whitelist.length; i++) {
key = whitelist[i];
if (d.properties && d.properties[key]) {
value = d.properties[key];
value = isFloat(value) ? value.toFixed(4) : value;
text += '<tr><td class="detailKey">' + key + '</td><td class="detailVal">' + value + '</td></tr>';
}
}
} else {
for (var key in d.properties) {
text += '<tr><td class="detailKey">' + key + '</td><td class="detailVal">' + d.properties[key] + '</td></tr>';
}
}
tooltip.html(text);
if (d.properties[id_field] !== hoverId) {
hoverId = d.properties[id_field];
CSV_LAYER.selection(selection_function);
}
return tooltip.style("visibility", "visible");
})
.on("mousemove", function() {
return tooltip.style("top", (d3.event.pageY - 0) + "px").style("left", (d3.event.pageX + 20) + "px");
})
.on("mouseout", function(d) {
d3.select(this).classed("selected", false);
return tooltip.style("visibility", "hidden");
});
};
})();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment