geocomplete_rails 1.6.3 → 1.6.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fb64c9bec93cd29e788747800763eef8fd345f97
4
- data.tar.gz: 1a15863cca6e3ea4ff629f0b5c5d6e42a5188533
3
+ metadata.gz: 0c98206237b7f337a6ae95ed9634d8f63b3f8ce7
4
+ data.tar.gz: c6896d1fda94b8b229ffbca47c20631bf44ac697
5
5
  SHA512:
6
- metadata.gz: 461f8dfdd75427f307550da6f413ed2d7a4ca6e54e1cf042b1159818bea44daa35979c94be7c9292073d1fc7b03d05eb24568983308351b65b9d45fee253cbeb
7
- data.tar.gz: 6e631815c246755d311771795a17b9e9a7721b286d2bf1fa0e14ba5536f998dbb3a98be0a1b68dfaae8838a771bf7b170522738b3dccf6f41629ece0f7e7e317
6
+ metadata.gz: d5261f258b4613d5b737a0a5b9841c25a13b9d70e5320e40f11aec2fd28ef75c77af89d06b73afb2327a806048c2d7c33a8abcd2f93496f51b49eb9091f53f5c
7
+ data.tar.gz: c3e32fdbd8828e8a5912186befd3102fa414b4db74e1bef86ba81487896df3e3d8640258f5148267ab56509f81ef2014f0f943553a7274b21de5a30de1ff420e
@@ -1,503 +1,521 @@
1
- /**
2
- * jQuery Geocoding and Places Autocomplete Plugin - V 1.6.1
3
- *
4
- * @author Martin Kleppe <kleppe@ubilabs.net>, 2014
5
- * @author Ubilabs http://ubilabs.net, 2014
6
- * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
7
- */
8
-
9
- // # $.geocomplete()
10
- // ## jQuery Geocoding and Places Autocomplete Plugin
11
- //
12
- // * https://github.com/ubilabs/geocomplete/
13
- // * by Martin Kleppe <kleppe@ubilabs.net>
14
-
15
- (function($, window, document, undefined){
16
-
17
- // ## Options
18
- // The default options for this plugin.
19
- //
20
- // * `map` - Might be a selector, an jQuery object or a DOM element. Default is `false` which shows no map.
21
- // * `details` - The container that should be populated with data. Defaults to `false` which ignores the setting.
22
- // * `location` - Location to initialize the map on. Might be an address `string` or an `array` with [latitude, longitude] or a `google.maps.LatLng`object. Default is `false` which shows a blank map.
23
- // * `bounds` - Whether to snap geocode search to map bounds. Default: `true` if false search globally. Alternatively pass a custom `LatLngBounds object.
24
- // * `autoselect` - Automatically selects the highlighted item or the first item from the suggestions list on Enter.
25
- // * `detailsAttribute` - The attribute's name to use as an indicator. Default: `"name"`
26
- // * `mapOptions` - Options to pass to the `google.maps.Map` constructor. See the full list [here](http://code.google.com/apis/maps/documentation/javascript/reference.html#MapOptions).
27
- // * `mapOptions.zoom` - The inital zoom level. Default: `14`
28
- // * `mapOptions.scrollwheel` - Whether to enable the scrollwheel to zoom the map. Default: `false`
29
- // * `mapOptions.mapTypeId` - The map type. Default: `"roadmap"`
30
- // * `markerOptions` - The options to pass to the `google.maps.Marker` constructor. See the full list [here](http://code.google.com/apis/maps/documentation/javascript/reference.html#MarkerOptions).
31
- // * `markerOptions.draggable` - If the marker is draggable. Default: `false`. Set to true to enable dragging.
32
- // * `markerOptions.disabled` - Do not show marker. Default: `false`. Set to true to disable marker.
33
- // * `maxZoom` - The maximum zoom level too zoom in after a geocoding response. Default: `16`
34
- // * `types` - An array containing one or more of the supported types for the places request. Default: `['geocode']` See the full list [here](http://code.google.com/apis/maps/documentation/javascript/places.html#place_search_requests).
35
-
36
- var defaults = {
37
- bounds: true,
38
- country: null,
39
- map: false,
40
- details: false,
41
- detailsAttribute: "name",
42
- autoselect: true,
43
- location: false,
44
-
45
- mapOptions: {
46
- zoom: 14,
47
- scrollwheel: false,
48
- mapTypeId: "roadmap"
49
- },
50
-
51
- markerOptions: {
52
- draggable: false
53
- },
54
-
55
- maxZoom: 16,
56
- types: ['geocode'],
57
- blur: false
58
- };
59
-
60
- // See: [Geocoding Types](https://developers.google.com/maps/documentation/geocoding/#Types)
61
- // on Google Developers.
62
- var componentTypes = ("street_address route intersection political " +
63
- "country administrative_area_level_1 administrative_area_level_2 " +
64
- "administrative_area_level_3 colloquial_area locality sublocality " +
65
- "neighborhood premise subpremise postal_code natural_feature airport " +
66
- "park point_of_interest post_box street_number floor room " +
67
- "lat lng viewport location " +
68
- "formatted_address location_type bounds").split(" ");
69
-
70
- // See: [Places Details Responses](https://developers.google.com/maps/documentation/javascript/places#place_details_responses)
71
- // on Google Developers.
72
- var placesDetails = ("id place_id url website vicinity reference name rating " +
73
- "international_phone_number icon formatted_phone_number").split(" ");
74
-
75
- // The actual plugin constructor.
76
- function GeoComplete(input, options) {
77
-
78
- this.options = $.extend(true, {}, defaults, options);
79
-
80
- this.input = input;
81
- this.$input = $(input);
82
-
83
- this._defaults = defaults;
84
- this._name = 'geocomplete';
85
-
86
- this.init();
87
- }
88
-
89
- // Initialize all parts of the plugin.
90
- $.extend(GeoComplete.prototype, {
91
- init: function(){
92
- this.initMap();
93
- this.initMarker();
94
- this.initGeocoder();
95
- this.initDetails();
96
- this.initLocation();
97
- },
98
-
99
- // Initialize the map but only if the option `map` was set.
100
- // This will create a `map` within the given container
101
- // using the provided `mapOptions` or link to the existing map instance.
102
- initMap: function(){
103
- if (!this.options.map){ return; }
104
-
105
- if (typeof this.options.map.setCenter == "function"){
106
- this.map = this.options.map;
107
- return;
108
- }
109
-
110
- this.map = new google.maps.Map(
111
- $(this.options.map)[0],
112
- this.options.mapOptions
113
- );
114
-
115
- // add click event listener on the map
116
- google.maps.event.addListener(
117
- this.map,
118
- 'click',
119
- $.proxy(this.mapClicked, this)
120
- );
121
-
122
- google.maps.event.addListener(
123
- this.map,
124
- 'zoom_changed',
125
- $.proxy(this.mapZoomed, this)
126
- );
127
- },
128
-
129
- // Add a marker with the provided `markerOptions` but only
130
- // if the option was set. Additionally it listens for the `dragend` event
131
- // to notify the plugin about changes.
132
- initMarker: function(){
133
- if (!this.map){ return; }
134
- var options = $.extend(this.options.markerOptions, { map: this.map });
135
-
136
- if (options.disabled){ return; }
137
-
138
- this.marker = new google.maps.Marker(options);
139
-
140
- google.maps.event.addListener(
141
- this.marker,
142
- 'dragend',
143
- $.proxy(this.markerDragged, this)
144
- );
145
- },
146
-
147
- // Associate the input with the autocompleter and create a geocoder
148
- // to fall back when the autocompleter does not return a value.
149
- initGeocoder: function(){
150
-
151
- var options = {
152
- types: this.options.types,
153
- bounds: this.options.bounds === true ? null : this.options.bounds,
154
- componentRestrictions: this.options.componentRestrictions
155
- };
156
-
157
- if (this.options.country){
158
- options.componentRestrictions = {country: this.options.country};
159
- }
160
-
161
- this.autocomplete = new google.maps.places.Autocomplete(
162
- this.input, options
163
- );
164
-
165
- this.geocoder = new google.maps.Geocoder();
166
-
167
- // Bind autocomplete to map bounds but only if there is a map
168
- // and `options.bindToMap` is set to true.
169
- if (this.map && this.options.bounds === true){
170
- this.autocomplete.bindTo('bounds', this.map);
171
- }
172
-
173
- // Watch `place_changed` events on the autocomplete input field.
174
- google.maps.event.addListener(
175
- this.autocomplete,
176
- 'place_changed',
177
- $.proxy(this.placeChanged, this)
178
- );
179
-
180
- // Prevent parent form from being submitted if user hit enter.
181
- this.$input.keypress(function(event){
182
- if (event.keyCode === 13){ return false; }
183
- });
184
-
185
- // Listen for "geocode" events and trigger find action.
186
- this.$input.bind("geocode", $.proxy(function(){
187
- this.find();
188
- }, this));
189
-
190
- // Trigger find action when input element is blured out.
191
- // (Usefull for typing partial location and tabing to the next field
192
- // or clicking somewhere else.)
193
- if (this.options.blur === true){
194
- this.$input.blur($.proxy(function(){
195
- this.find();
196
- }, this));
197
- }
198
- },
199
-
200
- // Prepare a given DOM structure to be populated when we got some data.
201
- // This will cycle through the list of component types and map the
202
- // corresponding elements.
203
- initDetails: function(){
204
- if (!this.options.details){ return; }
205
-
206
- var $details = $(this.options.details),
207
- attribute = this.options.detailsAttribute,
208
- details = {};
209
-
210
- function setDetail(value){
211
- details[value] = $details.find("[" + attribute + "=" + value + "]");
212
- }
213
-
214
- $.each(componentTypes, function(index, key){
215
- setDetail(key);
216
- setDetail(key + "_short");
217
- });
218
-
219
- $.each(placesDetails, function(index, key){
220
- setDetail(key);
221
- });
222
-
223
- this.$details = $details;
224
- this.details = details;
225
- },
226
-
227
- // Set the initial location of the plugin if the `location` options was set.
228
- // This method will care about converting the value into the right format.
229
- initLocation: function() {
230
-
231
- var location = this.options.location, latLng;
232
-
233
- if (!location) { return; }
234
-
235
- if (typeof location == 'string') {
236
- this.find(location);
237
- return;
238
- }
239
-
240
- if (location instanceof Array) {
241
- latLng = new google.maps.LatLng(location[0], location[1]);
242
- }
243
-
244
- if (location instanceof google.maps.LatLng){
245
- latLng = location;
246
- }
247
-
248
- if (latLng){
249
- if (this.map){ this.map.setCenter(latLng); }
250
- if (this.marker){ this.marker.setPosition(latLng); }
251
- }
252
- },
253
-
254
- // Look up a given address. If no `address` was specified it uses
255
- // the current value of the input.
256
- find: function(address){
257
- this.geocode({
258
- address: address || this.$input.val()
259
- });
260
- },
261
-
262
- // Requests details about a given location.
263
- // Additionally it will bias the requests to the provided bounds.
264
- geocode: function(request){
265
- if (this.options.bounds && !request.bounds){
266
- if (this.options.bounds === true){
267
- request.bounds = this.map && this.map.getBounds();
268
- } else {
269
- request.bounds = this.options.bounds;
270
- }
271
- }
272
-
273
- if (this.options.country){
274
- request.region = this.options.country;
275
- }
276
-
277
- this.geocoder.geocode(request, $.proxy(this.handleGeocode, this));
278
- },
279
-
280
- // Get the selected result. If no result is selected on the list, then get
281
- // the first result from the list.
282
- selectFirstResult: function() {
283
- //$(".pac-container").hide();
284
-
285
- var selected = '';
286
- // Check if any result is selected.
287
- if ($(".pac-item-selected")[0]) {
288
- selected = '-selected';
289
- }
290
-
291
- // Get the first suggestion's text.
292
- var $span1 = $(".pac-container .pac-item" + selected + ":first span:nth-child(2)").text();
293
- var $span2 = $(".pac-container .pac-item" + selected + ":first span:nth-child(3)").text();
294
-
295
- // Adds the additional information, if available.
296
- var firstResult = $span1;
297
- if ($span2) {
298
- firstResult += " - " + $span2;
299
- }
300
-
301
- this.$input.val(firstResult);
302
-
303
- return firstResult;
304
- },
305
-
306
- // Handles the geocode response. If more than one results was found
307
- // it triggers the "geocode:multiple" events. If there was an error
308
- // the "geocode:error" event is fired.
309
- handleGeocode: function(results, status){
310
- if (status === google.maps.GeocoderStatus.OK) {
311
- var result = results[0];
312
- this.$input.val(result.formatted_address);
313
- this.update(result);
314
-
315
- if (results.length > 1){
316
- this.trigger("geocode:multiple", results);
317
- }
318
-
319
- } else {
320
- this.trigger("geocode:error", status);
321
- }
322
- },
323
-
324
- // Triggers a given `event` with optional `arguments` on the input.
325
- trigger: function(event, argument){
326
- this.$input.trigger(event, [argument]);
327
- },
328
-
329
- // Set the map to a new center by passing a `geometry`.
330
- // If the geometry has a viewport, the map zooms out to fit the bounds.
331
- // Additionally it updates the marker position.
332
- center: function(geometry){
333
-
334
- if (geometry.viewport){
335
- this.map.fitBounds(geometry.viewport);
336
- if (this.map.getZoom() > this.options.maxZoom){
337
- this.map.setZoom(this.options.maxZoom);
338
- }
339
- } else {
340
- this.map.setZoom(this.options.maxZoom);
341
- this.map.setCenter(geometry.location);
342
- }
343
-
344
- if (this.marker){
345
- this.marker.setPosition(geometry.location);
346
- this.marker.setAnimation(this.options.markerOptions.animation);
347
- }
348
- },
349
-
350
- // Update the elements based on a single places or geoocoding response
351
- // and trigger the "geocode:result" event on the input.
352
- update: function(result){
353
-
354
- if (this.map){
355
- this.center(result.geometry);
356
- }
357
-
358
- if (this.$details){
359
- this.fillDetails(result);
360
- }
361
-
362
- this.trigger("geocode:result", result);
363
- },
364
-
365
- // Populate the provided elements with new `result` data.
366
- // This will lookup all elements that has an attribute with the given
367
- // component type.
368
- fillDetails: function(result){
369
-
370
- var data = {},
371
- geometry = result.geometry,
372
- viewport = geometry.viewport,
373
- bounds = geometry.bounds;
374
-
375
- // Create a simplified version of the address components.
376
- $.each(result.address_components, function(index, object){
377
- var name = object.types[0];
378
-
379
- $.each(object.types, function(index, name){
380
- data[name] = object.long_name;
381
- data[name + "_short"] = object.short_name;
382
- });
383
- });
384
-
385
- // Add properties of the places details.
386
- $.each(placesDetails, function(index, key){
387
- data[key] = result[key];
388
- });
389
-
390
- // Add infos about the address and geometry.
391
- $.extend(data, {
392
- formatted_address: result.formatted_address,
393
- location_type: geometry.location_type || "PLACES",
394
- viewport: viewport,
395
- bounds: bounds,
396
- location: geometry.location,
397
- lat: geometry.location.lat(),
398
- lng: geometry.location.lng()
399
- });
400
-
401
- // Set the values for all details.
402
- $.each(this.details, $.proxy(function(key, $detail){
403
- var value = data[key];
404
- this.setDetail($detail, value);
405
- }, this));
406
-
407
- this.data = data;
408
- },
409
-
410
- // Assign a given `value` to a single `$element`.
411
- // If the element is an input, the value is set, otherwise it updates
412
- // the text content.
413
- setDetail: function($element, value){
414
-
415
- if (value === undefined){
416
- value = "";
417
- } else if (typeof value.toUrlValue == "function"){
418
- value = value.toUrlValue();
419
- }
420
-
421
- if ($element.is(":input")){
422
- $element.val(value);
423
- } else {
424
- $element.text(value);
425
- }
426
- },
427
-
428
- // Fire the "geocode:dragged" event and pass the new position.
429
- markerDragged: function(event){
430
- this.trigger("geocode:dragged", event.latLng);
431
- },
432
-
433
- mapClicked: function(event) {
434
- this.trigger("geocode:click", event.latLng);
435
- },
436
-
437
- mapZoomed: function(event) {
438
- this.trigger("geocode:zoom", this.map.getZoom());
439
- },
440
-
441
- // Restore the old position of the marker to the last now location.
442
- resetMarker: function(){
443
- this.marker.setPosition(this.data.location);
444
- this.setDetail(this.details.lat, this.data.location.lat());
445
- this.setDetail(this.details.lng, this.data.location.lng());
446
- },
447
-
448
- // Update the plugin after the user has selected an autocomplete entry.
449
- // If the place has no geometry it passes it to the geocoder.
450
- placeChanged: function(){
451
- var place = this.autocomplete.getPlace();
452
-
453
- if (!place || !place.geometry){
454
- if (this.options.autoselect) {
455
- // Automatically selects the highlighted item or the first item from the
456
- // suggestions list.
457
- var autoSelection = this.selectFirstResult();
458
- this.find(autoSelection);
459
- }
460
- } else {
461
- // Use the input text if it already gives geometry.
462
- this.update(place);
463
- }
464
- }
465
- });
466
-
467
- // A plugin wrapper around the constructor.
468
- // Pass `options` with all settings that are different from the default.
469
- // The attribute is used to prevent multiple instantiations of the plugin.
470
- $.fn.geocomplete = function(options) {
471
-
472
- var attribute = 'plugin_geocomplete';
473
-
474
- // If you call `.geocomplete()` with a string as the first parameter
475
- // it returns the corresponding property or calls the method with the
476
- // following arguments.
477
- if (typeof options == "string"){
478
-
479
- var instance = $(this).data(attribute) || $(this).geocomplete().data(attribute),
480
- prop = instance[options];
481
-
482
- if (typeof prop == "function"){
483
- prop.apply(instance, Array.prototype.slice.call(arguments, 1));
484
- return $(this);
485
- } else {
486
- if (arguments.length == 2){
487
- prop = arguments[1];
488
- }
489
- return prop;
490
- }
491
- } else {
492
- return this.each(function() {
493
- // Prevent against multiple instantiations.
494
- var instance = $.data(this, attribute);
495
- if (!instance) {
496
- instance = new GeoComplete( this, options );
497
- $.data(this, attribute, instance);
498
- }
499
- });
500
- }
501
- };
502
-
503
- })( jQuery, window, document );
1
+ /**
2
+ * jQuery Geocoding and Places Autocomplete Plugin - V 1.6.4
3
+ *
4
+ * @author Martin Kleppe <kleppe@ubilabs.net>, 2014
5
+ * @author Ubilabs http://ubilabs.net, 2014
6
+ * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
7
+ */
8
+
9
+ // # $.geocomplete()
10
+ // ## jQuery Geocoding and Places Autocomplete Plugin
11
+ //
12
+ // * https://github.com/ubilabs/geocomplete/
13
+ // * by Martin Kleppe <kleppe@ubilabs.net>
14
+
15
+ (function($, window, document, undefined){
16
+
17
+ // ## Options
18
+ // The default options for this plugin.
19
+ //
20
+ // * `map` - Might be a selector, an jQuery object or a DOM element. Default is `false` which shows no map.
21
+ // * `details` - The container that should be populated with data. Defaults to `false` which ignores the setting.
22
+ // * `location` - Location to initialize the map on. Might be an address `string` or an `array` with [latitude, longitude] or a `google.maps.LatLng`object. Default is `false` which shows a blank map.
23
+ // * `bounds` - Whether to snap geocode search to map bounds. Default: `true` if false search globally. Alternatively pass a custom `LatLngBounds object.
24
+ // * `autoselect` - Automatically selects the highlighted item or the first item from the suggestions list on Enter.
25
+ // * `detailsAttribute` - The attribute's name to use as an indicator. Default: `"name"`
26
+ // * `mapOptions` - Options to pass to the `google.maps.Map` constructor. See the full list [here](http://code.google.com/apis/maps/documentation/javascript/reference.html#MapOptions).
27
+ // * `mapOptions.zoom` - The inital zoom level. Default: `14`
28
+ // * `mapOptions.scrollwheel` - Whether to enable the scrollwheel to zoom the map. Default: `false`
29
+ // * `mapOptions.mapTypeId` - The map type. Default: `"roadmap"`
30
+ // * `markerOptions` - The options to pass to the `google.maps.Marker` constructor. See the full list [here](http://code.google.com/apis/maps/documentation/javascript/reference.html#MarkerOptions).
31
+ // * `markerOptions.draggable` - If the marker is draggable. Default: `false`. Set to true to enable dragging.
32
+ // * `markerOptions.disabled` - Do not show marker. Default: `false`. Set to true to disable marker.
33
+ // * `maxZoom` - The maximum zoom level too zoom in after a geocoding response. Default: `16`
34
+ // * `types` - An array containing one or more of the supported types for the places request. Default: `['geocode']` See the full list [here](http://code.google.com/apis/maps/documentation/javascript/places.html#place_search_requests).
35
+ // * `blur` - Trigger geocode when input loses focus.
36
+ // * `geocodeAfterResult` - If blur is set to true, choose whether to geocode if user has explicitly selected a result before blur.
37
+
38
+ var defaults = {
39
+ bounds: true,
40
+ country: null,
41
+ map: false,
42
+ details: false,
43
+ detailsAttribute: "name",
44
+ autoselect: true,
45
+ location: false,
46
+
47
+ mapOptions: {
48
+ zoom: 14,
49
+ scrollwheel: false,
50
+ mapTypeId: "roadmap"
51
+ },
52
+
53
+ markerOptions: {
54
+ draggable: false
55
+ },
56
+
57
+ maxZoom: 16,
58
+ types: ['geocode'],
59
+ blur: false,
60
+ geocodeAfterResult: false
61
+ };
62
+
63
+ // See: [Geocoding Types](https://developers.google.com/maps/documentation/geocoding/#Types)
64
+ // on Google Developers.
65
+ var componentTypes = ("street_address route intersection political " +
66
+ "country administrative_area_level_1 administrative_area_level_2 " +
67
+ "administrative_area_level_3 colloquial_area locality sublocality " +
68
+ "neighborhood premise subpremise postal_code natural_feature airport " +
69
+ "park point_of_interest post_box street_number floor room " +
70
+ "lat lng viewport location " +
71
+ "formatted_address location_type bounds").split(" ");
72
+
73
+ // See: [Places Details Responses](https://developers.google.com/maps/documentation/javascript/places#place_details_responses)
74
+ // on Google Developers.
75
+ var placesDetails = ("id place_id url website vicinity reference name rating " +
76
+ "international_phone_number icon formatted_phone_number").split(" ");
77
+
78
+ // The actual plugin constructor.
79
+ function GeoComplete(input, options) {
80
+
81
+ this.options = $.extend(true, {}, defaults, options);
82
+
83
+ this.input = input;
84
+ this.$input = $(input);
85
+
86
+ this._defaults = defaults;
87
+ this._name = 'geocomplete';
88
+
89
+ this.init();
90
+ }
91
+
92
+ // Initialize all parts of the plugin.
93
+ $.extend(GeoComplete.prototype, {
94
+ init: function(){
95
+ this.initMap();
96
+ this.initMarker();
97
+ this.initGeocoder();
98
+ this.initDetails();
99
+ this.initLocation();
100
+ },
101
+
102
+ // Initialize the map but only if the option `map` was set.
103
+ // This will create a `map` within the given container
104
+ // using the provided `mapOptions` or link to the existing map instance.
105
+ initMap: function(){
106
+ if (!this.options.map){ return; }
107
+
108
+ if (typeof this.options.map.setCenter == "function"){
109
+ this.map = this.options.map;
110
+ return;
111
+ }
112
+
113
+ this.map = new google.maps.Map(
114
+ $(this.options.map)[0],
115
+ this.options.mapOptions
116
+ );
117
+
118
+ // add click event listener on the map
119
+ google.maps.event.addListener(
120
+ this.map,
121
+ 'click',
122
+ $.proxy(this.mapClicked, this)
123
+ );
124
+
125
+ google.maps.event.addListener(
126
+ this.map,
127
+ 'zoom_changed',
128
+ $.proxy(this.mapZoomed, this)
129
+ );
130
+ },
131
+
132
+ // Add a marker with the provided `markerOptions` but only
133
+ // if the option was set. Additionally it listens for the `dragend` event
134
+ // to notify the plugin about changes.
135
+ initMarker: function(){
136
+ if (!this.map){ return; }
137
+ var options = $.extend(this.options.markerOptions, { map: this.map });
138
+
139
+ if (options.disabled){ return; }
140
+
141
+ this.marker = new google.maps.Marker(options);
142
+
143
+ google.maps.event.addListener(
144
+ this.marker,
145
+ 'dragend',
146
+ $.proxy(this.markerDragged, this)
147
+ );
148
+ },
149
+
150
+ // Associate the input with the autocompleter and create a geocoder
151
+ // to fall back when the autocompleter does not return a value.
152
+ initGeocoder: function(){
153
+
154
+ // Indicates is user did select a result from the dropdown.
155
+ var selected = false;
156
+
157
+ var options = {
158
+ types: this.options.types,
159
+ bounds: this.options.bounds === true ? null : this.options.bounds,
160
+ componentRestrictions: this.options.componentRestrictions
161
+ };
162
+
163
+ if (this.options.country){
164
+ options.componentRestrictions = {country: this.options.country};
165
+ }
166
+
167
+ this.autocomplete = new google.maps.places.Autocomplete(
168
+ this.input, options
169
+ );
170
+
171
+ this.geocoder = new google.maps.Geocoder();
172
+
173
+ // Bind autocomplete to map bounds but only if there is a map
174
+ // and `options.bindToMap` is set to true.
175
+ if (this.map && this.options.bounds === true){
176
+ this.autocomplete.bindTo('bounds', this.map);
177
+ }
178
+
179
+ // Watch `place_changed` events on the autocomplete input field.
180
+ google.maps.event.addListener(
181
+ this.autocomplete,
182
+ 'place_changed',
183
+ $.proxy(this.placeChanged, this)
184
+ );
185
+
186
+ // Prevent parent form from being submitted if user hit enter.
187
+ this.$input.keypress(function(event){
188
+ if (event.keyCode === 13){ return false; }
189
+ });
190
+
191
+ // Assume that if user types anything after having selected a result,
192
+ // the selected location is not valid any more.
193
+ if (this.options.geocodeAfterResult === true){
194
+ this.$input.bind('keypress', $.proxy(function(){
195
+ if (event.keyCode != 9 && this.selected === true){
196
+ this.selected = false;
197
+ }
198
+ }, this));
199
+ }
200
+
201
+ // Listen for "geocode" events and trigger find action.
202
+ this.$input.bind("geocode", $.proxy(function(){
203
+ this.find();
204
+ }, this));
205
+
206
+ // Trigger find action when input element is blurred out and user has
207
+ // not explicitly selected a result.
208
+ // (Useful for typing partial location and tabbing to the next field
209
+ // or clicking somewhere else.)
210
+ if (this.options.blur === true){
211
+ this.$input.blur($.proxy(function(){
212
+ if (this.options.geocodeAfterResult === true && this.selected === true){ return; }
213
+ this.find();
214
+ }, this));
215
+ }
216
+ },
217
+
218
+ // Prepare a given DOM structure to be populated when we got some data.
219
+ // This will cycle through the list of component types and map the
220
+ // corresponding elements.
221
+ initDetails: function(){
222
+ if (!this.options.details){ return; }
223
+
224
+ var $details = $(this.options.details),
225
+ attribute = this.options.detailsAttribute,
226
+ details = {};
227
+
228
+ function setDetail(value){
229
+ details[value] = $details.find("[" + attribute + "=" + value + "]");
230
+ }
231
+
232
+ $.each(componentTypes, function(index, key){
233
+ setDetail(key);
234
+ setDetail(key + "_short");
235
+ });
236
+
237
+ $.each(placesDetails, function(index, key){
238
+ setDetail(key);
239
+ });
240
+
241
+ this.$details = $details;
242
+ this.details = details;
243
+ },
244
+
245
+ // Set the initial location of the plugin if the `location` options was set.
246
+ // This method will care about converting the value into the right format.
247
+ initLocation: function() {
248
+
249
+ var location = this.options.location, latLng;
250
+
251
+ if (!location) { return; }
252
+
253
+ if (typeof location == 'string') {
254
+ this.find(location);
255
+ return;
256
+ }
257
+
258
+ if (location instanceof Array) {
259
+ latLng = new google.maps.LatLng(location[0], location[1]);
260
+ }
261
+
262
+ if (location instanceof google.maps.LatLng){
263
+ latLng = location;
264
+ }
265
+
266
+ if (latLng){
267
+ if (this.map){ this.map.setCenter(latLng); }
268
+ if (this.marker){ this.marker.setPosition(latLng); }
269
+ }
270
+ },
271
+
272
+ // Look up a given address. If no `address` was specified it uses
273
+ // the current value of the input.
274
+ find: function(address){
275
+ this.geocode({
276
+ address: address || this.$input.val()
277
+ });
278
+ },
279
+
280
+ // Requests details about a given location.
281
+ // Additionally it will bias the requests to the provided bounds.
282
+ geocode: function(request){
283
+ if (this.options.bounds && !request.bounds){
284
+ if (this.options.bounds === true){
285
+ request.bounds = this.map && this.map.getBounds();
286
+ } else {
287
+ request.bounds = this.options.bounds;
288
+ }
289
+ }
290
+
291
+ if (this.options.country){
292
+ request.region = this.options.country;
293
+ }
294
+
295
+ this.geocoder.geocode(request, $.proxy(this.handleGeocode, this));
296
+ },
297
+
298
+ // Get the selected result. If no result is selected on the list, then get
299
+ // the first result from the list.
300
+ selectFirstResult: function() {
301
+ //$(".pac-container").hide();
302
+
303
+ var selected = '';
304
+ // Check if any result is selected.
305
+ if ($(".pac-item-selected")[0]) {
306
+ selected = '-selected';
307
+ }
308
+
309
+ // Get the first suggestion's text.
310
+ var $span1 = $(".pac-container:last .pac-item" + selected + ":first span:nth-child(2)").text();
311
+ var $span2 = $(".pac-container:last .pac-item" + selected + ":first span:nth-child(3)").text();
312
+
313
+ // Adds the additional information, if available.
314
+ var firstResult = $span1;
315
+ if ($span2) {
316
+ firstResult += " - " + $span2;
317
+ }
318
+
319
+ this.$input.val(firstResult);
320
+
321
+ return firstResult;
322
+ },
323
+
324
+ // Handles the geocode response. If more than one results was found
325
+ // it triggers the "geocode:multiple" events. If there was an error
326
+ // the "geocode:error" event is fired.
327
+ handleGeocode: function(results, status){
328
+ if (status === google.maps.GeocoderStatus.OK) {
329
+ var result = results[0];
330
+ this.$input.val(result.formatted_address);
331
+ this.update(result);
332
+
333
+ if (results.length > 1){
334
+ this.trigger("geocode:multiple", results);
335
+ }
336
+
337
+ } else {
338
+ this.trigger("geocode:error", status);
339
+ }
340
+ },
341
+
342
+ // Triggers a given `event` with optional `arguments` on the input.
343
+ trigger: function(event, argument){
344
+ this.$input.trigger(event, [argument]);
345
+ },
346
+
347
+ // Set the map to a new center by passing a `geometry`.
348
+ // If the geometry has a viewport, the map zooms out to fit the bounds.
349
+ // Additionally it updates the marker position.
350
+ center: function(geometry){
351
+ if (geometry.viewport){
352
+ this.map.fitBounds(geometry.viewport);
353
+ if (this.map.getZoom() > this.options.maxZoom){
354
+ this.map.setZoom(this.options.maxZoom);
355
+ }
356
+ } else {
357
+ this.map.setZoom(this.options.maxZoom);
358
+ this.map.setCenter(geometry.location);
359
+ }
360
+
361
+ if (this.marker){
362
+ this.marker.setPosition(geometry.location);
363
+ this.marker.setAnimation(this.options.markerOptions.animation);
364
+ }
365
+ },
366
+
367
+ // Update the elements based on a single places or geocoding response
368
+ // and trigger the "geocode:result" event on the input.
369
+ update: function(result){
370
+
371
+ if (this.map){
372
+ this.center(result.geometry);
373
+ }
374
+
375
+ if (this.$details){
376
+ this.fillDetails(result);
377
+ }
378
+
379
+ this.trigger("geocode:result", result);
380
+ },
381
+
382
+ // Populate the provided elements with new `result` data.
383
+ // This will lookup all elements that has an attribute with the given
384
+ // component type.
385
+ fillDetails: function(result){
386
+
387
+ var data = {},
388
+ geometry = result.geometry,
389
+ viewport = geometry.viewport,
390
+ bounds = geometry.bounds;
391
+
392
+ // Create a simplified version of the address components.
393
+ $.each(result.address_components, function(index, object){
394
+ var name = object.types[0];
395
+
396
+ $.each(object.types, function(index, name){
397
+ data[name] = object.long_name;
398
+ data[name + "_short"] = object.short_name;
399
+ });
400
+ });
401
+
402
+ // Add properties of the places details.
403
+ $.each(placesDetails, function(index, key){
404
+ data[key] = result[key];
405
+ });
406
+
407
+ // Add infos about the address and geometry.
408
+ $.extend(data, {
409
+ formatted_address: result.formatted_address,
410
+ location_type: geometry.location_type || "PLACES",
411
+ viewport: viewport,
412
+ bounds: bounds,
413
+ location: geometry.location,
414
+ lat: geometry.location.lat(),
415
+ lng: geometry.location.lng()
416
+ });
417
+
418
+ // Set the values for all details.
419
+ $.each(this.details, $.proxy(function(key, $detail){
420
+ var value = data[key];
421
+ this.setDetail($detail, value);
422
+ }, this));
423
+
424
+ this.data = data;
425
+ },
426
+
427
+ // Assign a given `value` to a single `$element`.
428
+ // If the element is an input, the value is set, otherwise it updates
429
+ // the text content.
430
+ setDetail: function($element, value){
431
+
432
+ if (value === undefined){
433
+ value = "";
434
+ } else if (typeof value.toUrlValue == "function"){
435
+ value = value.toUrlValue();
436
+ }
437
+
438
+ if ($element.is(":input")){
439
+ $element.val(value);
440
+ } else {
441
+ $element.text(value);
442
+ }
443
+ },
444
+
445
+ // Fire the "geocode:dragged" event and pass the new position.
446
+ markerDragged: function(event){
447
+ this.trigger("geocode:dragged", event.latLng);
448
+ },
449
+
450
+ mapClicked: function(event) {
451
+ this.trigger("geocode:click", event.latLng);
452
+ },
453
+
454
+ mapZoomed: function(event) {
455
+ this.trigger("geocode:zoom", this.map.getZoom());
456
+ },
457
+
458
+ // Restore the old position of the marker to the last now location.
459
+ resetMarker: function(){
460
+ this.marker.setPosition(this.data.location);
461
+ this.setDetail(this.details.lat, this.data.location.lat());
462
+ this.setDetail(this.details.lng, this.data.location.lng());
463
+ },
464
+
465
+ // Update the plugin after the user has selected an autocomplete entry.
466
+ // If the place has no geometry it passes it to the geocoder.
467
+ placeChanged: function(){
468
+ var place = this.autocomplete.getPlace();
469
+ this.selected = true;
470
+
471
+ if (!place.geometry){
472
+ if (this.options.autoselect) {
473
+ // Automatically selects the highlighted item or the first item from the
474
+ // suggestions list.
475
+ var autoSelection = this.selectFirstResult();
476
+ this.find(autoSelection);
477
+ }
478
+ } else {
479
+ // Use the input text if it already gives geometry.
480
+ this.update(place);
481
+ }
482
+ }
483
+ });
484
+
485
+ // A plugin wrapper around the constructor.
486
+ // Pass `options` with all settings that are different from the default.
487
+ // The attribute is used to prevent multiple instantiations of the plugin.
488
+ $.fn.geocomplete = function(options) {
489
+
490
+ var attribute = 'plugin_geocomplete';
491
+
492
+ // If you call `.geocomplete()` with a string as the first parameter
493
+ // it returns the corresponding property or calls the method with the
494
+ // following arguments.
495
+ if (typeof options == "string"){
496
+
497
+ var instance = $(this).data(attribute) || $(this).geocomplete().data(attribute),
498
+ prop = instance[options];
499
+
500
+ if (typeof prop == "function"){
501
+ prop.apply(instance, Array.prototype.slice.call(arguments, 1));
502
+ return $(this);
503
+ } else {
504
+ if (arguments.length == 2){
505
+ prop = arguments[1];
506
+ }
507
+ return prop;
508
+ }
509
+ } else {
510
+ return this.each(function() {
511
+ // Prevent against multiple instantiations.
512
+ var instance = $.data(this, attribute);
513
+ if (!instance) {
514
+ instance = new GeoComplete( this, options );
515
+ $.data(this, attribute, instance);
516
+ }
517
+ });
518
+ }
519
+ };
520
+
521
+ })( jQuery, window, document );
@@ -6,7 +6,7 @@ require 'geocomplete_rails/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "geocomplete_rails"
8
8
  spec.version = GeocompleteRails::VERSION
9
- spec.authors = ["Guy Israeli"]
9
+ spec.authors = ["Guy Israeli", "Justin Reese"]
10
10
  spec.description = %q{Wrapper for geocomplete.js - a jQuery Geocoding and Places Autocomplete Plugin}
11
11
  spec.summary = %q{jQuery Geocoding and Places Autocomplete Plugin}
12
12
  spec.homepage = "https://github.com/guyisra/geocomplete_rails"
@@ -1,3 +1,3 @@
1
1
  module GeocompleteRails
2
- VERSION = "1.6.3"
2
+ VERSION = "1.6.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geocomplete_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.3
4
+ version: 1.6.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guy Israeli
8
+ - Justin Reese
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-09-09 00:00:00.000000000 Z
12
+ date: 2015-01-19 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bundler
@@ -88,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
89
  version: '0'
89
90
  requirements: []
90
91
  rubyforge_project:
91
- rubygems_version: 2.2.2
92
+ rubygems_version: 2.4.5
92
93
  signing_key:
93
94
  specification_version: 4
94
95
  summary: jQuery Geocoding and Places Autocomplete Plugin