summaryrefslogtreecommitdiff
path: root/httemplate/elements/polygon.html
blob: a0d380bb8f1710c008c86f3e8b66dd427665428e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<%init>
my %opt = @_;
my $field = $opt{'field'};
my $id = $opt{'id'} || $opt{'field'};
my $div_id = "div_$id";

my $vertices_json = $opt{'curr_value'} || '[]';

my $apikey = FS::Conf->new->config('google_maps_api_key');

</%init>
<& hidden.html, %opt &>
<div id="<% $div_id %>" style="height: 600px; width: 600px"></div>
<div id="<% $div_id %>_hint" style="width: 100%; border: 2px solid black; text-align: center; box-sizing: border-box; padding: 4px">&nbsp;</div>

<script src="https://maps.googleapis.com/maps/api/js?libraries=drawing&v=3.22<% $apikey ? "&key=$apikey" : '' %>"></script>
<script>
var map;
var drawingManager;

function updateFormInput(event) {
  var path = window.polygon.getPath();
  var vertices = []; // array of arrays, geoJSON style
  for (var i =0; i < path.getLength(); i++) {
    var xy = path.getAt(i);
    vertices[i] = [ xy.lat(), xy.lng() ];
  }
  if (console) console.log(vertices); //XXX
  $('#<% $field %>').prop('value', JSON.stringify(vertices));
}

$(function() {
  mapOptions = {
    zoom: 4,
    center: {lat: 39.40114, lng: -96.57127}, // continental U.S.
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    panControl: true,
    scaleControl: true,
    streetViewControl: false,
  };
  var div_map = $('#<% $div_id %>');
  var div_hint = $('#<% $div_id %>_hint');
  map = new google.maps.Map(div_map[0], mapOptions);

  var set_hint = function(txt) {
    div_hint.text(txt);
  }

  var polygonComplete = function(p) {
    window.polygon = p;
    if (drawingManager) {
      drawingManager.setDrawingMode(null);
      drawingManager.setOptions({ drawingControl: false });
    }
    // double click to delete a vertex (so long as it remains a polygon)
    p.addListener('dblclick', function (mev) {
      if (mev.vertex != null && window.polygon.getPath().length > 3) {
        p.getPath().removeAt(mev.vertex);
      }
    });
    // any time the polygon is modified, update the vertex list
    p.getPath().addListener('set_at', updateFormInput);
    p.getPath().addListener('insert_at', updateFormInput);
    p.getPath().addListener('remove_at', updateFormInput);

    // and also now
    updateFormInput();

    set_hint('Edit the zone by dragging the markers. Double-click to remove a vertex.');

  };

  var polygonOptions = {
    fillColor: '#0000a0',
    fillOpacity: 0.2,
    strokeColor: '#0000a0',
    strokeWeight: 2,
    clickable: false,
    editable: true,
    zIndex: 1,
    map: map,
  };

  var vertex_array = <% $vertices_json %>;
  if ( vertex_array.length > 2 ) {
    // then we already have a polygon. make it acceptable to google maps,
    // and also create a bounding box for it and fit the map to that.

    var path = [];
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0; i < vertex_array.length; i++) {
      var xy = new google.maps.LatLng(vertex_array[i][0], vertex_array[i][1]);
      path.push(xy);
      bounds.extend(xy);
    }

    polygonOptions.paths = [ path ];
    polygonComplete(new google.maps.Polygon(polygonOptions));
    map.fitBounds(bounds);

  } else {
    // there are no vertices, or not enough to make a polygon, so 
    // enable drawing mode to create a new one

    drawingManager = new google.maps.drawing.DrawingManager({
      drawingMode: google.maps.drawing.OverlayType.POLYGON,
      drawingControl: true,
      drawingControlOptions: {
        position: google.maps.ControlPosition.TOP_CENTER,
        drawingModes: [
          google.maps.drawing.OverlayType.POLYGON,
        ]
      },
      polygonOptions: polygonOptions,
    });

    // after a single polygon is drawn: remember it, add a listener to let
    // nodes be deleted, and exit drawing mode
    drawingManager.addListener('polygoncomplete', polygonComplete);
    drawingManager.setMap(map);

    // center the map on the user (for lack of a better choice)
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(function(position) {
        var pos = {
          lat: position.coords.latitude,
          lng: position.coords.longitude
        };

        map.setCenter(pos);
        map.setZoom(12);
      });
    } // on error, or if geolocation isn't available, do nothing

    set_hint('Click to place the corners of the zone.');
  }

});

    </script>
  </body>
</html>