知恵袋 (前に戻る)
101新仕様20250828
1. HTML(index.html) <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>検索テスト</title> <!-- スマホ画面のサイズ調整CSS --> <link rel="stylesheet" href="responsive.css"> <!-- 上へ・下へボタンCSS --> <link rel="stylesheet" href="scrollButtons.css"> <!-- 検索ボックスCSS --> <link rel="stylesheet" href="searchBox.css"> </head> <body id="top"> <!-- 🔍 検索ボックス --> <div id="searchBox"> <input type="text" id="searchInput" placeholder="検索語を入力"> <button onclick="searchText()">検索</button> <button onclick="prevResult()">← 前</button> <button onclick="nextResult()">次 →</button> </div><!-- /#searchBox 終わり --> <!-- 本文(検索範囲) --> <div id="content"> <p>これはテスト文章です。検索やスクロールのテストをします。</p> <p>もう一つ段落を入れて、検索結果のハイライトを確認します。</p> <p>もう一つ段落を入れて、検索結果のハイライトを確認します。</p> <p>もう一つ段落を入れて、検索結果のハイライトを確認します。</p> <p>もう一つ段落を入れて、検索結果のハイライトを確認します。</p> </div><!-- /#content 終わり --> <!-- 「下へ行く」ボタン --> <a href="#bottom" id="goToBottomCSS" title="下へ行く">↓</a> <!-- 「上へ戻る」ボタン --> <a href="#top" id="backToTopCSS" title="上に戻る">↑</a> <!-- ジャンプ先を空のアンカーで定義 --> <a id="bottom"></a> <!-- 検索スクリプト --> <script src="search.js" charset="UTF-8"></script> </body> </html> 2. CSSファイル responsive.css(スマホサイズ調整) @charset "UTF-8"; /* --- 文字折り返し --- */ * { word-break: break-all; } /* --- テーブルと画像を画面幅に収める --- */ table { max-width: 800px; width: 100% !important; margin: 0 auto; } img { max-width: 100% !important; height: auto !important; } /* --- スマホ幅調整(767px以下) --- */ @media screen and (max-width: 767px) { table { max-width: 650px; } } 2. CSSファイル scrollButtons.css(上へ・下へボタン) @charset "UTF-8"; /* --- 上へ戻るボタン --- */ #backToTopCSS { position: fixed; bottom: 20px; right: 20px; z-index: 99999; /* ← ここを100 → 99999に変更 */ display: block; background-color: #333; /* --- 丸いボタン・濃い灰色 --- */ color: #fff; /* --- 矢印ボタン・白色 --- */ padding: 10px 15px; border-radius: 50%; font-size: 20px; text-decoration: none; box-shadow: 0 2px 5px rgba(0,0,0,0.3); } #backToTopCSS:hover { background-color: #555; /* --- 丸いボタン・マウスを乗せた時・薄い灰色 --- */ } /* --- 下へ行くボタン --- */ #goToBottomCSS { position: fixed; bottom: 20px; left: 20px; z-index: 99999; /* ← ここを100 → 99999に変更 */ display: block; background-color: #333; color: #fff; padding: 10px 15px; border-radius: 50%; font-size: 20px; text-decoration: none; box-shadow: 0 2px 5px rgba(0,0,0,0.3); } #goToBottomCSS:hover { background-color: #555; } 2. CSSファイル searchBox.css(検索ボックス) @charset "UTF-8"; /* --- 固定表示検索ボックス --- */ #searchBox { position: fixed; top: 0; left: 0; width: 100%; background-color: #fff; border-bottom: 1px solid #ccc; padding: 8px; box-sizing: border-box; z-index: 99999; /* ← ここを9999 → 99999に変更 */ /* 横並びデザイン */ display: flex; flex-wrap: nowrap; align-items: center; gap: 5px; justify-content: center; margin: 10px 0; } /* --- 入力欄 --- */ #searchInput { width: 50%; min-width: 120px; padding: 8px 12px; font-size: 16px; border: 1px solid #666; border-radius: 6px; } /* --- ボタン --- */ #searchBox button { padding: 6px 10px; font-size: 14px; cursor: pointer; white-space: nowrap; } /* --- 本文との重なり防止 --- */ #content { margin-top: 70px; } /* --- スマホ向け(480px以下) --- */ @media (max-width: 480px) { #searchInput { width: 55%; font-size: 14px; } #searchBox button { font-size: 12px; padding: 6px 10px; } #content { margin-top: 90px; } } 3. JavaScript(search.js) // ============================= // 🔍 検索機能+ハイライト // ============================= let results = []; let currentIndex = 0; // --- 正規表現のエスケープ --- function escapeRegExp(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } // --- 既存ハイライト解除 --- function removeHighlights(root) { root.querySelectorAll('mark').forEach(mark => { const parent = mark.parentNode; parent.replaceChild(document.createTextNode(mark.textContent), mark); parent.normalize(); }); } // --- テキストノードをハイライト --- function highlightTextNodes(root, regex) { const SKIP = /^(script|style|noscript|mark)$/i; const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, { acceptNode(node) { if (!node.nodeValue || !node.nodeValue.trim()) return NodeFilter.FILTER_REJECT; if (node.parentNode && SKIP.test(node.parentNode.tagName)) return NodeFilter.FILTER_REJECT; return NodeFilter.FILTER_ACCEPT; } }); const nodes = []; let n; while ((n = walker.nextNode())) nodes.push(n); nodes.forEach(node => { const text = node.nodeValue; regex.lastIndex = 0; if (!regex.test(text)) return; const frag = document.createDocumentFragment(); let last = 0; let m; regex.lastIndex = 0; while ((m = regex.exec(text)) !== null) { if (m.index > last) frag.appendChild(document.createTextNode(text.slice(last, m.index))); const mark = document.createElement('mark'); mark.textContent = m[0]; frag.appendChild(mark); last = m.index + m[0].length; if (m[0].length === 0) { regex.lastIndex++; } } if (last < text.length) frag.appendChild(document.createTextNode(text.slice(last))); node.parentNode.replaceChild(frag, node); }); } // --- 検索実行 --- function searchText() { const inputEl = document.getElementById('searchInput'); const term = (inputEl ? inputEl.value : '').trim(); const content = document.getElementById('content'); if (!content) return; removeHighlights(content); results = []; currentIndex = 0; if (!term) { try { sessionStorage.removeItem('lastSearch'); } catch (e) {} return; } const regex = new RegExp(escapeRegExp(term), 'gi'); highlightTextNodes(content, regex); results = Array.from(content.querySelectorAll('mark')); if (results.length > 0) { results[0].scrollIntoView({ behavior: 'smooth', block: 'center' }); results[0].style.backgroundColor = 'yellow'; } try { sessionStorage.setItem('lastSearch', term); } catch (e) {} } // --- 次の検索結果 --- function nextResult() { if (results.length === 0) return; results[currentIndex].style.backgroundColor = 'orange'; currentIndex = (currentIndex + 1) % results.length; results[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' }); results[currentIndex].style.backgroundColor = 'yellow'; } // --- 前の検索結果 --- function prevResult() { if (results.length === 0) return; results[currentIndex].style.backgroundColor = 'orange'; currentIndex = (currentIndex - 1 + results.length) % results.length; results[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' }); results[currentIndex].style.backgroundColor = 'yellow'; } // --- ページ読み込み時 --- document.addEventListener('DOMContentLoaded', () => { const inputEl = document.getElementById('searchInput'); try { const last = sessionStorage.getItem('lastSearch') || ''; if (inputEl) inputEl.value = last; if (last) searchText(); } catch (e) {} if (inputEl) { inputEl.addEventListener('keydown', e => { if (e.key === 'Enter') searchText(); }); } // 検索ボックス高さに応じて本文margin調整 const searchBox = document.getElementById("searchBox"); const content = document.getElementById("content"); if (searchBox && content) { const h = searchBox.offsetHeight; content.style.marginTop = h + "px"; } }); <script> タグは基本的に <body> の一番下( </body> の直前)に置くのが一般的です。(理由:JS読み込みが完了するまでHTMLの表示が止まるのを防ぐため) これ以下は、旧仕様 ホームページ サイト内(ページ内)検索HTML作成手順 ①search-demo.htmlをルートに設置(テスト用なので不要・削除してもOK) 内容は yoko8zに有る。 このページの下段にも記述あり ②目的ページの</HEAD>の直前に <style> <!-- /* 固定表示検索ボックス */ #searchBox{ position: fixed; /* 画面上段に固定 */ top: 0; left: 0; width: 100%; background-color: #fff; border-bottom: 1px solid #ccc; padding: 8px; box-sizing: border-box; z-index: 9999; } /* 入力欄 */ #searchInput{ padding: 8px 12px; font-size: 16px; width: 65%; /* 入力欄の幅調整 */ border: 1px solid #666; border-radius: 6px; } /* ボタン */ #searchBox button{ padding: 8px 12px; font-size: 14px; margin-left: 4px; cursor: pointer; } /* 本文との重なり防止 */ #content{ margin-top: 70px; /* 検索ボックスの高さに合わせる */ } /* スマホ向けレスポンシブ調整 */ @media (max-width: 480px) { #searchInput{ width: 55%; font-size: 14px; } #searchBox button{ font-size: 12px; padding: 6px 10px; } #content{ margin-top: 90px; } } --> </style> <style> <!-- /* 🔍 検索ボックス用スタイル */ #searchBox{ display: flex; /* 横並びにする */ flex-wrap: nowrap; /* 折り返さない */ align-items: center; /* ボタンを縦位置中央に */ gap: 5px; /* ボタンとの隙間 */ justify-content: center; /* 中央寄せ */ margin: 10px 0; } #searchBox input[type="text"]{ width: 50%; /* 入力欄を半分くらいに */ min-width: 120px; /* スマホでも潰れすぎないように下限幅 */ padding: 5px; font-size: 14px; } #searchBox button{ padding: 5px 10px; font-size: 14px; white-space: nowrap; /* ボタン内の文字を折り返さない */ } --> </style> を記述 内容はhttp://hamada777.g1.xrea.com/index2.htmlに有る ③<body>の下(<table>の上)に下記を記述 <!-- 🔍 固定表示検索ボックス --> <div id="searchBox"> <input type="text" id="searchInput" placeholder="検索ワードを入力"> <button onclick="searchText()">検索</button> <button onclick="nextResult()">次へ</button> <button onclick="prevResult()">前へ</button> </div> <!-- ★検索対象を div#content で囲む --> <div id="content"> このあと検索対象の最後を </div> <!-- ★ここまで --> で閉じる。注意!は 囲んだdivと/divの間に別のdivと/divが入って 検索できなくなることがある。 間に別のdivと/divを入れないように! ④</body>の直前に下記scriptを2つ記述 (ホームページビルダーのプレビューでスクリプトエラーになっても問題ない) <script> // --- 安全ハイライト20250824改良版(属性は一切さわらない / リンク壊れません) --- let results = []; let currentIndex = 0; function escapeRegExp(s){ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function removeHighlights(root){ root.querySelectorAll('mark').forEach(mark=>{ const parent = mark.parentNode; parent.replaceChild(document.createTextNode(mark.textContent), mark); parent.normalize(); }); } function highlightTextNodes(root, regex){ const SKIP = /^(script|style|noscript|mark)$/i; // 置換でツリーが変わると困るので、先に対象テキストノードを配列に退避 const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, { acceptNode(node){ if (!node.nodeValue || !node.nodeValue.trim()) return NodeFilter.FILTER_REJECT; if (node.parentNode && SKIP.test(node.parentNode.tagName)) return NodeFilter.FILTER_REJECT; return NodeFilter.FILTER_ACCEPT; } }); const nodes = []; let n; while ((n = walker.nextNode())) nodes.push(n); nodes.forEach(node=>{ const text = node.nodeValue; regex.lastIndex = 0; if (!regex.test(text)) return; const frag = document.createDocumentFragment(); let last = 0; regex.lastIndex = 0; let m; while ((m = regex.exec(text)) !== null){ if (m.index > last) frag.appendChild(document.createTextNode(text.slice(last, m.index))); const mark = document.createElement('mark'); mark.textContent = m[0]; frag.appendChild(mark); last = m.index + m[0].length; if (m[0].length === 0) { regex.lastIndex++; } // 念のため無限ループ防止 } if (last < text.length) frag.appendChild(document.createTextNode(text.slice(last))); node.parentNode.replaceChild(frag, node); }); } function searchText(){ const inputEl = document.getElementById('searchInput'); const term = (inputEl ? inputEl.value : '').trim(); const content = document.getElementById('content'); if (!content) return; // 既存ハイライト解除 removeHighlights(content); results = []; currentIndex = 0; if (!term){ try{ sessionStorage.removeItem('lastSearch'); }catch(e){} return; } // 正規表現は「リテラル検索」になるようエスケープ(部分一致・大小無視) const regex = new RegExp(escapeRegExp(term), 'gi'); // テキストノードだけを置換(属性やタグ文字列は触らない) highlightTextNodes(content, regex); // 見つかった <mark> を収集して先頭へスクロール results = Array.from(content.querySelectorAll('mark')); if (results.length > 0){ results[0].scrollIntoView({ behavior: 'smooth', block: 'center' }); results[0].style.backgroundColor = 'yellow'; } // 次ページでも同じ語で自動検索するため保存 try{ sessionStorage.setItem('lastSearch', term); }catch(e){} } function nextResult(){ if (results.length === 0) return; results[currentIndex].style.backgroundColor = 'orange'; currentIndex = (currentIndex + 1) % results.length; results[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' }); results[currentIndex].style.backgroundColor = 'yellow'; } function prevResult(){ if (results.length === 0) return; results[currentIndex].style.backgroundColor = 'orange'; currentIndex = (currentIndex - 1 + results.length) % results.length; results[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' }); results[currentIndex].style.backgroundColor = 'yellow'; } // ページ読み込み時:前回語があれば自動再検索(要:各ページにこのスクリプト設置) document.addEventListener('DOMContentLoaded', ()=>{ const inputEl = document.getElementById('searchInput'); try{ const last = sessionStorage.getItem('lastSearch') || ''; if (inputEl) inputEl.value = last; if (last) searchText(); }catch(e){} // Enter でも検索できるように(ボタンも従来どおり使えます) if (inputEl){ inputEl.addEventListener('keydown', e=>{ if (e.key === 'Enter') searchText(); }); } }); </script> <script> // 検索ボックスの高さを自動計算させる window.addEventListener("load", function() { var searchBox = document.getElementById("searchBox"); var content = document.getElementById("content"); if (searchBox && content) { var h = searchBox.offsetHeight; content.style.marginTop = h + "px"; } }); </script> このscriptは最初の版でバグあり 検索窓でヒットした項目をクリックすると <mark>文字がURLに組み込まれて「ページが無い」のエラーになる <script> let results = []; // 検索ヒットした要素を保存バグ修正前の版 let currentIndex = 0; // 現在の位置 function searchText() { const input = document.getElementById("searchInput").value.trim(); const content = document.getElementById("content"); // 前回のハイライトを解除 content.querySelectorAll("mark").forEach(mark => { const parent = mark.parentNode; parent.replaceChild(document.createTextNode(mark.textContent), mark); parent.normalize(); }); results = []; currentIndex = 0; if (input === "") return; // 正規表現で検索語をハイライト const regex = new RegExp(input, "gi"); content.innerHTML = content.innerHTML.replace(regex, match => `<mark>${match}</mark>`); results = Array.from(content.querySelectorAll("mark")); if (results.length > 0) { results[0].scrollIntoView({ behavior: "smooth", block: "center" }); results[0].style.backgroundColor = "yellow"; } } function nextResult() { if (results.length === 0) return; results[currentIndex].style.backgroundColor = "orange"; currentIndex = (currentIndex + 1) % results.length; results[currentIndex].scrollIntoView({ behavior: "smooth", block: "center" }); results[currentIndex].style.backgroundColor = "yellow"; } function prevResult() { if (results.length === 0) return; results[currentIndex].style.backgroundColor = "orange"; currentIndex = (currentIndex - 1 + results.length) % results.length; results[currentIndex].scrollIntoView({ behavior: "smooth", block: "center" }); results[currentIndex].style.backgroundColor = "yellow"; } </script> ①search-demo.html(参考保存のみ) <!doctype html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <title>ページ内テキスト検索デモ(HTML+JSのみ)</title> <style> :root { --accent: #0d6efd; } body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Hiragino Kaku Gothic ProN", Meiryo, sans-serif; line-height: 1.7; margin: 0; } header { position: sticky; top: 0; background: #fff; border-bottom: 1px solid #e5e7eb; z-index: 10; } .container { max-width: 960px; margin: 0 auto; padding: 16px; } .toolbar { display: grid; grid-template-columns: 1fr auto auto auto auto; gap: 8px; align-items: center; } .toolbar input[type="text"] { padding: 10px 12px; border: 1px solid #cbd5e1; border-radius: 10px; } .toolbar button, .toolbar label { padding: 10px 12px; border-radius: 10px; border: 1px solid #cbd5e1; background: #f8fafc; cursor: pointer; } .toolbar button.primary { background: var(--accent); border-color: var(--accent); color: #fff; } .toolbar .count { font-variant-numeric: tabular-nums; color: #334155; padding: 0 8px; } mark.find-hit { background: #fff59d; padding: 0 2px; border-radius: 3px; } mark.find-current { background: #ffd54f; outline: 2px solid #ffb300; } .content { padding: 24px 16px 64px; } .hint { color: #64748b; font-size: 14px; } .kbd { padding: 1px 6px; border: 1px solid #cbd5e1; border-radius: 6px; background: #fff; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } </style> </head> <body> <header> <div class="container"> <div class="toolbar" role="search"> <input id="q" type="text" placeholder="このページ内を検索… (例: フェーズドアレイ)" autocomplete="off" /> <button id="btnFind" class="primary" title="検索 (Enter)">検索</button> <button id="btnPrev" title="前の一致 (Shift+Enter)">前へ</button> <button id="btnNext" title="次の一致 (Enter)">次へ</button> <button id="btnClear" title="結果を解除 (Esc)">解除</button> <div class="count" id="counter" aria-live="polite"></div> </div> <div class="hint">Enter=検索/次へ、Shift+Enter=前へ、Esc=解除。 大文字小文字 <label><input type="checkbox" id="optCase" /> 区別する</label>・<label><input type="checkbox" id="optWord" /> 単語全体一致</label></div> </div> </header> <main class="container content"> <!-- ★★ 検索対象はこの#content内だけです。自分のページでは本文をこのdivに入れてください。 --> <article id="content"> <h1>ページ内テキスト検索デモ</h1> <p>このサンプルは、サーバー側のプログラムなし(FTPアップロードのみ)で<strong>ページ内のテキストを検索</strong>し、 一致箇所へ自動スクロール&ハイライトします。日本語もOKです。</p> <p>主なポイント: <ul> <li>検索語の全一致を順送り/逆送り(次へ/前へ)</li> <li>大文字小文字の区別・単語全体一致の切替</li> <li>Escで解除して元の本文に戻す(元HTMLを一時保存)</li> <li>検索バーはページ上部に固定(<code>position: sticky</code>)</li> </ul> </p> <h2>ダミー本文</h2> <p>たとえば「アンテナ」「フェーズドアレイ」「Excel」などで試してみてください。検索結果は <mark>強調表示</mark>され、現在位置はさらに濃い色で表示されます。</p> <p>段落が長くてもOKです。複数の一致がある場合、Enterで次の一致へ自動スクロールします。</p> <p>英語: phased array antenna / array factor / beam steering / FFT. 日本語: 位相制御 / 素子間隔 / 指向性。 </p> </article> </main> <script> (function(){ const $ = (sel, ctx=document) => ctx.querySelector(sel); const $$ = (sel, ctx=document) => Array.from(ctx.querySelectorAll(sel)); const box = $('#q'); const btnFind = $('#btnFind'); const btnNext = $('#btnNext'); const btnPrev = $('#btnPrev'); const btnClear = $('#btnClear'); const counter = $('#counter'); const optCase = $('#optCase'); const optWord = $('#optWord'); const content = $('#content'); let hits = []; // Array<HTMLElement mark.find-hit> let pos = -1; // 現在の一致位置インデックス let originalHTML = null; // 元のHTML(解除用) function escapeRegExp(s){ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function buildRegex(query){ if(!query) return null; const flags = optCase.checked ? 'g' : 'gi'; const src = optWord.checked ? `\\b${escapeRegExp(query)}\\b` : escapeRegExp(query); try { return new RegExp(src, flags); } catch(e){ return null; } } function clearHighlights(){ if(originalHTML != null){ content.innerHTML = originalHTML; } else { // 念のため:markを外す(初回前はmark存在しない) $$('.find-hit', content).forEach(m => { const t = document.createTextNode(m.textContent); m.replaceWith(t); }); } hits = []; pos = -1; originalHTML = null; updateCounter(); } function updateCounter(){ if(hits.length === 0){ counter.textContent = ''; return; } counter.textContent = `${pos+1} / ${hits.length}`; } function scrollToCurrent(){ if(pos < 0 || pos >= hits.length) return; hits.forEach(h => h.classList.remove('find-current')); const el = hits[pos]; el.classList.add('find-current'); el.scrollIntoView({ behavior: 'smooth', block: 'center' }); } function doFind(direction = 0){ const q = box.value.trim(); if(!q){ clearHighlights(); return; } // 既存の結果が検索語・オプションと一致しているか簡易チェック const sameQuery = content.dataset._lastQuery === q && content.dataset._lastCase === String(optCase.checked) && content.dataset._lastWord === String(optWord.checked); if(!sameQuery){ // 初回または条件変更:ハイライトを作り直す clearHighlights(); originalHTML = content.innerHTML; // 元を保存(解除で復元) const regex = buildRegex(q); if(!regex){ return; } // テキストノードを走査してmark化 const walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT, { acceptNode(node){ // 目に見えるテキストのみ(空白や改行のみは除外) return /\S/.test(node.nodeValue) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; } }); const textNodes = []; while(walker.nextNode()) textNodes.push(walker.currentNode); textNodes.forEach(node => { const parent = node.parentNode; let html = node.nodeValue; if(!regex.test(html)) return; // 該当なし // global RegExp は状態を持つので都度リセット regex.lastIndex = 0; const parts = []; let lastIdx = 0; let m; while((m = regex.exec(html))){ const before = html.slice(lastIdx, m.index); const hit = m[0]; parts.push(document.createTextNode(before)); const mark = document.createElement('mark'); mark.className = 'find-hit'; mark.textContent = hit; parts.push(mark); hits.push(mark); lastIdx = m.index + hit.length; } parts.push(document.createTextNode(html.slice(lastIdx))); const frag = document.createDocumentFragment(); parts.forEach(p => frag.appendChild(p)); parent.replaceChild(frag, node); }); content.dataset._lastQuery = q; content.dataset._lastCase = String(optCase.checked); content.dataset._lastWord = String(optWord.checked); if(hits.length === 0){ updateCounter(); return; } pos = 0; // 最初の一致へ updateCounter(); scrollToCurrent(); return; } // 既存の結果で移動 if(hits.length === 0){ updateCounter(); return; } if(direction === 0){ // Enter=次へ pos = (pos + 1) % hits.length; } else if(direction < 0){ // 前へ pos = (pos - 1 + hits.length) % hits.length; } else { // 明示的に次へ pos = (pos + 1) % hits.length; } updateCounter(); scrollToCurrent(); } // ---- イベント btnFind.addEventListener('click', () => doFind(+1)); btnNext.addEventListener('click', () => doFind(+1)); btnPrev.addEventListener('click', () => doFind(-1)); btnClear.addEventListener('click', clearHighlights); box.addEventListener('keydown', (e) => { if(e.key === 'Enter'){ e.preventDefault(); doFind(e.shiftKey ? -1 : +1); } else if(e.key === 'Escape'){ clearHighlights(); } }); // ページ全体のショートカット(/ でフォーカス) document.addEventListener('keydown', (e) => { if(e.key === '/' && !e.ctrlKey && !e.metaKey && !e.altKey){ e.preventDefault(); box.focus(); box.select(); } }); })(); </script> </body> </html> |
(前に戻る)
chie2.html(tvm)
<EOF>