空間ナビゲーションで次に移動できる要素を強調するUserJSを作ろうとした→失敗

この前↓から作ってたやつだが、かなり良い出来になった。普通のページで使っても、ほとんどの場合で問題は無さそう。


しかし、もう一歩のところで致命的 (?) な欠陥があることがわかった。

どこで失敗かを書く前にまずソースの解説から入る。

前提として、document.moveFocusUp() とかいうメソッドで空間ナビゲーションと同じことが出来る。

これを使ってまず4方向へ空間ナビゲーションで移動しておいて、移動先の要素を記憶しておく。

それぞれ移動した後には、元の要素まで戻るようにする。この時使うのが下に紹介した nav-right などという CSS プロパティで、元の要素に仮の ID を付けてからそれをターゲットにして (ry ということをやっている。

難解そうなところが2点。

下のような2つの行があるのだが、

['left','up','right','down'].forEach(highlight);
['down','right','up','left'].forEach(removeStyle);

highlight という関数の中で左上右下の順に「background-color が元から付いていればそれをキャッシュして (ry」ということをやっているので、戻すときは逆の下右上左という順に「キャッシュがあればそれを戻してあげて (ry」とやらないと、背景色が消えなかったりしておかしくなる。


それからもう1点は、moveFocus(Up|Down|Left|Right) の返り値が、空間ナビゲーションが成功すれば true、失敗すれば false となること。

空間ナビゲーションが失敗というのは、その方向に動けないとき、つまり既にドキュメントの端にあるとき。

空間ナビゲーションが成功というのは、2パターンあって、1つ目は普通に隣の要素にフォーカスが動くとき。

2つ目は、画面内に隣の要素が無いので、とりあえずドキュメントを1ページ分スクロールするとき。(この場合フォーカスが隣の要素に移るわけではない)

これが曲者で、せっかく隣の要素を判定するために「見えない空間ナビゲーション」を行なっているのに、その方向に進める要素が無いときはスクロールしてしまって、「見えない空間ナビゲーション」にならない。

ここで失敗した。


これを回避できるかもしれない対策は、(1) アルゴリズムを変えていちいち隣の要素を計算する方式にするか、(2) document.addEventListener の替わりに opera.addEventListener を使うこと。

前者は面倒すぎるのでパス。

後者の場合は、UserJS イベントの 'beforeEvent.scroll' なんかに EventListener を付けて、捕捉したら preventDefault すれば出来るかもしれない。

ただこれをやるには、他のところも色々マイナーな修正をしないといけないので、ちょっとモチベーションが下がりつつある。


気が向いた時にでもまたやるかもしれない。もしどうしてもという需要があるならもうちょっと頑張ってみます。。