-
Notifications
You must be signed in to change notification settings - Fork 8
/
jquery.geolocation.edit.js
280 lines (234 loc) · 6.63 KB
/
jquery.geolocation.edit.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/**
* jQuery geolocation.edit plugin
* Copyright (c) 2012 Milos Popovic <[email protected]>
*
* Freely distributable under the MIT license.
*
* @version 0.0.16 (2015-10-16)
* @see http://github.com/miloss/jquery-geolocation-edit
*/
(function ($) {
var loadScript;
// Queued initializations
var inits = [];
// Methods container object
var methods = {};
// Plugin methods
/**
* Main execution method
* @param {Object} options Passed plugin options
*/
methods.main = function (options) {
var selector = this;
// Check for required fields
if (typeof options.lat === 'undefined' || typeof options.lng === 'undefined') {
$.error("Please provide 'lat' and 'lng' options for jQuery.geolocate");
return;
}
// If GoogleMaps not loaded - push init to queue and go on
if (typeof google === 'undefined' || typeof google.maps === 'undefined') {
inits.push(function () {
$(selector).geolocate(options);
});
loadScript();
return;
}
// Extend default options
var opts = $.extend(true, {
address: [],
changeOnEdit: false,
readOnlyMap: false, // Don't allow pin movement on click
mapOptions: {
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false,
streetViewControl: false
},
markerOptions: {
draggable:true,
animation: google.maps.Animation.DROP
},
geoCallback: function(){},
navigatorCallback: function(){},
navigatorFailCallback: function(){}
}, options);
$(this).data('opts', opts);
// Init map and marker - per coordinates
var llat = parseFloat( $( opts.lat ).val() );
var llng = parseFloat( $( opts.lng ).val() );
if (isNaN(llat)) {
llat = 0;
}
if (isNaN(llng)) {
llng = 0;
}
var llocation = new google.maps.LatLng(llat, llng);
$(this).geolocate({}, 'initMap', llocation);
// Bind actions - coordinates fields
if ( opts.changeOnEdit ) {
$( opts.lat ).change(function () { $(selector).geolocate({}, 'updateLatLng', opts); });
$( opts.lng ).change(function () { $(selector).geolocate({}, 'updateLatLng', opts); });
}
// Bind actions - address field
var addrlen = opts.address.length;
for (var i = 0; i < addrlen; i++) {
$( opts.address[i] ).change(function () {
$(selector).geolocate({}, 'callGeocoding');
});
}
};
/**
* Initialize GoogleMaps Map on page
* @param {LatLng} location GoogleMaps object
*/
methods.initMap = function (location) {
var self = $(this).get(0);
var gmaps = google.maps;
var opts = $.data(self, 'opts');
var map = new gmaps.Map(self, $.extend({
center: location
}, opts.mapOptions));
var markerOptions = $.extend({
map: map,
position: location
}, opts.markerOptions);
var marker = new gmaps.Marker(markerOptions);
$.data(self, 'map', map);
$.data(self, 'marker', marker);
gmaps.event.addListener(marker, 'dragend', function () {
$(self).geolocate({}, 'getMarkerLocation');
});
// Move the marker to the location user clicks
if (!opts.readOnlyMap) {
gmaps.event.addListener(map, 'click', function (event) {
marker.setPosition(event.latLng);
$(self).geolocate({}, 'getMarkerLocation');
});
}
};
/**
* Make Google Geocoding call with provided address
*/
methods.callGeocoding = function () {
var self = $(this).get(0);
var opts = $.data(self, 'opts');
var len = opts.address.length;
var cbfunc = opts.geoCallback;
// Get address
var addr = '';
while (len--) {
addr += $( opts.address[len] ).val();
}
// Make request
var geo = new google.maps.Geocoder();
// Geocoder response
geo.geocode({
address: addr
}, function (data, status) {
var loc, first, map, marker;
cbfunc(data, status);
first = data[0];
if (typeof first === 'undefined') return;
map = $.data(self, 'map');
marker = $.data(self, 'marker');
loc = first.geometry.location;
map.panToBounds( first.geometry.viewport );
map.panTo( loc );
marker.setPosition( loc );
$(self).geolocate({}, 'getMarkerLocation');
});
};
/**
* Use navigator provided location
*/
methods.navigatorLocation = function () {
var self = $(this).get(0)
var opts = $.data(self, 'opts');
var cbfunc = opts.navigatorCallback;
var cbfailfunc = opts.navigatorFailCallback;
// Try HTML5 geolocation.
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position) {
var loc, map, marker;
cbfunc(position);
loc = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
map = $.data(self, "map");
marker = $.data(self, "marker");
map.panTo(loc);
marker.setPosition(loc);
map.setCenter(loc);
$(self).geolocate({}, "getMarkerLocation");
},
cbfailfunc
);
} else {
cbfailfunc();
}
};
/**
* Copy marker position to coordinates fields
*/
methods.getMarkerLocation = function () {
var marker = $.data($(this).get(0), 'marker');
var opts = $.data($(this).get(0), 'opts');
var pos = marker.getPosition();;
$( opts.lat ).val( pos.lat() );
$( opts.lng ).val( pos.lng() );
};
/**
* Move to the current settings for lat & lng
* @param {Object} opts
*/
methods.updateLatLng = function (opts) {
var self = $(this).get(0);
var lat = $( opts.lat ).val();
var lng = $( opts.lng ).val();
var loc = new google.maps.LatLng(lat, lng);
var map = $.data(self, 'map');
var marker = $.data(self, 'marker');
map.panTo(loc);
marker.setPosition(loc);
};
// Main plugin function
// Call appropriate method, or execute 'main'
$.fn.geolocate = function (os, method) {
var pslice = Array.prototype.slice;
if ( typeof method === 'undefined' ) { // Only method passed (as 1st parameter)
if ( typeof os === 'string' && typeof methods[os] !== 'undefined' ) {
return methods[ os ].apply( this, pslice.call( arguments, 1 ));
} else {
$(this).geolocate({}, 'main', os);
}
} else if ( methods[method] ) {
return methods[ method ].apply( this, pslice.call( arguments, 2 ));
} else {
$.error("Method " + method + " does not exist on jQuery.geolocate");
}
return this;
};
// Callback to GoogleMaps async loading
// FIXME find non-jQuery.fn-polluting solution
$.fn.geolocateGMapsLoaded = function () {
while (inits.length) {
inits.shift()();
}
};
// Private functions
// Load GoogleMaps, we want to do it only once
loadScript = (function () {
var ran = false;
return function () {
var script;
if (ran) return;
ran = true;
script = document.createElement("script");
script.type = "text/javascript";
script.src = "//maps.googleapis.com/maps/api/js?sensor=false&callback=$.fn.geolocateGMapsLoaded";
document.body.appendChild(script);
};
})();
})(jQuery);