OpenLayers 3 Geocoder Extension

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/ol3/3.11.1/ol.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/ol3/3.11.1/ol.min.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/openlayers.geocoder/latest/ol3-geocoder.min.css">
<script src="//cdn.jsdelivr.net/openlayers.geocoder/latest/ol3-geocoder.js"></script>
<div id="map" tabindex="0"></div>
<div id="popup" class="ol-popup">
    <a href="#" id="popup-closer" class="ol-popup-closer"></a>
    <div id="popup-content"></div>
</div>

CSS

@import url(https://fonts.googleapis.com/css?family=Open+Sans);
html, body, #map{
    width:100%;
    height:100%;
    overflow:hidden;
}
body {
    font: 1em/1.5 "Open Sans",Helvetica,Arial,sans-serif;
    color: #222;
    font-weight: 400;
}

#map{
    position:absolute;
    z-index:1;
    top:0; bottom:0;
}
.ol-control button{ 
    background-color: rgba(40, 40, 40, 0.8) !important;
}
.ol-control button:hover{ 
    background-color: rgba(40, 40, 40, 1) !important;
}

.ol-popup {
    position: absolute;
    min-width: 180px;
    background-color: white;
    -webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
    filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
    padding: 15px;
    border-radius: 10px;
    border: 1px solid #ccc;
    bottom: 12px;
    left: -50px;
}
.ol-popup:after, .ol-popup:before {
    top: 100%;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
}
.ol-popup:after {
    border-top-color: white;
    border-width: 10px;
    left: 48px;
    margin-left: -10px;
}
.ol-popup:before {
    border-top-color: #cccccc;
    border-width: 11px;
    left: 48px;
    margin-left: -11px;
}
.ol-popup-closer {
    text-decoration: none;
    position: absolute;
    top: 2px;
    right: 8px;
}
.ol-popup-closer:after {
    content: "✖";
}

JavaScript

(function(win, doc){
  'use strict';
  var 
    olview = new ol.View({
      center: [0, 0],
      zoom: 3,
      minZoom: 2,
      maxZoom: 20
    }),
    baseLayer = new ol.layer.Tile({
      source: new ol.source.MapQuest({layer: 'osm'})
    }),
    map = new ol.Map({
      target: doc.getElementById('map'),
      view: olview,
      loadTilesWhileAnimating: true,
      loadTilesWhileInteracting: true,
      layers: [baseLayer]
    })
  ;

  //Instantiate with some options and add the Control
  var geocoder = new Geocoder('mapzen', {
    provider: 'pelias',
    key: 'search-xxxxxx',
    lang: 'en',
    placeholder: 'Search for ...',
    limit: 5,
    keepOpen: true
  });
  map.addControl(geocoder);
  
  //Listen when an address is chosen
  geocoder.on('addresschosen', function(evt){
    var
      feature = evt.feature,
      coord = evt.coordinate,
      address_html = feature.get('address_html')
    ;
    content.innerHTML = '<p>'+address_html+'</p>';
    overlay.setPosition(coord);
  });

  /**
  * Popup
  **/
  var
    container = doc.getElementById('popup'),
    content = doc.getElementById('popup-content'),
    closer = doc.getElementById('popup-closer'),
    overlay = new ol.Overlay({
      element: container,
      offset: [0, -40]
    })
  ;
  closer.onclick = function() {
    overlay.setPosition(undefined);
    closer.blur();
    return false;
  };
  map.addOverlay(overlay);
})(window, document);