forked from NCEAS/metacatui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support flying to a user-entered Lat,Long pair
fixes NCEAS#2246
- Loading branch information
Showing
10 changed files
with
568 additions
and
13 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<div class="<%= classNames.baseClass %>"> | ||
<h2>View finder</h2> | ||
<span>Search for a latitude and longitude pair and click the "search" button to show that point on the map.</span> | ||
<br /><br /> | ||
<div class="view-finder__form-field"> | ||
<div class="view-finder__field"> | ||
<input class="<%= classNames.input %>" type="text" placeholder="<%= placeholder %>" value="<%= inputValue %>" /> | ||
<button class="<%= classNames.button %>"> | ||
<i class="icon icon-search"></i> | ||
</button> | ||
</div> | ||
|
||
<% if(errorMessage) { %> | ||
<div class="view-finder__error"> | ||
<%= errorMessage %> | ||
</div> | ||
<% } %> | ||
</div> | ||
</div> |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
"use strict"; | ||
|
||
define([ | ||
"backbone", | ||
"text!templates/maps/view-finder.html", | ||
], ( | ||
Backbone, | ||
Template, | ||
) => { | ||
/** | ||
* @class ViewFinderView | ||
* @classdesc The ViewFinderView allows a user to search for a latitude and longitude in the map view. | ||
* @classcategory Views/Maps | ||
* @name ViewFinderView | ||
* @extends Backbone.View | ||
* @screenshot views/maps/ViewFinderView.png | ||
* @since 2.27.1 | ||
* @constructs ViewFinderView | ||
*/ | ||
var ViewFinderView = Backbone.View.extend({ | ||
/** | ||
* The type of View this is | ||
* @type {string} | ||
*/ | ||
type: "ViewFinderView", | ||
|
||
/** | ||
* The HTML classes to use for this view's element | ||
* @type {string} | ||
*/ | ||
className: classNames.baseClass, | ||
|
||
/** | ||
* The events this view will listen to and the associated function to call. | ||
* @type {Object} | ||
*/ | ||
events: { | ||
[`click .${classNames.button}`]: 'search', | ||
[`keyup .${classNames.input}`]: 'keyup', | ||
}, | ||
|
||
/** | ||
* Values meant to be used by the rendered HTML template. | ||
*/ | ||
templateVars: { | ||
errorMessage: "", | ||
inputValue: "", | ||
placeholder: "Search by latitude and longitude", | ||
classNames, | ||
}, | ||
|
||
/** | ||
* @typedef {Object} ViewFinderViewOptions | ||
* @property {Map} The Map model associated with this view allowing control | ||
* of panning to different locations on the map. | ||
*/ | ||
initialize(options) { | ||
this.mapModel = options.model; | ||
}, | ||
|
||
render() { | ||
this.focusInput(); | ||
|
||
this.el.innerHTML = _.template(Template)(this.templateVars); | ||
}, | ||
|
||
/** | ||
* Focus the input field on a delay to allow for the input to be | ||
* visible on the page before attempting to focus. | ||
*/ | ||
focusInput() { | ||
_.defer(() => { | ||
const input = this.getInput(); | ||
input.focus(); | ||
// Move cursor to end of input. | ||
input.val(""); | ||
input.val(this.templateVars.inputValue); | ||
}); | ||
}, | ||
|
||
getInput() { | ||
return this.$el.find(`.${classNames.input}`); | ||
}, | ||
|
||
getButton() { | ||
return this.$el.find(`.${classNames.button}`); | ||
}, | ||
|
||
/** Event handler for Backbone.View configuration. */ | ||
keyup(event) { | ||
this.templateVars.inputValue = this.getInput().val(); | ||
if (event.key === "Enter") { | ||
this.search(); | ||
} | ||
}, | ||
|
||
/** Event handler for Backbone.View configuration. */ | ||
search() { | ||
this.clearError(); | ||
|
||
const coords = this.parseValue(this.templateVars.inputValue) | ||
if (!coords) return; | ||
|
||
this.model.zoomTo({ ...coords, height: 321321 /* meters */ }); | ||
}, | ||
|
||
/** | ||
* Parse the user's input as a pair of floating point numbers. Log errors to the UI | ||
* @return {{Number,Number}|undefined} Undefined represents an irrecoverable user input, | ||
* otherwise returns a latitude, longitude pair. | ||
*/ | ||
parseValue(value) { | ||
const matches = value.match(floatsRegex); | ||
const hasBannedChars = value.match(bannedCharactersRegex) != null; | ||
if (matches?.length !== 2 || isNaN(matches[0]) || isNaN(matches[1]) || hasBannedChars) { | ||
this.setError("Try entering a search query with two numerical values representing a latitude and longitude (e.g. 64.84, -147.72)."); | ||
return; | ||
} | ||
|
||
const latitude = Number(matches[0]); | ||
const longitude = Number(matches[1]); | ||
if (latitude > 90 || latitude < -90) { | ||
this.setError("Latitude values outside of the range of -90 to 90 may behave unexpectedly."); | ||
} else if (longitude > 180 || longitude < -180) { | ||
this.setError("Longitude values outside of the range of -180 to 180 may behave unexpectedly."); | ||
} | ||
|
||
return { latitude, longitude }; | ||
}, | ||
|
||
clearError() { | ||
this.setError(""); | ||
}, | ||
|
||
setError(errorMessage) { | ||
this.templateVars.errorMessage = errorMessage; | ||
this.render(); | ||
}, | ||
}); | ||
|
||
return ViewFinderView; | ||
}); | ||
|
||
// Regular expression matching a string that contains two numbers optionally separated by a comma. | ||
const floatsRegex = /[+-]?[0-9]*[.]?[0-9]+/g; | ||
|
||
// Regular expression matching everything except numbers, periods, and commas. | ||
const bannedCharactersRegex = /[^0-9,.+-\s]/g; | ||
|
||
// Class names that correspond to elements in the template. | ||
const classNames = { | ||
baseClass: 'view-finder', | ||
button: "view-finder__button", | ||
input: "view-finder__input", | ||
}; |
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
Oops, something went wrong.