CSSの最適化や内部挙動の改良
This commit is contained in:
@@ -7,9 +7,7 @@ const XSS = {
|
||||
},
|
||||
|
||||
setTextSafe: function (element, text) {
|
||||
if (element) {
|
||||
element.textContent = text;
|
||||
}
|
||||
if (element) element.textContent = text;
|
||||
},
|
||||
|
||||
sanitizeUrl: function (url) {
|
||||
@@ -17,13 +15,9 @@ const XSS = {
|
||||
const cleaned = String(url).replace(/[\x00-\x1F\x7F]/g, '').trim();
|
||||
try {
|
||||
const parsed = new URL(cleaned, window.location.origin);
|
||||
if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {
|
||||
return parsed.href;
|
||||
}
|
||||
if (parsed.protocol === 'http:' || parsed.protocol === 'https:') return parsed.href;
|
||||
} catch (e) {
|
||||
if (cleaned.startsWith('/') && !cleaned.startsWith('//')) {
|
||||
return cleaned;
|
||||
}
|
||||
if (cleaned.startsWith('/') && !cleaned.startsWith('//')) return cleaned;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
@@ -31,26 +25,73 @@ const XSS = {
|
||||
|
||||
window.XSS = XSS;
|
||||
|
||||
let _pendingConfirmForm = null;
|
||||
|
||||
function showConfirmModal(message, onOk) {
|
||||
const bodyEl = document.getElementById('confirmModalBody');
|
||||
const okBtn = document.getElementById('confirmModalOk');
|
||||
if (!bodyEl || !okBtn) { if (onOk) onOk(); return; }
|
||||
bodyEl.textContent = message;
|
||||
const handler = function () {
|
||||
okBtn.removeEventListener('click', handler);
|
||||
bootstrap.Modal.getInstance(document.getElementById('confirmModal')).hide();
|
||||
if (onOk) onOk();
|
||||
};
|
||||
okBtn.addEventListener('click', handler);
|
||||
new bootstrap.Modal(document.getElementById('confirmModal')).show();
|
||||
}
|
||||
|
||||
window.showConfirmModal = showConfirmModal;
|
||||
|
||||
function setupFormSubmitOnce(form) {
|
||||
form.addEventListener('submit', function () {
|
||||
const btn = form.querySelector('[type=submit]');
|
||||
if (!btn || btn.disabled) return;
|
||||
btn.disabled = true;
|
||||
const orig = btn.innerHTML;
|
||||
btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>処理中...';
|
||||
window.addEventListener('pageshow', function () {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = orig;
|
||||
}, { once: true });
|
||||
});
|
||||
}
|
||||
|
||||
function showCopyFeedback(message) {
|
||||
let el = document.getElementById('globalCopyFeedback');
|
||||
if (!el) {
|
||||
el = document.createElement('div');
|
||||
el.id = 'globalCopyFeedback';
|
||||
el.className = 'copy-feedback alert alert-success shadow-sm py-2 px-3';
|
||||
document.body.appendChild(el);
|
||||
}
|
||||
el.textContent = message;
|
||||
el.classList.add('show');
|
||||
clearTimeout(el._timeout);
|
||||
el._timeout = setTimeout(function () { el.classList.remove('show'); }, 2000);
|
||||
}
|
||||
|
||||
window.showCopyFeedback = showCopyFeedback;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const alerts = document.querySelectorAll('.alert:not(.alert-danger):not(.modal .alert)');
|
||||
alerts.forEach(function (alert) {
|
||||
setTimeout(function () {
|
||||
alert.classList.add('fade');
|
||||
setTimeout(function () {
|
||||
alert.remove();
|
||||
}, 150);
|
||||
setTimeout(function () { alert.remove(); }, 150);
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
const confirmForms = document.querySelectorAll('form[data-confirm]');
|
||||
confirmForms.forEach(function (form) {
|
||||
document.querySelectorAll('form[data-confirm]').forEach(function (form) {
|
||||
form.addEventListener('submit', function (e) {
|
||||
if (!confirm(form.dataset.confirm)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
e.preventDefault();
|
||||
const msg = form.dataset.confirm;
|
||||
showConfirmModal(msg, function () { form.submit(); });
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('form:not([data-confirm])').forEach(setupFormSubmitOnce);
|
||||
|
||||
const dueDateInput = document.getElementById('due_date');
|
||||
if (dueDateInput && !dueDateInput.value) {
|
||||
const tomorrow = new Date();
|
||||
|
||||
Reference in New Issue
Block a user