@ntlab/ntjs-repo 3.0.0
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/Bootstrap/Dialog/Confirm.js +82 -0
- package/Bootstrap/Dialog/Input.js +85 -0
- package/Bootstrap/Dialog/Message.js +63 -0
- package/Bootstrap/Dialog/Wait.js +136 -0
- package/Bootstrap/Dialog/index.js +345 -0
- package/Bootstrap/FormPost.js +145 -0
- package/Bootstrap/Notification.js +94 -0
- package/Bootstrap/index.js +45 -0
- package/BootstrapIcons.js +42 -0
- package/JQuery/AjaxHelper.js +82 -0
- package/JQuery/Define.js +81 -0
- package/JQuery/FormPost.js +278 -0
- package/JQuery/Notification.js +127 -0
- package/JQuery/PostErrorHelper.js +266 -0
- package/JQuery/PostHandler.js +78 -0
- package/JQuery/ScrollTo.js +63 -0
- package/JQuery/Util.js +112 -0
- package/JQuery/index.js +71 -0
- package/LICENSE +21 -0
- package/Popper.js +65 -0
- package/README.md +3 -0
- package/SemanticUI/Dialog/Confirm.js +79 -0
- package/SemanticUI/Dialog/Input.js +79 -0
- package/SemanticUI/Dialog/Message.js +59 -0
- package/SemanticUI/Dialog/Wait.js +75 -0
- package/SemanticUI/Dialog/index.js +228 -0
- package/SemanticUI/Loader.js +157 -0
- package/SemanticUI/Notification.js +58 -0
- package/SemanticUI/index.js +46 -0
- package/SocketIO/index.js +43 -0
- package/index.js +29 -0
- package/package.json +30 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2023-2025 Toha <tohenk@yahoo.com>
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
7
|
+
* this software and associated documentation files (the "Software"), to deal in
|
|
8
|
+
* the Software without restriction, including without limitation the rights to
|
|
9
|
+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
10
|
+
* of the Software, and to permit persons to whom the Software is furnished to do
|
|
11
|
+
* so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const Stringify = require('@ntlab/ntlib/stringify');
|
|
26
|
+
const { ScriptRepository, ScriptManager } = require('@ntlab/ntjs');
|
|
27
|
+
const JQuery = ScriptManager.require('JQuery');
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Bootstrap/Dialog script repository.
|
|
31
|
+
*/
|
|
32
|
+
class Dialog extends JQuery {
|
|
33
|
+
|
|
34
|
+
initialize() {
|
|
35
|
+
this.name = 'Dialog';
|
|
36
|
+
this.position = ScriptRepository.POSITION_FIRST;
|
|
37
|
+
this.addDependencies(['Bootstrap', 'JQuery/Define', 'JQuery/Util']);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getIconSet() {
|
|
41
|
+
const loading = this.translate('Loading...');
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
'ICON_INFO': 'bi-info-circle text-info fs-1',
|
|
45
|
+
'ICON_ALERT':'bi-exclamation-circle text-warning fs-1',
|
|
46
|
+
'ICON_ERROR': 'bi-x-circle text-danger fs-1',
|
|
47
|
+
'ICON_SUCCESS': 'bi-check-circle text-success fs-1',
|
|
48
|
+
'ICON_QUESTION': 'bi-question-circle text-primary fs-1',
|
|
49
|
+
'ICON_INPUT': 'bi-pencil-square text-primary fs-1',
|
|
50
|
+
'BTN_ICON_OK': 'bi-check-lg',
|
|
51
|
+
'BTN_ICON_CANCEL': 'bi-x-lg',
|
|
52
|
+
'BTN_ICON_CLOSE': 'bi-x-circle',
|
|
53
|
+
'spinnerTmpl': `<div class="spinner-border text-secondary" role="status"><span class="visually-hidden">${loading}</span></div>`,
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getScript() {
|
|
58
|
+
const icons = this.getIconSet();
|
|
59
|
+
|
|
60
|
+
return `
|
|
61
|
+
$.define('ntdlg', {
|
|
62
|
+
ICON_INFO: null,
|
|
63
|
+
ICON_ALERT: null,
|
|
64
|
+
ICON_ERROR: null,
|
|
65
|
+
ICON_SUCCESS: null,
|
|
66
|
+
ICON_QUESTION: null,
|
|
67
|
+
ICON_INPUT: null,
|
|
68
|
+
BTN_ICON_OK: null,
|
|
69
|
+
BTN_ICON_CANCEL: null,
|
|
70
|
+
BTN_ICON_CLOSE: null,
|
|
71
|
+
dialogTmpl:
|
|
72
|
+
'<div id="%ID%" class="modal fade" tabindex="-1" aria-labelledby="%ID%-title">' +
|
|
73
|
+
' <div class="%MODAL%">' +
|
|
74
|
+
' <div class="modal-content">' +
|
|
75
|
+
' <div class="modal-header">' +
|
|
76
|
+
' <h5 id="%ID%-title" class="modal-title text-truncate">%TITLE%</h5>' +
|
|
77
|
+
' %CLOSE%' +
|
|
78
|
+
' </div>' +
|
|
79
|
+
' <div class="modal-body">%CONTENT%</div>' +
|
|
80
|
+
' <div class="modal-footer">%BUTTONS%</div>' +
|
|
81
|
+
' </div>' +
|
|
82
|
+
' </div>' +
|
|
83
|
+
'</div>',
|
|
84
|
+
iconTmpl:
|
|
85
|
+
'<span class="dialog-icon %ICON%"></span>',
|
|
86
|
+
messageTmpl:
|
|
87
|
+
'<div class="d-flex flex-row">' +
|
|
88
|
+
' <div class="flex-shrink-0 px-2">%ICON%</div>' +
|
|
89
|
+
' <div class="flex-grow-1 ms-3 align-self-center">%MESSAGE%</div>' +
|
|
90
|
+
'</div>',
|
|
91
|
+
buttonClass:
|
|
92
|
+
'btn btn-outline-%TYPE%',
|
|
93
|
+
buttonIconTmpl:
|
|
94
|
+
'<span class="%ICON%"></span> %CAPTION%',
|
|
95
|
+
buttonTmpl:
|
|
96
|
+
'<button id="%ID%" type="button" class="%BTNCLASS%">%CAPTION%</button>',
|
|
97
|
+
closeTmpl:
|
|
98
|
+
'<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="$close"></button>',
|
|
99
|
+
title(t) {
|
|
100
|
+
let _icon, _title;
|
|
101
|
+
if (t && t.title) {
|
|
102
|
+
_title = t.title;
|
|
103
|
+
if (t.icon) {
|
|
104
|
+
_icon = t.icon;
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
_title = t;
|
|
108
|
+
}
|
|
109
|
+
if (_icon) {
|
|
110
|
+
_icon = typeof $.ntdlg.createIcon === 'function' ? $.ntdlg.createIcon(_icon) :
|
|
111
|
+
\`<span class="\${_icon}"></span>\`;
|
|
112
|
+
} else if ($.ntdlg.defaultIcon) {
|
|
113
|
+
_icon = $.ntdlg.defaultIcon;
|
|
114
|
+
}
|
|
115
|
+
return _icon ? _icon + ' ' + _title : _title;
|
|
116
|
+
},
|
|
117
|
+
create(id, title, message, options) {
|
|
118
|
+
const self = this;
|
|
119
|
+
const dlg_id = '#' + id;
|
|
120
|
+
$(dlg_id).remove();
|
|
121
|
+
if ($.ntdlg.moved && $.ntdlg.moved.refs[id] !== undefined) {
|
|
122
|
+
$('div.' + $.ntdlg.moved.refs[id]).remove();
|
|
123
|
+
delete $.ntdlg.moved.refs[id];
|
|
124
|
+
}
|
|
125
|
+
const closable = options.closable !== undefined ? options.closable : true;
|
|
126
|
+
const buttons = [];
|
|
127
|
+
const handlers = [];
|
|
128
|
+
let cnt = 0;
|
|
129
|
+
if (options.buttons) {
|
|
130
|
+
Object.keys(options.buttons).forEach(k => {
|
|
131
|
+
const v = options.buttons[k];
|
|
132
|
+
let caption, btnType, btnIcon, handler;
|
|
133
|
+
if (Array.isArray(v) || typeof v === 'object') {
|
|
134
|
+
caption = v.caption ? v.caption : k;
|
|
135
|
+
btnType = v.type ? v.type : (0 === cnt ? 'primary' : 'secondary');
|
|
136
|
+
if (v.icon) {
|
|
137
|
+
btnIcon = v.icon;
|
|
138
|
+
}
|
|
139
|
+
handler = typeof v.handler === 'function' ? v.handler : null;
|
|
140
|
+
} else {
|
|
141
|
+
caption = k;
|
|
142
|
+
btnType = 0 === cnt ? 'primary' : 'secondary';
|
|
143
|
+
handler = typeof v === 'function' ? v : null;
|
|
144
|
+
}
|
|
145
|
+
const btnid = id + '_btn_' + caption.replace(/\W+/g, "-").toLowerCase();
|
|
146
|
+
const btnclass = $.util.template(self.buttonClass, {TYPE: btnType});
|
|
147
|
+
if (btnIcon) {
|
|
148
|
+
caption = $.util.template(self.buttonIconTmpl, {CAPTION: caption, ICON: btnIcon});
|
|
149
|
+
}
|
|
150
|
+
buttons.push($.util.template(self.buttonTmpl, {
|
|
151
|
+
ID: btnid,
|
|
152
|
+
BTNCLASS: btnclass,
|
|
153
|
+
CAPTION: caption
|
|
154
|
+
}));
|
|
155
|
+
if (typeof handler === 'function') {
|
|
156
|
+
handlers.push({id: btnid, handler: handler});
|
|
157
|
+
}
|
|
158
|
+
cnt++;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
const m = ['modal-dialog', 'modal-dialog-centered'];
|
|
162
|
+
if (options.size) {
|
|
163
|
+
m.push('modal-' + options.size);
|
|
164
|
+
}
|
|
165
|
+
const content = $.util.template(self.dialogTmpl, {
|
|
166
|
+
ID: id,
|
|
167
|
+
TITLE: self.title(title),
|
|
168
|
+
MODAL: m.join(' '),
|
|
169
|
+
CLOSE: closable ? self.closeTmpl : '',
|
|
170
|
+
BUTTONS: buttons.join(''),
|
|
171
|
+
CONTENT: message
|
|
172
|
+
});
|
|
173
|
+
$(document.body).append(content);
|
|
174
|
+
const dlg = $(dlg_id);
|
|
175
|
+
// move embedded modal
|
|
176
|
+
const bd = dlg.find('.modal-body');
|
|
177
|
+
const d = bd.find('div.modal');
|
|
178
|
+
if (d.length) {
|
|
179
|
+
if (!$.ntdlg.moved) {
|
|
180
|
+
$.ntdlg.moved = {count: 0, refs: {}}
|
|
181
|
+
}
|
|
182
|
+
$.ntdlg.moved.count++;
|
|
183
|
+
const movedDlg = id + '-moved-' + $.ntdlg.moved.count;
|
|
184
|
+
$.ntdlg.moved.refs[id] = movedDlg;
|
|
185
|
+
d.addClass(movedDlg);
|
|
186
|
+
d.appendTo($(document.body));
|
|
187
|
+
}
|
|
188
|
+
if (buttons.length === 0) {
|
|
189
|
+
dlg.find('.modal-footer').hide();
|
|
190
|
+
}
|
|
191
|
+
Object.values(handlers).forEach(v => {
|
|
192
|
+
$('#' + v.id).on('click', function(e) {
|
|
193
|
+
e.preventDefault();
|
|
194
|
+
v.handler.apply(dlg);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
const opts = ['backdrop', 'keyboard', 'show', 'remote'];
|
|
198
|
+
const events = ['show.bs.modal', 'shown.bs.modal', 'hide.bs.modal', 'hidden.bs.modal', 'loaded.bs.modal'];
|
|
199
|
+
const modal_options = {};
|
|
200
|
+
$.util.applyProp(opts, options, modal_options);
|
|
201
|
+
$.util.applyEvent(dlg, events, options);
|
|
202
|
+
// compatibility with JQuery UI dialog
|
|
203
|
+
const deprecatedEvents = {open: 'shown.bs.modal', close: 'hidden.bs.modal'};
|
|
204
|
+
Object.keys(deprecatedEvents).forEach(event => {
|
|
205
|
+
const newEvent = deprecatedEvents[event];
|
|
206
|
+
if (typeof options[event] === 'function') {
|
|
207
|
+
dlg.on(newEvent, options[event]);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
self._create(dlg[0], modal_options);
|
|
211
|
+
return dlg;
|
|
212
|
+
},
|
|
213
|
+
dialog(id, title, message, icon, buttons, close_cb) {
|
|
214
|
+
const self = this;
|
|
215
|
+
icon = icon || self.ICON_INFO;
|
|
216
|
+
buttons = buttons || [];
|
|
217
|
+
message = $.util.template(self.messageTmpl, {
|
|
218
|
+
ICON: $.util.template(self.iconTmpl, {ICON: icon}),
|
|
219
|
+
MESSAGE: message
|
|
220
|
+
});
|
|
221
|
+
const dlg = self.create(id, title, message, {
|
|
222
|
+
['shown.bs.modal'](e) {
|
|
223
|
+
e.preventDefault();
|
|
224
|
+
let focused = dlg.find('input.focused');
|
|
225
|
+
if (focused.length) {
|
|
226
|
+
focused.focus();
|
|
227
|
+
} else {
|
|
228
|
+
const buttons = dlg.find('.modal-footer button.btn');
|
|
229
|
+
if (buttons.length) {
|
|
230
|
+
buttons.first().focus();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
['hidden.bs.modal'](e) {
|
|
235
|
+
e.preventDefault();
|
|
236
|
+
if (typeof close_cb === 'function') {
|
|
237
|
+
close_cb();
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
buttons
|
|
241
|
+
});
|
|
242
|
+
$.ntdlg.show(dlg);
|
|
243
|
+
return dlg;
|
|
244
|
+
},
|
|
245
|
+
show(dlg) {
|
|
246
|
+
const self = this;
|
|
247
|
+
if (dlg && !this.isVisible(dlg)) {
|
|
248
|
+
if (typeof dlg === 'string') {
|
|
249
|
+
dlg = $('#' + dlg);
|
|
250
|
+
}
|
|
251
|
+
let d = self._get(dlg[0]);
|
|
252
|
+
if (!d) {
|
|
253
|
+
d = self._create(dlg[0]);
|
|
254
|
+
}
|
|
255
|
+
if (d) {
|
|
256
|
+
d.show();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
close(dlg) {
|
|
261
|
+
const self = this;
|
|
262
|
+
if (dlg) {
|
|
263
|
+
if (typeof dlg === 'string') {
|
|
264
|
+
dlg = $('#' + dlg);
|
|
265
|
+
}
|
|
266
|
+
const d = self._get(dlg[0]);
|
|
267
|
+
if (d) {
|
|
268
|
+
d.hide();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
isVisible(dlg) {
|
|
273
|
+
if (dlg) {
|
|
274
|
+
if (typeof dlg === 'string') {
|
|
275
|
+
dlg = $('#' + dlg);
|
|
276
|
+
}
|
|
277
|
+
if (dlg.length) {
|
|
278
|
+
if (dlg.hasClass('modal') && dlg.is(':visible')) {
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
getBody(dlg) {
|
|
286
|
+
if (dlg) {
|
|
287
|
+
if (typeof dlg === 'string') {
|
|
288
|
+
dlg = $('#' + dlg);
|
|
289
|
+
}
|
|
290
|
+
return dlg.find('.modal-body:first');
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
_create(el, options) {
|
|
294
|
+
return new bootstrap.Modal(el, options || {});
|
|
295
|
+
},
|
|
296
|
+
_get(el) {
|
|
297
|
+
return bootstrap.Modal.getInstance(el);
|
|
298
|
+
},
|
|
299
|
+
init() {
|
|
300
|
+
// icon set
|
|
301
|
+
Object.assign(this, ${Stringify.from(icons, 2)});
|
|
302
|
+
// https://stackoverflow.com/questions/19305821/multiple-modals-overlay
|
|
303
|
+
// fix z-index
|
|
304
|
+
const p = bootstrap.Modal.prototype;
|
|
305
|
+
if (p.__showElement === undefined) {
|
|
306
|
+
p.__showElement = p._showElement;
|
|
307
|
+
p._showElement = function(relatedTarget) {
|
|
308
|
+
this.__showElement(relatedTarget);
|
|
309
|
+
let cIdx = zIdx = parseInt($(this._element).css('z-index'));
|
|
310
|
+
if ($.ntdlg.zIndex) {
|
|
311
|
+
zIdx = Math.max(zIdx, $.ntdlg.zIndex);
|
|
312
|
+
}
|
|
313
|
+
const modalCount = $('.modal:visible').length;
|
|
314
|
+
if (modalCount > 1 || zIdx > cIdx) {
|
|
315
|
+
zIdx += 10 * (modalCount - 1);
|
|
316
|
+
$(this._element).css('z-index', zIdx);
|
|
317
|
+
$(this._backdrop).css('z-index', zIdx - 1);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// re-add modal-open class if there're still opened modal
|
|
322
|
+
if (p.__resetAdjustments === undefined) {
|
|
323
|
+
p.__resetAdjustments = p._resetAdjustments;
|
|
324
|
+
p._resetAdjustments = function() {
|
|
325
|
+
this.__resetAdjustments();
|
|
326
|
+
if ($('.modal:visible').length > 0) {
|
|
327
|
+
$(document.body).addClass('modal-open');
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}, true);
|
|
333
|
+
`;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
getInitScript() {
|
|
337
|
+
this.addLast(`$.ntdlg.init();`);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
static instance() {
|
|
341
|
+
return new this();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
module.exports = Dialog;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2018-2025 Toha <tohenk@yahoo.com>
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
7
|
+
* this software and associated documentation files (the "Software"), to deal in
|
|
8
|
+
* the Software without restriction, including without limitation the rights to
|
|
9
|
+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
10
|
+
* of the Software, and to permit persons to whom the Software is furnished to do
|
|
11
|
+
* so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const Stringify = require('@ntlab/ntlib/stringify');
|
|
26
|
+
const { ScriptRepository, ScriptManager } = require('@ntlab/ntjs');
|
|
27
|
+
const JQueryFormPost = ScriptManager.require('JQuery/FormPost');
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Bootstrap/FormPost script repository.
|
|
31
|
+
*/
|
|
32
|
+
class FormPost extends JQueryFormPost {
|
|
33
|
+
|
|
34
|
+
initialize() {
|
|
35
|
+
this.name = 'FormPost';
|
|
36
|
+
this.position = ScriptRepository.POSITION_FIRST;
|
|
37
|
+
this.addDependencies(['JQuery', 'JQuery/PostHandler', 'Bootstrap/Dialog/Wait', 'Bootstrap/Dialog/Message']);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getOverrides() {
|
|
41
|
+
const ok = this.translate('OK');
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
showSuccessMessage: Stringify.raw(`function(title, message, opts) {
|
|
45
|
+
const autoclose = opts.autoClose !== undefined ? opts.autoClose : false;
|
|
46
|
+
const withokay = opts.withOkay !== undefined ? opts.withOkay : true;
|
|
47
|
+
const buttons = {};
|
|
48
|
+
if (withokay && !autoclose) {
|
|
49
|
+
buttons['${ok}'] = {
|
|
50
|
+
icon: $.ntdlg.BTN_ICON_OK,
|
|
51
|
+
handler() {
|
|
52
|
+
$.ntdlg.close($(this));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const dlg = $.ntdlg.dialog('form_post_success', title, message, $.ntdlg.ICON_SUCCESS, buttons);
|
|
57
|
+
if (autoclose) {
|
|
58
|
+
dlg.on('shown.bs.modal', function() {
|
|
59
|
+
$.ntdlg.close($(this));
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}`),
|
|
63
|
+
showErrorMessage: Stringify.raw(`function(title, message, callback) {
|
|
64
|
+
$.ntdlg.dialog('form_post_error', title, message, $.ntdlg.ICON_ERROR, {
|
|
65
|
+
'${ok}': {
|
|
66
|
+
icon: $.ntdlg.BTN_ICON_OK,
|
|
67
|
+
handler() {
|
|
68
|
+
$.ntdlg.close($(this));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}, callback);
|
|
72
|
+
}`),
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getErrHelperOptions() {
|
|
77
|
+
return {
|
|
78
|
+
errorContainer: '.alert-danger .msg',
|
|
79
|
+
errorFormat: Stringify.raw('$.errformat.INPLACE'),
|
|
80
|
+
parentClass: null,
|
|
81
|
+
errClass: 'is-invalid',
|
|
82
|
+
toggleClass: 'd-none',
|
|
83
|
+
listClass: 'list-unstyled mb-0',
|
|
84
|
+
visibilityUseClass: true,
|
|
85
|
+
inplace: Stringify.raw(`function(el, error) {
|
|
86
|
+
if (el.hasClass('alert-danger')) {
|
|
87
|
+
el.html(error);
|
|
88
|
+
} else {
|
|
89
|
+
let tt = el;
|
|
90
|
+
const f = function(x, a, p) {
|
|
91
|
+
const errDisp = x.attr(a);
|
|
92
|
+
if (errDisp) {
|
|
93
|
+
const xel = p ? x.parents(errDisp) : x.siblings(errDisp);
|
|
94
|
+
if (xel.length) {
|
|
95
|
+
return xel;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
let xel = f(tt, 'data-err-display');
|
|
100
|
+
if (!xel) {
|
|
101
|
+
xel = f(tt, 'data-err-display-parent', true);
|
|
102
|
+
}
|
|
103
|
+
if (xel) {
|
|
104
|
+
tt = xel;
|
|
105
|
+
}
|
|
106
|
+
// don't add tooltip on hidden input
|
|
107
|
+
if (tt.is('input[type="hidden"]')) {
|
|
108
|
+
tt = tt.siblings('input');
|
|
109
|
+
}
|
|
110
|
+
let tooltip = bootstrap.Tooltip.getInstance(tt[0]);
|
|
111
|
+
if (tooltip) {
|
|
112
|
+
tooltip._config.title = error;
|
|
113
|
+
} else {
|
|
114
|
+
tooltip = new bootstrap.Tooltip(tt[0], {title: error, placement: 'right'});
|
|
115
|
+
}
|
|
116
|
+
xel = f(el, 'data-err-target');
|
|
117
|
+
el = xel ? xel : tt;
|
|
118
|
+
el.data('err-tt', tt);
|
|
119
|
+
}
|
|
120
|
+
return el;
|
|
121
|
+
}`),
|
|
122
|
+
onErrReset: Stringify.raw(`function(helper) {
|
|
123
|
+
if (helper.container) {
|
|
124
|
+
helper.container.find('.' + helper.errClass).each(function() {
|
|
125
|
+
const el = $(this);
|
|
126
|
+
const tt = el.data('err-tt');
|
|
127
|
+
if (tt) {
|
|
128
|
+
const tooltip = bootstrap.Tooltip.getInstance(tt[0]);
|
|
129
|
+
if (tooltip) {
|
|
130
|
+
tooltip._config.title = '';
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
el.removeClass(helper.errClass);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}`),
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static instance() {
|
|
141
|
+
return new this();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
module.exports = FormPost;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2018-2025 Toha <tohenk@yahoo.com>
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
7
|
+
* this software and associated documentation files (the "Software"), to deal in
|
|
8
|
+
* the Software without restriction, including without limitation the rights to
|
|
9
|
+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
10
|
+
* of the Software, and to permit persons to whom the Software is furnished to do
|
|
11
|
+
* so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const { ScriptManager, ScriptRepository } = require('@ntlab/ntjs');
|
|
26
|
+
const JQuery = ScriptManager.require('JQuery');
|
|
27
|
+
|
|
28
|
+
class Notification extends JQuery {
|
|
29
|
+
|
|
30
|
+
initialize() {
|
|
31
|
+
this.name = 'Notification';
|
|
32
|
+
this.position = ScriptRepository.POSITION_MIDDLE;
|
|
33
|
+
this.dependencies = ['Bootstrap', 'JQuery/Define', 'JQuery/Notification'];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getScript() {
|
|
37
|
+
const close = this.translate('Close');
|
|
38
|
+
|
|
39
|
+
return `
|
|
40
|
+
$.define('notif', {
|
|
41
|
+
notifyMessage(message, options) {
|
|
42
|
+
const self = this;
|
|
43
|
+
let icon;
|
|
44
|
+
switch (options) {
|
|
45
|
+
case 'success':
|
|
46
|
+
icon = 'bi-check-circle text-success';
|
|
47
|
+
break;
|
|
48
|
+
case 'error':
|
|
49
|
+
icon = 'bi-x-circle text-danger';
|
|
50
|
+
break;
|
|
51
|
+
case 'info':
|
|
52
|
+
icon = 'bi-info-circle text-info';
|
|
53
|
+
break;
|
|
54
|
+
case 'warn':
|
|
55
|
+
icon = 'bi-exclamation-circle text-warning';
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
const tmpl =
|
|
59
|
+
'<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">' +
|
|
60
|
+
' <div class="toast-header">' +
|
|
61
|
+
' <span class="bi-bell me-1"></span>' +
|
|
62
|
+
' <strong class="me-auto">%TITLE%</strong>' +
|
|
63
|
+
' <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="${close}"></button>' +
|
|
64
|
+
' </div>' +
|
|
65
|
+
' <div class="toast-body">' +
|
|
66
|
+
' <div class="d-flex flex-row">' +
|
|
67
|
+
' <div class="flex-shrink-0"><span class="%ICON% fs-4"></span></div>' +
|
|
68
|
+
' <div class="flex-grow-1 ms-3 align-self-center">%MESSAGE%</div>' +
|
|
69
|
+
' </div>' +
|
|
70
|
+
' </div>' +
|
|
71
|
+
'</div>';
|
|
72
|
+
const toast = tmpl
|
|
73
|
+
.replace(/%TITLE%/, options.title || self.title)
|
|
74
|
+
.replace(/%ICON%/, icon)
|
|
75
|
+
.replace(/%MESSAGE%/, message)
|
|
76
|
+
;
|
|
77
|
+
if (self.container === undefined) {
|
|
78
|
+
self.container = $('<div class="notification-container position-fixed bottom-0 end-0 p-3"></div>').appendTo(document.body);
|
|
79
|
+
}
|
|
80
|
+
const el = $(toast).appendTo(self.container);
|
|
81
|
+
const t = new bootstrap.Toast(el[0]);
|
|
82
|
+
t.show();
|
|
83
|
+
return t;
|
|
84
|
+
}
|
|
85
|
+
}, true);
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static instance() {
|
|
90
|
+
return new this();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = Notification;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2023-2025 Toha <tohenk@yahoo.com>
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
7
|
+
* this software and associated documentation files (the "Software"), to deal in
|
|
8
|
+
* the Software without restriction, including without limitation the rights to
|
|
9
|
+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
10
|
+
* of the Software, and to permit persons to whom the Software is furnished to do
|
|
11
|
+
* so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const { Script, ScriptAsset } = require('@ntlab/ntjs');
|
|
26
|
+
|
|
27
|
+
class Bootstrap extends Script {
|
|
28
|
+
|
|
29
|
+
initialize() {
|
|
30
|
+
this.name = 'Bootstrap';
|
|
31
|
+
this.dependencies = ['Popper'];
|
|
32
|
+
this.assetPath = 'bootstrap';
|
|
33
|
+
this.getAsset()
|
|
34
|
+
.setPath(ScriptAsset.JAVASCRIPT, 'js')
|
|
35
|
+
.setPath(ScriptAsset.STYLESHEET, 'css');
|
|
36
|
+
this.addAsset(ScriptAsset.JAVASCRIPT, 'bootstrap.min');
|
|
37
|
+
this.addAsset(ScriptAsset.STYLESHEET, 'bootstrap.min');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static instance() {
|
|
41
|
+
return new this();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = Bootstrap;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2023-2025 Toha <tohenk@yahoo.com>
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
7
|
+
* this software and associated documentation files (the "Software"), to deal in
|
|
8
|
+
* the Software without restriction, including without limitation the rights to
|
|
9
|
+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
10
|
+
* of the Software, and to permit persons to whom the Software is furnished to do
|
|
11
|
+
* so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const { Script, ScriptAsset } = require('@ntlab/ntjs');
|
|
26
|
+
|
|
27
|
+
class BootstrapIcons extends Script {
|
|
28
|
+
|
|
29
|
+
initialize() {
|
|
30
|
+
this.name = 'BootstrapIcons';
|
|
31
|
+
this.assetPath = 'bootstrap-icons';
|
|
32
|
+
this.getAsset()
|
|
33
|
+
.setPath(ScriptAsset.STYLESHEET, 'font');
|
|
34
|
+
this.addAsset(ScriptAsset.STYLESHEET, 'bootstrap-icons');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static instance() {
|
|
38
|
+
return new this();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = BootstrapIcons;
|