redactor
This commit is contained in:
95
static/js/main.js
Normal file
95
static/js/main.js
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
// Bootstrap helpers
|
||||
(() => {
|
||||
'use strict';
|
||||
|
||||
// 1) Show Flask flash messages as Bootstrap toasts
|
||||
const flashes = document.getElementById('_flash_msgs');
|
||||
if (flashes) {
|
||||
try{
|
||||
const msgs = JSON.parse(flashes.dataset.msgs || "[]");
|
||||
const stack = document.getElementById('toast-stack');
|
||||
msgs.forEach((m) => {
|
||||
const el = document.createElement('div');
|
||||
el.className = 'toast align-items-center text-bg-primary border-0';
|
||||
el.role = 'alert'; el.ariaLive = 'assertive'; el.ariaAtomic = 'true';
|
||||
el.innerHTML = `<div class="d-flex">
|
||||
<div class="toast-body"><i class="bi bi-info-circle me-2"></i>${m}</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Zamknij"></button>
|
||||
</div>`;
|
||||
stack.appendChild(el);
|
||||
const t = new bootstrap.Toast(el, { delay: 3500 });
|
||||
t.show();
|
||||
});
|
||||
}catch(e){ console.warn('Toast parse error', e); }
|
||||
}
|
||||
|
||||
// 2) Client-side validation (Bootstrap)
|
||||
const forms = document.querySelectorAll('form');
|
||||
Array.from(forms).forEach(form => {
|
||||
form.addEventListener('submit', event => {
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
} else {
|
||||
// 3) Micro-loader on submit
|
||||
const submitBtn = form.querySelector('[type="submit"]');
|
||||
if (submitBtn && !submitBtn.dataset.loading) {
|
||||
submitBtn.dataset.loading = '1';
|
||||
submitBtn.disabled = true;
|
||||
const original = submitBtn.innerHTML;
|
||||
submitBtn.dataset.original = original;
|
||||
submitBtn.innerHTML = `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Przetwarzanie...`;
|
||||
}
|
||||
}
|
||||
form.classList.add('was-validated');
|
||||
}, false);
|
||||
});
|
||||
|
||||
// 4) Auto-accordion for long forms:
|
||||
// If a form contains multiple H2/H3 sections, group content between them.
|
||||
const targetForms = document.querySelectorAll('form');
|
||||
targetForms.forEach(form => {
|
||||
const headers = Array.from(form.querySelectorAll(':scope h2, :scope h3')).filter(h => h.textContent.trim().length>0);
|
||||
if (headers.length >= 2) {
|
||||
const acc = document.createElement('div');
|
||||
acc.className = 'accordion my-3'; acc.id = 'autoAccordion-' + Math.random().toString(36).slice(2);
|
||||
let startIdx = 0;
|
||||
headers.forEach((h, i) => {
|
||||
const itemId = acc.id + '-item-' + i;
|
||||
const headerId = itemId + '-hdr';
|
||||
const bodyId = itemId + '-body';
|
||||
const item = document.createElement('div'); item.className = 'accordion-item bg-body';
|
||||
const btnText = h.textContent.trim();
|
||||
// gather content until next header or end
|
||||
const chunk = [];
|
||||
let el = h.nextElementSibling;
|
||||
while (el && !headers.includes(el)) {
|
||||
chunk.push(el);
|
||||
el = el.nextElementSibling;
|
||||
}
|
||||
h.remove();
|
||||
const bodyInner = document.createElement('div');
|
||||
chunk.forEach(c => bodyInner.appendChild(c));
|
||||
item.innerHTML = `
|
||||
<h2 class="accordion-header" id="${headerId}">
|
||||
<button class="accordion-button ${i>0 ? 'collapsed' : ''}" type="button" data-bs-toggle="collapse" data-bs-target="#${bodyId}" aria-expanded="${i===0?'true':'false'}" aria-controls="${bodyId}">
|
||||
${btnText}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="${bodyId}" class="accordion-collapse collapse ${i===0?'show':''}" aria-labelledby="${headerId}" data-bs-parent="#${acc.id}">
|
||||
<div class="accordion-body"></div>
|
||||
</div>`;
|
||||
item.querySelector('.accordion-body').appendChild(bodyInner);
|
||||
acc.appendChild(item);
|
||||
});
|
||||
// Insert at top of form
|
||||
form.prepend(acc);
|
||||
}
|
||||
});
|
||||
|
||||
// Focus first control
|
||||
const first = document.querySelector('form input, form select, form textarea');
|
||||
if (first) first.focus({preventScroll:true});
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user