repeated_auto_complete 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +21 -0
- data/README +102 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/init.rb +3 -0
- data/lib/auto_complete.rb +49 -0
- data/lib/auto_complete_form_builder_helper.rb +38 -0
- data/lib/auto_complete_macros_helper.rb +152 -0
- data/lib/repeated_auto_complete.rb +4 -0
- data/lib/view_mapper/README +4 -0
- data/lib/view_mapper/has_many_auto_complete_view.rb +88 -0
- data/lib/view_mapper/templates/controller.rb +90 -0
- data/lib/view_mapper/templates/layout.html.erb +19 -0
- data/lib/view_mapper/templates/style.css +82 -0
- data/lib/view_mapper/templates/view_child_form.html.erb +16 -0
- data/lib/view_mapper/templates/view_form.html.erb +24 -0
- data/rails/init.rb +3 -0
- data/repeated_auto_complete.gemspec +78 -0
- data/test/auto_complete_form_builder_helper_test.rb +123 -0
- data/test/auto_complete_nested_attributes_test.rb +143 -0
- data/test/auto_complete_test.rb +136 -0
- data/test/helper.rb +14 -0
- data/test/view_mapper/expected_templates/_form.html.erb +26 -0
- data/test/view_mapper/expected_templates/_person.html.erb +22 -0
- data/test/view_mapper/expected_templates/create_parents.rb +16 -0
- data/test/view_mapper/expected_templates/edit.html.erb +11 -0
- data/test/view_mapper/expected_templates/index.html.erb +20 -0
- data/test/view_mapper/expected_templates/new.html.erb +10 -0
- data/test/view_mapper/expected_templates/parent.rb +15 -0
- data/test/view_mapper/expected_templates/show.html.erb +37 -0
- data/test/view_mapper/expected_templates/testies_controller.rb +92 -0
- data/test/view_mapper/has_many_auto_complete_view_test.rb +587 -0
- metadata +93 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
class <%= controller_class_name %>Controller < ApplicationController
|
2
|
+
|
3
|
+
<% auto_complete_attributes.each do |attrib| -%>
|
4
|
+
auto_complete_for :<%= attrib[:model_name] %>, :<%= attrib[:text_field] %>
|
5
|
+
<% end -%>
|
6
|
+
|
7
|
+
# GET /<%= table_name %>
|
8
|
+
# GET /<%= table_name %>.xml
|
9
|
+
def index
|
10
|
+
@<%= table_name %> = <%= class_name %>.all
|
11
|
+
|
12
|
+
respond_to do |format|
|
13
|
+
format.html # index.html.erb
|
14
|
+
format.xml { render :xml => @<%= table_name %> }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# GET /<%= table_name %>/1
|
19
|
+
# GET /<%= table_name %>/1.xml
|
20
|
+
def show
|
21
|
+
@<%= file_name %> = <%= class_name %>.find(params[:id])
|
22
|
+
|
23
|
+
respond_to do |format|
|
24
|
+
format.html # show.html.erb
|
25
|
+
format.xml { render :xml => @<%= file_name %> }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# GET /<%= table_name %>/new
|
30
|
+
# GET /<%= table_name %>/new.xml
|
31
|
+
def new
|
32
|
+
@<%= file_name %> = <%= class_name %>.new
|
33
|
+
|
34
|
+
respond_to do |format|
|
35
|
+
format.html # new.html.erb
|
36
|
+
format.xml { render :xml => @<%= file_name %> }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# GET /<%= table_name %>/1/edit
|
41
|
+
def edit
|
42
|
+
@<%= file_name %> = <%= class_name %>.find(params[:id])
|
43
|
+
end
|
44
|
+
|
45
|
+
# POST /<%= table_name %>
|
46
|
+
# POST /<%= table_name %>.xml
|
47
|
+
def create
|
48
|
+
@<%= file_name %> = <%= class_name %>.new(params[:<%= file_name %>])
|
49
|
+
|
50
|
+
respond_to do |format|
|
51
|
+
if @<%= file_name %>.save
|
52
|
+
flash[:notice] = '<%= class_name %> was successfully created.'
|
53
|
+
format.html { redirect_to(@<%= file_name %>) }
|
54
|
+
format.xml { render :xml => @<%= file_name %>, :status => :created, :location => @<%= file_name %> }
|
55
|
+
else
|
56
|
+
format.html { render :action => "new" }
|
57
|
+
format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# PUT /<%= table_name %>/1
|
63
|
+
# PUT /<%= table_name %>/1.xml
|
64
|
+
def update
|
65
|
+
@<%= file_name %> = <%= class_name %>.find(params[:id])
|
66
|
+
|
67
|
+
respond_to do |format|
|
68
|
+
if @<%= file_name %>.update_attributes(params[:<%= file_name %>])
|
69
|
+
flash[:notice] = '<%= class_name %> was successfully updated.'
|
70
|
+
format.html { redirect_to(@<%= file_name %>) }
|
71
|
+
format.xml { head :ok }
|
72
|
+
else
|
73
|
+
format.html { render :action => "edit" }
|
74
|
+
format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# DELETE /<%= table_name %>/1
|
80
|
+
# DELETE /<%= table_name %>/1.xml
|
81
|
+
def destroy
|
82
|
+
@<%= file_name %> = <%= class_name %>.find(params[:id])
|
83
|
+
@<%= file_name %>.destroy
|
84
|
+
|
85
|
+
respond_to do |format|
|
86
|
+
format.html { redirect_to(<%= table_name %>_url) }
|
87
|
+
format.xml { head :ok }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
|
7
|
+
<title><%= controller_class_name %>: <%%= controller.action_name %></title>
|
8
|
+
<%%= stylesheet_link_tag 'scaffold' %>
|
9
|
+
<%%= javascript_include_tag :defaults %>
|
10
|
+
<%%= javascript_include_tag 'nested_attributes.js' %>
|
11
|
+
</head>
|
12
|
+
<body>
|
13
|
+
|
14
|
+
<p style="color: green"><%%= flash[:notice] %></p>
|
15
|
+
|
16
|
+
<%%= yield %>
|
17
|
+
|
18
|
+
</body>
|
19
|
+
</html>
|
@@ -0,0 +1,82 @@
|
|
1
|
+
body { background-color: #fff; color: #333; }
|
2
|
+
|
3
|
+
body, p, ol, ul, td {
|
4
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
5
|
+
font-size: 13px;
|
6
|
+
line-height: 18px;
|
7
|
+
}
|
8
|
+
|
9
|
+
pre {
|
10
|
+
background-color: #eee;
|
11
|
+
padding: 10px;
|
12
|
+
font-size: 11px;
|
13
|
+
}
|
14
|
+
|
15
|
+
a { color: #000; }
|
16
|
+
a:visited { color: #666; }
|
17
|
+
a:hover { color: #fff; background-color:#000; }
|
18
|
+
|
19
|
+
.fieldWithErrors {
|
20
|
+
padding: 2px;
|
21
|
+
background-color: red;
|
22
|
+
display: table;
|
23
|
+
}
|
24
|
+
|
25
|
+
#errorExplanation {
|
26
|
+
width: 400px;
|
27
|
+
border: 2px solid red;
|
28
|
+
padding: 7px;
|
29
|
+
padding-bottom: 12px;
|
30
|
+
margin-bottom: 20px;
|
31
|
+
background-color: #f0f0f0;
|
32
|
+
}
|
33
|
+
|
34
|
+
#errorExplanation h2 {
|
35
|
+
text-align: left;
|
36
|
+
font-weight: bold;
|
37
|
+
padding: 5px 5px 5px 15px;
|
38
|
+
font-size: 12px;
|
39
|
+
margin: -7px;
|
40
|
+
background-color: #c00;
|
41
|
+
color: #fff;
|
42
|
+
}
|
43
|
+
|
44
|
+
#errorExplanation p {
|
45
|
+
color: #333;
|
46
|
+
margin-bottom: 0;
|
47
|
+
padding: 5px;
|
48
|
+
}
|
49
|
+
|
50
|
+
#errorExplanation ul li {
|
51
|
+
font-size: 12px;
|
52
|
+
list-style: square;
|
53
|
+
}
|
54
|
+
|
55
|
+
.child {
|
56
|
+
border-left: 10px solid #eee;
|
57
|
+
padding-left:10px;
|
58
|
+
}
|
59
|
+
|
60
|
+
div.auto_complete {
|
61
|
+
width: 350px;
|
62
|
+
background: #fff;
|
63
|
+
}
|
64
|
+
div.auto_complete ul {
|
65
|
+
border:1px solid #888;
|
66
|
+
margin:0;
|
67
|
+
padding:0;
|
68
|
+
width:100%;
|
69
|
+
list-style-type:none;
|
70
|
+
}
|
71
|
+
div.auto_complete ul li {
|
72
|
+
margin:0;
|
73
|
+
padding:3px;
|
74
|
+
}
|
75
|
+
div.auto_complete ul li.selected {
|
76
|
+
background-color: #ffb;
|
77
|
+
}
|
78
|
+
div.auto_complete ul strong.highlight {
|
79
|
+
color: #800;
|
80
|
+
margin:0;
|
81
|
+
padding:0;
|
82
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<div class="child">
|
2
|
+
<% for attribute in child_model.attributes -%>
|
3
|
+
<p>
|
4
|
+
<%= child_model.name %> <%%= f.label :<%= attribute.name %> %><br />
|
5
|
+
<%- if is_auto_complete_attribute? child_model.name.downcase, attribute.name -%>
|
6
|
+
<%%= f.text_field_with_auto_complete :<%= attribute.name %>, {}, { :method => :get, :skip_style => true } %>
|
7
|
+
<%- else -%>
|
8
|
+
<%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
|
9
|
+
<%- end -%>
|
10
|
+
</p>
|
11
|
+
<% end -%>
|
12
|
+
<p>
|
13
|
+
<%%= f.hidden_field :_delete, :class => 'delete' %>
|
14
|
+
<%%= remove_child_link 'remove', f %>
|
15
|
+
</p>
|
16
|
+
</div>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<%%= f.error_messages %>
|
2
|
+
<% for attribute in attributes -%>
|
3
|
+
|
4
|
+
<p>
|
5
|
+
<%%= f.label :<%= attribute.name %> %><br />
|
6
|
+
<%- if is_auto_complete_attribute? singular_name, attribute.name -%>
|
7
|
+
<%%= f.text_field_with_auto_complete :<%= attribute.name %>, {}, { :method => :get, :skip_style => true } %>
|
8
|
+
<%- else -%>
|
9
|
+
<%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
|
10
|
+
<%- end -%>
|
11
|
+
</p>
|
12
|
+
<% end -%>
|
13
|
+
<% child_models.each do |child_model| -%>
|
14
|
+
|
15
|
+
<div id='<%= child_model.name.underscore %>_children'>
|
16
|
+
<%% f.fields_for :<%= child_model.name.underscore.pluralize %> do |<%= child_model.name.underscore %>_form| %>
|
17
|
+
<%%= render :partial => '<%= child_model.name.underscore %>', :locals => { :f => <%= child_model.name.underscore %>_form } %>
|
18
|
+
<%% end %>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<p>
|
22
|
+
<%%= add_child_link 'Add a <%= child_model.name %>', '<%= child_model.name.underscore %>', f %>
|
23
|
+
</p>
|
24
|
+
<% end -%>
|
data/rails/init.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{repeated_auto_complete}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Pat Shaughnessy"]
|
12
|
+
s.date = %q{2009-11-25}
|
13
|
+
s.description = %q{auto_complete plugin refactored to handle complex forms and named scopes}
|
14
|
+
s.email = %q{pat@patshaughnessy.net}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"README",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"init.rb",
|
24
|
+
"lib/auto_complete.rb",
|
25
|
+
"lib/auto_complete_form_builder_helper.rb",
|
26
|
+
"lib/auto_complete_macros_helper.rb",
|
27
|
+
"lib/repeated_auto_complete.rb",
|
28
|
+
"lib/view_mapper/README",
|
29
|
+
"lib/view_mapper/has_many_auto_complete_view.rb",
|
30
|
+
"lib/view_mapper/templates/controller.rb",
|
31
|
+
"lib/view_mapper/templates/layout.html.erb",
|
32
|
+
"lib/view_mapper/templates/style.css",
|
33
|
+
"lib/view_mapper/templates/view_child_form.html.erb",
|
34
|
+
"lib/view_mapper/templates/view_form.html.erb",
|
35
|
+
"rails/init.rb",
|
36
|
+
"repeated_auto_complete.gemspec",
|
37
|
+
"test/auto_complete_form_builder_helper_test.rb",
|
38
|
+
"test/auto_complete_nested_attributes_test.rb",
|
39
|
+
"test/auto_complete_test.rb",
|
40
|
+
"test/helper.rb",
|
41
|
+
"test/view_mapper/expected_templates/_form.html.erb",
|
42
|
+
"test/view_mapper/expected_templates/_person.html.erb",
|
43
|
+
"test/view_mapper/expected_templates/create_parents.rb",
|
44
|
+
"test/view_mapper/expected_templates/edit.html.erb",
|
45
|
+
"test/view_mapper/expected_templates/index.html.erb",
|
46
|
+
"test/view_mapper/expected_templates/new.html.erb",
|
47
|
+
"test/view_mapper/expected_templates/parent.rb",
|
48
|
+
"test/view_mapper/expected_templates/show.html.erb",
|
49
|
+
"test/view_mapper/expected_templates/testies_controller.rb",
|
50
|
+
"test/view_mapper/has_many_auto_complete_view_test.rb"
|
51
|
+
]
|
52
|
+
s.homepage = %q{http://patshaughnessy.net/repeated_auto_complete}
|
53
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
54
|
+
s.require_paths = ["lib"]
|
55
|
+
s.rubygems_version = %q{1.3.5}
|
56
|
+
s.summary = %q{auto_complete plugin refactored to handle complex forms and named scopes}
|
57
|
+
s.test_files = [
|
58
|
+
"test/auto_complete_form_builder_helper_test.rb",
|
59
|
+
"test/auto_complete_nested_attributes_test.rb",
|
60
|
+
"test/auto_complete_test.rb",
|
61
|
+
"test/helper.rb",
|
62
|
+
"test/view_mapper/expected_templates/create_parents.rb",
|
63
|
+
"test/view_mapper/expected_templates/parent.rb",
|
64
|
+
"test/view_mapper/expected_templates/testies_controller.rb",
|
65
|
+
"test/view_mapper/has_many_auto_complete_view_test.rb"
|
66
|
+
]
|
67
|
+
|
68
|
+
if s.respond_to? :specification_version then
|
69
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
70
|
+
s.specification_version = 3
|
71
|
+
|
72
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
73
|
+
else
|
74
|
+
end
|
75
|
+
else
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class Person
|
4
|
+
attr_accessor :name, :id
|
5
|
+
def initialize name, id = nil
|
6
|
+
@name, @id = name, id
|
7
|
+
end
|
8
|
+
def to_param
|
9
|
+
id.to_s
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class AutoCompleteFormBuilderHelperTest < Test::Unit::TestCase
|
14
|
+
|
15
|
+
include AutoCompleteMacrosHelper
|
16
|
+
include ActionView::Helpers::UrlHelper
|
17
|
+
include ActionView::Helpers::TagHelper
|
18
|
+
include ActionView::Helpers::FormHelper
|
19
|
+
|
20
|
+
def setup
|
21
|
+
|
22
|
+
@existing_person = Person.new "Existing Person", 1234
|
23
|
+
@person = Person.new "New Person"
|
24
|
+
|
25
|
+
controller_class = Class.new do
|
26
|
+
def url_for(options)
|
27
|
+
url = "http://www.example.com/"
|
28
|
+
url << options[:action].to_s if options and options[:action]
|
29
|
+
url
|
30
|
+
end
|
31
|
+
end
|
32
|
+
@controller = controller_class.new
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_two_auto_complete_fields_have_different_ids
|
37
|
+
id_attribute_pattern = /id=\"[^\"]*\"/i
|
38
|
+
_erbout = ''
|
39
|
+
_erbout2 = ''
|
40
|
+
fields_for('group[person_attributes][]', @person) do |f|
|
41
|
+
_erbout.concat f.text_field_with_auto_complete(:name)
|
42
|
+
_erbout2.concat f.text_field_with_auto_complete(:name)
|
43
|
+
end
|
44
|
+
assert_equal [], _erbout.scan(id_attribute_pattern) & _erbout2.scan(id_attribute_pattern)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_compare_macro_to_fields_for
|
48
|
+
standard_auto_complete_html = text_field_with_auto_complete(:person, :name)
|
49
|
+
|
50
|
+
_erbout = ''
|
51
|
+
fields_for('group[person_attributes][]', @person) do |f|
|
52
|
+
_erbout.concat f.text_field_with_auto_complete(:name)
|
53
|
+
end
|
54
|
+
|
55
|
+
assert_equal standard_auto_complete_html,
|
56
|
+
_erbout.gsub(/group\[person_attributes\]\[\]/, 'person').gsub(/person_[0-9]+_name/, 'person_name').gsub(/paramName:'person\[name\]'/, '')
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_ajax_url
|
60
|
+
_erbout = ''
|
61
|
+
fields_for('group[person_attributes][]', @person) do |f|
|
62
|
+
_erbout.concat f.text_field_with_auto_complete(:name)
|
63
|
+
end
|
64
|
+
assert _erbout.index('http://www.example.com/auto_complete_for_person_name')
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_ajax_param
|
68
|
+
_erbout = ''
|
69
|
+
fields_for('group[person_attributes][]', @person) do |f|
|
70
|
+
_erbout.concat f.text_field_with_auto_complete(:name)
|
71
|
+
end
|
72
|
+
assert _erbout.index("{paramName:'person[name]'}")
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_object_value
|
76
|
+
_erbout = ''
|
77
|
+
fields_for('group[person_attributes][]', @existing_person) do |f|
|
78
|
+
_erbout.concat f.text_field_with_auto_complete(:name)
|
79
|
+
end
|
80
|
+
assert _erbout.index('value="Existing Person"')
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_auto_index_value_for_existing_record
|
84
|
+
_erbout = ''
|
85
|
+
fields_for('group[person_attributes][]', @existing_person) do |f|
|
86
|
+
_erbout.concat f.text_field_with_auto_complete(:name)
|
87
|
+
end
|
88
|
+
assert _erbout.index("[1234]")
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_auto_index_value_for_new_record
|
92
|
+
_erbout = ''
|
93
|
+
fields_for('group[person_attributes][]', @person) do |f|
|
94
|
+
_erbout.concat f.text_field_with_auto_complete(:name)
|
95
|
+
end
|
96
|
+
assert _erbout.index("[]")
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_child_index_fields_for_option
|
100
|
+
_erbout = ''
|
101
|
+
fields_for 'group[person_attributes][]', @person, { :child_index => 5678 } do |f|
|
102
|
+
_erbout.concat f.text_field_with_auto_complete(:name, {}, { :method => :get })
|
103
|
+
assert _erbout.index('person_5678_name')
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_child_index_completion_option
|
108
|
+
_erbout = ''
|
109
|
+
fields_for('group[person_attributes][]', @person) do |f|
|
110
|
+
_erbout.concat f.text_field_with_auto_complete(:name, {}, { :method => :get, :child_index => 1234 })
|
111
|
+
assert _erbout.index('person_1234_name')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_child_index_completion_option_overrides_fields_for_option
|
116
|
+
_erbout = ''
|
117
|
+
fields_for('group[person_attributes][]', @person, { :child_index => 5678 }) do |f|
|
118
|
+
_erbout.concat f.text_field_with_auto_complete(:name, {}, { :method => :get, :child_index => 1234 })
|
119
|
+
assert _erbout.index('person_1234_name')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|