You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
5.4 KiB
187 lines
5.4 KiB
(function () { |
|
'use strict'; |
|
|
|
var frameId = 'app-content'; |
|
var shell = document.querySelector('[data-app-shell]'); |
|
if (!shell) { |
|
return; |
|
} |
|
|
|
function isDesktop() { |
|
return window.matchMedia('(min-width: 1024px)').matches; |
|
} |
|
|
|
function routeMatches(patterns, routeName) { |
|
if (!routeName || !patterns || !patterns.length) { |
|
return false; |
|
} |
|
|
|
return patterns.some(function (pattern) { |
|
if (pattern.slice(-2) === '.*') { |
|
var prefix = pattern.slice(0, -2); |
|
return routeName === prefix || routeName.indexOf(prefix + '.') === 0; |
|
} |
|
|
|
return routeName === pattern; |
|
}); |
|
} |
|
|
|
function parsePatterns(el) { |
|
var raw = el.getAttribute('data-nav-patterns'); |
|
if (!raw) { |
|
return []; |
|
} |
|
|
|
try { |
|
return JSON.parse(raw); |
|
} catch (e) { |
|
return []; |
|
} |
|
} |
|
|
|
function updateNavActive(routeName) { |
|
shell.querySelectorAll('[data-nav-patterns]').forEach(function (el) { |
|
var active = routeMatches(parsePatterns(el), routeName); |
|
el.classList.toggle('is-active', active); |
|
|
|
if (el.classList.contains('app-shell__link') || el.classList.contains('app-shell__bottom-item') || el.classList.contains('app-shell__sheet-link')) { |
|
if (active) { |
|
el.setAttribute('aria-current', 'page'); |
|
} else { |
|
el.removeAttribute('aria-current'); |
|
} |
|
} |
|
}); |
|
|
|
shell.querySelectorAll('[data-nav-group]').forEach(function (groupEl) { |
|
var childLinks = groupEl.querySelectorAll('[data-nav-patterns]'); |
|
var groupActive = false; |
|
|
|
childLinks.forEach(function (link) { |
|
if (routeMatches(parsePatterns(link), routeName)) { |
|
groupActive = true; |
|
} |
|
}); |
|
|
|
if (groupActive) { |
|
groupEl.setAttribute('data-open', ''); |
|
var btn = groupEl.querySelector('[data-nav-group-toggle]'); |
|
if (btn) { |
|
btn.setAttribute('aria-expanded', 'true'); |
|
} |
|
} |
|
}); |
|
} |
|
|
|
function readPageMeta(frame) { |
|
var marker = frame ? frame.querySelector('[data-page-route]') : null; |
|
if (!marker) { |
|
return { route: '', title: document.title }; |
|
} |
|
|
|
return { |
|
route: marker.getAttribute('data-page-route') || '', |
|
title: marker.getAttribute('data-page-title') || document.title, |
|
}; |
|
} |
|
|
|
function showProgress() { |
|
var bar = document.getElementById('app-content-progress'); |
|
if (bar) { |
|
bar.hidden = false; |
|
bar.classList.add('is-active'); |
|
} |
|
|
|
var frame = document.getElementById(frameId); |
|
if (frame) { |
|
frame.classList.add('is-loading'); |
|
} |
|
} |
|
|
|
function hideProgress() { |
|
var bar = document.getElementById('app-content-progress'); |
|
if (bar) { |
|
bar.classList.remove('is-active'); |
|
bar.hidden = true; |
|
} |
|
|
|
var frame = document.getElementById(frameId); |
|
if (frame) { |
|
frame.classList.remove('is-loading'); |
|
} |
|
} |
|
|
|
function onFrameLoaded(frame) { |
|
if (!frame || frame.id !== frameId) { |
|
return; |
|
} |
|
|
|
hideProgress(); |
|
|
|
var meta = readPageMeta(frame); |
|
if (meta.title) { |
|
document.title = meta.title; |
|
} |
|
|
|
if (meta.route) { |
|
updateNavActive(meta.route); |
|
} |
|
|
|
if (isDesktop()) { |
|
frame.scrollTop = 0; |
|
} else { |
|
window.scrollTo({ top: 0, behavior: 'instant' in window ? 'instant' : 'auto' }); |
|
} |
|
|
|
if (window.UiFeedback && window.UiFeedback.onFrameLoad) { |
|
window.UiFeedback.onFrameLoad(frame); |
|
} |
|
|
|
document.dispatchEvent(new CustomEvent('app:frame-loaded', { detail: { frame: frame, meta: meta } })); |
|
|
|
if (shell.classList.contains('is-nav-open')) { |
|
shell.classList.remove('is-nav-open'); |
|
var sheet = shell.querySelector('[data-nav-sheet]'); |
|
var backdrop = shell.querySelector('[data-nav-backdrop]'); |
|
if (sheet) { |
|
sheet.hidden = true; |
|
} |
|
if (backdrop) { |
|
backdrop.hidden = true; |
|
} |
|
document.body.classList.remove('app-nav-open'); |
|
} |
|
} |
|
|
|
document.addEventListener('turbo:frame-request-start', function (event) { |
|
if (event.target.id === frameId) { |
|
showProgress(); |
|
} |
|
}); |
|
|
|
document.addEventListener('turbo:frame-request-finish', function (event) { |
|
if (event.target.id === frameId) { |
|
hideProgress(); |
|
} |
|
}); |
|
|
|
document.addEventListener('turbo:frame-load', function (event) { |
|
onFrameLoaded(event.target); |
|
}); |
|
|
|
document.addEventListener('turbo:frame-missing', function (event) { |
|
if (event.target.id === frameId) { |
|
event.detail.response.redirected = false; |
|
event.preventDefault(); |
|
window.location.href = event.detail.url; |
|
} |
|
}); |
|
|
|
var initialFrame = document.getElementById(frameId); |
|
if (initialFrame) { |
|
var initialMeta = readPageMeta(initialFrame); |
|
if (initialMeta.route) { |
|
updateNavActive(initialMeta.route); |
|
} |
|
} |
|
})();
|
|
|