decidim-forms 0.16.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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +65 -0
  3. data/Rakefile +3 -0
  4. data/app/assets/config/admin/decidim_forms_manifest.js +1 -0
  5. data/app/assets/config/decidim_forms_manifest.js +1 -0
  6. data/app/assets/images/decidim/surveys/icon.svg +19 -0
  7. data/app/assets/javascripts/decidim/forms/admin/auto_buttons_by_min_items.component.js.es6 +25 -0
  8. data/app/assets/javascripts/decidim/forms/admin/auto_select_options_by_total_items.component.js.es6 +23 -0
  9. data/app/assets/javascripts/decidim/forms/admin/forms.js.es6 +188 -0
  10. data/app/assets/javascripts/decidim/forms/autosortable_checkboxes.component.js.es6 +65 -0
  11. data/app/assets/javascripts/decidim/forms/forms.js.es6 +20 -0
  12. data/app/assets/javascripts/decidim/forms/option_attached_inputs.component.js.es6 +32 -0
  13. data/app/commands/decidim/forms/admin/update_questionnaire.rb +86 -0
  14. data/app/commands/decidim/forms/answer_questionnaire.rb +54 -0
  15. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +95 -0
  16. data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +84 -0
  17. data/app/forms/decidim/forms/admin/answer_option_form.rb +23 -0
  18. data/app/forms/decidim/forms/admin/question_form.rb +35 -0
  19. data/app/forms/decidim/forms/admin/questionnaire_form.rb +27 -0
  20. data/app/forms/decidim/forms/answer_choice_form.rb +15 -0
  21. data/app/forms/decidim/forms/answer_form.rb +69 -0
  22. data/app/forms/decidim/forms/questionnaire_form.rb +22 -0
  23. data/app/helpers/decidim/forms/admin/application_helper.rb +19 -0
  24. data/app/models/concerns/decidim/forms/has_questionnaire.rb +20 -0
  25. data/app/models/decidim/forms/answer.rb +45 -0
  26. data/app/models/decidim/forms/answer_choice.rb +15 -0
  27. data/app/models/decidim/forms/answer_option.rb +11 -0
  28. data/app/models/decidim/forms/application_record.rb +10 -0
  29. data/app/models/decidim/forms/question.rb +36 -0
  30. data/app/models/decidim/forms/questionnaire.rb +23 -0
  31. data/app/queries/decidim/forms/questionnaire_user_answers.rb +28 -0
  32. data/app/views/decidim/forms/admin/questionnaires/_answer_option.html.erb +44 -0
  33. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +51 -0
  34. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +115 -0
  35. data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +7 -0
  36. data/app/views/decidim/forms/questionnaires/_answer.html.erb +94 -0
  37. data/app/views/decidim/forms/questionnaires/show.html.erb +84 -0
  38. data/config/locales/ca.yml +79 -0
  39. data/config/locales/de.yml +79 -0
  40. data/config/locales/en.yml +79 -0
  41. data/config/locales/es-PY.yml +79 -0
  42. data/config/locales/es.yml +79 -0
  43. data/config/locales/eu.yml +79 -0
  44. data/config/locales/fi-pl.yml +79 -0
  45. data/config/locales/fi.yml +79 -0
  46. data/config/locales/fr.yml +79 -0
  47. data/config/locales/gl.yml +79 -0
  48. data/config/locales/hu.yml +79 -0
  49. data/config/locales/id-ID.yml +1 -0
  50. data/config/locales/it.yml +79 -0
  51. data/config/locales/nl.yml +79 -0
  52. data/config/locales/pl.yml +79 -0
  53. data/config/locales/pt-BR.yml +79 -0
  54. data/config/locales/pt.yml +79 -0
  55. data/config/locales/ru.yml +1 -0
  56. data/config/locales/sv.yml +79 -0
  57. data/config/locales/tr-TR.yml +1 -0
  58. data/config/locales/uk.yml +1 -0
  59. data/db/migrate/20170511092231_create_decidim_forms_questionnaires.rb +15 -0
  60. data/db/migrate/20170515090916_create_decidim_forms_questions.rb +17 -0
  61. data/db/migrate/20170515144119_create_decidim_forms_answers.rb +15 -0
  62. data/db/migrate/20180405015012_create_decidim_forms_answer_options.rb +11 -0
  63. data/db/migrate/20180405015147_create_decidim_forms_answer_choices.rb +13 -0
  64. data/lib/decidim/forms.rb +13 -0
  65. data/lib/decidim/forms/admin.rb +9 -0
  66. data/lib/decidim/forms/admin_engine.rb +21 -0
  67. data/lib/decidim/forms/data_portability_user_answers_serializer.rb +37 -0
  68. data/lib/decidim/forms/engine.rb +14 -0
  69. data/lib/decidim/forms/test.rb +4 -0
  70. data/lib/decidim/forms/test/factories.rb +55 -0
  71. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +524 -0
  72. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +626 -0
  73. data/lib/decidim/forms/user_answers_serializer.rb +29 -0
  74. data/lib/decidim/forms/version.rb +10 -0
  75. metadata +165 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ddc9adf1fa3236f89e1a63a9f08ec53daa5c9dca46be2de0ed5855334d9dc81a
4
+ data.tar.gz: 86eb4e54e761e29f03ba5d859bc7303bbaf9770c9f12bb6dda991bfd986e537a
5
+ SHA512:
6
+ metadata.gz: 19cd51ee2b4d5db3bf9857551e840e9a1f5fbfcc839f89e9c6fbbab3af2342d314f7c11baa2da05b8429e58d1cc2e1fb4bcb9ec4ba8e4c7a773a7918064ee1d7
7
+ data.tar.gz: c8da685c765fff9c6d7757a25efc573b3bed4bdb2d441f2c63cd7648224f5560729e6e42a2943740b7cd374689e851a2c0a6b5a613b660c6c9d621ba13c51d7c
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # Decidim::Forms
2
+
3
+ This gem encapsulates the logic to create and manage forms, so it can be reused in other modules, like surveys and meetings.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your module's gemspec:
8
+
9
+ ```ruby
10
+ s.add_dependency "decidim-forms", Decidim::YourModule.version
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ bundle
17
+ ```
18
+
19
+ ## Contributing
20
+
21
+ See [Decidim](https://github.com/decidim/decidim).
22
+
23
+ ## License
24
+
25
+ See [Decidim](https://github.com/decidim/decidim).
26
+
27
+ ## Seeds
28
+
29
+ Since questionnaires cannot exist without a real model we are not including specific seeds for this engine.
30
+
31
+ Other engines are free to include questionnaires on their seeds like this:
32
+
33
+ ```ruby
34
+ Decidim::Forms::Questionnaire.new(
35
+ title: Decidim::Faker::Localized.paragraph,
36
+ description: Decidim::Faker::Localized.wrapped("<p>", "</p>") do
37
+ Decidim::Faker::Localized.paragraph(3)
38
+ end,
39
+ tos: Decidim::Faker::Localized.wrapped("<p>", "</p>") do
40
+ Decidim::Faker::Localized.paragraph(2)
41
+ end,
42
+ )
43
+
44
+ Decidim::Surveys::Survey.create!(component: component, questionnaire: questionnaire)
45
+
46
+ %w(short_answer long_answer).each do |text_question_type|
47
+ Decidim::Forms::Question.create!(
48
+ questionnaire: questionnaire,
49
+ body: Decidim::Faker::Localized.paragraph,
50
+ question_type: text_question_type
51
+ )
52
+ end
53
+
54
+ %w(single_option multiple_option).each do |multiple_choice_question_type|
55
+ question = Decidim::Forms::Question.create!(
56
+ questionnaire: questionnaire,
57
+ body: Decidim::Faker::Localized.paragraph,
58
+ question_type: multiple_choice_question_type
59
+ )
60
+
61
+ 3.times do
62
+ question.answer_options.create!(body: Decidim::Faker::Localized.sentence)
63
+ end
64
+ end
65
+ ```
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/dev/common_rake"
@@ -0,0 +1 @@
1
+ //= link decidim/forms/admin/forms.js
@@ -0,0 +1 @@
1
+ // = link decidim/forms/forms.js
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ viewBox="0 0 36 36" style="enable-background:new 0 0 36 36;" xml:space="preserve">
5
+ <path d="M27,28H9c-0.6,0-1-0.4-1-1V11c0-0.6,0.4-1,1-1h3.1c0.6,0,1,0.4,1,1v1.9h9.7V11c0-0.6,0.4-1,1-1H27c0.6,0,1,0.4,1,1v16
6
+ C28,27.6,27.6,28,27,28z M10,26h16V12h-1.2v1.9c0,0.6-0.4,1-1,1H12.1c-0.6,0-1-0.4-1-1V12H10V26z"/>
7
+ <g>
8
+ <g>
9
+ <path d="M21,11h-6c-0.6,0-1-0.4-1-1s0.4-1,1-1h6c0.6,0,1,0.4,1,1S21.6,11,21,11z"/>
10
+ </g>
11
+ <g>
12
+ <path d="M18.7,11h-1.5c-0.6,0-1-0.4-1-1V8c0-0.6,0.4-1,1-1h1.5c0.6,0,1,0.4,1,1v2C19.7,10.5,19.3,11,18.7,11z"/>
13
+ </g>
14
+ </g>
15
+ <g>
16
+ <path d="M18,36.1c-9.9,0-18-8.1-18-18s8.1-18,18-18s18,8.1,18,18S27.9,36.1,18,36.1z M18,2.1c-8.8,0-16,7.2-16,16s7.2,16,16,16
17
+ s16-7.2,16-16S26.8,2.1,18,2.1z"/>
18
+ </g>
19
+ </svg>
@@ -0,0 +1,25 @@
1
+ ((exports) => {
2
+ class AutoButtonsByMinItemsComponent {
3
+ constructor(options = {}) {
4
+ this.listSelector = options.listSelector;
5
+ this.minItems = options.minItems;
6
+ this.hideOnMinItemsOrLessSelector = options.hideOnMinItemsOrLessSelector;
7
+
8
+ this.run();
9
+ }
10
+
11
+ run() {
12
+ const $list = $(this.listSelector);
13
+ const $items = $list.find(this.hideOnMinItemsOrLessSelector);
14
+
15
+ if ($list.length <= this.minItems) {
16
+ $items.hide();
17
+ } else {
18
+ $items.show();
19
+ }
20
+ }
21
+ }
22
+
23
+ exports.DecidimAdmin = exports.DecidimAdmin || {};
24
+ exports.DecidimAdmin.AutoButtonsByMinItemsComponent = AutoButtonsByMinItemsComponent;
25
+ })(window);
@@ -0,0 +1,23 @@
1
+ ((exports) => {
2
+ class AutoSelectOptionsByTotalItemsComponent {
3
+ constructor(options = {}) {
4
+ this.wrapperSelector = options.wrapperSelector;
5
+ this.selectSelector = options.selectSelector;
6
+ this.listSelector = options.listSelector;
7
+ }
8
+
9
+ run() {
10
+ const $list = $(this.listSelector);
11
+ const $selectField = $list.parents(this.wrapperSelector).find(this.selectSelector);
12
+
13
+ $selectField.find("option").slice(1).remove();
14
+
15
+ for (let idx = 2; idx <= $list.length; idx += 1) {
16
+ $(`<option value="${idx}">${idx}</option>`).appendTo($selectField);
17
+ }
18
+ }
19
+ }
20
+
21
+ exports.DecidimAdmin = exports.DecidimAdmin || {};
22
+ exports.DecidimAdmin.AutoSelectOptionsByTotalItemsComponent = AutoSelectOptionsByTotalItemsComponent;
23
+ })(window);
@@ -0,0 +1,188 @@
1
+ // = require ./auto_buttons_by_min_items.component
2
+ // = require ./auto_select_options_by_total_items.component
3
+
4
+ ((exports) => {
5
+ const { AutoLabelByPositionComponent, AutoButtonsByPositionComponent, AutoButtonsByMinItemsComponent, AutoSelectOptionsByTotalItemsComponent, createFieldDependentInputs, createDynamicFields, createSortList } = exports.DecidimAdmin;
6
+ const { createQuillEditor } = exports.Decidim;
7
+
8
+ const wrapperSelector = ".questionnaire-questions";
9
+ const fieldSelector = ".questionnaire-question";
10
+ const questionTypeSelector = "select[name$=\\[question_type\\]]";
11
+ const answerOptionFieldSelector = ".questionnaire-question-answer-option";
12
+ const answerOptionsWrapperSelector = ".questionnaire-question-answer-options";
13
+ const answerOptionRemoveFieldButtonSelector = ".remove-answer-option";
14
+ const maxChoicesWrapperSelector = ".questionnaire-question-max-choices";
15
+
16
+ const autoLabelByPosition = new AutoLabelByPositionComponent({
17
+ listSelector: ".questionnaire-question:not(.hidden)",
18
+ labelSelector: ".card-title span:first",
19
+ onPositionComputed: (el, idx) => {
20
+ $(el).find("input[name$=\\[position\\]]").val(idx);
21
+ }
22
+ });
23
+
24
+ const autoButtonsByPosition = new AutoButtonsByPositionComponent({
25
+ listSelector: ".questionnaire-question:not(.hidden)",
26
+ hideOnFirstSelector: ".move-up-question",
27
+ hideOnLastSelector: ".move-down-question"
28
+ });
29
+
30
+ const createAutoMaxChoicesByNumberOfAnswerOptions = (fieldId) => {
31
+ return new AutoSelectOptionsByTotalItemsComponent({
32
+ wrapperSelector: fieldSelector,
33
+ selectSelector: `${maxChoicesWrapperSelector} select`,
34
+ listSelector: `#${fieldId} ${answerOptionsWrapperSelector} .questionnaire-question-answer-option:not(.hidden)`
35
+ })
36
+ };
37
+
38
+ const createAutoButtonsByMinItemsForAnswerOptions = (fieldId) => {
39
+ return new AutoButtonsByMinItemsComponent({
40
+ wrapperSelector: fieldSelector,
41
+ listSelector: `#${fieldId} ${answerOptionsWrapperSelector} .questionnaire-question-answer-option:not(.hidden)`,
42
+ minItems: 2,
43
+ hideOnMinItemsOrLessSelector: answerOptionRemoveFieldButtonSelector
44
+ })
45
+ };
46
+
47
+ const createSortableList = () => {
48
+ createSortList(".questionnaire-questions-list:not(.published)", {
49
+ handle: ".question-divider",
50
+ placeholder: '<div style="border-style: dashed; border-color: #000"></div>',
51
+ forcePlaceholderSize: true,
52
+ onSortUpdate: () => { autoLabelByPosition.run() }
53
+ });
54
+ };
55
+
56
+ const createDynamicFieldsForAnswerOptions = (fieldId) => {
57
+ const autoButtons = createAutoButtonsByMinItemsForAnswerOptions(fieldId);
58
+ const autoSelectOptions = createAutoMaxChoicesByNumberOfAnswerOptions(fieldId);
59
+
60
+ return createDynamicFields({
61
+ placeholderId: "questionnaire-question-answer-option-id",
62
+ wrapperSelector: `#${fieldId} ${answerOptionsWrapperSelector}`,
63
+ containerSelector: ".questionnaire-question-answer-options-list",
64
+ fieldSelector: answerOptionFieldSelector,
65
+ addFieldButtonSelector: ".add-answer-option",
66
+ removeFieldButtonSelector: answerOptionRemoveFieldButtonSelector,
67
+ onAddField: () => {
68
+ autoButtons.run();
69
+ autoSelectOptions.run();
70
+ },
71
+ onRemoveField: () => {
72
+ autoButtons.run();
73
+ autoSelectOptions.run();
74
+ }
75
+ });
76
+ };
77
+
78
+ const dynamicFieldsForAnswerOptions = {};
79
+
80
+ const isMultipleChoiceOption = ($selectField) => {
81
+ const value = $selectField.val();
82
+
83
+ return value === "single_option" || value === "multiple_option" || value === "sorting"
84
+ }
85
+
86
+ const setupInitialQuestionAttributes = ($target) => {
87
+ const fieldId = $target.attr("id");
88
+ const $fieldQuestionTypeSelect = $target.find(questionTypeSelector);
89
+
90
+ createFieldDependentInputs({
91
+ controllerField: $fieldQuestionTypeSelect,
92
+ wrapperSelector: fieldSelector,
93
+ dependentFieldsSelector: answerOptionsWrapperSelector,
94
+ dependentInputSelector: `${answerOptionFieldSelector} input`,
95
+ enablingCondition: ($field) => {
96
+ return isMultipleChoiceOption($field);
97
+ }
98
+ });
99
+
100
+ createFieldDependentInputs({
101
+ controllerField: $fieldQuestionTypeSelect,
102
+ wrapperSelector: fieldSelector,
103
+ dependentFieldsSelector: maxChoicesWrapperSelector,
104
+ dependentInputSelector: "select",
105
+ enablingCondition: ($field) => {
106
+ return $field.val() === "multiple_option"
107
+ }
108
+ });
109
+
110
+ dynamicFieldsForAnswerOptions[fieldId] = createDynamicFieldsForAnswerOptions(fieldId);
111
+
112
+ const dynamicFields = dynamicFieldsForAnswerOptions[fieldId];
113
+
114
+ const onQuestionTypeChange = () => {
115
+ if (isMultipleChoiceOption($fieldQuestionTypeSelect)) {
116
+ const nOptions = $fieldQuestionTypeSelect.parents(fieldSelector).find(answerOptionFieldSelector).length;
117
+
118
+ if (nOptions === 0) {
119
+ dynamicFields._addField();
120
+ dynamicFields._addField();
121
+ }
122
+ }
123
+ };
124
+
125
+ $fieldQuestionTypeSelect.on("change", onQuestionTypeChange);
126
+
127
+ onQuestionTypeChange();
128
+ }
129
+
130
+ const hideDeletedQuestion = ($target) => {
131
+ const inputDeleted = $target.find("input[name$=\\[deleted\\]]").val();
132
+
133
+ if (inputDeleted === "true") {
134
+ $target.addClass("hidden");
135
+ $target.hide();
136
+ }
137
+ }
138
+
139
+ createDynamicFields({
140
+ placeholderId: "questionnaire-question-id",
141
+ wrapperSelector: wrapperSelector,
142
+ containerSelector: ".questionnaire-questions-list",
143
+ fieldSelector: fieldSelector,
144
+ addFieldButtonSelector: ".add-question",
145
+ removeFieldButtonSelector: ".remove-question",
146
+ moveUpFieldButtonSelector: ".move-up-question",
147
+ moveDownFieldButtonSelector: ".move-down-question",
148
+ onAddField: ($field) => {
149
+ setupInitialQuestionAttributes($field);
150
+ createSortableList();
151
+
152
+ $field.find(".editor-container").each((idx, el) => {
153
+ createQuillEditor(el);
154
+ });
155
+
156
+ autoLabelByPosition.run();
157
+ autoButtonsByPosition.run();
158
+ },
159
+ onRemoveField: ($field) => {
160
+ autoLabelByPosition.run();
161
+ autoButtonsByPosition.run();
162
+
163
+ $field.find(answerOptionRemoveFieldButtonSelector).each((idx, el) => {
164
+ dynamicFieldsForAnswerOptions[$field.attr("id")]._removeField(el);
165
+ });
166
+ },
167
+ onMoveUpField: () => {
168
+ autoLabelByPosition.run();
169
+ autoButtonsByPosition.run();
170
+ },
171
+ onMoveDownField: () => {
172
+ autoLabelByPosition.run();
173
+ autoButtonsByPosition.run();
174
+ }
175
+ });
176
+
177
+ createSortableList();
178
+
179
+ $(fieldSelector).each((idx, el) => {
180
+ const $target = $(el);
181
+
182
+ hideDeletedQuestion($target);
183
+ setupInitialQuestionAttributes($target);
184
+ });
185
+
186
+ autoLabelByPosition.run();
187
+ autoButtonsByPosition.run();
188
+ })(window);
@@ -0,0 +1,65 @@
1
+ ((exports) => {
2
+ class AutosortableCheckboxesComponent {
3
+ constructor(options = {}) {
4
+ this.wrapperField = options.wrapperField;
5
+ this._bindEvent();
6
+ this._run();
7
+ }
8
+
9
+ _run() {
10
+ $(this.wrapperField).find("input[type=checkbox]").each((idx, el) => {
11
+ const $parentLabel = $(el).parents("label");
12
+
13
+ if ($(el).is(":checked")) {
14
+ const $lastSorted = this.wrapperField.find("label.sorted").last();
15
+
16
+ if ($lastSorted.length > 0) {
17
+ $lastSorted.removeClass("last-sorted");
18
+ $parentLabel.insertAfter($lastSorted);
19
+ } else {
20
+ $parentLabel.insertBefore(this.wrapperField.find("label:first-child"));
21
+ }
22
+
23
+ $parentLabel.addClass("sorted");
24
+ $parentLabel.addClass("last-sorted");
25
+ } else {
26
+ const $lastUnsorted = this.wrapperField.find("label:not(.sorted)").last();
27
+
28
+ if ($lastUnsorted.length > 0) {
29
+ $parentLabel.insertBefore($lastUnsorted);
30
+ } else {
31
+ $parentLabel.insertAfter(this.wrapperField.find("label:last-child"));
32
+ }
33
+
34
+ $parentLabel.removeClass("sorted");
35
+ }
36
+ });
37
+
38
+ $(this.wrapperField).find("label").each((idx, el) => {
39
+ const $positionSelector = $(el).find(".position");
40
+ const $positionField = $(el).find("input[name$=\\[position\\]]");
41
+
42
+ if ($(el).hasClass("sorted")) {
43
+ $positionField.val(idx);
44
+ $positionField.prop("disabled", false);
45
+ $positionSelector.html(`${idx + 1}. `);
46
+ } else {
47
+ $positionField.val("");
48
+ $positionField.prop("disabled", true);
49
+ $positionSelector.html("");
50
+ }
51
+ });
52
+ }
53
+
54
+ _bindEvent() {
55
+ $(this.wrapperField).find("input[type=checkbox]").on("change", () => {
56
+ this._run();
57
+ });
58
+ }
59
+ }
60
+
61
+ exports.Decidim = exports.Decidim || {};
62
+ exports.Decidim.createAutosortableCheckboxes = (options) => {
63
+ return new AutosortableCheckboxesComponent(options);
64
+ };
65
+ })(window);
@@ -0,0 +1,20 @@
1
+ // = require ./option_attached_inputs.component
2
+ // = require ./autosortable_checkboxes.component
3
+
4
+ ((exports) => {
5
+ const { createOptionAttachedInputs, createAutosortableCheckboxes } = exports.Decidim;
6
+
7
+ $(".radio-button-collection, .check-box-collection").each((idx, el) => {
8
+ createOptionAttachedInputs({
9
+ wrapperField: $(el),
10
+ controllerFieldSelector: "input[type=radio], input[type=checkbox]",
11
+ dependentInputSelector: "input[type=text], input[type=hidden]"
12
+ });
13
+ });
14
+
15
+ $(".sortable-check-box-collection").each((idx, el) => {
16
+ createAutosortableCheckboxes({
17
+ wrapperField: $(el)
18
+ })
19
+ });
20
+ })(window);
@@ -0,0 +1,32 @@
1
+ ((exports) => {
2
+ class OptionAttachedInputsComponent {
3
+ constructor(options = {}) {
4
+ this.wrapperField = options.wrapperField;
5
+ this.controllerFieldSelector = options.controllerFieldSelector;
6
+ this.dependentInputSelector = options.dependentInputSelector;
7
+ this.controllerSelector = this.wrapperField.find(this.controllerFieldSelector);
8
+ this._bindEvent();
9
+ this._run();
10
+ }
11
+
12
+ _run() {
13
+ this.controllerSelector.each((idx, el) => {
14
+ const $field = $(el);
15
+ const enabled = $field.is(":checked");
16
+
17
+ $field.parents("label").find(this.dependentInputSelector).prop("disabled", !enabled);
18
+ });
19
+ }
20
+
21
+ _bindEvent() {
22
+ this.controllerSelector.on("change", () => {
23
+ this._run();
24
+ });
25
+ }
26
+ }
27
+
28
+ exports.Decidim = exports.Decidim || {};
29
+ exports.Decidim.createOptionAttachedInputs = (options) => {
30
+ return new OptionAttachedInputsComponent(options);
31
+ };
32
+ })(window);