b7d135dd6204a8dd1cfd896e5dfb2b5ab87608cf
[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 g = feature.getGeometry();
103     if (g.getType() == 'Point') {
104       bounds.extend(g.get());
105     } else if (g.getArray) {
106       g.getArray().forEach(function(point) { bounds.extend(point); });
107     }
108   });
109
110   map.fitBounds(bounds);
111   map.data.setStyle(featureStyle);
112
113   var info = new google.maps.InfoWindow;
114   map.data.addListener('click', function(ev) {
115     var feature = ev.feature;
116     if ( feature.getGeometry().getType() == 'Point' ) {
117       // then pop up an info box with the feature content
118       info.close();
119       info.setPosition(feature.getGeometry().get());
120       info.setContent(feature.getProperty('content'));
121       info.open(map);
122     }
123
124     // snap to feature ROI if it has one
125     if ( feature.getProperty('bounds') ) {
126       map.fitBounds( feature.getProperty('bounds') );
127     }
128
129   }); // addListener()
130
131   data_overlays.forEach(function(x) {
132     var url = x.url;
133     delete x.url;
134     var overlay = new google.maps.GroundOverlay( url, x );
135     overlay.setMap(map);
136     overlay.setOpacity(0.4);
137     overlays.push(overlay); 
138   });
139 }
140
141 $().ready( initMap );
142 </script>
143