gmaps-autocomplete-rails 0.1.0 → 0.1.1

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.
data/README.md CHANGED
@@ -23,37 +23,108 @@ Packed and ready for the Asset pipeline :)
23
23
 
24
24
  ```javascript
25
25
  $(document).ready(function() {
26
- GmapsAutoComplete.gmaps_init();
27
- GmapsAutoComplete.autocomplete_init();
26
+ GmapsAutoComplete.init();
27
+ GmapsAutoComplete.autoCompleteInit();
28
28
  });
29
29
  ```
30
30
 
31
31
  ## Configuration options
32
32
 
33
- `gmaps_init()` take an option hash, using the following defaults:
33
+ `init()` take an option hash, using the following defaults:
34
34
 
35
35
  ```javascript
36
- defaultOptions = {
37
- mapElem: "#gmaps-canvas",
38
- zoomLevel: 2,
39
- mapType: google.maps.MapTypeId.ROADMAP,
40
- pos: [51.751724, -1.255284],
41
- inputField: '#gmaps-input-address',
42
- errorField: '#gmaps-error',
43
- positionOutputter: this.defaultPositionOutputter
44
- };
36
+ defaultOptions = {
37
+ mapElem: "#gmaps-canvas",
38
+ zoomLevel: 2,
39
+ mapType: google.maps.MapTypeId.ROADMAP,
40
+ pos: [51.751724, -1.255284],
41
+ inputField: '#gmaps-input-address',
42
+ errorField: '#gmaps-error',
43
+ positionOutputter: this.defaultPositionOutputter,
44
+ updateUI : this.defaultUpdateUI,
45
+ updateMap : this.defaultUpdateMap
46
+ };
45
47
  ```
46
48
 
47
- `autocomplete_init` also takes an option hash, but currently only [region](https://developers.google.com/maps/documentation/geocoding/#RegionCodes) is used.
49
+ `autoCompleteInit` also takes an option hash, but currently only [region](https://developers.google.com/maps/documentation/geocoding/#RegionCodes) is used.
48
50
 
49
51
  ```javascript
50
- autocomplete_init({region: 'ES'});
52
+ autoCompleteInit({region: 'USA'});
53
+ ```
54
+
55
+ # Examples
56
+
57
+ See `spec/index.html` for an example page using this "plugin". Note that if you set `mapElem`to null or leave out that element on the page, the autocomplete will function without attempting to update the map :)
58
+
59
+ ## Customization
60
+
61
+ Some of the prime candidate functions for customization are:
62
+
63
+ * updateUi
64
+ * updateMap
65
+
66
+ Here the default simple `updateUI` implementation:
67
+
68
+ ```javascript
69
+ updateUi: function( address, latLng ) {
70
+ $(this.inputField).autocomplete("close");
71
+ $(this.inputField).val(address);
72
+
73
+ this.positionOutputter(latLng);
74
+ }
75
+ ```
76
+
77
+ Let's enrich the autocomplete fields with a jobs count for "the area" for each address.
78
+
79
+ ```javascript
80
+ updateUi: function( address, latLng ) {
81
+ $(this.inputField).autocomplete("close");
82
+
83
+ var jobsCount = $.ajax(url: 'jobs/search?address=' + address + '&type=count');
84
+
85
+ $(this.inputField).val(address + ' (' + jobsCount + ' jobs)');
86
+ }
87
+ ```
88
+
89
+ ## Customize messages
90
+
91
+ For now, directly define your own implementation (override) the following functions directly on GmapsAutoComplete
92
+
93
+ * geocodeErrorMsg: function()
94
+ * invalidAddressMsg: function(value)
95
+ * noAddressFoundMsg: function()
96
+
97
+ Example:
98
+
99
+ ```javascript
100
+
101
+ GmapsAutoComplete.geocodeErrorMsg = function() {
102
+ "Geocode error!"
103
+ }
104
+ ```
105
+
106
+ ## Formtastic example
107
+
108
+ For [formtastic](https://github.com/justinfrench/formtastic) something like:
109
+
110
+ ```ruby
111
+ = semantic_form_for @search do |f|
112
+ = f.input :address, placeholder: 'find address'
113
+ %span#address_error
114
+
115
+ ```javascript
116
+ $(document).ready(function() {
117
+ GmapsAutoComplete.init({inputField: 'form#search #address', errorField: 'form#search #address_error'});
118
+ GmapsAutoComplete.autoCompleteInit({region: 'DK'});
119
+ });
51
120
  ```
52
121
 
53
122
  ## TODO
54
123
 
55
124
  * better Javascript encapsulation
56
- * translation to Coffeescript and use Coffee classes :)
125
+ * translation to Coffeescript using Coffee classes :)
126
+
127
+ Please help out with suggestions and improvements etc!
57
128
 
58
129
  ## Contributing to gmaps-autocomplete-rails
59
130
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -0,0 +1,86 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "gmaps-autocomplete-rails"
8
+ s.version = "0.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Kristian Mandrup"]
12
+ s.date = "2012-09-07"
13
+ s.description = "Easily add autocomplete geo-functionality to your Rails app :)"
14
+ s.email = "kmandrup@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.md",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "gmaps-autocomplete-rails.gemspec",
29
+ "lib/gmaps-autocomplete-rails.rb",
30
+ "lib/gmaps-autocomplete/view_helper.rb",
31
+ "spec/index.html",
32
+ "spec/init.js",
33
+ "spec/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png",
34
+ "spec/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png",
35
+ "spec/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png",
36
+ "spec/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png",
37
+ "spec/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png",
38
+ "spec/jquery-ui/images/ui-bg_glass_75_ffffff_1x400.png",
39
+ "spec/jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png",
40
+ "spec/jquery-ui/images/ui-bg_inset-soft_95_fef1ec_1x100.png",
41
+ "spec/jquery-ui/images/ui-icons_222222_256x240.png",
42
+ "spec/jquery-ui/images/ui-icons_2e83ff_256x240.png",
43
+ "spec/jquery-ui/images/ui-icons_454545_256x240.png",
44
+ "spec/jquery-ui/images/ui-icons_888888_256x240.png",
45
+ "spec/jquery-ui/images/ui-icons_cd0a0a_256x240.png",
46
+ "spec/jquery-ui/images/ui-icons_f6cf3b_256x240.png",
47
+ "spec/jquery-ui/jquery-ui-1.8.16.custom.css",
48
+ "spec/jquery-ui/jquery.ui.1.8.16.ie.css",
49
+ "spec/main.css",
50
+ "spec/spec_helper.rb",
51
+ "vendor/assets/javascripts/gmaps-autocomplete.js"
52
+ ]
53
+ s.homepage = "http://github.com/kristianmandrup/gmaps-autocomplete-rails"
54
+ s.licenses = ["MIT"]
55
+ s.require_paths = ["lib"]
56
+ s.rubygems_version = "1.8.24"
57
+ s.summary = "Google Maps v3 search with jQuery UI Autocomplete, ready for use with Rails asset pipeline"
58
+
59
+ if s.respond_to? :specification_version then
60
+ s.specification_version = 3
61
+
62
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
63
+ s.add_runtime_dependency(%q<rails>, [">= 3.0.0"])
64
+ s.add_development_dependency(%q<rspec>, [">= 2.8.0"])
65
+ s.add_development_dependency(%q<rdoc>, [">= 3.12"])
66
+ s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
67
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
68
+ s.add_development_dependency(%q<simplecov>, [">= 0.5"])
69
+ else
70
+ s.add_dependency(%q<rails>, [">= 3.0.0"])
71
+ s.add_dependency(%q<rspec>, [">= 2.8.0"])
72
+ s.add_dependency(%q<rdoc>, [">= 3.12"])
73
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
74
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
75
+ s.add_dependency(%q<simplecov>, [">= 0.5"])
76
+ end
77
+ else
78
+ s.add_dependency(%q<rails>, [">= 3.0.0"])
79
+ s.add_dependency(%q<rspec>, [">= 2.8.0"])
80
+ s.add_dependency(%q<rdoc>, [">= 3.12"])
81
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
82
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
83
+ s.add_dependency(%q<simplecov>, [">= 0.5"])
84
+ end
85
+ end
86
+
@@ -1,4 +1,4 @@
1
1
  $(document).ready(function() {
2
- GmapsAutoComplete.gmaps_init();
3
- GmapsAutoComplete.autocomplete_init();
2
+ GmapsAutoComplete.init();
3
+ GmapsAutoComplete.autoCompleteInit();
4
4
  });
@@ -5,6 +5,9 @@ var GmapsAutoComplete = {
5
5
  inputField: null,
6
6
  errorField: null,
7
7
  positionOutputter: null,
8
+ updateUI: null,
9
+ updateMap: null,
10
+ region: null,
8
11
 
9
12
  // initialise the google maps objects, and add listeners
10
13
  mapElem: document.getElementById("gmaps-canvas"),
@@ -15,7 +18,7 @@ var GmapsAutoComplete = {
15
18
  errorField: '#gmaps-error',
16
19
  positionOutputter: this.defaultPositionOutputter,
17
20
 
18
- gmaps_init: function(opts){
21
+ init: function(opts){
19
22
  opts = opts || {};
20
23
 
21
24
  defaultOptions = {
@@ -25,7 +28,9 @@ var GmapsAutoComplete = {
25
28
  pos: [51.751724, -1.255284],
26
29
  inputField: '#gmaps-input-address',
27
30
  errorField: '#gmaps-error',
28
- positionOutputter: this.defaultPositionOutputter
31
+ positionOutputter: this.defaultPositionOutputter,
32
+ updateUI : this.defaultUpdateUI,
33
+ updateMap : this.defaultUpdateMap
29
34
  };
30
35
 
31
36
  $.extend(opts, defaultOptions);
@@ -47,6 +52,8 @@ var GmapsAutoComplete = {
47
52
  this.errorField = opts['#gmaps-error'];
48
53
 
49
54
  this.positionOutputter = opts['positionOutputter'];
55
+ this.updateUI = opts['updateUI'];
56
+ this.updateMap = opts['updateMap'];
50
57
 
51
58
  // center of the universe
52
59
  var latlng = new google.maps.LatLng(lat, lng);
@@ -66,46 +73,52 @@ var GmapsAutoComplete = {
66
73
  self.showError("Map element " + opts['mapElem'] + " could not be resolved!");
67
74
  }
68
75
 
69
- if (mapElem) {
70
- // create our map object
71
- this.map = new google.maps.Map(mapElem, options);
72
-
73
- if (this.map) {
74
- // the marker shows us the position of the latest address
75
- this.marker = new google.maps.Marker({
76
- map: this.map,
77
- draggable: true
78
- });
79
-
80
- marker = this.marker;
81
-
82
- // event triggered when marker is dragged and dropped
83
- google.maps.event.addListener(this.marker, 'dragend', function() {
84
- self.geocode_lookup( 'latLng', marker.getPosition() );
85
- });
86
-
87
- // event triggered when map is clicked
88
- google.maps.event.addListener(this.map, 'click', function(event) {
89
- marker.setPosition(event.latLng)
90
- self.geocode_lookup( 'latLng', event.latLng );
91
- });
92
- }
93
- }
76
+ if (!mapElem) { return }
77
+
78
+ // create our map object
79
+ this.map = new google.maps.Map(mapElem, options);
80
+
81
+ if (!this.map) { return }
82
+
83
+ // the marker shows us the position of the latest address
84
+ this.marker = new google.maps.Marker({
85
+ map: this.map,
86
+ draggable: true
87
+ });
88
+
89
+ self.addMapListeners(this.marker, this.map);
90
+ },
91
+
92
+ addMapListeners: function(marker, map) {
93
+ self = this;
94
+ // event triggered when marker is dragged and dropped
95
+ google.maps.event.addListener(marker, 'dragend', function() {
96
+ self.geocodeLookup( 'latLng', marker.getPosition() );
97
+ });
98
+
99
+ // event triggered when map is clicked
100
+ google.maps.event.addListener(map, 'click', function(event) {
101
+ marker.setPosition(event.latLng)
102
+ self.geocodeLookup( 'latLng', event.latLng );
103
+ });
94
104
  },
95
105
 
96
106
  // move the marker to a new position, and center the map on it
97
- update_map: function( geometry ) {
98
- if (this.map) {
99
- this.map.fitBounds( geometry.viewport )
107
+ defaultUpdateMap: function( geometry ) {
108
+ var map = this.map;
109
+ var marker = this.marker;
110
+
111
+ if (map) {
112
+ map.fitBounds( geometry.viewport )
100
113
  }
101
114
 
102
- if (this.marker) {
103
- this.marker.setPosition( geometry.location )
115
+ if (marker) {
116
+ marker.setPosition( geometry.location )
104
117
  }
105
118
  },
106
119
 
107
120
  // fill in the UI elements with new position data
108
- update_ui: function( address, latLng ) {
121
+ defaultUpdateUI: function( address, latLng ) {
109
122
  $(this.inputField).autocomplete("close");
110
123
  $(this.inputField).val(address);
111
124
 
@@ -125,7 +138,7 @@ var GmapsAutoComplete = {
125
138
  // value: search query
126
139
  //
127
140
  // update: should we update the map (center map and position marker)?
128
- geocode_lookup: function( type, value, update ) {
141
+ geocodeLookup: function( type, value, update ) {
129
142
  // default value: update = false
130
143
  update = typeof update !== 'undefined' ? update : false;
131
144
 
@@ -133,101 +146,127 @@ var GmapsAutoComplete = {
133
146
  request[type] = value;
134
147
  var self = this;
135
148
 
136
- geocoder.geocode({address: request.term, region: 'DK'}, function(results, status) {
137
- $(self.errorField).html('');
138
- if (status == google.maps.GeocoderStatus.OK) {
139
- // Google geocoding has succeeded!
140
- if (results[0]) {
141
- // Always update the UI elements with new location data
142
- self.update_ui( results[0].formatted_address,
143
- results[0].geometry.location )
144
-
145
- // Only update the map (position marker and center map) if requested
146
- if( update ) { update_map( results[0].geometry ) }
147
- } else {
148
- // Geocoder status ok but no results!?
149
- self.showError("Sorry, something went wrong. Try again!");
150
- }
151
- } else {
152
- // Google Geocoding has failed. Two common reasons:
153
- // * Address not recognised (e.g. search for 'zxxzcxczxcx')
154
- // * Location doesn't map to address (e.g. click in middle of Atlantic)
155
-
156
- if( type == 'address' ) {
157
- // User has typed in an address which we can't geocode to a location
158
- self.showError("Sorry! We couldn't find " + value + ". Try a different search term, or click the map." );
159
- } else {
160
- // User has clicked or dragged marker to somewhere that Google can't do a reverse lookup for
161
- // In this case we display a warning, clear the address box, but fill in LatLng
162
- self.showError("Woah... that's pretty remote! You're going to have to manually enter a place name." );
163
- self.update_ui('', value)
164
- }
165
- };
166
- });
149
+ geocoder.geocode(request, performGeocode);
150
+ },
151
+
152
+ performGeocode: function(results, status) {
153
+ $(self.errorField).html('');
154
+ if (status == google.maps.GeocoderStatus.OK) {
155
+ self.geocodeSuccess(results);
156
+ } else {
157
+ self.geocodeFailure(type, value);
158
+ };
159
+ },
160
+
161
+ geocodeSuccess: function(results) {
162
+ // Google geocoding has succeeded!
163
+ if (results[0]) {
164
+ // Always update the UI elements with new location data
165
+ this.updateUI( results[0].formatted_address,
166
+ results[0].geometry.location )
167
+
168
+ // Only update the map (position marker and center map) if requested
169
+ if( update ) { this.updateMap( results[0].geometry ) }
170
+ } else {
171
+ // Geocoder status ok but no results!?
172
+ this.showError( this.geocodeErrorMsg() );
173
+ }
174
+ },
175
+
176
+ geocodeFailure: function(type, value) {
177
+ // Google Geocoding has failed. Two common reasons:
178
+ // * Address not recognised (e.g. search for 'zxxzcxczxcx')
179
+ // * Location doesn't map to address (e.g. click in middle of Atlantic)
180
+ if( type == 'address' ) {
181
+ // User has typed in an address which we can't geocode to a location
182
+ this.showError( this.invalidAddressMsg(value) );
183
+ } else {
184
+ // User has clicked or dragged marker to somewhere that Google can't do a reverse lookup for
185
+ // In this case we display a warning, clear the address box, but fill in LatLng
186
+ this.showError( this.noAddressFoundMsg() );
187
+ this.updateUI('', value)
188
+ }
189
+ },
190
+
191
+ geocodeErrorMsg: function() {
192
+ "Sorry, something went wrong. Try again!"
193
+ },
194
+
195
+ invalidAddressMsg: function(value) {
196
+ "Sorry! We couldn't find " + value + ". Try a different search term, or click the map."
197
+ },
198
+
199
+ noAddressFoundMsg: function() {
200
+ "Woah... that's pretty remote! You're going to have to manually enter a place name."
167
201
  },
168
202
 
169
203
  showError: function(msg) {
170
- $(self.errorField).html(msg);
171
- $(self.errorField).show();
204
+ $(this.errorField).html(msg);
205
+ $(this.errorField).show();
172
206
 
173
207
  setTimeout(function(){
174
- $(self.errorField).hide();
208
+ $(this.errorField).hide();
175
209
  }, 1000);
176
210
  },
177
211
 
178
212
  // initialise the jqueryUI autocomplete element
179
- autocomplete_init: function (opts) {
180
- var self = this;
213
+ autoCompleteInit: function (opts) {
181
214
  opts = opts || {};
182
- var region = opts['region'] || 'DK';
183
-
184
- $(self.inputField).autocomplete({
215
+ this.region = opts['region'] || 'DK';
185
216
 
217
+ $(this.inputField).autocomplete({
186
218
  // source is the list of input options shown in the autocomplete dropdown.
187
219
  // see documentation: http://jqueryui.com/demos/autocomplete/
188
- source: function(request,response) {
189
-
190
- // https://developers.google.com/maps/documentation/geocoding/#RegionCodes
191
- console.log('region', region);
192
- var region_postfix = ''
193
- if (region) {
194
- region_postfix = ', ' + region
195
- }
196
-
197
- geocode_opts = {'address': request.term + region_postfix }
198
-
199
- // the geocode method takes an address or LatLng to search for
200
- // and a callback function which should process the results into
201
- // a format accepted by jqueryUI autocomplete
202
- geocoder.geocode(geocode_opts, function(results, status) {
203
- response($.map(results, function(item) {
204
- return {
205
- label: item.formatted_address, // appears in dropdown box
206
- value: item.formatted_address, // inserted into input element when selected
207
- geocode: item // all geocode data: used in select callback event
208
- }
209
- }));
210
- })
211
- },
212
-
220
+ source: this.autoCompleteSource,
213
221
  // event triggered when drop-down option selected
214
- select: function(event,ui){
215
- self.update_ui( ui.item.value, ui.item.geocode.geometry.location )
216
- self.update_map( ui.item.geocode.geometry )
217
- }
222
+ select: this.autoCompleteSelect
218
223
  });
219
224
 
220
225
  // triggered when user presses a key in the address box
221
- $(self.inputField).bind('keydown', function(event) {
222
- if(event.keyCode == 13) {
223
- geocode_lookup( 'address', $(self.inputField).val(), true );
224
-
225
- // ensures dropdown disappears when enter is pressed
226
- $(self.inputField).autocomplete("disable")
227
- } else {
228
- // re-enable if previously disabled above
229
- $(self.inputField).autocomplete("enable")
230
- }
231
- });
232
- } // autocomplete_init
226
+ $(self.inputField).bind('keydown', this.keyDownHandler);
227
+ }, // autocomplete_init
228
+
229
+ keyDownHandler: function(event) {
230
+ if(event.keyCode == 13) {
231
+ this.geocodeLookup( 'address', $(self.inputField).val(), true );
232
+
233
+ // ensures dropdown disappears when enter is pressed
234
+ $(this.inputField).autocomplete("disable")
235
+ } else {
236
+ // re-enable if previously disabled above
237
+ $(this.inputField).autocomplete("enable")
238
+ }
239
+ },
240
+
241
+ // self grants access to caller scope
242
+ autoCompleteSelect: function(event,ui){
243
+ self.updateUI( ui.item.value, ui.item.geocode.geometry.location )
244
+ self.updateMap( ui.item.geocode.geometry )
245
+ },
246
+
247
+ // self grants access to caller scope
248
+ autoCompleteSource: function(request,response) {
249
+ // https://developers.google.com/maps/documentation/geocoding/#RegionCodes
250
+ var region_postfix = ''
251
+ var region = self.region;
252
+
253
+ if (region) {
254
+ region_postfix = ', ' + region
255
+ }
256
+
257
+ geocode_opts = {'address': request.term + region_postfix }
258
+
259
+ // the geocode method takes an address or LatLng to search for
260
+ // and a callback function which should process the results into
261
+ // a format accepted by jqueryUI autocomplete
262
+ geocoder.geocode(geocode_opts, function(results, status) {
263
+ response($.map(results, function(item) {
264
+ return {
265
+ label: item.formatted_address, // appears in dropdown box
266
+ value: item.formatted_address, // inserted into input element when selected
267
+ geocode: item // all geocode data: used in select callback event
268
+ }
269
+ }));
270
+ })
271
+ }
233
272
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gmaps-autocomplete-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-06 00:00:00.000000000 Z
12
+ date: 2012-09-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -123,6 +123,7 @@ files:
123
123
  - README.md
124
124
  - Rakefile
125
125
  - VERSION
126
+ - gmaps-autocomplete-rails.gemspec
126
127
  - lib/gmaps-autocomplete-rails.rb
127
128
  - lib/gmaps-autocomplete/view_helper.rb
128
129
  - spec/index.html
@@ -161,7 +162,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
161
162
  version: '0'
162
163
  segments:
163
164
  - 0
164
- hash: 2031419109795997149
165
+ hash: -4192616330667044491
165
166
  required_rubygems_version: !ruby/object:Gem::Requirement
166
167
  none: false
167
168
  requirements: