rails-autocomplete 1.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +51 -0
- data/LICENSE +20 -0
- data/README.md +453 -0
- data/Rakefile +21 -0
- data/lib/assets/javascripts/autocomplete-rails-uncompressed.js +197 -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 +112 -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 +6 -0
- data/lib/rails-jquery-autocomplete/orm/active_record.rb +83 -0
- data/lib/rails-jquery-autocomplete/rails/engine.rb +5 -0
- data/lib/rails-jquery-autocomplete/simple_form_plugin.rb +100 -0
- data/lib/rails-jquery-autocomplete/version.rb +3 -0
- data/lib/steak/autocomplete.rb +12 -0
- data/test/form_helper_test.rb +25 -0
- data/test/generators/autocomplete/install_generator_test.rb +25 -0
- data/test/generators/autocomplete/uncompressed_generator_test.rb +25 -0
- data/test/lib/rails-jquery-autocomplete/autocomplete_test.rb +93 -0
- data/test/lib/rails-jquery-autocomplete/orm/active_record_test.rb +190 -0
- data/test/lib/rails-jquery-autocomplete/simple_form_plugin_test.rb +33 -0
- data/test/lib/rails-jquery-autocomplete_test.rb +38 -0
- data/test/test_helper.rb +35 -0
- data/test/view_test_helper.rb +108 -0
- metadata +196 -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,197 @@
|
|
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(selector) {
|
21
|
+
var handler = function() {
|
22
|
+
if (!this.railsAutoCompleter) {
|
23
|
+
this.railsAutoCompleter = new jQuery.railsAutocomplete(this);
|
24
|
+
}
|
25
|
+
};
|
26
|
+
if (jQuery.fn.on !== undefined) {
|
27
|
+
if (!selector) {
|
28
|
+
return;
|
29
|
+
}
|
30
|
+
return jQuery(document).on('focus',selector,handler);
|
31
|
+
}
|
32
|
+
else {
|
33
|
+
return this.live('focus',handler);
|
34
|
+
}
|
35
|
+
};
|
36
|
+
|
37
|
+
jQuery.railsAutocomplete = function (e) {
|
38
|
+
var _e = e;
|
39
|
+
this.init(_e);
|
40
|
+
};
|
41
|
+
jQuery.railsAutocomplete.options = {
|
42
|
+
showNoMatches: true,
|
43
|
+
noMatchesLabel: 'no existing match'
|
44
|
+
}
|
45
|
+
|
46
|
+
jQuery.railsAutocomplete.fn = jQuery.railsAutocomplete.prototype = {
|
47
|
+
railsAutocomplete: '0.0.1'
|
48
|
+
};
|
49
|
+
|
50
|
+
jQuery.railsAutocomplete.fn.extend = jQuery.railsAutocomplete.extend = jQuery.extend;
|
51
|
+
jQuery.railsAutocomplete.fn.extend({
|
52
|
+
init: function(e) {
|
53
|
+
e.delimiter = jQuery(e).attr('data-delimiter') || null;
|
54
|
+
e.min_length = jQuery(e).attr('data-min-length') || jQuery(e).attr('min-length') || 2;
|
55
|
+
e.append_to = jQuery(e).attr('data-append-to') || null;
|
56
|
+
e.autoFocus = jQuery(e).attr('data-auto-focus') || false;
|
57
|
+
function split( val ) {
|
58
|
+
return val.split( e.delimiter );
|
59
|
+
}
|
60
|
+
function extractLast( term ) {
|
61
|
+
return split( term ).pop().replace(/^\s+/,"");
|
62
|
+
}
|
63
|
+
|
64
|
+
jQuery(e).autocomplete({
|
65
|
+
appendTo: e.append_to,
|
66
|
+
autoFocus: e.autoFocus,
|
67
|
+
delay: jQuery(e).attr('delay') || 0,
|
68
|
+
source: function( request, response ) {
|
69
|
+
var firedFrom = this.element[0];
|
70
|
+
var params = {term: extractLast( request.term )};
|
71
|
+
if (jQuery(e).attr('data-autocomplete-fields')) {
|
72
|
+
jQuery.each(jQuery.parseJSON(jQuery(e).attr('data-autocomplete-fields')), function(field, selector) {
|
73
|
+
params[field] = jQuery(selector).val();
|
74
|
+
});
|
75
|
+
}
|
76
|
+
jQuery.getJSON( jQuery(e).attr('data-autocomplete'), params, function() {
|
77
|
+
var options = {};
|
78
|
+
jQuery.extend(options, jQuery.railsAutocomplete.options);
|
79
|
+
jQuery.each(options, function(key, value) {
|
80
|
+
if(options.hasOwnProperty(key)) {
|
81
|
+
var attrVal = jQuery(e).attr('data-' + key);
|
82
|
+
options[key] = attrVal ? attrVal : value;
|
83
|
+
}
|
84
|
+
});
|
85
|
+
if(arguments[0].length == 0 && jQuery.inArray(options.showNoMatches, [true, 'true']) >= 0) {
|
86
|
+
arguments[0] = [];
|
87
|
+
arguments[0][0] = { id: "", label: options.noMatchesLabel };
|
88
|
+
}
|
89
|
+
jQuery(arguments[0]).each(function(i, el) {
|
90
|
+
var obj = {};
|
91
|
+
obj[el.id] = el;
|
92
|
+
jQuery(e).data(obj);
|
93
|
+
});
|
94
|
+
response.apply(null, arguments);
|
95
|
+
jQuery(firedFrom).trigger('railsAutocomplete.source', arguments);
|
96
|
+
});
|
97
|
+
},
|
98
|
+
change: function( event, ui ) {
|
99
|
+
if(!jQuery(this).is('[data-id-element]') ||
|
100
|
+
jQuery(jQuery(this).attr('data-id-element')).val() === "") {
|
101
|
+
return;
|
102
|
+
}
|
103
|
+
jQuery(jQuery(this).attr('data-id-element')).val(ui.item ? ui.item.id : "").trigger('change');
|
104
|
+
|
105
|
+
if (jQuery(this).attr('data-update-elements')) {
|
106
|
+
var update_elements = jQuery.parseJSON(jQuery(this).attr("data-update-elements"));
|
107
|
+
var data = ui.item ? jQuery(this).data(ui.item.id.toString()) : {};
|
108
|
+
if(update_elements && jQuery(update_elements['id']).val() === "") {
|
109
|
+
return;
|
110
|
+
}
|
111
|
+
for (var key in update_elements) {
|
112
|
+
var element = jQuery(update_elements[key]);
|
113
|
+
if (element.is(':checkbox')) {
|
114
|
+
if (data[key] != null) {
|
115
|
+
element.prop('checked', data[key]);
|
116
|
+
}
|
117
|
+
} else {
|
118
|
+
element.val(ui.item ? data[key] : "").trigger('change');
|
119
|
+
}
|
120
|
+
}
|
121
|
+
}
|
122
|
+
},
|
123
|
+
search: function() {
|
124
|
+
// custom minLength
|
125
|
+
var term = extractLast( this.value );
|
126
|
+
if ( term.length < e.min_length ) {
|
127
|
+
return false;
|
128
|
+
}
|
129
|
+
},
|
130
|
+
focus: function() {
|
131
|
+
// prevent value inserted on focus
|
132
|
+
return false;
|
133
|
+
},
|
134
|
+
select: function( event, ui ) {
|
135
|
+
// first ensure value is a string
|
136
|
+
ui.item.value = ui.item.value.toString();
|
137
|
+
if(ui.item.value.toLowerCase().indexOf('no match') != -1 || ui.item.value.toLowerCase().indexOf('too many results') != -1){
|
138
|
+
jQuery(this).trigger('railsAutocomplete.noMatch', ui);
|
139
|
+
return false;
|
140
|
+
}
|
141
|
+
var terms = split( this.value );
|
142
|
+
// remove the current input
|
143
|
+
terms.pop();
|
144
|
+
// add the selected item
|
145
|
+
terms.push( ui.item.value );
|
146
|
+
// add placeholder to get the comma-and-space at the end
|
147
|
+
if (e.delimiter != null) {
|
148
|
+
terms.push( "" );
|
149
|
+
this.value = terms.join( e.delimiter );
|
150
|
+
} else {
|
151
|
+
this.value = terms.join("");
|
152
|
+
if (jQuery(this).attr('data-id-element')) {
|
153
|
+
jQuery(jQuery(this).attr('data-id-element')).val(ui.item.id).trigger('change');
|
154
|
+
}
|
155
|
+
if (jQuery(this).attr('data-update-elements')) {
|
156
|
+
var data = ui.item;
|
157
|
+
var new_record = ui.item.value.indexOf('Create New') != -1 ? true : false;
|
158
|
+
var update_elements = jQuery.parseJSON(jQuery(this).attr("data-update-elements"));
|
159
|
+
for (var key in update_elements) {
|
160
|
+
if(jQuery(update_elements[key]).attr("type") === "checkbox"){
|
161
|
+
if(data[key] === true || data[key] === 1) {
|
162
|
+
jQuery(update_elements[key]).attr("checked","checked");
|
163
|
+
}
|
164
|
+
else {
|
165
|
+
jQuery(update_elements[key]).removeAttr("checked");
|
166
|
+
}
|
167
|
+
}
|
168
|
+
else{
|
169
|
+
if((new_record && data[key] && data[key].indexOf('Create New') == -1) || !new_record){
|
170
|
+
jQuery(update_elements[key]).val(data[key]).trigger('change');
|
171
|
+
}else{
|
172
|
+
jQuery(update_elements[key]).val('').trigger('change');
|
173
|
+
}
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
}
|
178
|
+
var remember_string = this.value;
|
179
|
+
jQuery(this).bind('keyup.clearId', function(){
|
180
|
+
if(jQuery.trim(jQuery(this).val()) != jQuery.trim(remember_string)){
|
181
|
+
jQuery(jQuery(this).attr('data-id-element')).val("").trigger('change');
|
182
|
+
jQuery(this).unbind('keyup.clearId');
|
183
|
+
}
|
184
|
+
});
|
185
|
+
jQuery(e).trigger('railsAutocomplete.select', ui);
|
186
|
+
|
187
|
+
return false;
|
188
|
+
}
|
189
|
+
});
|
190
|
+
jQuery(e).trigger('railsAutocomplete.init');
|
191
|
+
}
|
192
|
+
});
|
193
|
+
|
194
|
+
jQuery(document).ready(function(){
|
195
|
+
jQuery('input[data-autocomplete]').railsAutocomplete('input[data-autocomplete]');
|
196
|
+
});
|
197
|
+
})(jQuery);
|
@@ -0,0 +1 @@
|
|
1
|
+
!function(t){t.fn.railsAutocomplete=function(e){var a=function(){this.railsAutoCompleter||(this.railsAutoCompleter=new t.railsAutocomplete(this))};if(void 0!==t.fn.on){if(!e)return;return t(document).on("focus",e,a)}return this.live("focus",a)},t.railsAutocomplete=function(t){var e=t;this.init(e)},t.railsAutocomplete.options={showNoMatches:!0,noMatchesLabel:"no existing match"},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("data-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,r){var n=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(){var a={};t.extend(a,t.railsAutocomplete.options),t.each(a,function(i,r){if(a.hasOwnProperty(i)){var n=t(e).attr("data-"+i);a[i]=n?n:r}}),0==arguments[0].length&&t.inArray(a.showNoMatches,[!0,"true"])>=0&&(arguments[0]=[],arguments[0][0]={id:"",label:a.noMatchesLabel}),t(arguments[0]).each(function(a,i){var r={};r[i.id]=i,t(e).data(r)}),r.apply(null,arguments),t(n).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:"").trigger("change"),t(this).attr("data-update-elements"))){var i=t.parseJSON(t(this).attr("data-update-elements")),r=a.item?t(this).data(a.item.id.toString()):{};if(i&&""===t(i.id).val())return;for(var n in i){var o=t(i[n]);o.is(":checkbox")?null!=r[n]&&o.prop("checked",r[n]):o.val(a.item?r[n]:"").trigger("change")}}},search:function(){var t=i(this.value);return t.length<e.min_length?!1:void 0},focus:function(){return!1},select:function(i,r){if(r.item.value=r.item.value.toString(),-1!=r.item.value.toLowerCase().indexOf("no match")||-1!=r.item.value.toLowerCase().indexOf("too many results"))return t(this).trigger("railsAutocomplete.noMatch",r),!1;var n=a(this.value);if(n.pop(),n.push(r.item.value),null!=e.delimiter)n.push(""),this.value=n.join(e.delimiter);else if(this.value=n.join(""),t(this).attr("data-id-element")&&t(t(this).attr("data-id-element")).val(r.item.id).trigger("change"),t(this).attr("data-update-elements")){var o=r.item,l=-1!=r.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"):l&&o[s]&&-1==o[s].indexOf("Create New")||!l?t(u[s]).val(o[s]).trigger("change"):t(u[s]).val("").trigger("change")}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("").trigger("change"),t(this).unbind("keyup.clearId"))}),t(e).trigger("railsAutocomplete.select",r),!1}}),t(e).trigger("railsAutocomplete.init")}}),t(document).ready(function(){t("input[data-autocomplete]").railsAutocomplete("input[data-autocomplete]")})}(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,112 @@
|
|
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
|
+
'active_record'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
define_method("get_autocomplete_order") do |method, options, model=nil|
|
50
|
+
method("#{get_prefix(get_object(options[:class_name] || object))}_get_autocomplete_order").call(method, options, model)
|
51
|
+
end
|
52
|
+
|
53
|
+
define_method("get_autocomplete_items") do |parameters|
|
54
|
+
method("#{get_prefix(get_object(options[:class_name] || object))}_get_autocomplete_items").call(parameters)
|
55
|
+
end
|
56
|
+
|
57
|
+
define_method("autocomplete_#{object}_#{method}") do
|
58
|
+
method = options[:column_name] if options.has_key?(:column_name)
|
59
|
+
|
60
|
+
term = params[:term]
|
61
|
+
|
62
|
+
if term && !term.blank?
|
63
|
+
#allow specifying fully qualified class name for model object
|
64
|
+
class_name = options[:class_name] || object
|
65
|
+
items = get_autocomplete_items(:model => get_object(class_name), \
|
66
|
+
:options => options, :term => term, :method => method)
|
67
|
+
else
|
68
|
+
items = {}
|
69
|
+
end
|
70
|
+
|
71
|
+
render :json => json_for_autocomplete(items, options[:display_value] ||= method, options[:extra_data], &block), root: false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns a limit that will be used on the query
|
77
|
+
def get_autocomplete_limit(options)
|
78
|
+
options[:limit] ||= 10
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns parameter model_sym as a constant
|
82
|
+
#
|
83
|
+
# get_object(:actor)
|
84
|
+
# # returns a Actor constant supposing it is already defined
|
85
|
+
#
|
86
|
+
def get_object(model_sym)
|
87
|
+
model_sym.to_s.camelize.constantize
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Returns a hash with three keys actually used by the Autocomplete jQuery-ui
|
92
|
+
# Can be overriden to show whatever you like
|
93
|
+
# Hash also includes a key/value pair for each method in extra_data
|
94
|
+
#
|
95
|
+
def json_for_autocomplete(items, method, extra_data=[])
|
96
|
+
items = items.collect do |item|
|
97
|
+
hash = HashWithIndifferentAccess.new({"id" => item.id.to_s, "label" => item.send(method), "value" => item.send(method)})
|
98
|
+
extra_data.each do |datum|
|
99
|
+
hash[datum] = item.send(datum)
|
100
|
+
end if extra_data
|
101
|
+
# TODO: Come back to remove this if clause when test suite is better
|
102
|
+
hash
|
103
|
+
end
|
104
|
+
if block_given?
|
105
|
+
yield(items)
|
106
|
+
else
|
107
|
+
items
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
@@ -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
|