geolocation-8.x-3.x-dev/modules/geolocation_google_maps/js/MapFeature/GoogleGeometryWidgetMapConnector.js

modules/geolocation_google_maps/js/MapFeature/GoogleGeometryWidgetMapConnector.js
import { GoogleMapFeature } from "./GoogleMapFeature.js";
import { GeolocationCoordinates } from "../../../../js/Base/GeolocationCoordinates.js";

/**
 * @prop {google.maps.drawing.DrawingManager} drawingManager
 */
export default class GoogleGeometryWidgetMapConnector extends GoogleMapFeature {
  constructor(settings, map) {
    super(settings, map);

    let drawingModes;

    switch (this.settings.field_type.replace("geolocation_geometry_", "")) {
      case "multiline":
      case "line":
        drawingModes = [google.maps.drawing.OverlayType.POLYLINE];
        break;

      case "multipolygon":
      case "polygon":
        drawingModes = [google.maps.drawing.OverlayType.RECTANGLE, google.maps.drawing.OverlayType.POLYGON];
        break;

      case "multipoint":
      case "point":
        drawingModes = [google.maps.drawing.OverlayType.MARKER];
        break;

      default:
        drawingModes = [google.maps.drawing.OverlayType.MARKER, google.maps.drawing.OverlayType.POLYLINE, google.maps.drawing.OverlayType.POLYGON, google.maps.drawing.OverlayType.RECTANGLE];
        break;
    }

    this.drawingManager = new google.maps.drawing.DrawingManager({
      drawingMode: null,
      drawingControl: true,
      drawingControlOptions: {
        position: google.maps.ControlPosition.TOP_CENTER,
        drawingModes,
      },
    });

    this.drawingManager.setMap(this.map.googleMap);
  }

  onMapReady() {
    google.maps.event.addListener(this.drawingManager, "overlaycomplete", (event) => {
      let currentElementCount = 0;
      let newIndex = 0;

      switch (this.settings.field_type.replace("geolocation_geometry_", "")) {
        case "point":
        case "multipoint":
          this.map.dataLayers.get("default").markers.forEach((element) => {
            currentElementCount++;
            const currentElementIndex = this.getIndexByShape(element);
            if (currentElementIndex === null) {
              return;
            }
            if (currentElementIndex >= newIndex) {
              newIndex = currentElementIndex + 1;
            }
          });
          break;

        default:
          this.map.dataLayers.get("default").shapes.forEach((element) => {
            currentElementCount++;
            const currentElementIndex = this.getIndexByShape(element);
            if (currentElementIndex === null) {
              return;
            }
            if (currentElementIndex >= newIndex) {
              newIndex = currentElementIndex + 1;
            }
          });
      }

      if (this.settings.cardinality <= currentElementCount && this.settings.cardinality !== -1) {
        const warning = document.createElement("div");
        warning.innerHTML = `<p>${Drupal.t("Maximum number of element reached.")}</p>`;
        Drupal.dialog(warning, {
          title: Drupal.t("Synchronization"),
        }).showModal();
        return;
      }

      event.overlay.setEditable(true);

      switch (event.type) {
        case google.maps.drawing.OverlayType.MARKER:
          break;

        case google.maps.drawing.OverlayType.POLYLINE:
          break;

        case google.maps.drawing.OverlayType.POLYGON:
        case google.maps.drawing.OverlayType.RECTANGLE:
          const polygon = this.map.createShapePolygon({ type: "Polygon", coordinates: [[]] }, {});
          this.setIndexByShape(polygon, newIndex);
          polygon.updateByGoogleShape(event.overlay);

          this.map.dataLayers.get("default").shapeAdded(polygon);
          break;
      }
    });

    return Promise.resolve();
  }

  setWidgetSubscriber(subscriber) {
    this.subscriber = subscriber;
  }

  /**
   * @param {GeolocationShape} shape
   *   Marker.
   *
   * @return {int|null}
   *   Index.
   */
  getIndexByShape(shape) {
    return Number(shape.wrapper.dataset.geolocationWidgetIndex ?? 0);
  }

  /**
   * @param {int} index
   *   Index.
   *
   * @return {GeolocationShape|null}
   *   Shape.
   */
  getShapeByIndex(index) {
    let returnValue = null;
    this.map.dataLayers.get("default").shapes.forEach((shape) => {
      if (index === this.getIndexByShape(shape)) {
        returnValue = shape;
      }
    });

    return returnValue;
  }

  /**
   * @param {GeolocationShape} shape
   *   Marker.
   * @param {int|false} index
   *   Index.
   */
  setIndexByShape(shape, index = false) {
    if (index === false) {
      delete shape.wrapper.dataset.geolocationWidgetIndex;
    } else {
      shape.wrapper.dataset.geolocationWidgetIndex = index.toString();
    }
  }

  /**
   * @param {Number} index
   *   Index.
   *
   * @return {String}
   *   Title.
   */
  getShapeTitle(index) {
    return `${index + 1}`;
  }

  addShapeSilently(index, geometry) {
    let shape;

    switch (geometry.type) {
      case "Point":
        const coordinates = new GeolocationCoordinates(geometry.coordinates[1], geometry.coordinates[0]);
        const marker = this.map.createMarker(coordinates, {
          title: this.getMarkerTitle(index, coordinates),
          label: index + 1,
          draggable: true,
        });

        this.setIndexByMarker(marker, index);

        marker.geolocationWidgetIgnore = true;
        this.map.dataLayers.get("default").markerAdded(marker);
        delete marker.geolocationWidgetIgnore;

        this.map.fitMapToElements();

        return marker;

      case "LineString":
        shape = this.map.createShapeLine(geometry, {
          title: this.getShapeTitle(index),
          label: index + 1,
          draggable: true,
        });
        break;

      case "Polygon":
        shape = this.map.createShapePolygon(geometry, {
          title: this.getShapeTitle(index),
          label: index + 1,
          draggable: true,
        });
        break;
    }

    if (!shape) return;

    this.setIndexByShape(shape, index);

    shape.geolocationWidgetIgnore = true;
    this.map.dataLayers.get("default").shapeAdded(shape);
    delete shape.geolocationWidgetIgnore;

    this.map.fitMapToElements();

    return shape;
  }

  reorderSilently(newOrder) {
    this.map.dataLayers.get("default").markers.forEach((marker) => {
      const oldIndex = this.getIndexByMarker(marker);
      const newIndex = newOrder.indexOf(oldIndex);

      marker.geolocationWidgetIgnore = true;
      marker.update(null, {
        title: this.getShapeTitle(newIndex),
        label: newIndex + 1,
      });
      delete marker.geolocationWidgetIgnore;

      this.setIndexByMarker(marker, newIndex);
    });
  }

  updateShapeSilently(index, geometry, settings = null) {
    const shape = this.getShapeByIndex(index);

    if (!shape) return this.addShapeSilently(index, geometry);

    if (shape.geometry === geometry && !settings) {
      return;
    }

    shape.geolocationWidgetIgnore = true;
    shape.update(geometry, settings ?? {});
    delete shape.geolocationWidgetIgnore;

    this.map.fitMapToElements();

    return shape;
  }

  removeShapeSilently(index) {
    const shape = this.getShapeByIndex(index);

    shape.geolocationWidgetIgnore = true;
    shape.remove();

    this.map.fitMapToElements();
  }

  onShapeAdded(shape) {
    super.onShapeAdded(shape);

    shape.googleShapes.forEach((googleShape) => {
      if (!googleShape.getEditable()) {
        googleShape.setEditable(true);
      }
    });

    if (shape.geolocationWidgetIgnore ?? false) return;

    this.subscriber?.geometryAdded(shape.geometry, this.getIndexByShape(shape) ?? 0);
  }

  onShapeClicked(shape, coordinates) {
    super.onShapeClicked(shape, coordinates);
    let editing = false;
    shape.googleShapes.forEach((googleShape) => {
      if (googleShape.getEditable()) {
        editing = true;
      }
    });

    if (editing) {
      return;
    }

    // Will trigger onShapeRemove and notify broker.
    shape.remove();
  }

  onShapeUpdated(shape) {
    super.onShapeUpdated(shape);

    if (shape.geolocationWidgetIgnore ?? false) return;

    this.subscriber?.geometryAltered(shape.geometry, this.getIndexByShape(shape));
  }

  onShapeRemove(shape) {
    super.onShapeRemove(shape);

    if (shape.geolocationWidgetIgnore ?? false) return;

    this.subscriber?.geometryRemoved(this.getIndexByShape(shape));
  }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc