cocooned 1.4.1 → 2.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 +4 -4
- data/CHANGELOG.md +178 -0
- data/README.md +244 -172
- data/app/assets/javascripts/cocoon.js +1 -13
- data/app/assets/javascripts/cocooned.js +929 -399
- data/app/assets/stylesheets/cocooned.css +1 -9
- data/cocooned.gemspec +27 -18
- data/lib/cocooned/association/builder.rb +66 -0
- data/lib/cocooned/association/renderer.rb +53 -0
- data/lib/cocooned/association.rb +8 -0
- data/lib/cocooned/deprecation.rb +105 -0
- data/lib/cocooned/helpers/containers.rb +72 -0
- data/lib/cocooned/helpers/tags/add.rb +136 -0
- data/lib/cocooned/helpers/tags/down.rb +76 -0
- data/lib/cocooned/helpers/tags/remove.rb +78 -0
- data/lib/cocooned/helpers/tags/up.rb +76 -0
- data/lib/cocooned/helpers/tags.rb +60 -0
- data/lib/cocooned/helpers.rb +3 -329
- data/lib/cocooned/railtie.rb +7 -2
- data/lib/cocooned/tags/add.rb +61 -0
- data/lib/cocooned/tags/base.rb +61 -0
- data/lib/cocooned/tags/down.rb +19 -0
- data/lib/cocooned/tags/remove.rb +35 -0
- data/lib/cocooned/tags/up.rb +19 -0
- data/lib/cocooned/tags.rb +12 -0
- data/lib/cocooned/tags_helper.rb +83 -0
- data/lib/cocooned/version.rb +1 -1
- data/lib/cocooned.rb +6 -1
- metadata +51 -86
- data/History.md +0 -283
- data/Rakefile +0 -113
- data/lib/cocooned/association_builder.rb +0 -68
- data/lib/cocooned/helpers/cocoon_compatibility.rb +0 -27
- data/lib/cocooned/helpers/deprecate.rb +0 -47
data/cocooned.gemspec
CHANGED
@@ -11,32 +11,41 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.authors = ['Gaël-Ian Havard', 'Nathan Van der Auwera']
|
12
12
|
spec.email = ['gael-ian@notus.sh', 'nathan@dixis.com']
|
13
13
|
|
14
|
-
spec.summary = '
|
15
|
-
spec.description =
|
16
|
-
|
14
|
+
spec.summary = 'Form builder agnostic handling of Rails nested forms'
|
15
|
+
spec.description = <<-DESC.gsub(/\s+/, ' ')
|
16
|
+
Easier nested form in Rails with capabilities to add, remove, reorder or limit nested items.
|
17
|
+
Works with standard Rails form builder, Formtastic or SimpleForm, and with or without jQuery.
|
18
|
+
DESC
|
19
|
+
spec.homepage = 'https://github.com/notus-sh/cocooned'
|
17
20
|
|
18
21
|
raise 'RubyGems 2.0 or newer is required.' unless spec.respond_to?(:metadata)
|
19
22
|
|
20
|
-
spec.metadata
|
23
|
+
spec.metadata = {
|
24
|
+
'allowed_push_host' => 'https://rubygems.org',
|
25
|
+
'rubygems_mfa_required' => 'true',
|
26
|
+
|
27
|
+
'bug_tracker_uri' => 'https://github.com/notus-sh/cocooned/issues',
|
28
|
+
'changelog_uri' => 'https://github.com/notus-sh/cocooned/blob/main/CHANGELOG.md',
|
29
|
+
'homepage_uri' => 'https://github.com/notus-sh/cocooned',
|
30
|
+
'source_code_uri' => 'https://github.com/notus-sh/cocooned',
|
31
|
+
'funding_uri' => 'https://opencollective.com/notus-sh'
|
32
|
+
}
|
21
33
|
|
22
34
|
spec.require_paths = ['lib']
|
35
|
+
|
36
|
+
excluded_dirs = %r{^(.github|dev|npm|spec)/}
|
37
|
+
excluded_files = %w[.gitignore .rspec Gemfile Gemfile.lock Rakefile package.json yarn.lock]
|
23
38
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
24
|
-
f.match(
|
25
|
-
%w[.gitignore .rspec .travis.yml].include?(f) ||
|
26
|
-
%w[Gemfile Gemfile.lock package.json yarn.lock].include?(f)
|
39
|
+
f.match(excluded_dirs) || excluded_files.include?(f)
|
27
40
|
end
|
28
|
-
spec.required_ruby_version = '>= 2.
|
41
|
+
spec.required_ruby_version = '>= 2.6'
|
29
42
|
|
30
|
-
spec.add_dependency 'rails', '>=
|
43
|
+
spec.add_dependency 'rails', '>= 6.0', '<= 7.1'
|
31
44
|
|
32
45
|
spec.add_development_dependency 'bundler', '~> 2.1'
|
33
|
-
spec.add_development_dependency '
|
34
|
-
spec.add_development_dependency 'rake'
|
35
|
-
spec.add_development_dependency 'rspec', '~> 3.
|
36
|
-
spec.add_development_dependency 'rspec-rails', '
|
37
|
-
spec.add_development_dependency '
|
38
|
-
spec.add_development_dependency 'rubocop-performance'
|
39
|
-
spec.add_development_dependency 'rubocop-rails'
|
40
|
-
spec.add_development_dependency 'rubocop-rake'
|
41
|
-
spec.add_development_dependency 'rubocop-rspec'
|
46
|
+
spec.add_development_dependency 'formtastic', '~> 4.0'
|
47
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
48
|
+
spec.add_development_dependency 'rspec', '~> 3.11'
|
49
|
+
spec.add_development_dependency 'rspec-rails', '>= 5.0'
|
50
|
+
spec.add_development_dependency 'simple_form', '~> 5.1'
|
42
51
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cocooned
|
4
|
+
module Association
|
5
|
+
class Builder # :nodoc:
|
6
|
+
attr_reader :association, :record
|
7
|
+
|
8
|
+
def initialize(record, association, options = {})
|
9
|
+
@record = record
|
10
|
+
@association = association
|
11
|
+
@options = options.dup.symbolize_keys.reverse_merge(force_non_association_create: false, wrap_object: false)
|
12
|
+
end
|
13
|
+
|
14
|
+
def build
|
15
|
+
model = reflection ? build_with_reflection : build_without_reflection
|
16
|
+
model = options[:wrap_object].call(model) if options[:wrap_object].respond_to?(:call)
|
17
|
+
model
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
attr_reader :options
|
23
|
+
|
24
|
+
def model
|
25
|
+
record.class
|
26
|
+
end
|
27
|
+
|
28
|
+
def reflection
|
29
|
+
@reflection ||= model.try(:reflect_on_association, association)
|
30
|
+
end
|
31
|
+
|
32
|
+
def build_with_reflection
|
33
|
+
return build_with_conditions if should_use_conditions?
|
34
|
+
|
35
|
+
# Assume ActiveRecord or compatible
|
36
|
+
# We use a clone of the current form object to not link
|
37
|
+
# object together (even if unsaved)
|
38
|
+
dummy = record.dup
|
39
|
+
model = if reflection.collection?
|
40
|
+
dummy.send(association).build
|
41
|
+
else
|
42
|
+
dummy.send("build_#{association}")
|
43
|
+
end
|
44
|
+
model = model.dup if model.frozen?
|
45
|
+
model
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_without_reflection
|
49
|
+
methods = %W[build_#{association.to_s.pluralize} build_#{association.to_s.singularize}]
|
50
|
+
available_methods = methods.select { |m| record.respond_to?(m) }
|
51
|
+
raise "Association #{association} doesn't exist on #{model}" unless available_methods.any?
|
52
|
+
|
53
|
+
record.send(available_methods.first)
|
54
|
+
end
|
55
|
+
|
56
|
+
def should_use_conditions?
|
57
|
+
reflection.class.name.starts_with?('Mongoid::') || options[:force_non_association_create]
|
58
|
+
end
|
59
|
+
|
60
|
+
def build_with_conditions
|
61
|
+
conditions = reflection.respond_to?(:conditions) ? reflection.conditions.flatten : []
|
62
|
+
reflection.klass.new(*conditions)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cocooned
|
4
|
+
module Association
|
5
|
+
class Renderer # :nodoc:
|
6
|
+
def initialize(template, form, association, object, options = {})
|
7
|
+
@template = template
|
8
|
+
@form = form
|
9
|
+
@association = association
|
10
|
+
@object = object
|
11
|
+
@options = options.dup.symbolize_keys
|
12
|
+
end
|
13
|
+
|
14
|
+
def render
|
15
|
+
form.public_send(form_method, association, object, form_options) do |form|
|
16
|
+
template.render(partial, **render_options(form))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
attr_reader :template, :form, :association, :object, :options
|
23
|
+
|
24
|
+
def singular_association
|
25
|
+
association.to_s.singularize
|
26
|
+
end
|
27
|
+
|
28
|
+
def form_method
|
29
|
+
ancestors = form.class.ancestors.map(&:to_s)
|
30
|
+
return :simple_fields_for if ancestors.include?('SimpleForm::FormBuilder')
|
31
|
+
return :semantic_fields_for if ancestors.include?('Formtastic::FormBuilder')
|
32
|
+
|
33
|
+
:fields_for
|
34
|
+
end
|
35
|
+
|
36
|
+
def form_options
|
37
|
+
options.fetch(:form_options, {}).symbolize_keys.reverse_merge(child_index: "new_#{association}")
|
38
|
+
end
|
39
|
+
|
40
|
+
def partial
|
41
|
+
options.fetch(:partial, "#{singular_association}_fields")
|
42
|
+
end
|
43
|
+
|
44
|
+
def render_options(form)
|
45
|
+
options.fetch(:locals, {}).merge(form_name => form)
|
46
|
+
end
|
47
|
+
|
48
|
+
def form_name
|
49
|
+
options.fetch(:form_name, :f).to_sym
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/deprecation'
|
4
|
+
|
5
|
+
module Cocooned
|
6
|
+
# Custom deprecator to use with ActiveSupport::Deprecation methods
|
7
|
+
class Deprecation < ActiveSupport::Deprecation
|
8
|
+
@deprecators = {}
|
9
|
+
|
10
|
+
def self.[](deprecation_horizon = nil)
|
11
|
+
@deprecators[deprecation_horizon] ||= new(deprecation_horizon)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(deprecation_horizon = nil, gem_name = 'Cocooned')
|
15
|
+
deprecation_horizon ||= format('%<major>d.0', major: Gem::Version.new(Cocooned::VERSION).segments.first + 1)
|
16
|
+
super(deprecation_horizon, gem_name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Deprecated methods
|
21
|
+
module Deprecated # :nodoc:
|
22
|
+
module Helpers # :nodoc:
|
23
|
+
module Tags # :nodoc:
|
24
|
+
# @deprecated: Please use {#cocooned_add_item_link} instead
|
25
|
+
def link_to_add_association(*args, &block)
|
26
|
+
cocooned_add_item_link(*args, &block)
|
27
|
+
end
|
28
|
+
deprecate link_to_add_association: 'Use :cocooned_add_link instead',
|
29
|
+
deprecator: Deprecation['3.0']
|
30
|
+
|
31
|
+
# @deprecated: Please use {#cocooned_remove_item_link} instead
|
32
|
+
def link_to_remove_association(*args, &block)
|
33
|
+
cocooned_remove_item_link(*args, &block)
|
34
|
+
end
|
35
|
+
deprecate link_to_remove_association: 'Use :cocooned_remove_item_link instead',
|
36
|
+
deprecator: Deprecation['3.0']
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module TagsHelper # :nodoc:
|
41
|
+
module DefaultLabel # :nodoc:
|
42
|
+
protected
|
43
|
+
|
44
|
+
def i18n_namespaces
|
45
|
+
return super unless I18n.exists?(:cocoon)
|
46
|
+
|
47
|
+
Deprecation['3.0'].warn 'Support for the :cocoon i18n namespace will be removed in 3.0', caller_locations(3)
|
48
|
+
super + %w[cocoon]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module DataAttributes # :nodoc:
|
53
|
+
protected
|
54
|
+
|
55
|
+
# Compatibility with the old way to pass data attributes to Rails view helpers
|
56
|
+
# Has we use the :data key (introduced in Rails 3.1), they will not be looked up.
|
57
|
+
def html_data
|
58
|
+
return super unless data_keys.size.positive?
|
59
|
+
|
60
|
+
Deprecation['3.0'].warn 'Compatibility with options named data-* will be removed in 3.0', caller_locations(3)
|
61
|
+
html_data_normalize super.merge(data_options)
|
62
|
+
end
|
63
|
+
|
64
|
+
def data_keys
|
65
|
+
options.keys.select { |k| k.to_s.match?(/data[_-]/) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def data_options
|
69
|
+
data_keys.each_with_object({}) do |original_key, extracted|
|
70
|
+
key = original_key.to_s.gsub(/^data[_-]/, '')
|
71
|
+
extracted[key] = options.delete(original_key)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module AssociationOptions # :nodoc:
|
77
|
+
protected
|
78
|
+
|
79
|
+
def association_options
|
80
|
+
if options.key? :insertion_traversal
|
81
|
+
Deprecation['3.0'].warn 'Support for the :insertion_traversal will be removed in 3.0', caller_locations(3)
|
82
|
+
end
|
83
|
+
|
84
|
+
super
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
module Renderer # :nodoc:
|
89
|
+
protected
|
90
|
+
|
91
|
+
def renderer_options
|
92
|
+
return super unless options.key?(:render_options)
|
93
|
+
|
94
|
+
Deprecation['3.0'].warn 'Support for :render_options will be removed in 3.0', caller_locations(3)
|
95
|
+
legacy_options = options.delete(:render_options)
|
96
|
+
|
97
|
+
super.tap do |opts|
|
98
|
+
opts[:locals] = legacy_options.delete(:locals) if legacy_options.key?(:locals)
|
99
|
+
opts[:form_options] = legacy_options
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cocooned
|
4
|
+
module Helpers
|
5
|
+
# Cocooned containers helpers output container or item wrappers as expected by
|
6
|
+
# the JavaScript companion package.
|
7
|
+
module Containers
|
8
|
+
# Wrap content with the expected markup for a Cocooned container.
|
9
|
+
#
|
10
|
+
# This is a wrapper around `ActionView::Base#content_tag` to automatically
|
11
|
+
# add default classes and data-attributes that define a Cocooned
|
12
|
+
# container.
|
13
|
+
#
|
14
|
+
# = Signatures
|
15
|
+
#
|
16
|
+
# cocooned_container(*arguments, **options) do
|
17
|
+
# # Container content
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# = Parameters
|
21
|
+
#
|
22
|
+
# `cocooned_container` supports following options:
|
23
|
+
#
|
24
|
+
# - `:limit` [Integer]
|
25
|
+
# Enable the limit plugin and set the accepted maximum number of items
|
26
|
+
# - `:reorderable` [Boolean|Hash]
|
27
|
+
# Enable the reorderable plugin. When a boolean, use plugin's default.
|
28
|
+
# You can also pass a Hash with explicit options (ex: `{ startAt: 1 }`).
|
29
|
+
#
|
30
|
+
# Any other argument or option supported by `ActionView::Base#content_tag`
|
31
|
+
# will be forwarded.
|
32
|
+
def cocooned_container(*args, &block)
|
33
|
+
options = args.extract_options!.dup
|
34
|
+
defaults = cocooned_wrapper_defaults(options, %w[cocooned-container], :'cocooned-container')
|
35
|
+
defaults[:data][:cocooned_options] = options.extract!(:limit, :reorderable).to_json
|
36
|
+
|
37
|
+
content_tag(:div, *args, **options.deep_merge(defaults), &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Wrap content with the expected markup for a Cocooned item.
|
41
|
+
#
|
42
|
+
# This is a wrapper around `ActionView::Base#content_tag` to automatically
|
43
|
+
# add default classes and data-attributes that define a Cocooned item.
|
44
|
+
#
|
45
|
+
# = Signatures
|
46
|
+
#
|
47
|
+
# cocooned_item(*arguments, **options) do
|
48
|
+
# # Item content
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# = Parameters
|
52
|
+
#
|
53
|
+
# Any argument or option supported by `ActionView::Base#content_tag` will
|
54
|
+
# be forwarded.
|
55
|
+
def cocooned_item(*args, &block)
|
56
|
+
options = args.extract_options!.dup
|
57
|
+
defaults = cocooned_wrapper_defaults(options, %w[cocooned-item nested-fields], :'cocooned-item')
|
58
|
+
|
59
|
+
content_tag(:div, *args, **options.deep_merge(defaults), &block)
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
def cocooned_wrapper_defaults(options, additional_classes, mark)
|
65
|
+
# TODO: Replace with compact_blank when dropping support for Rails 6.0
|
66
|
+
classes = Array.wrap(options.delete(:class)).flat_map { |k| k.to_s.split }.reject(&:blank?)
|
67
|
+
|
68
|
+
{ class: (classes + additional_classes), data: { mark => true } }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cocooned
|
4
|
+
module Helpers
|
5
|
+
module Tags
|
6
|
+
# Helpers to generate action triggers to add items in a nested form.
|
7
|
+
#
|
8
|
+
# = Signatures
|
9
|
+
#
|
10
|
+
# {method}(label, form, association, options = {})
|
11
|
+
# # Explicit name
|
12
|
+
#
|
13
|
+
# {method}(form, association, options = {}) do
|
14
|
+
# # Name as a block
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# {method}(form, association, options = {})
|
18
|
+
# # Use default name
|
19
|
+
#
|
20
|
+
# = Parameters
|
21
|
+
#
|
22
|
+
# `label` is the text to be used as the link label. See the main
|
23
|
+
# documentation for Cocooned::Helpers::Tags for more about labelling.
|
24
|
+
#
|
25
|
+
# `form` is your form builder. Can be a SimpleForm::Builder,
|
26
|
+
# Formtastic::Builder or a standard Rails FormBuilder.
|
27
|
+
#
|
28
|
+
# `association` is the name of the nested association.
|
29
|
+
# Ex: cocooned_add_item_link "Add an item", form, :items
|
30
|
+
#
|
31
|
+
# = Options
|
32
|
+
#
|
33
|
+
# `options` can be any of the following.
|
34
|
+
#
|
35
|
+
# Association options:
|
36
|
+
#
|
37
|
+
# - **insertion_method** : the method to be used to insert new items.
|
38
|
+
# Can be any of `before`, `after`, `append`, `prepend`, `replaceWith`.
|
39
|
+
# Defaults to `before`
|
40
|
+
# - **insertion_node** : a CSS selector to match new items insertion node.
|
41
|
+
# Can be any CSS selector supported by `document.querySelector`.
|
42
|
+
# For compatibility with the original Cocoon:
|
43
|
+
# * 'this' is supported as a special value to use the trigger itself as
|
44
|
+
# insertion node.
|
45
|
+
# * If no value is specified, the trigger's parent will be used.
|
46
|
+
# - **count**: how many item will be inserted on click.
|
47
|
+
# Defaults to 1.
|
48
|
+
#
|
49
|
+
# Rendering options:
|
50
|
+
#
|
51
|
+
# - **partial**: the nested form partial.
|
52
|
+
# Defaults to `{association.singular_name}_fields`.
|
53
|
+
# - **form_name**: name used to access the form builder in the nested form
|
54
|
+
# partial. Defaults to `:f`.
|
55
|
+
# - **form_options**: options to be passed to the nested form builder. Can
|
56
|
+
# be used to specify a wrapper for simple_form_fields if you use its
|
57
|
+
# Bootstrap setup, for example. No defaults.
|
58
|
+
# - **locals**: a hash of local variables to forward to the partial. No
|
59
|
+
# default.
|
60
|
+
#
|
61
|
+
# Building options:
|
62
|
+
#
|
63
|
+
# - **wrap_object**: anything responding to `call` to be used to wrap the
|
64
|
+
# newly build item instance. Can be useful with decorators or special
|
65
|
+
# initialisations. No default.
|
66
|
+
# Ex:
|
67
|
+
# cocooned_add_item_link "Add an item", form, :items,
|
68
|
+
# wrap_object: Proc.new { |comment| CommentDecorator.new(comment) })
|
69
|
+
# - **force_non_association_create**: force to build instances of the
|
70
|
+
# nested model without calling association build methods
|
71
|
+
# (`build_{association}` or `{association}.build`). Can be usefull if,
|
72
|
+
# for some specific reason, you need an object to _not_ be created on
|
73
|
+
# the association, for example if you did not want `after_add` callbacks
|
74
|
+
# to be triggered. Defaults to false.
|
75
|
+
#
|
76
|
+
# Compatibility options:
|
77
|
+
#
|
78
|
+
# These options are supported for backward compatibility with the original
|
79
|
+
# Cocoon. **Support for these options will be removed in the next major
|
80
|
+
# release !**.
|
81
|
+
#
|
82
|
+
# - **insertion_traversal**: a jQuery DOM traversal method name to use in
|
83
|
+
# combination with **insertion_node** to find the insertion node from
|
84
|
+
# the trigger. Can be any of `closest`, `parent`, `prev`, `next` or
|
85
|
+
# `siblings`.
|
86
|
+
# Expressed in jQuery pseudo-code, the insertion node will be determined
|
87
|
+
# as the result of `$(trigger).{traversal}({insertion_node})`.
|
88
|
+
# - **render_options**: A nested Hash originally used to pass locals and form
|
89
|
+
# builder options.
|
90
|
+
module Add
|
91
|
+
# Output a link to add an item in a nested form.
|
92
|
+
#
|
93
|
+
# = Signatures
|
94
|
+
#
|
95
|
+
# cocooned_add_item_link(label, form, association, options = {})
|
96
|
+
# # Explicit name
|
97
|
+
#
|
98
|
+
# cocooned_add_item_link(form, association, options = {}) do
|
99
|
+
# # Name as a block
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
# cocooned_add_item_link(form, association, options = {})
|
103
|
+
# # Use default name
|
104
|
+
#
|
105
|
+
# See Cocooned::Helpers::Tags::Add main documentation for a reference of
|
106
|
+
# supported parameters.
|
107
|
+
#
|
108
|
+
# See the documentation of +ActionView::Base#link_to+ for additional
|
109
|
+
# options.
|
110
|
+
def cocooned_add_item_link(*args, &block)
|
111
|
+
cocooned_link(Cocooned::Tags::Add, *args, &block)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Output a button to add an item in a nested form.
|
115
|
+
#
|
116
|
+
# = Signatures
|
117
|
+
#
|
118
|
+
# cocooned_add_item_button(label, form, association, options = {})
|
119
|
+
# # Explicit name
|
120
|
+
#
|
121
|
+
# cocooned_add_item_button(form, association, options = {}) do
|
122
|
+
# # Name as a block
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
# cocooned_add_item_button(form, association, options = {})
|
126
|
+
# # Use default name
|
127
|
+
#
|
128
|
+
# See Cocooned::Helpers::Tags::Add main documentation for a reference of
|
129
|
+
# supported options.
|
130
|
+
def cocooned_add_item_button(*args, &block)
|
131
|
+
cocooned_button(Cocooned::Tags::Add, *args, &block)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cocooned
|
4
|
+
module Helpers
|
5
|
+
module Tags
|
6
|
+
# Helpers to generate action triggers to move items down in a nested form.
|
7
|
+
#
|
8
|
+
# = Signatures
|
9
|
+
#
|
10
|
+
# {method}(label, form, options = {})
|
11
|
+
# # Explicit name
|
12
|
+
#
|
13
|
+
# {method}(form, options = {}) do
|
14
|
+
# # Name as a block
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# {method}(form, options = {})
|
18
|
+
# # Use default name
|
19
|
+
#
|
20
|
+
# = Parameters
|
21
|
+
#
|
22
|
+
# `label` is the text to be used as the link label. See the main
|
23
|
+
# documentation for Cocooned::Helpers::Tags for more about labelling.
|
24
|
+
#
|
25
|
+
# `form` is your form builder. Can be a SimpleForm::Builder,
|
26
|
+
# Formtastic::Builder or a standard Rails FormBuilder.
|
27
|
+
module Down
|
28
|
+
# Output a link to move an item down.
|
29
|
+
#
|
30
|
+
# = Signatures
|
31
|
+
#
|
32
|
+
# cocooned_move_item_down_link(label, form, options = {})
|
33
|
+
# # Explicit name
|
34
|
+
#
|
35
|
+
# cocooned_move_item_down_link(form, options = {}) do
|
36
|
+
# # Name as a block
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# cocooned_move_item_down_link(form, options = {})
|
40
|
+
# # Use default name
|
41
|
+
#
|
42
|
+
# See Cocooned::Helpers::Tags::Down main documentation for a reference
|
43
|
+
# of supported parameters.
|
44
|
+
#
|
45
|
+
# See the documentation of +ActionView::Base#link_to+ for additional
|
46
|
+
# options.
|
47
|
+
def cocooned_move_item_down_link(*args, &block)
|
48
|
+
cocooned_link(Cocooned::Tags::Down, *args, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Output a button to move an item down.
|
52
|
+
#
|
53
|
+
# = Signatures
|
54
|
+
#
|
55
|
+
# cocooned_move_item_down_button(label, form, options = {})
|
56
|
+
# # Explicit name
|
57
|
+
#
|
58
|
+
# cocooned_move_item_down_button(form, options = {}) do
|
59
|
+
# # Name as a block
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# cocooned_move_item_down_button(form, options = {})
|
63
|
+
# # Use default name
|
64
|
+
#
|
65
|
+
# See Cocooned::Helpers::Tags::Add main documentation for a reference of
|
66
|
+
# supported parameters.
|
67
|
+
#
|
68
|
+
# See the documentation of +ActionView::Helpers::FormBuilder#button+ for
|
69
|
+
# valid options.
|
70
|
+
def cocooned_move_item_down_button(*args, &block)
|
71
|
+
cocooned_button(Cocooned::Tags::Down, *args, &block)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cocooned
|
4
|
+
module Helpers
|
5
|
+
module Tags
|
6
|
+
# Helpers to generate action triggers to remove items in a nested form.
|
7
|
+
#
|
8
|
+
# = Signatures
|
9
|
+
#
|
10
|
+
# {method}(label, form, options = {})
|
11
|
+
# # Explicit name
|
12
|
+
#
|
13
|
+
# {method}(form, options = {}) do
|
14
|
+
# # Name as a block
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# {method}(form, options = {})
|
18
|
+
# # Use default name
|
19
|
+
#
|
20
|
+
# = Parameters
|
21
|
+
#
|
22
|
+
# `label` is the text to be used as the link label. See the main
|
23
|
+
# documentation for Cocooned::Helpers::Tags for more about labelling.
|
24
|
+
#
|
25
|
+
# `form` is your form builder. Can be a SimpleForm::Builder,
|
26
|
+
# Formtastic::Builder or a standard Rails FormBuilder.
|
27
|
+
module Remove
|
28
|
+
# Output a link to remove an item (and an hidden field to mark
|
29
|
+
# it as destroyed if it has already been persisted).
|
30
|
+
#
|
31
|
+
# = Signatures
|
32
|
+
#
|
33
|
+
# cocooned_remove_item_link(label, form, options = {})
|
34
|
+
# # Explicit name
|
35
|
+
#
|
36
|
+
# cocooned_remove_item_link(form, options = {}) do
|
37
|
+
# # Name as a block
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# cocooned_remove_item_link(form, options = {})
|
41
|
+
# # Use default name
|
42
|
+
#
|
43
|
+
# See Cocooned::Helpers::Tags::Remove main documentation for a reference
|
44
|
+
# of supported parameters.
|
45
|
+
#
|
46
|
+
# See the documentation of +ActionView::Base#link_to+ for additional
|
47
|
+
# options.
|
48
|
+
def cocooned_remove_item_link(*args, &block)
|
49
|
+
cocooned_link(Cocooned::Tags::Remove, *args, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Output a button to remove an item (and an hidden field to mark
|
53
|
+
# it as destroyed if it has already been persisted).
|
54
|
+
#
|
55
|
+
# = Signatures
|
56
|
+
#
|
57
|
+
# cocooned_remove_item_link(label, form, options = {})
|
58
|
+
# # Explicit name
|
59
|
+
#
|
60
|
+
# cocooned_remove_item_link(form, options = {}) do
|
61
|
+
# # Name as a block
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# cocooned_remove_item_link(form, options = {})
|
65
|
+
# # Use default name
|
66
|
+
#
|
67
|
+
# See Cocooned::Helpers::Tags::Remove main documentation for a reference
|
68
|
+
# of supported parameters.
|
69
|
+
#
|
70
|
+
# See the documentation of +ActionView::Base#link_to+ for additional
|
71
|
+
# options.
|
72
|
+
def cocooned_remove_item_button(*args, &block)
|
73
|
+
cocooned_button(Cocooned::Tags::Remove, *args, &block)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|