47db1507d4a4c1c828052bc1ce73930a6e95c439
[freeside.git] / httemplate / search / elements / gmap.html
1 <%args>
2 @features
3 @overlays
4 </%args>
5 <%doc>
6 Generic Google Maps front end.
7
8 <& /elements/gmap.html,
9   features => [
10     { id => 'svc_acct/12',
11       geometry => {
12         type        => 'Point',
13         coordinates => [ -86, 40 ], # optionally altitude as the third coord
14       },
15       properties => {
16         # see https://developers.google.com/maps/documentation/javascript/3.exp/reference#Data.StyleOptions
17         style => {
18           icon => {
19             scale => 4,
20             fillColor => 'orange',
21           }
22         },
23         # content of popup info box (might AJAX this later)
24         content => '<a href="view/svc_acct.cgi?12">username@example.com</a>',
25       }
26     }, # end of feature
27   ],
28   overlays => [
29     { url => 'https://localhost/freeside/view/sector_map-png.html?102',
30       west  => -130.0,
31       east  => -128.0,
32       south => 10.0,
33       north => 12.0,
34     }, # make a ground overlay
35   ],
36 &>
37
38 </%doc>
39 <%init>
40 foreach (@features) {
41   $_->{type} = 'Feature';
42   # any other per-feature massaging can go here
43 }
44 my $tree = {
45   type => 'FeatureCollection',
46   features => \@features
47 };
48
49 </%init>
50 <div id="map_canvas"></div>
51
52 <style type="text/css">
53 html { height: 100% }
54
55 body { height: 100%; margin: 0px; padding: 0px }
56
57 #map_canvas { height: 100%; }
58 </style>
59
60 <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3">
61 </script>
62
63 <script type="text/javascript">
64
65 var data_geojson = <% encode_json($tree) %>;
66 var data_overlays = <% encode_json(\@overlays) %>;
67
68 var baseStyle = {
69   clickable: true,
70   icon: {
71     path: google.maps.SymbolPath.CIRCLE,
72     scale: 4,
73     fillColor: 'green',
74     fillOpacity: 1,
75     strokeColor: 'black',
76     strokeWeight: 1,
77   },
78 };
79
80 var featureStyle = function(feature) {
81   // jQuery.extend(): merge properties of objects
82   // 'true' makes it a deep copy; start the merge with {} so that
83   // baseStyle doesn't get overwritten
84   return $.extend(true, {}, baseStyle, feature.getProperty('style'));
85 };
86
87 var map;
88 var overlays = [];
89 function initMap() {
90   var canvas = $('#map_canvas');
91   map = new google.maps.Map(canvas[0], { zoom: 6 });
92   try {
93     map.data.addGeoJson(data_geojson);
94   } catch(ex) {
95     console.log(ex.toString);
96     debugger;
97   }
98
99   // construct bounds around all of the features
100   var bounds = new google.maps.LatLngBounds;
101   map.data.forEach(function(feature) {
102     var b = feature.getProperty('bounds');
103     if (b) { // if it specifies an ROI, include all of it 
104       bounds.union(b);
105     } else {
106       var g = feature.getGeometry();
107       if (g.getType() == 'Point') {
108         bounds.extend(g.get());
109       } else if (g.getArray) {
110         g.getArray().forEach(function(point) { bounds.extend(point); });
111       }
112     }
113   });
114
115   map.fitBounds(bounds);
116   map.data.setStyle(featureStyle);
117
118   var info = new google.maps.InfoWindow;
119   map.data.addListener('click', function(ev) {
120     var feature = ev.feature;
121     if ( feature.getGeometry().getType() == 'Point' ) {
122       // then pop up an info box with the feature content
123       info.close();
124       info.setPosition(feature.getGeometry().get());
125       info.setContent(feature.getProperty('content'));
126       info.open(map);
127     }
128
129     // snap to feature ROI if it has one
130     if ( feature.getProperty('bounds') ) {
131       map.fitBounds( feature.getProperty('bounds') );
132     }
133
134   }); // addListener()
135
136   data_overlays.forEach(function(x) {
137     var url = x.url;
138     delete x.url;
139     var overlay = new google.maps.GroundOverlay( url, x );
140     overlay.setMap(map);
141     overlay.setOpacity(0.4);
142     overlays.push(overlay); 
143   });
144 }
145
146 $().ready( initMap );
147 </script>
148