Skip to content

Commit e34172a

Browse files
committed
Reworked client code and JS API
1 parent 43a5616 commit e34172a

File tree

12 files changed

+115
-68
lines changed

12 files changed

+115
-68
lines changed

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ Active Form comes with two helpers to deal with this functionality:
242242
1. `link_to_add_association` will display a link that renders fields to create a new object.
243243
2. `link_to_remove_association` will display a link to remove a existing/dynamic object.
244244

245-
In order to use it you have to insert this line: `//= require link_helpers` to your `app/assets/javascript/application.js` file.
245+
In order to use it you have to insert this line: `//= require activeform` to your `app/assets/javascript/application.js` file.
246246

247247
In our `ConferenceForm` we can dynamically create/remove `Speaker` objects. To do that we would write in the `app/views/conferences/_form.html.erb` partial:
248248

@@ -271,12 +271,16 @@ In our `ConferenceForm` we can dynamically create/remove `Speaker` objects. To d
271271
</div>
272272
273273
<h2>Speaker Details</h2>
274-
<%= f.fields_for :speakers do |speaker_fields| %>
275-
<%= render "speaker_fields", :f => speaker_fields %>
276-
<% end %>
274+
275+
<%= render_association_template f, :speakers %>
276+
<div class="speakers_list">
277+
<%= f.fields_for :speakers do |speaker_fields| %>
278+
<%= render "speaker_fields", :f => speaker_fields %>
279+
<% end %>
280+
</div>
277281
278282
<div class="links">
279-
<%= link_to_add_association "Add a Speaker", f, :speakers %>
283+
<%= link_to_add_association "Add a Speaker", f, :speakers, data: { "association-insertion-node" => ".speakers_list" } %>
280284
</div>
281285
282286
<div class="actions">

app/assets/javascripts/link_helpers.js renamed to app/assets/javascripts/activeform.js

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,41 @@
11
(function($) {
2+
// Form API, draft version:
3+
// $(".task_list").addFormField("tasks")
4+
// $(".task_list").removeFormField("tasks", 2) // destroy second field
5+
26
var activeFormHelpers = {
37
generateResourceId: function() {
48
return new Date().getTime();
5-
},
6-
decodeHtml: function(input){
7-
var e = document.createElement('div');
8-
e.innerHTML = input;
9-
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
10-
},
9+
}
1110
};
1211

13-
$.fn.removeFormField = function(nodeToDelete) {
14-
// maybe nodeToDelete could be field index
12+
$.fn.removeFormField = function(nodeToDeleteOrIndex, options) {
13+
if(options == undefined) {
14+
options = {}
15+
}
16+
17+
var nodeToDelete;
18+
19+
if(nodeToDeleteOrIndex instanceof jQuery) {
20+
nodeToDelete = nodeToDeleteOrIndex;
21+
} else {
22+
var wrapperClass = this.data('wrapper-class') || 'nested-fields';
23+
console.log(wrapperClass)
24+
nodeToDelete = this.find("." + wrapperClass).filter(function(i, b) {
25+
return $(b).css('display') != 'none';
26+
}).eq(nodeToDeleteOrIndex);
27+
}
1528

1629
this.trigger('before-remove', [nodeToDelete]);
1730

1831
var timeout = this.data('remove-timeout') || 0;
1932

20-
console.log(nodeToDelete)
2133
var input = nodeToDelete.find("input").filter(function(i, t) {
22-
console.log(t, $(t).attr("name"))
2334
return false
2435
})
2536

37+
var isDynamic = nodeToDelete.hasClass("dynamic");
38+
2639
var context = this;
2740
setTimeout(function() {
2841
if (isDynamic) {
@@ -41,20 +54,26 @@
4154
if(options == undefined) {
4255
options = {}
4356
}
44-
var selector = "." + assoc + "_template";
45-
var contentTemplate = this.find(selector)
46-
47-
if(contentTemplate.length == 0) {
48-
contentTemplate = this.siblings().filter(selector)
49-
}
57+
var templateSelector = "." + assoc + "_template";
58+
59+
var templateContainer;
60+
$(this).parents().each(function(i, el){
61+
var found = $(el).find(templateSelector)
62+
if(found.length > 0) {
63+
templateContainer = found.eq(0)
64+
return false;
65+
}
66+
})
5067

5168
var newId = activeFormHelpers.generateResourceId();
5269
var regex = new RegExp("new_" + assoc, "g");
53-
var content = contentTemplate.text().replace(regex, newId);
54-
var contentNode = $(activeFormHelpers.decodeHtml(content));
70+
var content = templateContainer.html().replace(regex, newId);
71+
var contentNode = $(content);
72+
73+
contentNode.addClass("dynamic")
5574

5675
if(!options.insertionMethod) {
57-
options.insertionMethod = 'before';
76+
options.insertionMethod = 'append';
5877
}
5978

6079
this.trigger('before-insert', [contentNode]);
@@ -80,7 +99,17 @@
8099
if (insertionTraversal){
81100
insertionNode = $link[insertionTraversal](insertionNode);
82101
} else {
83-
insertionNode = insertionNode == "this" ? $link : $(insertionNode);
102+
if(insertionNode == "this") {
103+
insertionNode = $(this)
104+
} else {
105+
$(this).parents().each(function(i, el){
106+
var found = $(el).find(insertionNode)
107+
if(found.length > 0) {
108+
insertionNode = found.eq(0)
109+
return false;
110+
}
111+
})
112+
}
84113
}
85114
} else {
86115
insertionNode = $link.parent();
@@ -92,7 +121,7 @@
92121
})
93122
});
94123

95-
$(document).on('click', '.remove_fields.dynamic, .remove_fields.existing', function(e) {
124+
$(document).on('click', '.remove_fields, .remove_fields', function(e) {
96125
e.preventDefault();
97126

98127
var $link = $(this);
@@ -101,7 +130,7 @@
101130

102131
var triggerNode = nodeToDelete.parent();
103132

104-
triggerNode.removeFormField(nodeToDelete, $link.hasClass('dynamic'))
133+
triggerNode.removeFormField(nodeToDelete)
105134
});
106135

107136
})(jQuery);

lib/active_form.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class Engine < ::Rails::Engine
1010

1111
config.before_initialize do
1212
if config.action_view.javascript_expansions
13-
config.action_view.javascript_expansions[:link_helpers] = %w(link_helpers)
13+
config.action_view.javascript_expansions[:activeform] = %w(activeform)
1414
end
1515
end
1616

lib/active_form/view_helpers.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ def render_association_template(f, association, html_options={})
4848
override_partial = html_options.delete(:partial)
4949
new_object = create_object(f, association)
5050

51-
content_tag :script, class: "association_template #{association}_template", type: "text/plain" do
52-
CGI.escapeHTML(render_association(association, f, new_object, render_options, override_partial)).html_safe
51+
content_tag :template, class: "association_template #{association}_template" do
52+
render_association(association, f, new_object, render_options, override_partial)
5353
end
5454
end
5555

lib/rails/generators/form/form_install_generator.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def create_forms_test_directory
2020
end
2121

2222
def include_js_file
23-
insert_into_file "app/assets/javascripts/application.js", "//= require link_helpers", :before => "//= require_tree ."
23+
insert_into_file "app/assets/javascripts/application.js", "//= require activeform", :before => "//= require_tree ."
2424
end
2525
end
2626
end

test/dummy/.ruby-version

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/dummy/app/assets/javascripts/application.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@
1212
//
1313
//= require jquery
1414
//= require jquery_ujs
15-
//= require link_helpers
15+
//= require activeform
1616
//= require_tree .

test/dummy/app/views/assignments/_form.html.erb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@
1818

1919
<h2>Tasks Details</h2>
2020

21-
<div class="tasks_container">
21+
<%= render_association_template(f, :tasks) %>
22+
<div class="task_list">
2223
<%= f.fields_for :tasks do |task_fields| %>
2324
<%= render "task_fields", :f => task_fields %>
2425
<% end %>
25-
<%= render_association_template(f, :tasks) %>
2626
</div>
2727

28-
<!-- $(".tasks_container").addFormField("tasks", {insertionMethod: 'after'}) -->
29-
<!-- $(".tasks_container").removeFormField("tasks", $(".nested-fields").eq(3)) -->
28+
<div class="links">
29+
<%= link_to_add_association "Add a Task", f, :tasks, { data: {"association-insertion-node" => ".task_list"} } %>
30+
</div>
31+
32+
<!-- $(".task_list").addFormField("tasks") -->
33+
<!-- $(".task_list").removeFormField("tasks", 2) -->
3034

3135
<div class="actions">
3236
<%= f.submit %>

test/dummy/app/views/assignments/_task_fields.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
<%= f.text_field :name %>
55
<%= link_to_remove_association "Delete", f %>
66
</div>
7-
</div>
7+
</div>

test/dummy/app/views/conferences/_speaker.html.erb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99
</div>
1010

1111
<h2>Presentantions</h2>
12+
<%= render_association_template f, :presentations %>
13+
<div class="presentations_list">
1214
<%= f.fields_for :presentations do |presentations_fields| %>
13-
<%= render "presentation_fields", :f => presentations_fields %>
15+
<%= render "presentation_fields", f: presentations_fields %>
1416
<% end %>
17+
</div>
1518

1619
<div class="links">
17-
<%= link_to_add_association "Add a Presentation", f, :presentations %>
18-
</div>
20+
<%= link_to_add_association "Add a Presentation", f, :presentations, data: { "association-insertion-node" => ".presentations_list" } %>
21+
</div>

0 commit comments

Comments
 (0)