map
Attachment 'jquery-ubuntu-maps-0.2.js'
Download 1 /*
2 * jQuery Google Map Plugin 0.2
3 * https://wiki.ubuntu.com/ubuntu-django-foundations/map
4 * Requires jQuery 1.4.2
5 *
6 * Copyright 2011, Ronnie van den Crommenacker
7 * Dual licensed under the MIT or GPL Version 2 licenses.
8 * http://jquery.org/license
9 */
10
11 (function($){
12 $.fn.extend({
13 showLocations: function(options){
14 var defaults = {
15 markers_url: null, // http://link/to/json/markers or /link/to/json/markers
16 markers_list: null, // [ {lat: 0.345, lng: 0.3456}, {lat: 44.345, lng: 34.3456} ]
17 position_name: {
18 lat: 'lat', // { lat: 0.4567, lng: 0.2345 }
19 lng: 'lng' // { lat: 0.4567, lng: 0.2345 }
20 },
21 marker_content_url: null, // The url to load when clicked on a marker
22 marker_content_tmpl: null, // The template to load when clicked on a marker
23 mapOptions: {
24 zoom: 2,
25 center: new google.maps.LatLng(22, 12),
26 mapTypeId: google.maps.MapTypeId.ROADMAP,
27 mapTypeControl: false
28 },
29 user_location_zoom: 7, // use null to disable this feature
30 single_marker_zoom: 7, // the zoomlevel. use null to disable
31 ajax_load_error: '<p>The page could not be loaded</p>',
32 ajax_load_icon: '/ubuntu-website/media/images/ajax-loader.gif',
33 marker_icon: null,
34 cluster_tmpl: null,
35 filter: null, //[ { element: $('...'), attrs: { attr: value }}, { element: $('...'), attrs: { attr: value }} ]
36 mcOptions: { gridSize: 40, maxZoom: 10, zoomOnClick: false//, styles: [
37 //{ url: 'images/supportCluster1.png', height: 48, width: 48, opt_anchor: [16, 0], opt_textColor: '#ffffff', opt_textSize: 10 }, /* 2-9 members */
38 //{ url: 'images/supportCluster2.png', height: 64, width: 64, opt_anchor: [24, 0], opt_textColor: '#ffffff', opt_textSize: 11 }, /* 10-99 members */
39 //{ url: 'images/supportCluster3.png', height: 96, width: 96, opt_anchor: [32, 0], opt_textColor: '#ffffff', opt_textSize: 12 }, /* 100-999 members */
40 //{ url: 'images/supportCluster4.png', height: 128, width: 128, opt_anchor: [32, 0], opt_textColor: '#ffffff', opt_textSize: 12 } /* 1000+ members */
41 //]
42 }
43 },
44 // Add the window where the details are shown when clicked on a marker
45 infowindow = new google.maps.InfoWindow();
46
47 options = $.extend( defaults, options );
48
49 // TODO: rewrite this one
50 function getAjaxLoader() {
51 var ajaximg = $('<img src="' + options.ajax_load_icon + '" />')
52 .attr({'style': 'display:inline-block;vertical-align:middle;margin-right:10px;'}),
53 ajaxtxt = $('<p>')
54 .attr({'style': 'display:inline-block;vertical-align:middle;'})
55 .html('Retrieving data<br />from server...'),
56 wrapper = $('<div>')
57 .attr({'style': 'margin:auto;width:130px;'});
58 return wrapper.append(ajaximg).append(ajaxtxt)[0];
59 }
60
61 infowindow.show = function( html, pos ){
62 this.setContent( html );
63 this.setPosition( pos );
64 this.open( this.map );
65 };
66 infowindow.ajaxloader = null;
67 infowindow.showLoader = function( pos ){
68 // Set a temporary loader while the data is retreved from the server
69 if( this.ajaxloader === null ){
70 // TODO: allow user defined ajax loader
71 this.ajaxloader = getAjaxLoader();
72 }
73 this.show( this.ajaxloader, pos );
74 };
75 infowindow.showTemplate = function( url, data, pos ){
76 var $data = data,
77 $pos = pos;
78
79 if( !$.tmpl ){
80 alert( 'jQuery.tmpl is not installed\nYou can download here:\nhttp://github.com/jquery/jquery-tmpl' );
81 return false;
82 }
83
84 this.showLoader( pos );
85 $.ajax({ url: url,
86 dataType: 'html',
87 success: function( template ){
88 infowindow.show( $( template ).tmpl( $data )[0], $pos );
89 },
90 error: function(){
91 infowindow.show( options.ajax_load_error, $pos );
92 }
93 });
94 };
95 infowindow.showHTML = function( url, pos ){
96 var $pos = pos;
97
98 this.showLoader( pos );
99 $.ajax({ url: url,
100 dataType: 'html',
101 success: function( template ){
102 infowindow.show( html, $pos );
103 },
104 error: function(){
105 infowindow.show( options.ajax_load_error, $pos );
106 }
107 });
108 };
109
110 // Constructs an url with ${...} together with data to a normal url
111 function constructUrl( url, marker ){
112 var pattern = /\$\{[^}]+\}/g, // match pattern for ${....}
113 url_match = url.match( pattern ), // Matches the url for ${...} and returns a list of matches
114 param = null, // Used for getting a specific param from the marker
115 tag = null; // The tags in the match pattern
116
117 for( tag in url_match ){
118 if( url_match.hasOwnProperty( tag ) ){
119 param = url_match[tag];
120 url = url.replace( param, marker[param.slice( 2, param.length-1 )] );
121 }
122 }
123 return url;
124 }
125
126 // Function executed when clicked on a cluster object
127 function clusterClicked( cluster ) {
128 var marker_list = null;
129 if( options.cluster_tmpl ){
130 infowindow.showTemplate( options.cluster_tmpl, { marker_list: cluster[0].markers_ }, cluster[0].getCenter() );
131 }
132 }
133
134 // Function that is executed when user clicks on a marker
135 function markerClicked() {
136 var url = null;
137
138 if( options.marker_content_url ){
139 url = constructUrl( options.marker_content_url, this );
140 infowindow.showHTML( url, this.position );
141 } else if( options.marker_content_tmpl ){
142 infowindow.showTemplate( options.marker_content_tmpl, { marker: this }, this.position );
143 }
144 }
145
146 // Create from json data the google.maps.Marker and add them to the markercluster (mc)
147 // Then center the map if there is only one cluster and options.single_marker_zoom is true
148 function createMarkers( map, mc, markers ){
149 var marker_list = [], // A list of gmakers
150 marker = null, // The json of a marker
151 gmarker = null, // The actual google.maps.Marker() type
152 idx = null, // Index
153 lat = options.position_name.lat, // The parameter that contains the latitude
154 lng = options.position_name.lng; // The parameter that contains the longitude
155
156 if( markers[0].fields ){
157 // Django model
158 // Use django pk and fields parameters
159 for( idx in markers ){
160 if ( markers.hasOwnProperty( idx ) ) {
161 marker = markers[idx].fields;
162 marker.pk = markers[idx].pk;
163 marker.position = new google.maps.LatLng( marker[lat], marker[lng] );
164 if( !marker.icon && options.marker_icon ){
165 marker.icon = options.marker_icon;
166 }
167 gmarker = new google.maps.Marker( marker );
168 google.maps.event.addDomListener(gmarker, 'click', markerClicked);
169 marker_list.push( gmarker );
170 }
171 }
172
173 } else {
174 // Use normal parameters
175 for( idx in markers ){
176 if ( markers.hasOwnProperty( idx ) ) {
177 marker = markers[idx];
178 marker.position = new google.maps.LatLng( marker[lat], marker[lng] );
179 if( !markers[idx].icon && options.marker_icon ){
180 marker.icon = options.marker_icon;
181 }
182 gmarker = new google.maps.Marker( marker );
183 google.maps.event.addDomListener(gmarker, 'click', markerClicked);
184 marker_list.push( gmarker );
185 }
186 }
187 }
188 mc.addMarkers(marker_list);
189
190 // If there is only one marker
191 if ( options.single_marker_zoom && marker_list.length === 1 ){
192 // Make sure the map is initialized
193 // FIXME: Look for an map.init event
194 setTimeout(function(){
195 map.setCenter( mc.getMarkers()[0].getPosition() );
196 map.setZoom( options.single_marker_zoom );
197 }, 100);
198 }
199 }
200
201 return $(this).each( function( i, html_element ){
202 var map = new google.maps.Map( html_element, options.mapOptions ),
203 markerCluster = new MarkerClusterer( map, [], options.mcOptions ),
204 filter = options.filter,
205 index = null;
206
207 // FIXME: Manually override the zoomOnClick because of this bug
208 // http://www.devcomments.com/V3-MarkerClusterer-zoomOnClick-issue-at255452.htm
209 markerCluster.zoomOnClick_ = false;
210
211 // Attach the info window to the curernt map
212 infowindow.map = map;
213
214 // When clicked on a cluster, call the event
215 google.maps.event.addListener( markerCluster, 'clusterclick', clusterClicked );
216
217 // Try W3C Geolocation (Preferred)
218 // Ask the user for their location and set the map to it
219 if( options.user_location_zoom && navigator.geolocation ){
220 navigator.geolocation.getCurrentPosition( function( position ) {
221 var pos = new google.maps.LatLng( position.coords.latitude, position.coords.longitude ),
222 opt = options;
223 map.setCenter( pos );
224 map.setZoom( opt.user_location_zoom );
225 });
226 }
227
228 // Load the list of markers into the map
229 if( options.markers_url ){
230 $.get( options.markers_url, function( markers ){
231 createMarkers( map, markerCluster, markers );
232 }, 'json');
233 } else if( options.markers_list ){
234 createMarkers( map, markerCluster, options.markers_list );
235 }
236
237 var filterer = (function(markerCluster){
238 var mc = markerCluster,
239 markers = mc.getMarkers();
240 return {
241 addFilter: function(filter){
242 filter.element.click(function(event){
243 event.preventDefault();
244 var attrs = filter.attrs,
245 visible_markers = [],
246 m = null,
247 a = null;
248
249 for( m in markers ){
250 if( markers.hasOwnProperty(m) ){
251 marker = markers[m];
252 for( a in attrs ){
253 if( attrs.hasOwnProperty(a) ){
254 if( marker[a] === attrs[a] ){
255 visible_markers.push(marker);
256 }
257 }
258 }
259 }
260 }
261 // If there are no filter options, show all markers
262 if( !a ){
263 visible_markers = markers;
264 }
265 mc.clearMarkers();
266 mc.addMarkers(visible_markers, false);
267 });
268 }
269 }
270 }(markerCluster));
271
272 if( filter ){
273 for( index in filter ){
274 if( filter.hasOwnProperty(index) ){
275 filterer.addFilter(filter[index]);
276 }
277 }
278 }
279 });
280 },
281 selectLocation: function(options){
282 var defaults = {
283 html_lng: null,
284 html_lat: null,
285 marker_icon: null,
286 markers: [],
287 html_addr: null,
288 mapOptions: {
289 zoom: 4,
290 center: new google.maps.LatLng(51.8211, 5.591),
291 mapTypeId: google.maps.MapTypeId.ROADMAP,
292 mapTypeControl: false
293 }
294 };
295 options = $.extend(defaults, options);
296
297 function showPositionHTML(location){
298 console.log('show', location);
299 if(options.html_lng && options.html_lat){
300 if( location.xa && location.za ){
301 options.html_lat.val(location.xa);
302 options.html_lng.val(location.za);
303 } else if( location.wa && location.ya ){
304 options.html_lat.val(location.wa);
305 options.html_lng.val(location.ya);
306 }
307 }
308 }
309
310 function setMarker(map, location){
311 var marker = null;
312
313 if( options.markers.length ){
314 marker = options.markers[0];
315 marker.setPosition(location);
316 marker.setAnimation(google.maps.Animation.DROP);
317 } else {
318 marker = new google.maps.Marker({
319 map: map,
320 position: location,
321 draggable:true,
322 animation: google.maps.Animation.DROP
323 });
324 if (options.marker_icon){
325 marker.icon = options.marker_icon;
326 }
327 options.markers.push(marker);
328 google.maps.event.addListener(options.markers[0], 'mouseup', function(){
329 showPositionHTML(marker.getPosition());
330 });
331 }
332
333 map.setCenter(location);
334 showPositionHTML(marker.getPosition());
335 }
336
337 return $(this).each(function(i, html_element){
338 var map = new google.maps.Map($(html_element)[0], options.mapOptions),
339 geoCoder = new google.maps.Geocoder();
340
341 if (options.html_addr) {
342 options.html_addr.change(function(){
343 var address = [];
344 options.html_addr.each(function(i, item){
345 address.push(item.value);
346 });
347
348 geoCoder.geocode({address: address.join(' ')}, function(results, status) {
349 if (status === google.maps.GeocoderStatus.OK) {
350 setMarker(map, results[0].geometry.location);
351 }
352 });
353 });
354 }
355 google.maps.event.addListener(map, 'click', function(event){
356 setMarker(map, event.latLng);
357 });
358
359 if (options.html_lat.val() && options.html_lng.val()) {
360 var location = new google.maps.LatLng(options.html_lat.val(),options.html_lng.val());
361 setMarker(map, location);
362 }
363 });
364
365 }
366 });
367 }(jQuery));
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.