gmapz 2.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.md +21 -0
- data/LICENSE.txt +22 -0
- data/README.md +83 -0
- data/Rakefile +2 -0
- data/gmapz.gemspec +23 -0
- data/lib/gmapz.rb +6 -0
- data/lib/gmapz/engine.rb +13 -0
- data/lib/gmapz/version.rb +3 -0
- data/src/css/gmapz-responsive.css +106 -0
- data/src/css/gmapz-sample-infobox.scss +125 -0
- data/src/img/gmapz/ic_clear_black_18px.svg +1 -0
- data/src/img/gmapz/pin-blue.png +0 -0
- data/src/img/gmapz/pin-cluster.png +0 -0
- data/src/img/gmapz/pin-green.png +0 -0
- data/src/img/gmapz/pin-orange.png +0 -0
- data/src/img/gmapz/pin-user-location.png +0 -0
- data/src/img/gmapz/pin.png +0 -0
- data/src/img/gmapz/scroll_disabled.svg +1 -0
- data/src/img/gmapz/scroll_enabled.svg +4 -0
- data/src/js/gmapz-dependencies/markerclusterer.js +1290 -0
- data/src/js/gmapz/gmapz.autocomplete.js +109 -0
- data/src/js/gmapz/gmapz.js +179 -0
- data/src/js/gmapz/gmapz.locations.js +474 -0
- data/src/js/gmapz/gmapz.map.js +789 -0
- data/src/js/gmapz/gmapz.pins.js +40 -0
- data/src/js/ready.js +389 -0
- metadata +102 -0
@@ -0,0 +1,789 @@
|
|
1
|
+
//
|
2
|
+
// Creates instances of GMapz maps
|
3
|
+
//
|
4
|
+
GMapz.map = (function() {
|
5
|
+
|
6
|
+
function Constructor($map, user_settings, initial_locs) {
|
7
|
+
|
8
|
+
if($map.length === 0) {
|
9
|
+
if (GMapz.debug) console.warn("'"+$map.selector+"' not found!");
|
10
|
+
return false;
|
11
|
+
}
|
12
|
+
|
13
|
+
// map
|
14
|
+
this.map = null; // gm object
|
15
|
+
this.$map = $map; // JQuery selector
|
16
|
+
this.map_id = null; // string ID
|
17
|
+
|
18
|
+
// Settings of object
|
19
|
+
this.gz_settings = {
|
20
|
+
is_initialized: false,
|
21
|
+
is_locked: null,
|
22
|
+
is_drawn: false,
|
23
|
+
test_str: 'unitialized',
|
24
|
+
zoom: {
|
25
|
+
// If you have a single marker you'll get a high zoom
|
26
|
+
// This value is the threshold that will trigger the
|
27
|
+
// automatic zoom level
|
28
|
+
threshold: 20,
|
29
|
+
target: 7 // Set to false to disable
|
30
|
+
}
|
31
|
+
};
|
32
|
+
|
33
|
+
// Google Maps event listener
|
34
|
+
this.listeners = {
|
35
|
+
'idle': null,
|
36
|
+
'zoom_on_scroll_lock': null,
|
37
|
+
'tilesloaded_responsive': null,
|
38
|
+
'on_draw': null
|
39
|
+
};
|
40
|
+
|
41
|
+
// Google maps settings on initialization
|
42
|
+
this.map_settings = {
|
43
|
+
scrollwheel: true,
|
44
|
+
scaleControl: true,
|
45
|
+
pixelOffset: false,
|
46
|
+
zoom: 9,
|
47
|
+
center: [0,0],
|
48
|
+
bounds: null,
|
49
|
+
mapTypeId: 'ROADMAP', // 'ROADMAP' / 'SATELLITE' / 'HYBRID' / 'TERRAIN'
|
50
|
+
mapTypeControlOptions: {
|
51
|
+
style: 1, // google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
|
52
|
+
position: 6, // google.maps.ControlPosition.LEFT_BOTTOM
|
53
|
+
},
|
54
|
+
// styles: [{"featureType":"landscape","stylers":[{"saturation":-100},{"lightness":60}]},{"featureType":"road.local","stylers":[{"saturation":-100},{"lightness":40},{"visibility":"on"}]},{"featureType":"transit","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"administrative.province","stylers":[{"visibility":"off"}]},{"featureType":"water","stylers":[{"visibility":"on"},{"lightness":30}]},{"featureType":"road.highway","elementType":"geometry.fill","stylers":[{"color":"#ef8c25"},{"lightness":40}]},{"featureType":"road.highway","elementType":"geometry.stroke","stylers":[{"visibility":"off"}]},{"featureType":"poi.park","elementType":"geometry.fill","stylers":[{"color":"#b6c54c"},{"lightness":40},{"saturation":-40}]},{}]
|
55
|
+
};
|
56
|
+
|
57
|
+
// ID único del mapa
|
58
|
+
if (this.$map.attr('data-gmapz')) {
|
59
|
+
this.map_id = this.$map.attr('data-gmapz');
|
60
|
+
} else {
|
61
|
+
this.map_id = GMapz.getUniqueId(8,'gz-');
|
62
|
+
this.$map.attr('data-gmapz', this.map_id);
|
63
|
+
}
|
64
|
+
|
65
|
+
// Localizaciones
|
66
|
+
if (typeof initial_locs !== 'undefined' && !jQuery.isEmptyObject(initial_locs)) {
|
67
|
+
this.initial_locs = initial_locs;
|
68
|
+
} else {
|
69
|
+
this.initial_locs = {};
|
70
|
+
}
|
71
|
+
|
72
|
+
// Marcadores (objectos de google)
|
73
|
+
this.markers = {};
|
74
|
+
|
75
|
+
// Info windows (objectos de google)
|
76
|
+
this.iws = {};
|
77
|
+
this.iw_current_idx = false;
|
78
|
+
this.iw_template = '<div class="gmapz-infowindow">{{__REPLACE__}}</div>';
|
79
|
+
|
80
|
+
// Infobox / infowindows personlizados
|
81
|
+
this.ibx = null;
|
82
|
+
|
83
|
+
// Extend settings
|
84
|
+
$.extend(this.map_settings, user_settings);
|
85
|
+
|
86
|
+
// Attach objecto DOM element
|
87
|
+
$map[0].gmapz = this;
|
88
|
+
|
89
|
+
if (GMapz.data.map_api_ready) {
|
90
|
+
// GM Api is already available
|
91
|
+
this.instanceReady();
|
92
|
+
} else {
|
93
|
+
// Request GM Api, instanceReady() will be called when done
|
94
|
+
GMapz.requestAPI();
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
Constructor.prototype = {
|
99
|
+
|
100
|
+
//
|
101
|
+
// Methods
|
102
|
+
//
|
103
|
+
|
104
|
+
instanceReady: function(e) {
|
105
|
+
|
106
|
+
var that = this;
|
107
|
+
|
108
|
+
if (GMapz.debug) console.info(this.map_id+' instanceReady();');
|
109
|
+
|
110
|
+
//function code
|
111
|
+
this.gz_settings.is_initialized = true;
|
112
|
+
|
113
|
+
// Fix spacial settings
|
114
|
+
this.map_settings.mapTypeId = google.maps.MapTypeId[this.map_settings.mapTypeId];
|
115
|
+
this.map_settings.center = new google.maps.LatLng(
|
116
|
+
this.map_settings.center[0],
|
117
|
+
this.map_settings.center[1]
|
118
|
+
);
|
119
|
+
|
120
|
+
// Calling the constructor, initializing the map
|
121
|
+
this.map = new google.maps.Map($("[data-gmapz='"+this.map_id+"']")[0], this.map_settings);
|
122
|
+
|
123
|
+
// If locations passed in start add them
|
124
|
+
if(!jQuery.isEmptyObject(this.initial_locs)) {
|
125
|
+
this.addLocations(this.initial_locs);
|
126
|
+
}
|
127
|
+
|
128
|
+
// Bounds
|
129
|
+
if (this.map_settings.bounds) {
|
130
|
+
var bounds = new google.maps.LatLngBounds();
|
131
|
+
bounds.extend( new google.maps.LatLng(
|
132
|
+
this.map_settings.bounds[0],this.map_settings.bounds[1])
|
133
|
+
);
|
134
|
+
bounds.extend( new google.maps.LatLng(
|
135
|
+
this.map_settings.bounds[2],this.map_settings.bounds[3])
|
136
|
+
);
|
137
|
+
this.map_settings.bounds = bounds;
|
138
|
+
this.map.fitBounds(bounds);
|
139
|
+
}
|
140
|
+
|
141
|
+
// Call ready handler
|
142
|
+
this.onReady();
|
143
|
+
|
144
|
+
// Will draw event when map is painted
|
145
|
+
this.listeners.on_draw = google.maps.event.addListenerOnce(this.map, 'tilesloaded', function(){
|
146
|
+
that.gz_settings.is_drawn = true;
|
147
|
+
google.maps.event.removeListener(that.listeners.on_draw);
|
148
|
+
that.onDraw();
|
149
|
+
});
|
150
|
+
},
|
151
|
+
|
152
|
+
// Override from outside
|
153
|
+
onReady: function() {
|
154
|
+
if (GMapz.debug) console.info(this.map_id+' instance onReady();');
|
155
|
+
},
|
156
|
+
|
157
|
+
// Override from outside
|
158
|
+
onDraw: function() {
|
159
|
+
if (GMapz.debug) console.info(this.map_id+' onDraw();');
|
160
|
+
},
|
161
|
+
|
162
|
+
// Map
|
163
|
+
setZoom: function (zoom) {
|
164
|
+
this.map.setZoom(zoom);
|
165
|
+
return this;
|
166
|
+
},
|
167
|
+
|
168
|
+
// Map
|
169
|
+
setSingleMarkerZoom: function (target, threshold) {
|
170
|
+
this.gz_settings.zoom.target = target;
|
171
|
+
if (threshold) {
|
172
|
+
this.gz_settings.zoom.threshold = threshold;
|
173
|
+
}
|
174
|
+
return this;
|
175
|
+
},
|
176
|
+
|
177
|
+
getZoom: function () {
|
178
|
+
return this.map.getZoom();
|
179
|
+
},
|
180
|
+
|
181
|
+
centerTo: function (lat, lng, zoom) {
|
182
|
+
var t = this;
|
183
|
+
this.map.setCenter(new google.maps.LatLng(lat, lng));
|
184
|
+
if (typeof zoom !== 'undefined' && zoom !== false) {
|
185
|
+
this.map.setZoom(zoom);
|
186
|
+
}
|
187
|
+
return this;
|
188
|
+
},
|
189
|
+
|
190
|
+
centerToMarker: function(idx, zoom) {
|
191
|
+
if (typeof zoom === 'undefined') {
|
192
|
+
zoom = false;
|
193
|
+
}
|
194
|
+
if (this.markers[idx]) {
|
195
|
+
this.setMarkerVisibility(idx, true);
|
196
|
+
// If map is locked we remove the listener...
|
197
|
+
if ( this.gz_settings.is_locked ) {
|
198
|
+
google.maps.event.removeListener(this.listeners.zoom_on_scroll_lock);
|
199
|
+
}
|
200
|
+
this.centerTo(
|
201
|
+
this.markers[idx].position.lat(),
|
202
|
+
this.markers[idx].position.lng(),
|
203
|
+
zoom
|
204
|
+
);
|
205
|
+
// ...to attach it again
|
206
|
+
if ( this.gz_settings.is_locked ) {
|
207
|
+
this.lockScrollAction();
|
208
|
+
}
|
209
|
+
}
|
210
|
+
return this;
|
211
|
+
},
|
212
|
+
|
213
|
+
// Expects array
|
214
|
+
showMarkerGroup: function (group, hide_rest) {
|
215
|
+
this.closeAllInfoWindows();
|
216
|
+
if (hide_rest) {
|
217
|
+
this.setAllMarkersVisibility(false);
|
218
|
+
}
|
219
|
+
for (var i in group) {
|
220
|
+
if (group.hasOwnProperty(i) && this.markers && this.markers[group[i]]) {
|
221
|
+
this.markers[group[i]].setVisible(true);
|
222
|
+
}
|
223
|
+
}
|
224
|
+
this.fitBounds(group);
|
225
|
+
},
|
226
|
+
|
227
|
+
// Locations & markers
|
228
|
+
addLocations: function (locs) {
|
229
|
+
|
230
|
+
var that = this;
|
231
|
+
|
232
|
+
// Get default pin
|
233
|
+
if (GMapz.pins['default']) {
|
234
|
+
default_pin = GMapz.pins['default'].pin;
|
235
|
+
}
|
236
|
+
|
237
|
+
for (var idx in locs) {
|
238
|
+
|
239
|
+
// Delete marker if exists
|
240
|
+
if (this.markers && this.markers[idx]) {
|
241
|
+
this.deleteMarkers([idx]);
|
242
|
+
}
|
243
|
+
|
244
|
+
current_pin = default_pin;
|
245
|
+
// Customized for this point
|
246
|
+
if (locs[idx].pin && GMapz.pins[locs[idx].pin]) {
|
247
|
+
current_pin = GMapz.pins[locs[idx].pin].pin;
|
248
|
+
}
|
249
|
+
// Markers array
|
250
|
+
var marker_options = {
|
251
|
+
idx: idx,
|
252
|
+
position: new google.maps.LatLng(locs[idx].lat,locs[idx].lng),
|
253
|
+
map: this.map,
|
254
|
+
icon: current_pin
|
255
|
+
// ,optimized: false
|
256
|
+
};
|
257
|
+
// Draggable marker?
|
258
|
+
if (locs[idx].draggable) { marker_options.draggable = true; }
|
259
|
+
// Create marker
|
260
|
+
this.markers[idx] = new google.maps.Marker(marker_options);
|
261
|
+
// Draggable marker event
|
262
|
+
if (locs[idx].draggable) {
|
263
|
+
google.maps.event.addListener(
|
264
|
+
this.markers[idx], 'dragend', function() {
|
265
|
+
that.onMarkerDragEnd(this);
|
266
|
+
});
|
267
|
+
}
|
268
|
+
// Add custom click
|
269
|
+
this.markers[idx].click = function() {
|
270
|
+
google.maps.event.trigger(this, 'click');
|
271
|
+
};
|
272
|
+
// If set 'hidden'
|
273
|
+
if (locs[idx].visible === false) {
|
274
|
+
this.markers[idx].setVisible(false);
|
275
|
+
}
|
276
|
+
// Create standard infowindows
|
277
|
+
// TO-DO create custom infowindows GMapz.infowindow?
|
278
|
+
if (locs[idx].iw) {
|
279
|
+
// We store the infowindow content in the marker also
|
280
|
+
this.markers[idx].iw = locs[idx].iw;
|
281
|
+
// Infowindows / Infoboxes array
|
282
|
+
if (!this.ibx) {
|
283
|
+
// There is NOT an infoBox defined
|
284
|
+
// We create standard infowindow
|
285
|
+
var iw_options = {
|
286
|
+
content: this.iw_template.replace('{{__REPLACE__}}',locs[idx].iw),
|
287
|
+
};
|
288
|
+
// Is there any pixelOffset?
|
289
|
+
if (this.map_settings.pixelOffset !== false) {
|
290
|
+
iw_options.pixelOffset = new google.maps.Size(
|
291
|
+
this.map_settings.pixelOffset[0],
|
292
|
+
this.map_settings.pixelOffset[1]
|
293
|
+
);
|
294
|
+
}
|
295
|
+
this.iws[idx] = new google.maps.InfoWindow(iw_options);
|
296
|
+
// Click on marker event open Infowindow
|
297
|
+
google.maps.event.addListener(this.markers[idx], 'click', function() {
|
298
|
+
that.onMarkerClick(this); // this -> markerObj
|
299
|
+
});
|
300
|
+
} else {
|
301
|
+
// We create infobox!
|
302
|
+
google.maps.event.addListener(this.markers[idx], 'click', function() {
|
303
|
+
// this -> marker
|
304
|
+
that.ibx.close();
|
305
|
+
var content = that.ibx.gmapz_template.replace('{{__REPLACE__}}',this.iw);
|
306
|
+
that.ibx.setContent(content);
|
307
|
+
that.ibx.open(that.map, this);
|
308
|
+
});
|
309
|
+
}
|
310
|
+
}
|
311
|
+
|
312
|
+
}
|
313
|
+
|
314
|
+
return this; // Chaining
|
315
|
+
}, // addLocations
|
316
|
+
|
317
|
+
onMarkerClick: function(marker_obj) {
|
318
|
+
// console.log(marker_obj);
|
319
|
+
this.closeAllInfoWindows();
|
320
|
+
this.iw_current_idx = marker_obj.idx;
|
321
|
+
this.iws[marker_obj.idx].open(this.map, this.markers[marker_obj.idx]);
|
322
|
+
// Add class to infowindow container
|
323
|
+
if (this.$map.find('.gm-style-iw-container').length === 0) {
|
324
|
+
this.$map.find('.gm-style-iw').parent().addClass('gm-style-iw-container');
|
325
|
+
}
|
326
|
+
},
|
327
|
+
|
328
|
+
// Info windows
|
329
|
+
|
330
|
+
closeInfoWindow: function(idx) {
|
331
|
+
if (this.iws[idx]) {
|
332
|
+
this.iws[idx].close();
|
333
|
+
}
|
334
|
+
return this;
|
335
|
+
},
|
336
|
+
|
337
|
+
closeAllInfoWindows: function() {
|
338
|
+
if (this.ibx) {
|
339
|
+
this.ibx.close();
|
340
|
+
}
|
341
|
+
for (var idx in this.iws) {
|
342
|
+
if (this.iws.hasOwnProperty(idx)) {
|
343
|
+
this.closeInfoWindow(idx);
|
344
|
+
}
|
345
|
+
}
|
346
|
+
this.iw_current_idx = false;
|
347
|
+
return this;
|
348
|
+
},
|
349
|
+
|
350
|
+
// Clicks on marker to show its infowindow
|
351
|
+
openInfoWindow: function(idx) {
|
352
|
+
if (this.iws[idx] && this.markers[idx]) {
|
353
|
+
this.markers[idx].click();
|
354
|
+
}
|
355
|
+
return this;
|
356
|
+
},
|
357
|
+
|
358
|
+
// Recalculate bounds and fit view depending on markers
|
359
|
+
fitBounds: function (idxArray) {
|
360
|
+
var
|
361
|
+
visible_count = 0,
|
362
|
+
bounds = new google.maps.LatLngBounds();
|
363
|
+
|
364
|
+
// Calculate all visible
|
365
|
+
if (!idxArray) {
|
366
|
+
for (var idx in this.markers) {
|
367
|
+
if (this.markers.hasOwnProperty(idx) && this.markers[idx].getVisible()) {
|
368
|
+
bounds.extend(this.markers[idx].getPosition());
|
369
|
+
visible_count++;
|
370
|
+
}
|
371
|
+
}
|
372
|
+
} else {
|
373
|
+
// Fit to idxs group
|
374
|
+
for (var i in idxArray) {
|
375
|
+
if (this.markers && this.markers[idxArray[i]]) {
|
376
|
+
bounds.extend(this.markers[idxArray[i]].getPosition());
|
377
|
+
visible_count++;
|
378
|
+
}
|
379
|
+
}
|
380
|
+
}
|
381
|
+
|
382
|
+
// Only one marker auto zoom
|
383
|
+
if (this.gz_settings.zoom.target !== false && visible_count == 1) {
|
384
|
+
this.singleMarkerZoomAdjust(this.gz_settings.zoom.threshold, this.gz_settings.zoom.target);
|
385
|
+
}
|
386
|
+
|
387
|
+
// More than one marker fit Bounds
|
388
|
+
// if (visible_count > 1) {
|
389
|
+
this.map.fitBounds(bounds);
|
390
|
+
// }
|
391
|
+
|
392
|
+
// If NO marker set, do nothing ;)
|
393
|
+
// Will use the default cenrter and zoom
|
394
|
+
|
395
|
+
return this; // Chainning
|
396
|
+
},
|
397
|
+
|
398
|
+
// Used when passing place object from gmapz.autocomplete!
|
399
|
+
fitToPlace: function (place, zoom) {
|
400
|
+
place = ($.isArray(place)) ? place[0] : place;
|
401
|
+
|
402
|
+
if (typeof place.geometry.viewport !== 'undefined') {
|
403
|
+
this.map.fitBounds(place.geometry.viewport);
|
404
|
+
}
|
405
|
+
this.map.setCenter(place.geometry.location);
|
406
|
+
if (typeof zoom !== 'undefined') {
|
407
|
+
this.map.setZoom(zoom);
|
408
|
+
}
|
409
|
+
return this;
|
410
|
+
},
|
411
|
+
|
412
|
+
singleMarkerZoomAdjust: function (max, target) {
|
413
|
+
// Single mark zoom adjust
|
414
|
+
// When you have an only marker focused adjust the
|
415
|
+
// map's zoom to a better adjustment
|
416
|
+
if (GMapz.debug) console.info('Automatic zoom for single marker attached.');
|
417
|
+
if (!max) max = 18; //
|
418
|
+
if (!target) target = 9;
|
419
|
+
var
|
420
|
+
that = this;
|
421
|
+
google.maps.event.addListenerOnce(this.map, 'idle', function() {
|
422
|
+
if (that.map.getZoom() > max) {
|
423
|
+
that.map.setZoom(target);
|
424
|
+
}
|
425
|
+
});
|
426
|
+
},
|
427
|
+
|
428
|
+
// Deletes a group os markers idxs (array)
|
429
|
+
deleteMarkers: function (idxArray) {
|
430
|
+
for (var i in idxArray) {
|
431
|
+
if (this.markers[idxArray[i]]) {
|
432
|
+
this.markers[idxArray[i]].setMap(null);
|
433
|
+
delete this.markers[idxArray[i]];
|
434
|
+
}
|
435
|
+
if (this.iws[idxArray[i]]) {
|
436
|
+
delete this.iws[idxArray[i]];
|
437
|
+
}
|
438
|
+
}
|
439
|
+
return this;
|
440
|
+
},
|
441
|
+
|
442
|
+
// Removes ALL markers in current map
|
443
|
+
deleteAllMarkers: function () {
|
444
|
+
if (this.markers) {
|
445
|
+
for (var idx in this.markers) {
|
446
|
+
if (this.markers.hasOwnProperty(idx) && this.markers[idx]) {
|
447
|
+
this.markers[idx].setMap(null);
|
448
|
+
delete this.markers[idx];
|
449
|
+
}
|
450
|
+
if (this.iws[idx]) {
|
451
|
+
delete this.iws[idx];
|
452
|
+
}
|
453
|
+
}
|
454
|
+
}
|
455
|
+
return this;
|
456
|
+
},
|
457
|
+
|
458
|
+
setMarkerVisibility: function (idx, visible) {
|
459
|
+
if (!visible) {
|
460
|
+
this.closeInfoWindow(idx);
|
461
|
+
}
|
462
|
+
this.markers[idx].setVisible(visible);
|
463
|
+
return this;
|
464
|
+
},
|
465
|
+
|
466
|
+
setAllMarkersVisibility: function (visible) {
|
467
|
+
for (var idx in this.markers) {
|
468
|
+
this.setMarkerVisibility(idx, visible);
|
469
|
+
}
|
470
|
+
if (visible) {
|
471
|
+
this.fitBounds();
|
472
|
+
}
|
473
|
+
return this;
|
474
|
+
},
|
475
|
+
|
476
|
+
//
|
477
|
+
// Geolocation
|
478
|
+
//
|
479
|
+
|
480
|
+
findNearestMarkerToPos: function (lat, lng) {
|
481
|
+
var
|
482
|
+
R = 6371, // radius of earth in km
|
483
|
+
distances = [],
|
484
|
+
nearidx = -1,
|
485
|
+
to_rad = Math.PI/180;
|
486
|
+
|
487
|
+
for (var key in this.markers) {
|
488
|
+
var
|
489
|
+
mlat = this.markers[key].position.lat(),
|
490
|
+
mlng = this.markers[key].position.lng(),
|
491
|
+
dLat = (mlat - lat)*to_rad,
|
492
|
+
dLng = (mlng - lng)*to_rad,
|
493
|
+
a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat*to_rad) * Math.cos(lat*to_rad) * Math.sin(dLng/2) * Math.sin(dLng/2),
|
494
|
+
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)),
|
495
|
+
d = R * c;
|
496
|
+
|
497
|
+
distances[key] = d;
|
498
|
+
if ( nearidx == -1 || d < distances[nearidx] ) {
|
499
|
+
nearidx = key;
|
500
|
+
}
|
501
|
+
}
|
502
|
+
return nearidx;
|
503
|
+
},
|
504
|
+
|
505
|
+
findNearestMarkerToAddress: function (addr) {
|
506
|
+
var
|
507
|
+
that = this,
|
508
|
+
geocoder = new google.maps.Geocoder();
|
509
|
+
|
510
|
+
// Convert location into longitude and latitude
|
511
|
+
geocoder.geocode(
|
512
|
+
{
|
513
|
+
address: addr
|
514
|
+
},
|
515
|
+
function(results, status) {
|
516
|
+
if (status == google.maps.GeocoderStatus.OK) {
|
517
|
+
var result = results[0].geometry.location;
|
518
|
+
that.geoShowPosition(result);
|
519
|
+
} else {
|
520
|
+
that.errorAddressNotFound(addr);
|
521
|
+
}
|
522
|
+
}
|
523
|
+
);
|
524
|
+
},
|
525
|
+
|
526
|
+
geoShowPosition: function (pos_or_place){
|
527
|
+
var
|
528
|
+
lat = null,
|
529
|
+
lng = null,
|
530
|
+
idx = null,
|
531
|
+
near_lat = null,
|
532
|
+
near_lng = null;
|
533
|
+
|
534
|
+
// Delete userl_location marker if exists
|
535
|
+
this.deleteUserLocationMarker();
|
536
|
+
|
537
|
+
// Coords from autocomplete (place)
|
538
|
+
if (pos_or_place.geometry) {
|
539
|
+
lat = pos_or_place.geometry.location.lat();
|
540
|
+
lng = pos_or_place.geometry.location.lng();
|
541
|
+
} else if (pos_or_place.coords) {
|
542
|
+
// Coords from Navigator.geolocation
|
543
|
+
lat = pos_or_place.coords.latitude;
|
544
|
+
lng = pos_or_place.coords.longitude;
|
545
|
+
} else {
|
546
|
+
// Coords from address geocode
|
547
|
+
lat = pos_or_place.lat();
|
548
|
+
lng = pos_or_place.lng();
|
549
|
+
}
|
550
|
+
|
551
|
+
// Find nearest marker
|
552
|
+
idx = this.findNearestMarkerToPos(lat, lng);
|
553
|
+
|
554
|
+
near_lat = this.markers[idx].position.lat();
|
555
|
+
near_lng = this.markers[idx].position.lng();
|
556
|
+
|
557
|
+
// Add user location
|
558
|
+
this.addUserLocationMarker(lat, lng);
|
559
|
+
this.map.setCenter(new google.maps.LatLng(lat, lng));
|
560
|
+
|
561
|
+
this.closeAllInfoWindows();
|
562
|
+
this.markers[idx].setVisible(true);
|
563
|
+
this.markers[idx].setAnimation(google.maps.Animation.DROP);
|
564
|
+
|
565
|
+
var bounds = new google.maps.LatLngBounds();
|
566
|
+
bounds.extend(this.markers[idx].getPosition());
|
567
|
+
bounds.extend(GMapz.getOppositeCorner(lat, lng, near_lat, near_lng));
|
568
|
+
this.map.fitBounds(bounds);
|
569
|
+
},
|
570
|
+
|
571
|
+
addUserLocationMarker: function (lat, lng) {
|
572
|
+
var
|
573
|
+
pos = new google.maps.LatLng(lat,lng);
|
574
|
+
if (!this.markers.user_location) {
|
575
|
+
this.markers.user_location = new google.maps.Marker({
|
576
|
+
position: pos,
|
577
|
+
map: this.map,
|
578
|
+
icon: GMapz.pins.user_location.pin
|
579
|
+
});
|
580
|
+
} else {
|
581
|
+
this.markers.user_location.setPosition(pos);
|
582
|
+
}
|
583
|
+
},
|
584
|
+
|
585
|
+
deleteUserLocationMarker: function () {
|
586
|
+
if (this.markers.user_location) {
|
587
|
+
this.markers.user_location.setMap(null);
|
588
|
+
delete this.markers.user_location;
|
589
|
+
}
|
590
|
+
},
|
591
|
+
|
592
|
+
geoShowError: function (error) {
|
593
|
+
switch(error.code) {
|
594
|
+
case error.PERMISSION_DENIED:
|
595
|
+
if (GMapz.debug) console.error('User denied the request for Geolocation.');
|
596
|
+
break;
|
597
|
+
case error.POSITION_UNAVAILABLE:
|
598
|
+
if (GMapz.debug) console.error('Location information is unavailable.');
|
599
|
+
break;
|
600
|
+
case error.TIMEOUT:
|
601
|
+
if (GMapz.debug) console.error('The request to get user location timed out.');
|
602
|
+
break;
|
603
|
+
case error.UNKNOWN_ERROR:
|
604
|
+
if (GMapz.debug) console.error('An unknown error occurred.');
|
605
|
+
break;
|
606
|
+
}
|
607
|
+
},
|
608
|
+
|
609
|
+
//
|
610
|
+
// Custom scroll control
|
611
|
+
//
|
612
|
+
addScrollControl: function() {
|
613
|
+
var
|
614
|
+
that = this,
|
615
|
+
$control = $('<div class="gmapz-scroll-control" title="Click to toggle map scroll"><div class="content"><span></span></div></div>');
|
616
|
+
|
617
|
+
// Attach custom control
|
618
|
+
this.map.controls[google.maps.ControlPosition.TOP_LEFT].push($control[0]);
|
619
|
+
|
620
|
+
$(document).on('click touchstart', '[data-gmapz="'+this.map_id+'"] .gmapz-scroll-control', function(e) {
|
621
|
+
e.preventDefault();
|
622
|
+
if ($(this).hasClass('locked')) {
|
623
|
+
that.resumeScroll();
|
624
|
+
} else {
|
625
|
+
that.lockScroll();
|
626
|
+
}
|
627
|
+
});
|
628
|
+
return this;
|
629
|
+
},
|
630
|
+
|
631
|
+
lockScroll: function() {
|
632
|
+
var that = this;
|
633
|
+
// Hack for execute only first time!
|
634
|
+
// Its first time map is drawn, we need to wait until tiles are drawn or
|
635
|
+
// the map.setOption(...) will not work
|
636
|
+
if (!this.gz_settings.is_drawn) {
|
637
|
+
this.listeners.tilesloaded_responsive = google.maps.event.addListenerOnce(this.map, 'tilesloaded', function(){
|
638
|
+
that.gz_settings.is_drawn = true;
|
639
|
+
google.maps.event.removeListener(that.listeners.tilesloaded_responsive);
|
640
|
+
that.lockScrollAction();
|
641
|
+
});
|
642
|
+
} else {
|
643
|
+
// Not first time, nothing to wait for
|
644
|
+
this.lockScrollAction();
|
645
|
+
}
|
646
|
+
},
|
647
|
+
|
648
|
+
lockScrollAction: function() {
|
649
|
+
var that = this;
|
650
|
+
$('[data-gmapz="'+this.map_id+'"] .gmapz-scroll-control').addClass('locked');
|
651
|
+
this.map.setOptions({
|
652
|
+
draggable: false,
|
653
|
+
scrollwheel: false
|
654
|
+
});
|
655
|
+
this.listeners.zoom_on_scroll_lock = google.maps.event.addListener(this.map, 'zoom_changed', function() {
|
656
|
+
if (GMapz.debug) console.info('Zoom changed');
|
657
|
+
that.resumeScroll();
|
658
|
+
});
|
659
|
+
},
|
660
|
+
|
661
|
+
resumeScroll: function() {
|
662
|
+
this.map.setOptions({
|
663
|
+
draggable: true,
|
664
|
+
scrollwheel: true
|
665
|
+
});
|
666
|
+
$('[data-gmapz="'+this.map_id+'"] .gmapz-scroll-control').removeClass('locked');
|
667
|
+
google.maps.event.removeListener(this.listeners.zoom_on_scroll_lock);
|
668
|
+
},
|
669
|
+
|
670
|
+
//
|
671
|
+
// Custom InfoBox infobox.js
|
672
|
+
//
|
673
|
+
defineInfoBox: function(ib_options) {
|
674
|
+
var that = this;
|
675
|
+
this.ibx = new InfoBox(ib_options);
|
676
|
+
this.ibx.gmapz_template = ib_options.content;
|
677
|
+
// Clean replace
|
678
|
+
this.ibx.setContent(this.ibx.gmapz_template.replace('{{__REPLACE__}}',''));
|
679
|
+
|
680
|
+
// Add close event for infobox
|
681
|
+
$(document).on('click touchstart', '.gmapz-ibx-close', function(e) {
|
682
|
+
e.preventDefault();
|
683
|
+
that.ibx.close();
|
684
|
+
});
|
685
|
+
},
|
686
|
+
|
687
|
+
//
|
688
|
+
// Buttons and interaction
|
689
|
+
//
|
690
|
+
|
691
|
+
btnAction: function (data, $el) {
|
692
|
+
// console.log(data);
|
693
|
+
// console.log($el);
|
694
|
+
|
695
|
+
var zoom = false;
|
696
|
+
if (typeof data.gmapzZoom !== 'undefined') {
|
697
|
+
zoom = parseInt(data.gmapzZoom, 10);
|
698
|
+
}
|
699
|
+
|
700
|
+
// Show all markers and fit map
|
701
|
+
if (typeof data.gmapzShowAll !== 'undefined') {
|
702
|
+
this.setAllMarkersVisibility(true);
|
703
|
+
}
|
704
|
+
|
705
|
+
// Show group of markers
|
706
|
+
if (typeof data.gmapzShowGroup !== 'undefined') {
|
707
|
+
var
|
708
|
+
group = data.gmapzShowGroup,
|
709
|
+
hide_rest = false;
|
710
|
+
if (typeof data.gmapzHideRest !== 'undefined' && data.gmapzHideRest === true) {
|
711
|
+
hide_rest = true;
|
712
|
+
}
|
713
|
+
if (data === parseInt(data, 10) || typeof group === 'string') {
|
714
|
+
group = [group];
|
715
|
+
}
|
716
|
+
this.showMarkerGroup(group, hide_rest);
|
717
|
+
}
|
718
|
+
|
719
|
+
// Center on marker
|
720
|
+
if (typeof data.gmapzCenterIdx !== 'undefined') {
|
721
|
+
this.centerToMarker(data.gmapzCenterIdx, zoom);
|
722
|
+
}
|
723
|
+
|
724
|
+
// Find near geolocation
|
725
|
+
if (typeof data.gmapzFindNear !== 'undefined') {
|
726
|
+
var
|
727
|
+
n = navigator.geolocation;
|
728
|
+
if(n) {
|
729
|
+
n.getCurrentPosition(this.geoShowPosition.bind(this), this.geoShowError.bind(this));
|
730
|
+
} else {
|
731
|
+
if (GMapz.debug) console.error('Your web browser doesn\'t support geolocation.');
|
732
|
+
return false;
|
733
|
+
}
|
734
|
+
}
|
735
|
+
|
736
|
+
// Find near address
|
737
|
+
if (typeof data.gmapzFindNearAddress !== 'undefined') {
|
738
|
+
var
|
739
|
+
$input = $($el.data('gmapzInput'));
|
740
|
+
if ($input.length) {
|
741
|
+
var addr = $input.val();
|
742
|
+
// console.log(addr);
|
743
|
+
this.findNearestMarkerToAddress(addr);
|
744
|
+
} else {
|
745
|
+
if (GMapz.debug) console.warn("<input> element '"+$el.data('gmapzInput')+"' not found!");
|
746
|
+
}
|
747
|
+
}
|
748
|
+
|
749
|
+
}, // btnAction
|
750
|
+
|
751
|
+
//
|
752
|
+
// Extra / helpers
|
753
|
+
//
|
754
|
+
|
755
|
+
// Converts latitude longitude to pixels on map
|
756
|
+
convertLatLngToPixels: function (lat_lng) {
|
757
|
+
var
|
758
|
+
scale = Math.pow(2, this.map.getZoom()),
|
759
|
+
proj = this.map.getProjection(),
|
760
|
+
bounds = this.map.getBounds(),
|
761
|
+
nw = proj.fromLatLngToPoint(
|
762
|
+
new google.maps.LatLng(
|
763
|
+
bounds.getNorthEast().lat(),
|
764
|
+
bounds.getSouthWest().lng()
|
765
|
+
)
|
766
|
+
),
|
767
|
+
point = proj.fromLatLngToPoint(lat_lng);
|
768
|
+
|
769
|
+
return new google.maps.Point(
|
770
|
+
Math.floor((point.x - nw.x) * scale),
|
771
|
+
Math.floor((point.y - nw.y) * scale)
|
772
|
+
);
|
773
|
+
},
|
774
|
+
|
775
|
+
//
|
776
|
+
// Eventos
|
777
|
+
//
|
778
|
+
onMarkerDragEnd: function(marker) {
|
779
|
+
if (GMapz.debug) console.log(marker);
|
780
|
+
},
|
781
|
+
errorAddressNotFound: function(addr) {
|
782
|
+
if (GMapz.debug) console.warn("'"+addr+"' address not found!");
|
783
|
+
}
|
784
|
+
|
785
|
+
};
|
786
|
+
|
787
|
+
return Constructor;
|
788
|
+
|
789
|
+
})();
|