vanilla_nested 1.0.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/app/assets/javascripts/vanilla_nested.js +100 -0
- data/lib/vanilla_nested.rb +11 -0
- data/lib/vanilla_nested/view_helpers.rb +30 -0
- metadata +46 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 42bb398c9c058f38333cb4c3af17957fb5477da3
|
4
|
+
data.tar.gz: bae3d4d29d855c18f9f676e7a3aeed0b58b67e5b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8a45642b3b74560d5cbfa90178f37c9eac5daf890ed2e0f25915e57b2bccdc5f4006d3106d04dfac2370e95d3d5ca9c444b8c50266a105698aa4a8901484b535
|
7
|
+
data.tar.gz: 5a476ebc770c15df32a6bd3579534acf7f3d7f4bed4f54ba9d278c63d2af6d679a373e0b0feccb33a8361428cec62cd36dbaeb81d4fa7a91204b08a375e50755
|
@@ -0,0 +1,100 @@
|
|
1
|
+
(function(){
|
2
|
+
window.addVanillaNestedFields = function(event) {
|
3
|
+
event.preventDefault();
|
4
|
+
const element = event.target;
|
5
|
+
const data = element.dataset;
|
6
|
+
const newHtml = data.html.replace(/_idx_placeholder_/g, Date.now());
|
7
|
+
const container = document.querySelector(data.containerSelector);
|
8
|
+
|
9
|
+
let inserted;
|
10
|
+
switch (data.methodForInsert) {
|
11
|
+
case ('append'):
|
12
|
+
container.insertAdjacentHTML('beforeend', newHtml);
|
13
|
+
inserted = container.lastElementChild;
|
14
|
+
break;
|
15
|
+
case ('prepend'):
|
16
|
+
container.insertAdjacentHTML('afterbegin', newHtml);
|
17
|
+
inserted = container.firstElementChild;
|
18
|
+
break;
|
19
|
+
}
|
20
|
+
_dispatchEvent(container, 'vanilla-nested:fields-added', element, {added: inserted})
|
21
|
+
}
|
22
|
+
|
23
|
+
window.removeVanillaNestedFields = function(event) {
|
24
|
+
event.preventDefault();
|
25
|
+
const element = event.target;
|
26
|
+
const data = element.dataset;
|
27
|
+
let wrapper = element.parentElement;
|
28
|
+
if (sel = data.fieldsWrapperSelector) wrapper = element.closest(sel);
|
29
|
+
|
30
|
+
if (data.undoTimeout) {
|
31
|
+
hideFieldsWithUndo(wrapper, element);
|
32
|
+
_dispatchEvent(wrapper, 'vanilla-nested:fields-hidden', element);
|
33
|
+
} else {
|
34
|
+
hideWrapper(wrapper);
|
35
|
+
unhideFields(wrapper);
|
36
|
+
_dispatchEvent(wrapper, 'vanilla-nested:fields-removed', element);
|
37
|
+
}
|
38
|
+
wrapper.querySelector('[name$="[_destroy]"]').value = '1';
|
39
|
+
}
|
40
|
+
|
41
|
+
function hideWrapper(wrapper) {
|
42
|
+
wrapper.style.display = 'none';
|
43
|
+
}
|
44
|
+
|
45
|
+
function unhideFields(wrapper) {
|
46
|
+
[...wrapper.children].forEach(child => child.style.display = 'initial');
|
47
|
+
}
|
48
|
+
|
49
|
+
function hideFieldsWithUndo(wrapper, element) {
|
50
|
+
[...wrapper.children].forEach(child => child.style.display = 'none');
|
51
|
+
|
52
|
+
// add the 'undo' link with it's callback
|
53
|
+
const undoLink = _createUndoWithElementsData(element.dataset);
|
54
|
+
wrapper.appendChild(undoLink);
|
55
|
+
|
56
|
+
const _onUndoClicked = function(e) {
|
57
|
+
e.preventDefault();
|
58
|
+
clearTimeout(timer);
|
59
|
+
unhideFields(wrapper);
|
60
|
+
wrapper.querySelector('[name$="[_destroy]"]').value = '0';
|
61
|
+
_dispatchEvent(wrapper, 'vanilla-nested:fields-hidden-undo', undoLink);
|
62
|
+
undoLink.remove();
|
63
|
+
}
|
64
|
+
|
65
|
+
undoLink.addEventListener('click', _onUndoClicked);
|
66
|
+
|
67
|
+
// start the timer
|
68
|
+
const _onTimerCompleted = function() {
|
69
|
+
hideWrapper(wrapper);
|
70
|
+
unhideFields(wrapper);
|
71
|
+
_dispatchEvent(wrapper, 'vanilla-nested:fields-removed', undoLink);
|
72
|
+
undoLink.remove();
|
73
|
+
}
|
74
|
+
|
75
|
+
let ms = element.dataset.undoTimeout;
|
76
|
+
let timer = setTimeout(_onTimerCompleted, ms);
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
function _dispatchEvent(element, eventName, triggeredBy, details) {
|
82
|
+
if (!details) details = {};
|
83
|
+
details.triggeredBy = triggeredBy;
|
84
|
+
|
85
|
+
let event = new CustomEvent(eventName, {bubbles: true, detail: details})
|
86
|
+
element.dispatchEvent(event);
|
87
|
+
}
|
88
|
+
|
89
|
+
function _createUndoWithElementsData(data) {
|
90
|
+
const undo = document.createElement('A');
|
91
|
+
|
92
|
+
undo.classList.add('vanilla-nested-undo');
|
93
|
+
if (classes = data.undoLinkClasses)
|
94
|
+
undo.classList.add(...classes.split(' '));
|
95
|
+
|
96
|
+
undo.innerText = data.undoText;
|
97
|
+
|
98
|
+
return undo;
|
99
|
+
}
|
100
|
+
})()
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'vanilla_nested/view_helpers'
|
2
|
+
|
3
|
+
module VanillaNested
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
initializer "vanilla_nested.initialize" do |app|
|
6
|
+
ActiveSupport.on_load :action_view do
|
7
|
+
ActionView::Base.send :include, VanillaNested::ViewHelpers
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module VanillaNested
|
2
|
+
module ViewHelpers
|
3
|
+
def link_to_add_nested(form, association, container_selector, link_text: nil, link_classes: '', insert_method: :append, partial: nil, partial_form_variable: :form)
|
4
|
+
association_class = form.object.class.reflections[association.to_s].klass
|
5
|
+
object = association_class.new
|
6
|
+
|
7
|
+
partial_name = partial ? partial : "#{association_class.name.downcase}_fields"
|
8
|
+
|
9
|
+
html = capture do
|
10
|
+
form.fields_for association, object, child_index: "_idx_placeholder_" do |ff|
|
11
|
+
render partial: partial_name, locals: {partial_form_variable => ff}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
methodForInsert = [:append, :prepend].include?(insert_method.to_sym) ? insert_method : :append
|
16
|
+
|
17
|
+
classes = "vanilla-nested-add #{link_classes}"
|
18
|
+
link_to '#', class: classes, onclick: 'addVanillaNestedFields(event)', data: {'container-selector': container_selector, html: html, 'method-for-insert': methodForInsert} do
|
19
|
+
link_text || "Add #{association_class.model_name}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def link_to_remove_nested(form, link_text: 'X', fields_wrapper_selector: nil, undo_link_timeout: nil, undo_link_text: 'Undo', undo_link_classes: '')
|
24
|
+
capture do
|
25
|
+
concat form.hidden_field(:_destroy, value: 0)
|
26
|
+
concat link_to(link_text, '#', class: 'vanilla-nested-remove', onclick: 'removeVanillaNestedFields(event)', data: {'fields-wrapper-selector': fields_wrapper_selector, 'undo-timeout': undo_link_timeout, 'undo-text': undo_link_text, 'undo-link-classes': undo_link_classes})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vanilla_nested
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ariel Juodziukynas <arieljuod@gmail.com>
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-04-10 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email: arieljuod@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- app/assets/javascripts/vanilla_nested.js
|
20
|
+
- lib/vanilla_nested.rb
|
21
|
+
- lib/vanilla_nested/view_helpers.rb
|
22
|
+
homepage: https://github.com/arielj/vanilla-nested
|
23
|
+
licenses:
|
24
|
+
- GPL-3.0
|
25
|
+
metadata: {}
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 2.6.14.1
|
43
|
+
signing_key:
|
44
|
+
specification_version: 4
|
45
|
+
summary: Dynamic nested forms using vanilla javascript
|
46
|
+
test_files: []
|