gmaps-autocomplete-rails 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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