wheel操作で見出しにジャンプするUserScript
お試し
code:js
import('/api/code/programming-notes/wheel操作で見出しにジャンプするUserScript/script.js');
実装したいこと
開閉ボタンをつける
position: fixedで、brand iconのすぐ下に置きたい
2021-07-16
2021-07-12
12:33:57 ちょっとだけrefactoring
2021-07-07
17:05:12 Page Menuから開閉できるようにした
UIが自然じゃない
ボタンとリストが反対側にある
遠すぎ
画面が小さいときリストが表示されなくなる
16:44:07 これは仕方のないことなのだが、切り替えるたびにweb browser履歴に残ってしまう
たくさんwheelをコロコロすると大量の履歴が発生する
16:43:24 wheelで切り替えられるようにした https://gyazo.com/a82bc5a32bfd0dbe10f7cd84a18d3c45
16:17:44 とりあえずできた
選択すると太字になるようにした
https://gyazo.com/92b91eca595f7332e6dacad394a72d72
欄が小さすぎるのが欠点
.expandable-menuみたく開閉できるようにするか?
dependencies
code:script.js
import {html, render} from '../htm@3.0.4%2Fpreact/script.js';
import {useState, useEffect, useCallback} from '../preact@10.5.13/hooks.js';
import {useToggle} from '../use-toggle@0.1.0/script.js';
import {useLinesChange} from '../use-lines-change@0.1.0/script.js';
const App = () => {
// ページが編集されるたびにリストを更新する
useLinesChange(update, {initialize: true});
// wheel操作で見出しを切り替える
const handleWheel = useCallback(e => {
const index = sections.findIndex(({id}) => id === selectedId);
const {deltaY} = e;
if (index <= 0 && deltaY < 0) return;
if (index === sections.length - 1 && deltaY > 0) return;
e.preventDefault();
e.stopPropagation();
if (deltaY > 0) {
return;
}
if (deltaY < 0) {
return;
}
// Page Menuで開閉する
useEffect(() => scrapbox.PageMenu.addMenu({
title: 'wheel見出し',
onClick: () => toggleOpen(),
}), []);
return html`
<style>
:host {
position: sticky;
top: 45px;
z-index: 1001;
}
ul {
margin-right: 10px;
border-radius: 3px;
min-width: 160px;
max-width: 50vw;
overflow-x: hidden;
overflow-y: auto;
padding: 5px 0;
margin: 2px 0 0;
list-style: none;
font-size: 14px;
border: 1px solid var(--dropdown-border-color, rgba(0,0,0,0.15));
border-radius: 4px;
box-shadow: 0 6px 12px var(--dropdown-shadow-color, rgba(0,0,0,0.175));
background-clip: padding-box;
white-space: nowrap;
text-align: left;
}
a {
display: flex;
clear: both;
align-items: center;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
text-decoration: none;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
a.selected {
font-weight: bold;
outline: 0;
}
a:hover {
background-color: var(--card-hover-bg, #f5f5f5); }
</style>
${open && html`<ul onWheel="${handleWheel}">
${sections.map(({id, text, jump}) => id === selectedId ?
html<li><a class="selected" href="#${id}" onClick="${jump}">${text}</a></li> :
html<li><a href="#${id}" onClick="${jump}">${text}</a></li>
)}
</ul>`}
`
}
見出しを作るcustom hook
code:script.js
function useSections() {
const jump = useCallback(id => {
setSelected(id);
location.hash = id;
}, []);
const update = useCallback(() =>
setSections(
scrapbox.Page.lines.flatMap(
({section: {start}, id, text}) => start ? [{
id,
text,
jump: () => jump(id),
}] : []
)
}
code:script.js
const app = document.createElement('div');
app.attachShadow({mode: 'open'});
app.dataset.userscriptName = 'section-jumper';
document.querySelector('.col-page-side')?.append?.(app);
render(html<${App} />, app.shadowRoot);