gmaps-autocomplete-rails 0.1.4 → 0.2.0

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.document +5 -0
  3. data/.rspec +1 -0
  4. data/CHANGELOG +21 -0
  5. data/Gemfile +0 -2
  6. data/README.md +84 -4
  7. data/Rakefile +40 -0
  8. data/VERSION +1 -0
  9. data/gmaps-autocomplete-rails.gemspec +56 -32
  10. data/lib/gmaps-autocomplete-rails.rb +2 -0
  11. data/lib/gmaps-autocomplete-rails/version.rb +5 -0
  12. data/lib/{gmaps-autocomplete → gmaps-autocomplete-rails}/view_helper.rb +0 -0
  13. data/spec/config/config-gmaps-auto-coffee.js +15 -0
  14. data/spec/config/config-gmaps-auto.coffee +7 -0
  15. data/spec/config/config-gmaps-auto.js +4 -0
  16. data/spec/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  17. data/spec/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  18. data/spec/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  19. data/spec/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  20. data/spec/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  21. data/spec/jquery-ui/images/ui-bg_glass_75_ffffff_1x400.png +0 -0
  22. data/spec/jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  23. data/spec/jquery-ui/images/ui-bg_inset-soft_95_fef1ec_1x100.png +0 -0
  24. data/spec/jquery-ui/images/ui-icons_222222_256x240.png +0 -0
  25. data/spec/jquery-ui/images/ui-icons_2e83ff_256x240.png +0 -0
  26. data/spec/jquery-ui/images/ui-icons_454545_256x240.png +0 -0
  27. data/spec/jquery-ui/images/ui-icons_888888_256x240.png +0 -0
  28. data/spec/jquery-ui/images/ui-icons_cd0a0a_256x240.png +0 -0
  29. data/spec/jquery-ui/images/ui-icons_f6cf3b_256x240.png +0 -0
  30. data/spec/jquery-ui/jquery-ui-1.8.16.custom.css +1320 -0
  31. data/spec/jquery-ui/jquery.ui.1.8.16.ie.css +6 -0
  32. data/spec/main.css +89 -0
  33. data/spec/spec_helper.rb +12 -0
  34. data/spec/test-gmaps-auto-coffee.html +54 -0
  35. data/spec/test-gmaps-auto.html +63 -0
  36. data/vendor/assets/javascripts/gmaps-auto-complete.coffee +306 -0
  37. data/vendor/assets/javascripts/gmaps-auto-complete.js +147 -287
  38. metadata +34 -32
@@ -0,0 +1,6 @@
1
+
2
+ .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-left, .ui-corner-bottom{ border-radius:0px;}
3
+ .ui-state-active,.ui-tabs-selected { border-radius:0px;}
4
+ .ui-tabs-selected { border-radius:0px;}
5
+ .ui-tabs .ui-tabs-nav li{ filter:none;}
6
+ .ui-tabs .ui-tabs-nav li a { border-radius:0px; }
data/spec/main.css ADDED
@@ -0,0 +1,89 @@
1
+ html {
2
+ margin:0;
3
+ padding:0;
4
+ border:0;
5
+ }
6
+
7
+ body, div, span, object, iframe,
8
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
9
+ a, abbr, acronym, address, code,
10
+ del, dfn, em, img, q, dl, dt, dd, ol, ul, li,
11
+ fieldset, form, label, legend,
12
+ table, caption, tbody, tfoot, thead, tr, th, td,
13
+ article, aside, dialog, figure, footer, header,
14
+ hgroup, nav, section {
15
+ margin: 0;
16
+ padding: 0;
17
+ border: 0;
18
+ font-size: 100%;
19
+ font: inherit;
20
+ vertical-align: baseline;
21
+ }
22
+
23
+ body {
24
+ color: #333;
25
+ margin: 50px;
26
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size:13px;
27
+ }
28
+
29
+ #gmaps-canvas {
30
+ height: 400px;
31
+
32
+ border: 1px solid #999;
33
+ -moz-box-shadow: 0px 0px 5px #ccc;
34
+ -webkit-box-shadow: 0px 0px 5px #ccc;
35
+ box-shadow: 0px 0px 5px #ccc;
36
+ }
37
+
38
+ #gmaps-error {
39
+ color: #cc0000;
40
+ }
41
+
42
+ h1 {
43
+ font-weight: bold;
44
+ padding-top: 5px;
45
+ padding-bottom: 5px;
46
+ }
47
+
48
+ p {
49
+ padding-top: 5px;
50
+ padding-bottom: 5px;
51
+ }
52
+
53
+ hr {
54
+ border: none;
55
+ padding: 5px;
56
+ border-bottom: 1px solid #efefef;
57
+ }
58
+
59
+ #container {
60
+ width: 80%;
61
+ margin-left: auto;
62
+ margin-right: auto;
63
+ margin-top: 30px;
64
+ padding: 25px;
65
+ border: 1px solid #999;
66
+ -moz-box-shadow: 0px 0px 15px #ccc;
67
+ -webkit-box-shadow: 0px 0px 15px #ccc;
68
+ box-shadow: 0px 0px 15px #ccc;
69
+ }
70
+
71
+ input {
72
+ width: 500px;
73
+ }
74
+
75
+ #results {
76
+ color: #555;
77
+ padding-top: 10px;
78
+ }
79
+
80
+ #input {
81
+ padding-top: 20px;
82
+ padding-bottom: 20px;
83
+ color: #ccc;
84
+ }
85
+ #input #gmaps-output-latitude, #input #gmaps-output-longitude {
86
+ color: green;
87
+ }
88
+
89
+ .download { float: right; }
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'gmaps-autocomplete-rails'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
@@ -0,0 +1,54 @@
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <meta charset='utf-8'>
4
+ <title>Google Maps and jqueryUI</title>
5
+ <link type="text/css" href="main.css" rel="stylesheet" />
6
+ <link type="text/css" href="jquery-ui/jquery-ui-1.8.16.custom.css" rel="stylesheet" />
7
+
8
+ <!-- google maps -->
9
+ <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
10
+
11
+ <!-- jquery -->
12
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
13
+
14
+ <!-- jquery UI -->
15
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
16
+
17
+ <!-- our javascript -->
18
+ <script type="text/javascript" src="../vendor/assets/javascripts/gmaps-auto-complete.js"></script>
19
+
20
+ <!-- configuration -->
21
+ <script type="text/javascript" src="config/config-gmaps-auto-coffee.js"></script>
22
+ </head>
23
+
24
+ <body>
25
+ <a href="https://github.com/rjshade/gmaps-autocomplete"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
26
+
27
+ <div id='container'>
28
+
29
+ <div id='instructions'>
30
+ <h1>Geocoding with Google Maps and jQuery UI</h1>
31
+ <p>This page shows how you can use the <a href="http://jqueryui.com/demos/autocomplete/">autocomplete widget</a> from <a href="http://jqueryui.com/">jQuery UI</a> in conjunction with the <a href="https://developers.google.com/maps/documentation/javascript/reference">Google Maps geocoding API</a> .
32
+ </p>
33
+ <p>
34
+ Start typing a in the search box to trigger the drop-down autocomplete menu. Reverse lookup is also implemented: click the map (or drag an existing marker) and the search box will be populated with the closest address Google can find.
35
+ </p>
36
+ </div>
37
+
38
+ <hr/>
39
+
40
+ <div id='input'>
41
+ <input id='gmaps-input-address' placeholder='Start typing a place name...' type='text' />
42
+ <br/>
43
+ <br/>
44
+ Latitude: <span id='gmaps-output-latitude'></span>
45
+ <br/>
46
+ Longitude: <span id='gmaps-output-longitude'></span>
47
+ <br/>
48
+
49
+ <div id='gmaps-error'></div>
50
+ </div>
51
+
52
+ <div id='gmaps-canvas'></div>
53
+ </div>
54
+ </body>
@@ -0,0 +1,63 @@
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <meta charset='utf-8'>
4
+ <title>Google Maps and jqueryUI</title>
5
+ <link type="text/css" href="main.css" rel="stylesheet" />
6
+ <link type="text/css" href="jquery-ui/jquery-ui-1.8.16.custom.css" rel="stylesheet" />
7
+
8
+ <!-- google maps -->
9
+ <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
10
+
11
+ <!-- jquery -->
12
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
13
+
14
+ <!-- jquery UI -->
15
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
16
+
17
+ <!-- our javascript -->
18
+ <script type="text/javascript" src="../vendor/assets/javascripts/gmaps-autocomplete.js"></script>
19
+
20
+ <!-- configuration -->
21
+ <script type="text/javascript" src="config/config-gmaps-auto.js"></script>
22
+ </head>
23
+
24
+ <body>
25
+ <a href="https://github.com/rjshade/gmaps-autocomplete"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
26
+
27
+ <div id='container'>
28
+ <div class="download">
29
+ <a href="https://github.com/rjshade/gmaps-autocomplete/zipball/master">
30
+ <img border="0" width="90" src="https://github.com/images/modules/download/zip.png"></a>
31
+ <a href="https://github.com/rjshade/gmaps-autocomplete/tarball/master">
32
+ <img border="0" width="90" src="https://github.com/images/modules/download/tar.png"></a>
33
+ </div>
34
+
35
+ <div id='instructions'>
36
+ <h1>Geocoding with Google Maps and jQuery UI</h1>
37
+ <p>This page shows how you can use the <a href="http://jqueryui.com/demos/autocomplete/">autocomplete widget</a> from <a href="http://jqueryui.com/">jQuery UI</a> in conjunction with the <a href="https://developers.google.com/maps/documentation/javascript/reference">Google Maps geocoding API</a> .
38
+ </p>
39
+ <p>
40
+ Start typing a in the search box to trigger the drop-down autocomplete menu. Reverse lookup is also implemented: click the map (or drag an existing marker) and the search box will be populated with the closest address Google can find.
41
+ </p>
42
+ <p>
43
+ The source code is on GitHub: <a href="https://github.com/rjshade/gmaps-autocomplete">rjshade/gmaps-autocomplete</a>
44
+ </p>
45
+ </div>
46
+
47
+ <hr/>
48
+
49
+ <div id='input'>
50
+ <input id='gmaps-input-address' placeholder='Start typing a place name...' type='text' />
51
+ <br/>
52
+ <br/>
53
+ Latitude: <span id='gmaps-output-latitude'></span>
54
+ <br/>
55
+ Longitude: <span id='gmaps-output-longitude'></span>
56
+ <br/>
57
+
58
+ <div id='gmaps-error'></div>
59
+ </div>
60
+
61
+ <div id='gmaps-canvas'></div>
62
+ </div>
63
+ </body>
@@ -0,0 +1,306 @@
1
+ class GmapsCompleter
2
+ geocoder: null
3
+ map: null
4
+ marker: null
5
+ inputField: null
6
+ errorField: null
7
+ positionOutputter: null
8
+ updateUI: null
9
+ updateMap: null
10
+ region: null
11
+ country: null
12
+ debugOn: false
13
+
14
+ # initialise the google maps objects, and add listeners
15
+ mapElem: null
16
+ zoomLevel: 2
17
+ mapType: null
18
+ pos: [0, 0]
19
+ inputField: '#gmaps-input-address'
20
+ errorField: '#gmaps-error'
21
+
22
+ constructor: (opts) ->
23
+ @init opts
24
+
25
+ init: (opts) ->
26
+ opts = opts || {}
27
+ callOpts = $.extend true, {}, opts
28
+
29
+ @debugOn = opts['debugOn']
30
+
31
+ @debug 'init(opts)', opts
32
+
33
+ completerAssistClass = opts['assist']
34
+
35
+ try
36
+ @assist = new completerAssistClass
37
+
38
+ catch error
39
+ @debug 'assist error', error, opts['assist']
40
+
41
+ @assist ||= new GmapsCompleterDefaultAssist
42
+
43
+ @defaultOptions = opts['defaultOptions'] || @assist.options
44
+ opts = $.extend true, {}, @defaultOptions, opts
45
+
46
+ @positionOutputter = opts['positionOutputter'] || @assist.positionOutputter
47
+ @updateUI = opts['updateUI'] || @assist.updateUI
48
+ @updateMap = opts['updateMap'] || @assist.updateMap
49
+
50
+ @geocodeErrorMsg = opts['geocodeErrorMsg'] || @assist.geocodeErrorMsg
51
+ @geocodeErrorMsg = opts['geocodeErrorMsg'] || @assist.geocodeErrorMsg
52
+ @noAddressFoundMsg = opts['noAddressFoundMsg'] || @assist.noAddressFoundMsg
53
+
54
+ pos = opts['pos']
55
+ lat = pos[0]
56
+ lng = pos[1]
57
+
58
+ mapType = opts['mapType']
59
+ mapElem = null
60
+ @mapElem = $("gmaps-canvas")
61
+
62
+ @mapElem = $(opts['mapElem']).get(0) if opts['mapElem']
63
+ @mapType = google.maps.MapTypeId.ROADMAP
64
+
65
+ zoomLevel = opts['zoomLevel']
66
+ scrollwheel = opts['scrollwheel']
67
+
68
+ @inputField = opts['inputField']
69
+ @errorField = opts['#gmaps-error']
70
+ @debugOn = opts['debugOn']
71
+
72
+ @debug 'called with opts', callOpts
73
+ @debug 'final completerAssist', @completerAssist
74
+ @debug 'defaultOptions', @defaultOptions
75
+ @debug 'options after merge with defaults', opts
76
+
77
+ # center of the universe
78
+ latlng = new google.maps.LatLng(lat, lng)
79
+ @debug 'lat,lng', latlng
80
+
81
+ mapOptions =
82
+ zoom: zoomLevel
83
+ scrollwheel: scrollwheel
84
+ center: latlng
85
+ mapTypeId: mapType
86
+
87
+ @debug 'map options', mapOptions
88
+
89
+ # the geocoder object allows us to do latlng lookup based on address
90
+ @geocoder = new google.maps.Geocoder()
91
+
92
+ self = @
93
+
94
+ if typeof(@mapElem) == 'undefined'
95
+ @showError("Map element " + opts['mapElem'] + " could not be resolved!")
96
+
97
+ @debug 'mapElem', @mapElem
98
+
99
+ return if not @mapElem
100
+
101
+ # create our map object
102
+ @map = new google.maps.Map @mapElem, mapOptions
103
+
104
+ return if not @map
105
+
106
+ # the marker shows us the position of the latest address
107
+ @marker = new google.maps.Marker(
108
+ map: @map
109
+ draggable: true
110
+ )
111
+
112
+ self.addMapListeners @marker, @map
113
+
114
+ debug: (label, obj) ->
115
+ return if not @debugOn
116
+ console.log label, obj
117
+
118
+ addMapListeners: (marker, map) ->
119
+ self = @;
120
+ # event triggered when marker is dragged and dropped
121
+ google.maps.event.addListener marker, 'dragend', ->
122
+ self.geocodeLookup 'latLng', marker.getPosition()
123
+
124
+ # event triggered when map is clicked
125
+ google.maps.event.addListener map, 'click', (event) ->
126
+ marker.setPosition event.latLng
127
+ self.geocodeLookup 'latLng', event.latLng
128
+
129
+
130
+ # Query the Google geocode object
131
+ #
132
+ # type: 'address' for search by address
133
+ # 'latLng' for search by latLng (reverse lookup)
134
+ #
135
+ # value: search query
136
+ #
137
+ # update: should we update the map (center map and position marker)?
138
+ geocodeLookup: ( type, value, update ) ->
139
+ # default value: update = false
140
+ @update ||= false
141
+
142
+ request = {}
143
+ request[type] = value
144
+
145
+ @geocoder.geocode request, @performGeocode
146
+
147
+ performGeocode: (results, status) =>
148
+ @debug 'performGeocode', status
149
+
150
+ $(@errorField).html ''
151
+
152
+ if (status == google.maps.GeocoderStatus.OK) then @geocodeSuccess(results) else @geocodeFailure(type, value)
153
+
154
+ geocodeSuccess: (results) ->
155
+ @debug 'geocodeSuccess', results
156
+
157
+ # Google geocoding has succeeded!
158
+ if results[0]
159
+ # Always update the UI elements with new location data
160
+ @updateUI results[0].formatted_address, results[0].geometry.location
161
+
162
+ # Only update the map (position marker and center map) if requested
163
+ @updateMap(results[0].geometry) if @update
164
+
165
+ else
166
+ # Geocoder status ok but no results!?
167
+ @showError @geocodeErrorMsg()
168
+
169
+ geocodeFailure: (type, value) ->
170
+ @debug 'geocodeFailure', type
171
+
172
+ # Google Geocoding has failed. Two common reasons:
173
+ # * Address not recognised (e.g. search for 'zxxzcxczxcx')
174
+ # * Location doesn't map to address (e.g. click in middle of Atlantic)
175
+ if (type == 'address')
176
+ # User has typed in an address which we can't geocode to a location
177
+ @showError @invalidAddressMsg(value)
178
+ else
179
+ # User has clicked or dragged marker to somewhere that Google can't do a reverse lookup for
180
+ # In this case we display a warning, clear the address box, but fill in LatLng
181
+ @showError @noAddressFoundMsg()
182
+ @updateUI '', value
183
+
184
+ showError: (msg) ->
185
+ $(@errorField).html(msg)
186
+ $(@errorField).show()
187
+
188
+ setTimeout( ->
189
+ $(@errorField).hide()
190
+ , 1000)
191
+
192
+ # initialise the jqueryUI autocomplete element
193
+ autoCompleteInit: (opts) ->
194
+ opts = opts || {}
195
+ @region = opts['region'] || @defaultOptions['region']
196
+ @country = opts['country'] || @defaultOptions['country']
197
+ @debug 'region', @region
198
+
199
+ self = @
200
+
201
+ autocompleteOpts = opts['autocomplete'] || {}
202
+
203
+ defaultAutocompleteOpts =
204
+ # event triggered when drop-down option selected
205
+ select: (event,ui) ->
206
+ self.updateUI ui.item.value, ui.item.geocode.geometry.location
207
+ self.updateMap ui.item.geocode.geometry
208
+ # source is the list of input options shown in the autocomplete dropdown.
209
+ # see documentation: http://jqueryui.com/demos/autocomplete/
210
+ source: (request,response) ->
211
+ # https://developers.google.com/maps/documentation/geocoding/#RegionCodes
212
+ region_postfix = ''
213
+ region = self.region
214
+
215
+ region_postfix = ', ' + region if region
216
+ address = request.term + region_postfix
217
+
218
+ self.debug 'geocode address', address
219
+
220
+ geocodeOpts = { address: address, componentRestrictions: { country: region || '' } }
221
+
222
+ # the geocode method takes an address or LatLng to search for
223
+ # and a callback function which should process the results into
224
+ # a format accepted by jqueryUI autocomplete
225
+ self.geocoder.geocode(geocodeOpts, (results, status) ->
226
+ response(
227
+ $.map(results, (item) ->
228
+ uiAddress = item.formatted_address.replace ", " + self.country, ''
229
+ # var uiAddress = item.formatted_address;
230
+ {
231
+ label: uiAddress # appears in dropdown box
232
+ value: uiAddress # inserted into input element when selected
233
+ geocode: item # all geocode data: used in select callback event
234
+ }
235
+ )
236
+ )
237
+ )
238
+
239
+ autocompleteOpts = $.extend true, defaultAutocompleteOpts, autocompleteOpts
240
+
241
+ $(@inputField).autocomplete(autocompleteOpts)
242
+
243
+ # triggered when user presses a key in the address box
244
+ $(@inputField).bind 'keydown', @keyDownHandler
245
+ # autocomplete_init
246
+
247
+ keyDownHandler: (event) =>
248
+ if (event.keyCode == 13)
249
+ @geocodeLookup 'address', $(@inputField).val(), true
250
+ # ensures dropdown disappears when enter is pressed
251
+ $(@inputField).autocomplete "disable"
252
+ else
253
+ # re-enable if previously disabled above
254
+ $(@inputField).autocomplete "enable"
255
+
256
+
257
+ class GmapsCompleterDefaultAssist
258
+ options:
259
+ mapElem: '#gmaps-canvas'
260
+ zoomLevel: 2
261
+ mapType: google.maps.MapTypeId.ROADMAP
262
+ pos: [0, 0]
263
+ inputField: '#gmaps-input-address'
264
+ errorField: '#gmaps-error'
265
+ debugOn: true
266
+
267
+ # move the marker to a new position, and center the map on it
268
+ updateMap: (geometry) ->
269
+ map = @map
270
+ marker = @marker
271
+
272
+ map.fitBounds(geometry.viewport) if map
273
+ marker.setPosition(geometry.location) if marker
274
+
275
+ # fill in the UI elements with new position data
276
+ updateUI: (address, latLng) ->
277
+ inputField = @inputField
278
+ country = @country
279
+
280
+ $(inputField).autocomplete 'close'
281
+
282
+ @debug 'country', country
283
+
284
+ updateAdr = address.replace ', ' + country, ''
285
+ updateAdr = address
286
+
287
+ @debug 'updateAdr', updateAdr
288
+
289
+ $(inputField).val updateAdr
290
+ @positionOutputter latLng
291
+
292
+ positionOutputter: (latLng) ->
293
+ $('#gmaps-output-latitude').html latLng.lat()
294
+ $('#gmaps-output-longitude').html latLng.lng()
295
+
296
+ geocodeErrorMsg: ->
297
+ "Sorry, something went wrong. Try again!"
298
+
299
+ invalidAddressMsg: (value) ->
300
+ "Sorry! We couldn't find " + value + ". Try a different search term, or click the map."
301
+
302
+ noAddressFoundMsg: ->
303
+ "Woah... that's pretty remote! You're going to have to manually enter a place name."
304
+
305
+ window.GmapsCompleter = GmapsCompleter
306
+ window.GmapsCompleterDefaultAssist = GmapsCompleterDefaultAssist