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(),
52 /* Subscribe to query updates */
53 jQuery.subscribe('/results/' + options.query_uuid + '/changed', {instance: $this}, update_map);
54 jQuery.subscribe('/update-set/' + options.query_uuid, {instance: $this}, on_resource_changed);
55 jQuery.subscribe('/query/' + options.query_uuid + '/changed', {instance: $this}, query_changed);
57 //data = jQuery(this).data();
59 // TODO: Change the status of a node based on the actions in GoogleMap plugin or in other plugins (e.g. DataTables)
60 // Can we publish a value in results row['sliver'] ???
61 // Today, the value is attached or undefined
62 // But can we think about a added/removed status ???
63 // This plugin would update the map based on the results published
68 destroy : function( ) {
70 return this.each(function(){
71 var $this = jQuery(this), data = $this.data('GoogleMap');
72 jQuery(window).unbind('GoogleMap');
73 data.GoogleMap.remove();
74 $this.removeData('GoogleMap');
79 reposition : function( ) { // ... },
80 update : function( ) { // ... },
81 hide : function( ) { // ... },
83 show : function( content ) {
84 google.maps.event.trigger(map, 'resize');
88 jQuery.fn.GoogleMap = function( method ) {
89 /* Method calling logic */
90 if ( methods[method] ) {
91 return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
92 } else if ( typeof method === 'object' || ! method ) {
93 return methods.init.apply( this, arguments );
95 jQuery.error( 'Method ' + method + ' does not exist on jQuery.GoogleMap' );
100 /* Private methods */
101 function query_changed(e,query){
102 var data = e.data.instance.data();
103 /* Compare current and advertised query to get added and removed fields */
104 previous_query=data.current_query;
105 /* Save the query as the current query */
106 data.current_query=query;
109 if(typeof(data.results)!="undefined" && data.results.length>0){
110 jQuery.each(data.results, function(i, row){
111 jQuery.each(query.filter, function (idx, filter){
112 if(get_value(row[filter[0]])==filter[2]){
117 data.markerCluster=[];
119 var myLatlng = new google.maps.LatLng(34.397, 150.644);
123 mapTypeId: google.maps.MapTypeId.ROADMAP
125 map = new google.maps.Map(jQuery('#map')[0],myOptions);
127 //map.clearMarkers();
131 function update_map(e, rows) {
132 var data = e.data.instance.data();
133 var instance_ = e.data.instance;
134 //$plugindiv.closest('.need-spin').spin(false);
135 instance_.closest('.need-spin').spin(false);
138 if (rows === undefined || !rows || rows.length==0) {
139 messages.warning ("Empty result in googlemap.update_map - nothing to show");
147 if(typeof(data.results)=="undefined" || data.results==null){
151 var markerCluster = data.markerCluster;
152 var markers = data.markers;
153 var coords = new Array();
154 var infowindow = new google.maps.InfoWindow();
156 if(typeof(markers)!="undefined" && markers.length>0){
160 data.current_resources = Array();
162 jQuery.each(data.results, function(i, result){
163 // get the coordinates
164 var latitude=get_value(result['latitude']);
165 var longitude=get_value(result['longitude']);
166 var hash = latitude + longitude;
168 // check to see if we've seen this hash before
169 if(coords[hash] == null) {
170 // get coordinate object
171 var myLatlng = new google.maps.LatLng(latitude, longitude);
172 // store an indicator that we've seen this point before
175 // add some randomness to this point 1500 = 100 meters, 15000 = 10 meters
176 var lat = latitude + (Math.random() -.5) / 1500;
177 var lng = longitude + (Math.random() -.5) / 1500;
179 // get the coordinate object
180 var myLatlng = new google.maps.LatLng(lat, lng);
182 // If the node is attached to the slice, action will be Remove; else action will be add to slice
183 if (typeof(result['sliver']) != 'undefined') {
184 data.current_resources.push(result['urn']);
186 action_class="ui-icon-circle-minus";
187 action_message="Remove from slice";
190 action_class="ui-icon-circle-plus";
191 action_message="Add to slice";
194 if (!(result['latitude'])) {
198 //jQuery(".map-button").click(button_click);
199 if(jQuery.inArray(result,rows)>-1){
200 var marker = new google.maps.Marker({
202 title: get_value(result['ip']),
203 // This should be done by the rendering
204 content: '<p>Agent: ' + get_value(result['ip']) + ' (' + get_value(result['urn']) + ')<br/>Platform: ' + get_value(result['platform'])+'</p>' +
205 '<div class="map-button" id="'+action+'/'+get_value(result['urn'])+'" style="cursor:pointer;">'+
206 '<span class="ui-icon '+action_class+'" style="clear:both;float:left;"></span>'+action_message+
210 google.maps.event.addListener(marker, 'click', function() {
211 infowindow.content = this.content;
212 infowindow.open(map, this);
213 // onload of the infowindow on the map, bind a click on a button
214 google.maps.event.addListener(infowindow, 'domready', function() {
215 jQuery('.map-button').unbind('click');
216 jQuery(".map-button").click({instance: instance_}, button_click);
219 markers.push(marker);
222 markerCluster = new MarkerClusterer(map, markers, {zoomOnClick: false});
223 google.maps.event.addListener(markerCluster, "clusterclick", function (cluster) {
224 var markers = cluster.getMarkers();
225 var bounds = new google.maps.LatLngBounds();
229 * Firefox JS Error - replaced $.each by JQuery.each
231 jQuery.each(markers, function(i, marker){
232 bounds.extend(marker.getPosition());
234 //map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
235 map.fitBounds(bounds);
237 data.markerCluster=markerCluster;
239 function button_click(e){
240 var data = e.data.instance.data().GoogleMap;
241 var op_value=this.id.split("/");
242 if(op_value.length>0){
243 jQuery.publish('selected', op_value[0]+'/'+op_value[1]);
244 var value = op_value[1];
246 if (op_value[0] == 'add') {
247 data.current_resources.push(value);
249 tmp = jQuery.grep(data.current_resources, function(x) { return x != value; });
250 data.current_resources = tmp;
253 /* inform slice that our selected resources have changed */
254 jQuery.publish('/update-set/' + data.query_uuid, [data.current_resources, true, e.data.instance]);
258 function on_resource_changed(e, resources, instance)
260 /* TODO OPENLAB : this query determines which checkboxes must be checked */
261 if (instance == e.data.instance)
263 data = e.data.instance.data().GoogleMap;
265 previous_resources = data.current_resources;
266 data.current_resources = resources;
268 /* TODO We uncheck all checkboxes ... */
269 //jQuery('datatables-checkbox-' + data.options.plugin_uuid).attr('checked', false);
270 /* ... and check the ones specified in the resource list */
271 //jQuery.each(data.current_resources, function(index, urn) {
272 // jQuery('#datatables-checkbox-' + data.options.plugin_uuid + "-" + urn).attr('checked', true)