Eat out at venues across the Front Range to raise funds for Ukraine.

When you dine at a restaurant or café from our growing list of venues, you support local businesses and the Ukrainian people.

Participating restaurants will donate a portion of the day's proceeds to support Sunflower Seeds Ukraine’s mission and help us to continue growing our impact.

Dine Out for Ukraine

July 23rd, 2026

.mp-root {
  --mp-bg: #ffffff;
  --mp-panel: #f7f8fa;
  --mp-border: #d7dce2;
  --mp-text: #16202a;
  --mp-muted: #5d6875;
  --mp-accent: #0f6b5f;
  --mp-accent-soft: #dff2ee;
  --mp-danger: #a6382f;
  color: var(--mp-text);
  background: var(--mp-bg);
  border: 1px solid var(--mp-border);
  border-radius: 8px;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  overflow: hidden;
}

.mp-header {
  padding: 20px 22px 16px;
  border-bottom: 1px solid var(--mp-border);
}

.mp-title {
  margin: 0;
  font-size: 1.35rem;
  line-height: 1.2;
  font-weight: 700;
}

.mp-description {
  margin: 8px 0 0;
  max-width: 68ch;
  color: var(--mp-muted);
  line-height: 1.45;
}

.mp-body {
  display: grid;
  grid-template-columns: minmax(260px, 34%) minmax(0, 1fr);
  height: min(70vh, 680px);
  min-height: 560px;
}

.mp-list-panel {
  min-width: 0;
  min-height: 0;
  background: var(--mp-panel);
  border-right: 1px solid var(--mp-border);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.mp-list {
  padding: 16px;
}

.mp-group+.mp-group {
  margin-top: 18px;
}

.mp-group-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  margin: 0 0 8px;
  padding: 4px 2px;
  color: var(--mp-muted);
  background: transparent;
  border: 0;
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0;
  text-align: left;
  text-transform: uppercase;
}

.mp-group-toggle:hover,
.mp-group-toggle:focus {
  color: var(--mp-accent);
  outline: none;
}

.mp-group-caret {
  display: inline-grid;
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  place-items: center;
  color: #ffffff;
  background: var(--mp-muted);
  border-radius: 50%;
  font-size: 0.86rem;
  line-height: 1;
}

.mp-group-toggle:hover .mp-group-caret,
.mp-group-toggle:focus .mp-group-caret {
  background: var(--mp-accent);
}

.mp-group-title {
  min-width: 0;
}

.mp-group-items[hidden] {
  display: none;
}

.mp-item {
  display: block;
  width: 100%;
  margin: 0 0 8px;
  padding: 12px;
  color: inherit;
  text-align: left;
  background: #ffffff;
  border: 1px solid var(--mp-border);
  border-radius: 6px;
  cursor: pointer;
}

.mp-item:hover,
.mp-item:focus {
  border-color: var(--mp-accent);
  outline: none;
}

.mp-item.is-selected {
  background: var(--mp-accent-soft);
  border-color: var(--mp-accent);
}

.mp-item-name {
  display: block;
  font-size: 0.98rem;
  font-weight: 700;
  line-height: 1.25;
}

.mp-item-address,
.mp-item-meta {
  display: block;
  margin-top: 5px;
  color: var(--mp-muted);
  font-size: 0.88rem;
  line-height: 1.35;
}

.mp-map-panel {
  position: relative;
  min-width: 0;
}

.mp-map {
  width: 100%;
  height: 100%;
  min-height: 560px;
}

.mp-status {
  padding: 12px 16px;
  color: var(--mp-muted);
  background: #ffffff;
  border-top: 1px solid var(--mp-border);
  font-size: 0.92rem;
}

.mp-status.is-error {
  color: var(--mp-danger);
}

.mp-popup {
  width: min(280px, calc(100vw - 40px));
  padding: 12px;
  color: var(--mp-text);
  background: #ffffff;
  border: 1px solid var(--mp-border);
  border-radius: 8px;
  box-shadow: 0 12px 32px rgba(16, 32, 42, 0.18);
}

.mp-popup-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 6px;
  font-size: 0.98rem;
  line-height: 1.25;
}

.mp-popup-glyph {
  display: inline-grid;
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  padding: 5px 2px;
  place-items: center;
  color: var(--mp-accent);
  background: var(--mp-accent-soft);
  border-radius: 50%;
  font-size: 0.86rem;
  line-height: 1;
}

.mp-popup-title-text {
  min-width: 0;
}

.mp-popup-address,
.mp-popup-meta {
  margin: 0;
  color: var(--mp-muted);
  font-size: 0.86rem;
  line-height: 1.35;
}

.mp-popup-meta {
  margin-top: 8px;
}

@media (max-width: 760px) {
  .mp-body {
    grid-template-columns: 1fr;
    height: auto;
    min-height: 0;
  }

  .mp-list-panel {
    max-height: 360px;
    border-right: 0;
    border-bottom: 1px solid var(--mp-border);
  }

  .mp-map,
  .mp-body {
    min-height: 420px;
  }
}
(function (global) {
  "use strict";

  function requireOpenLayers() {
    if (!global.ol) {
      throw new Error("OpenLayers is required before map-plugin.js");
    }
    return global.ol;
  }

  function createElement(tagName, className, text) {
    var element = document.createElement(tagName);
    if (className) {
      element.className = className;
    }
    if (text !== undefined && text !== null) {
      element.textContent = text;
    }
    return element;
  }

  function getFeatureName(feature) {
    return feature.get("name") || feature.get("Name") || "Untitled location";
  }

  function getFeatureValue(feature, key) {
    var value = feature.get(key);
    return value === undefined || value === null || value === "" ? "" : String(value);
  }

  function getAddress(feature) {
    return getFeatureValue(feature, "address") || getFeatureValue(feature, "Address");
  }

  function getMetadata(feature, excludedKeys) {
    var properties = feature.getProperties();
    return Object.keys(properties)
      .filter(function (key) {
        return excludedKeys.indexOf(key) === -1 && properties[key] !== undefined && properties[key] !== "";
      })
      .sort()
      .map(function (key) {
        return { key: key, value: String(properties[key]) };
      });
  }

  function formatMetaLine(metadata) {
    return metadata
      .slice(0, 2)
      .map(function (item) {
        return item.key + ": " + item.value;
      })
      .join(" | ");
  }

  function normalizeMarkerMapping(mapping, defaultField) {
    if (!mapping) {
      return { field: defaultField, values: {} };
    }
    if (mapping.values || mapping.map) {
      return {
        field: mapping.field || defaultField,
        values: mapping.values || mapping.map || {},
      };
    }
    return { field: defaultField, values: mapping };
  }

  function normalizeOptions(options) {
    var config = options || {};
    var content = config.content || {};
    var data = config.data || {};
    var markers = config.markers || {};
    var categoryMarkers = markers.categories || {};
    var markerFields = markers.fields || {};
    var imageMarkers = markers.images || {};
    var fontMarkers = markers.font || {};

    var settings = Object.assign(
      {
        categoryField: "",
        categoryColorMap: {},
        categoryColorField: "",
        categoryGlyphMap: {},
        categoryGlyphField: "",
        categoryImageMap: {},
        categoryImageField: "",
        categoryIconMap: {},
        categorySizeMap: {},
        categorySizeField: "",
        title: "",
        description: "",
        groupBy: "",
        iconBaseUrl: "",
        iconColorField: "",
        iconField: "",
        iconFontFamily: "",
        iconFontWeight: "normal",
        iconGlyphField: "",
        iconSizeField: "",
        initialZoom: 12,
      },
      config
    );

    settings.containerId = data.containerId || settings.containerId;
    settings.kmlUrl = data.kmlUrl || settings.kmlUrl;
    settings.groupBy = data.groupBy || settings.groupBy;
    settings.initialZoom =
      data.initialZoom === undefined ? settings.initialZoom : data.initialZoom;

    settings.title = content.title || settings.title;
    settings.description = content.description || settings.description;

    settings.categoryField = categoryMarkers.field || settings.categoryField || settings.groupBy;
    settings.categoryIconMap = categoryMarkers.map || settings.categoryIconMap;
    var glyphMapping = normalizeMarkerMapping(
      categoryMarkers.glyphs || settings.categoryGlyphMap,
      settings.categoryGlyphField || settings.categoryField
    );
    var colorMapping = normalizeMarkerMapping(
      categoryMarkers.colors || settings.categoryColorMap,
      settings.categoryColorField || settings.categoryField
    );
    var sizeMapping = normalizeMarkerMapping(
      categoryMarkers.sizes || settings.categorySizeMap,
      settings.categorySizeField || settings.categoryField
    );
    var imageMapping = normalizeMarkerMapping(
      categoryMarkers.icons || settings.categoryImageMap,
      settings.categoryImageField || settings.categoryField
    );
    settings.categoryGlyphField = glyphMapping.field || settings.categoryGlyphField;
    settings.categoryColorField = colorMapping.field || settings.categoryColorField;
    settings.categorySizeField = sizeMapping.field || settings.categorySizeField;
    settings.categoryImageField = imageMapping.field || settings.categoryImageField;
    settings.categoryGlyphMap = glyphMapping.values || settings.categoryGlyphMap;
    settings.categoryColorMap = colorMapping.values || settings.categoryColorMap;
    settings.categorySizeMap = sizeMapping.values || settings.categorySizeMap;
    settings.categoryImageMap = imageMapping.values || settings.categoryImageMap;

    settings.iconBaseUrl = imageMarkers.baseUrl || settings.iconBaseUrl;
    settings.iconField = imageMarkers.field || markerFields.image || settings.iconField;

    settings.iconFontFamily = fontMarkers.family || settings.iconFontFamily;
    settings.iconFontWeight = fontMarkers.weight || settings.iconFontWeight;
    settings.iconGlyphField = markerFields.glyph || settings.iconGlyphField;
    settings.iconColorField = markerFields.color || settings.iconColorField;
    settings.iconSizeField = markerFields.size || settings.iconSizeField;

    settings.categoryField = settings.categoryField || settings.groupBy;
    settings.categoryGlyphField = settings.categoryGlyphField || settings.categoryField;
    settings.categoryColorField = settings.categoryColorField || settings.categoryField;
    settings.categorySizeField = settings.categorySizeField || settings.categoryField;
    settings.categoryImageField = settings.categoryImageField || settings.categoryField;
    settings.categoryIconMap = settings.categoryIconMap || {};
    settings.categoryGlyphMap = settings.categoryGlyphMap || {};
    settings.categoryColorMap = settings.categoryColorMap || {};
    settings.categorySizeMap = settings.categorySizeMap || {};
    settings.categoryImageMap = settings.categoryImageMap || {};
    return settings;
  }

  function init(options) {
    var ol = requireOpenLayers();
    var settings = normalizeOptions(options);

    if (!settings.containerId) {
      throw new Error("MapPlugin.init requires containerId");
    }
    if (!settings.kmlUrl) {
      throw new Error("MapPlugin.init requires kmlUrl");
    }

    var container = document.getElementById(settings.containerId);
    if (!container) {
      throw new Error("MapPlugin container not found: " + settings.containerId);
    }

    container.innerHTML = "";
    container.classList.add("mp-root");

    if (settings.title || settings.description) {
      var header = createElement("div", "mp-header");
      if (settings.title) {
        header.appendChild(createElement("h2", "mp-title", settings.title));
      }
      if (settings.description) {
        header.appendChild(createElement("p", "mp-description", settings.description));
      }
      container.appendChild(header);
    }

    var body = createElement("div", "mp-body");
    var listPanel = createElement("aside", "mp-list-panel");
    var list = createElement("div", "mp-list");
    var mapPanel = createElement("div", "mp-map-panel");
    var mapElement = createElement("div", "mp-map");
    var status = createElement("div", "mp-status", "Loading locations...");

    listPanel.appendChild(list);
    mapPanel.appendChild(mapElement);
    body.appendChild(listPanel);
    body.appendChild(mapPanel);
    container.appendChild(body);
    container.appendChild(status);

    var popup = createElement("div", "mp-popup");
    popup.style.display = "none";
    mapPanel.appendChild(popup);

    var overlay = new ol.Overlay({
      element: popup,
      offset: [0, -44],
      positioning: "bottom-center",
      stopEvent: false,
    });

    var selectedFeature = null;
    var itemById = {};
    var groupById = {};
    var groupControlsByName = {};
    var iconStyleCache = {};
    var collapsedGroups = {};

    var selectedCircleStyle = new ol.style.Style({
      image: new ol.style.Circle({
        radius: 5,
        fill: new ol.style.Fill({ color: "#f4c542" }),
        stroke: new ol.style.Stroke({ color: "#155caa", width: 6 }),
      }),
    });

    var defaultCircleStyle = new ol.style.Style({
      image: new ol.style.Circle({
        radius: 6,
        fill: new ol.style.Fill({ color: "#2f6fb0" }),
        stroke: new ol.style.Stroke({ color: "#ffffff", width: 2 }),
      }),
    });

    function joinIconUrl(baseUrl, iconValue) {
      if (!baseUrl || !iconValue) {
        return "";
      }
      return baseUrl + iconValue;
    }

    function getCategoryIconConfig(feature) {
      var categoryValue = settings.categoryField
        ? getFeatureValue(feature, settings.categoryField)
        : "";
      return settings.categoryIconMap[categoryValue] || settings.categoryIconMap.default || {};
    }

    function getCategoryMapValue(feature, map, legacyKey) {
      var field =
        legacyKey === "glyph"
          ? settings.categoryGlyphField
          : legacyKey === "color"
          ? settings.categoryColorField
          : legacyKey === "size"
          ? settings.categorySizeField
          : settings.categoryImageField;
      var mapValue = field ? getFeatureValue(feature, field) : "";
      var value = map[mapValue];
      if (value === undefined || value === null || value === "") {
        value = map.default;
      }
      if (value === undefined || value === null || value === "") {
        value = getCategoryIconConfig(feature)[legacyKey];
      }
      return value === undefined || value === null ? "" : value;
    }

    function getIconScale(feature) {
      var rawSize = settings.iconSizeField ? getFeatureValue(feature, settings.iconSizeField) : "";
      var mappedSize = getCategoryMapValue(feature, settings.categorySizeMap, "size");
      var size = rawSize === "" ? Number.parseFloat(mappedSize) : Number.parseFloat(rawSize);

      if (!Number.isFinite(size) || size <= 0) {
        return 1;
      }

      return Math.max(0.5, Math.min(size, 2));
    }

    function getIconColor(feature) {
      var color = settings.iconColorField ? getFeatureValue(feature, settings.iconColorField) : "";
      return color || getCategoryMapValue(feature, settings.categoryColorMap, "color") || "#2f6fb0";
    }

    function getIconGlyph(feature) {
      var glyph = settings.iconGlyphField ? getFeatureValue(feature, settings.iconGlyphField) : "";
      return glyph || getCategoryMapValue(feature, settings.categoryGlyphMap, "glyph") || "";
    }

    function getSelectedIconHaloStyle(scale) {
      var cacheKey = "halo|" + scale;
      if (!iconStyleCache[cacheKey]) {
        iconStyleCache[cacheKey] = new ol.style.Style({
          image: new ol.style.Circle({
            radius: 13 * scale,
            fill: new ol.style.Fill({ color: "#f4c542" }),
            stroke: new ol.style.Stroke({ color: "#155caa", width: 6 }),
          }),
        });
      }
      return iconStyleCache[cacheKey];
    }

    function getFontIconStyle(feature, isSelected) {
      if (!settings.iconFontFamily) {
        return null;
      }

      var glyph = getIconGlyph(feature);
      if (!glyph) {
        return null;
      }

      var iconScale = getIconScale(feature);
      var markerScale = isSelected ? iconScale * 0.85 : iconScale;
      var color = getIconColor(feature);
      var fontSize = Math.round(26 * markerScale);
      var cacheKey = [
        "font",
        glyph,
        settings.iconFontFamily,
        settings.iconFontWeight,
        color,
        fontSize,
      ].join("|");

      if (!iconStyleCache[cacheKey]) {
        iconStyleCache[cacheKey] = new ol.style.Style({
          text: new ol.style.Text({
            text: glyph,
            font: settings.iconFontWeight + " " + fontSize + "px " + settings.iconFontFamily,
            fill: new ol.style.Fill({ color: color }),
            stroke: new ol.style.Stroke({ color: "#ffffff", width: 4 }),
            offsetY: -fontSize * 0.9,
          }),
        });
      }

      return iconStyleCache[cacheKey];
    }

    function getImageIconStyle(feature, isSelected) {
      var iconValue = settings.iconField ? getFeatureValue(feature, settings.iconField) : "";
      iconValue = iconValue || getCategoryMapValue(feature, settings.categoryImageMap, "icon");
      var iconUrl = joinIconUrl(settings.iconBaseUrl, iconValue);
      if (!iconUrl) {
        return null;
      }

      var iconScale = getIconScale(feature);
      var markerScale = isSelected ? iconScale * 0.85 : iconScale;
      var cacheKey = iconUrl + "|" + markerScale;
      if (!iconStyleCache[cacheKey]) {
        iconStyleCache[cacheKey] = new ol.style.Style({
          image: new ol.style.Icon({
            src: iconUrl,
            anchor: [0.5, 1],
            crossOrigin: "anonymous",
            scale: markerScale,
          }),
        });
      }

      return isSelected
        ? [getSelectedIconHaloStyle(iconScale), iconStyleCache[cacheKey]]
        : iconStyleCache[cacheKey];
    }

    function getIconStyle(feature, isSelected) {
      var fontIconStyle = getFontIconStyle(feature, isSelected);
      if (fontIconStyle) {
        return isSelected
          ? [getSelectedIconHaloStyle(getIconScale(feature)), fontIconStyle]
          : fontIconStyle;
      }

      if (settings.iconBaseUrl) {
        var imageIconStyle = getImageIconStyle(feature, isSelected);
        if (imageIconStyle) {
          return imageIconStyle;
        }
      }

      return isSelected ? selectedCircleStyle : defaultCircleStyle;
    }

    var vectorSource = new ol.source.Vector();
    var vectorLayer = new ol.layer.Vector({
      source: vectorSource,
      style: function (feature) {
        return getIconStyle(feature, feature === selectedFeature);
      },
    });

    var map = new ol.Map({
      target: mapElement,
      overlays: [overlay],
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM(),
        }),
        vectorLayer,
      ],
      view: new ol.View({
        center: ol.proj.fromLonLat([-98.5795, 39.8283]),
        zoom: 4,
      }),
    });

    function setStatus(message, isError) {
      status.textContent = message;
      status.classList.toggle("is-error", Boolean(isError));
    }

    function renderPopup(feature) {
      var metadata = getMetadata(feature, [
        "geometry",
        "name",
        "Name",
        "description",
        "address",
        "Address",
        "latitude",
        "longitude",
        settings.iconColorField,
        settings.iconField,
        settings.iconGlyphField,
        settings.iconSizeField,
      ]);
      popup.innerHTML = "";
      var title = createElement("h3", "mp-popup-title");
      var popupGlyph = getIconGlyph(feature);
      if (popupGlyph) {
        var glyph = createElement("span", "mp-popup-glyph", popupGlyph);
        glyph.style.color = getIconColor(feature);
        if (settings.iconFontFamily) {
          glyph.style.fontFamily = settings.iconFontFamily;
          glyph.style.fontWeight = settings.iconFontWeight;
        }
        title.appendChild(glyph);
      }
      title.appendChild(createElement("span", "mp-popup-title-text", getFeatureName(feature)));
      popup.appendChild(title);
      var address = getAddress(feature);
      if (address) {
        popup.appendChild(createElement("p", "mp-popup-address", address));
      }
      var metaLine = formatMetaLine(metadata);
      if (metaLine) {
        popup.appendChild(createElement("p", "mp-popup-meta", metaLine));
      }
      popup.style.display = "block";
    }

    function selectFeature(feature, scrollList) {
      selectedFeature = feature;
      Object.keys(itemById).forEach(function (id) {
        itemById[id].classList.toggle("is-selected", feature && feature.getId() === id);
      });

      if (!feature) {
        popup.style.display = "none";
        overlay.setPosition(undefined);
        vectorLayer.changed();
        return;
      }

      var geometry = feature.getGeometry();
      if (geometry) {
        var coordinate = geometry.getCoordinates();
        overlay.setPosition(coordinate);
        renderPopup(feature);
        map.getView().animate({ center: coordinate, duration: 250 });
      }

      if (scrollList && itemById[feature.getId()]) {
        expandGroup(groupById[feature.getId()]);
        itemById[feature.getId()].scrollIntoView({ block: "nearest", behavior: "smooth" });
      }

      vectorLayer.changed();
    }

    function groupFeatures(features) {
      return features.reduce(function (groups, feature) {
        var groupName = settings.groupBy ? getFeatureValue(feature, settings.groupBy) : "";
        groupName = groupName || "Other";
        if (!groups[groupName]) {
          groups[groupName] = [];
        }
        groups[groupName].push(feature);
        return groups;
      }, {});
    }

    function renderList(features) {
      list.innerHTML = "";
      itemById = {};
      groupById = {};
      groupControlsByName = {};
      var groups = groupFeatures(features);
      Object.keys(groups)
        .sort()
        .forEach(function (groupName) {
          var groupElement = createElement("section", "mp-group");
          var groupId = "mp-group-" + groupName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
          var groupItems = groups[groupName].sort(function (a, b) {
            return getFeatureName(a).localeCompare(getFeatureName(b));
          });
          var isCollapsed = Boolean(collapsedGroups[groupName]);
          var header = createElement("button", "mp-group-toggle");
          var caret = createElement("span", "mp-group-caret", isCollapsed ? "+" : "-");
          var title = createElement(
            "span",
            "mp-group-title",
            groupName + " (" + groupItems.length + ")"
          );
          var content = createElement("div", "mp-group-items");

          header.type = "button";
          header.setAttribute("aria-expanded", String(!isCollapsed));
          header.setAttribute("aria-controls", groupId);
          header.appendChild(caret);
          header.appendChild(title);
          content.id = groupId;
          content.hidden = isCollapsed;

          header.addEventListener("click", function () {
            setGroupCollapsed(groupName, !collapsedGroups[groupName]);
          });

          groupControlsByName[groupName] = {
            caret: caret,
            content: content,
            header: header,
          };
          groupElement.appendChild(header);

          groupItems.forEach(function (feature) {
            var item = createElement("button", "mp-item");
            item.type = "button";
            item.appendChild(createElement("span", "mp-item-name", getFeatureName(feature)));

            var address = getAddress(feature);
            if (address) {
              item.appendChild(createElement("span", "mp-item-address", address));
            }

            var metaLine = formatMetaLine(
              getMetadata(feature, [
                "geometry",
                "name",
                "Name",
                "address",
                "Address",
                "latitude",
                "longitude",
                settings.iconColorField,
                settings.iconField,
                settings.iconGlyphField,
                settings.iconSizeField,
              ])
            );
            if (metaLine) {
              item.appendChild(createElement("span", "mp-item-meta", metaLine));
            }

            item.addEventListener("click", function () {
              if (selectedFeature === feature) {
                selectFeature(null, false);
                return;
              }
              selectFeature(feature, false);
            });

            itemById[feature.getId()] = item;
            groupById[feature.getId()] = groupName;
            content.appendChild(item);
          });

          groupElement.appendChild(content);
          list.appendChild(groupElement);
        });
    }

    function setGroupCollapsed(groupName, isCollapsed) {
      if (!groupName || !groupControlsByName[groupName]) {
        return;
      }

      collapsedGroups[groupName] = isCollapsed;
      groupControlsByName[groupName].content.hidden = isCollapsed;
      groupControlsByName[groupName].header.setAttribute("aria-expanded", String(!isCollapsed));
      groupControlsByName[groupName].caret.textContent = isCollapsed ? "+" : "-";
    }

    function expandGroup(groupName) {
      setGroupCollapsed(groupName, false);
    }

    function fitMap(features) {
      if (!features.length) {
        return;
      }
      var extent = vectorSource.getExtent();
      map.getView().fit(extent, {
        padding: [40, 40, 40, 40],
        maxZoom: settings.initialZoom,
        duration: 250,
      });
    }

    map.on("click", function (event) {
      var feature = map.forEachFeatureAtPixel(event.pixel, function (candidate) {
        return candidate;
      });
      if (feature) {
        selectFeature(feature, true);
      }
    });

    fetch(settings.kmlUrl)
      .then(function (response) {
        if (!response.ok) {
          throw new Error("KML request failed with status " + response.status);
        }
        return response.text();
      })
      .then(function (kmlText) {
        var features = new ol.format.KML({ extractStyles: false }).readFeatures(kmlText, {
          featureProjection: "EPSG:3857",
        });

        features = features.filter(function (feature, index) {
          if (!feature.getGeometry()) {
            return false;
          }
          feature.setId("mp-feature-" + index);
          return true;
        });

        if (!features.length) {
          throw new Error("KML did not contain any point placemarks");
        }

        vectorSource.addFeatures(features);
        renderList(features);
        fitMap(features);
        setStatus(features.length + " location(s) loaded.");
      })
      .catch(function (error) {
        list.innerHTML = "";
        setStatus(error.message, true);
      });

    return {
      map: map,
      source: vectorSource,
      selectFeature: selectFeature,
    };
  }

  global.MapPlugin = {
    init: init,
  };
})(window);

Venues by Location

Boulder

Colorado Springs

Denver

Estes Park

Fort Collins

Glendale

Lafayette

Longmont

Louisville

Superior