bullet_train-fields 1.6.37 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/concerns/fields/super_select_support.rb +2 -2
- data/app/helpers/account/forms_helper.rb +2 -2
- data/app/javascript/controllers/fields/color_picker_controller.js +22 -23
- data/app/javascript/controllers/fields/date_controller.js +83 -44
- data/app/javascript/controllers/fields/super_select_controller.js +18 -12
- data/lib/bullet_train/fields/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15e17d1f6ce3e83a96ffb6010b7f8f42f2bcb87870cd48ed182cc4947d3b6470
|
4
|
+
data.tar.gz: 03a1f3b08a2d14a6395d81c12ab83ea48f9987c81db7abb185d7e535a034cc05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fed2c6efd2436abf9231a3c0ed31facc653a5dd95373aac3bdd0502bb1b970ce1522c07e6ee2f5cf7b4c42898104d093346d8db6516cdfca209a8e760410bfd8
|
7
|
+
data.tar.gz: 3ba2447f87e6e4a82e7a983f9facabe764453c20b186cce1b26f160ced3ea572811e19f5517c1beee7b7677a083785bd3cef0c6d246a6880f38f7760c19fa46b
|
@@ -11,7 +11,7 @@ module Fields::SuperSelectSupport
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def create_model_if_new(id)
|
14
|
-
ActiveSupport::Deprecation.warn(
|
14
|
+
ActiveSupport::Deprecation.new.warn(
|
15
15
|
"#create_model_if_new is deprecated. " \
|
16
16
|
"Use #ensure_backing_models_on instead. See examples at https://bullettrain.co/docs/field-partials/super-select#accepting-new-entries"
|
17
17
|
)
|
@@ -24,7 +24,7 @@ module Fields::SuperSelectSupport
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def create_models_if_new(ids)
|
27
|
-
ActiveSupport::Deprecation.warn(
|
27
|
+
ActiveSupport::Deprecation.new.warn(
|
28
28
|
"#create_models_if_new is deprecated. " \
|
29
29
|
"Use #ensure_backing_models_on instead. See examples at https://bullettrain.co/docs/field-partials/super-select#accepting-new-entries"
|
30
30
|
)
|
@@ -33,13 +33,13 @@ module Account::FormsHelper
|
|
33
33
|
|
34
34
|
def labels_for(form, method)
|
35
35
|
keys = [:placeholder, :label, :help, :options_help]
|
36
|
-
path = [model_key(form),
|
36
|
+
path = [model_key(form), current_fields_namespace || :fields, method].compact
|
37
37
|
Struct.new(*keys).new(*keys.map { |key| t((path + [key]).join("."), default: "").presence })
|
38
38
|
end
|
39
39
|
|
40
40
|
def options_for(form, method)
|
41
41
|
# e.g. "scaffolding/completely_concrete/tangible_things.fields.text_area_value.options"
|
42
|
-
path = [model_key(form),
|
42
|
+
path = [model_key(form), current_fields_namespace || :fields, method, :options]
|
43
43
|
options = t(path.compact.join("."))
|
44
44
|
return options unless options.is_a?(Hash)
|
45
45
|
options.stringify_keys
|
@@ -21,27 +21,22 @@ export default class extends Controller {
|
|
21
21
|
|
22
22
|
connect() {
|
23
23
|
this.initPluginInstance()
|
24
|
-
this.colorOptions = $(this.colorOptionsTarget)
|
25
|
-
.find('button')
|
26
|
-
.map(function (_, button) {
|
27
|
-
return $(button).attr('data-color').toLowerCase()
|
28
|
-
})
|
29
|
-
.get()
|
30
24
|
}
|
31
25
|
|
32
26
|
disconnect() {
|
33
27
|
this.teardownPluginInstance()
|
34
28
|
}
|
35
29
|
|
30
|
+
|
31
|
+
|
36
32
|
pickColor(event) {
|
37
33
|
event.preventDefault()
|
38
34
|
|
39
|
-
const
|
40
|
-
const color = targetEl.dataset.color
|
35
|
+
const color = event.target.dataset.color
|
41
36
|
|
42
|
-
|
43
|
-
|
44
|
-
|
37
|
+
this.colorInputTarget.value = color
|
38
|
+
this.colorPickerValueTarget.value = color
|
39
|
+
this.userSelectedColorTarget.dataset.color = color
|
45
40
|
|
46
41
|
this.pickr.setColor(color)
|
47
42
|
}
|
@@ -61,21 +56,20 @@ export default class extends Controller {
|
|
61
56
|
}
|
62
57
|
|
63
58
|
showUserSelectedColor(color) {
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
.show()
|
59
|
+
this.colorInputTarget.value = color
|
60
|
+
this.colorPickerValueTarget.value = color
|
61
|
+
|
62
|
+
this.userSelectedColorTarget.style.backgroundColor = color
|
63
|
+
this.userSelectedColorTarget.style.setProperty('--tw-ring-color', color)
|
64
|
+
this.userSelectedColorTarget.setAttribute('data-color', color)
|
65
|
+
this.userSelectedColorTarget.classList.remove('hidden')
|
72
66
|
}
|
73
67
|
|
74
68
|
unpickColor(event) {
|
75
69
|
event.preventDefault()
|
76
|
-
|
77
|
-
|
78
|
-
|
70
|
+
this.colorPickerValueTarget.value = ''
|
71
|
+
this.colorInputTarget.value = ''
|
72
|
+
this.userSelectedColorTarget.classList.add('hidden')
|
79
73
|
this.dispatchChangeEvent()
|
80
74
|
}
|
81
75
|
|
@@ -146,7 +140,12 @@ export default class extends Controller {
|
|
146
140
|
this.pickr.destroy()
|
147
141
|
}
|
148
142
|
|
143
|
+
get colorOptions () {
|
144
|
+
const colorButtons = this.colorOptionsTarget.querySelectorAll('button[data-color]')
|
145
|
+
return Array.from(colorButtons).map(button => button.getAttribute('data-color').toLowerCase());
|
146
|
+
}
|
147
|
+
|
149
148
|
get selectedColor() {
|
150
|
-
return
|
149
|
+
return this.colorInputTarget.value
|
151
150
|
}
|
152
151
|
}
|
@@ -2,8 +2,10 @@ import { Controller } from "@hotwired/stimulus"
|
|
2
2
|
require("daterangepicker/daterangepicker.css");
|
3
3
|
|
4
4
|
// requires jQuery, moment, might want to consider a vanilla JS alternative
|
5
|
+
import jquery from "jquery";
|
5
6
|
import 'daterangepicker';
|
6
7
|
import moment from 'moment-timezone'
|
8
|
+
import select2 from "select2";
|
7
9
|
|
8
10
|
export default class extends Controller {
|
9
11
|
static targets = [ "field", "displayField", "clearButton", "currentTimeZoneWrapper", "timeZoneButtons", "timeZoneSelectWrapper", "timeZoneField", "timeZoneSelect" ]
|
@@ -17,6 +19,19 @@ export default class extends Controller {
|
|
17
19
|
pickerLocale: { type: Object, default: {} }
|
18
20
|
}
|
19
21
|
|
22
|
+
initialize() {
|
23
|
+
if (window.jQuery === undefined) {
|
24
|
+
window.jQuery = jquery // required for select2 used for time zone select, but we also use global jQuery throughout below
|
25
|
+
}
|
26
|
+
if (!this.isSelect2LoadedOnWindowJquery) {
|
27
|
+
select2()
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
get isSelect2LoadedOnWindowJquery() {
|
32
|
+
return window?.jQuery?.fn?.select2 !== undefined
|
33
|
+
}
|
34
|
+
|
20
35
|
connect() {
|
21
36
|
this.initPluginInstance()
|
22
37
|
}
|
@@ -29,13 +44,13 @@ export default class extends Controller {
|
|
29
44
|
// don't submit the form, unless it originated from the cancel/clear button
|
30
45
|
event.preventDefault()
|
31
46
|
|
32
|
-
|
33
|
-
|
47
|
+
this.fieldTarget.value = ''
|
48
|
+
this.displayFieldTarget.value = ''
|
34
49
|
}
|
35
50
|
|
36
51
|
currentTimeZone(){
|
37
52
|
return (
|
38
|
-
( this.hasTimeZoneSelectWrapperTarget &&
|
53
|
+
( this.hasTimeZoneSelectWrapperTarget && jQuery(this.timeZoneSelectWrapperTarget).is(":visible") && this.timeZoneSelectTarget.value ) ||
|
39
54
|
( this.hasTimeZoneFieldTarget && this.timeZoneFieldTarget.value ) ||
|
40
55
|
this.currentTimeZoneValue
|
41
56
|
)
|
@@ -51,8 +66,8 @@ export default class extends Controller {
|
|
51
66
|
)
|
52
67
|
const displayVal = momentVal.format(format)
|
53
68
|
const dataVal = this.includeTimeValue ? momentVal.toISOString(true) : momentVal.format('YYYY-MM-DD')
|
54
|
-
|
55
|
-
|
69
|
+
this.displayFieldTarget.value = displayVal
|
70
|
+
this.fieldTarget.value = dataVal
|
56
71
|
// bubble up a change event when the input is updated for other listeners
|
57
72
|
if(picker){
|
58
73
|
this.displayFieldTarget.dispatchEvent(new CustomEvent('change', { detail: { picker: picker }}))
|
@@ -63,8 +78,8 @@ export default class extends Controller {
|
|
63
78
|
// don't follow the anchor
|
64
79
|
event.preventDefault()
|
65
80
|
|
66
|
-
|
67
|
-
|
81
|
+
this.currentTimeZoneWrapperTarget.classList.toggle('hidden')
|
82
|
+
this.timeZoneButtonsTarget.classList.toggle('hidden')
|
68
83
|
}
|
69
84
|
|
70
85
|
// triggered on other click from the timezone buttons
|
@@ -72,23 +87,23 @@ export default class extends Controller {
|
|
72
87
|
// don't follow the anchor
|
73
88
|
event.preventDefault()
|
74
89
|
|
75
|
-
|
90
|
+
this.timeZoneButtonsTarget.classList.toggle('hidden')
|
76
91
|
if (this.hasTimeZoneSelectWrapperTarget) {
|
77
|
-
|
92
|
+
this.timeZoneSelectWrapperTarget.classList.toggle('hidden')
|
78
93
|
}
|
79
94
|
if(!["", null].includes(this.fieldTarget.value)){
|
80
|
-
|
95
|
+
jQuery(this.displayFieldTarget).trigger("apply.daterangepicker");
|
81
96
|
}
|
82
97
|
}
|
83
98
|
|
84
99
|
resetTimeZoneUI(e) {
|
85
100
|
e && e.preventDefault()
|
86
101
|
|
87
|
-
|
88
|
-
|
102
|
+
this.currentTimeZoneWrapperTarget.classList.remove('hidden')
|
103
|
+
this.timeZoneButtonsTarget.classList.add('hidden')
|
89
104
|
|
90
105
|
if (this.hasTimeZoneSelectWrapperTarget) {
|
91
|
-
|
106
|
+
this.timeZoneSelectWrapperTarget.classList.add('hidden')
|
92
107
|
}
|
93
108
|
}
|
94
109
|
|
@@ -97,20 +112,26 @@ export default class extends Controller {
|
|
97
112
|
// don't follow the anchor
|
98
113
|
event.preventDefault()
|
99
114
|
const currentTimeZoneEl = this.currentTimeZoneWrapperTarget.querySelector('a')
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
115
|
+
if (this.hasTimeZoneFieldTarget) {
|
116
|
+
this.timeZoneFieldTarget.value = event.target.dataset.value
|
117
|
+
}
|
118
|
+
currentTimeZoneEl.textContent = event.target.dataset.label
|
119
|
+
this.element.querySelectorAll('.time-zone-button').forEach(el => {
|
120
|
+
el.classList.remove('button');
|
121
|
+
el.classList.add('button-alternative');
|
122
|
+
});
|
123
|
+
event.target.classList.remove('button-alternative')
|
124
|
+
event.target.classList.add('button')
|
104
125
|
this.resetTimeZoneUI()
|
105
126
|
if(!["", null].includes(this.fieldTarget.value)){
|
106
|
-
|
127
|
+
jQuery(this.displayFieldTarget).trigger("apply.daterangepicker");
|
107
128
|
}
|
108
129
|
}
|
109
130
|
|
110
131
|
// triggered on selecting a new timezone from the timezone picker
|
111
132
|
selectTimeZoneChange(event) {
|
112
133
|
if(!["", null].includes(this.fieldTarget.value)){
|
113
|
-
|
134
|
+
jQuery(this.displayFieldTarget).trigger("apply.daterangepicker");
|
114
135
|
}
|
115
136
|
}
|
116
137
|
|
@@ -119,7 +140,7 @@ export default class extends Controller {
|
|
119
140
|
event.preventDefault()
|
120
141
|
this.resetTimeZoneUI()
|
121
142
|
if(!["", null].includes(this.fieldTarget.value)){
|
122
|
-
|
143
|
+
jQuery(this.displayFieldTarget).trigger("apply.daterangepicker")
|
123
144
|
}
|
124
145
|
}
|
125
146
|
|
@@ -130,10 +151,10 @@ export default class extends Controller {
|
|
130
151
|
if(momentParsed.isValid()){
|
131
152
|
const momentVal = moment.tz(momentParsed.format("YYYY-MM-DDTHH:mm"), newTimeZone)
|
132
153
|
const dataVal = this.includeTimeValue ? momentVal.toISOString(true) : momentVal.format('YYYY-MM-DD')
|
133
|
-
|
154
|
+
this.fieldTarget.value = dataVal
|
134
155
|
} else {
|
135
156
|
// nullify field value when the display format is wrong
|
136
|
-
|
157
|
+
this.fieldTarget.value = ''
|
137
158
|
}
|
138
159
|
}
|
139
160
|
|
@@ -142,7 +163,7 @@ export default class extends Controller {
|
|
142
163
|
const isAmPm = this.isAmPmValue
|
143
164
|
localeValues['format'] = this.includeTimeValue ? this.timeFormatValue : this.dateFormatValue
|
144
165
|
|
145
|
-
|
166
|
+
jQuery(this.displayFieldTarget).daterangepicker({
|
146
167
|
singleDatePicker: true,
|
147
168
|
timePicker: this.includeTimeValue,
|
148
169
|
timePickerIncrement: 5,
|
@@ -151,41 +172,59 @@ export default class extends Controller {
|
|
151
172
|
timePicker24Hour: !isAmPm,
|
152
173
|
})
|
153
174
|
|
154
|
-
|
155
|
-
|
156
|
-
|
175
|
+
jQuery(this.displayFieldTarget).on('apply.daterangepicker', this.applyDateToField.bind(this))
|
176
|
+
jQuery(this.displayFieldTarget).on('cancel.daterangepicker', this.clearDate.bind(this))
|
177
|
+
jQuery(this.displayFieldTarget).on('input', this,this.displayFieldChange.bind(this));
|
157
178
|
|
158
179
|
this.pluginMainEl = this.displayFieldTarget
|
159
|
-
this.plugin =
|
180
|
+
this.plugin = jQuery(this.pluginMainEl).data('daterangepicker') // weird
|
160
181
|
|
161
182
|
// Init time zone select
|
162
183
|
if (this.includeTimeValue && this.hasTimeZoneSelectWrapperTarget) {
|
163
184
|
this.timeZoneSelect = this.timeZoneSelectWrapperTarget.querySelector('select.select2')
|
164
185
|
|
165
|
-
|
186
|
+
jQuery(this.timeZoneSelect).select2({
|
166
187
|
width: 'style'
|
167
188
|
})
|
168
189
|
|
169
190
|
const self = this
|
170
191
|
|
171
|
-
|
192
|
+
jQuery(this.timeZoneSelect).on('change.select2', function(event) {
|
172
193
|
const currentTimeZoneEl = self.currentTimeZoneWrapperTarget.querySelector('a')
|
173
194
|
const {value} = event.target
|
174
|
-
$(self.timeZoneFieldTarget).val(value)
|
175
|
-
$(currentTimeZoneEl).text(value)
|
176
195
|
|
177
|
-
const
|
196
|
+
const selectedTimeZoneOption = event.target.options[event.target.options.selectedIndex]
|
178
197
|
|
179
|
-
if (self.
|
180
|
-
|
181
|
-
|
182
|
-
|
198
|
+
if (self.hasTimeZoneFieldTarget) {
|
199
|
+
self.timeZoneFieldTarget.value = value
|
200
|
+
}
|
201
|
+
currentTimeZoneEl.textContent = selectedTimeZoneOption.textContent
|
202
|
+
|
203
|
+
const selectedOptionTimeZoneButton = self.element.querySelector('.selected-option-time-zone-button')
|
204
|
+
|
205
|
+
if (self.defaultTimeZonesValue.includes(selectedTimeZoneOption.textContent)) {
|
206
|
+
self.element.querySelectorAll('.time-zone-button').forEach(el => {
|
207
|
+
el.classList.remove('button');
|
208
|
+
el.classList.add('button-alternative');
|
209
|
+
})
|
210
|
+
selectedOptionTimeZoneButton.classList.add('hidden')
|
211
|
+
selectedOptionTimeZoneButton.hidden = true
|
212
|
+
self.element.querySelectorAll(`a[data-value="${value}"`).forEach(el => {
|
213
|
+
el.classList.remove('button-alternative')
|
214
|
+
el.classList.add('button')
|
215
|
+
})
|
183
216
|
} else {
|
184
217
|
// deselect any selected button
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
218
|
+
self.element.querySelectorAll('.time-zone-button').forEach(el => {
|
219
|
+
el.classList.remove('button');
|
220
|
+
el.classList.add('button-alternative');
|
221
|
+
})
|
222
|
+
selectedOptionTimeZoneButton.textContent = selectedTimeZoneOption.textContent
|
223
|
+
selectedOptionTimeZoneButton.setAttribute('data-value', value)
|
224
|
+
selectedOptionTimeZoneButton.hidden = false
|
225
|
+
selectedOptionTimeZoneButton.classList.remove('hidden')
|
226
|
+
selectedOptionTimeZoneButton.classList.remove('button-alternative')
|
227
|
+
selectedOptionTimeZoneButton.classList.add('button')
|
189
228
|
}
|
190
229
|
|
191
230
|
self.resetTimeZoneUI()
|
@@ -195,13 +234,13 @@ export default class extends Controller {
|
|
195
234
|
|
196
235
|
teardownPluginInstance() {
|
197
236
|
if (this.plugin === undefined) { return }
|
198
|
-
|
199
|
-
|
237
|
+
jQuery(this.pluginMainEl).off('apply.daterangepicker')
|
238
|
+
jQuery(this.pluginMainEl).off('cancel.daterangepicker')
|
200
239
|
// revert to original markup, remove any event listeners
|
201
240
|
this.plugin.remove()
|
202
241
|
|
203
|
-
if (this.includeTimeValue) {
|
204
|
-
|
242
|
+
if (this.includeTimeValue && this.hasTimeZoneSelectWrapperTarget) {
|
243
|
+
jQuery(this.timeZoneSelectTarget).select2('destroy');
|
205
244
|
}
|
206
245
|
}
|
207
246
|
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { Controller } from "@hotwired/stimulus"
|
2
2
|
require("select2/dist/css/select2.min.css");
|
3
3
|
import select2 from "select2";
|
4
|
+
import jquery from "jquery";
|
4
5
|
|
5
6
|
const select2SelectedPreviewSelector = ".select2-selection--single"
|
6
7
|
const select2SearchInputFieldSelector = ".select2-search__field"
|
@@ -20,13 +21,16 @@ export default class extends Controller {
|
|
20
21
|
|
21
22
|
initialize() {
|
22
23
|
this.dispatchNativeEvent = this.dispatchNativeEvent.bind(this)
|
24
|
+
if (window.jQuery === undefined) {
|
25
|
+
window.jQuery = jquery
|
26
|
+
}
|
23
27
|
if (!this.isSelect2LoadedOnWindowJquery) {
|
24
28
|
select2()
|
25
29
|
}
|
26
30
|
}
|
27
31
|
|
28
32
|
get isSelect2LoadedOnWindowJquery() {
|
29
|
-
return window
|
33
|
+
return window?.jQuery?.fn?.select2 !== undefined
|
30
34
|
}
|
31
35
|
|
32
36
|
get optionsOverride() {
|
@@ -41,16 +45,18 @@ export default class extends Controller {
|
|
41
45
|
}
|
42
46
|
|
43
47
|
disconnect() {
|
44
|
-
this.
|
48
|
+
if (this.isSelect2LoadedOnWindowJquery) {
|
49
|
+
this.teardownPluginInstance()
|
50
|
+
}
|
45
51
|
}
|
46
52
|
|
47
53
|
cleanupBeforeInit() {
|
48
|
-
|
54
|
+
this.element.querySelectorAll('.select2-container--default').forEach(el => el.remove());
|
49
55
|
}
|
50
56
|
|
51
57
|
initPluginInstance() {
|
52
58
|
let options = {
|
53
|
-
dropdownParent:
|
59
|
+
dropdownParent: jQuery(this.element)
|
54
60
|
};
|
55
61
|
|
56
62
|
if (!this.enableSearchValue) {
|
@@ -84,7 +90,7 @@ export default class extends Controller {
|
|
84
90
|
|
85
91
|
this.cleanupBeforeInit() // in case improperly torn down
|
86
92
|
this.pluginMainEl = this.selectTarget // required because this.selectTarget is unavailable on disconnect()
|
87
|
-
|
93
|
+
jQuery(this.pluginMainEl).select2(options);
|
88
94
|
|
89
95
|
this.initReissuePluginEventsAsNativeEvents()
|
90
96
|
}
|
@@ -96,11 +102,11 @@ export default class extends Controller {
|
|
96
102
|
this.teardownPluginEventsAsNativeEvents()
|
97
103
|
|
98
104
|
// revert to original markup, remove any event listeners
|
99
|
-
|
105
|
+
jQuery(this.pluginMainEl).select2('destroy');
|
100
106
|
}
|
101
107
|
|
102
108
|
open() {
|
103
|
-
|
109
|
+
jQuery(this.pluginMainEl).select2('open')
|
104
110
|
}
|
105
111
|
|
106
112
|
focusOnTextField(event) {
|
@@ -127,13 +133,13 @@ export default class extends Controller {
|
|
127
133
|
|
128
134
|
initReissuePluginEventsAsNativeEvents() {
|
129
135
|
this.constructor.jQueryEventsToReissue.forEach((eventName) => {
|
130
|
-
|
136
|
+
jQuery(this.pluginMainEl).on(eventName, this.dispatchNativeEvent)
|
131
137
|
})
|
132
138
|
}
|
133
139
|
|
134
140
|
teardownPluginEventsAsNativeEvents() {
|
135
141
|
this.constructor.jQueryEventsToReissue.forEach((eventName) => {
|
136
|
-
|
142
|
+
jQuery(this.pluginMainEl).off(eventName)
|
137
143
|
})
|
138
144
|
}
|
139
145
|
|
@@ -144,12 +150,12 @@ export default class extends Controller {
|
|
144
150
|
|
145
151
|
// https://stackoverflow.com/questions/29290389/select2-add-image-icon-to-option-dynamically
|
146
152
|
formatState(opt) {
|
147
|
-
var imageUrl =
|
153
|
+
var imageUrl = opt.element?.dataset.image
|
148
154
|
var imageHtml = "";
|
149
155
|
if (imageUrl) {
|
150
156
|
imageHtml = '<img src="' + imageUrl + '" /> ';
|
151
157
|
}
|
152
|
-
return
|
158
|
+
return jQuery('<span>' + imageHtml + sanitizeHTML(opt.text) + '</span>');
|
153
159
|
}
|
154
160
|
}
|
155
161
|
|
@@ -158,4 +164,4 @@ function sanitizeHTML(str) {
|
|
158
164
|
return str.replace(/[^\w. ]/gi, function (c) {
|
159
165
|
return '&#' + c.charCodeAt(0) + ';';
|
160
166
|
});
|
161
|
-
};
|
167
|
+
};
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bullet_train-fields
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Culver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-03-
|
11
|
+
date: 2024-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: standard
|