Scrapboxのポップアップメニューをキーボードで操作する
https://gyazo.com/280c2a630742f8d7a345dfccd877b128
とりあえず無理やり実装してみて、できることはわかった(2020/11/11)
ポップアップメニューを表示しているとき
space、shift + enterでフォーカス移動
ctrl + enterで実行
mousetrapのおかげでブラケティングと同じキーバインドで移動できるようになった(2020/11/17) ポップアップメニューを表示しているとき
tab、shift + tabでフォーカス移動
enterで実行
一行で文字を選択しているとき、tabを使う事はないので潰しても問題ない
tabを使うなら選択していないときなので
複数行で文字を選択しているとき、インデントとして使うこともあるのでちょっと困る
今はポップアップメニューの操作で上書きされている
ctrl + ←→で代替できるのでひとまずOK
複数行選択しているときは無効にするようにした(2020/11/18)
コードブロックの場合は選択されていてもポップアップメニューが出ないのでそれを考慮する(2020/11/20)
Porter上での挙動と競合することに気づいた(2020/12/10) 文字選択後、選択範囲を変更しようとしたら選択範囲変わらず、高速でポップアップメニューの候補が変わる
https://gyazo.com/aff8c4a3427b385f3ea97a198a2f18d3
↑撮った後もう一度繰り返してみたら再現しなかった…
ポップアップメニューが表示されているときのみ、tabキーでメニューを動かすようにとか?
範囲選択をするとselectionsクラスが生成される
code:html
<div class="selections">
<div class="popup-menu" style="left: 0px; top: 550px;">
<div class="button-container" style="left: 65.5px; transform: translateX(-14.7826%);">
<div class="button link-button">Link</div> <div class="button strong-button">
<strong>Strong</strong>
</div>
<div class="button italic-button">
<i>Italic</i>
</div>
...
selectionクラスの中のpopup-menuクラスのbutton-containerクラスの中にbuttonクラスが並んでいる
これを判定したい
入力モードのとき
selectionsクラスが存在する?
存在するときにtabキーを押すと0番目のbuttonクラスにフォーカスを当てる
enterキーでフォーカスのあるbuttonクラスをクリック?
クリックできるの?
tabまたはshift + tabでフォーカスを移動したい
ポップアップメニューを出してるときもインデントにtabを使うのでどうすればいいのか…
enterで実行したい
ポップアップメニューが出ているときのenterキーイベントを無効にする方法がよくわからない
テキストエリアに入力内容を出力しないようにするにはkeydownイベントでreturn false;を返す
適当なキーqとかやspaceはそれでよい
tabやenterは反映されてしまう
なぜ
ユーザーエージェントに、イベントが明示的に処理されない場合にその既定のアクションを通常どおりに行うべきではないことを伝えます。このイベントは通常、イベントリスナーの1つが stopPropagation() または stopImmediatePropagation() を呼び出し、いずれかが一度に伝播を終了しない限り、伝播し続けます。
??
code:js
(function() {
document.onkeydown = function (e) {
console.log(e);
e.preventDefault();
if (e.key === 'q') {
console.log('press q');
}
if (e.key === ' ') {
console.log('press space');
}
if (e.key === 'Tab') {
console.log('press tab');
}
if (e.key === 'Enter') {
console.log('press enter');
}
}
})();
これでもやっぱりtabやenterは反映されてしまう
文字を出力するキーは出力されないようになっている
そもそもの前提が違った
他のサイトのtextarea領域で試してみたらtabもenterも無効化されていた
Scrapboxがtabとenterを独自に送信しているっぽい?
わからない
見えない所でドロップダウンリストを生成し、そっちにフォーカスを移してtabとenterで移動しようとしたけど一回挫折した
どこが効いてるのかわからない
これでとりあえず動く版
何行選択しているか調べるには
一行or複数行or何も選択していない
選択している行数によってselectionクラスが増える
code:js
document.getElementsByClassName('selection').length;
選択していない:0
一行選択している:1
複数行選択しているか:3?
いやダメだ
複数行(line * n行)を選択しているかはわかる
めちゃくちゃ長い一行なのか判断できない
これも結果が3になってしまう
一行選択時のみあるボタン(linkとかstrongとか)と複数行選択時のみあるボタン(New Pageとか)で判別するしかない?
New Pageがあるか?
code:js
document.querySelector('.selections .popup-menu .button-container').children0.className // "button new-page-button"
code:js
document.querySelector('.selections .popup-menu .button-container').children0.classList.contains('new-page-button') // true
これでしばらく様子見
ブラケティングの補完とかち合ってる…
code:html
<div class="line section-1 cursor-line section-title" id="L5fb7662cf458200000da8012" style="min-height: 28px;">
<div class="popup-menu" style="left: 0px; top: 5px;">
<div class="button-container" style="left: 20.5px; transform: translateX(-10.2676%);">
<div class="button">MSTest</div>
<div class="button">testビュー</div>
</div>
<div class="triangle" style="left: 20.5px;"></div>
</div>
</span>
</span><span><span class="c-8">a</span><span class="c-9">s</span><span class="c-10">d</span><span class="c-11">f</span><span class="c-12">j</span><span class="c-13">k</span></span>
</span>
</span>
</div>
#editorの直下がポップアップ
.textの下がブラケティングの補完
code:js
// ポップアップメニューの方のpopup-menu
document.querySelector('#editor .selections .popup-menu');
// ブラケティング補完の方のpopup-menu
document.querySelector('#editor .lines .line .text .popup-menu');
ログ
selectionがどこに生えるのか見に来た(2022/04/07)