かんたん神業ゲーム攻略

なぜ、宗教関係者が日本に多いのか

2024-06-14から1日間の記事一覧

Fallou4 武器作成MODさらに伝説効果付与 クラフト系MOD for PS4 PS5

レールライフル Fallout4 ※6月15日、今日の天気は晴れ 夜まで蒸し暑かった。例の薄い本をさがしに行った。机の上に置いてあったので無事に入手できた。他もまわって4冊手に入った。居住地にもどったらフェラルが押し寄せてフリーズした。 エラー報告をします…

(() => { 'use strict'; const CONFIG = { articleSelector: '.entry-content', headingSelector: 'h2, h3, h4, h5', minimumHeadingsForToc: 3, enableImageZoom: true, enableProgressBar: true, enableBackToTop: true }; const ready = (fn) => { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', fn, { once: true }); } else { fn(); } }; const safeId = (text, index) => { const normalized = String(text || '') .trim() .toLowerCase() .replace(/[^\p{L}\p{N}_-]+/gu, '-') .replace(/^-+|-+$/g, '') .slice(0, 70); return normalized || `have-reader-heading-${index + 1}`; }; const uniqueId = (base, used) => { let id = base; let n = 2; while (used.has(id) || document.getElementById(id)) { id = `${base}-${n++}`; } used.add(id); return id; }; const buildToc = (article) => { const headings = [...article.querySelectorAll(CONFIG.headingSelector)] .filter((heading) => heading.textContent.trim()); if (headings.length < CONFIG.minimumHeadingsForToc) return; const usedIds = new Set(); const nav = document.createElement('nav'); nav.className = 'have-reader-toc'; nav.setAttribute('aria-label', '記事内の見出し'); const head = document.createElement('div'); head.className = 'have-reader-toc__head'; const title = document.createElement('p'); title.className = 'have-reader-toc__title'; title.textContent = 'この記事の見出し'; const toggle = document.createElement('button'); toggle.type = 'button'; toggle.className = 'have-reader-toc__toggle'; toggle.textContent = '閉じる'; toggle.setAttribute('aria-expanded', 'true'); const list = document.createElement('ol'); list.className = 'have-reader-toc__list'; const links = new Map(); headings.forEach((heading, index) => { if (!heading.id) { heading.id = uniqueId(safeId(heading.textContent, index), usedIds); } const item = document.createElement('li'); item.dataset.level = heading.tagName.slice(1); const link = document.createElement('a'); link.href = `#${encodeURIComponent(heading.id)}`; link.textContent = heading.textContent.trim(); link.addEventListener('click', (event) => { event.preventDefault(); heading.scrollIntoView({ behavior: 'smooth', block: 'start' }); history.replaceState(null, '', `#${encodeURIComponent(heading.id)}`); }); item.appendChild(link); list.appendChild(item); links.set(heading, link); }); toggle.addEventListener('click', () => { const willHide = !list.hidden; list.hidden = willHide; toggle.textContent = willHide ? '開く' : '閉じる'; toggle.setAttribute('aria-expanded', String(!willHide)); }); head.append(title, toggle); nav.append(head, list); article.parentNode.insertBefore(nav, article); if ('IntersectionObserver' in window) { const observer = new IntersectionObserver((entries) => { const visible = entries .filter((entry) => entry.isIntersecting) .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top); if (!visible.length) return; links.forEach((link) => link.classList.remove('is-current')); const current = links.get(visible[0].target); if (current) current.classList.add('is-current'); }, { rootMargin: '-12% 0px -72% 0px', threshold: [0, 1] }); headings.forEach((heading) => observer.observe(heading)); } }; const installProgressBar = (article) => { if (!CONFIG.enableProgressBar) return; const bar = document.createElement('div'); bar.className = 'have-reader-progress'; bar.setAttribute('aria-hidden', 'true'); document.body.appendChild(bar); let ticking = false; const update = () => { ticking = false; const rect = article.getBoundingClientRect(); const articleTop = window.scrollY + rect.top; const start = articleTop - Math.min(window.innerHeight * 0.2, 140); const end = articleTop + article.offsetHeight - window.innerHeight; const span = Math.max(1, end - start); const ratio = Math.min(1, Math.max(0, (window.scrollY - start) / span)); bar.style.width = `${ratio * 100}%`; }; const requestUpdate = () => { if (!ticking) { ticking = true; requestAnimationFrame(update); } }; window.addEventListener('scroll', requestUpdate, { passive: true }); window.addEventListener('resize', requestUpdate, { passive: true }); update(); }; const installBackToTop = () => { if (!CONFIG.enableBackToTop) return; const button = document.createElement('button'); button.type = 'button'; button.className = 'have-reader-top'; button.textContent = '↑'; button.setAttribute('aria-label', 'ページ上部へ戻る'); document.body.appendChild(button); const update = () => { button.classList.toggle('is-visible', window.scrollY > 700); }; button.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); window.addEventListener('scroll', update, { passive: true }); update(); }; const installImageZoom = (article) => { if (!CONFIG.enableImageZoom) return; const images = [...article.querySelectorAll('img')] .filter((img) => !img.closest('a[href]')); if (!images.length) return; const box = document.createElement('div'); box.className = 'have-reader-lightbox'; box.hidden = true; box.setAttribute('role', 'dialog'); box.setAttribute('aria-modal', 'true'); box.setAttribute('aria-label', '画像の拡大表示'); const close = document.createElement('button'); close.type = 'button'; close.className = 'have-reader-lightbox__close'; close.textContent = '×'; close.setAttribute('aria-label', '拡大表示を閉じる'); const large = document.createElement('img'); large.alt = ''; const closeBox = () => { box.hidden = true; large.removeAttribute('src'); document.documentElement.style.overflow = ''; }; const openBox = (img) => { large.src = img.currentSrc || img.src; large.alt = img.alt || ''; box.hidden = false; document.documentElement.style.overflow = 'hidden'; close.focus(); }; images.forEach((img) => { img.tabIndex = 0; img.setAttribute('role', 'button'); img.setAttribute('aria-label', `${img.alt || '記事画像'}を拡大`); img.addEventListener('click', () => openBox(img)); img.addEventListener('keydown', (event) => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); openBox(img); } }); }); close.addEventListener('click', closeBox); large.addEventListener('click', closeBox); box.addEventListener('click', (event) => { if (event.target === box) closeBox(); }); document.addEventListener('keydown', (event) => { if (event.key === 'Escape' && !box.hidden) closeBox(); }); box.append(close, large); document.body.appendChild(box); }; ready(() => { const articles = [...document.querySelectorAll(CONFIG.articleSelector)]; if (!articles.length) return; articles.forEach((article) => buildToc(article)); const primaryArticle = articles[0]; installProgressBar(primaryArticle); installImageZoom(primaryArticle); installBackToTop(); }); })();