vanilla_nested 1.0.0 → 1.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/app/assets/javascripts/vanilla_nested.js +55 -5
- data/lib/vanilla_nested.rb +4 -2
- data/lib/vanilla_nested/view_helpers.rb +56 -9
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8b6d8ed9c309bf72014920bec0254c922804f9077967492047139cb3aabc54f3
|
4
|
+
data.tar.gz: 890d67164554668f8054724329cb9bfe56884e73ab44a864ef3b8283c011cae9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6df5288710235fce651f21a7d03aff41c9d7d529bbb1f0626677bdfe3bf8f670b1277fde0b942c8978a7240de1ecd0586f96d218e6c63f4a27eb63325539964
|
7
|
+
data.tar.gz: f2b7ec1060c226133354d30cb0643620bf12251657771357429f21a3069c76390085715eeb7fcc381ae4ca016ec0d6a632f0573eb1ec5f7df7bac6f1fa835296
|
@@ -1,10 +1,16 @@
|
|
1
1
|
(function(){
|
2
|
+
// Get the html from the data attribute and insert the new fields on the container
|
3
|
+
// "event" is the click event of the link created by the rails helper
|
2
4
|
window.addVanillaNestedFields = function(event) {
|
3
5
|
event.preventDefault();
|
4
|
-
|
6
|
+
|
7
|
+
let element = event.target;
|
8
|
+
if (!element.classList.contains('vanilla-nested-add'))
|
9
|
+
element = element.closest('.vanilla-nested-add')
|
10
|
+
|
5
11
|
const data = element.dataset;
|
6
|
-
const newHtml = data.html.replace(/_idx_placeholder_/g, Date.now());
|
7
12
|
const container = document.querySelector(data.containerSelector);
|
13
|
+
const newHtml = data.html.replace(/_idx_placeholder_/g, Date.now());
|
8
14
|
|
9
15
|
let inserted;
|
10
16
|
switch (data.methodForInsert) {
|
@@ -17,12 +23,30 @@
|
|
17
23
|
inserted = container.firstElementChild;
|
18
24
|
break;
|
19
25
|
}
|
26
|
+
|
20
27
|
_dispatchEvent(container, 'vanilla-nested:fields-added', element, {added: inserted})
|
28
|
+
|
29
|
+
let removeLink = inserted.querySelector('.vanilla-nested-remove');
|
30
|
+
if (removeLink)
|
31
|
+
removeLink.addEventListener('click', removeVanillaNestedFields, true);
|
32
|
+
|
33
|
+
// dispatch an event if we reached the limit configured on the model
|
34
|
+
if (data.limit) {
|
35
|
+
let nestedElements = container.children.length;
|
36
|
+
if (nestedElements >= data.limit)
|
37
|
+
_dispatchEvent(container, 'vanilla-nested:fields-limit-reached', element)
|
38
|
+
}
|
21
39
|
}
|
22
40
|
|
41
|
+
// Removes the fields or hides them until the undo timer times out
|
42
|
+
// "event" is the click event of the link created by the rails helper
|
23
43
|
window.removeVanillaNestedFields = function(event) {
|
24
44
|
event.preventDefault();
|
25
|
-
|
45
|
+
|
46
|
+
let element = event.target;
|
47
|
+
if (!element.classList.contains('vanilla-nested-remove'))
|
48
|
+
element = element.closest('.vanilla-nested-remove')
|
49
|
+
|
26
50
|
const data = element.dataset;
|
27
51
|
let wrapper = element.parentElement;
|
28
52
|
if (sel = data.fieldsWrapperSelector) wrapper = element.closest(sel);
|
@@ -38,14 +62,21 @@
|
|
38
62
|
wrapper.querySelector('[name$="[_destroy]"]').value = '1';
|
39
63
|
}
|
40
64
|
|
65
|
+
// Hides an element, mainly the wrapper of a group of fields
|
66
|
+
// "wrapper" is the wrapper of the link to remove fields
|
41
67
|
function hideWrapper(wrapper) {
|
42
68
|
wrapper.style.display = 'none';
|
43
69
|
}
|
44
70
|
|
71
|
+
// Unhides the children given a fields wrapper
|
72
|
+
// "wrapper" is the wrapper of the link to remove fields
|
45
73
|
function unhideFields(wrapper) {
|
46
74
|
[...wrapper.children].forEach(child => child.style.display = 'initial');
|
47
75
|
}
|
48
76
|
|
77
|
+
// Hides an element and adds an "undo" link to unhide it
|
78
|
+
// "wrapper" is the wrapper to hide
|
79
|
+
// "element" is the link to remove the wrapper
|
49
80
|
function hideFieldsWithUndo(wrapper, element) {
|
50
81
|
[...wrapper.children].forEach(child => child.style.display = 'none');
|
51
82
|
|
@@ -76,8 +107,6 @@
|
|
76
107
|
let timer = setTimeout(_onTimerCompleted, ms);
|
77
108
|
}
|
78
109
|
|
79
|
-
|
80
|
-
|
81
110
|
function _dispatchEvent(element, eventName, triggeredBy, details) {
|
82
111
|
if (!details) details = {};
|
83
112
|
details.triggeredBy = triggeredBy;
|
@@ -97,4 +126,25 @@
|
|
97
126
|
|
98
127
|
return undo;
|
99
128
|
}
|
129
|
+
|
130
|
+
function initVanillaNested() {
|
131
|
+
document.querySelectorAll('.vanilla-nested-add').forEach(el => {
|
132
|
+
el.addEventListener('click', addVanillaNestedFields, true);
|
133
|
+
})
|
134
|
+
|
135
|
+
document.querySelectorAll('.vanilla-nested-remove').forEach(el => {
|
136
|
+
el.addEventListener('click', removeVanillaNestedFields, true);
|
137
|
+
})
|
138
|
+
}
|
139
|
+
|
140
|
+
document.addEventListener('DOMContentLoaded', function(){
|
141
|
+
initVanillaNested();
|
142
|
+
})
|
143
|
+
|
144
|
+
// Don't run turbolinks event callback for first load, we already do it with DOMContentLoaded
|
145
|
+
const notEmpty = (obj) => Object.keys(obj).length;
|
146
|
+
|
147
|
+
document.addEventListener('turbolinks:load', function(e){
|
148
|
+
if (notEmpty(e.data.timing)) initVanillaNested();
|
149
|
+
})
|
100
150
|
})()
|
data/lib/vanilla_nested.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'vanilla_nested/view_helpers'
|
2
4
|
|
3
5
|
module VanillaNested
|
4
6
|
class Engine < ::Rails::Engine
|
5
|
-
initializer
|
7
|
+
initializer 'vanilla_nested.initialize' do |_app|
|
6
8
|
ActiveSupport.on_load :action_view do
|
7
9
|
ActionView::Base.send :include, VanillaNested::ViewHelpers
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
11
|
-
end
|
13
|
+
end
|
@@ -1,29 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module VanillaNested
|
2
4
|
module ViewHelpers
|
3
|
-
|
5
|
+
# @param form [FormBuild] builder on a "form_for" block
|
6
|
+
# @param association [Symbol] name of the association
|
7
|
+
# @param container_selector [String] selector of the element to inser the fields
|
8
|
+
# @param link_text [String, nil] text to use for the link tag
|
9
|
+
# @param link_classes [String] space separated classes for the link tag
|
10
|
+
# @param insert_method [:append, :prepend] tells javascript if the new fields should be appended or prepended to the container
|
11
|
+
# @param partial_form_variable [String, Symbol] name of the variable that represents the form builder inside the fields partial
|
12
|
+
# @param link_content [Block] block of code for the link content
|
13
|
+
# @return [String] link tag
|
14
|
+
def link_to_add_nested(form, association, container_selector, link_text: nil, link_classes: '', insert_method: :append, partial: nil, partial_form_variable: :form, &link_content)
|
4
15
|
association_class = form.object.class.reflections[association.to_s].klass
|
5
16
|
object = association_class.new
|
6
17
|
|
7
|
-
partial_name = partial
|
18
|
+
partial_name = partial || "#{association_class.name.underscore}_fields"
|
8
19
|
|
9
20
|
html = capture do
|
10
|
-
form.fields_for association, object, child_index:
|
11
|
-
render partial: partial_name, locals: {partial_form_variable => ff}
|
21
|
+
form.fields_for association, object, child_index: '_idx_placeholder_' do |ff|
|
22
|
+
render partial: partial_name, locals: { partial_form_variable => ff }
|
12
23
|
end
|
13
24
|
end
|
14
25
|
|
15
|
-
|
26
|
+
method_for_insert = %i[append prepend].include?(insert_method.to_sym) ? insert_method : :append
|
16
27
|
|
17
28
|
classes = "vanilla-nested-add #{link_classes}"
|
18
|
-
|
19
|
-
|
29
|
+
data = {
|
30
|
+
'container-selector': container_selector,
|
31
|
+
'html': html,
|
32
|
+
'method-for-insert': method_for_insert
|
33
|
+
}
|
34
|
+
|
35
|
+
nested_options = form.object.class.nested_attributes_options[association.to_sym]
|
36
|
+
data['limit'] = nested_options[:limit] if nested_options[:limit]
|
37
|
+
|
38
|
+
if block_given?
|
39
|
+
link_to '#', class: classes, data: data, &link_content
|
40
|
+
else
|
41
|
+
text = link_text || "Add #{association_class.model_name}"
|
42
|
+
link_to text, '#', class: classes, data: data
|
20
43
|
end
|
21
44
|
end
|
22
45
|
|
23
|
-
|
46
|
+
# @param form [FormBuilder] builder on a "form_for" block
|
47
|
+
# @param link_text [String, nil] text for the link, defaults to 'X'
|
48
|
+
# @param fields_wrapper_selector [String] selector for the wrapper of the fields, must be an ancestor
|
49
|
+
# @param undo_link_timeout [Integer] time until undo timeouts
|
50
|
+
# @param undo_link_text [String] text to show as "undo"
|
51
|
+
# @param undo_link_classes [String] space separated list of classes for the "undo" link
|
52
|
+
# @param ulink_classes [String] space separated list of classes for the "x" link
|
53
|
+
# @param link_content [Block] block of code for the link content
|
54
|
+
# @return [String] hidden field and link tag
|
55
|
+
def link_to_remove_nested(form, link_text: 'X', fields_wrapper_selector: nil, undo_link_timeout: nil, undo_link_text: 'Undo', undo_link_classes: '', link_classes: '', &link_content)
|
56
|
+
data = {
|
57
|
+
'fields-wrapper-selector': fields_wrapper_selector,
|
58
|
+
'undo-timeout': undo_link_timeout,
|
59
|
+
'undo-text': undo_link_text,
|
60
|
+
'undo-link-classes': undo_link_classes
|
61
|
+
}
|
62
|
+
|
63
|
+
classes = "vanilla-nested-remove #{link_classes}"
|
64
|
+
|
24
65
|
capture do
|
25
66
|
concat form.hidden_field(:_destroy, value: 0)
|
26
|
-
concat
|
67
|
+
concat(
|
68
|
+
if block_given?
|
69
|
+
link_to('#', class: classes, data: data, &link_content)
|
70
|
+
else
|
71
|
+
link_to(link_text.html_safe, '#', class: classes, data: data)
|
72
|
+
end
|
73
|
+
)
|
27
74
|
end
|
28
75
|
end
|
29
76
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vanilla_nested
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ariel Juodziukynas <arieljuod@gmail.com>
|
@@ -21,7 +21,7 @@ files:
|
|
21
21
|
- lib/vanilla_nested/view_helpers.rb
|
22
22
|
homepage: https://github.com/arielj/vanilla-nested
|
23
23
|
licenses:
|
24
|
-
-
|
24
|
+
- MIT
|
25
25
|
metadata: {}
|
26
26
|
post_install_message:
|
27
27
|
rdoc_options: []
|
@@ -38,8 +38,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '0'
|
40
40
|
requirements: []
|
41
|
-
|
42
|
-
rubygems_version: 2.6.14.1
|
41
|
+
rubygems_version: 3.0.9
|
43
42
|
signing_key:
|
44
43
|
specification_version: 4
|
45
44
|
summary: Dynamic nested forms using vanilla javascript
|