frayerjj-frontend 0.2.37 → 0.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frayerjj-frontend",
3
- "version": "0.2.37",
3
+ "version": "0.3.1",
4
4
  "description": "My base frontend for various projects",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/ckeupload.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
2
- import { message } from "./message";
2
+ import { msg } from "./msg";
3
3
 
4
4
  export const ckeupload = {
5
5
  adapter: editor => {
@@ -86,7 +86,7 @@ export const ckeupload = {
86
86
  extraPlugins: [ CkeUploadAdapter ]
87
87
  }).then(editor => {
88
88
  window.editors[el.id] = editor;
89
- message.verbose('CKEditor Initialized');
89
+ msg.verbose('CKEditor Initialized');
90
90
  }).catch( error => {
91
91
  console.error( 'There was a problem initializing the editor.', error );
92
92
  });
package/src/fileUpload.js CHANGED
@@ -1,5 +1,230 @@
1
+ import { loading } from "./loading";
2
+ import { msg } from "./msg";
3
+ import { modal } from "./modal";
4
+
1
5
  export const fileUpload = {
6
+
7
+ imgFormats: ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/webp'],
8
+
9
+ icons: {
10
+ 'application/msword': 'fa-file-word',
11
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'fa-file-word',
12
+ 'application/vnd.ms-excel': 'fa-file-excel',
13
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'fa-file-excel',
14
+ 'application/vnd.ms-powerpoint': 'fa-file-powerpoint',
15
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'fa-file-powerpoint',
16
+ 'application/pdf': 'fa-file-pdf',
17
+ },
18
+
19
+ sampleArgs: {
20
+ name: 'files', // Variable name
21
+ mimes: ['image/jpeg', 'image/png'], // Allowed MIME types
22
+ iconSize: 128, // Icon size
23
+ files: [ // Existing files
24
+ { id: 1, name: 'file1.jpg', mime: 'image/jpeg', uri: '/path/to/file1.jpg' },
25
+ ],
26
+ messages: { // Messages
27
+ instructions: 'Drag and drop files here or click the button below.',
28
+ browse: 'Browse',
29
+ close: 'Close',
30
+ view: 'View',
31
+ delete: 'Delete',
32
+ errorTitle: 'Error',
33
+ uploadError: 'Error uploading file.',
34
+ deleteError: 'Error deleting file.'
35
+ },
36
+ uris: { // URIs
37
+ upload: '/path/to/upload',
38
+ delete: '/path/to/delete'
39
+ }
40
+ },
41
+
2
42
  build: {
3
-
43
+
44
+ core: args => {
45
+ let container = document.createElement('div');
46
+ let list = document.createElement('ul');
47
+ list.classList.add('upload-files');
48
+ Objects.values(args.files).forEach(file => {
49
+ list.insertAdjacentHTML('beforeend', fileUpload.build.item(args, file));
50
+ });
51
+ let input = document.createElement('input');
52
+ input.type = 'file';
53
+ input.style.display = 'none';
54
+ let instructions = document.createElement('div');
55
+ instructions.classList.add('upload-instructions');
56
+ let icon = document.createElement('span');
57
+ icon.classList.add('fas', 'fa-arrow-alt-circle-u');
58
+ instructions.appendChild(icon);
59
+ let text = document.createElement('p');
60
+ text.textContent = args.messages.instructions ?? fileUpload.sampleArgs.messages.instructions;
61
+ instructions.appendChild(text);
62
+ let button = document.createElement('button');
63
+ button.classList.add('btn', 'btn-outline-secondary', 'btn-browse');
64
+ button.textContent = args.messages.browse ?? fileUpload.sampleArgs.messages.browse;
65
+ instructions.appendChild(button);
66
+ container.appendChild(list);
67
+ container.appendChild(input);
68
+ container.appendChild(instructions);
69
+ return container.outerHTML;
70
+ },
71
+
72
+ item: (args, file) => {
73
+ let item = document.createElement('li');
74
+ item.classList.add('upload-file');
75
+ item.title = file.name;
76
+ item.setAttribute('data-uri', file.uri);
77
+ if (fileUpload.imgFormats.includes(file.mime))
78
+ item.classList.add('upload-type-image');
79
+ else
80
+ item.classList.add('upload-type-file');
81
+ let input = document.createElement('input');
82
+ input.type = 'hidden';
83
+ input.name = args.name + '[]';
84
+ input.value = file.id;
85
+ item.appendChild(input);
86
+ let icon = fileUpload.imgFormats.includes(file.mime) ? fileUpload.build.thumb(file) : fileUpload.build.icon(file);
87
+ item.appendChild(icon);
88
+ let heading = document.createElement('h6');
89
+ heading.textContent = file.name;
90
+ item.appendChild(heading);
91
+ let buttons = document.createElement('div');
92
+ buttons.classList.add('btn-group');
93
+ let view = document.createElement('button');
94
+ view.classList.add('btn', 'btn-outline-secondary', 'btn-view');
95
+ view.textContent = args.messages.view ?? fileUpload.sampleArgs.messages.view;
96
+ buttons.appendChild(view);
97
+ let del = document.createElement('button');
98
+ del.classList.add('btn', 'btn-outline-danger', 'btn-delete');
99
+ del.textContent = args.messages.delete ?? fileUpload.sampleArgs.messages.delete;
100
+ buttons.appendChild(del);
101
+ item.appendChild(buttons);
102
+ return item.outerHTML;
103
+ },
104
+
105
+ icon: file => {
106
+ let icon = document.createElement('span');
107
+ icon.classList.add('border', 'fas');
108
+ if (fileUpload.icons[file.mime])
109
+ icon.classList.add(fileUpload.icons[file.mime]);
110
+ else
111
+ icon.classList.add('fa-file');
112
+ icon.style.width = fileUpload.iconSize + 'px';
113
+ icon.style.height = fileUpload.iconSize + 'px';
114
+ return icon;
115
+ },
116
+
117
+ thumb: file => {
118
+ let thumb = document.createElement('img');
119
+ thumb.src = file.uri;
120
+ thumb.style.width = fileUpload.iconSize + 'px';
121
+ thumb.style.height = fileUpload.iconSize + 'px';
122
+ return thumb;
123
+ }
124
+ },
125
+
126
+ delete: (el, item) => {
127
+ loading.start(1, el);
128
+ let data = new FormData();
129
+ data.append('id', item.querySelector('input[type="hidden"]').value);
130
+ fetch(el.getAttribute('data-delete-uri'), {
131
+ method: 'POST',
132
+ body: data,
133
+ headers: {
134
+ 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
135
+ }
136
+ }).then(response => response.json()).then(result => {
137
+ if (result.success)
138
+ item.remove();
139
+ else
140
+ modal.alert(args.messages.errorTitle ?? fileUpload.sampleArgs.messages.errorTitle, args.messages.deleteError ?? fileUpload.sampleArgs.messages.deleteError);
141
+ loading.stop();
142
+ }).catch(error => {
143
+ modal.alert(args.messages.errorTitle ?? fileUpload.sampleArgs.messages.errorTitle, args.messages.deleteError ?? fileUpload.sampleArgs.messages.deleteError);
144
+ msg.error(error);
145
+ loading.stop();
146
+ });
147
+ },
148
+
149
+ init: () => {
150
+ document.querySelectorAll('.file-upload').forEach(el => {
151
+ // Get arguments
152
+ let args = JSON.parse(el.innerHTML);
153
+ // Build has many input
154
+ el.innerHTML = fileUpload.build.core(args);
155
+ // Add event listeners
156
+ el.querySelector('.btn-browse').addEventListener('click', () => {
157
+ el.querySelector('input[type="file"]').click();
158
+ });
159
+ el.querySelector('input[type="file"]').addEventListener('change', ev => {
160
+ fileUpload.upload(el, args, ev.target.files);
161
+ });
162
+ el.addEventListener('dragover', ev => {
163
+ ev.preventDefault();
164
+ el.classList.add('dragover');
165
+ });
166
+ el.addEventListener('dragleave', ev => {
167
+ el.classList.remove('dragover');
168
+ });
169
+ el.addEventListener('drop', ev => {
170
+ ev.preventDefault();
171
+ el.classList.remove('dragover');
172
+ fileUpload.upload(el, args, ev.dataTransfer.files);
173
+ });
174
+ el.querySelectorAll('.btn-delete').forEach(btn => {
175
+ btn.addEventListener('click', () => {
176
+ fileUpload.delete(el, btn.closest('.upload-file'));
177
+ });
178
+ });
179
+ el.querySelectorAll('.btn-view').forEach(btn => {
180
+ btn.addEventListener('click', () => {
181
+ fileUpload.view(args, btn.closest('.upload-file'));
182
+ });
183
+ });
184
+ });
185
+ },
186
+
187
+ upload: (el, file, args) => {
188
+ loading.start(1, el);
189
+ let data = new FormData();
190
+ data.append('owner', args.name);
191
+ data.append('file', file[0]);
192
+ fetch(args.uris.upload, {
193
+ method: 'POST',
194
+ body: data,
195
+ headers: {
196
+ 'multipart': 'form-data',
197
+ 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
198
+ }
199
+ }).then(response => response.json()).then(result => {
200
+ if (result.success)
201
+ el.querySelector('.upload-files').insertAdjacentHTML('beforeend', fileUpload.build.item(args, result.file));
202
+ else
203
+ modal.alert(args.messages.errorTitle ?? fileUpload.sampleArgs.messages.errorTitle, args.messages.uploadError ?? fileUpload.sampleArgs.messages.uploadError);
204
+ loading.stop();
205
+ }).catch(error => {
206
+ modal.alert(args.messages.errorTitle ?? fileUpload.sampleArgs.messages.errorTitle, args.messages.uploadError ?? fileUpload.sampleArgs.messages.uploadError);
207
+ msg.error(error);
208
+ loading.stop();
209
+ });
210
+ },
211
+
212
+ view: (args, item) => {
213
+ if (item.classList.contains('upload-type-image')) {
214
+ let body = document.createElement('img');
215
+ body.src = item.querySelector('img').src;
216
+ }
217
+ else {
218
+ let body = document.createElement('iframe');
219
+ body.src = `https://docs.google.com/gview?url=${window.location.protocol}//${window.location.host}${item.getAttribute('data-uri')}&embedded=true`;
220
+ }
221
+ let randomId = modal.randomId('fileview');
222
+ document.querySelector('body').insertAdjacentHTML('beforeend', modal.build.modal({
223
+ id: randomId,
224
+ className: 'modal-lg',
225
+ title: item.title,
226
+ body: body.outerHTML,
227
+ buttons: [{ text: args.messages.close ?? fileUpload.sampleArgs.messages.close }]
228
+ }));
4
229
  }
5
230
  };
package/src/hasMany.js CHANGED
@@ -1,11 +1,27 @@
1
- import { message } from './message.js';
1
+ import { msg } from './msg.js';
2
2
  import { modal } from './modal.js';
3
3
 
4
4
  export const hasMany = {
5
+
6
+ sampleArgs: {
7
+ name: 'name', // Variable name
8
+ title: 'Title', // Verbose name
9
+ notb: false, // Use None of the Below
10
+ messages: {
11
+ notbLabel: 'None', // Label for None of the Below
12
+ close: 'Close', // Close button text
13
+ button: 'Select Objects' // OK button text
14
+ },
15
+ options: [
16
+ { id: 1, label: 'Option 1', checked: false },
17
+ { id: 2, label: 'Option 2', checked: true }
18
+ ]
19
+ },
20
+
5
21
  build: {
6
22
 
7
23
  core: args => {
8
- message.verbose('Building Has Many Inupt');
24
+ msg.verbose('Building Has Many Inupt');
9
25
  // Create container
10
26
  let container = document.createElement('div');
11
27
  // Create list of selected items
@@ -23,7 +39,7 @@ export const hasMany = {
23
39
  if (args.notb)
24
40
  modalList.insertAdjacentHTML('beforeend', hasMany.build.checkItem(args.name, {
25
41
  id: 'notb',
26
- label: (args.notbLabel ?? 'None'),
42
+ label: (args.notbLabel ?? hasMany.sampleArgs.messages.notbLabel),
27
43
  notb: true
28
44
  }));
29
45
  // Cycle through all options
@@ -39,7 +55,7 @@ export const hasMany = {
39
55
  id: randomId,
40
56
  title: args.title,
41
57
  body: modalList.outerHTML,
42
- buttons: [ { text: 'OK' } ]
58
+ buttons: [ { text: args.messages.close ?? hasMany.sampleArgs.messages.close } ]
43
59
  }));
44
60
  // Create button to open modal
45
61
  let button = document.createElement('button');
@@ -47,6 +63,7 @@ export const hasMany = {
47
63
  button.className = 'btn btn-outline-secondary btn-block';
48
64
  button.setAttribute('data-bs-toggle', 'modal');
49
65
  button.setAttribute('data-bs-target', '#' + randomId);
66
+ button.textContent = args.messages.button ?? hasMany.sampleArgs.messages.button;
50
67
  // Add elements to container
51
68
  container.appendChild(input);
52
69
  container.appendChild(list);
package/src/init.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as bootstrap from 'bootstrap';
2
2
  import { ClassicEditor } from '@ckeditor/ckeditor5-build-classic';
3
3
  import { createPopper } from '@popperjs/core';
4
- import { parsePhoneNumber } from 'libphonenumber-js/min';
5
4
  import { avatarCropper } from './avatarCropper';
6
5
  import { ckeupload } from './ckeupload';
6
+ import { fileUpload } from './fileUpload';
7
7
  import { hasMany } from './hasMany';
8
8
  import { loading } from './loading';
9
- import { message } from './message';
9
+ import { msg } from './msg';
10
10
  import { modal } from './modal';
11
11
  import { phoneInput } from './phoneInput';
12
12
  import { session } from './session';
@@ -16,20 +16,20 @@ export const init = () => {
16
16
 
17
17
  window.bootstrap = bootstrap;
18
18
  window.createPopper = createPopper;
19
- window.message = message;
19
+ window.msg = msg;
20
20
  window.modal = modal;
21
21
  window.session = session;
22
22
  window.validate = validate;
23
23
  window.loading = loading;
24
24
  window.ClassicEditor = ClassicEditor;
25
- window.parsePhoneNumber = parsePhoneNumber;
26
25
  loading.init();
27
26
 
28
27
  window.addEventListener('load', () => {
29
28
 
30
- message.verbose('Page Loaded, Initializing');
29
+ msg.verbose('Page Loaded, Initializing');
31
30
  avatarCropper.init();
32
31
  ckeupload.init();
32
+ fileUpload.init();
33
33
  hasMany.init();
34
34
  modal.ajax.init();
35
35
  phoneInput.init();
@@ -56,9 +56,9 @@ export const init = () => {
56
56
 
57
57
  // Updates the id in the form action inside a modal. Used for delete confirm and edit modals.
58
58
  document.querySelectorAll('.modal-uuid-update').forEach(el => {
59
- message.verbose('Enabling Modal UUID Update');
59
+ msg.verbose('Enabling Modal UUID Update');
60
60
  el.addEventListener('click', ev => {
61
- message.verbose('Updating Modal UUID');
61
+ msg.verbose('Updating Modal UUID');
62
62
  ev.preventDefault();
63
63
  let uuid = el.getAttribute('inst-uuid'),
64
64
  modalSelector = el.getAttribute('data-bs-target'),
@@ -70,7 +70,7 @@ export const init = () => {
70
70
  form.setAttribute('action', action);
71
71
  }
72
72
  else {
73
- message.warn('Unable to update modal UUID.');
73
+ msg.warn('Unable to update modal UUID.');
74
74
  modal.close();
75
75
  modal.alert('Error', 'Unable to initialize form.');
76
76
  }
@@ -79,18 +79,18 @@ export const init = () => {
79
79
 
80
80
  // Automatically submits on change. Used in Page Nav Selects.
81
81
  document.querySelectorAll('.change-submit').forEach(el => {
82
- message.verbose('Enabling Change Submit');
82
+ msg.verbose('Enabling Change Submit');
83
83
  el.addEventListener('change', () => {
84
- message.verbose('Change Submit Triggered');
84
+ msg.verbose('Change Submit Triggered');
85
85
  el.closest('form').submit();
86
86
  });
87
87
  });
88
88
 
89
89
  // Confirm/Delete Modals
90
90
  document.querySelectorAll('.confirm-link').forEach(el => {
91
- message.verbose('Enabling Confirm Link');
91
+ msg.verbose('Enabling Confirm Link');
92
92
  el.addEventListener('click', ev => {
93
- message.verbose('Confirm Link Triggered');
93
+ msg.verbose('Confirm Link Triggered');
94
94
  ev.preventDefault();
95
95
  modal.confirm(
96
96
  el.getAttribute('confirm-msg') || 'Are you sure?',
@@ -105,21 +105,21 @@ export const init = () => {
105
105
  });
106
106
 
107
107
  // Filter Selects
108
- document.querySelectorAll('.filter-select').forEach(select => {
109
- message.verbose('Enabling Filter Select');
108
+ let filterSelects = document.querySelectorAll('.filter-select');
109
+ if (filterSelects.length) filterSelects.forEach(select => {
110
+ msg.verbose('Enabling Filter Select');
110
111
  select.addEventListener('change', ev => {
111
- message.verbose('Filter Select Triggered');
112
- if (el.value)
113
- document.querySelectorAll('.filter-' + select.getAttribute('name')).forEach(el => {
114
- if (el.classList.contains('filter-' + select.getAttribute('name') + '-' + select.value))
115
- el.style.display = '';
116
- else
117
- el.style.display = 'none';
118
- });
119
- else
120
- document.querySelectorAll('.filter-' + select.getAttribute('name')).forEach(el => {
121
- el.style.display = '';
112
+ msg.verbose('Filter Select Triggered');
113
+ document.querySelectorAll('.filter-items').forEach(el => {
114
+ el.style.display = '';
115
+ filterSelects.forEach(filter => {
116
+ if (filter.value) {
117
+ let attr = filter.getAttribute('filter-attr');
118
+ if (el.getAttribute(attr) != filter.value)
119
+ el.style.display = 'none';
120
+ }
122
121
  });
122
+ });
123
123
  });
124
124
  });
125
125
 
@@ -127,15 +127,15 @@ export const init = () => {
127
127
  let toTop = document.getElementById('toTopBtn');
128
128
  toTop.style.visibility = "hidden";
129
129
  toTop.addEventListener('click', () => {
130
- message.verbose('Scrolling to Top');
130
+ msg.verbose('Scrolling to Top');
131
131
  scrollTo(0, 0);
132
132
  });
133
133
  window.addEventListener('scroll', () => {
134
134
  if (scrollY > 1500) {
135
- message.verbose('Scrolling to Top Button Visible');
135
+ msg.verbose('Scrolling to Top Button Visible');
136
136
  toTop.style.visibility = "visible";
137
137
  } else {
138
- message.verbose('Scrolling to Top Button Hidden');
138
+ msg.verbose('Scrolling to Top Button Hidden');
139
139
  toTop.style.visibility = "hidden";
140
140
  }
141
141
  });
package/src/loading.js CHANGED
@@ -1,4 +1,4 @@
1
- import { message } from './message';
1
+ import { msg } from './msg';
2
2
  import { session } from './session';
3
3
 
4
4
  export const loading = {
@@ -72,32 +72,32 @@ export const loading = {
72
72
 
73
73
  init: () => {
74
74
  window.addEventListener('DOMContentLoaded', () => {
75
- message.verbose('DOM Loaded, Starting Animation');
75
+ msg.verbose('DOM Loaded, Starting Animation');
76
76
  loading.start();
77
77
  });
78
78
  window.addEventListener('beforeunload', () => {
79
- message.verbose('Navigating Away, Starting Animation');
79
+ msg.verbose('Navigating Away, Starting Animation');
80
80
  loading.start(1);
81
81
  });
82
82
  window.addEventListener('error', () => {
83
- message.verbose('DOM Error, Clearing Animation');
83
+ msg.verbose('DOM Error, Clearing Animation');
84
84
  loading.clear();
85
85
  });
86
86
  window.addEventListener('abort', () => {
87
- message.verbose('Load Aborted, Clearing Animation');
87
+ msg.verbose('Load Aborted, Clearing Animation');
88
88
  loading.clear();
89
89
  });
90
90
  window.addEventListener('unload', () => {
91
- message.verbose('Page Unloaded, Clearing Animation');
91
+ msg.verbose('Page Unloaded, Clearing Animation');
92
92
  loading.clear();
93
93
  });
94
94
  window.addEventListener('load', () => {
95
- message.verbose('Resources Loaded, Stopping Animation');
95
+ msg.verbose('Resources Loaded, Stopping Animation');
96
96
  loading.stop();
97
97
  });
98
98
  window.addEventListener('pageshow', (e) => {
99
99
  if (e.originalEvent && e.originalEvent.persisted) {
100
- message.verbose('Back button detected, Stopping Animation');
100
+ msg.verbose('Back button detected, Stopping Animation');
101
101
  loading.stop();
102
102
  }
103
103
  });
package/src/modal.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Modal } from 'bootstrap';
2
- import { message } from './message.js';
2
+ import { msg } from './msg.js';
3
3
 
4
4
  export const modal = {
5
5
 
@@ -13,10 +13,10 @@ export const modal = {
13
13
  init: () => {
14
14
  // Cycle through all AJAX Modals in DOM
15
15
  document.querySelectorAll('.ajax-modal').forEach(el => {
16
- message.verbose('Enabling AJAX Modal');
16
+ msg.verbose('Enabling AJAX Modal');
17
17
  el.addEventListener('click', ev => {
18
18
  ev.preventDefault();
19
- message.verbose('Building AJAX Modal');
19
+ msg.verbose('Building AJAX Modal');
20
20
  let buttons;
21
21
  if (el.getAttribute('modal-info'))
22
22
  buttons = [{ text: 'OK' }];
@@ -38,7 +38,7 @@ export const modal = {
38
38
  let bsAjaxModal = Modal.getOrCreateInstance(ajaxModal);
39
39
  bsAjaxModal.show();
40
40
  loading.start(0, ajaxModalBody);
41
- message.verbose('Loading AJAX Modal');
41
+ msg.verbose('Loading AJAX Modal');
42
42
  fetch(el.getAttribute('modal-load-uri'), { method: 'GET' }).then(response => {
43
43
  ajaxModalBody.insertAdjacentHTML('afterbegin', response);
44
44
  let images = ajaxModalBody.querySelectorAll('img')
@@ -51,30 +51,30 @@ export const modal = {
51
51
  });
52
52
  });
53
53
  } else loading.stop();
54
- message.verbose('AJAX Modal Loaded');
54
+ msg.verbose('AJAX Modal Loaded');
55
55
  if (!el.getAttribute('modal-info')) {
56
- message.verbose('Adding submit handler to AJAX Modal');
56
+ msg.verbose('Adding submit handler to AJAX Modal');
57
57
  ajaxModal.querySelector('.btn-save').addEventListener('click', () => {
58
- message.verbose('Submitting AJAX Modal');
58
+ msg.verbose('Submitting AJAX Modal');
59
59
  loading.start(0, ajaxModalBody);
60
60
  let form = ajaxModal.querySelector('form');
61
61
  fetch(form.getAttribute('action'), {
62
62
  method: 'POST',
63
63
  body: new FormData(form)
64
64
  }).then(response => {
65
- message.verbose('AJAX Modal Saved');
65
+ msg.verbose('AJAX Modal Saved');
66
66
  loading.stop();
67
67
  bsAjaxModal.hide();
68
68
  ajaxModal.remove();
69
69
  }).catch(() => {
70
- message.warn('AJAX Modal Save Failed');
70
+ msg.warn('AJAX Modal Save Failed');
71
71
  loading.stop();
72
72
  modal.alert(modal.ajax.error.save.msg, modal.ajax.error.save.title);
73
73
  });
74
74
  });
75
75
  }
76
76
  }).catch(() => {
77
- message.warn('AJAX Modal Load Failed');
77
+ msg.warn('AJAX Modal Load Failed');
78
78
  loading.stop();
79
79
  bsAjaxModal.hide();
80
80
  ajaxModal.remove();
@@ -86,7 +86,7 @@ export const modal = {
86
86
  },
87
87
 
88
88
  alert: (msg, title = "Alert", button = "OK") => {
89
- message.verbose('Building Alert Modal');
89
+ msg.verbose('Building Alert Modal');
90
90
  let randomId = modal.randomId('confirm');
91
91
  document.querySelector('body').insertAdjacentHTML('beforeend', modal.build.modal({
92
92
  id: randomId,
@@ -105,89 +105,89 @@ export const modal = {
105
105
 
106
106
  build: {
107
107
 
108
- input: vars => {
108
+ input: args => {
109
109
  let input;
110
- if (vars.type == 'select') {
110
+ if (args.type == 'select') {
111
111
  input = document.createElement('select');
112
112
  input.className = 'form-select';
113
- if (vars.opts)
114
- for (let [key, val] of Object.entries(vars.opts)) {
113
+ if (args.opts)
114
+ for (let [key, val] of Object.entries(args.opts)) {
115
115
  let option = document.createElement('option');
116
116
  option.value = key;
117
117
  option.textContent = val;
118
- if (key == vars.value)
118
+ if (key == args.value)
119
119
  option.setAttribute('selected', 'selected');
120
120
  input.appendChild(option);
121
121
  }
122
122
  } else {
123
- if (vars.type == 'textarea')
123
+ if (args.type == 'textarea')
124
124
  input = document.createElement('textarea');
125
125
  else {
126
126
  input = document.createElement('input');
127
- input.setAttribute('type', vars.type);
128
- input.value = vars.value;
127
+ input.setAttribute('type', args.type);
128
+ input.value = args.value;
129
129
  }
130
130
  input.className = 'form-control';
131
- if (vars.placeholder)
132
- input.setAttribute('placeholder', vars.placeholder);
131
+ if (args.placeholder)
132
+ input.setAttribute('placeholder', args.placeholder);
133
133
  }
134
- input.id = vars.id;
135
- input.setAttribute('aria-label', vars.placeholder ?? vars.label);
136
- if (vars.checked)
134
+ input.id = args.id;
135
+ input.setAttribute('aria-label', args.placeholder ?? args.label);
136
+ if (args.checked)
137
137
  input.setAttribute('checked', 'checked');
138
- if (vars.inputClass)
139
- input.classList.add(vars.inputClass);
138
+ if (args.inputClass)
139
+ input.classList.add(args.inputClass);
140
140
  return input.outerHTML;
141
141
  },
142
142
 
143
- inputLine: vars => {
143
+ inputLine: args => {
144
144
  let row = document.createElement('div');
145
145
  row.className = 'row';
146
- if (vars.rowClass)
147
- row.classList.add(vars.rowClass);
148
- row.insertAdjacentHTML('beforeend', modal.build.input(vars));
149
- if (vars.label)
150
- if (vars.type == 'checkbox' || vars.type == 'radio')
146
+ if (args.rowClass)
147
+ row.classList.add(args.rowClass);
148
+ row.insertAdjacentHTML('beforeend', modal.build.input(args));
149
+ if (args.label)
150
+ if (args.type == 'checkbox' || args.type == 'radio')
151
151
  row.insertAdjacentHTML('beforeend', label);
152
152
  else
153
- row.insertAdjacentHTML('afterbegin', modal.build.label(vars));
153
+ row.insertAdjacentHTML('afterbegin', modal.build.label(args));
154
154
  return row.outerHTML;
155
155
  },
156
156
 
157
- line: vars => {
157
+ line: args => {
158
158
  let row = document.createElement('div');
159
159
  row.className = 'row';
160
- if (vars.rowClass)
161
- row.classList.add(vars.rowClass);
162
- if (vars.label)
163
- row.insertAdjacentHTML('beforeend', modal.build.label(vars));
160
+ if (args.rowClass)
161
+ row.classList.add(args.rowClass);
162
+ if (args.label)
163
+ row.insertAdjacentHTML('beforeend', modal.build.label(args));
164
164
  return row.outerHTML;
165
165
  },
166
166
 
167
- label: vars => {
167
+ label: args => {
168
168
  let label = document.createElement('label');
169
- label.setAttribute('for', vars.id);
169
+ label.setAttribute('for', args.id);
170
170
  label.className = 'fw-bold text-dark';
171
- label.textContent = vars.label;
171
+ label.textContent = args.label;
172
172
  return label.outerHTML;
173
173
  },
174
174
 
175
- modal: vars => {
176
- message.verbose('Building Dynamic Modal');
175
+ modal: args => {
176
+ msg.verbose('Building Dynamic Modal');
177
177
 
178
178
  // Modal container
179
179
  let modal = document.createElement('div');
180
180
  modal.className = 'modal fade';
181
- modal.id = vars.id;
181
+ modal.id = args.id;
182
182
  modal.setAttribute('tabindex', '-1');
183
183
  modal.setAttribute('role', 'dialog');
184
- modal.setAttribute('aria-labelledby', vars.title);
184
+ modal.setAttribute('aria-labelledby', args.title);
185
185
 
186
186
  // Modal dialog
187
187
  let modalDialog = document.createElement('div');
188
188
  modalDialog.className = 'modal-dialog';
189
- if (vars.class)
190
- modalDialog.classList.add(vars.class);
189
+ if (args.className)
190
+ modalDialog.classList.add(args.class);
191
191
 
192
192
  // Modal content
193
193
  let modalContent = document.createElement('div');
@@ -199,8 +199,8 @@ export const modal = {
199
199
 
200
200
  let modalTitle = document.createElement('h5');
201
201
  modalTitle.className = 'modal-title';
202
- modalTitle.id = `${vars.id}Label`;
203
- modalTitle.textContent = vars.title;
202
+ modalTitle.id = `${args.id}Label`;
203
+ modalTitle.textContent = args.title;
204
204
 
205
205
  let closeButton = document.createElement('button');
206
206
  closeButton.className = 'btn-close';
@@ -214,10 +214,10 @@ export const modal = {
214
214
  // Modal body
215
215
  let modalBody = document.createElement('div');
216
216
  modalBody.className = 'modal-body';
217
- modalBody.innerHTML = vars.body ?? '';
217
+ modalBody.innerHTML = args.body ?? '';
218
218
 
219
- if (vars.inputs)
220
- Object.values(vars.inputs).forEach(i => {
219
+ if (args.inputs)
220
+ Object.values(args.inputs).forEach(i => {
221
221
  if (i.type)
222
222
  modalBody.insertAdjacentHTML('beforeend', modal.build.inputLine(i));
223
223
  else
@@ -228,8 +228,8 @@ export const modal = {
228
228
  let modalFooter = document.createElement('div');
229
229
  modalFooter.className = 'modal-footer';
230
230
 
231
- if (vars.buttons)
232
- Object.values(vars.buttons).forEach(b => {
231
+ if (args.buttons)
232
+ Object.values(args.buttons).forEach(b => {
233
233
  let button = document.createElement('button');
234
234
  button.className = 'btn btn-outline-secondary me-1';
235
235
  if (b.class)
@@ -251,7 +251,7 @@ export const modal = {
251
251
  },
252
252
 
253
253
  close: () => {
254
- message.verbose('Closing Modals');
254
+ msg.verbose('Closing Modals');
255
255
  document.querySelectorAll('.modal').forEach(modal => {
256
256
  let bsModal = Modal.getOrCreateInstance(modal);
257
257
  if (bsModal) bsModal.hide();
@@ -259,7 +259,7 @@ export const modal = {
259
259
  },
260
260
 
261
261
  confirm: (msg, onConfirm, onCancel, title = "Are you sure?", buttonYes = "Yes", buttonNo = "No") => {
262
- message.verbose('Building Confirm Modal');
262
+ msg.verbose('Building Confirm Modal');
263
263
  let randomId = modal.randomId('confirm');
264
264
  document.querySelector('body').insertAdjacentHTML('beforeend', modal.build.modal({
265
265
  id: randomId,
@@ -1,4 +1,4 @@
1
- export const message = {
1
+ export const msg = {
2
2
 
3
3
  verbose: (msg) => {
4
4
  if (window.verbose) console.log(msg);
package/src/phoneInput.js CHANGED
@@ -27,6 +27,8 @@ export const phoneInput = {
27
27
  el.parentNode.querySelector('.input-group-text').innerHTML = '+';
28
28
  }
29
29
  });
30
+ if (el.value)
31
+ el.dispatchEvent(new Event('blur'));
30
32
  });
31
33
  }
32
34
  };
package/src/session.js CHANGED
@@ -1,37 +1,37 @@
1
- import { message } from "./message";
1
+ import { msg } from "./msg";
2
2
 
3
3
  export const session = {
4
4
  // Get a session variable as an integer
5
5
  getIntVar: (varName, defaultVal) => {
6
- message.verbose('Getting Integer Session Variable: ' + varName);
6
+ msg.verbose('Getting Integer Session Variable: ' + varName);
7
7
  var val = parseInt(sessionStorage.getItem(varName));
8
8
  return isNaN(val) ? defaultVal : val;
9
9
  },
10
10
  // Get a session variable as a boolean
11
11
  getBoolVar: (varName, defaultVal) => {
12
- message.verbose('Getting Boolean Session Variable: ' + varName);
12
+ msg.verbose('Getting Boolean Session Variable: ' + varName);
13
13
  var val = sessionStorage.getItem(varName);
14
14
  return val == 'true' ? true : val == 'false' ? false : defaultVal;
15
15
  },
16
16
  // Get a session variable as a string
17
17
  getStrVar: (varName, defaultVal) => {
18
- message.verbose('Getting String Session Variable: ' + varName);
18
+ msg.verbose('Getting String Session Variable: ' + varName);
19
19
  var val = sessionStorage.getItem(varName);
20
20
  return val ?? defaultVal;
21
21
  },
22
22
  // Set a session variable
23
23
  set: (varName, val) => {
24
- //message.verbose('Setting Session Variable: ' + varName + ' = ' + val);
24
+ //msg.verbose('Setting Session Variable: ' + varName + ' = ' + val);
25
25
  sessionStorage.setItem(varName, val);
26
26
  },
27
27
  // Remove a session variable
28
28
  removeVar: (varName) => {
29
- message.verbose('Removing Session Variable: ' + varName);
29
+ msg.verbose('Removing Session Variable: ' + varName);
30
30
  sessionStorage.removeItem(varName);
31
31
  },
32
32
  // Clear all session variables
33
33
  clear: () => {
34
- message.verbose('Clearing Session Variables');
34
+ msg.verbose('Clearing Session Variables');
35
35
  sessionStorage.clear();
36
36
  }
37
37
  };
package/src/validate.js CHANGED
@@ -1,4 +1,4 @@
1
- import { message } from './message.js';
1
+ import { msg } from './msg.js';
2
2
 
3
3
  export const validate = {
4
4
  methods: {
@@ -32,7 +32,7 @@ export const validate = {
32
32
  return form.querySelectorAll('input.is-invalid,select.is-invalid,textarea.is-invalid').length == 0;
33
33
  },
34
34
  init: () => {
35
- message.verbose('Initializing Validation');
35
+ msg.verbose('Initializing Validation');
36
36
  Object.entries(validate.methods).forEach(([ className, validationMethod ]) => {
37
37
  document.querySelectorAll('input.' + className + ',select.' + className + ',textarea.' + className).forEach(input => {
38
38
  input.addEventListener('blur', () => {
@@ -48,12 +48,12 @@ export const validate = {
48
48
  });
49
49
  document.querySelectorAll('form:not(.skip-validation)').forEach(form => {
50
50
  form.addEventListener('submit', ev => {
51
- message.verbose('Form Submitted, Validating');
51
+ msg.verbose('Form Submitted, Validating');
52
52
  if (!validate.check(form)) {
53
- message.warn('Form failed validation. Submited cancelled.');
53
+ msg.warn('Form failed validation. Submited cancelled.');
54
54
  ev.preventDefault();
55
55
  form.querySelector('input.is-invalid,select.is-invalid,textarea.is-invalid').focus();
56
- message.warn('Form failed validation. Submited cancelled.');
56
+ msg.warn('Form failed validation. Submited cancelled.');
57
57
  }
58
58
  });
59
59
  });