frayerjj-frontend 0.2.10 → 0.2.12
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.
- package/package.json +1 -1
- package/src/modal.js +208 -127
package/package.json
CHANGED
package/src/modal.js
CHANGED
|
@@ -3,119 +3,6 @@ import { ajax } from './ajax.js';
|
|
|
3
3
|
import { message } from './message.js';
|
|
4
4
|
|
|
5
5
|
export const modal = {
|
|
6
|
-
|
|
7
|
-
buildLine: vars => {
|
|
8
|
-
let row = '<div class="row ' + (vars.rowClass ?? '') + '">';
|
|
9
|
-
if (vars.label) row += '<label class="fw-bold text-dark">' + vars.label + "</label>";
|
|
10
|
-
row += '</div>';
|
|
11
|
-
return row;
|
|
12
|
-
},
|
|
13
|
-
|
|
14
|
-
buildInput: vars => {
|
|
15
|
-
let input = '';
|
|
16
|
-
if (vars.type == 'textarea') input += '<textarea class="form-control ';
|
|
17
|
-
if (vars.type == 'select') input += '<select class="form-select ';
|
|
18
|
-
else input += '<input type="' + vars.type + '" value="' + vars.value + '" placeholder="' + (vars.placeholder ?? vars.label) + '" class="form-control ';
|
|
19
|
-
input += (vars.inputClass ?? '') + '" id="' + vars.id + '" aria-label="' + (vars.placeholder ?? vars.label) + '" ' + (vars.checked ? 'checked' : '') + '>';
|
|
20
|
-
if (vars.type == 'textarea') input += vars.value + '</textarea>'
|
|
21
|
-
if (vars.type == 'select') input += '</select>';
|
|
22
|
-
return input;
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
buildInputLine: vars => {
|
|
26
|
-
let row = '<div class="row ' + (vars.rowClass ?? '') + '">';
|
|
27
|
-
if (vars.type == 'checkbox' || vars.type == 'radio') {
|
|
28
|
-
row += modal.buildInput(vars);
|
|
29
|
-
if (vars.label) row += '<label for="' + vars.id + '" class="fw-bold text-dark">' + vars.label + '</label>';
|
|
30
|
-
} else {
|
|
31
|
-
if (vars.label) row += '<label for="' + vars.id + '" class="fw-bold text-dark">' + vars.label + '</label>';
|
|
32
|
-
row += '<div class="input-group">';
|
|
33
|
-
if (vars.prepend) row += '<span class="input-group-text">' + vars.prepend + '</span>';
|
|
34
|
-
row += modal.buildInput(vars);
|
|
35
|
-
if (vars.append) row += '<span class="input-group-text">' + vars.append + '</span>';
|
|
36
|
-
row += '</div></div>';
|
|
37
|
-
}
|
|
38
|
-
return row;
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
build: vars => {
|
|
42
|
-
message.verbose('Building Dynamic Modal');
|
|
43
|
-
let html =
|
|
44
|
-
'<div id="' + vars.id + '" class="modal" tabindex="-1">' +
|
|
45
|
-
'<div class="modal-dialog ' + (vars.class ?? '') + '">' +
|
|
46
|
-
'<div class="modal-content">' +
|
|
47
|
-
'<div class="modal-header">' +
|
|
48
|
-
'<h5 class="modal-title">' + vars.title + '</h5>' +
|
|
49
|
-
'<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>' +
|
|
50
|
-
'</div>' +
|
|
51
|
-
'<div class="modal-body">' +
|
|
52
|
-
'<div class="col">' + (vars.body ?? '');
|
|
53
|
-
if (vars.inputs) Object.values(vars.inputs).forEach(i => {
|
|
54
|
-
if (i.type) html += modal.buildInputLine(i);
|
|
55
|
-
else html += modal.buildLine(i);
|
|
56
|
-
});
|
|
57
|
-
html +=
|
|
58
|
-
'</div>' +
|
|
59
|
-
'</div>' +
|
|
60
|
-
'<div class="modal-footer">';
|
|
61
|
-
if (vars.buttons) Object.values(vars.buttons).forEach(b => {
|
|
62
|
-
html += '<button type="button" class="btn btn-outline-secondary me-1 ' + (b.class ?? '') + '" data-bs-dismiss="modal">' + b.text + '</button>';
|
|
63
|
-
});
|
|
64
|
-
html +=
|
|
65
|
-
'</div>' +
|
|
66
|
-
'</div>' +
|
|
67
|
-
'</div>' +
|
|
68
|
-
'</div>';
|
|
69
|
-
return html;
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
alert: (msg, title = "Alert", button = "OK") => {
|
|
73
|
-
message.verbose('Building Alert Modal');
|
|
74
|
-
document.querySelector('body').insertAdjacentHTML('beforeend', modal.build({
|
|
75
|
-
id: 'alert-modal',
|
|
76
|
-
title: title,
|
|
77
|
-
body: '<p>' + msg + '</p>',
|
|
78
|
-
buttons: [ { text: button } ]
|
|
79
|
-
}));
|
|
80
|
-
let alertModal = document.getElementById('alert-modal');
|
|
81
|
-
alertModal.addEventListener('hidden.bs.modal', ev => {
|
|
82
|
-
ev.target.remove();
|
|
83
|
-
});
|
|
84
|
-
let bsAlertModal = bootstrap.Modal.getOrCreateInstance(alertModal);
|
|
85
|
-
bsAlertModal.show();
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
confirm: (msg, onConfirm, onCancel, title = "Are you sure?", buttonYes = "Yes", buttonNo = "No") => {
|
|
89
|
-
message.verbose('Building Confirm Modal');
|
|
90
|
-
document.querySelector('body').insertAdjacentHTML('beforeend', modal.build({
|
|
91
|
-
id: 'confirm-modal',
|
|
92
|
-
title: title,
|
|
93
|
-
body: '<p>' + msg + '</p>',
|
|
94
|
-
buttons: [
|
|
95
|
-
{ text: buttonYes, class: 'btn-confirm' },
|
|
96
|
-
{ text: buttonNo, class: 'btn-outline-danger' } ]
|
|
97
|
-
}));
|
|
98
|
-
let confirmModal = document.getElementById('confirm-modal');
|
|
99
|
-
confirmModal.addEventListener('hidden.bs.modal', ev => {
|
|
100
|
-
ev.target.remove();
|
|
101
|
-
});
|
|
102
|
-
confirmModal.querySelector('.btn-confirm').addEventListener('click', () => {
|
|
103
|
-
onConfirm();
|
|
104
|
-
});
|
|
105
|
-
confirmModal.querySelector('.btn-outline-danger').addEventListener('click', () => {
|
|
106
|
-
onCancel();
|
|
107
|
-
});
|
|
108
|
-
let bsConfirmModal = bootstrap.Modal.getOrCreateInstance(confirmModal);
|
|
109
|
-
bsConfirmModal.show();
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
close: () => {
|
|
113
|
-
message.verbose('Closing Modals');
|
|
114
|
-
document.querySelectorAll('.modal').forEach(modal => {
|
|
115
|
-
let bsModal = bootstrap.Modal.getOrCreateInstance(modal);
|
|
116
|
-
if (bsModal) bsModal.hide();
|
|
117
|
-
});
|
|
118
|
-
},
|
|
119
6
|
|
|
120
7
|
ajax: {
|
|
121
8
|
|
|
@@ -132,23 +19,25 @@ export const modal = {
|
|
|
132
19
|
ev.preventDefault();
|
|
133
20
|
message.verbose('Building AJAX Modal');
|
|
134
21
|
let buttons;
|
|
135
|
-
if (el.getAttribute('modal-info'))
|
|
136
|
-
|
|
137
|
-
|
|
22
|
+
if (el.getAttribute('modal-info'))
|
|
23
|
+
buttons = [{ text: 'OK' }];
|
|
24
|
+
else
|
|
25
|
+
buttons = [{ text: 'Save', class: 'btn-save' }, { text: 'Cancel' }];
|
|
26
|
+
modal.show({
|
|
138
27
|
id: el.getAttribute('data-bs-target').substring(1),
|
|
139
28
|
title: el.getAttribute('modal-title'),
|
|
140
29
|
body: '',
|
|
141
30
|
class: (el.getAttribute('modal-class') ?? ''),
|
|
142
31
|
buttons: buttons
|
|
143
|
-
})
|
|
144
|
-
let ajaxModal = document.
|
|
32
|
+
});
|
|
33
|
+
let ajaxModal = document.querySelector(el.getAttribute('data-bs-target')),
|
|
34
|
+
bsAjaxModal = bootstrap.Modal.getOrCreateInstance(ajaxModal),
|
|
35
|
+
ajaxModalBody = ajaxModal.querySelector('.modal-body');
|
|
145
36
|
ajaxModal.addEventListener('hidden.bs.modal', ev => {
|
|
146
37
|
ev.target.remove();
|
|
147
38
|
});
|
|
148
|
-
let ajaxModalBody = ajaxModal.querySelector('.modal-body');
|
|
149
|
-
let bsAjaxModal = bootstrap.Modal.getOrCreateInstance(ajaxModal);
|
|
150
39
|
bsAjaxModal.show();
|
|
151
|
-
loading.start(ajaxModalBody);
|
|
40
|
+
loading.start(1, ajaxModalBody);
|
|
152
41
|
message.verbose('Loading AJAX Modal');
|
|
153
42
|
window.ajax({
|
|
154
43
|
method: 'GET',
|
|
@@ -168,10 +57,11 @@ export const modal = {
|
|
|
168
57
|
} else loading.stop();
|
|
169
58
|
message.verbose('AJAX Modal Loaded');
|
|
170
59
|
if (!el.getAttribute('modal-info')) {
|
|
60
|
+
message.verbose('Adding submit handler to AJAX Modal');
|
|
171
61
|
let saveButton = ajaxModal.querySelector('.btn-save');
|
|
172
62
|
saveButton.removeAttribute('data-bs-dismiss').addEventListener('click', () => {
|
|
173
|
-
message.verbose('
|
|
174
|
-
loading.start(
|
|
63
|
+
message.verbose('Submitting AJAX Modal');
|
|
64
|
+
loading.start(1, ajaxModalBody);
|
|
175
65
|
let form = ajaxModal.querySelector('form');
|
|
176
66
|
ajax({
|
|
177
67
|
method: 'POST',
|
|
@@ -179,14 +69,14 @@ export const modal = {
|
|
|
179
69
|
vars: serialize(form),
|
|
180
70
|
success: () => {
|
|
181
71
|
message.verbose('AJAX Modal Saved');
|
|
182
|
-
if (bsAjaxModal) bsAjaxModal.hide();
|
|
183
|
-
ajaxModal.remove();
|
|
184
72
|
loading.stop();
|
|
73
|
+
bsAjaxModal.hide();
|
|
74
|
+
ajaxModal.remove();
|
|
185
75
|
},
|
|
186
76
|
failure: () => {
|
|
187
77
|
message.warn('AJAX Modal Save Failed');
|
|
188
|
-
modal.alert(modal.ajax.error.save.msg, modal.ajax.error.save.title);
|
|
189
78
|
loading.stop();
|
|
79
|
+
modal.alert(modal.ajax.error.save.msg, modal.ajax.error.save.title);
|
|
190
80
|
}
|
|
191
81
|
});
|
|
192
82
|
});
|
|
@@ -195,7 +85,7 @@ export const modal = {
|
|
|
195
85
|
failure: () => {
|
|
196
86
|
message.warn('AJAX Modal Load Failed');
|
|
197
87
|
loading.stop();
|
|
198
|
-
|
|
88
|
+
bsAjaxModal.hide();
|
|
199
89
|
ajaxModal.remove();
|
|
200
90
|
modal.alert(modal.ajax.error.load.msg, modal.ajax.error.load.title);
|
|
201
91
|
}
|
|
@@ -203,5 +93,196 @@ export const modal = {
|
|
|
203
93
|
});
|
|
204
94
|
});
|
|
205
95
|
}
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
alert: (msg, title = "Alert", button = "OK") => {
|
|
99
|
+
message.verbose('Building Alert Modal');
|
|
100
|
+
modal.show({ id: 'alert-modal', title, body: `<p>${msg}</p>`, buttons: [{ text: button }] });
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
build: {
|
|
104
|
+
|
|
105
|
+
input: vars => {
|
|
106
|
+
let input;
|
|
107
|
+
if (vars.type == 'select') {
|
|
108
|
+
input = document.createElement('select');
|
|
109
|
+
input.className = 'form-select';
|
|
110
|
+
if (vars.opts)
|
|
111
|
+
for (let [key, val] of Object.entries(vars.opts)) {
|
|
112
|
+
let option = document.createElement('option');
|
|
113
|
+
option.value = key;
|
|
114
|
+
option.textContent = val;
|
|
115
|
+
if (key == vars.value)
|
|
116
|
+
option.setAttribute('selected', 'selected');
|
|
117
|
+
input.appendChild(option);
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
if (vars.type == 'textarea')
|
|
121
|
+
input = document.createElement('textarea');
|
|
122
|
+
else {
|
|
123
|
+
input = document.createElement('input');
|
|
124
|
+
input.setAttribute('type', vars.type);
|
|
125
|
+
input.value = vars.value;
|
|
126
|
+
}
|
|
127
|
+
input.className = 'form-control';
|
|
128
|
+
if (vars.placeholder)
|
|
129
|
+
input.setAttribute('placeholder', vars.placeholder);
|
|
130
|
+
}
|
|
131
|
+
input.id = vars.id;
|
|
132
|
+
input.setAttribute('aria-label', vars.placeholder ?? vars.label);
|
|
133
|
+
if (vars.checked)
|
|
134
|
+
input.setAttribute('checked', 'checked');
|
|
135
|
+
if (vars.inputClass)
|
|
136
|
+
input.classList.add(vars.inputClass);
|
|
137
|
+
return input.outerHTML;
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
inputLine: vars => {
|
|
141
|
+
let row = document.createElement('div');
|
|
142
|
+
row.className = 'row';
|
|
143
|
+
if (vars.rowClass)
|
|
144
|
+
row.classList.add(vars.rowClass);
|
|
145
|
+
row.insertAdjacentHTML('beforeend', modal.build.input(vars));
|
|
146
|
+
if (vars.label)
|
|
147
|
+
if (vars.type == 'checkbox' || vars.type == 'radio')
|
|
148
|
+
row.insertAdjacentHTML('beforeend', label);
|
|
149
|
+
else
|
|
150
|
+
row.insertAdjacentHTML('afterbegin', modal.build.label(vars));
|
|
151
|
+
return row.outerHTML;
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
line: vars => {
|
|
155
|
+
let row = document.createElement('div');
|
|
156
|
+
row.className = 'row';
|
|
157
|
+
if (vars.rowClass)
|
|
158
|
+
row.classList.add(vars.rowClass);
|
|
159
|
+
if (vars.label)
|
|
160
|
+
row.insertAdjacentHTML('beforeend', modal.build.label(vars));
|
|
161
|
+
return row.outerHTML;
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
label: vars => {
|
|
165
|
+
let label = document.createElement('label');
|
|
166
|
+
label.setAttribute('for', vars.id);
|
|
167
|
+
label.className = 'fw-bold text-dark';
|
|
168
|
+
label.textContent = vars.label;
|
|
169
|
+
return label.outerHTML;
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
modal: vars => {
|
|
173
|
+
message.verbose('Building Dynamic Modal');
|
|
174
|
+
|
|
175
|
+
// Modal container
|
|
176
|
+
let modal = document.createElement('div');
|
|
177
|
+
modal.className = 'modal fade';
|
|
178
|
+
modal.id = vars.id;
|
|
179
|
+
modal.setAttribute('tabindex', '-1');
|
|
180
|
+
modal.setAttribute('role', 'dialog');
|
|
181
|
+
modal.setAttribute('aria-labelledby', vars.title);
|
|
182
|
+
modal.setAttribute('aria-hidden', 'true');
|
|
183
|
+
|
|
184
|
+
// Modal dialog
|
|
185
|
+
let modalDialog = document.createElement('div');
|
|
186
|
+
modalDialog.className = 'modal-dialog';
|
|
187
|
+
if (vars.class)
|
|
188
|
+
modalDialog.classList.add(vars.class);
|
|
189
|
+
|
|
190
|
+
// Modal content
|
|
191
|
+
let modalContent = document.createElement('div');
|
|
192
|
+
modalContent.className = 'modal-content';
|
|
193
|
+
|
|
194
|
+
// Modal header
|
|
195
|
+
let modalHeader = document.createElement('div');
|
|
196
|
+
modalHeader.className = 'modal-header';
|
|
197
|
+
|
|
198
|
+
let modalTitle = document.createElement('h5');
|
|
199
|
+
modalTitle.className = 'modal-title';
|
|
200
|
+
modalTitle.id = `${vars.id}Label`;
|
|
201
|
+
modalTitle.textContent = vars.title;
|
|
202
|
+
|
|
203
|
+
let closeButton = document.createElement('button');
|
|
204
|
+
closeButton.className = 'btn-close';
|
|
205
|
+
closeButton.setAttribute('type', 'button');
|
|
206
|
+
closeButton.setAttribute('data-bs-dismiss', 'modal');
|
|
207
|
+
closeButton.setAttribute('aria-label', 'Close');
|
|
208
|
+
|
|
209
|
+
modalHeader.appendChild(modalTitle);
|
|
210
|
+
modalHeader.appendChild(closeButton);
|
|
211
|
+
|
|
212
|
+
// Modal body
|
|
213
|
+
let modalBody = document.createElement('div');
|
|
214
|
+
modalBody.className = 'modal-body';
|
|
215
|
+
modalBody.innerHTML = vars.body ?? '';
|
|
216
|
+
|
|
217
|
+
if (vars.inputs)
|
|
218
|
+
Object.values(vars.inputs).forEach(i => {
|
|
219
|
+
if (i.type)
|
|
220
|
+
modalBody.insertAdjacentHTML('beforeend', modal.build.inputLine(i));
|
|
221
|
+
else
|
|
222
|
+
modalBody.insertAdjacentHTML('beforeend', modal.build.line(i));
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Modal footer
|
|
226
|
+
let modalFooter = document.createElement('div');
|
|
227
|
+
modalFooter.className = 'modal-footer';
|
|
228
|
+
|
|
229
|
+
if (vars.buttons)
|
|
230
|
+
Object.values(vars.buttons).forEach(b => {
|
|
231
|
+
let button = document.createElement('button');
|
|
232
|
+
button.className = 'btn btn-outline-secondary me-1';
|
|
233
|
+
if (b.class)
|
|
234
|
+
button.classList.add(b.class);
|
|
235
|
+
button.setAttribute('type', 'button');
|
|
236
|
+
button.setAttribute('data-bs-dismiss', 'modal');
|
|
237
|
+
button.textContent = b.text;
|
|
238
|
+
modalFooter.appendChild(button);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
modalContent.appendChild(modalHeader);
|
|
242
|
+
modalContent.appendChild(modalBody);
|
|
243
|
+
modalContent.appendChild(modalFooter);
|
|
244
|
+
modalDialog.appendChild(modalContent);
|
|
245
|
+
modal.appendChild(modalDialog);
|
|
246
|
+
|
|
247
|
+
return modal.outerHTML;
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
close: () => {
|
|
252
|
+
message.verbose('Closing Modals');
|
|
253
|
+
document.querySelectorAll('.modal').forEach(modal => {
|
|
254
|
+
let bsModal = bootstrap.Modal.getOrCreateInstance(modal);
|
|
255
|
+
if (bsModal) bsModal.hide();
|
|
256
|
+
});
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
confirm: (msg, onConfirm, onCancel, title = "Are you sure?", buttonYes = "Yes", buttonNo = "No") => {
|
|
260
|
+
message.verbose('Building Confirm Modal');
|
|
261
|
+
modal.show({
|
|
262
|
+
id: 'confirm-modal',
|
|
263
|
+
title,
|
|
264
|
+
body: `<p>${msg}</p>`,
|
|
265
|
+
buttons: [
|
|
266
|
+
{ text: buttonYes, class: 'btn-confirm btn-primary', action: 'onConfirm' },
|
|
267
|
+
{ text: buttonNo, class: 'btn-outline-danger', action: 'onCancel' }
|
|
268
|
+
],
|
|
269
|
+
onConfirm,
|
|
270
|
+
onCancel
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
show: config => {
|
|
275
|
+
document.body.appendChild(modal.build.modal(config));
|
|
276
|
+
let modalEl = document.getElementById(config.id);
|
|
277
|
+
let bsModal = new bootstrap.Modal(modalEl);
|
|
278
|
+
modalEl.addEventListener('hidden.bs.modal', () => modalEl.remove());
|
|
279
|
+
modalEl.querySelectorAll('[data-action]').forEach(button =>
|
|
280
|
+
button.addEventListener('click', () => {
|
|
281
|
+
if (config[button.dataset.action]) config[button.dataset.action]();
|
|
282
|
+
bsModal.hide();
|
|
283
|
+
})
|
|
284
|
+
);
|
|
285
|
+
bsModal.show();
|
|
206
286
|
}
|
|
287
|
+
|
|
207
288
|
};
|