4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
# File 'lib/formtastic_jquery_ui/autocomplete.rb', line 4
def autocomplete_input(method, options)
html_options = options.delete(:input_html) || {}
options = set_include_blank(options)
html_options[:multiple] = html_options[:multiple] || options.delete(:multiple)
html_options.delete(:multiple) if html_options[:multiple].nil?
autocomplete_options = options.delete(:autocomplete) || {}
autocomplete_option_min_length = autocomplete_options[:min_length] || 2
autocomplete_option_min_length_js = "minLength: #{autocomplete_option_min_length},"
html = ""
reflection = self.reflection_for(method)
input_name = "autocomplete_for_#{sanitized_object_name}_#{method}"
param_name = options[:param_name] || 'term'
url = options[:url] || ''
if reflection && [:has_many, :has_and_belongs_to_many].include?(reflection.macro)
selections_name = generate_html_id(method, 'selections')
selection_name = "#{sanitized_object_name}[#{method.to_s.singularize}_ids][]"
html << template.content_tag(:ul, object.send(method).map { |i| template.content_tag(:li, "<input type=\"hidden\" name=\"#{selection_name}\" value=\"#{i.id}\" />#{i.to_label} <a href=\"#\" onclick=\"$(this).closest('li').remove(); return false;\">Remove</a>".html_safe) }.join.html_safe, :id => selections_name)
html << template.tag(:input, :type => 'hidden', :name => selection_name, :value => '')
html << template.text_field_tag(input_name)
autocomplete_js = <<-EOT
<script type="text/javascript">
$('##{input_name}').autocomplete({
source: function(request, response) {
$.ajax({
url: '#{url}',
dataType: 'json',
data: {
search: { #{param_name}: request.term }
},
success: function(data) {
response(data);
}
});
},
#{autocomplete_option_min_length_js}
select: function(event, selection) {
if($('##{selections_name} input[value=' + selection.item.value + ']').length == 0)
$('##{selections_name}').append('<li><input type="hidden" name="#{selection_name}" value="' + selection.item.value + '" />' + selection.item.label + ' <a href="#" onclick="$(this).closest(\\'li\\').remove(); return false;">Remove</a></li>');
$('##{input_name}').val('');
return false;
},
focus: function(event, ui) { return false; }
});
</script>
EOT
html << autocomplete_js.html_safe
elsif (reflection && [:belongs_to].include?(reflection.macro)) || reflection.nil?
hidden_field_name = reflection.try(:primary_key_name) || "#{method}_id"
html << self.hidden_field(hidden_field_name)
html << template.text_field_tag(input_name, object.send(method).try(detect_label_method([object.send(method)])))
html << template.content_tag(:script, :type => 'text/javascript') do
<<-EOT
$('##{input_name}').autocomplete({
source: function(request, response) {
$.ajax({
url: '#{url}',
dataType: 'json',
data: {
search: { #{param_name}: request.term }
},
success: function(data) {
response(data);
}
});
},
#{autocomplete_option_min_length_js}
select: function(event, selection) {
$('##{sanitized_object_name}_#{hidden_field_name}').val(selection.item.value);
$('##{input_name}').val(selection.item.label);
return false;
},
focus: function(event, ui) { return false; }
});
$('##{input_name}').blur(function(event){
if($(this).val() == '')
$('##{sanitized_object_name}_#{hidden_field_name}').val('');
})
EOT
end
end
template.content_tag(:label, localized_string(method, options[:label].is_a?(::String) ? options[:label] : nil, :label) || humanized_attribute_name(method), :for => input_name) << Formtastic::Util.html_safe(html)
end
|