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