diff --git a/static/site.js b/static/site.js
index 4ba407e..3f86f68 100644
--- a/static/site.js
+++ b/static/site.js
@@ -217,4 +217,17 @@ $( function() {
alert("Browser doesn't support geolocation!");
}
});
-});
\ No newline at end of file
+});
+
+String.prototype.truncate = String.prototype.truncate ||
+function ( n, useWordBoundary ){
+ if (this.length <= n) { return this; }
+ const subString = this.substr(0, n-1); // the original check
+ return (useWordBoundary
+ ? subString.substr(0, subString.lastIndexOf(" "))
+ : subString) + "…";
+};
+
+function scroll_to_element(element, complete) {
+ $('html, body').animate({ scrollTop: element.offset().top }, { duration: 'slow', complete: complete });
+}
\ No newline at end of file
diff --git a/static/svg-icon.js b/static/svg-icon.js
new file mode 100644
index 0000000..e01f576
--- /dev/null
+++ b/static/svg-icon.js
@@ -0,0 +1,199 @@
+//Leaflet-SVGIcon
+//SVG icon for any marker class
+//Ilya Atkin
+//ilya.atkin@unh.edu
+
+L.DivIcon.SVGIcon = L.DivIcon.extend({
+ options: {
+ "circleText": "",
+ "className": "svg-icon",
+ "circleAnchor": null, //defaults to [iconSize.x/2, iconSize.x/2]
+ "circleColor": null, //defaults to color
+ "circleOpacity": null, // defaults to opacity
+ "circleFillColor": "rgb(255,255,255)",
+ "circleFillOpacity": null, //default to opacity
+ "circleRatio": 0.5,
+ "circleWeight": null, //defaults to weight
+ "color": "rgb(0,102,255)",
+ "fillColor": null, // defaults to color
+ "fillOpacity": 0.4,
+ "fontColor": "rgb(0, 0, 0)",
+ "fontOpacity": "1",
+ "fontSize": null, // defaults to iconSize.x/4
+ "fontWeight": "normal",
+ "iconAnchor": null, //defaults to [iconSize.x/2, iconSize.y] (point tip)
+ "iconSize": L.point(32,48),
+ "opacity": 1,
+ "popupAnchor": null,
+ "weight": 2
+ },
+ initialize: function(options) {
+ options = L.Util.setOptions(this, options)
+
+ //iconSize needs to be converted to a Point object if it is not passed as one
+ options.iconSize = L.point(options.iconSize)
+
+ //in addition to setting option dependant defaults, Point-based options are converted to Point objects
+ if (!options.circleAnchor) {
+ options.circleAnchor = L.point(Number(options.iconSize.x)/2, Number(options.iconSize.x)/2)
+ }
+ else {
+ options.circleAnchor = L.point(options.circleAnchor)
+ }
+ if (!options.circleColor) {
+ options.circleColor = options.color
+ }
+ if (!options.circleFillOpacity) {
+ options.circleFillOpacity = options.opacity
+ }
+ if (!options.circleOpacity) {
+ options.circleOpacity = options.opacity
+ }
+ if (!options.circleWeight) {
+ options.circleWeight = options.weight
+ }
+ if (!options.fillColor) {
+ options.fillColor = options.color
+ }
+ if (!options.fontSize) {
+ options.fontSize = Number(options.iconSize.x/4)
+ }
+ if (!options.iconAnchor) {
+ options.iconAnchor = L.point(Number(options.iconSize.x)/2, Number(options.iconSize.y))
+ }
+ else {
+ options.iconAnchor = L.point(options.iconAnchor)
+ }
+ if (!options.popupAnchor) {
+ options.popupAnchor = L.point(0, (-0.75)*(options.iconSize.y))
+ }
+ else {
+ options.popupAnchor = L.point(options.popupAnchor)
+ }
+
+ options.html = this._createSVG()
+ },
+ _createCircle: function() {
+ var cx = Number(this.options.circleAnchor.x)
+ var cy = Number(this.options.circleAnchor.y)
+ var radius = this.options.iconSize.x/2 * Number(this.options.circleRatio)
+ var fill = this.options.circleFillColor
+ var fillOpacity = this.options.circleFillOpacity
+ var stroke = this.options.circleColor
+ var strokeOpacity = this.options.circleOpacity
+ var strokeWidth = this.options.circleWeight
+ var className = this.options.className + "-circle"
+
+ var circle = ''
+
+ return circle
+ },
+ _createPathDescription: function() {
+ var height = Number(this.options.iconSize.y)
+ var width = Number(this.options.iconSize.x)
+ var weight = Number(this.options.weight)
+ var margin = weight / 2
+
+ var startPoint = "M " + margin + " " + (width/2) + " "
+ var leftLine = "L " + (width/2) + " " + (height - weight) + " "
+ var rightLine = "L " + (width - margin) + " " + (width/2) + " "
+ var arc = "A " + (width/4) + " " + (width/4) + " 0 0 0 " + margin + " " + (width/2) + " Z"
+
+ var d = startPoint + leftLine + rightLine + arc
+
+ return d
+ },
+ _createPath: function() {
+ var pathDescription = this._createPathDescription()
+ var strokeWidth = this.options.weight
+ var stroke = this.options.color
+ var strokeOpacity = this.options.opacity
+ var fill = this.options.fillColor
+ var fillOpacity = this.options.fillOpacity
+ var className = this.options.className + "-path"
+
+ var path = ''
+
+ return path
+ },
+ _createSVG: function() {
+ var path = this._createPath()
+ var circle = this._createCircle()
+ var text = this._createText()
+ var className = this.options.className + "-svg"
+
+ var style = "width:" + this.options.iconSize.x + "px; height:" + this.options.iconSize.y + "px;"
+
+ var svg = ''
+
+ return svg
+ },
+ _createText: function() {
+ var fontSize = this.options.fontSize + "px"
+ var fontWeight = this.options.fontWeight
+ var lineHeight = Number(this.options.fontSize)
+
+ var x = this.options.circleAnchor.x
+ var y = this.options.circleAnchor.y + (lineHeight * 0.35) //35% was found experimentally
+ var circleText = this.options.circleText
+ var textColor = this.options.fontColor.replace("rgb(", "rgba(").replace(")", "," + this.options.fontOpacity + ")")
+
+ var text = '' + circleText + ''
+
+ return text
+ }
+})
+
+L.divIcon.svgIcon = function(options) {
+ return new L.DivIcon.SVGIcon(options)
+}
+
+L.Marker.SVGMarker = L.Marker.extend({
+ options: {
+ "iconFactory": L.divIcon.svgIcon,
+ "iconOptions": {}
+ },
+ initialize: function(latlng, options) {
+ options = L.Util.setOptions(this, options)
+ options.icon = options.iconFactory(options.iconOptions)
+ this._latlng = latlng
+ },
+ onAdd: function(map) {
+ L.Marker.prototype.onAdd.call(this, map)
+ },
+ setStyle: function(style) {
+ if (this._icon) {
+ var svg = this._icon.children[0]
+ var iconBody = this._icon.children[0].children[0]
+ var iconCircle = this._icon.children[0].children[1]
+
+ if (style.color && !style.iconOptions) {
+ var stroke = style.color.replace("rgb","rgba").replace(")", ","+this.options.icon.options.opacity+")")
+ var fill = style.color.replace("rgb","rgba").replace(")", ","+this.options.icon.options.fillOpacity+")")
+ iconBody.setAttribute("stroke", stroke)
+ iconBody.setAttribute("fill", fill)
+ iconCircle.setAttribute("stroke", stroke)
+
+ this.options.icon.fillColor = fill
+ this.options.icon.color = stroke
+ this.options.icon.circleColor = stroke
+ }
+ if (style.opacity) {
+ this.setOpacity(style.opacity)
+ }
+ if (style.iconOptions) {
+ if (style.color) { style.iconOptions.color = style.color }
+ var iconOptions = L.Util.setOptions(this.options.icon, style.iconOptions)
+ this.setIcon(L.divIcon.svgIcon(iconOptions))
+ }
+ }
+ }
+})
+
+L.marker.svgMarker = function(latlng, options) {
+ return new L.Marker.SVGMarker(latlng, options)
+}
diff --git a/templates/_macros.html b/templates/_macros.html
index 69d3a4a..89b1669 100644
--- a/templates/_macros.html
+++ b/templates/_macros.html
@@ -540,7 +540,7 @@ $( function() {
{% macro render_pagination(pagination) %}
{% if 'prev_url' in pagination or 'next_url' in pagination %}
-