wf-rails3-jquery-autocomplete 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ * 1.0.3 Fixed Formtastic 2.0 + Ruby 1.8.7 compat issue
4
+ * 1.0.2 Fixed issue #93, #94
5
+ * 1.0.1 Formtastic 2.0 compatibility fix
6
+ * 1.0.0 Rails 3.1 asset pipeline support
7
+ * 0.9.1 Fixes issues #96 and #32
8
+ * 0.9.0 Massive rewrite
9
+ * 0.8.0 Compressed JS file
10
+ * 0.7.5 Pull request #46
11
+ * 0.7.4 Allows Rails 3.1
12
+ * 0.7.3 MongoMapper
13
+ * 0.7.2 Steak helper
14
+ * 0.7.1 Fixed joined scopes (Issue #43)
15
+ * 0.7.0 Scopes
16
+ * 0.6.6 ILIKE for postgres
17
+ * 0.6.5 JS select event
18
+ * 0.6.4 Use YAJL instead of JSON
19
+ * 0.6.3 SimpleForm plugin
20
+ * 0.6.2 Fix Issue #8
21
+ * 0.6.1 Allow specifying fully qualified class name for model object as an option to autocomplete
22
+ * 0.6.0 JS Code cleanup
23
+ * 0.5.1 Add STI support
24
+ * 0.5.0 Formtastic support
25
+ * 0.4.0 MongoID support
26
+ * 0.3.6 Using .live() to put autocomplete on dynamic fields
27
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 David Padilla
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,345 @@
1
+ # rails3-jquery-autocomplete
2
+
3
+ An easy way to use jQuery's autocomplete with Rails 3.
4
+
5
+ Supports both ActiveRecord, [mongoid](http://github.com/mongoid/mongoid), and [MongoMapper](https://github.com/jnunemaker/mongomapper).
6
+
7
+ Works with [Formtastic](http://github.com/justinfrench/formtastic)
8
+ and [SimpleForm](https://github.com/plataformatec/simple_form)
9
+
10
+ ## ActiveRecord
11
+
12
+ You can find a [detailed example](http://github.com/crowdint/rails3-jquery-autocomplete-app)
13
+ on how to use this gem with ActiveRecord [here](http://github.com/crowdint/rails3-jquery-autocomplete-app).
14
+
15
+ ## MongoID
16
+
17
+ You can find a [detailed example](http://github.com/crowdint/rails3-jquery-autocomplete-app/tree/mongoid)
18
+ on how to use this gem with MongoID [here](http://github.com/crowdint/rails3-jquery-autocomplete-app/tree/mongoid). (Same thing, different branch)
19
+
20
+ ## Before you start
21
+
22
+ Make sure your project is using jQuery-UI and the autocomplete widget
23
+ before you continue.
24
+
25
+ You can find more info about that here:
26
+
27
+ * http://jquery.com/
28
+ * http://jqueryui.com/demos/autocomplete/
29
+ * http://github.com/rails/jquery-ujs
30
+
31
+ I'd encourage you to understand how to use those 3 amazing tools before attempting to use this gem.
32
+
33
+ ## Installing
34
+
35
+ Include the gem on your Gemfile
36
+
37
+ gem 'rails3-jquery-autocomplete'
38
+
39
+ Install it
40
+
41
+ bundle install
42
+
43
+ ### Rails 3.0.x
44
+
45
+ Run the generator
46
+
47
+ rails generate autocomplete:install
48
+
49
+ And include autocomplete-rails.js on your layouts
50
+
51
+ javascript_include_tag "autocomplete-rails.js"
52
+
53
+ ### Rails 3.1.x
54
+
55
+ Just add it to your app/assets/javascripts/application.js file
56
+
57
+ //= require jquery
58
+ //= require jquery_ujs
59
+ //= require autocomplete-rails
60
+
61
+ ## Upgrading from older versions
62
+
63
+ If you are upgrading from a previous version, run the generator after installing to replace the javascript file.
64
+
65
+ rails generate autocomplete:install
66
+
67
+ I'd recommend you do this every time you update to make sure you have the latest JS file.
68
+
69
+ ## Uncompressed Javascript file
70
+
71
+ If you want to make changes to the JS file, you can install the
72
+ uncompressed version by running:
73
+
74
+ rails generate autocomplete:uncompressed
75
+
76
+ ## Usage
77
+
78
+ ### Model Example
79
+
80
+ Assuming you have a Brand model:
81
+
82
+ class Brand < ActiveRecord::Base
83
+ end
84
+
85
+ create_table :brand do |t|
86
+ t.column :name, :string
87
+ end
88
+
89
+ ### Controller
90
+
91
+ To set up the required action on your controller, all you have to do is call it with the class name and the method
92
+ as in the following example:
93
+
94
+ class ProductsController < Admin::BaseController
95
+ autocomplete :brand, :name
96
+ end
97
+
98
+ This will create an action _autocomplete_brand_name_ on your controller, don't forget to add it on your routes file
99
+
100
+ resources :products do
101
+ get :autocomplete_brand_name, :on => :collection
102
+ end
103
+
104
+ ### Options
105
+
106
+ #### :full => true
107
+
108
+ By default, the search starts from the beginning of the string you're searching for. If you want to do a full search, set the _full_ parameter to true.
109
+
110
+ class ProductsController < Admin::BaseController
111
+ autocomplete :brand, :name, :full => true
112
+ end
113
+
114
+ The following terms would match the query 'un':
115
+
116
+ * Luna
117
+ * Unacceptable
118
+ * Rerun
119
+
120
+ #### :full => false (default behavior)
121
+
122
+ Only the following terms mould match the query 'un':
123
+
124
+ * Unacceptable
125
+
126
+ #### :extra_data
127
+
128
+ By default, your search will only return the required columns from the database needed to populate your form, namely id and the column you are searching (name, in the above example).
129
+
130
+ Passing an array of attributes/column names to this option will fetch and return the specified data.
131
+
132
+ class ProductsController < Admin::BaseController
133
+ autocomplete :brand, :name, :extra_data => [:slogan]
134
+ end
135
+
136
+ #### :display_value
137
+
138
+ If you want to display a different version of what you're looking for, you can use the :display_value option.
139
+
140
+ This options receives a method name as the parameter, and that method will be called on the instance when displaying the results.
141
+
142
+ class Brand < ActiveRecord::Base
143
+ def funky_method
144
+ "#{self.name}.camelize"
145
+ end
146
+ end
147
+
148
+
149
+ class ProductsController < Admin::BaseController
150
+ autocomplete :brand, :name, :display_value => :funky_method
151
+ end
152
+
153
+ In the example above, you will search by _name_, but the autocomplete list will display the result of _funky_method_
154
+
155
+ This wouldn't really make much sense unless you use it with the "id_element" attribute. (See below)
156
+
157
+ Only the object's id and the column you are searching on will be returned in JSON, so if your display_value method requires another parameter, make sure to fetch it with the :extra_data option
158
+
159
+
160
+ #### :scopes
161
+ Added option to use scopes. Pass scopes in an array.
162
+ e.g `:scopes => [:scope1, :scope2]`
163
+
164
+ #### :column_name
165
+ By default autocomplete uses method name as column name. Now it can be specified using column_name options
166
+ `:column_name => 'name'`
167
+
168
+ #### json encoder
169
+ Autocomplete uses Yajl as JSON encoder/decoder, but you can specify your own
170
+
171
+ class ProductsController < Admin::BaseController
172
+ autocomplete :brand, :name do |items|
173
+ CustomJSON::Encoder.encode(items)
174
+ end
175
+ end
176
+
177
+ ### View
178
+
179
+ On your view, all you have to do is include the attribute autocomplete on the text field
180
+ using the url to the autocomplete action as the value.
181
+
182
+ form_for @product do |f|
183
+ f.autocomplete_field :brand_name, autocomplete_brand_name_products_path
184
+ end
185
+
186
+ This will generate an HTML tag that looks like:
187
+
188
+ <input type="text" data-autocomplete="products/autocomplete_brand_name">
189
+
190
+ If you are not using a FormBuilder (form_for) or you just want to include an autocomplete field without the form, you can use the
191
+ *autocomplete_field_tag* helper.
192
+
193
+ form_tag 'some/path'
194
+ autocomplete_field_tag 'address', '', address_autocomplete_path, :size => 75
195
+ end
196
+
197
+ Now your autocomplete code is unobtrusive, Rails 3 style.
198
+
199
+ ### Getting the object id
200
+
201
+ If you need to use the id of the selected object, you can use the *id_element* attribute too:
202
+
203
+ f.autocomplete_field :brand_name, autocomplete_brand_name_products_path, :id_element => '#some_element'
204
+
205
+ This will update the field with id *#some_element with the id of the selected object. The value for this option can be any jQuery selector.
206
+
207
+ ### Getting extra object data
208
+
209
+ If you need to extra data about the selected object, you can use the *:update_elements* HTML attribute.
210
+
211
+ The :update_elements attribute accepts a hash where the keys represent the object attribute/column data to use to update and the values are jQuery selectors to retrieve the HTML element to update:
212
+
213
+ f.autocomplete_field :brand_name, autocomplete_brand_name_products_path, :update_elements => {:id => '#id_element', :slogan => '#some_other_element'}
214
+
215
+ class ProductsController < Admin::BaseController
216
+ autocomplete :brand, :name, :extra_data => [:slogan]
217
+ end
218
+
219
+ The previous example would fetch the extra attribute slogan and update jQuery('#some_other_element') with the slogan value.
220
+
221
+ ### Running custom code on selection
222
+
223
+ A javascript event named *railsAutocomplete.select* is fired on the input field when a value is selected from the autocomplete drop down. If you need to do something more complex than update fields with data, you can hook into this event, like so:
224
+
225
+ $('#my_autocomplete_field').bind('railsAutocomplete.select', function(event, data){
226
+ /* Do something here */
227
+ alert(data.item.id);
228
+ });
229
+
230
+ ## Formtastic
231
+
232
+ If you are using [Formtastic](http://github.com/justinfrench/formtastic), you automatically get the *autocompleted_input* helper on *semantic_form_for*:
233
+
234
+ semantic_form_for @product do |f|
235
+ f.input :brand_name, :as => :autocomplete, :url => autocomplete_brand_name_products_path
236
+ end
237
+
238
+ The only difference with the original helper is that you must specify the autocomplete url using the *:url* option.
239
+
240
+ ## SimpleForm
241
+
242
+ If you want to use it with simple_form, all you have to do is use the
243
+ :as option on the input and set the autocomplete path with the :url
244
+ option.
245
+
246
+
247
+ simple_form_for @product do |form|
248
+ form.input :name
249
+ form.input :brand_name, :url => autocomplete_brand_name_products_path, :as => :autocomplete
250
+
251
+ # Cucumber
252
+
253
+ I have created a step to test your autocomplete with Cucumber and Capybara, all you have to do is add the following lines to your *env.rb* file:
254
+
255
+ require 'cucumber/autocomplete'
256
+
257
+ Then you'll have access to the following step:
258
+
259
+ I choose "([^"]*)" in the autocomplete list
260
+
261
+ An example on how to use it:
262
+
263
+ @javascript
264
+ Scenario: Autocomplete
265
+ Given the following brands exists:
266
+ | name |
267
+ | Alpha |
268
+ | Beta |
269
+ | Gamma |
270
+ And I go to the home page
271
+ And I fill in "Brand name" with "al"
272
+ And I choose "Alpha" in the autocomplete list
273
+ Then the "Brand name" field should contain "Alpha"
274
+
275
+ I have only tested this using Capybara, no idea if it works with something else, to see it in action, check the [example app](http://github.com/crowdint/rails3-jquery-autocomplete-app).
276
+
277
+ # Steak
278
+
279
+ I have created a helper to test your autocomplete with Steak and Capybara, all you have to do is add the following lines to your *acceptance_helper.rb* file:
280
+
281
+ require 'steak/autocomplete'
282
+
283
+ Then you'll have access to the following helper:
284
+
285
+ choose_autocomplete_result
286
+
287
+ An example on how to use it:
288
+
289
+ scenario "Autocomplete" do
290
+ lambda do
291
+ Brand.create! [
292
+ {:name => "Alpha"},
293
+ {:name => "Beta"},
294
+ {:name => "Gamma"}
295
+ ]
296
+ end.should change(Brand, :count).by(3)
297
+
298
+ visit home_page
299
+ fill_in "Brand name", :with => "al"
300
+ choose_autocomplete_result "Alpha"
301
+ find_field("Brand name").value.should include("Alpha")
302
+ end
303
+
304
+ I have only tested this using Capybara, no idea if it works with something else.
305
+
306
+ # Development
307
+
308
+ If you want to make changes to the gem, first install bundler 1.0.0:
309
+
310
+ gem install bundler
311
+
312
+ And then, install all your dependencies:
313
+
314
+ bundle install
315
+
316
+ ## Running the test suite
317
+
318
+ You need to have an instance of MongoDB running on your computer or all the mongo tests will fail miserably.
319
+
320
+ rake test
321
+
322
+ ## Integration tests
323
+
324
+ If you make changes or add features to the jQuery part, please make sure
325
+ you write a cucumber test for it.
326
+
327
+ You can find an example Rails app on the *integration* folder.
328
+
329
+ You can run the integration tests with the cucumber command while on the
330
+ integration folder:
331
+
332
+ cd integration
333
+ rake db:migrate
334
+ cucumber
335
+
336
+ # Thanks to
337
+
338
+ Everyone on [this list](https://github.com/crowdint/rails3-jquery-autocomplete/contributors)
339
+
340
+ # About the Author
341
+
342
+ [Crowd Interactive](http://www.crowdint.com) is an American web design and development company that happens to work in Colima, Mexico.
343
+ We specialize in building and growing online retail stores. We don’t work with everyone – just companies we believe in. Call us today to see if there’s a fit.
344
+ Find more info [here](http://www.crowdint.com)!
345
+
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+ require 'rcov/rcovtask'
6
+
7
+ task :default => [:uglify, :test]
8
+
9
+ Rake::TestTask.new(:test) do |test|
10
+ test.libs << 'lib' << 'test'
11
+ test.pattern = 'test/**/*_test.rb'
12
+ test.verbose = true
13
+ end
14
+
15
+ task :uglify do
16
+ require 'uglifier'
17
+ file_folder = "lib/assets/javascripts"
18
+ File.open("#{file_folder}/autocomplete-rails.js", "w") do |f|
19
+ f << Uglifier.compile(File.read("#{file_folder}/autocomplete-rails-uncompressed.js"))
20
+ end
21
+ end
22
+
23
+ Rcov::RcovTask.new do |t|
24
+ t.libs << "test"
25
+ t.test_files = FileList['test/**/*_test.rb']
26
+ t.rcov_opts = %w{--exclude \/gems\/}
27
+ t.verbose = true
28
+ end
@@ -0,0 +1,113 @@
1
+ /*
2
+ * Unobtrusive autocomplete
3
+ *
4
+ * To use it, you just have to include the HTML attribute autocomplete
5
+ * with the autocomplete URL as the value
6
+ *
7
+ * Example:
8
+ * <input type="text" data-autocomplete="/url/to/autocomplete">
9
+ *
10
+ * Optionally, you can use a jQuery selector to specify a field that can
11
+ * be updated with the element id whenever you find a matching value
12
+ *
13
+ * Example:
14
+ * <input type="text" data-autocomplete="/url/to/autocomplete" data-id-element="#id_field">
15
+ */
16
+
17
+ $(document).ready(function(){
18
+ $('input[data-autocomplete]').railsAutocomplete();
19
+ });
20
+
21
+ (function(jQuery)
22
+ {
23
+ var self = null;
24
+ jQuery.fn.railsAutocomplete = function() {
25
+ return this.live('focus',function() {
26
+ if (!this.railsAutoCompleter) {
27
+ this.railsAutoCompleter = new jQuery.railsAutocomplete(this);
28
+ }
29
+ });
30
+ };
31
+
32
+ jQuery.railsAutocomplete = function (e) {
33
+ _e = e;
34
+ this.init(_e);
35
+ };
36
+
37
+ jQuery.railsAutocomplete.fn = jQuery.railsAutocomplete.prototype = {
38
+ railsAutocomplete: '0.0.1'
39
+ };
40
+
41
+ jQuery.railsAutocomplete.fn.extend = jQuery.railsAutocomplete.extend = jQuery.extend;
42
+ jQuery.railsAutocomplete.fn.extend({
43
+ init: function(e) {
44
+ e.delimiter = $(e).attr('data-delimiter') || null;
45
+ function split( val ) {
46
+ return val.split( e.delimiter );
47
+ }
48
+ function extractLast( term ) {
49
+ return split( term ).pop().replace(/^\s+/,"");
50
+ }
51
+
52
+ $(e).autocomplete({
53
+ source: function( request, response ) {
54
+ $.getJSON( $(e).attr('data-autocomplete'), {
55
+ term: extractLast( request.term )
56
+ }, function() {
57
+ $(arguments[0]).each(function(i, el) {
58
+ var obj = {};
59
+ obj[el.id] = el;
60
+ $(e).data(obj);
61
+ });
62
+ response.apply(null, arguments);
63
+ });
64
+ },
65
+ search: function() {
66
+ // custom minLength
67
+ var term = extractLast( this.value );
68
+ if ( term.length < 2 ) {
69
+ return false;
70
+ }
71
+ },
72
+ focus: function() {
73
+ // prevent value inserted on focus
74
+ return false;
75
+ },
76
+ select: function( event, ui ) {
77
+ var terms = split( this.value );
78
+ // remove the current input
79
+ terms.pop();
80
+ // add the selected item
81
+ terms.push( ui.item.value );
82
+ // add placeholder to get the comma-and-space at the end
83
+ if (e.delimiter != null) {
84
+ terms.push( "" );
85
+ this.value = terms.join( e.delimiter );
86
+ } else {
87
+ this.value = terms.join("");
88
+ if ($(this).attr('data-id-element')) {
89
+ $($(this).attr('data-id-element')).val(ui.item.id);
90
+ }
91
+ if ($(this).attr('data-update-elements')) {
92
+ var data = $(this).data(ui.item.id.toString());
93
+ var update_elements = $.parseJSON($(this).attr("data-update-elements"));
94
+ for (var key in update_elements) {
95
+ $(update_elements[key]).val(data[key]);
96
+ }
97
+ }
98
+ }
99
+ var remember_string = this.value;
100
+ $(this).bind('keyup.clearId', function(){
101
+ if($(this).val().trim() != remember_string.trim()){
102
+ $($(this).attr('data-id-element')).val("");
103
+ $(this).unbind('keyup.clearId');
104
+ }
105
+ });
106
+ $(this).trigger('railsAutocomplete.select', ui);
107
+
108
+ return false;
109
+ }
110
+ });
111
+ }
112
+ });
113
+ })(jQuery);
@@ -0,0 +1,16 @@
1
+ /*
2
+ * Unobtrusive autocomplete
3
+ *
4
+ * To use it, you just have to include the HTML attribute autocomplete
5
+ * with the autocomplete URL as the value
6
+ *
7
+ * Example:
8
+ * <input type="text" data-autocomplete="/url/to/autocomplete">
9
+ *
10
+ * Optionally, you can use a jQuery selector to specify a field that can
11
+ * be updated with the element id whenever you find a matching value
12
+ *
13
+ * Example:
14
+ * <input type="text" data-autocomplete="/url/to/autocomplete" data-id-element="#id_field">
15
+ */
16
+ $(document).ready(function(){$("input[data-autocomplete]").railsAutocomplete()}),function(a){var b=null;a.fn.railsAutocomplete=function(){return this.live("focus",function(){this.railsAutoCompleter||(this.railsAutoCompleter=new a.railsAutocomplete(this))})},a.railsAutocomplete=function(a){_e=a,this.init(_e)},a.railsAutocomplete.fn=a.railsAutocomplete.prototype={railsAutocomplete:"0.0.1"},a.railsAutocomplete.fn.extend=a.railsAutocomplete.extend=a.extend,a.railsAutocomplete.fn.extend({init:function(a){function b(b){return b.split(a.delimiter)}function c(a){return b(a).pop().replace(/^\s+/,"")}a.delimiter=$(a).attr("data-delimiter")||null,$(a).autocomplete({source:function(b,d){$.getJSON($(a).attr("data-autocomplete"),{term:c(b.term)},function(){$(arguments[0]).each(function(b,c){var d={};d[c.id]=c,$(a).data(d)}),d.apply(null,arguments)})},search:function(){var a=c(this.value);if(a.length<2)return!1},focus:function(){return!1},select:function(c,d){var f=b(this.value);f.pop(),f.push(d.item.value);if(a.delimiter!=null)f.push(""),this.value=f.join(a.delimiter);else{this.value=f.join(""),$(this).attr("data-id-element")&&$($(this).attr("data-id-element")).val(d.item.id);if($(this).attr("data-update-elements")){var g=$(this).data(d.item.id.toString()),h=$.parseJSON($(this).attr("data-update-elements"));for(var i in h)$(h[i]).val(g[i])}}var j=this.value;return $(this).bind("keyup.clearId",function(){$(this).val().trim()!=j.trim()&&($($(this).attr("data-id-element")).val(""),$(this).unbind("keyup.clearId"))}),$(this).trigger("railsAutocomplete.select",d),!1}})}})}(jQuery)
@@ -0,0 +1,6 @@
1
+ Given /^I choose "([^"]*)" in the autocomplete list$/ do |text|
2
+ page.execute_script %Q{ $('input[data-autocomplete]').trigger("focus") }
3
+ page.execute_script %Q{ $('input[data-autocomplete]').trigger("keydown") }
4
+ sleep 1
5
+ page.execute_script %Q{ $('.ui-menu-item a:contains("#{text}")').trigger("mouseenter").trigger("click"); }
6
+ end
@@ -0,0 +1,14 @@
1
+ require 'rails/generators'
2
+
3
+ module Autocomplete
4
+ class InstallGenerator < Rails::Generators::Base
5
+ def install
6
+ # Copy the unobtrusive JS file
7
+ copy_file('autocomplete-rails.js', 'public/javascripts/autocomplete-rails.js')
8
+ end
9
+
10
+ def self.source_root
11
+ File.join(File.dirname(__FILE__), '..', '..', 'assets', 'javascripts')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require 'rails/generators'
2
+
3
+ module Autocomplete
4
+ class UncompressedGenerator < Rails::Generators::Base
5
+ def install
6
+ # Copy the unobtrusive JS file
7
+ copy_file('autocomplete-rails-uncompressed.js', 'public/javascripts/autocomplete-rails.js')
8
+ end
9
+
10
+ def self.source_root
11
+ File.join(File.dirname(__FILE__), '..', '..', 'assets', 'javascripts')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ require 'rails3-jquery-autocomplete/form_helper'
2
+ require 'rails3-jquery-autocomplete/autocomplete'
3
+
4
+ module Rails3JQueryAutocomplete
5
+ autoload :Orm , 'rails3-jquery-autocomplete/orm'
6
+ autoload :FormtasticPlugin , 'rails3-jquery-autocomplete/formtastic_plugin'
7
+
8
+ unless ::Rails.version < "3.1"
9
+ require 'rails3-jquery-autocomplete/rails/engine'
10
+ end
11
+ end
12
+
13
+ class ActionController::Base
14
+ include Rails3JQueryAutocomplete::Autocomplete
15
+ end
16
+
17
+ require 'rails3-jquery-autocomplete/formtastic'
18
+
19
+ begin
20
+ require 'simple_form'
21
+ require 'rails3-jquery-autocomplete/simple_form_plugin'
22
+ rescue LoadError
23
+ end
@@ -0,0 +1,110 @@
1
+ module Rails3JQueryAutocomplete
2
+ module Autocomplete
3
+ def self.included(target)
4
+ target.extend Rails3JQueryAutocomplete::Autocomplete::ClassMethods
5
+
6
+ target.send :include, Rails3JQueryAutocomplete::Orm::Mongoid if defined?(Mongoid::Document)
7
+ target.send :include, Rails3JQueryAutocomplete::Orm::MongoMapper if defined?(MongoMapper::Document)
8
+ target.send :include, Rails3JQueryAutocomplete::Orm::ActiveRecord
9
+ end
10
+
11
+ #
12
+ # Usage:
13
+ #
14
+ # class ProductsController < Admin::BaseController
15
+ # autocomplete :brand, :name
16
+ # end
17
+ #
18
+ # This will magically generate an action autocomplete_brand_name, so,
19
+ # don't forget to add it on your routes file
20
+ #
21
+ # resources :products do
22
+ # get :autocomplete_brand_name, :on => :collection
23
+ # end
24
+ #
25
+ # Now, on your view, all you have to do is have a text field like:
26
+ #
27
+ # f.text_field :brand_name, :autocomplete => autocomplete_brand_name_products_path
28
+ #
29
+ #
30
+ # Yajl is used by default to encode results, if you want to use a different encoder
31
+ # you can specify your custom encoder via block
32
+ #
33
+ # class ProductsController < Admin::BaseController
34
+ # autocomplete :brand, :name do |items|
35
+ # CustomJSONEncoder.encode(items)
36
+ # end
37
+ # end
38
+ #
39
+ module ClassMethods
40
+ def autocomplete(object, method, options = {})
41
+ define_method("get_prefix") do |model|
42
+ if model.superclass == ActiveRecord::Base
43
+ 'active_record'
44
+ elsif model.superclass == Object && model.include?(Mongoid::Document)
45
+ 'mongoid'
46
+ elsif model.superclass == Object && model.include?(MongoMapper::Document)
47
+ 'mongo_mapper'
48
+ end
49
+ end
50
+
51
+ define_method("get_autocomplete_order") do |method, options, model=nil|
52
+ method("#{get_prefix(get_object(options[:class_name] || object))}_get_autocomplete_order").call(method, options, model)
53
+ end
54
+
55
+ define_method("get_autocomplete_items") do |parameters|
56
+ method("#{get_prefix(get_object(options[:class_name] || object))}_get_autocomplete_items").call(parameters)
57
+ end
58
+
59
+ define_method("autocomplete_#{object}_#{method}") do
60
+
61
+ method = options[:column_name] if options.has_key?(:column_name)
62
+
63
+ term = params[:term]
64
+
65
+ if term && !term.blank?
66
+ #allow specifying fully qualified class name for model object
67
+ class_name = options[:class_name] || object
68
+ items = get_autocomplete_items(:model => get_object(class_name), \
69
+ :options => options, :term => term, :method => method)
70
+ else
71
+ items = {}
72
+ end
73
+
74
+ render :json => json_for_autocomplete(items, options[:display_value] ||= method, options[:extra_data])
75
+ end
76
+ end
77
+ end
78
+
79
+ # Returns a limit that will be used on the query
80
+ def get_autocomplete_limit(options)
81
+ options[:limit] ||= 10
82
+ end
83
+
84
+ # Returns parameter model_sym as a constant
85
+ #
86
+ # get_object(:actor)
87
+ # # returns a Actor constant supposing it is already defined
88
+ #
89
+ def get_object(model_sym)
90
+ object = model_sym.to_s.camelize.constantize
91
+ end
92
+
93
+ #
94
+ # Returns a hash with three keys actually used by the Autocomplete jQuery-ui
95
+ # Can be overriden to show whatever you like
96
+ # Hash also includes a key/value pair for each method in extra_data
97
+ #
98
+ def json_for_autocomplete(items, method, extra_data=[])
99
+ items.collect do |item|
100
+ hash = {"id" => item.id.to_s, "label" => item.send(method), "value" => item.send(method)}
101
+ extra_data.each do |datum|
102
+ hash[datum] = item.send(datum)
103
+ end if extra_data
104
+ # TODO: Come back to remove this if clause when test suite is better
105
+ hash
106
+ end
107
+ end
108
+ end
109
+ end
110
+
@@ -0,0 +1,47 @@
1
+ module ActionView
2
+ module Helpers
3
+ module FormHelper
4
+ # Returns an input tag of the "text" type tailored for accessing a specified attribute (identified by +method+) and
5
+ # that is populated with jQuery's autocomplete plugin.
6
+ #
7
+ # ==== Examples
8
+ # autocomplete_field(:post, :title, author_autocomplete_path, :size => 20)
9
+ # # => <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" data-autocomplete="author/autocomplete"/>
10
+ #
11
+ def autocomplete_field(object_name, method, source, options ={})
12
+ options["data-autocomplete"] = source
13
+ text_field(object_name, method, rewrite_autocomplete_option(options))
14
+ end
15
+ end
16
+
17
+ module FormTagHelper
18
+ # Creates a standard text field that can be populated with jQuery's autocomplete plugin
19
+ #
20
+ # ==== Examples
21
+ # autocomplete_field_tag 'address', '', address_autocomplete_path, :size => 75
22
+ # # => <input id="address" name="address" size="75" type="text" value="" data-autocomplete="address/autocomplete"/>
23
+ #
24
+ def autocomplete_field_tag(name, value, source, options ={})
25
+ options["data-autocomplete"] = source
26
+ text_field_tag(name, value, rewrite_autocomplete_option(options))
27
+ end
28
+ end
29
+
30
+ #
31
+ # Method used to rename the autocomplete key to a more standard
32
+ # data-autocomplete key
33
+ #
34
+ private
35
+ def rewrite_autocomplete_option(options)
36
+ options["data-update-elements"] = JSON.generate(options.delete :update_elements) if options[:update_elements]
37
+ options["data-id-element"] = options.delete :id_element if options[:id_element]
38
+ options
39
+ end
40
+ end
41
+ end
42
+
43
+ class ActionView::Helpers::FormBuilder #:nodoc:
44
+ def autocomplete_field(method, source, options = {})
45
+ @template.autocomplete_field(@object_name, method, source, objectify_options(options))
46
+ end
47
+ end
@@ -0,0 +1,41 @@
1
+ #
2
+ # Load the formtastic plugin if using Formtastic
3
+ #
4
+ begin
5
+ require 'formtastic'
6
+ begin
7
+ require "formtastic/version"
8
+ rescue LoadError
9
+ end
10
+
11
+ if defined?(Formtastic::VERSION)
12
+ #
13
+ # Formtastic 2.x
14
+ #
15
+
16
+ module Formtastic
17
+ module Inputs
18
+ class AutocompleteInput
19
+ include Base
20
+ include Base::Stringish
21
+
22
+ def to_html
23
+ input_wrapping do
24
+ label_html <<
25
+ builder.autocomplete_field(method, options.delete(:url), input_html_options)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ else
32
+
33
+ #
34
+ # Formtastic 1.x
35
+ #
36
+ class Formtastic::SemanticFormBuilder < ActionView::Helpers::FormBuilder
37
+ include Rails3JQueryAutocomplete::FormtasticPlugin
38
+ end
39
+ end
40
+ rescue LoadError
41
+ end
@@ -0,0 +1,44 @@
1
+ module Rails3JQueryAutocomplete
2
+ module FormtasticPlugin
3
+ def autocomplete_input(method, options = {})
4
+ if options.key?(:selected) || options.key?(:checked) || options.key?(:default)
5
+ ::ActiveSupport::Deprecation.warn(
6
+ "The :selected, :checked (and :default) options are deprecated in Formtastic and will be removed from 1.0. " <<
7
+ "Please set default values in your models (using an after_initialize callback) or in your controller set-up. " <<
8
+ "See http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html for more information.", caller)
9
+ end
10
+
11
+ options[:required] = method_required?(method) unless options.key?(:required)
12
+ options[:as] ||= "autocompleted_string"
13
+
14
+ html_class = [ options[:as], (options[:required] ? :required : :optional) ]
15
+ html_class << 'error' if @object && @object.respond_to?(:errors) && !@object.errors[method.to_sym].blank?
16
+
17
+ wrapper_html = options.delete(:wrapper_html) || {}
18
+ wrapper_html[:id] ||= generate_html_id(method)
19
+ wrapper_html[:class] = (html_class << wrapper_html[:class]).flatten.compact.join(' ')
20
+
21
+ if options[:input_html] && options[:input_html][:id]
22
+ options[:label_html] ||= {}
23
+ options[:label_html][:for] ||= options[:input_html][:id]
24
+ end
25
+
26
+ input_parts = self.class.inline_order.dup
27
+ input_parts = input_parts - [:errors, :hints] if options[:as] == :hidden
28
+
29
+ list_item_content = input_parts.map do |type|
30
+ send(:"inline_#{type}_for", method, options)
31
+ end.compact.join("\n")
32
+
33
+ return template.content_tag(:li, Formtastic::Util.html_safe(list_item_content), wrapper_html)
34
+ end
35
+
36
+ alias_method :autocompleted_input, :autocomplete_input
37
+
38
+
39
+ protected
40
+ def autocompleted_string_input(method, options)
41
+ self.label(method, options_for_label(options)) << autocomplete_field(method, options.delete(:url), options)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,8 @@
1
+ module Rails3JQueryAutocomplete
2
+ module Orm
3
+ autoload :ActiveRecord , 'rails3-jquery-autocomplete/orm/active_record'
4
+ autoload :Mongoid , 'rails3-jquery-autocomplete/orm/mongoid'
5
+ autoload :MongoMapper , 'rails3-jquery-autocomplete/orm/mongo_mapper'
6
+ end
7
+ end
8
+
@@ -0,0 +1,47 @@
1
+ module Rails3JQueryAutocomplete
2
+ module Orm
3
+ module ActiveRecord
4
+ def active_record_get_autocomplete_order(method, options, model=nil)
5
+ order = options[:order]
6
+
7
+ table_prefix = model ? "#{model.table_name}." : ""
8
+ order || "#{table_prefix}#{method} ASC"
9
+ end
10
+
11
+ def active_record_get_autocomplete_items(parameters)
12
+ model = parameters[:model]
13
+ term = parameters[:term]
14
+ method = parameters[:method]
15
+ options = parameters[:options]
16
+ scopes = Array(options[:scopes])
17
+ limit = get_autocomplete_limit(options)
18
+ order = active_record_get_autocomplete_order(method, options, model)
19
+
20
+
21
+ items = model.scoped
22
+
23
+ scopes.each { |scope| items = items.send(scope) } unless scopes.empty?
24
+
25
+ items = items.select(get_autocomplete_select_clause(model, method, options)) unless options[:full_model]
26
+ items = items.where(get_autocomplete_where_clause(model, term, method, options)).
27
+ limit(limit).order(order)
28
+ end
29
+
30
+ def get_autocomplete_select_clause(model, method, options)
31
+ table_name = model.table_name
32
+ (["#{table_name}.#{model.primary_key}", "#{table_name}.#{method}"] + (options[:extra_data].blank? ? [] : options[:extra_data]))
33
+ end
34
+
35
+ def get_autocomplete_where_clause(model, term, method, options)
36
+ table_name = model.table_name
37
+ is_full_search = options[:full]
38
+ like_clause = (postgres? ? 'ILIKE' : 'LIKE')
39
+ ["LOWER(#{table_name}.#{method}) #{like_clause} ?", "#{(is_full_search ? '%' : '')}#{term.downcase}%"]
40
+ end
41
+
42
+ def postgres?
43
+ defined?(PGconn)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,30 @@
1
+ module Rails3JQueryAutocomplete
2
+ module Orm
3
+ module MongoMapper
4
+ def mongo_mapper_get_autocomplete_order(method, options, model=nil)
5
+ order = options[:order]
6
+ if order
7
+ order.split(',').collect do |fields|
8
+ sfields = fields.split
9
+ [sfields[0].downcase.to_sym, sfields[1].downcase.to_sym]
10
+ end
11
+ else
12
+ [[method.to_sym, :asc]]
13
+ end
14
+ end
15
+
16
+ def mongo_mapper_get_autocomplete_items(parameters)
17
+ model = parameters[:model]
18
+ method = parameters[:method]
19
+ options = parameters[:options]
20
+ is_full_search = options[:full]
21
+ term = parameters[:term]
22
+ limit = get_autocomplete_limit(options)
23
+ order = mongo_mapper_get_autocomplete_order(method, options)
24
+
25
+ search = (is_full_search ? '.*' : '^') + term + '.*'
26
+ items = model.where(method.to_sym => /#{search}/i).limit(limit).sort(order)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ module Rails3JQueryAutocomplete
2
+ module Orm
3
+ module Mongoid
4
+ def mongoid_get_autocomplete_order(method, options, model=nil)
5
+ order = options[:order]
6
+ if order
7
+ order.split(',').collect do |fields|
8
+ sfields = fields.split
9
+ [sfields[0].downcase.to_sym, sfields[1].downcase.to_sym]
10
+ end
11
+ else
12
+ [[method.to_sym, :asc]]
13
+ end
14
+ end
15
+
16
+ def mongoid_get_autocomplete_items(parameters)
17
+ model = parameters[:model]
18
+ method = parameters[:method]
19
+ options = parameters[:options]
20
+ is_full_search = options[:full]
21
+ term = parameters[:term]
22
+ limit = get_autocomplete_limit(options)
23
+ order = mongoid_get_autocomplete_order(method, options)
24
+
25
+ if is_full_search
26
+ search = '.*' + term + '.*'
27
+ else
28
+ search = '^' + term
29
+ end
30
+ items = model.where(method.to_sym => /#{search}/i).limit(limit).order_by(order)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ module Rails3JQueryAutocomplete
2
+ module Rails
3
+ class Engine < ::Rails::Engine ; end
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ module SimpleForm
2
+ module Inputs
3
+ class AutocompleteInput < Base
4
+ def input
5
+ @builder.autocomplete_field(attribute_name, options[:url], input_html_options)
6
+ end
7
+
8
+ protected
9
+
10
+ def limit
11
+ column && column.limit
12
+ end
13
+
14
+ def has_placeholder?
15
+ placeholder_present?
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ module SimpleForm
22
+ class FormBuilder
23
+ map_type :autocomplete, :to => SimpleForm::Inputs::AutocompleteInput
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module Rails3JQueryAutocomplete
2
+ VERSION = '1.0.4'
3
+ end
@@ -0,0 +1,12 @@
1
+ module Steak
2
+ module Autocomplete
3
+ def choose_autocomplete_result(text, input_id="input[data-autocomplete]")
4
+ page.execute_script %Q{ $('#{input_id}').trigger("focus") }
5
+ page.execute_script %Q{ $('#{input_id}').trigger("keydown") }
6
+ sleep 1
7
+ page.execute_script %Q{ $('.ui-menu-item a:contains("#{text}")').trigger("mouseenter").trigger("click"); }
8
+ end
9
+ end
10
+ end
11
+
12
+ RSpec.configuration.include Steak::Autocomplete, :type => :acceptance
metadata ADDED
@@ -0,0 +1,210 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wf-rails3-jquery-autocomplete
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Padilla
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sqlite3-ruby
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: mongoid
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 2.0.0
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: mongo_mapper
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0.9'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0.9'
78
+ - !ruby/object:Gem::Dependency
79
+ name: bson_ext
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 1.3.0
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 1.3.0
94
+ - !ruby/object:Gem::Dependency
95
+ name: shoulda
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 2.11.1
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 2.11.1
110
+ - !ruby/object:Gem::Dependency
111
+ name: uglifier
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rr
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: rcov
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ description: Use jQuery's autocomplete plugin with Rails 3.
159
+ email: david.padilla@crowdint.com
160
+ executables: []
161
+ extensions: []
162
+ extra_rdoc_files: []
163
+ files:
164
+ - lib/assets/javascripts/autocomplete-rails-uncompressed.js
165
+ - lib/assets/javascripts/autocomplete-rails.js
166
+ - lib/cucumber/autocomplete.rb
167
+ - lib/generators/autocomplete/install_generator.rb
168
+ - lib/generators/autocomplete/uncompressed_generator.rb
169
+ - lib/rails3-jquery-autocomplete/autocomplete.rb
170
+ - lib/rails3-jquery-autocomplete/formtastic.rb
171
+ - lib/rails3-jquery-autocomplete/formtastic_plugin.rb
172
+ - lib/rails3-jquery-autocomplete/form_helper.rb
173
+ - lib/rails3-jquery-autocomplete/orm/active_record.rb
174
+ - lib/rails3-jquery-autocomplete/orm/mongoid.rb
175
+ - lib/rails3-jquery-autocomplete/orm/mongo_mapper.rb
176
+ - lib/rails3-jquery-autocomplete/orm.rb
177
+ - lib/rails3-jquery-autocomplete/rails/engine.rb
178
+ - lib/rails3-jquery-autocomplete/simple_form_plugin.rb
179
+ - lib/rails3-jquery-autocomplete/version.rb
180
+ - lib/rails3-jquery-autocomplete.rb
181
+ - lib/steak/autocomplete.rb
182
+ - CHANGELOG.md
183
+ - LICENSE
184
+ - README.md
185
+ - Rakefile
186
+ homepage: http://github.com/crowdint/rails3-jquery-autocomplete
187
+ licenses: []
188
+ post_install_message:
189
+ rdoc_options: []
190
+ require_paths:
191
+ - lib
192
+ required_ruby_version: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ! '>='
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ required_rubygems_version: !ruby/object:Gem::Requirement
199
+ none: false
200
+ requirements:
201
+ - - ! '>='
202
+ - !ruby/object:Gem::Version
203
+ version: '0'
204
+ requirements: []
205
+ rubyforge_project:
206
+ rubygems_version: 1.8.24
207
+ signing_key:
208
+ specification_version: 3
209
+ summary: Use jQuery's autocomplete plugin with Rails 3.
210
+ test_files: []