formstrap 0.4.0 → 0.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c4dc719e94a4901d00b1b1cfce0d9c6a36653ec1bf706b56d689092db97b278d
4
- data.tar.gz: 902aab69bbe1517164fd888d55a4a881522a4e313cbe77b2596486711912ca1c
3
+ metadata.gz: 47528e297776dc1c0bfaf1d0d15fcbe65a6872631c1275d4cfcd1af722b92bad
4
+ data.tar.gz: b8002a2e136bc2b14ae89b41a7641d9562cf23a151d6f37c94bb07d7fdcbcc99
5
5
  SHA512:
6
- metadata.gz: 2691612aa8b8a8362495627b48cd7008e88f510a7b285242e8413111599a685fd05bcc6babd241f7d4b98456e4d31b465e1be0b4549672a2e320c1a4ac3650d7
7
- data.tar.gz: 707a301d754f4bb13280c008994b6971b4844698206b6d1a7bd3537c794c5d2e90c76d50dc9351956661be43831dc1c8d64fd31fe177f1ad47e6eb5b450b387e
6
+ metadata.gz: 402ca1e7525e7847453c7026d46828c6c60f73020cd77d927757cdbbecfbb29e3dbfad79cc08b3ffcb1e95be5b66d490fa437f4d52eda80c1180a68f2e7d5b6f
7
+ data.tar.gz: 764ed214b9c39f07a01a7028b0a2b65ef4c3719717db522efd86936231eba94151f008d81274920af8d697ececef6fc60deca7ab3db0bfaa9c82b9ae4c727301
@@ -1,3 +1,4 @@
1
+ /* global crypto */
1
2
  import { Controller } from '@hotwired/stimulus'
2
3
  import Sortable from 'sortablejs'
3
4
 
@@ -193,7 +194,7 @@ export default class extends Controller {
193
194
 
194
195
  randomizeIds (template) {
195
196
  const regex = new RegExp(template.dataset.templateIdRegex, 'g')
196
- const randomNumber = Math.floor(100000000 + Math.random() * 900000000)
197
+ const randomNumber = crypto.randomUUID().substring(0, 8)
197
198
  return template.innerHTML.replace(regex, randomNumber)
198
199
  }
199
200
 
@@ -126,7 +126,8 @@ export default class extends Controller {
126
126
  const formData = new FormData()
127
127
 
128
128
  // Replace all occurrences of "page[blocks_attributes][0]" with "block"
129
- const regex = /\w+\[([^\]]+)s_attributes]\[\d+]/g
129
+ // Replace all occurrences of "form[fields_attributes][random]" with "field"
130
+ const regex = /\w+\[([^\]]+)s_attributes]\[[^\]]+]/g
130
131
  const formElements = fields.querySelectorAll('input[name]:not([name$="[id]"]), select[name]:not([name$="[id]"]), textarea[name]:not([name$="[id]"]), button[name]:not([name$="[id]"])')
131
132
  formElements.forEach((element) => {
132
133
  const currentName = element.getAttribute('name')
@@ -1,3 +1,4 @@
1
+ /* global crypto */
1
2
  import { Controller } from '@hotwired/stimulus'
2
3
  import Sortable from 'sortablejs'
3
4
 
@@ -23,7 +24,6 @@ export default class extends Controller {
23
24
  this.resetPositions()
24
25
  }
25
26
  })
26
-
27
27
  this.toggleEmpty()
28
28
  }
29
29
 
@@ -38,8 +38,7 @@ export default class extends Controller {
38
38
  }
39
39
 
40
40
  updatePopupButtonIndices (index) {
41
- const popup = document.querySelector(`[data-popup-target="popup"][data-popup-id="repeater-buttons-${this.idValue}"]`)
42
- const buttons = popup.querySelectorAll('[data-popup-target="button"]')
41
+ const buttons = document.querySelectorAll(`[data-popup-target="button"][data-popup-id="repeater-buttons-${this.idValue}"]`)
43
42
  buttons.forEach((button) => {
44
43
  button.dataset.rowIndex = index
45
44
  })
@@ -53,7 +52,7 @@ export default class extends Controller {
53
52
 
54
53
  // Prepare html from template
55
54
  let template = this.getTemplate(templateName).content.cloneNode(true)
56
- template = this.replaceIdsWithTimestamps(template)
55
+ template = this.randomizeIds(template)
57
56
 
58
57
  // Fallback to last row if no index is set
59
58
  if (rowIndex) {
@@ -107,44 +106,24 @@ export default class extends Controller {
107
106
  })[0]
108
107
  }
109
108
 
110
- replaceIdsWithTimestamps (template) {
111
- const pattern = 'rrrrrrrrr'
112
- const replacement = new Date().getTime().toString()
109
+ randomizeIds (template) {
110
+ const randomNumber = crypto.randomUUID().substring(0, 8)
111
+ const pattern = `_${this.idValue}_`
113
112
  const regex = new RegExp(pattern, 'g')
114
113
 
115
- // Replace ids
116
- template.querySelectorAll(`input[id*="${pattern}"], select[id*="${pattern}"], textarea[id*="${pattern}"], button[id*="${pattern}"]`).forEach((node) => {
117
- const idValue = node.getAttribute('id')
118
- node.setAttribute('id', idValue.replace(pattern, replacement))
119
- })
120
-
121
- // Search and replace pattern in templates
122
- template.querySelectorAll('template').forEach((node) => {
123
- node.innerHTML = node.innerHTML.replace(regex, replacement)
124
- })
125
-
126
- // Replace labels
127
- template.querySelectorAll(`label[for*="${pattern}"]`).forEach((node) => {
128
- const forValue = node.getAttribute('for')
129
- node.setAttribute('for', forValue.replace(pattern, replacement))
130
- })
131
-
132
- // Replace names
133
- template.querySelectorAll(`input[name*="${pattern}"], select[name*="${pattern}"], textarea[name*="${pattern}"], button[name*="${pattern}"]`).forEach((node) => {
134
- const nameValue = node.getAttribute('name')
135
- node.setAttribute('name', nameValue.replace(pattern, replacement))
136
- })
137
-
138
- // Replace offcanvas targets
139
- template.querySelectorAll(`div[data-bs-target="#offcanvas-${pattern}"]`).forEach((node) => {
140
- const targetValue = node.getAttribute('data-bs-target')
141
- node.setAttribute('data-bs-target', targetValue.replace(pattern, replacement))
142
- })
114
+ // Loop through each node in the template
115
+ template.querySelectorAll('*').forEach(node => {
116
+ // Replace attribute values
117
+ for (const attribute of node.attributes) {
118
+ if (attribute.value.includes(pattern)) {
119
+ attribute.value = attribute.value.replace(pattern, randomNumber)
120
+ }
121
+ }
143
122
 
144
- // Replace offcanvas ids
145
- template.querySelectorAll(`.offcanvas[id="offcanvas-${pattern}"]`).forEach((node) => {
146
- const idValue = node.getAttribute('id')
147
- node.setAttribute('id', idValue.replace(pattern, replacement))
123
+ // Replace template content
124
+ if (node.nodeName === 'TEMPLATE' && node.innerHTML.includes(pattern)) {
125
+ node.innerHTML = node.innerHTML.replace(regex, randomNumber)
126
+ }
148
127
  })
149
128
 
150
129
  return template
@@ -11213,7 +11213,7 @@ var media_controller_default = class extends Controller {
11213
11213
  }
11214
11214
  randomizeIds(template) {
11215
11215
  const regex = new RegExp(template.dataset.templateIdRegex, "g");
11216
- const randomNumber = Math.floor(1e8 + Math.random() * 9e8);
11216
+ const randomNumber = crypto.randomUUID().substring(0, 8);
11217
11217
  return template.innerHTML.replace(regex, randomNumber);
11218
11218
  }
11219
11219
  removeAllDeselectedItems(items) {
@@ -11498,7 +11498,7 @@ var nested_preview_controller_default = class extends Controller {
11498
11498
  buildFormData() {
11499
11499
  const fields = this.fieldsTarget;
11500
11500
  const formData = new FormData();
11501
- const regex = /\w+\[([^\]]+)s_attributes]\[\d+]/g;
11501
+ const regex = /\w+\[([^\]]+)s_attributes]\[[^\]]+]/g;
11502
11502
  const formElements = fields.querySelectorAll('input[name]:not([name$="[id]"]), select[name]:not([name$="[id]"]), textarea[name]:not([name$="[id]"]), button[name]:not([name$="[id]"])');
11503
11503
  formElements.forEach((element) => {
11504
11504
  const currentName = element.getAttribute("name");
@@ -13276,8 +13276,7 @@ var repeater_controller_default = class extends Controller {
13276
13276
  return this.rowTargets.includes(row);
13277
13277
  }
13278
13278
  updatePopupButtonIndices(index2) {
13279
- const popup = document.querySelector(`[data-popup-target="popup"][data-popup-id="repeater-buttons-${this.idValue}"]`);
13280
- const buttons = popup.querySelectorAll('[data-popup-target="button"]');
13279
+ const buttons = document.querySelectorAll(`[data-popup-target="button"][data-popup-id="repeater-buttons-${this.idValue}"]`);
13281
13280
  buttons.forEach((button) => {
13282
13281
  button.dataset.rowIndex = index2;
13283
13282
  });
@@ -13288,7 +13287,7 @@ var repeater_controller_default = class extends Controller {
13288
13287
  const templateName = button.dataset.templateName;
13289
13288
  const rowIndex = button.dataset.rowIndex;
13290
13289
  let template = this.getTemplate(templateName).content.cloneNode(true);
13291
- template = this.replaceIdsWithTimestamps(template);
13290
+ template = this.randomizeIds(template);
13292
13291
  if (rowIndex) {
13293
13292
  const row = this.rowTargets[rowIndex];
13294
13293
  this.listTarget.insertBefore(template, row.nextSibling);
@@ -13324,32 +13323,19 @@ var repeater_controller_default = class extends Controller {
13324
13323
  return template.dataset.templateName === name;
13325
13324
  })[0];
13326
13325
  }
13327
- replaceIdsWithTimestamps(template) {
13328
- const pattern = "rrrrrrrrr";
13329
- const replacement = new Date().getTime().toString();
13326
+ randomizeIds(template) {
13327
+ const randomNumber = crypto.randomUUID().substring(0, 8);
13328
+ const pattern = `_${this.idValue}_`;
13330
13329
  const regex = new RegExp(pattern, "g");
13331
- template.querySelectorAll(`input[id*="${pattern}"], select[id*="${pattern}"], textarea[id*="${pattern}"], button[id*="${pattern}"]`).forEach((node) => {
13332
- const idValue = node.getAttribute("id");
13333
- node.setAttribute("id", idValue.replace(pattern, replacement));
13334
- });
13335
- template.querySelectorAll("template").forEach((node) => {
13336
- node.innerHTML = node.innerHTML.replace(regex, replacement);
13337
- });
13338
- template.querySelectorAll(`label[for*="${pattern}"]`).forEach((node) => {
13339
- const forValue = node.getAttribute("for");
13340
- node.setAttribute("for", forValue.replace(pattern, replacement));
13341
- });
13342
- template.querySelectorAll(`input[name*="${pattern}"], select[name*="${pattern}"], textarea[name*="${pattern}"], button[name*="${pattern}"]`).forEach((node) => {
13343
- const nameValue = node.getAttribute("name");
13344
- node.setAttribute("name", nameValue.replace(pattern, replacement));
13345
- });
13346
- template.querySelectorAll(`div[data-bs-target="#offcanvas-${pattern}"]`).forEach((node) => {
13347
- const targetValue = node.getAttribute("data-bs-target");
13348
- node.setAttribute("data-bs-target", targetValue.replace(pattern, replacement));
13349
- });
13350
- template.querySelectorAll(`.offcanvas[id="offcanvas-${pattern}"]`).forEach((node) => {
13351
- const idValue = node.getAttribute("id");
13352
- node.setAttribute("id", idValue.replace(pattern, replacement));
13330
+ template.querySelectorAll("*").forEach((node) => {
13331
+ for (const attribute of node.attributes) {
13332
+ if (attribute.value.includes(pattern)) {
13333
+ attribute.value = attribute.value.replace(pattern, randomNumber);
13334
+ }
13335
+ }
13336
+ if (node.nodeName === "TEMPLATE" && node.innerHTML.includes(pattern)) {
13337
+ node.innerHTML = node.innerHTML.replace(regex, randomNumber);
13338
+ }
13353
13339
  });
13354
13340
  return template;
13355
13341
  }
@@ -106,8 +106,9 @@
106
106
  class="btn btn-sm btn-outline-secondary"
107
107
  data-repeater-target="addButton"
108
108
  data-popup-target="button"
109
- data-popup-id="<%= "repeater-buttons-#{repeater_id}" %>"
109
+ data-popup-id="repeater-buttons-<%= repeater_id %>"
110
110
  data-popup-pass-thru="<%= pass_thru %>"
111
+ data-row-index=""
111
112
  data-action="click->repeater#resetButtonIndices click->popup#open"
112
113
  >
113
114
  <%= bootstrap_icon("plus") %>
@@ -121,7 +122,7 @@
121
122
  <div
122
123
  class="btn btn-sm btn-outline-secondary"
123
124
  data-popup-target="button"
124
- data-popup-id="<%= "repeater-buttons-#{repeater_id}" %>"
125
+ data-popup-id="repeater-buttons-<%= repeater_id %>"
125
126
  data-action="click->repeater#addRow click->popup#close"
126
127
  data-row-index=""
127
128
  data-template-name="<%= name %>"
@@ -135,7 +136,7 @@
135
136
  <!-- Templates -->
136
137
  <% template_names.each do |template_name| %>
137
138
  <template data-repeater-target="template" data-template-name="<%= template_name %>">
138
- <%= form.fields_for attribute, association_object, child_index: "rrrrrrrrr" do |ff| %>
139
+ <%= form.fields_for attribute, association_object, child_index: "_#{repeater_id}_" do |ff| %>
139
140
  <%= render "formstrap/repeater/row", row_options.merge(form: ff, pass_thru: pass_thru, repeater_id: repeater_id, index: nil, template_name: template_name) do %>
140
141
  <%= yield(ff, template_name) %>
141
142
  <% end %>
@@ -41,7 +41,7 @@
41
41
  title="<%= t(".add") %>"
42
42
  data-repeater-target="addButton"
43
43
  data-popup-target="button"
44
- data-popup-id="<%= "repeater-buttons-#{repeater_id}" %>"
44
+ data-popup-id="repeater-buttons-<%= repeater_id %>"
45
45
  data-popup-pass-thru="<%= pass_thru %>"
46
46
  data-action="click->repeater#resetButtonIndices click->popup#open"
47
47
  >
@@ -1,3 +1,3 @@
1
1
  module Formstrap
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontierdotbe/formstrap",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "description": "Bootstrap-powered Form Helpers",
5
5
  "module": "app/assets/javascripts/formstrap.js",
6
6
  "main": "app/assets/javascripts/formstrap.js",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: formstrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jef Vlamings
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-09 00:00:00.000000000 Z
11
+ date: 2024-05-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: An extensive Bootstrap form library to power your Ruby On Rails application.
14
14
  email: