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

上のことを踏まえて、getAbsolutePosition 関数を次のように書き直してみた。

function getAbsolutePosition(elem) {
  var style = getComputedStyle(elem, null);
  var rect = rectFixForOpera(elem) || elem.getClientRects()[0];
  if (rect && rect.right-rect.left && style.visibility != 'hidden' && style.opacity !=0 && rect.left >= 0 && rect.top >= -5 && rect.bottom <= window.innerHeight + 5 && rect.right <= window.innerWidth) {
    var html = document.documentElement;
    var body = document.body;
    return {
      top: (body.scrollTop || html.scrollTop) - html.clientTop + rect.top,
      left: (body.scrollLeft || html.scrollLeft) - html.clientLeft + rect.left
    }
  }
  return false;
}
function rectFixForOpera(elem) {
  if(!window.opera) return null;
  if(elem.tagName.toLowerCase()!='a')return null; 
  if(getComputedStyle(elem,null).cssFloat!='none')return null;
  var c = elem.firstChild;
  var cIsAfterWhiteSpace = true;
  while (cIsAfterWhiteSpace) {
    if (!c) return {
      left: 0,
      right: 0,
      top: 0,
      bottom: 0
    };
    cIsAfterWhiteSpace = (c.nodeName.toLowerCase() == 'br' || c.nodeName == '#comment' || c.nodeName == '#text' && !/\S/.test(c.nodeValue));
    if (c instanceof HTMLImageElement || c.tagName && c.tagName.toLowerCase()!='br' && getComputedStyle(c, null).display == 'block') return c.getBoundingClientRect();
    c = c.nextSibling;
  }
  return null;
}

中身が画像なのか< br >なのか、ブロック要素なのかインライン要素か、ということを調べる必要があるので、ちょっと複雑になってしまった。スピードも若干犠牲に。

タイプを判定するのに、instanceof でやるのがいいのか、nodeName がいいのか、tagName がいいのか、よくわかってないので僕の Hit-a-Hint のソース中にはそれらが混在してる。

とりあえず今日までの分を公開しておく。

かなり堅牢になってきたと思うので、そろそろコードフリーズになると思う。

バグがあったので修正。

cssFloat にも 対応。