SearchBox integration
Overview of the tutorial
This tutorial shows the basic use of the SearchBox plugin to display it in a web page.
Prerequisites
To start using the latest version of the SearchBox plugin, you need the following:
- The SearchBox plugin can be used in three ways.
- NPM
- With a
CDN: https://api.tomtom.com/maps-sdk-for-web/cdn/plugins/SearchBox/<version>/SearchBox-web.js
Include the latest version in the URL.
- Download it from this
page: Downloads.
In this tutorial we are using a CDN as an example.
- API Key - If you don't have an API Key visit the How to get a TomTom API Key site and create one.
We recommend that you have npm and Node.js already installed on your computer to quickly spin up a HTTP server to display the page we will create.
There are two ways to include the SearchBox into your page.
- Using the SearchBox as an independent element.
- Using the SearchBox as a control in the map.
Using the SearchBox as an independent element
Now, let's create a basic HTML file to display the SearchBox plugin. For this example we created a file named index.html.
Next, copy the following script to your index.html file.
1<!DOCTYPE html>2<html class="use-all-space">3 <head>4 <meta http-equiv="X-UA-Compatible" content="IE=Edge" />5 <meta charset="UTF-8" />6 <meta7 name="viewport"8 content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"9 />10 <title>SearchBox</title>11 <link12 rel="stylesheet"13 type="text/css"14 href="https://api.tomtom.com/maps-sdk-for-web/cdn/plugins/SearchBox/3.1.3-public-preview.0/SearchBox.css"15 />16 <script src="https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.1.2-public-preview.15/services/services-web.min.js"></script>17 <script src="https://api.tomtom.com/maps-sdk-for-web/cdn/plugins/SearchBox/3.1.3-public-preview.0/SearchBox-web.js"></script>18 </head>19 <body>20 <script>21 var options = {22 searchOptions: {23 key: "<your-tomtom-API-key>",24 language: "en-GB",25 limit: 5,26 },27 autocompleteOptions: {28 key: "<your-tomtom-API-key>",29 language: "en-GB",30 },31 }32 var ttSearchBox = new tt.plugins.SearchBox(tt.services, options)33 var searchBoxHTML = ttSearchBox.getSearchBoxHTML()34 document.body.append(searchBoxHTML)35 </script>36 </body>37</html>
Let's go over the important lines
First, we import all the necessary assets. In this case there are SearchBox styles, the plugin, and the Services library.
1<link2 rel="stylesheet"3 type="text/css"4 href="https://api.tomtom.com/maps-sdk-for-web/cdn/plugins/SearchBox/3.1.3-public-preview.0/SearchBox.css"5/>6<script src="https://api.tomtom.com/maps-sdk-for-web/cdn/plugins/SearchBox/3.1.3-public-preview.0/SearchBox-web.js"></script>7<script src="https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.1.2-public-preview.15/services/services-web.min.js"></script>
- SearchBox styles - these provide the styles for SearchBox.
- SearchBox plugin - this provides the search box and its functionality to your page.
- Services library - This provides the necessary tools to integrate Tomtom services with your application.
Then we define the basic options configuration. See the following code example.
1var options = {2 searchOptions: {3 key: "<your-tomtom-API-key>",4 language: "en-GB",5 limit: 5,6 },7 autocompleteOptions: {8 key: "<your-tomtom-API-key>",9 language: "en-GB",10 },11}
- searchOptions - this is for the Fuzzy Search service. For a full list of options please refer to the Fuzzy Search service documentation.
- autocompleteOptions - this is for the Autocomplete service. For a full list of options please
refer to
the Autocomplete service documentation.
If you pass this option, the results list will be extended by the results returned by the Autocomplete service. They are used as filters for the fuzzy search.
Remember to replace the placeholders with your real data.
your-tomtom-API-Key | Your TomTom API Key generated earlier. |
For more details on how to use the configuration options, please refer to the documentation.
Then, we can create our new SearchBox instance
var ttSearchBox = new tt.plugins.SearchBox(tt.services, options)
and append it to our application. In our example it's the body of the document.
var searchBoxHTML = ttSearchBox.getSearchBoxHTML()document.body.appendChild(searchBoxHTML)
Using the SearchBox as a control in the map
The workflow of adding the SearchBox as a control is almost the same. You need to include a Map in your page and add there created instance of SearchBox with subscribed event handlers.
To check how to add the Map, please refer to the Display a vector map tutorial.
1var map = tt.map({2 key: "<your-tomtom-API-Key>",3 container: "map",4 center: [15.4, 53.0],5 zoom: 3,6})7var ttSearchBox = new tt.plugins.SearchBox(tt.services, options)8var searchMarkersManager = new SearchMarkersManager(map)9ttSearchBox.on("tomtom.searchbox.resultsfound", handleResultsFound)10ttSearchBox.on("tomtom.searchbox.resultselected", handleResultSelection)11ttSearchBox.on("tomtom.searchbox.resultfocused", handleResultSelection)12ttSearchBox.on("tomtom.searchbox.resultscleared", handleResultClearing)13map.addControl(ttSearchBox, "top-left")
SearchBox options was described above.
Remember to replace the placeholders with your real data.
your-tomtom-API-Key | Your TomTom API Key generated earlier. |
For more map configuration options please refer to the Map documentation.
Then we define event handlers.
1function handleResultsFound(event) {2 var results = event.data.results.fuzzySearch.results34 if (results.length === 0) {5 searchMarkersManager.clear()6 }7 searchMarkersManager.draw(results)8 fitToViewport(results)9}1011function handleResultSelection(event) {12 var result = event.data.result13 if (result.type === "category" || result.type === "brand") {14 return15 }16 searchMarkersManager.draw([result])17 fitToViewport(result)18}1920function fitToViewport(markerData) {21 if (!markerData || (markerData instanceof Array && !markerData.length)) {22 return23 }24 var bounds = new tt.LngLatBounds()25 if (markerData instanceof Array) {26 markerData.forEach(function (marker) {27 bounds.extend(getBounds(marker))28 })29 } else {30 bounds.extend(getBounds(markerData))31 }32 map.fitBounds(bounds, { padding: 100, linear: true })33}3435function getBounds(data) {36 var btmRight37 var topLeft38 if (data.viewport) {39 btmRight = [40 data.viewport.btmRightPoint.lng,41 data.viewport.btmRightPoint.lat,42 ]43 topLeft = [data.viewport.topLeftPoint.lng, data.viewport.topLeftPoint.lat]44 }45 return [btmRight, topLeft]46}4748function handleResultClearing() {49 searchMarkersManager.clear()50}
- handleResultsFound - executes when the search results are found. The event handler clears previously founded results and draws new. After that, it will try to fit drawn results on a vewport by executing fitToViewport method.
- handleResultSelection - executes in two cases:
- results were found and a user presses arrow up/down;
- results were found and a user chooses one by clicking on it;
- handleResultClearing - executes when a user clicks on "X" button of the SearchBox. As a result, all founded results will be cleared from the map.
After all these predefined steps we can create SearchMarkersManager, which will be responsible for manipulation with a marker.
In our example it has draw and clear methods
1function SearchMarkersManager(map, options) {2 this.map = map3 this._options = options || {}4 this._poiList = undefined5 this.markers = {}6}78SearchMarkersManager.prototype.draw = function (poiList) {9 this._poiList = poiList10 this.clear()11 this._poiList.forEach(function (poi) {12 var markerId = poi.id13 var poiOpts = {14 name: poi.poi ? poi.poi.name : undefined,15 address: poi.address ? poi.address.freeformAddress : "",16 distance: poi.dist,17 classification: poi.poi ? poi.poi.classifications[0].code : undefined,18 position: poi.position,19 entryPoints: poi.entryPoints,20 }21 var marker = new SearchMarker(poiOpts, this._options)22 marker.addTo(this.map)23 this.markers[markerId] = marker24 }, this)25}2627SearchMarkersManager.prototype.clear = function () {28 for (var markerId in this.markers) {29 var marker = this.markers[markerId]30 marker.remove()31 }32 this.markers = {}33 this._lastClickedMarker = null34}
and SearchMarker, which will be responsible for appearance of the marker and providing possibility add/remove it from the map
1function SearchMarker(poiData, options) {2 this.poiData = poiData3 this.options = options || {}4 this.marker = new tt.Marker({5 element: this.createMarker(),6 anchor: "bottom",7 })8 var lon = this.poiData.position.lng || this.poiData.position.lon9 this.marker.setLngLat([lon, this.poiData.position.lat])10}1112SearchMarker.prototype.addTo = function (map) {13 this.marker.addTo(map)14 this._map = map15 return this16}1718SearchMarker.prototype.createMarker = function () {19 var elem = document.createElement("div")20 elem.className = "tt-icon-marker-black tt-search-marker"21 if (this.options.markerClassName) {22 elem.className += " " + this.options.markerClassName23 }24 var innerElem = document.createElement("div")25 innerElem.setAttribute(26 "style",27 "background: white; width: 10px; height: 10px; border-radius: 50%; border: 3px solid black;"28 )2930 elem.appendChild(innerElem)31 return elem32}3334SearchMarker.prototype.remove = function () {35 this.marker.remove()36 this._map = null37}
For more advanced example of using the described code above please refer to the code tab of Search with autocomplete example.
Handling events
The SearchBox emits 7 different events:
- tomtom.searchbox.inputrestored - fired when the input is restored. This happens when the user uses the arrows to navigate through the suggestions list and navigates back to the input.
- tomtom.searchbox.loadingstarted - fired when a request in the background is started.
- tomtom.searchbox.loadingfinished - fired when a request in the background is finished.
- tomtom.searchbox.resultfocused - fired when the result is focused.
- tomtom.searchbox.resultscleared - fired when the search results are cleared.
- tomtom.searchbox.resultselected - fired when the user selects an element on the results list.
- tomtom.searchbox.resultsfound - fired when the search results are found.
If you want to subscribe for an event, use the following example code:
1ttSearchBox.on("tomtom.searchbox.resultsfound", function (data) {2 console.log(data)3})
Option updating
If you have initialized the SearchBox and you want to change it's options later, you can do the following:
1ttSearchBox.updateOptions({2 minNumberOfCharacters: 5,3 showSearchButton: false,4 labels: {5 placeholder: "Query e.g. TomTom",6 },7})
The query method triggers the search with updated options. This is necessary if you want to update results for the user with new options.
ttSearchBox.query()
For more details on how to use the configuration options, please refer to the documentation.
Run a HTTP server
Using a terminal, navigate to the directory containing our example.
For example:
~$ cd searchbox-example/~searchbox-example$
Install a lightweight HTTP server (you might need to run this command with admin/root privileges).
npm install -g http-server
Then just simply run the following command.
http-server
Note that npm comes bundled with Node.js, so please make sure you have it installed on your machine.
So now it is time to see the results!
Open a browser and type this URL in the address bar: http://localhost:8080/index.html. You should be able to see the SearchBox!
Summary
From this tutorial you learned:
- How to prepare a basic HTML page to use the SearchBox.
- How to show the SearchBox on your map.