diff --git a/src/mmw/js/src/core/models.js b/src/mmw/js/src/core/models.js
index e9710c23b..c5f343ff4 100644
--- a/src/mmw/js/src/core/models.js
+++ b/src/mmw/js/src/core/models.js
@@ -22,7 +22,8 @@ var MapModel = Backbone.Model.extend({
geolocationEnabled: true,
previousAreaOfInterest: null,
dataCatalogResults: null, // GeoJSON array
- dataCatalogActiveResult: null // GeoJSON
+ dataCatalogActiveResult: null, // GeoJSON
+ selectedGeocoderArea: null, // GeoJSON
},
revertMaskLayer: function() {
diff --git a/src/mmw/js/src/core/views.js b/src/mmw/js/src/core/views.js
index 226d03b83..0ec2f0dc7 100644
--- a/src/mmw/js/src/core/views.js
+++ b/src/mmw/js/src/core/views.js
@@ -44,6 +44,16 @@ var dataCatalogActiveStyle = {
fillOpacity: 0.2
};
+var selectedGeocoderAreaStyle = {
+ stroke: true,
+ fill: true,
+ weight: 3,
+ opacity: 0.5,
+ fillOpacity: 0.2,
+ fillColor: '#E77471',
+ color: '#E77471'
+};
+
var RootView = Marionette.LayoutView.extend({
el: 'body',
ui: {
@@ -195,7 +205,8 @@ var MapView = Marionette.ItemView.extend({
'change:size': 'toggleMapSize',
'change:maskLayerApplied': 'toggleMask',
'change:dataCatalogResults': 'renderDataCatalogResults',
- 'change:dataCatalogActiveResult': 'renderDataCatalogActiveResult'
+ 'change:dataCatalogActiveResult': 'renderDataCatalogActiveResult',
+ 'change:selectedGeocoderArea': 'renderSelectedGeocoderArea',
},
// L.Map instance.
@@ -209,9 +220,15 @@ var MapView = Marionette.ItemView.extend({
// L.FeatureGroup instance.
_modificationsLayer: null,
+ // Shapes for the active data catalog tab's results.
+ // L.FeatureGroup instance
_dataCatalogResultsLayer: null,
_dataCatalogActiveLayer: null,
+ // The shape for a selected geocoder boundary result
+ // L.FeatureGroup instance
+ _selectedGeocoderAreaLayer: null,
+
// Flag used to determine if AOI change should trigger a prompt.
_areaOfInterestSet: false,
_didRevert: false,
@@ -242,6 +259,7 @@ var MapView = Marionette.ItemView.extend({
this._modificationsLayer = new L.FeatureGroup();
this._dataCatalogResultsLayer = new L.FeatureGroup();
this._dataCatalogActiveLayer = new L.FeatureGroup();
+ this._selectedGeocoderAreaLayer = new L.FeatureGroup();
this.fitToDefaultBounds();
@@ -281,6 +299,7 @@ var MapView = Marionette.ItemView.extend({
map.addLayer(this._modificationsLayer);
map.addLayer(this._dataCatalogResultsLayer);
map.addLayer(this._dataCatalogActiveLayer);
+ map.addLayer(this._selectedGeocoderAreaLayer);
},
fitToDefaultBounds: function() {
@@ -701,6 +720,20 @@ var MapView = Marionette.ItemView.extend({
this._dataCatalogActiveLayer.addLayer(layer);
}
}
+ },
+
+ renderSelectedGeocoderArea: function() {
+ var geom = this.model.get('selectedGeocoderArea');
+
+ this._selectedGeocoderAreaLayer.clearLayers();
+
+ if (geom) {
+ this.disableGeolocation();
+
+ var layer = new L.GeoJSON(geom, { style: selectedGeocoderAreaStyle });
+ this._leafletMap.fitBounds(layer.getBounds(), { reset: true });
+ this._selectedGeocoderAreaLayer.addLayer(layer);
+ }
}
});
diff --git a/src/mmw/js/src/draw/controllers.js b/src/mmw/js/src/draw/controllers.js
index d4327cf1d..aeabfc230 100644
--- a/src/mmw/js/src/draw/controllers.js
+++ b/src/mmw/js/src/draw/controllers.js
@@ -20,7 +20,10 @@ var DrawController = {
toolbarModel.set('predefinedShapeTypes',
_.filter(settings.get('boundary_layers'), { selectable: true }));
- App.rootView.geocodeSearchRegion.show(geocodeSearch);
+ if (!App.rootView.geocodeSearchRegion.hasView()) {
+ App.rootView.geocodeSearchRegion.show(geocodeSearch);
+ }
+
App.rootView.sidebarRegion.show(new views.DrawWindow({
model: toolbarModel
}));
diff --git a/src/mmw/js/src/draw/views.js b/src/mmw/js/src/draw/views.js
index 9056b4458..e6088b519 100644
--- a/src/mmw/js/src/draw/views.js
+++ b/src/mmw/js/src/draw/views.js
@@ -1114,6 +1114,8 @@ module.exports = {
DrawWindow: DrawWindow,
getShapeAndAnalyze: getShapeAndAnalyze,
addLayer: addLayer,
+ validateShape: validateShape,
+ displayAlert: displayAlert,
clearAoiLayer: clearAoiLayer,
selectBoundary: selectBoundary,
drawArea: drawArea,
diff --git a/src/mmw/js/src/geocode/models.js b/src/mmw/js/src/geocode/models.js
index 1ea27252b..64fd35ce3 100644
--- a/src/mmw/js/src/geocode/models.js
+++ b/src/mmw/js/src/geocode/models.js
@@ -7,6 +7,7 @@ var _ = require('underscore'),
var GeocoderModel = Backbone.Model.extend({
defaults: {
+ selectedSuggestion: null, // SuggestionModel
query: ''
}
});
diff --git a/src/mmw/js/src/geocode/templates/search.html b/src/mmw/js/src/geocode/templates/search.html
index f0c3022bf..c29c53c11 100644
--- a/src/mmw/js/src/geocode/templates/search.html
+++ b/src/mmw/js/src/geocode/templates/search.html
@@ -1,5 +1,14 @@
-
+
+{% if selectedSuggestion and selectedSuggestion.get('isBoundaryLayer') %}
+
+{% endif %}
diff --git a/src/mmw/js/src/geocode/views.js b/src/mmw/js/src/geocode/views.js
index 772d08fd1..fcad91fec 100644
--- a/src/mmw/js/src/geocode/views.js
+++ b/src/mmw/js/src/geocode/views.js
@@ -5,13 +5,16 @@ var _ = require('underscore'),
Backbone = require('../../shim/backbone'),
Marionette = require('../../shim/backbone.marionette'),
App = require('../app'),
+ router = require('../router').router,
drawViews = require('../draw/views'),
+ modalModels = require('../core/modals/models'),
models = require('./models'),
geocoderTmpl = require('./templates/geocoder.html'),
searchTmpl = require('./templates/search.html'),
suggestionsTmpl = require('./templates/suggestions.html');
-var ENTER_KEYCODE = 13;
+var ENTER_KEYCODE = 13,
+ ESC_KEYCODE = 27;
var ICON_BASE = 'search-icon fa ',
ICON_DEFAULT = 'fa-search',
@@ -24,20 +27,31 @@ var MSG_DEFAULT = '',
MSG_ERROR = 'Oops! Something went wrong.';
-function addBoundaryLayer(model) {
+function addBoundaryLayer(suggestionModel, shape) {
+ var layerCode = suggestionModel.get('code'),
+ shapeId = suggestionModel.get('id'),
+ shapeName = suggestionModel.get('text'),
+ layerName = suggestionModel.get('label'),
+ wkaoi = layerCode + '__' + shapeId;
+
+ drawViews.addLayer(shape, shapeName, layerName, wkaoi);
+}
+
+function addGeocoderBoundaryLayer(suggestionModel) {
App.restApi.getPolygon({
- layerCode: model.get('code'),
- shapeId: model.get('id')
+ layerCode: suggestionModel.get('code'),
+ shapeId: suggestionModel.get('id')
})
.then(function(shape) {
- drawViews.addLayer(shape);
+ App.map.set('selectedGeocoderArea', shape);
});
}
function selectSearchSuggestion(model) {
model.setMapViewToLocation();
if (model.get('isBoundaryLayer')) {
- addBoundaryLayer(model);
+ addGeocoderBoundaryLayer(model);
+ router.navigate('draw/', { trigger: true });
} else {
drawViews.clearAoiLayer();
}
@@ -68,22 +82,28 @@ var SearchBoxView = Marionette.LayoutView.extend({
'searchIcon': '.search-icon',
'message': '.message',
'messageDismiss': '.dismiss',
- 'resultsRegion': '#geocode-search-results-region'
+ 'resultsRegion': '#geocode-search-results-region',
+ 'selectButton': '.search-select-btn'
},
events: {
'keyup @ui.searchBox': 'processSearchInputEvent',
'click @ui.messageDismiss': 'dismissAction',
+ 'click @ui.selectButton': 'validateShapeAndGoToAnalyze'
},
modelEvents: {
- 'change:query': 'render'
+ 'change:query change:selectedSuggestion': 'render'
},
regions: {
'resultsRegion': '#geocode-search-results-region'
},
+ onDestroy: function() {
+ App.map.set('selectedGeocoderArea', null);
+ },
+
setIcon: function(icon) {
this.ui.searchIcon.prop('class', ICON_BASE + icon);
},
@@ -119,7 +139,12 @@ var SearchBoxView = Marionette.LayoutView.extend({
},
processSearchInputEvent: function(e) {
- var query = $(e.target).val().trim();
+ var query = this.ui.searchBox.val().trim();
+
+ if (e.keyCode === ESC_KEYCODE) {
+ this.dismissAction();
+ return false;
+ }
if (query === '') {
this.setStateDefault();
@@ -191,9 +216,8 @@ var SearchBoxView = Marionette.LayoutView.extend({
.first()
.select()
.done(function() {
- self.setStateDefault();
var model = self.collection.first();
- selectSearchSuggestion(model);
+ self.selectSuggestion(model);
})
.fail(_.bind(this.setStateError, this))
.always(_.bind(this.reset, this));
@@ -209,9 +233,8 @@ var SearchBoxView = Marionette.LayoutView.extend({
this.listenTo(view, 'suggestion:select:in-progress', function() {
this.setStateWorking();
});
- this.listenTo(view, 'suggestion:select:success', function() {
- this.reset();
- this.setStateDefault();
+ this.listenTo(view, 'suggestion:select:success', function(suggestionModel) {
+ this.selectSuggestion(suggestionModel);
});
this.listenTo(view, 'suggestion:select:failure', function() {
this.setStateError();
@@ -224,14 +247,47 @@ var SearchBoxView = Marionette.LayoutView.extend({
this.getRegion('resultsRegion').empty();
},
+ selectSuggestion: function(suggestionModel) {
+ this.dismissAction();
+ this.model.set('selectedSuggestion', suggestionModel);
+ selectSearchSuggestion(suggestionModel);
+ },
+
reset: function() {
- this.model.set('query', '');
+ this.ui.searchBox.val('');
+ this.model.set({
+ query: '',
+ selectedSuggestion: null,
+ });
this.emptyResultsRegion();
+ App.map.set('selectedGeocoderArea', null);
},
dismissAction: function() {
this.reset();
this.setStateDefault();
+ },
+
+ validateShapeAndGoToAnalyze: function() {
+ var selectedBoundary = this.model.get('selectedSuggestion'),
+ selectedBoundaryShape = App.map.get('selectedGeocoderArea');
+
+ if (!selectedBoundary.get('isBoundaryLayer') ||
+ !selectedBoundaryShape) {
+ // Fail early if there's no selected geocoder result on the map
+ // or the selected suggestion isn't a boundary layer
+ return false;
+ }
+
+ drawViews.validateShape(selectedBoundaryShape)
+ .fail(function(message) {
+ drawViews.displayAlert(message, modalModels.AlertTypes.error);
+ })
+ .done(function() {
+ App.map.set('selectedGeocoderArea', null);
+ addBoundaryLayer(selectedBoundary, selectedBoundaryShape);
+ router.navigate('/analyze', { trigger: true});
+ });
}
});
@@ -254,8 +310,7 @@ var SuggestionsView = Backbone.View.extend({
},
selectSuccess: function(model) {
- selectSearchSuggestion(model);
- this.trigger('suggestion:select:success');
+ this.trigger('suggestion:select:success', model);
},
selectFail: function() {
diff --git a/src/mmw/sass/pages/_search-map.scss b/src/mmw/sass/pages/_search-map.scss
index 668d9fc37..999e8a655 100644
--- a/src/mmw/sass/pages/_search-map.scss
+++ b/src/mmw/sass/pages/_search-map.scss
@@ -35,6 +35,16 @@
}
}
+ .search-select-btn {
+ font-size: $font-size-p;
+ position: absolute;
+ top: 12px;
+ right: 42px;
+ background-color: $brand-primary;
+ color: $paper;
+ border: none;
+ }
+
.message {
position: absolute;
color: $paper-74;