Skip to content

Commit

Permalink
Merge pull request #5450 from camptocamp/GSGMF-1186
Browse files Browse the repository at this point in the history
Add search input to the api
  • Loading branch information
fredj committed Jan 24, 2020
2 parents a36e0c7 + 2ac4392 commit d2f4905
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 0 deletions.
15 changes: 15 additions & 0 deletions api/dist/apihelp/apihelp.html
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,21 @@ <h2>Load data from a text file</h2>
</pre>
</div>

<div class="api">
<h2>Search input</h2>
<div id='map10search' style="width: 400px;"></div>
<div id='map10' class="map"></div>
<pre data-language="javascript">
var map = new demo.Map({
div: 'map10',
zoom: 3,
center: [2544500, 1210100],
searchDiv: 'map10search'
});
</pre>
</div>


</div>
<script>
var apis = document.getElementsByTagName('pre');
Expand Down
2 changes: 2 additions & 0 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ config.themesUrl = 'https://geomapfish-demo-2-5.camptocamp.com/themes?' +

config.localeUrl = 'https://geomapfish-demo-2-5.camptocamp.com/locale.json'

config.searchUrl = 'https://geomapfish-demo-2-5.camptocamp.com/search?interface=api&limit=15';

const lib = {
Map
};
Expand Down
23 changes: 23 additions & 0 deletions api/src/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import constants from './constants.js';

import {getFeaturesFromIds, getFeaturesFromCoordinates} from './Querent.js';
import * as themes from './Themes.js';
import Search from './Search.js';


/**
Expand All @@ -52,6 +53,7 @@ import * as themes from './Themes.js';
* @property {boolean} [addMiniMap=false]
* @property {boolean} [miniMapExpanded=true]
* @property {boolean} [addLayerSwitcher=false]
* @property {boolean} [searchDiv]
* @property {string[]} [layers]
* @property {string[]} [backgroundLayers]
*/
Expand Down Expand Up @@ -222,6 +224,27 @@ class Map {
}
}
});

if (options.searchDiv) {
const element = document.querySelector(`#${options.searchDiv}`);
if (element) {
const vectorLayer = new VectorLayer({
zIndex: 1,
source: new VectorSource()
});
this.map_.addLayer(vectorLayer);

new Search({
container: element,
url: constants.searchUrl,
source: vectorLayer.getSource(),
view: this.map_.getView()
});
} else {
throw new Error('Invalid searchDiv option');
}
}

}

/**
Expand Down
83 changes: 83 additions & 0 deletions api/src/Search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import GeoJSON from 'ol/format/GeoJSON.js';
import Autocomplete from '@trevoreyre/autocomplete-js';


/**
* @typedef {Object} SearchOptions
* @property {HTMLElement} container
* @property {string} url
* @property {import("ol/source/Vector").default<any>} source
* @property {import("ol/View").default} view
*/

export default class Search {

/**
* @param {SearchOptions} options API options.
*/
constructor(options) {

this.format_ = new GeoJSON();

this.url_ = new URL(options.url);

this.source_ = options.source;

this.view_ = options.view;

const input = document.createElement('input');
input.className = 'api-search-input';
const ul = document.createElement('ul');
ul.className = 'api-search-results';

options.container.append(input, ul);

this.autocomplete_ = new Autocomplete(options.container, {
search: this.search_.bind(this),
getResultValue: this.getResultValue_.bind(this),
onSubmit: this.onSubmit_.bind(this)
});
}

/**
* @param {string} input
*/
search_(input) {
return new Promise(resolve => {
if (input.length >= 1) {
this.url_.searchParams.set('query', input);
fetch(this.url_.href)
.then(response => response.json())
.then(collection => collection.features)
.then(features => resolve(features.filter(this.hasGeometry_)));
} else {
resolve([]);
}
});
}

/**
* @param {import("geojson").Feature} feature
*/
hasGeometry_(feature) {
return feature.geometry !== null;
}

/**
* @param {import("geojson").Feature} result
*/
getResultValue_(result) {
return result.properties.label;
}

/**
* @param {import("geojson").Feature} result
*/
onSubmit_(result) {
this.source_.clear();
const feature = this.format_.readFeature(result);
this.source_.addFeature(feature);
this.view_.fit(this.source_.getExtent());
}

}
19 changes: 19 additions & 0 deletions api/src/api.css
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,22 @@
overflow: hidden;
height: 0;
}

.api-search-input {
width: 100%;
}

.api-search-results {
max-height: 400px;
overflow: hidden;
overflow-y: auto;
margin: 0;
padding: 0;
list-style: none;
background-color: #fff;
}

.api-search-results .autocomplete-result {
cursor: pointer;
padding: 4px;
}
1 change: 1 addition & 0 deletions api/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default /** @type {APIConfig} */({
// The URL to the themes service.
themesUrl: 'https://www.example.com',
localeUrl: undefined,
searchUrl: undefined,

// The projection of the map
projection: EPSG2056,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@geoblocks/proj": "0.4.2",
"@sentry/browser": "5.10.2",
"@sentry/types": "5.10.0",
"@trevoreyre/autocomplete-js": "2.1.0",
"@types/angular": "1.6.57",
"@types/angular-animate": "1.5.10",
"@types/angular-dynamic-locale": "0.1.35",
Expand Down

0 comments on commit d2f4905

Please sign in to comment.