for Firefox #11

赤福プラスに関して、大体のところは Firefox でも動くようになった。ただ、やはりまだキーバインドについて詰め切れていないところがある。

たとえばスペースキーに対して、通常の状態では

  • ページ前提のスクロール領域の末尾にすでにいるなら、続きを読む
  • そうでなければ、何もしない(つまり、ブラウザのデフォルトアクションに委ねる)

というハンドラを割り当てている。

一方、lightbox を実行している場合は

  • 表示している画像をスクロールさせる。ブラウザのデフォルトアクションは常に preventDefault() する

とさせている。

何が違うのか。前者は、もともとブラウザが持っているアクションを置き換えて、ちょっとした tweak を行っている。従ってその置き換えがエクステンションによって無効にされたとしても、必ずしも致命的な不具合にはならない。すなわちエクステンションによるキーバインディングよりも優先度が低い。

一方で後者は、ブラウザの機能とは全く別のものだ。この処理をエクステンションによって無効にされると、lightbox により画像を表示している裏で単にページがスクロールするだけになってしまう。全く機能が破綻してしまうということだ。従ってこのケースはエクステンションによるキーバインディングよりも優先度が高くなければならないのである。

エクステンションによるキーバインディングが行われても構わないか・あるいは困るかという表明を、なんとかエクステンション側に対して伝えられないだろうか。それを両者で共有し連携すれば辻褄が合う。

表明については、documentElement の data-なんとか属性に優先度の高いキーバインディングを DOMTokenList 形式で列挙すればよいのではないか。で、.keysnail.js の登録したハンドラ側では、登録したキーバインディングについてドキュメント側でその表明が行われていない場合にのみ自前の処理を行えばよい、はずだ。

 * * *

ということでやってみた。[cci][/cci] とした文書を用意する。.keysnail.js の preserve 領域に

function tdoc (ev) {
return ev.originalTarget.ownerDocument;
}

function twin (ev) {
return ev.originalTarget.ownerDocument.defaultView;
}

function dispatch (stroke, ev, handler) {
var doc = tdoc(ev);
if (!doc) return;

var m = doc.documentElement.getAttribute('data-prior-keys');
if (m && (' ' + m + ' ').indexOf(stroke) >= 0) {
var ev2 = key.stringToKeyEvent(stroke, true, 'keypress', true);
if (!doc.dispatchEvent(ev2)) {
return;
}
}

handler(doc, twin(ev), ev);
}

とし、実際のスペースキーに対するハンドラは

key.setViewKey('SPC', function (ev, arg) {
dispatch('SPC', ev, function (d, w) {
if (w.scrollY >= d.documentElement.scrollHeight - w.innerHeight) {
let customEvent = d.createEvent('CustomEvent');
customEvent.initCustomEvent('RequestMoreContent', true, true, {});

if (d.dispatchEvent(customEvent)) {
// do a special job
}
}
else {
w.scrollBy(0, Math.floor(w.innerHeight / 2));
}
});
}, 'ビューの半分の高さだけスクロールダウン', false);

とする。これにより、html 要素の data-prior-keys 属性に表明されているキーストロークは、いったんページのスクリプトに処理を丸投げする。ただし丸投げしたとしてもページスクリプト側で preventDefault() されていない場合は、keysnail 側のハンドラも実行する。一方、data-prior-keys 属性に表明されていないキーストロークは、即 keysnail で処理する。

丸投げの部分は、本来真面目にやろうとすると keydown/keyup もエミュレートしないといけなかったり、さらにキーリピート絡みも考えなければならなかったり、もっと言えば本当は key プロパティも正しくセットされるように initKeyEvent() ではなく KeyboardEvent() の方を使わないといけなかったりとかなり大規模になるのだが、まあ、とりあえず。

でも基本的にこのやり方、つまり文書側が使用する特定のキーストロークを外部に対して表明するという仕組みはかなり、いいと思う。こんな場末のブログとエクステンションだけが使うにはもったいない感じがする。どこか有名所の javascript のフレームワークとかがパクってくれないだろうか。

Leave a Reply

Your email address will not be published. Required fields are marked *