fix pwa, wizard focus, supervisor 5
This commit is contained in:
1 parent
ffc1ec0dcf
commit
d72381f0ac
11 files changed
+99
-25
No files matched your search
@@ -13,6 +13,8 @@
|
||||
const canonicalFiles = form.querySelector('input[name="files"]');
|
||||
const voiceRoot = form.querySelector('[data-ticket-voice-recorder]');
|
||||
let currentStep = 1;
|
||||
let guidedField = null;
|
||||
let guideTimer = null;
|
||||
|
||||
const toPersianDigits = value => String(value).replace(/\d/g, digit => '۰۱۲۳۴۵۶۷۸۹'[digit]);
|
||||
|
||||
@@ -39,14 +41,47 @@
|
||||
function clearValidation(number) {
|
||||
const step = form.querySelector(`[data-wizard-step="${number}"]`);
|
||||
const error = form.querySelector(`[data-wizard-error="${number}"]`);
|
||||
step?.querySelectorAll('[aria-invalid="true"]').forEach(field => field.removeAttribute('aria-invalid'));
|
||||
step?.querySelectorAll('[aria-invalid="true"]').forEach(field => {
|
||||
field.removeAttribute('aria-invalid');
|
||||
if (field.getAttribute('aria-describedby') === error?.id) field.removeAttribute('aria-describedby');
|
||||
});
|
||||
if (error) {
|
||||
error.textContent = '';
|
||||
error.classList.remove('is-visible');
|
||||
error.removeAttribute('tabindex');
|
||||
}
|
||||
}
|
||||
|
||||
function clearGuidedField(field = guidedField) {
|
||||
if (!field) return;
|
||||
field.closest('.field, .ticket-intent-search, .ticket-location-fields')?.classList.remove('is-guided-field');
|
||||
if (field === guidedField) guidedField = null;
|
||||
if (guideTimer) {
|
||||
window.clearTimeout(guideTimer);
|
||||
guideTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function guideToField(fields, error) {
|
||||
const field = fields.find(item => item && !item.disabled && !item.hidden && item.getClientRects().length);
|
||||
if (!field) {
|
||||
error?.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
|
||||
return;
|
||||
}
|
||||
clearGuidedField();
|
||||
guidedField = field;
|
||||
const container = field.closest('.field, .ticket-intent-search, .ticket-location-fields');
|
||||
container?.classList.add('is-guided-field');
|
||||
requestAnimationFrame(() => {
|
||||
field.focus({ preventScroll: true });
|
||||
field.scrollIntoView({
|
||||
behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth',
|
||||
block: 'center',
|
||||
inline: 'nearest',
|
||||
});
|
||||
});
|
||||
guideTimer = window.setTimeout(() => clearGuidedField(field), 2800);
|
||||
}
|
||||
|
||||
function showValidation(number, problem) {
|
||||
const step = form.querySelector(`[data-wizard-step="${number}"]`);
|
||||
const error = form.querySelector(`[data-wizard-error="${number}"]`);
|
||||
@@ -55,14 +90,13 @@
|
||||
if (manualRouting) manualRouting.open = true;
|
||||
}
|
||||
step?.querySelectorAll('[aria-invalid="true"]').forEach(field => field.removeAttribute('aria-invalid'));
|
||||
problem.fields.forEach(field => field?.setAttribute('aria-invalid', 'true'));
|
||||
error.textContent = problem.message;
|
||||
error.tabIndex = -1;
|
||||
error.classList.add('is-visible');
|
||||
requestAnimationFrame(() => {
|
||||
error.focus({ preventScroll: true });
|
||||
error.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
|
||||
problem.fields.forEach(field => {
|
||||
field?.setAttribute('aria-invalid', 'true');
|
||||
if (field && error?.id) field.setAttribute('aria-describedby', error.id);
|
||||
});
|
||||
error.textContent = problem.message;
|
||||
error.classList.add('is-visible');
|
||||
guideToField(problem.fields, error);
|
||||
}
|
||||
|
||||
function problemForStep(number) {
|
||||
@@ -145,9 +179,15 @@
|
||||
|
||||
form.addEventListener('input', event => {
|
||||
event.target.removeAttribute?.('aria-invalid');
|
||||
if (event.target.getAttribute?.('aria-describedby')?.startsWith('wizard-error-')) event.target.removeAttribute('aria-describedby');
|
||||
clearGuidedField(event.target);
|
||||
if (event.target === body) form.querySelector('[data-body-count]').textContent = toPersianDigits(body.value.length);
|
||||
});
|
||||
form.addEventListener('change', event => event.target.removeAttribute?.('aria-invalid'));
|
||||
form.addEventListener('change', event => {
|
||||
event.target.removeAttribute?.('aria-invalid');
|
||||
if (event.target.getAttribute?.('aria-describedby')?.startsWith('wizard-error-')) event.target.removeAttribute('aria-describedby');
|
||||
clearGuidedField(event.target);
|
||||
});
|
||||
|
||||
form.addEventListener('submit', event => {
|
||||
const invalidStep = [1, 2, 3, 4].find(number => problemForStep(number));
|
||||
@@ -314,7 +354,10 @@
|
||||
showStep(initialStep, { scroll: false });
|
||||
if (serverErrorStep) {
|
||||
const messages = [...serverErrorStep.querySelectorAll('.errorlist li')].map(item => item.textContent.trim()).filter(Boolean);
|
||||
const fields = [...serverErrorStep.querySelectorAll('.errorlist')]
|
||||
.map(list => list.closest('.field, .ticket-server-errors')?.querySelector('input, select, textarea'))
|
||||
.filter(Boolean);
|
||||
const number = Number(serverErrorStep.dataset.wizardStep);
|
||||
requestAnimationFrame(() => showValidation(number, { message: messages.join(' '), fields: [] }));
|
||||
requestAnimationFrame(() => showValidation(number, { message: messages.join(' '), fields }));
|
||||
}
|
||||
})();
|
||||
Reference in new issue
Block a user