CaiWuXiTong/resources/views/system_settings/partials/navigation-script.blade.php

75 lines
3.4 KiB
PHP

@once
@push('scripts_start')
<script>
(() => {
if (window.caiwuSettingsNavigation) return;
window.caiwuSettingsNavigation = true;
let pending;
const supports = url => url.origin === location.origin
&& /\/system-settings\/(?:(?:users|groups)(?:\/create|\/\d+\/edit)?|users\/\d+\/groups|permissions|sidebar|workflow-reviewers)$/.test(url.pathname);
async function navigate(url, push = true) {
const current = document.querySelector('[data-settings-workspace]');
if (!current) return;
pending?.abort();
const controller = new AbortController();
pending = controller;
current.setAttribute('aria-busy', 'true');
try {
const response = await fetch(url, {signal:controller.signal, credentials:'same-origin'});
const page = new DOMParser().parseFromString(await response.text(), 'text/html');
const next = page.querySelector('[data-settings-workspace]');
const header = page.querySelector('#header');
if (!response.ok || !next || !header) throw new Error('unavailable');
current.replaceWith(next);
document.querySelector('#header')?.replaceWith(header);
document.title = page.title;
document.querySelectorAll('#menu-settings a[id]').forEach(link => {
const updated = page.getElementById(link.id);
if (updated) link.className = updated.className;
});
if (push) {
history.replaceState({...history.state, settingsPage:true}, '', location.href);
history.pushState({settingsPage:true}, '', url);
}
const title = header.querySelector('h1');
title?.setAttribute('tabindex', '-1');
title?.focus({preventScroll:true});
window.scrollTo(0, 0);
} catch (error) {
if (error.name === 'AbortError') return;
let alert = current.querySelector('[data-settings-navigation-error]');
if (!alert) {
alert = document.createElement('p');
alert.dataset.settingsNavigationError = '';
alert.setAttribute('role', 'alert');
alert.className = 'mb-4 text-sm text-red-700';
current.prepend(alert);
}
alert.textContent = '页面暂时无法加载,请重试。';
} finally {
current.removeAttribute('aria-busy');
}
}
document.addEventListener('click', event => {
const link = event.target.closest('a[href]');
if (!link || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || link.target) return;
const url = new URL(link.href);
if (!document.querySelector('[data-settings-workspace]') || !supports(url)) return;
event.preventDefault();
navigate(url.href);
});
document.addEventListener('change', event => {
if (!event.target.matches('[data-settings-subject]')) return;
const form = event.target.form;
const url = new URL(form.action);
url.search = new URLSearchParams(new FormData(form)).toString();
navigate(url.href);
});
window.addEventListener('popstate', event => {
if (event.state?.settingsPage && supports(new URL(location.href))) navigate(location.href, false);
});
})();
</script>
@endpush
@endonce