Created
October 2, 2014 04:16
-
-
Save djtfmartin/d9b0832a370606e79b60 to your computer and use it in GitHub Desktop.
ALA mapping example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
<title>ALA Occurrence Records Map Example</title> | |
<meta name="description" content=""> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> | |
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css"> | |
<style> | |
body { | |
padding-top: 50px; | |
padding-bottom: 20px; | |
} | |
.mapContainer { | |
height: 650px; | |
width: 100%; | |
} | |
/* typeahead styles */ | |
.typeahead, | |
.tt-query, | |
.tt-hint { | |
width: 396px; | |
height: 34px; | |
padding: 6px 12px; | |
font-size: 14px; | |
line-height: 1.42857143; | |
/* border: 2px solid #ccc;*/ | |
-webkit-border-radius: 8px; | |
-moz-border-radius: 8px; | |
border-radius: 8px; | |
outline: none; | |
} | |
.typeahead { | |
background-color: #fff; | |
} | |
.typeahead:focus { | |
border: 2px solid #0097cf; | |
} | |
.input-group > .twitter-typeahead > .form-control.tt-input { | |
-webkit-border-top-left-radius: 4px; | |
-webkit-border-bottom-left-radius: 4px; | |
-moz-border-radius-topleft: 4px; | |
-moz-border-radius-bottomleft: 4px; | |
border-top-left-radius: 4px; | |
border-bottom-left-radius: 4px; | |
} | |
.tt-query { | |
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
} | |
.tt-hint { | |
color: #999 | |
} | |
.tt-dropdown-menu { | |
width: 422px; | |
margin-top: 12px; | |
padding: 8px 0; | |
background-color: #fff; | |
border: 1px solid #ccc; | |
border: 1px solid rgba(0, 0, 0, 0.2); | |
-webkit-border-radius: 8px; | |
-moz-border-radius: 8px; | |
border-radius: 8px; | |
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); | |
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); | |
box-shadow: 0 5px 10px rgba(0, 0, 0, .2); | |
} | |
.tt-suggestion { | |
padding: 3px 20px; | |
font-size: 14px; | |
line-height: 20px; | |
} | |
.tt-suggestion.tt-cursor { | |
color: #fff; | |
background-color: #0097cf; | |
} | |
.tt-suggestion p { | |
margin: 0; | |
} | |
.twitter-typeahead { | |
width: 100%; | |
position: relative; | |
} | |
.twitter-typeahead .tt-query, | |
.twitter-typeahead .tt-hint { | |
margin-bottom: 0; | |
width: 100%; | |
height: 34px; | |
position: absolute; | |
top: 0; | |
left: 0; | |
} | |
.input-group .twitter-typeahead { | |
display: table-cell !important; | |
} | |
.twitter-typeahead .tt-hint { | |
color: #a1a1a1; | |
z-index: 1; | |
padding: 6px 12px; | |
border: 1px solid transparent; | |
} | |
.twitter-typeahead .tt-query { | |
z-index: 2; | |
border-radius: 4px !important; | |
/* add these 2 statements if you have an appended input group */ | |
border-top-right-radius: 0 !important; | |
border-bottom-right-radius: 0 !important; | |
/* add these 2 statements if you have an prepended input group */ | |
/* border-top-left-radius: 0!important; | |
border-bottom-left-radius: 0!important; */ | |
} | |
.tt-dropdown-menu { | |
min-width: 160px; | |
margin-top: 2px; | |
padding: 5px 0; | |
background-color: #fff; | |
border: 1px solid #ccc; | |
border: 1px solid rgba(0, 0, 0, .2); | |
*border-right-width: 2px; | |
*border-bottom-width: 2px; | |
-webkit-border-radius: 6px; | |
-moz-border-radius: 6px; | |
border-radius: 6px; | |
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); | |
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); | |
box-shadow: 0 5px 10px rgba(0, 0, 0, .2); | |
-webkit-background-clip: padding-box; | |
-moz-background-clip: padding; | |
background-clip: padding-box; | |
} | |
.tt-suggestion { | |
display: block; | |
padding: 3px 20px; | |
} | |
.tt-suggestion.tt-is-under-cursor { | |
color: #fff; | |
background-color: #0081c2; | |
background-image: -moz-linear-gradient(top, #0088cc, #0077b3); | |
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); | |
background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); | |
background-image: -o-linear-gradient(top, #0088cc, #0077b3); | |
background-image: linear-gradient(to bottom, #0088cc, #0077b3); | |
background-repeat: repeat-x; | |
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0) | |
} | |
.tt-suggestion.tt-is-under-cursor a { | |
color: #fff; | |
} | |
.tt-suggestion p { | |
margin: 0; | |
} | |
.queryRow .label { | |
opacity: 0.8; | |
} | |
.info { | |
padding:5px; | |
margin:10px 0; | |
-webkit-border-radius: 4px; | |
-moz-border-radius: 4px; | |
border-radius: 4px; | |
font-weight: bold; | |
} | |
.info span { | |
font-weight: normal; | |
} | |
#downloadUrl span { | |
font-family: "Lucida Console", Monaco, monospace; | |
font-size: 11px; | |
} | |
.form-horizontal .form-control { | |
padding: 4px 10px; | |
margin: 5px; | |
height: auto; | |
} | |
.control-label { | |
font-weight: normal; | |
} | |
.form-group { | |
margin: 0; | |
} | |
</style> | |
<link rel="stylesheet" type="text/css" href="http://dev.openlayers.org/theme/default/style.css"> | |
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script> | |
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> | |
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script> | |
<script src="http://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script> | |
<script type='text/javascript' src="http://dev.openlayers.org/OpenLayers.js"></script> | |
<script type="text/javascript"> | |
var map, ala_wms, boxLayer, polygonLayer, drawControls, wkt; | |
var alaBaseUrl = "http://biocache.ala.org.au/ws"; | |
var downloadPath = '/occurrences/index/download?'; | |
var downloadExtraParams = { | |
email: '', // email address of person (optional) | |
sourceTypeId: 0, // ALA records | |
reasonTypeId: 10, // use of data (see all values at http://logger.ala.org.au/service/logger/reasons) not optional | |
file: 'ala_occurrence_records', // filename of download | |
extra: 'dataResourceUid,dataResourceName.p' // additional fields to include in download | |
}; | |
var wmsBaseUrl = alaBaseUrl + "/mapping/wms/reflect"; // see http://api.ala.org.au/#ws9 for options | |
var defaultParamsObj = { | |
q: "*:*", // '*:* for all records OR species_group:Fish, etc | |
fq: '' // E.g. "geospatial_kosher:true" or "" | |
}; // constant | |
var searchParams = $.extend({}, defaultParamsObj); // clone obj - this one changes | |
var defaultENV = "name:circle;size:2;opacity:1.0"; | |
$(document).ready(function () { | |
map = new OpenLayers.Map("map", { | |
//controls: [new OpenLayers.Control.PanZoom()] | |
} ); | |
var ol_wms = new OpenLayers.Layer.WMS( | |
"OpenLayers WMS", | |
"http://vmap0.tiles.osgeo.org/wms/vmap0", | |
{layers: "basic"} | |
); | |
//var osm_layer = new OpenLayers.Layer.OSM( "Simple OSM Map" ); | |
var mapParams = { | |
layers: 'ALA:occurrences', | |
transparent: "true", | |
format: "image/png", | |
outline: false, | |
ENV: "color:ff0000;" + defaultENV //"colormode:grid" f49421 | |
} | |
ala_wms = new OpenLayers.Layer.WMS( | |
"Occurrence records", | |
wmsBaseUrl, | |
$.extend(mapParams, defaultParamsObj), | |
{ opacity: 0.8, isBaseLayer: false, visibility: true, sphericalMercator: true } | |
); | |
boxLayer = new OpenLayers.Layer.Vector("Box layer"); | |
polygonLayer = new OpenLayers.Layer.Vector("Polygon Layer"); | |
updateDownloadUrl(); | |
updateTotalRecords(); | |
map.addLayers([ol_wms, ala_wms, boxLayer, polygonLayer]); | |
map.addControl(new OpenLayers.Control.LayerSwitcher()); | |
map.addControl(new OpenLayers.Control.MousePosition()); | |
map.setCenter(new OpenLayers.LonLat(134, -25), 4); | |
drawControls = { | |
polygon: new OpenLayers.Control.DrawFeature(polygonLayer, | |
OpenLayers.Handler.Polygon), | |
box: new OpenLayers.Control.DrawFeature(boxLayer, | |
OpenLayers.Handler.RegularPolygon, { | |
handlerOptions: { | |
sides: 4, | |
irregular: true | |
} | |
} | |
) | |
}; | |
for (var key in drawControls) { | |
map.addControl(drawControls[key]); | |
var type = (key == 'box') ? 'create' : 'point'; | |
drawControls[key].handler.callbacks[type] = function(data) { | |
if (boxLayer.features.length > 0) { | |
boxLayer.removeAllFeatures(); | |
} | |
if (polygonLayer.features.length > 0) { | |
polygonLayer.removeAllFeatures(); | |
} | |
} | |
drawControls[key].events.register("featureadded", ' ' , function() { | |
searchParams.wkt = getBBoxWkt(); | |
//updateDownloadUrl(); | |
//updateTotalRecords(); | |
updatePanel(); | |
$('#clearFeature').removeClass('hide'); | |
}); | |
} | |
document.getElementById('noneToggle').checked = true; | |
wkt = new OpenLayers.Format.WKT(); | |
//updateLegend(defaultParamsObj); // inactive (hidden in DOM) | |
$(window).resize(function () { | |
$('#map').height($(window).height() - $(".navbar").height() | |
- parseInt($(".navbar").css("margin-bottom")) | |
- parseInt($(".navbar").css("margin-top")) | |
- parseInt($('#map').css("margin-bottom")) | |
); | |
}); | |
$(window).resize(); | |
var bieJson = new Bloodhound({ | |
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), | |
queryTokenizer: Bloodhound.tokenizers.whitespace, | |
//prefetch: '../data/films/post_1960.json', | |
remote: { | |
url: 'http://bie.ala.org.au/search/auto.jsonp?q=%QUERY', | |
filter: function (resp) { | |
var results = []; | |
$.each(resp.autoCompleteList, function(i, el) { | |
if (el.matchedNames.length > 0) { | |
results.push({name: el.matchedNames[0] }); | |
} else { | |
results.push({name: el.name }); | |
} | |
}); | |
//return resp.autoCompleteList; | |
return results; | |
}, | |
ajax: { dataType: 'jsonp' }} | |
}); | |
bieJson.initialize(); | |
var ta = $('.typeahead').typeahead(null, { | |
name: 'species-lookup', | |
displayKey: 'name', | |
source: bieJson.ttAdapter() | |
}).on('typeahead:autocompleted typeahead:selected', function (obj, datum) { | |
//console.log('typeahead:autocompleted', obj, datum); | |
$('#lsid').val(datum.guid); | |
}).on('typeahead:cursorchanged', function () { | |
//console.log('typeahead:cursorchanged'); | |
$('#lsid').val(''); | |
}); | |
// on submit | |
$('#searchForm').submit(function (e) { | |
e.preventDefault(); | |
var name = $('#query').val(); | |
if (name) { | |
lookupTaxaGuid(name); | |
//reset typeahead | |
$('#query').val(''); | |
$('.typeahead').typeahead('close'); | |
} | |
}); | |
// remove species | |
$(document).on('click', '.removeItem', function (e) { | |
$(this).closest('tr').remove(); | |
updateMap(); | |
}); | |
$('#vectorInfo').click(function(e) { | |
if (confirm('Do you want to download all ' + $('#totalRecords').text() + ' records?')) { | |
window.location.href = $('#downloadUrl span').text(); | |
} | |
}); | |
$('#clearFeature').click(function(e) { | |
searchParams.wkt = ''; | |
updatePanel(true); | |
$(this).addClass('hide'); | |
}); | |
//$('input[name="type"]').change(function(e) { | |
$(document).on('change', 'input[name="type"]', function (e) { | |
var type = $(this).val(); | |
if (type != 'none') { | |
updatePanel(true); | |
} | |
var element = this; | |
for (key in drawControls) { | |
var control = drawControls[key]; | |
if (element.value == key && element.checked) { | |
control.activate(); | |
} else { | |
control.deactivate(); | |
} | |
} | |
}); | |
// date filtering | |
$('.dataRange').change(function() { | |
var thisDate = $(this).val(); | |
var date_regex = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/; // YYYY-MM-DD | |
if (!thisDate || (thisDate && date_regex.test(thisDate))) { | |
// date good | |
$(this).closest('.form-group').removeClass('has-error'); | |
updateMap(); | |
} else { | |
// error | |
alert('date is not provided in the expected format (YYYY-MM-DD)'); | |
$(this).closest('.form-group').addClass('has-error'); | |
} | |
}); | |
}); | |
function getAlaWmsBaseurl() { | |
var mappingUrl = "http://biocache.ala.org.au/ws"; | |
return mappingUrl + "/webportal/wms/reflect" + params; | |
} | |
function getBBoxWkt() { | |
var str = ''; | |
if (boxLayer.features[0]) { | |
str = wkt.write(boxLayer.features[0]); | |
} else if (polygonLayer.features[0]) { | |
str = wkt.write(polygonLayer.features[0]); | |
} | |
return str; | |
} | |
function updateDownloadUrl() { | |
//console.log('searchParams', searchParams); | |
var dlParams = $.extend({}, searchParams, downloadExtraParams); | |
var url = alaBaseUrl + downloadPath + $.param(dlParams); | |
$('#downloadUrl span').text(url); | |
} | |
function updateTotalRecords() { | |
var url = alaBaseUrl + '/occurrences/search.json?' + $.param(searchParams) + '&pageSize=0&facet=off&callback=?'; | |
$.getJSON(url, function (data) { | |
var total = data.totalRecords; | |
try { | |
total = total.toLocaleString(); | |
} catch (e) { | |
// return e.name === "RangeError"; | |
} | |
$('#totalRecords').text(total); | |
}); | |
} | |
function updateMap() { | |
var queries = []; | |
$('.queryRow .taxonName').each(function (i, el) { | |
var name = $(this).text(); | |
var guid = $(this).data('guid'); | |
if (guid) { | |
queries.push("lsid:" + guid); | |
} else { | |
queries.push("text:" + name); | |
} | |
}); | |
var newParams = $.extend({}, searchParams, defaultParamsObj); // take a copy | |
if (queries.length > 0) { | |
//console.log('queries', queries); | |
newParams.q = queries.join(" OR "); | |
newParams.ENV = "colormode:species_guid;" + defaultENV; | |
} else { | |
newParams.ENV = "color:ff0000;" + defaultENV; | |
$('#firstRow').show(); | |
} | |
var startDate = $('#startDate').val(); | |
var endDate = $('#endDate').val(); | |
var isoSuffix = 'T00:00:00Z'; | |
if (startDate || endDate) { | |
var start = (startDate) ? startDate + isoSuffix : '*'; | |
var end = (endDate) ? endDate + isoSuffix : '*'; | |
newParams.fq = 'occurrence_date:[' + start + ' TO ' + end + ']'; | |
} else { | |
newParams.fq = ''; | |
} | |
searchParams.q = newParams.q; | |
searchParams.fq = newParams.fq; | |
ala_wms.mergeNewParams(newParams); | |
updatePanel(); | |
//updateLegend(newParams); | |
} | |
function lookupTaxaGuid(name) { | |
var url = 'http://bie.ala.org.au/ws/guid/batch.json?q=' + name + '&callback=?'; // q= | |
$.getJSON(url, function (data) { | |
var items = []; | |
$.each(data, function (key, val) { | |
//console.log('hit', key, val); | |
if (val[0] && val[0].identifier) { | |
//console.log('val', val[0].identifier); | |
updateSpeciesTable(val[0].name, val[0].identifier) | |
} else { | |
updateSpeciesTable(name, '') | |
} | |
}); | |
updateMap(); | |
}); | |
} | |
function updateSpeciesTable(name, guid) { | |
$('#firstRow').hide(); | |
var tmpl = $('.rowTemplate').clone(); | |
tmpl.removeClass('hide').removeClass('rowTemplate').addClass('queryRow'); | |
tmpl.find('.taxonName').html(name); | |
if (guid) { | |
tmpl.find('.taxonName').data('guid', guid); | |
tmpl.find('.matched').removeClass('hide'); | |
} else { | |
tmpl.find('.taxonName').data('guid', ''); | |
tmpl.find('.unmatched').removeClass('hide'); | |
} | |
//console.log('params', name, guid); | |
$('#results tbody').append(tmpl); | |
//$('#results tbody').append('<tr><td data-guid="">' + name + '</td><td><button class="btn btn-default btn-xs" title="remove item"><span class="glyphicon glyphicon-remove"></span> </button></td></tr>'); | |
} | |
function updatePanel(removeFeature) { | |
if (removeFeature) { | |
boxLayer.removeAllFeatures(); | |
polygonLayer.removeAllFeatures(); | |
searchParams.wkt = ''; | |
} | |
updateTotalRecords(); | |
updateDownloadUrl(); | |
} | |
function updateLegend(params) { | |
$('#legend span').html('<img id="gridLegendImg" src="' + alaBaseUrl + '/density/legend?' + $.param(params) + '"/>'); | |
} | |
</script> | |
</head> | |
<body> | |
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation"> | |
<div class="container-fluid"> | |
<div class="navbar-header"> | |
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> | |
<span class="sr-only">Toggle navigation</span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
</button> | |
<a class="navbar-brand" href="#">ALA map demo</a> | |
</div> | |
<div class="navbar-collapse collapse"> | |
<form class="hide navbar-form navbar-right" role="form"> | |
<div class="form-group"> | |
<input type="text" placeholder="Email" class="form-control"> | |
</div> | |
<div class="form-group"> | |
<input type="password" placeholder="Password" class="form-control"> | |
</div> | |
<button type="submit" class="btn btn-success">Sign in</button> | |
</form> | |
</div> | |
<!--/.navbar-collapse --> | |
</div> | |
</div> | |
<div class="container-fluid"> | |
<!-- Example row of columns --> | |
<div class="row"> | |
<div class="col-md-4 sidebar"> | |
<h3>Step 2: Create a subset</h3> | |
<form id="searchForm"> | |
<div class="input-group"> | |
<input type="text" id="query" class="form-control typeahead" value="" | |
placeholder="Search for species"/> | |
<input type="hidden" id="lsid" value=""/> | |
<span class="input-group-btn"> | |
<button class="btn btn-default" type="submit" id="searchBtn">Add</button> | |
</span> | |
</div> | |
<!-- /input-group --> | |
</form> | |
<div> </div> | |
<table id="results" class="table table-bordered table-striped"> | |
<thead> | |
<tr> | |
<th>Species</th> | |
</tr> | |
<tbody> | |
<tr id='firstRow'> | |
<td style="color:#999;">Currently showing all records. Use the search box above to filter by a species or higher taxon</td> | |
</tr> | |
<tr class="hide rowTemplate"> | |
<td> | |
<span class="taxonName"></span> | |
<span class="hide label label-success matched">Matched name</span> | |
<span class="hide label label-warning unmatched">Unmatched name</span> | |
<button class="removeItem btn btn-default btn-xs pull-right" title="remove item"> | |
<span class="glyphicon glyphicon-remove"></span> | |
</button> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<div class="form-group"> | |
<b>Map control</b> | |
<button id="clearFeature" class="hide btn btn-info pull-right" title="clear bounding box"> | |
<span class="glyphicon glyphicon-remove-circle"></span> Clear bounding box | |
</button> | |
<div class="radio"> | |
<label> | |
<input type="radio" name="type" id="noneToggle" value="none" checked> | |
Navigate map | |
</label> | |
</div> | |
<div class="radio"> | |
<label> | |
<input type="radio" name="type" id="boxToggle" value="box" > | |
Draw box | |
</label> | |
</div> | |
<div class="radio"> | |
<label> | |
<input type="radio" name="type" id="polygonToggle" value="polygon"> | |
Draw polygon | |
</label> | |
</div> | |
</div> | |
<form class="form-horizontal" role="form"> | |
<!--Filter by date: <b>1900</b> <input id="dateRange" type="text" class="span2" value="" data-slider-min="1900" data-slider-max="2015" data-slider-step="5" data-slider-value="[2000,2015]"/> <b>2015</b>--> | |
<b>Date (UTC)</b><br/> | |
between<br> | |
<div class="form-group "> | |
<label class="control-label col-sm-3" for="startDate">start date</label> | |
<div class="col-sm-6"> | |
<input type="text" id="startDate" class="dataRange form-control" value="" placeholder="yyyy-mm-dd"/> | |
</div> | |
</div> | |
<div class="form-group "> | |
<label class="control-label col-sm-3" for="endDate">end date</label> | |
<div class="col-sm-6"> | |
<input type="text" id="endDate" class="dataRange form-control" value="" placeholder="yyyy-mm-dd"/> | |
</div> | |
</div> | |
</form> | |
<div class="hide" id="legend">Record density legend:<br/><span></span></div> | |
<div class="info bg-danger"> | |
Total records: <span id="totalRecords"></span> | |
</div> | |
<div class="info bg-info" id="downloadUrl" style="word-wrap:break-word;"> | |
download URL: <span></span> | |
</div> | |
<button id="vectorInfo" class="btn btn-default btn-sm" title="get vector info"> | |
Next <span class="glyphicon glyphicon-forward"></span> | |
</button> | |
</div> | |
<div class="col-md-8 main"> | |
<div id="map" class="mapContainer"></div> | |
</div> | |
</div> | |
<!-- ><hr> | |
<footer> | |
<p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/deed.en_US">Creative Commons Attribution 3.0 Unported License</a></p> | |
</footer> --> | |
</div> | |
<!-- /container --> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment