Home Reference Source Test Repository

src/components/map/mapbox/markerset.js

import { Component } from "../../../core/bane";
import Arkham from "../../../core/arkham";
import MapActions from "../actions";
import MapState from "../state";
import React from "react";
import Pin from "../views/pin.jsx";

import "mapbox.js";

let L = window.L;

class MarkerSet extends Component {

  initialize({ pois, map, layer }) {
    this.events = {
      // "click.marker .poi": "_poiClick", doesn't work, because marker is z-indexed lower than popup-pane?
      "click.marker .pin": "_poiClick"
    };

    this.pois = pois;
    this.map = map;
    this.layer = layer;

    this.listen();

    this._createLayer();
    this._clearMarkers();
    this._createGeoJSON();
    this._addIcons();

    this.layer.addTo(this.map);
    this.map.fitBounds(this.layer.getBounds(), { padding: [ 50, 50 ], maxZoom:  14 });
  }

  listen() {
    let _this = this;

    Arkham.off("map.poihover");
    Arkham.on("map.poihover", (data) => {
      let layer = _this._findLayerByIndex(data.poiIndex);
      _this._poiHover(layer);
    });

    Arkham.off("map.poiunhover");
    Arkham.on("map.poiunhover", (data) => {
      let layer = _this._findLayerByIndex(data.poiIndex);
      _this._poiUnhover(layer);
    });

  }

  _findLayerByIndex(i) {
    let l;

    this.layer.eachLayer(function(layer) {
      if (layer.feature.properties.index === (i)) {
        l = layer;
      }
    });

    return l;
  }

  _createGeoJSON() {
    let geojson = {
      type: "FeatureCollection",
      features: []
    };

    for (let i = 0, l = this.pois.length; i < l; i++) {
      let geo = this.pois[i].geo;

      if(geo.geometry.coordinates[0] === null || geo.geometry.coordinates[1] === null) {
        continue;
      } else {
        geo.properties.index = i;
        geojson.features.push(geo);
      }
    }

    this.layer.setGeoJSON(geojson);
  }

  _addIcons() {
    this.layer.eachLayer(function(l) {
      let myIcon = L.divIcon({
        className: "poi js-poi",
        iconSize: [14, 14]
      });

      l.setIcon(myIcon);
    });
  }

  _createIcon(layer) {
    let state = MapState.getState();
    // If there's no active set for the current view, use the first set
    let index = state.sets[state.activeSetIndex] ?
      state.activeSetIndex :
      state.lastActiveSetIndex;

    let set = state.sets[index || 0];

    if (!set) {
      return;
    }

    let pin = set.items[layer.feature.properties.index];
    let poi = { pin: pin };
    let markup = React.renderToStaticMarkup(React.createElement(Pin, poi));
    // let pin = PinTemplate(layer.feature.properties);
    return markup;
  }

  _clearMarkers() {
    this.layer.setGeoJSON([]);
  }

  _createLayer() {
    this.layer
      .off("mouseover")
      .off("mouseout");

    this.layer
      .on("mouseover", (e) => {
        this._poiHover(e.layer);
      })
      .on("mouseout", (e) => {
        this._poiUnhover(e.layer);
      });
    
    this.layer.off("click");
    this.layer.on("click", (e) => {
      this._poiClick(e);
    });
  }

  _poiHover(layer) {
    // this._fixzIndex(layer); Not needed since pop-ups moved off the markers?
    let template = this._createIcon(layer),
        lat = layer._latlng.lat,
        lng = layer._latlng.lng;

    this.activeLayer = layer;
    this.popup = L.popup({
        closeButton: false,
        keepInView: true,
        offset: L.point(0, -25)
      })
      .setLatLng(L.latLng(lat, lng))
      .setContent(template)
      .openOn(this.map);

    let poiIndex = layer.feature.properties.index;
    MapActions.itemHighlight(poiIndex);
  }

  // A layer argument is passed in, but it is not used
  // The defined argument has been removed to pass ESLint
  _poiUnhover(layer) {
    // Use if needed
    this.activeLayer = layer;
  }

  _poiClick(event) {
    let poiIndex = (event.layer || this.activeLayer).feature.properties.index,
        poi = this.pois[poiIndex];
    if (poi.item_type === "Place") {
      MapActions.gotoPlace({ place: poi.slug, placeTitle: poi.title, breadcrumb: poi.subtitle });
    } else {
      MapActions.poiOpen({ index: poiIndex, poi });
    }
  }

  _fixzIndex(currentLayer) {
    this.layer.eachLayer(function(layer) {
      layer._icon.style.zIndex = layer._icon._leaflet_pos.y;
    });
    currentLayer._icon.style.zIndex = currentLayer._icon._leaflet_pos.y + currentLayer.options.zIndexOffset + 60;
  }

}

export default MarkerSet;