title: Add search bar to Mapbox GL JS
body: <p>I'm working form the demo file form MapBox to create a store locator (<a href="https://docs.mapbox.com/help/tutorials/building-a-store-locator/" rel="nofollow noreferrer">https://docs.mapbox.com/help/tutorials/building-a-store-locator/</a>)</p>
  <p>I'd like to add a search bar that filters the results, based on the 'city' field.
  I've tried working with the documentation on the MapBox website, but i've been unsuccessful.
  <a href="https://docs.mapbox.com/mapbox-gl-js/example/filter-features-within-map-view/" rel="nofollow noreferrer">https://docs.mapbox.com/mapbox-gl-js/example/filter-features-within-map-view/</a></p>
  <p>HTML/JS</p>
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
    &lt;head&gt;
      &lt;meta charset='utf-8' /&gt;
      &lt;title&gt;Store Locator&lt;/title&gt;
      &lt;meta name='robots' content='noindex, nofollow'&gt;
      &lt;meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /&gt;
  
      &lt;link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700' rel='stylesheet'&gt;
      &lt;link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css' rel='stylesheet' /&gt;
      &lt;link href='stylesheet.css' rel='stylesheet' /&gt;
  
      &lt;script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js'&gt;&lt;/script&gt;
      &lt;script src='store-info.js'&gt;&lt;/script&gt;
  
      &lt;script src=&quot;https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.5.1/mapbox-gl-geocoder.min.js&quot;&gt;&lt;/script&gt;
      &lt;link
      rel=&quot;stylesheet&quot;
      href=&quot;https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.5.1/mapbox-gl-geocoder.css&quot;
      type=&quot;text/css&quot;
      /&gt;
      &lt;!-- Promise polyfill script required to use Mapbox GL Geocoder in IE 11 --&gt;
      &lt;script src=&quot;https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.min.js&quot;&gt;&lt;/script&gt;
      &lt;script src=&quot;https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.min.js&quot;&gt;&lt;/script&gt;
  
    &lt;/head&gt;
  
  
    &lt;body&gt;
        &lt;div class=&quot;center-all&quot;&gt;
        &lt;div class=&quot;WTB-container&quot;&gt;
          &lt;h2&gt;Find a riderwear stockist near you.&lt;/h2&gt;
          &lt;p&gt;Please contact your chosen store to confirm stock before beginning your journey.&lt;/p&gt;
      &lt;div class=&quot;map-container&quot;&gt;
      &lt;div class='sidebar'&gt;
        &lt;div class='heading'&gt;
          &lt;h1&gt;Stores&lt;/h1&gt;
        &lt;/div&gt;
        &lt;div id='listings' class='listings'&gt;&lt;/div&gt;
      &lt;/div&gt;
      &lt;div id='map' class='map'&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  
  
  &lt;script&gt;
    // This will let you use the .remove() function later on
    if (!('remove' in Element.prototype)) {
      Element.prototype.remove = function() {
        if (this.parentNode) {
            this.parentNode.removeChild(this);
        }
      };
    }
  
    mapboxgl.accessToken = 'pk.eyJ1IjoibWFyY3VzdGVzdGFjY291bnQiLCJhIjoiY2tmaTA3ODJ5MHFnZjJxczJla2M3bjRneSJ9.iafUvLt1Zn1Cs8IrRbYhOw';
    /** 
     * Add the map to the page
    */
    var map = new mapboxgl.Map({
      container: 'map',
      style: 'mapbox://styles/mapbox/light-v10',
      center: [-1.480048, 53.553637],
      zoom: 5,
      scrollZoom: true
    });
  
  
    /**
     * Assign a unique id to each store. You'll use this `id`
     * later to associate each point on the map with a listing
     * in the sidebar.
    */
    stores.features.forEach(function(store, i){
      store.properties.id = i;
    });
  
    /**
     * Wait until the map loads to make changes to the map.
    */
    map.on('load', function (e) {
      /** 
       * This is where your '.addLayer()' used to be, instead
       * add only the source without styling a layer
      */
      map.addSource(&quot;places&quot;, {
        &quot;type&quot;: &quot;geojson&quot;,
        &quot;data&quot;: stores
      });
  
      /**
       * Add all the things to the page:
       * - The location listings on the side of the page
       * - The markers onto the map
      */
      buildLocationList(stores);
      addMarkers();
    });
  
    /**
     * Add a marker to the map for every store listing.
    **/
    function addMarkers() {
      /* For each feature in the GeoJSON object above: */
      stores.features.forEach(function(marker) {
        /* Create a div element for the marker. */
        var el = document.createElement('div');
        /* Assign a unique `id` to the marker. */
        el.id = &quot;marker-&quot; + marker.properties.id;
        /* Assign the `marker` class to each marker for styling. */
        el.className = 'marker';
        
        /**
         * Create a marker using the div element
         * defined above and add it to the map.
        **/
        new mapboxgl.Marker(el, { offset: [0, -23] })
          .setLngLat(marker.geometry.coordinates)
          .addTo(map);
  
        /**
         * Listen to the element and when it is clicked, do three things:
         * 1. Fly to the point
         * 2. Close all other popups and display popup for clicked store
         * 3. Highlight listing in sidebar (and remove highlight for all other listings)
        **/
        el.addEventListener('click', function(e){
          /* Fly to the point */
          flyToStore(marker);
          /* Close all other popups and display popup for clicked store */
          createPopUp(marker);
          /* Highlight listing in sidebar */
          var activeItem = document.getElementsByClassName('active');
          e.stopPropagation();
          if (activeItem[0]) {
            activeItem[0].classList.remove('active');
          }
          var listing = document.getElementById('listing-' + marker.properties.id);
          listing.classList.add('active');
        });
      });
    }
  
    /**
     * Add a listing for each store to the sidebar.
    **/
    function buildLocationList(data) {
      data.features.forEach(function(store, i){
        /**
         * Create a shortcut for `store.properties`,
         * which will be used several times below.
        **/
        var prop = store.properties;
  
        /* Add a new listing section to the sidebar. */
        var listings = document.getElementById('listings');
        var listing = listings.appendChild(document.createElement('div'));
        /* Assign a unique `id` to the listing. */
        listing.id = &quot;listing-&quot; + prop.id;
        /* Assign the `item` class to each listing for styling. */
        listing.className = 'item';
  
        /* Add the link to the individual listing created above. */
        var link = listing.appendChild(document.createElement('a'));
        link.href = '#';
        link.className = 'title';
        link.id = &quot;link-&quot; + prop.id;
        link.innerHTML = prop.name;
  
        /* Add details to the individual listing. */
        var details = listing.appendChild(document.createElement('div'));
        details.innerHTML = prop.city;
        if (prop.phone) {
          details.innerHTML += ' · ' + prop.phone;
        }
  
        /**
         * Listen to the element and when it is clicked, do four things:
         * 1. Update the `currentFeature` to the store associated with the clicked link
         * 2. Fly to the point
         * 3. Close all other popups and display popup for clicked store
         * 4. Highlight listing in sidebar (and remove highlight for all other listings)
        **/
        link.addEventListener('click', function(e){
          for (var i=0; i &lt; data.features.length; i++) {
            if (this.id === &quot;link-&quot; + data.features[i].properties.id) {
              var clickedListing = data.features[i];
              flyToStore(clickedListing);
              createPopUp(clickedListing);
            }
          }
          var activeItem = document.getElementsByClassName('active');
          if (activeItem[0]) {
            activeItem[0].classList.remove('active');
          }
          this.parentNode.classList.add('active');
        });
      });
    }
  
    /**
     * Use Mapbox GL JS's `flyTo` to move the camera smoothly
     * a given center point.
    **/
    function flyToStore(currentFeature) {
      map.flyTo({
        center: currentFeature.geometry.coordinates,
        zoom: 15
      });
    }
  
    /**
     * Create a Mapbox GL JS `Popup`.
    **/
    function createPopUp(currentFeature) {
      var popUps = document.getElementsByClassName('mapboxgl-popup');
      if (popUps[0]) popUps[0].remove();
      var popup = new mapboxgl.Popup({closeOnClick: false})
        .setLngLat(currentFeature.geometry.coordinates)
        .setHTML('&lt;h3&gt;' + currentFeature.properties.name + '&lt;/h3&gt;' +
        '&lt;h4&gt;' + currentFeature.properties.address + '&lt;/h4&gt;' + 
        '&lt;h4&gt;' +currentFeature.properties.county + '&lt;/h4&gt;' +  
        '&lt;h4&gt;' + currentFeature.properties.postalCode + '&lt;/h4&gt;')
        .addTo(map);
    }
  
  
    
  // Add geolocate control to the map.
  map.addControl(
  new mapboxgl.GeolocateControl({
  positionOptions: {
  enableHighAccuracy: true
  },
  trackUserLocation: true
  })
  );
  
  // Add zoom and rotation controls to the map.
  map.addControl(new mapboxgl.NavigationControl());
  </code></pre>
  
  <p>CSS</p>
  <pre><code>    body {
          color:#404040;
          font:400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif;
          margin:0;
          padding:0;
          -webkit-font-smoothing:antialiased;
        }
  
        * {
          -webkit-box-sizing:border-box;
          -moz-box-sizing:border-box;
          box-sizing:border-box;
        }
  h2{
    margin-bottom: 0;
  }
  
  
  
    .center-all{
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
  
      height: 100vh;
    }
  
        .WTB-container{
          width: 1200px;
          height: auto;
  
          margin: auto;
  
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
  
          text-align: left;
        }
        .map-container{
          width: 80%;
          height: auto;
  
          
  
          display: flex;
          justify-content: center;
          align-items: center;
  
          margin: 0;
            margin-top: 50px;
        }
  
        .sidebar {
          width:30%;
          height:500px;
  
          overflow:hidden;
          border-right:1px solid rgba(0,0,0,0.25);
        }
        .pad2 {
          padding:20px;
        }
  
        .map {
          width:60%;
          height: 500px;
        }
  
        h1 {
          font-size:22px;
          margin:0;
          font-weight:400;
          line-height: 20px;
          padding: 20px 2px;
        }
  
        a {
          color:#404040;
          text-decoration:none;
        }
  
        a:hover {
          color:#101010;
        }
  
        .heading {
          background:#fff;
          border-bottom:1px solid #eee;
          min-height:60px;
          line-height:60px;
          padding:0 10px;
          background-color: #1060AB;
          color: #fff;
        }
  
        .listings {
          height:100%;
          overflow:auto;
          padding-bottom:60px;
        }
  
        .listings .item {
          display:block;
          border-bottom:1px solid #eee;
          padding:10px;
          text-decoration:none;
        }
  
        .listings .item:last-child { border-bottom:none; }
        .listings .item .title {
          display:block;
          color:#1060AB;
          font-weight:700;
        }
  
        .listings .item .title small { font-weight:400; }
        .listings .item.active .title,
        .listings .item .title:hover { color:#1060AB; }
        .listings .item.active {
          background-color:#f8f8f8;
        }
        ::-webkit-scrollbar {
          width:3px;
          height:3px;
          border-left:0;
          background:rgba(0,0,0,0.1);
        }
        ::-webkit-scrollbar-track {
          background:none;
        }
        ::-webkit-scrollbar-thumb {
          background:#1060AB;
          border-radius:0;
        }
  
        .marker {
          border: none;
          cursor: pointer;
          height: 56px;
          width: 56px;
          background-image: url(marker.png);
          background-color: rgba(0, 0, 0, 0);
        }
  
        .clearfix { display:block; }
        .clearfix:after {
          content:'.';
          display:block;
          height:0;
          clear:both;
          visibility:hidden;
        }
  
        /* Marker tweaks */
        .mapboxgl-popup {
          padding-bottom: 50px;
        }
  
        .mapboxgl-popup-close-button {
          display:none;
        }
        .mapboxgl-popup-content {
          font:400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif;
          padding:0;
          width:180px;
        }
        .mapboxgl-popup-content-wrapper {
          padding:1%;
        }
        .mapboxgl-popup-content h3 {
          background:#1060AB;
          color:#fff;
          margin:0;
          display:block;
          padding:10px;
          border-radius:3px 3px 0 0;
          font-weight:700;
          margin-top:-15px;
        }
  
        .mapboxgl-popup-content h4 {
          margin:0;
          display:block;
          padding: 10px 10px 10px 10px;
          font-weight:400;
        }
  
        .mapboxgl-popup-content div {
          padding:10px;
        }
  
        .mapboxgl-container .leaflet-marker-icon {
          cursor:pointer;
        }
  
        .mapboxgl-popup-anchor-top &gt; .mapboxgl-popup-content {
          margin-top: 15px;
        }
  
        .mapboxgl-popup-anchor-top &gt; .mapboxgl-popup-tip {
          border-bottom-color: #1060AB;
        }
  
  
          .mapboxgl-ctrl-compass{
            display: none !important;
          }
  
          
  </code></pre>
  <p>GeoJSON</p>
  <pre><code>var stores = {
    &quot;type&quot;: &quot;FeatureCollection&quot;,
    &quot;features&quot;: [
      {
        &quot;type&quot;: &quot;Feature&quot;,
        &quot;geometry&quot;: {
          &quot;type&quot;: &quot;Point&quot;,
          &quot;coordinates&quot;: [
          -1.310840,
          51.830350
          ]
        },
        &quot;properties&quot;: {
          &quot;name&quot;:&quot;Helmet City&quot;,
          &quot;phone&quot;: &quot;01865 372529&quot;,
          &quot;address&quot;: &quot;Saint Georges House, Langford Lane&quot;,
          &quot;city&quot;: &quot;Kidlington&quot;,
          &quot;county&quot;: &quot;Oxfordshire&quot;,
          &quot;country&quot;: &quot;England&quot;,
          &quot;postalCode&quot;: &quot;OX5 1HT&quot;,
  
        }
      },
      {
        &quot;type&quot;: &quot;Feature&quot;,
        &quot;geometry&quot;: {
          &quot;type&quot;: &quot;Point&quot;,
          &quot;coordinates&quot;: [
            -1.714590,
            52.200806
          ]
        },
        &quot;properties&quot;: {
          &quot;name&quot;:&quot;Performance Triumph&quot;,
          &quot;phone&quot;: &quot;01789 205149&quot;,
          &quot;address&quot;: &quot;14 Western Road&quot;,
          &quot;city&quot;: &quot;Stratford Upon Avon&quot;,
          &quot;county&quot;: &quot;Warwickshire&quot;,
          &quot;country&quot;: &quot;England&quot;,
          &quot;postalCode&quot;: &quot;CV37 0AH&quot;,
  
        }
      }
  
    ]
  };
  </code></pre>
  <p>Nike (<a href="https://www.nike.com/gb/retail?latitude=51.50722&amp;longitude=-0.1275&amp;page=1&amp;storesPerPage=15" rel="nofollow noreferrer">https://www.nike.com/gb/retail?latitude=51.50722&amp;longitude=-0.1275&amp;page=1&amp;storesPerPage=15</a>) have the feature i'm after, but I can't recreate it. Any help would be appreciated.</p>