text: 
  
  var measuring = false;
  var measureControl = (function (Control) {
      measureControl = function(opt_options) {
  
        var options = opt_options || {};
  
        var button = document.createElement('button');
        button.className += ' fas fa-ruler ';
  
        var this_ = this;
        var handleMeasure = function(e) {
          if (!measuring) {
              this_.getMap().addInteraction(draw);
              createHelpTooltip();
              createMeasureTooltip();
              measuring = true;
          } else {
              this_.getMap().removeInteraction(draw);
              measuring = false;
              this_.getMap().removeOverlay(helpTooltip);
              this_.getMap().removeOverlay(measureTooltip);
          }
        };
  
        button.addEventListener('click', handleMeasure, false);
        button.addEventListener('touchstart', handleMeasure, false);
  
        var element = document.createElement('div');
        element.className = 'measure-control ol-unselectable ol-control';
        element.appendChild(button);
  
        ol.control.Control.call(this, {
          element: element,
          target: options.target
        });
  
      };
      if (Control) measureControl.__proto__ = Control;
      measureControl.prototype = Object.create(Control && Control.prototype);
      measureControl.prototype.constructor = measureControl;
      return measureControl;
  }(ol.control.Control));
  var container = document.getElementById('popup');
  var content = document.getElementById('popup-content');
  var closer = document.getElementById('popup-closer');
  var sketch;
  
  closer.onclick = function() {
      container.style.display = 'none';
      closer.blur();
      return false;
  };
  var overlayPopup = new ol.Overlay({
      element: container
  });
  
  var expandedAttribution = new ol.control.Attribution({
      collapsible: false
  });
  
  var map = new ol.Map({
      controls: ol.control.defaults({attribution:false}).extend([
          expandedAttribution,new measureControl()
      ]),
      target: document.getElementById('map'),
      renderer: 'canvas',
      overlays: [overlayPopup],
      layers: layersList,
      view: new ol.View({
           maxZoom: 28, minZoom: 1
      })
  });
  
  var layerSwitcher = new ol.control.LayerSwitcher({tipLabel: "Layers"});
  map.addControl(layerSwitcher);
  
      var searchLayer = new SearchLayer({
        layer: lyr_BatasKecamatan_2,
        colName: 'Kecamatan',
        zoom: 10,
        collapsed: true,
        map: map
      });
  
      map.addControl(searchLayer);
      document.getElementsByClassName('search-layer')[0]
      .getElementsByTagName('button')[0].className +=
      ' fa fa-binoculars';
      
  map.getView().fit([12174915.298189, -877542.086161, 12236252.355358, -833141.284691], map.getSize());
  
  var NO_POPUP = 0
  var ALL_FIELDS = 1
  
  /**
   * Returns either NO_POPUP, ALL_FIELDS or the name of a single field to use for
   * a given layer
   * @param layerList {Array} List of ol.Layer instances
   * @param layer {ol.Layer} Layer to find field info about
   */
  function getPopupFields(layerList, layer) {
      // Determine the index that the layer will have in the popupLayers Array,
      // if the layersList contains more items than popupLayers then we need to
      // adjust the index to take into account the base maps group
      var idx = layersList.indexOf(layer) - (layersList.length - popupLayers.length);
      return popupLayers[idx];
  }
  
  
  var collection = new ol.Collection();
  var featureOverlay = new ol.layer.Vector({
      map: map,
      source: new ol.source.Vector({
          features: collection,
          useSpatialIndex: false // optional, might improve performance
      }),
      style: [new ol.style.Style({
          stroke: new ol.style.Stroke({
              color: '#f00',
              width: 1
          }),
          fill: new ol.style.Fill({
              color: 'rgba(255,0,0,0.1)'
          }),
      })],
      updateWhileAnimating: true, // optional, for instant visual feedback
      updateWhileInteracting: true // optional, for instant visual feedback
  });
  
  var doHighlight = false;
  var doHover = false;
  
  var highlight;
  var autolinker = new Autolinker({truncate: {length: 30, location: 'smart'}});
  var onPointerMove = function(evt) {
      if (!doHover && !doHighlight) {
          return;
      }
      var pixel = map.getEventPixel(evt.originalEvent);
      var coord = evt.coordinate;
      var popupField;
      var currentFeature;
      var currentLayer;
      var currentFeatureKeys;
      var clusteredFeatures;
      var popupText = '<ul>';
      map.forEachFeatureAtPixel(pixel, function(feature, layer) {
          // We only care about features from layers in the layersList, ignore
          // any other layers which the map might contain such as the vector
          // layer used by the measure tool
          if (layersList.indexOf(layer) === -1) {
              return;
          }
          var doPopup = false;
          for (k in layer.get('fieldImages')) {
              if (layer.get('fieldImages')[k] != "Hidden") {
                  doPopup = true;
              }
          }
          currentFeature = feature;
          currentLayer = layer;
          clusteredFeatures = feature.get("features");
          var clusterFeature;
          if (typeof clusteredFeatures !== "undefined") {
              if (doPopup) {
                  for(var n=0; n<clusteredFeatures.length; n++) {
                      clusterFeature = clusteredFeatures[n];
                      currentFeatureKeys = clusterFeature.getKeys();
                      popupText += '<li><table>'
                      for (var i=0; i<currentFeatureKeys.length; i++) {
                          if (currentFeatureKeys[i] != 'geometry') {
                              popupField = '';
                              if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "inline label") {
                              popupField += '<th>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + ':</th><td>';
                              } else {
                                  popupField += '<td colspan="2">';
                              }
                              if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "header label") {
                                  popupField += '<strong>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + ':</strong><br />';
                              }
                              if (layer.get('fieldImages')[currentFeatureKeys[i]] != "ExternalResource") {
                                  popupField += (clusterFeature.get(currentFeatureKeys[i]) != null ? autolinker.link(clusterFeature.get(currentFeatureKeys[i]).toLocaleString()) + '</td>' : '');
                              } else {
                                  popupField += (clusterFeature.get(currentFeatureKeys[i]) != null ? '<img src="images/' + clusterFeature.get(currentFeatureKeys[i]).replace(/[\\\/:]/g, '_').trim()  + '" /></td>' : '');
                              }
                              popupText += '<tr>' + popupField + '</tr>';
                          }
                      } 
                      popupText += '</table></li>';    
                  }
              }
          } else {
              currentFeatureKeys = currentFeature.getKeys();
              if (doPopup) {
                  popupText += '<li><table>';
                  for (var i=0; i<currentFeatureKeys.length; i++) {
                      if (currentFeatureKeys[i] != 'geometry') {
                          popupField = '';
                          if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "inline label") {
                              popupField += '<th>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + ':</th><td>';
                          } else {
                              popupField += '<td colspan="2">';
                          }
                          if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "header label") {
                              popupField += '<strong>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + ':</strong><br />';
                          }
                          if (layer.get('fieldImages')[currentFeatureKeys[i]] != "ExternalResource") {
                              popupField += (currentFeature.get(currentFeatureKeys[i]) != null ? autolinker.link(currentFeature.get(currentFeatureKeys[i]).toLocaleString()) + '</td>' : '');
                          } else {
                              popupField += (currentFeature.get(currentFeatureKeys[i]) != null ? '<img src="images/' + currentFeature.get(currentFeatureKeys[i]).replace(/[\\\/:]/g, '_').trim()  + '" /></td>' : '');
                          }
                          popupText += '<tr>' + popupField + '</tr>';
                      }
                  }
                  popupText += '</table></li>';
              }
          }
      });
      if (popupText == '<ul>') {
          popupText = '';
      } else {
          popupText += '</ul>';
      }
  
      if (doHighlight) {
          if (currentFeature !== highlight) {
              if (highlight) {
                  featureOverlay.getSource().removeFeature(highlight);
              }
              if (currentFeature) {
                  var styleDefinition = currentLayer.getStyle().toString();
  
                  if (currentFeature.getGeometry().getType() == 'Point') {
                      var radius = styleDefinition.split('radius')[1].split(' ')[1];
  
                      highlightStyle = new ol.style.Style({
                          image: new ol.style.Circle({
                              fill: new ol.style.Fill({
                                  color: "#ffff00"
                              }),
                              radius: radius
                          })
                      })
                  } else if (currentFeature.getGeometry().getType() == 'LineString') {
  
                      var featureWidth = styleDefinition.split('width')[1].split(' ')[1].replace('})','');
  
                      highlightStyle = new ol.style.Style({
                          stroke: new ol.style.Stroke({
                              color: '#ffff00',
                              lineDash: null,
                              width: featureWidth
                          })
                      });
  
                  } else {
                      highlightStyle = new ol.style.Style({
                          fill: new ol.style.Fill({
                              color: '#ffff00'
                          })
                      })
                  }
                  featureOverlay.getSource().addFeature(currentFeature);
                  featureOverlay.setStyle(highlightStyle);
              }
              highlight = currentFeature;
          }
      }
  
      if (doHover) {
          if (popupText) {
              overlayPopup.setPosition(coord);
              content.innerHTML = popupText;
              container.style.display = 'block';        
          } else {
              container.style.display = 'none';
              closer.blur();
          }
      }
  };
  
  var onSingleClick = function(evt) {
      if (doHover) {
          return;
      }
      if (sketch) {
          return;
      }
      var pixel = map.getEventPixel(evt.originalEvent);
      var coord = evt.coordinate;
      var popupField;
      var currentFeature;
      var currentFeatureKeys;
      var clusteredFeatures;
      var popupText = '<ul>';
      map.forEachFeatureAtPixel(pixel, function(feature, layer) {
          if (feature instanceof ol.Feature && (layer.get("interactive") || layer.get("interactive") == undefined)) {
              var doPopup = false;
              for (k in layer.get('fieldImages')) {
                  if (layer.get('fieldImages')[k] != "Hidden") {
                      doPopup = true;
                  }
              }
              currentFeature = feature;
              clusteredFeatures = feature.get("features");
              var clusterFeature;
              if (typeof clusteredFeatures !== "undefined") {
                  if (doPopup) {
                      for(var n=0; n<clusteredFeatures.length; n++) {
                          clusterFeature = clusteredFeatures[n];
                          currentFeatureKeys = clusterFeature.getKeys();
                          popupText += '<li><table>'
                          for (var i=0; i<currentFeatureKeys.length; i++) {
                              if (currentFeatureKeys[i] != 'geometry') {
                                  popupField = '';
                                  if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "inline label") {
                                  popupField += '<th>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + ':</th><td>';
                                  } else {
                                      popupField += '<td colspan="2">';
                                  }
                                  if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "header label") {
                                      popupField += '<strong>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + ':</strong><br />';
                                  }
                                  if (layer.get('fieldImages')[currentFeatureKeys[i]] != "ExternalResource") {
                                      popupField += (clusterFeature.get(currentFeatureKeys[i]) != null ? autolinker.link(clusterFeature.get(currentFeatureKeys[i]).toLocaleString()) + '</td>' : '');
                                  } else {
                                      popupField += (clusterFeature.get(currentFeatureKeys[i]) != null ? '<img src="images/' + clusterFeature.get(currentFeatureKeys[i]).replace(/[\\\/:]/g, '_').trim()  + '" /></td>' : '');
                                  }
                                  popupText += '<tr>' + popupField + '</tr>';
                              }
                          } 
                          popupText += '</table></li>';    
                      }
                  }
              } else {
                  currentFeatureKeys = currentFeature.getKeys();
                  if (doPopup) {
                      popupText += '<li><table>';
                      for (var i=0; i<currentFeatureKeys.length; i++) {
                          if (currentFeatureKeys[i] != 'geometry') {
                              popupField = '';
                              if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "inline label") {
                                  popupField += '<th>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + ':</th><td>';
                              } else {
                                  popupField += '<td colspan="2">';
                              }
                              if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "header label") {
                                  popupField += '<strong>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + ':</strong><br />';
                              }
                              if (layer.get('fieldImages')[currentFeatureKeys[i]] != "ExternalResource") {
                                  popupField += (currentFeature.get(currentFeatureKeys[i]) != null ? autolinker.link(currentFeature.get(currentFeatureKeys[i]).toLocaleString()) + '</td>' : '');
                              } else {
                                  popupField += (currentFeature.get(currentFeatureKeys[i]) != null ? '<img src="images/' + currentFeature.get(currentFeatureKeys[i]).replace(/[\\\/:]/g, '_').trim()  + '" /></td>' : '');
                              }
                              popupText += '<tr>' + popupField + '</tr>';
                          }
                      }
                      popupText += '</table>';
                  }
              }
          }
      });
      if (popupText == '<ul>') {
          popupText = '';
      } else {
          popupText += '</ul>';
      }
      
      var viewProjection = map.getView().getProjection();
      var viewResolution = map.getView().getResolution();
      for (i = 0; i < wms_layers.length; i++) {
          if (wms_layers[i][1]) {
              var url = wms_layers[i][0].getSource().getGetFeatureInfoUrl(
                  evt.coordinate, viewResolution, viewProjection,
                  {
                      'INFO_FORMAT': 'text/html',
                  });
              if (url) {
                  popupText = popupText + '<iframe style="width:100%;height:110px;border:0px;" id="iframe" seamless src="' + url + '"></iframe>';
              }
          }
      }
  
      if (popupText) {
          overlayPopup.setPosition(coord);
          content.innerHTML = popupText;
          container.style.display = 'block';        
      } else {
          container.style.display = 'none';
          closer.blur();
      }
  };
  
  
      map.on('pointermove', function(evt) {
          if (evt.dragging) {
              return;
          }
          if (measuring) {
              /** @type {string} */
              var helpMsg = 'Click to start drawing';
              if (sketch) {
                  var geom = (sketch.getGeometry());
                  if (geom instanceof ol.geom.Polygon) {
                      helpMsg = continuePolygonMsg;
                  } else if (geom instanceof ol.geom.LineString) {
                      helpMsg = continueLineMsg;
                  }
              }
              helpTooltipElement.innerHTML = helpMsg;
              helpTooltip.setPosition(evt.coordinate);
          }
      });
      
  
  map.on('pointermove', function(evt) {
      onPointerMove(evt);
  });
  map.on('singleclick', function(evt) {
      onSingleClick(evt);
  });
  
  /**
   * Currently drawn feature.
   * @type {ol.Feature}
   */
  
  /**
   * The help tooltip element.
   * @type {Element}
   */
  var helpTooltipElement;
  
  
  /**
   * Overlay to show the help messages.
   * @type {ol.Overlay}
   */
  var helpTooltip;
  
  
  /**
   * The measure tooltip element.
   * @type {Element}
   */
  var measureTooltipElement;
  
  
  /**
   * Overlay to show the measurement.
   * @type {ol.Overlay}
   */
  var measureTooltip;
  
  
  /**
   * Message to show when the user is drawing a line.
   * @type {string}
   */
  var continueLineMsg = 'Click to continue drawing the line';
  
  
  
  
  
  
  var source = new ol.source.Vector();
  
  var measureLayer = new ol.layer.Vector({
      source: source,
      style: new ol.style.Style({
          fill: new ol.style.Fill({
              color: 'rgba(255, 255, 255, 0.2)'
          }),
          stroke: new ol.style.Stroke({
              color: '#ffcc33',
              width: 3
          }),
          image: new ol.style.Circle({
              radius: 7,
              fill: new ol.style.Fill({
                  color: '#ffcc33'
              })
          })
      })
  });
  
  map.addLayer(measureLayer);
  
  var draw; // global so we can remove it later
  function addInteraction() {
    var type = 'LineString';
    draw = new ol.interaction.Draw({
      source: source,
      type: /** @type {ol.geom.GeometryType} */ (type),
      style: new ol.style.Style({
        fill: new ol.style.Fill({
          color: 'rgba(255, 255, 255, 0.2)'
        }),
        stroke: new ol.style.Stroke({
          color: 'rgba(0, 0, 0, 0.5)',
          lineDash: [10, 10],
          width: 2
        }),
        image: new ol.style.Circle({
          radius: 5,
          stroke: new ol.style.Stroke({
            color: 'rgba(0, 0, 0, 0.7)'
          }),
          fill: new ol.style.Fill({
            color: 'rgba(255, 255, 255, 0.2)'
          })
        })
      })
    });
  
    var listener;
    draw.on('drawstart',
        function(evt) {
          // set sketch
          sketch = evt.feature;
  
          /** @type {ol.Coordinate|undefined} */
          var tooltipCoord = evt.coordinate;
  
          listener = sketch.getGeometry().on('change', function(evt) {
            var geom = evt.target;
            var output;
              output = formatLength( /** @type {ol.geom.LineString} */ (geom));
              tooltipCoord = geom.getLastCoordinate();
            measureTooltipElement.innerHTML = output;
            measureTooltip.setPosition(tooltipCoord);
          });
        }, this);
  
    draw.on('drawend',
        function(evt) {
          measureTooltipElement.className = 'tooltip tooltip-static';
          measureTooltip.setOffset([0, -7]);
          // unset sketch
          sketch = null;
          // unset tooltip so that a new one can be created
          measureTooltipElement = null;
          createMeasureTooltip();
          ol.Observable.unByKey(listener);
        }, this);
  }
  
  
  /**
   * Creates a new help tooltip
   */
  function createHelpTooltip() {
    if (helpTooltipElement) {
      helpTooltipElement.parentNode.removeChild(helpTooltipElement);
    }
    helpTooltipElement = document.createElement('div');
    helpTooltipElement.className = 'tooltip hidden';
    helpTooltip = new ol.Overlay({
      element: helpTooltipElement,
      offset: [15, 0],
      positioning: 'center-left'
    });
    map.addOverlay(helpTooltip);
  }
  
  
  /**
   * Creates a new measure tooltip
   */
  function createMeasureTooltip() {
    if (measureTooltipElement) {
      measureTooltipElement.parentNode.removeChild(measureTooltipElement);
    }
    measureTooltipElement = document.createElement('div');
    measureTooltipElement.className = 'tooltip tooltip-measure';
    measureTooltip = new ol.Overlay({
      element: measureTooltipElement,
      offset: [0, -15],
      positioning: 'bottom-center'
    });
    map.addOverlay(measureTooltip);
  }
  
  
  
  /**
   * format length output
   * @param {ol.geom.LineString} line
   * @return {string}
   */
  var formatLength = function(line) {
    var length;
    var coordinates = line.getCoordinates();
    length = 0;
    var sourceProj = map.getView().getProjection();
    for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {
        var c1 = ol.proj.transform(coordinates[i], sourceProj, 'EPSG:4326');
        var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'EPSG:4326');
        length += ol.sphere.getDistance(c1, c2);
      }
    var output;
    if (length > 100) {
      output = (Math.round(length / 1000 * 100) / 100) +
          ' ' + 'km';
    } else {
      output = (Math.round(length * 100) / 100) +
          ' ' + 'm';
    }
    return output;
  };
  
  addInteraction();
  
  
  
  var geocoder = new Geocoder('nominatim', {
    provider: 'osm',
    lang: 'en-US',
    placeholder: 'Search for ...',
    limit: 5,
    keepOpen: true
  });
  map.addControl(geocoder);
  
  document.getElementsByClassName('gcd-gl-btn')[0].className += ' fa fa-search';
  
  var attributionComplete = false;
  map.on("rendercomplete", function(evt) {
      if (!attributionComplete) {
          var attribution = document.getElementsByClassName('ol-attribution')[0];
          var attributionList = attribution.getElementsByTagName('ul')[0];
          var firstLayerAttribution = attributionList.getElementsByTagName('li')[0];
          var qgis2webAttribution = document.createElement('li');
          qgis2webAttribution.innerHTML = '<a href="https://github.com/tomchadwin/qgis2web">qgis2web</a> &middot; ';
          var olAttribution = document.createElement('li');
          olAttribution.innerHTML = '<a href="https://openlayers.org/">OpenLayers</a> &middot; ';
          var qgisAttribution = document.createElement('li');
          qgisAttribution.innerHTML = '<a href="https://qgis.org/">QGIS</a>';
          attributionList.insertBefore(qgis2webAttribution, firstLayerAttribution);
          attributionList.insertBefore(olAttribution, firstLayerAttribution);
          attributionList.insertBefore(qgisAttribution, firstLayerAttribution);
          attributionComplete = true;
      }
  })
  