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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/modal.js +208 -127
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frayerjj-frontend",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": "My base frontend for various projects",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
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')) buttons = [{ text: 'OK' }];
136
- else buttons = [{ text: 'Save', class: 'btn-save' }, { text: 'Cancel' }];
137
- document.querySelector('body').insertAdjacentHTML('beforeend', modal.build({
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.getElementById(el.getAttribute('data-bs-target').substring(1));
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('Saving AJAX Modal');
174
- loading.start(ajaxModal.querySelector('.modal-body'));
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
- if (bsAjaxModal) bsAjaxModal.hide();
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
  };