2 * Description: display a query result in a googlemap
3 * Copyright (c) 2012 UPMC Sorbonne Universite - INRIA
8 * It's a best practice to pass jQuery to an IIFE (Immediately Invoked Function
9 * Expression) that maps it to the dollar sign so it can't be overwritten by
10 * another library in the scope of its execution.
15 var PLUGIN_NAME = 'GoogleMap';
18 jQuery.fn.GoogleMap = function( method ) {
19 if ( methods[method] ) {
20 return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
21 } else if ( typeof method === 'object' || ! method ) {
22 return methods.init.apply( this, arguments );
24 jQuery.error( 'Method ' + method + ' does not exist on jQuery.' + PLUGIN_NAME );
28 /***************************************************************************
30 ***************************************************************************/
35 * @brief Plugin initialization
36 * @param options : an associative array of setting values
37 * @return : a jQuery collection of objects on which the plugin is
38 * applied, which allows to maintain chainability of calls
40 init : function( options ) {
42 return this.each(function(){
46 /* An object that will hold private variables and methods */
47 var plugin = new GoogleMaps(options);
48 $this.data('Manifold', plugin);
53 $this.on('show.' + PLUGIN_NAME, methods.show);
55 $this.set_query_handler(options.query_uuid, plugin.query_handler);
56 $this.set_record_handler(options.query_uuid, plugin.record_handler);
57 $this.set_record_handler(options.query_all_uuid, plugin.record_handler_all);
63 * @brief Plugin destruction
64 * @return : a jQuery collection of objects on which the plugin is
65 * applied, which allows to maintain chainability of calls
67 destroy : function( ) {
69 return this.each(function() {
71 var hazelnut = $this.data('Manifold');
73 // Unbind all events using namespacing
74 $(window).unbind(PLUGIN_NAME);
76 // Remove associated data
78 $this.removeData('Manifold');
84 google.maps.event.trigger(map, 'resize');
89 /***************************************************************************
91 ***************************************************************************/
93 function GoogleMaps(options)
95 /* member variables */
96 this.options = options;
99 this.received_all = false;
100 this.received_set = false;
101 this.in_set_buffer = Array();
107 this.initialize = function() {
109 this.markerCluster = null;
111 this.coords = new Array();
113 var myLatlng = new google.maps.LatLng(options.latitude, options.longitude);
117 mapTypeId: google.maps.MapTypeId.ROADMAP
120 this.map = new google.maps.Map(document.getElementById("map"), myOptions);
121 this.infowindow = new google.maps.InfoWindow();
126 this.new_record = function(record)
129 // get the coordinates
130 var latitude=get_value(record['latitude']);
131 var longitude=get_value(record['longitude']);
132 var hash = latitude + longitude;
134 // check to see if we've seen this hash before
135 if(this.coords[hash] == null) {
136 // get coordinate object
137 var myLatlng = new google.maps.LatLng(latitude, longitude);
138 // store an indicator that we've seen this point before
139 this.coords[hash] = 1;
141 // add some randomness to this point 1500 = 100 meters, 15000 = 10 meters
142 var lat = latitude + (Math.random() -.5) / 1500;
143 var lng = longitude + (Math.random() -.5) / 1500;
145 // get the coordinate object
146 var myLatlng = new google.maps.LatLng(lat, lng);
148 // If the node is attached to the slice, action will be Remove; else action will be add to slice
149 if (typeof(record['sliver']) != 'undefined') {
150 data.current_resources.push(record['urn']);
152 action_class="ui-icon-circle-minus";
153 action_message="Remove from slice";
156 action_class="ui-icon-circle-plus";
157 action_message="Add to slice";
160 if (!(record['latitude'])) {
164 //jQuery(".map-button").click(button_click);
165 //if(jQuery.inArray(record, rows)>-1){
166 var marker = new google.maps.Marker({
168 title: get_value(record['hostname']),
169 // This should be done by the rendering
170 content: '<p>Agent: ' + get_value(record['ip']) + ' (' + get_value(record['resource_hrn']) + ')<br/>Platform: ' + get_value(record['platform'])+'</p>' +
171 '<div class="map-button" id="'+action+'/'+get_value(record['resource_hrn'])+'" style="cursor:pointer;">'+
172 '<span class="ui-icon '+action_class+'" style="clear:both;float:left;"></span>'+action_message+
176 this.addInfoWindow(marker, object.map);
177 object.markers.push(marker);
182 this.addInfoWindow = function(marker, map) {
183 google.maps.event.addListener(marker, 'click', function () {
184 if(object.infowindow){
185 object.infowindow.close();
187 object.infowindow.setContent(marker.content);// = new google.maps.InfoWindow({ content: marker.content });
188 object.infowindow.open(map, marker);
189 // onload of the infowindow on the map, bind a click on a button
190 google.maps.event.addListener(object.infowindow, 'domready', function() {
191 jQuery('.map-button').unbind('click');
192 // jQuery(".map-button").click({instance: instance_, infoWindow: object.infowindow}, button_click);
198 this.set_checkbox = function(record)
200 // XXX urn should be replaced by the key
201 // XXX we should enforce that both queries have the same key !!
202 //checkbox_id = "#hazelnut-checkbox-" + object.options.plugin_uuid + "-" + unfold.escape_id(record[ELEMENT_KEY].replace(/\\/g, ''))
203 //$(checkbox_id, object.table.fnGetNodes()).attr('checked', true);
206 this.record_handler = function(e, event_type, record)
211 /* NOTE in fact we are doing a join here */
212 if (object.received_all)
213 // update checkbox for record
214 object.set_checkbox(record);
216 // store for later update of checkboxes
217 object.in_set_buffer.push(record);
220 // nothing to do here
223 manifold.spin($(this));
226 if (object.received_all)
227 manifold.spin($(this), false);
228 object.received_set = true;
233 this.record_handler_all = function(e, event_type, record)
238 // Add the record to the table
239 object.new_record(record);
242 // object.table.fnClearTable();
245 manifold.spin($(this));
250 object.markerCluster = new MarkerClusterer(object.map, object.markers, {zoomOnClick: false});
251 google.maps.event.addListener(object.markerCluster, "clusterclick", function (cluster) {
252 var markers = cluster.getMarkers();
253 var bounds = new google.maps.LatLngBounds();
257 * Firefox JS Error - replaced $.each by JQuery.each
259 jQuery.each(markers, function(i, marker){
260 bounds.extend(marker.getPosition());
263 //map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
264 object.map.fitBounds(bounds);
267 if (object.received_set) {
268 /* XXX needed ? XXX We uncheck all checkboxes ... */
269 $("[id^='datatables-checkbox-" + object.options.plugin_uuid +"']").attr('checked', false);
271 /* ... and check the ones specified in the resource list */
272 $.each(object.in_set_buffer, function(i, record) {
273 object.set_checkbox(record);
276 manifold.spin($(this), false);
278 object.received_all = true;
284 this.query_handler = function(e, event_type, query)
286 // This replaces the complex set_query function
287 // The plugin does not need to remember the query anymore
293 // XXX Here we might need to maintain the list of filters !
294 /* Process updates in filters / current_query must be updated before this call for filtering ! */
295 object.table.fnDraw();
299 /* Hide/unhide columns to match added/removed fields */
305 alert('GoogleMaps::clear_fields() not implemented');
312 function button_click(e){
313 var op_value=this.id.split("/");
314 if(op_value.length>0){
315 var value = op_value[1];
316 manifold.raise_event(object.options.query_uuid, (op_value[0] == 'add')?SET_ADD:SET_REMOVED, value);
318 } // function button_click()
322 // jQuery.each(data.results, function(i, row){
323 // jQuery.each(query.filter, function (idx, filter){
324 // if(get_value(row[filter[0]])==filter[2]){
329 // data.markerCluster=[];
331 // var myLatlng = new google.maps.LatLng(34.397, 150.644);
335 // mapTypeId: google.maps.MapTypeId.ROADMAP
337 // map = new google.maps.Map(jQuery('#map')[0],myOptions);
339 // //map.clearMarkers();
340 // update_map(e, rows);