rails-jquery-autocomplete 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/CHANGELOG.md +31 -0
- data/LICENSE +20 -0
- data/README.md +476 -0
- data/Rakefile +21 -0
- data/lib/assets/javascripts/autocomplete-rails-uncompressed.js +179 -0
- data/lib/assets/javascripts/autocomplete-rails.js +1 -0
- data/lib/cucumber/autocomplete.rb +6 -0
- data/lib/generators/autocomplete/install_generator.rb +14 -0
- data/lib/generators/autocomplete/uncompressed_generator.rb +14 -0
- data/lib/rails-jquery-autocomplete.rb +23 -0
- data/lib/rails-jquery-autocomplete/autocomplete.rb +116 -0
- data/lib/rails-jquery-autocomplete/form_helper.rb +49 -0
- data/lib/rails-jquery-autocomplete/formtastic.rb +41 -0
- data/lib/rails-jquery-autocomplete/formtastic_plugin.rb +44 -0
- data/lib/rails-jquery-autocomplete/orm.rb +8 -0
- data/lib/rails-jquery-autocomplete/orm/active_record.rb +56 -0
- data/lib/rails-jquery-autocomplete/orm/mongo_mapper.rb +30 -0
- data/lib/rails-jquery-autocomplete/orm/mongoid.rb +34 -0
- data/lib/rails-jquery-autocomplete/rails/engine.rb +5 -0
- data/lib/rails-jquery-autocomplete/simple_form_plugin.rb +85 -0
- data/lib/rails-jquery-autocomplete/version.rb +3 -0
- data/lib/steak/autocomplete.rb +12 -0
- metadata +250 -0
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
task :default => [:uglify, :test]
|
7
|
+
|
8
|
+
Rake::TestTask.new(:test) do |test|
|
9
|
+
test.libs << 'lib' << 'test'
|
10
|
+
test.pattern = 'test/**/*_test.rb'
|
11
|
+
test.verbose = true
|
12
|
+
end
|
13
|
+
|
14
|
+
task :uglify do
|
15
|
+
require 'uglifier'
|
16
|
+
file_folder = "lib/assets/javascripts"
|
17
|
+
File.open("#{file_folder}/autocomplete-rails.js", "w") do |f|
|
18
|
+
f << Uglifier.compile(File.read("#{file_folder}/autocomplete-rails-uncompressed.js"))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,179 @@
|
|
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
|
+
(function(jQuery)
|
18
|
+
{
|
19
|
+
var self = null;
|
20
|
+
jQuery.fn.railsAutocomplete = function() {
|
21
|
+
var handler = function() {
|
22
|
+
if (!this.railsAutoCompleter) {
|
23
|
+
this.railsAutoCompleter = new jQuery.railsAutocomplete(this);
|
24
|
+
}
|
25
|
+
};
|
26
|
+
if (jQuery.fn.on !== undefined) {
|
27
|
+
return jQuery(document).on('focus',this.selector,handler);
|
28
|
+
}
|
29
|
+
else {
|
30
|
+
return this.live('focus',handler);
|
31
|
+
}
|
32
|
+
};
|
33
|
+
|
34
|
+
jQuery.railsAutocomplete = function (e) {
|
35
|
+
var _e = e;
|
36
|
+
this.init(_e);
|
37
|
+
};
|
38
|
+
|
39
|
+
jQuery.railsAutocomplete.fn = jQuery.railsAutocomplete.prototype = {
|
40
|
+
railsAutocomplete: '0.0.1'
|
41
|
+
};
|
42
|
+
|
43
|
+
jQuery.railsAutocomplete.fn.extend = jQuery.railsAutocomplete.extend = jQuery.extend;
|
44
|
+
jQuery.railsAutocomplete.fn.extend({
|
45
|
+
init: function(e) {
|
46
|
+
e.delimiter = jQuery(e).attr('data-delimiter') || null;
|
47
|
+
e.min_length = jQuery(e).attr('min-length') || 2;
|
48
|
+
e.append_to = jQuery(e).attr('data-append-to') || null;
|
49
|
+
e.autoFocus = jQuery(e).attr('data-auto-focus') || false;
|
50
|
+
function split( val ) {
|
51
|
+
return val.split( e.delimiter );
|
52
|
+
}
|
53
|
+
function extractLast( term ) {
|
54
|
+
return split( term ).pop().replace(/^\s+/,"");
|
55
|
+
}
|
56
|
+
|
57
|
+
jQuery(e).autocomplete({
|
58
|
+
appendTo: e.append_to,
|
59
|
+
autoFocus: e.autoFocus,
|
60
|
+
delay: jQuery(e).attr('delay') || 0,
|
61
|
+
source: function( request, response ) {
|
62
|
+
var firedFrom = this.element[0];
|
63
|
+
var params = {term: extractLast( request.term )};
|
64
|
+
if (jQuery(e).attr('data-autocomplete-fields')) {
|
65
|
+
jQuery.each(jQuery.parseJSON(jQuery(e).attr('data-autocomplete-fields')), function(field, selector) {
|
66
|
+
params[field] = jQuery(selector).val();
|
67
|
+
});
|
68
|
+
}
|
69
|
+
jQuery.getJSON( jQuery(e).attr('data-autocomplete'), params, function() {
|
70
|
+
if(arguments[0].length === 0) {
|
71
|
+
arguments[0] = [];
|
72
|
+
arguments[0][0] = { id: "", label: "no existing match" };
|
73
|
+
}
|
74
|
+
jQuery(arguments[0]).each(function(i, el) {
|
75
|
+
var obj = {};
|
76
|
+
obj[el.id] = el;
|
77
|
+
jQuery(e).data(obj);
|
78
|
+
});
|
79
|
+
response.apply(null, arguments);
|
80
|
+
jQuery(firedFrom).trigger('railsAutocomplete.source', arguments);
|
81
|
+
});
|
82
|
+
},
|
83
|
+
change: function( event, ui ) {
|
84
|
+
if(!jQuery(this).is('[data-id-element]') ||
|
85
|
+
jQuery(jQuery(this).attr('data-id-element')).val() === "") {
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
jQuery(jQuery(this).attr('data-id-element')).val(ui.item ? ui.item.id : "");
|
89
|
+
|
90
|
+
if (jQuery(this).attr('data-update-elements')) {
|
91
|
+
var update_elements = jQuery.parseJSON(jQuery(this).attr("data-update-elements"));
|
92
|
+
var data = ui.item ? jQuery(this).data(ui.item.id.toString()) : {};
|
93
|
+
if(update_elements && jQuery(update_elements['id']).val() === "") {
|
94
|
+
return;
|
95
|
+
}
|
96
|
+
for (var key in update_elements) {
|
97
|
+
var element = jQuery(update_elements[key]);
|
98
|
+
if (element.is(':checkbox')) {
|
99
|
+
if (data[key] != null) {
|
100
|
+
element.prop('checked', data[key]);
|
101
|
+
}
|
102
|
+
} else {
|
103
|
+
element.val(ui.item ? data[key] : "");
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
},
|
108
|
+
search: function() {
|
109
|
+
// custom minLength
|
110
|
+
var term = extractLast( this.value );
|
111
|
+
if ( term.length < e.min_length ) {
|
112
|
+
return false;
|
113
|
+
}
|
114
|
+
},
|
115
|
+
focus: function() {
|
116
|
+
// prevent value inserted on focus
|
117
|
+
return false;
|
118
|
+
},
|
119
|
+
select: function( event, ui ) {
|
120
|
+
if(ui.item.value.toLowerCase().indexOf('no match') != -1 || ui.item.value.toLowerCase().indexOf('too many results') != -1){
|
121
|
+
jQuery(this).trigger('railsAutocomplete.noMatch', ui);
|
122
|
+
return false;
|
123
|
+
}
|
124
|
+
var terms = split( this.value );
|
125
|
+
// remove the current input
|
126
|
+
terms.pop();
|
127
|
+
// add the selected item
|
128
|
+
terms.push( ui.item.value );
|
129
|
+
// add placeholder to get the comma-and-space at the end
|
130
|
+
if (e.delimiter != null) {
|
131
|
+
terms.push( "" );
|
132
|
+
this.value = terms.join( e.delimiter );
|
133
|
+
} else {
|
134
|
+
this.value = terms.join("");
|
135
|
+
if (jQuery(this).attr('data-id-element')) {
|
136
|
+
jQuery(jQuery(this).attr('data-id-element')).val(ui.item.id);
|
137
|
+
}
|
138
|
+
if (jQuery(this).attr('data-update-elements')) {
|
139
|
+
var data = ui.item;
|
140
|
+
var new_record = ui.item.value.indexOf('Create New') != -1 ? true : false;
|
141
|
+
var update_elements = jQuery.parseJSON(jQuery(this).attr("data-update-elements"));
|
142
|
+
for (var key in update_elements) {
|
143
|
+
if(jQuery(update_elements[key]).attr("type") === "checkbox"){
|
144
|
+
if(data[key] === true || data[key] === 1) {
|
145
|
+
jQuery(update_elements[key]).attr("checked","checked");
|
146
|
+
}
|
147
|
+
else {
|
148
|
+
jQuery(update_elements[key]).removeAttr("checked");
|
149
|
+
}
|
150
|
+
}
|
151
|
+
else{
|
152
|
+
if((new_record && data[key] && data[key].indexOf('Create New') == -1) || !new_record){
|
153
|
+
jQuery(update_elements[key]).val(data[key]);
|
154
|
+
}else{
|
155
|
+
jQuery(update_elements[key]).val('');
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
}
|
161
|
+
var remember_string = this.value;
|
162
|
+
jQuery(this).bind('keyup.clearId', function(){
|
163
|
+
if(jQuery.trim(jQuery(this).val()) != jQuery.trim(remember_string)){
|
164
|
+
jQuery(jQuery(this).attr('data-id-element')).val("");
|
165
|
+
jQuery(this).unbind('keyup.clearId');
|
166
|
+
}
|
167
|
+
});
|
168
|
+
jQuery(e).trigger('railsAutocomplete.select', ui);
|
169
|
+
|
170
|
+
return false;
|
171
|
+
}
|
172
|
+
});
|
173
|
+
}
|
174
|
+
});
|
175
|
+
|
176
|
+
jQuery(document).ready(function(){
|
177
|
+
jQuery('input[data-autocomplete]').railsAutocomplete();
|
178
|
+
});
|
179
|
+
})(jQuery);
|
@@ -0,0 +1 @@
|
|
1
|
+
!function(t){t.fn.railsAutocomplete=function(){var e=function(){this.railsAutoCompleter||(this.railsAutoCompleter=new t.railsAutocomplete(this))};return void 0!==t.fn.on?t(document).on("focus",this.selector,e):this.live("focus",e)},t.railsAutocomplete=function(t){var e=t;this.init(e)},t.railsAutocomplete.fn=t.railsAutocomplete.prototype={railsAutocomplete:"0.0.1"},t.railsAutocomplete.fn.extend=t.railsAutocomplete.extend=t.extend,t.railsAutocomplete.fn.extend({init:function(e){function a(t){return t.split(e.delimiter)}function i(t){return a(t).pop().replace(/^\s+/,"")}e.delimiter=t(e).attr("data-delimiter")||null,e.min_length=t(e).attr("min-length")||2,e.append_to=t(e).attr("data-append-to")||null,e.autoFocus=t(e).attr("data-auto-focus")||!1,t(e).autocomplete({appendTo:e.append_to,autoFocus:e.autoFocus,delay:t(e).attr("delay")||0,source:function(a,n){var r=this.element[0],o={term:i(a.term)};t(e).attr("data-autocomplete-fields")&&t.each(t.parseJSON(t(e).attr("data-autocomplete-fields")),function(e,a){o[e]=t(a).val()}),t.getJSON(t(e).attr("data-autocomplete"),o,function(){0===arguments[0].length&&(arguments[0]=[],arguments[0][0]={id:"",label:"no existing match"}),t(arguments[0]).each(function(a,i){var n={};n[i.id]=i,t(e).data(n)}),n.apply(null,arguments),t(r).trigger("railsAutocomplete.source",arguments)})},change:function(e,a){if(t(this).is("[data-id-element]")&&""!==t(t(this).attr("data-id-element")).val()&&(t(t(this).attr("data-id-element")).val(a.item?a.item.id:""),t(this).attr("data-update-elements"))){var i=t.parseJSON(t(this).attr("data-update-elements")),n=a.item?t(this).data(a.item.id.toString()):{};if(i&&""===t(i.id).val())return;for(var r in i){var o=t(i[r]);o.is(":checkbox")?null!=n[r]&&o.prop("checked",n[r]):o.val(a.item?n[r]:"")}}},search:function(){var t=i(this.value);return t.length<e.min_length?!1:void 0},focus:function(){return!1},select:function(i,n){if(-1!=n.item.value.toLowerCase().indexOf("no match")||-1!=n.item.value.toLowerCase().indexOf("too many results"))return t(this).trigger("railsAutocomplete.noMatch",n),!1;var r=a(this.value);if(r.pop(),r.push(n.item.value),null!=e.delimiter)r.push(""),this.value=r.join(e.delimiter);else if(this.value=r.join(""),t(this).attr("data-id-element")&&t(t(this).attr("data-id-element")).val(n.item.id),t(this).attr("data-update-elements")){var o=n.item,l=-1!=n.item.value.indexOf("Create New")?!0:!1,u=t.parseJSON(t(this).attr("data-update-elements"));for(var s in u)"checkbox"===t(u[s]).attr("type")?o[s]===!0||1===o[s]?t(u[s]).attr("checked","checked"):t(u[s]).removeAttr("checked"):t(u[s]).val(l&&o[s]&&-1==o[s].indexOf("Create New")||!l?o[s]:"")}var c=this.value;return t(this).bind("keyup.clearId",function(){t.trim(t(this).val())!=t.trim(c)&&(t(t(this).attr("data-id-element")).val(""),t(this).unbind("keyup.clearId"))}),t(e).trigger("railsAutocomplete.select",n),!1}})}}),t(document).ready(function(){t("input[data-autocomplete]").railsAutocomplete()})}(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 'rails-jquery-autocomplete/form_helper'
|
2
|
+
require 'rails-jquery-autocomplete/autocomplete'
|
3
|
+
|
4
|
+
module RailsJQueryAutocomplete
|
5
|
+
autoload :Orm , 'rails-jquery-autocomplete/orm'
|
6
|
+
autoload :FormtasticPlugin , 'rails-jquery-autocomplete/formtastic_plugin'
|
7
|
+
|
8
|
+
unless ::Rails.version < "3.1"
|
9
|
+
require 'rails-jquery-autocomplete/rails/engine'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ActionController::Base
|
14
|
+
include RailsJQueryAutocomplete::Autocomplete
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'rails-jquery-autocomplete/formtastic'
|
18
|
+
|
19
|
+
begin
|
20
|
+
require 'simple_form'
|
21
|
+
require 'rails-jquery-autocomplete/simple_form_plugin'
|
22
|
+
rescue LoadError
|
23
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module RailsJQueryAutocomplete
|
2
|
+
module Autocomplete
|
3
|
+
def self.included(target)
|
4
|
+
target.extend RailsJQueryAutocomplete::Autocomplete::ClassMethods
|
5
|
+
|
6
|
+
target.send :include, RailsJQueryAutocomplete::Orm::Mongoid if defined?(Mongoid::Document)
|
7
|
+
target.send :include, RailsJQueryAutocomplete::Orm::MongoMapper if defined?(MongoMapper::Document)
|
8
|
+
target.send :include, RailsJQueryAutocomplete::Orm::ActiveRecord
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# Usage:
|
14
|
+
#
|
15
|
+
# class ProductsController < Admin::BaseController
|
16
|
+
# autocomplete :brand, :name
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# This will magically generate an action autocomplete_brand_name, so,
|
20
|
+
# don't forget to add it on your routes file
|
21
|
+
#
|
22
|
+
# resources :products do
|
23
|
+
# get :autocomplete_brand_name, :on => :collection
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# Now, on your view, all you have to do is have a text field like:
|
27
|
+
#
|
28
|
+
# f.text_field :brand_name, :autocomplete => autocomplete_brand_name_products_path
|
29
|
+
#
|
30
|
+
#
|
31
|
+
# Yajl is used by default to encode results, if you want to use a different encoder
|
32
|
+
# you can specify your custom encoder via block
|
33
|
+
#
|
34
|
+
# class ProductsController < Admin::BaseController
|
35
|
+
# autocomplete :brand, :name do |items|
|
36
|
+
# CustomJSONEncoder.encode(items)
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
module ClassMethods
|
41
|
+
def autocomplete(object, method, options = {}, &block)
|
42
|
+
|
43
|
+
define_method("get_prefix") do |model|
|
44
|
+
if defined?(Mongoid::Document) && model.include?(Mongoid::Document)
|
45
|
+
'mongoid'
|
46
|
+
elsif defined?(MongoMapper::Document) && model.include?(MongoMapper::Document)
|
47
|
+
'mongo_mapper'
|
48
|
+
else
|
49
|
+
'active_record'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
define_method("get_autocomplete_order") do |method, options, model=nil|
|
53
|
+
method("#{get_prefix(get_object(options[:class_name] || object))}_get_autocomplete_order").call(method, options, model)
|
54
|
+
end
|
55
|
+
|
56
|
+
define_method("get_autocomplete_items") do |parameters|
|
57
|
+
method("#{get_prefix(get_object(options[:class_name] || object))}_get_autocomplete_items").call(parameters)
|
58
|
+
end
|
59
|
+
|
60
|
+
define_method("autocomplete_#{object}_#{method}") do
|
61
|
+
|
62
|
+
method = options[:column_name] if options.has_key?(:column_name)
|
63
|
+
|
64
|
+
term = params[:term]
|
65
|
+
|
66
|
+
if term && !term.blank?
|
67
|
+
#allow specifying fully qualified class name for model object
|
68
|
+
class_name = options[:class_name] || object
|
69
|
+
items = get_autocomplete_items(:model => get_object(class_name), \
|
70
|
+
:options => options, :term => term, :method => method)
|
71
|
+
else
|
72
|
+
items = {}
|
73
|
+
end
|
74
|
+
|
75
|
+
render :json => json_for_autocomplete(items, options[:display_value] ||= method, options[:extra_data], &block), root: false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a limit that will be used on the query
|
81
|
+
def get_autocomplete_limit(options)
|
82
|
+
options[:limit] ||= 10
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns parameter model_sym as a constant
|
86
|
+
#
|
87
|
+
# get_object(:actor)
|
88
|
+
# # returns a Actor constant supposing it is already defined
|
89
|
+
#
|
90
|
+
def get_object(model_sym)
|
91
|
+
object = model_sym.to_s.camelize.constantize
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Returns a hash with three keys actually used by the Autocomplete jQuery-ui
|
96
|
+
# Can be overriden to show whatever you like
|
97
|
+
# Hash also includes a key/value pair for each method in extra_data
|
98
|
+
#
|
99
|
+
def json_for_autocomplete(items, method, extra_data=[])
|
100
|
+
items = items.collect do |item|
|
101
|
+
hash = {"id" => item.id.to_s, "label" => item.send(method), "value" => item.send(method)}
|
102
|
+
extra_data.each do |datum|
|
103
|
+
hash[datum] = item.send(datum)
|
104
|
+
end if extra_data
|
105
|
+
# TODO: Come back to remove this if clause when test suite is better
|
106
|
+
hash
|
107
|
+
end
|
108
|
+
if block_given?
|
109
|
+
yield(items)
|
110
|
+
else
|
111
|
+
items
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
@@ -0,0 +1,49 @@
|
|
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-autocomplete-fields"] = JSON.generate(options.delete :fields) if options[:fields]
|
37
|
+
options["data-update-elements"] = JSON.generate(options.delete :update_elements) if options[:update_elements]
|
38
|
+
options["data-id-element"] = options.delete :id_element if options[:id_element]
|
39
|
+
options["data-append-to"] = options.delete :append_to if options[:append_to]
|
40
|
+
options
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class ActionView::Helpers::FormBuilder #:nodoc:
|
46
|
+
def autocomplete_field(method, source, options = {})
|
47
|
+
@template.autocomplete_field(@object_name, method, source, objectify_options(options))
|
48
|
+
end
|
49
|
+
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 RailsJQueryAutocomplete::FormtasticPlugin
|
38
|
+
end
|
39
|
+
end
|
40
|
+
rescue LoadError
|
41
|
+
end
|