generated at
mobile版scrapboxのtext-inputにfocusを当て
目的
mobile版scrapboxでUserScriptから文字入力できる状態にしたい
画面を触らず、物理キーボードのみで編集できるようにするために必要

背景
mobile版scrapboxでは、画面を長押しすることでキーボードが表示され、文字入力できるようになる
タッチパネルのみで操作するなら問題ない
しかし、物理キーボードで操作するとなると面倒なことになる
キーボードが隠れるたびに、画面に手を伸ばして長押ししてキーボードをいちいち出さないといけない
そこで、UserScriptからなんとか長押しをemulateできないか試してみることにした

成果

作業log
実験用コード
js
(async () => { const {focusEnd} = await import("https://scrapbox.io/api/code/takker/scrapbox-motion-emulation/script.js"); scrapBindings.push({key:"i", command: async () => {await focusEnd();return false}, type: "browser"}); })();
うまくいったもの
js
export async function mimicHoldDown(element, {button = 0, X, Y, shiftKey = false, ctrlKey = false, altKey = false, holding = 1000, wait = 10} = {}) { const touch = new Touch({ identifier: 0, target: element, clientX: X, clientY: Y, pageX: X + window.scrollX, pageY: Y + window.scrollY, }); const mouseOptions = { button: 0, clientX: X, clientY: Y, changedTouches: [touch], touches: [touch], bubbles: true, cancelable: true, shiftKey: shiftKey, ctrlKey: ctrlKey, altKey: altKey, view: window, }; element.dispatchEvent(new TouchEvent("touchstart", mouseOptions)); element.dispatchEvent(new MouseEvent("mousedown", mouseOptions)); await sleep(holding); element.dispatchEvent(new MouseEvent("mouseup", mouseOptions)); element.dispatchEvent(new TouchEvent("touchend", mouseOptions)); element.dispatchEvent(new MouseEvent("click", mouseOptions)); await sleep(wait); // 少し待つ }
element span.text にした
長押しは1秒で十分
うまくいかなかったもの
MouseEventを使う
js
export async function mimicHoldDown(element, {button = 0, X, Y, shiftKey = false, ctrlKey = false, altKey = false, holding = 2000, wait = 10} = {}) { const mouseOptions = { button: 0, clientX: X, clientY: Y, bubbles: true, cancelable: true, shiftKey: shiftKey, ctrlKey: ctrlKey, altKey: altKey, view: window, }; element.dispatchEvent(new MouseEvent("mousedown", mouseOptions)); await sleep(holding); element.dispatchEvent(new MouseEvent("mouseup", mouseOptions)); element.dispatchEvent(new MouseEvent("click", mouseOptions)); await sleep(wait); // 少し待つ }
これで行末を長押しするようにしてみたところ、行末への移動はできたがキーボードを表示する事はできなかった
TouchEventを同時に出す
TouchEventを使ったらこんなエラーが出た
log
index.js:formatted:117319 Uncaught TypeError: Cannot read property 'pageX' of undefined at getPageX (index.js:formatted:117319) at getInitialValues (index.js:formatted:117288) at MobilePointerEvent.resetSwipeCursor (index.js:formatted:117059) at MobilePointerEvent.onTouchStart (index.js:formatted:117075) at HTMLDivElement.wrapper (index.js:formatted:2361) at HTMLDivElement.dispatch (index.js:formatted:9774) at HTMLDivElement.pe.handle (index.js:formatted:9712) at HTMLDivElement.wrapped (index.js:formatted:32685) at mimicHoldDown (script.js:34) at focusEnd (script.js:24) at command (<anonymous>:3:60) at c (VM743 mousetrap.min.js:5) at d.k._handleKey (VM743 mousetrap.min.js:7) at d.handleKey (VM743 mousetrap.min.js:10) at HTMLDocument.e (VM743 mousetrap.min.js:5) at HTMLDocument.wrapped (index.js:formatted:32685)
どうやらTouchEvent.changedTouchesTouchを入れておかないといけないみたい
入れた
js
export async function mimicHoldDown(element, {button = 0, X, Y, shiftKey = false, ctrlKey = false, altKey = false, holding = 1000, wait = 10} = {}) { const touch = new Touch({ identifier: 0, target: element, clientX: X, clientY: Y, }); const mouseOptions = { button: 0, clientX: X, clientY: Y, changedTouches: [touch], touches: [touch], bubbles: true, cancelable: true, shiftKey: shiftKey, ctrlKey: ctrlKey, altKey: altKey, view: window, }; element.dispatchEvent(new TouchEvent("touchstart", mouseOptions)); element.dispatchEvent(new MouseEvent("mousedown", mouseOptions)); await sleep(holding); element.dispatchEvent(new MouseEvent("mouseup", mouseOptions)); element.dispatchEvent(new TouchEvent("touchend", mouseOptions)); element.dispatchEvent(new MouseEvent("click", mouseOptions)); await sleep(wait); // 少し待つ }
12:42:16 反応なし……
elementを span.text に替えたりしたのに……
何が行けないのだろう?takker
実際に長押ししたときのEventとの違い
関係なさそうなやつ
cancelBubble: true
defaultPrevented: true
composed: true
pageX pageY がある
12:53:47 ↑を入れたらキーボードでてきた!

#2021-08-23 12:21:08