Opera用Hit-a-Hint作成記・経過報告 1

かなりコードを整理した。ソースは一番下に (これを便宜的に新版と呼ぶ)。

一応この前公開したやつ↓ (便宜的にベータ版と呼ぶ) に比べると見違えるほど速くなった。

しかし、その前に公開したやつ↓ (旧版と呼ぶ) よりはまだ時間がかかる。

入力欄などにもフォーカスできるようにした故、仕方が無いといえば仕方がないのだけど、なんか釈然としない。


旧版のボトルネックはおそらく、すべてのアンカーにヒントを appendChild して innerHTML していたところだろう。


新版ではヒント要素はアンカーやテキストエリアの子要素にはしなくなったので、スタイルも一回だけ設定することにし、DocumentFragment も使えるようになった。だから旧版でのボトルネックは解消されているはずなんだけど。

(ただし Opera の DocumentFragment には↓のようなバグがあるみたい。大丈夫かな?)


そのかわり、ヒントを振る要素が画面上にあるかどうかの判断が必須になってくるので、それを毎要素について下のように判断している。

function isShown(element) {
  var style = getComputedStyle(element, '');
  if (style.display == 'none' || style.width == '0px') {
    return false;
  } else {
    while (element && element != document) {
      style = getComputedStyle(element, '');
      if (style.visibility == 'visible') {
        element = element.parentNode;
      } else {
        return false;
      }
    }
    return true;
  }
}

このため、アンカー要素の多いページでは優勢だが、DOM ツリーの階層が深いページなどでモタつく。
この while ループがどうにかなれば旧版に準ずるくらいの所要時間にすることはできるのだけど…

(あー、本気でやるなら position がかぶってて z-index が大きい他の要素とかも考慮しないといけないな。あと opacity = 0 とか。)

しかしBlazeixさんの版に比べるとまだかなり差がある。

親要素の visibility が hidden なのに、子要素の Computed Style が hidden にならないのはおかしいんじゃないのかなあ?

とりあえず while ループの中で一回でもスキャンされた要素はキャッシュしておいて、次にそれを踏んだらループを止めることにしようかと考えてるとこ。

むしろ visibility の判断はもういいかもと思ったり。


とりあえず現在の版は置いておきます。ヒント描写までにかかった時間を教えてくれるオマケ付き。改善点の指摘は歓迎です。

このあたりのページでやると、ベンチマークには良いと思います。