2 * Description: display a query result in a googlemap
3 * Copyright (c) 2012 UPMC Sorbonne Universite - INRIA
7 // xxx TODO -- this one could use a bit of cleaning like what was done for the first plugins
8 // especially wrt using 'instance' and 'data' in such a confusing way
13 init : function( options ) {
15 return this.each(function(){
17 var $this = jQuery(this),
18 data = $this.data('GoogleMap'), GoogleMap = jQuery('<div />', {text : $this.attr('title')});
20 // If the plugin hasn't been initialized yet
23 /* Plugin initialization */
25 //google.load('maps', '3', { other_params: 'sensor=false' });
26 //google.setOnLoadCallback(initialize);
28 $this.data('map', null);
29 $this.data('markerCluster', null);
30 $this.data('markers', []);
32 var myLatlng = new google.maps.LatLng(options.latitude, options.longitude);
36 mapTypeId: google.maps.MapTypeId.ROADMAP
39 var map = new google.maps.Map(document.getElementById("map"), myOptions);
40 $this.data('map', map);
42 /* End of plugin initialization */
44 jQuery(this).data('GoogleMap', {
45 plugin_uuid: options.plugin_uuid,
46 query_uuid: options.query_uuid,
48 current_resources: Array(),
53 $this.on('show.GoogleMaps', methods.show);
56 /* Subscribe to query updates */
57 jQuery.subscribe('/results/' + options.query_uuid + '/changed', {instance: $this}, update_map);
58 jQuery.subscribe('/update-set/' + options.query_uuid, {instance: $this}, on_resource_changed);
59 jQuery.subscribe('/query/' + options.query_uuid + '/changed', {instance: $this}, query_changed);
61 //data = jQuery(this).data();
63 // TODO: Change the status of a node based on the actions in GoogleMap plugin or in other plugins (e.g. DataTables)
64 // Can we publish a value in results row['sliver'] ???
65 // Today, the value is attached or undefined
66 // But can we think about a added/removed status ???
67 // This plugin would update the map based on the results published
72 destroy : function( ) {
74 return this.each(function(){
75 var $this = jQuery(this), data = $this.data('GoogleMap');
76 jQuery(window).unbind('GoogleMap');
77 data.GoogleMap.remove();
78 $this.removeData('GoogleMap');
83 reposition : function( ) { // ... },
84 update : function( ) { // ... },
85 hide : function( ) { // ... },
87 show : function( content ) {
88 google.maps.event.trigger(map, 'resize');
92 jQuery.fn.GoogleMap = function( method ) {
93 /* Method calling logic */
94 if ( methods[method] ) {
95 return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
96 } else if ( typeof method === 'object' || ! method ) {
97 return methods.init.apply( this, arguments );
99 jQuery.error( 'Method ' + method + ' does not exist on jQuery.GoogleMap' );
104 /* Private methods */
105 function query_changed(e,query){
106 var data = e.data.instance.data();
107 /* Compare current and advertised query to get added and removed fields */
108 previous_query=data.current_query;
109 /* Save the query as the current query */
110 data.current_query=query;
113 if(typeof(data.results)!="undefined" && data.results.length>0){
114 jQuery.each(data.results, function(i, row){
115 jQuery.each(query.filter, function (idx, filter){
116 if(get_value(row[filter[0]])==filter[2]){
121 data.markerCluster=[];
123 var myLatlng = new google.maps.LatLng(34.397, 150.644);
127 mapTypeId: google.maps.MapTypeId.ROADMAP
129 map = new google.maps.Map(jQuery('#map')[0],myOptions);
131 //map.clearMarkers();
135 function update_map(e, rows) {
136 var data = e.data.instance.data();
137 var instance_ = e.data.instance;
138 //$plugindiv.closest('.need-spin').spin(false);
139 instance_.closest('.need-spin').spin(false);
142 if (rows === undefined || !rows || rows.length==0) {
143 messages.warning ("Empty result in googlemap.update_map - nothing to show");
151 if(typeof(data.results)=="undefined" || data.results==null){
155 var markerCluster = data.markerCluster;
156 var markers = data.markers;
157 var coords = new Array();
158 var infowindow = new google.maps.InfoWindow();
160 if(typeof(markers)!="undefined" && markers.length>0){
164 data.current_resources = Array();
166 jQuery.each(data.results, function(i, result){
167 // get the coordinates
168 var latitude=get_value(result['latitude']);
169 var longitude=get_value(result['longitude']);
170 var hash = latitude + longitude;
172 // check to see if we've seen this hash before
173 if(coords[hash] == null) {
174 // get coordinate object
175 var myLatlng = new google.maps.LatLng(latitude, longitude);
176 // store an indicator that we've seen this point before
179 // add some randomness to this point 1500 = 100 meters, 15000 = 10 meters
180 var lat = latitude + (Math.random() -.5) / 1500;
181 var lng = longitude + (Math.random() -.5) / 1500;
183 // get the coordinate object
184 var myLatlng = new google.maps.LatLng(lat, lng);
186 // If the node is attached to the slice, action will be Remove; else action will be add to slice
187 if (typeof(result['sliver']) != 'undefined') {
188 data.current_resources.push(result['urn']);
190 action_class="ui-icon-circle-minus";
191 action_message="Remove from slice";
194 action_class="ui-icon-circle-plus";
195 action_message="Add to slice";
198 if (!(result['latitude'])) {
202 //jQuery(".map-button").click(button_click);
203 if(jQuery.inArray(result,rows)>-1){
204 var marker = new google.maps.Marker({
206 title: get_value(result['ip']),
207 // This should be done by the rendering
208 content: '<p>Agent: ' + get_value(result['ip']) + ' (' + get_value(result['urn']) + ')<br/>Platform: ' + get_value(result['platform'])+'</p>' +
209 '<div class="map-button" id="'+action+'/'+get_value(result['urn'])+'" style="cursor:pointer;">'+
210 '<span class="ui-icon '+action_class+'" style="clear:both;float:left;"></span>'+action_message+
214 google.maps.event.addListener(marker, 'click', function() {
215 infowindow.content = this.content;
216 infowindow.open(map, this);
217 // onload of the infowindow on the map, bind a click on a button
218 google.maps.event.addListener(infowindow, 'domready', function() {
219 jQuery('.map-button').unbind('click');
220 jQuery(".map-button").click({instance: instance_}, button_click);
223 markers.push(marker);
226 markerCluster = new MarkerClusterer(map, markers, {zoomOnClick: false});
227 google.maps.event.addListener(markerCluster, "clusterclick", function (cluster) {
228 var markers = cluster.getMarkers();
229 var bounds = new google.maps.LatLngBounds();
233 * Firefox JS Error - replaced $.each by JQuery.each
235 jQuery.each(markers, function(i, marker){
236 bounds.extend(marker.getPosition());
238 //map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
239 map.fitBounds(bounds);
241 data.markerCluster=markerCluster;
243 function button_click(e){
244 var data = e.data.instance.data().GoogleMap;
245 var op_value=this.id.split("/");
246 if(op_value.length>0){
247 jQuery.publish('selected', op_value[0]+'/'+op_value[1]);
248 var value = op_value[1];
250 if (op_value[0] == 'add') {
251 data.current_resources.push(value);
253 tmp = jQuery.grep(data.current_resources, function(x) { return x != value; });
254 data.current_resources = tmp;
257 /* inform slice that our selected resources have changed */
258 jQuery.publish('/update-set/' + data.query_uuid, [data.current_resources, true, e.data.instance]);
262 function on_resource_changed(e, resources, instance)
264 /* TODO OPENLAB : this query determines which checkboxes must be checked */
265 if (instance == e.data.instance)
267 data = e.data.instance.data().GoogleMap;
269 previous_resources = data.current_resources;
270 data.current_resources = resources;
272 /* TODO We uncheck all checkboxes ... */
273 //jQuery('datatables-checkbox-' + data.options.plugin_uuid).attr('checked', false);
274 /* ... and check the ones specified in the resource list */
275 //jQuery.each(data.current_resources, function(index, urn) {
276 // jQuery('#datatables-checkbox-' + data.options.plugin_uuid + "-" + urn).attr('checked', true)