RT# 81150 Google now requires api key for drawing api
[freeside.git] / httemplate / elements / polygon.html
1 <%init>
2 my %opt = @_;
3 my $field = $opt{'field'};
4 my $id = $opt{'id'} || $opt{'field'};
5 my $div_id = "div_$id";
6
7 my $vertices_json = $opt{'curr_value'} || '[]';
8
9 my $apikey = FS::Conf->new->config('google_maps_api_key');
10
11 </%init>
12 <& hidden.html, %opt &>
13 <div id="<% $div_id %>" style="height: 600px; width: 600px"></div>
14 <div id="<% $div_id %>_hint" style="width: 100%; border: 2px solid black; text-align: center; box-sizing: border-box; padding: 4px">&nbsp;</div>
15
16 <script src="<% $fsurl %>elements/jquery.js"></script>
17 <script src="https://maps.googleapis.com/maps/api/js?libraries=drawing&v=3.22<% $apikey ? "&key=$apikey" : '' %>"></script>
18 <script>
19 var map;
20 var drawingManager;
21
22 function updateFormInput(event) {
23   var path = window.polygon.getPath();
24   var vertices = []; // array of arrays, geoJSON style
25   for (var i =0; i < path.getLength(); i++) {
26     var xy = path.getAt(i);
27     vertices[i] = [ xy.lat(), xy.lng() ];
28   }
29   if (console) console.log(vertices); //XXX
30   $('#<% $field %>').prop('value', JSON.stringify(vertices));
31 }
32
33 $(function() {
34   mapOptions = {
35     zoom: 4,
36     center: {lat: 39.40114, lng: -96.57127}, // continental U.S.
37     mapTypeId: google.maps.MapTypeId.ROADMAP,
38     panControl: true,
39     scaleControl: true,
40     streetViewControl: false,
41   };
42   var div_map = $('#<% $div_id %>');
43   var div_hint = $('#<% $div_id %>_hint');
44   map = new google.maps.Map(div_map[0], mapOptions);
45
46   var set_hint = function(txt) {
47     div_hint.text(txt);
48   }
49
50   var polygonComplete = function(p) {
51     window.polygon = p;
52     if (drawingManager) {
53       drawingManager.setDrawingMode(null);
54       drawingManager.setOptions({ drawingControl: false });
55     }
56     // double click to delete a vertex (so long as it remains a polygon)
57     p.addListener('dblclick', function (mev) {
58       if (mev.vertex != null && window.polygon.getPath().length > 3) {
59         p.getPath().removeAt(mev.vertex);
60       }
61     });
62     // any time the polygon is modified, update the vertex list
63     p.getPath().addListener('set_at', updateFormInput);
64     p.getPath().addListener('insert_at', updateFormInput);
65     p.getPath().addListener('remove_at', updateFormInput);
66
67     // and also now
68     updateFormInput();
69
70     set_hint('Edit the zone by dragging the markers. Double-click to remove a vertex.');
71
72   };
73
74   var polygonOptions = {
75     fillColor: '#0000a0',
76     fillOpacity: 0.2,
77     strokeColor: '#0000a0',
78     strokeWeight: 2,
79     clickable: false,
80     editable: true,
81     zIndex: 1,
82     map: map,
83   };
84
85   var vertex_array = <% $vertices_json %>;
86   if ( vertex_array.length > 2 ) {
87     // then we already have a polygon. make it acceptable to google maps,
88     // and also create a bounding box for it and fit the map to that.
89
90     var path = [];
91     var bounds = new google.maps.LatLngBounds();
92     for (var i = 0; i < vertex_array.length; i++) {
93       var xy = new google.maps.LatLng(vertex_array[i][0], vertex_array[i][1]);
94       path.push(xy);
95       bounds.extend(xy);
96     }
97
98     polygonOptions.paths = [ path ];
99     polygonComplete(new google.maps.Polygon(polygonOptions));
100     map.fitBounds(bounds);
101
102   } else {
103     // there are no vertices, or not enough to make a polygon, so 
104     // enable drawing mode to create a new one
105
106     drawingManager = new google.maps.drawing.DrawingManager({
107       drawingMode: google.maps.drawing.OverlayType.POLYGON,
108       drawingControl: true,
109       drawingControlOptions: {
110         position: google.maps.ControlPosition.TOP_CENTER,
111         drawingModes: [
112           google.maps.drawing.OverlayType.POLYGON,
113         ]
114       },
115       polygonOptions: polygonOptions,
116     });
117
118     // after a single polygon is drawn: remember it, add a listener to let
119     // nodes be deleted, and exit drawing mode
120     drawingManager.addListener('polygoncomplete', polygonComplete);
121     drawingManager.setMap(map);
122
123     // center the map on the user (for lack of a better choice)
124     if (navigator.geolocation) {
125       navigator.geolocation.getCurrentPosition(function(position) {
126         var pos = {
127           lat: position.coords.latitude,
128           lng: position.coords.longitude
129         };
130
131         map.setCenter(pos);
132         map.setZoom(12);
133       });
134     } // on error, or if geolocation isn't available, do nothing
135
136     set_hint('Click to place the corners of the zone.');
137   }
138
139 });
140
141     </script>
142   </body>
143 </html>