素人がプログラミングを勉強していたブログ

プログラミング、セキュリティ、英語、Webなどのブログ since 2008

連絡先: twitter: @javascripter にどうぞ。

Hit-a-HintをパクってGreasemonkeyスクリプトにした

細かい使い勝手が悪いからまだイマイチだけど、一応は動く。

// ==UserScript==
// @name           HaH_modoki
// @namespace      http://d.hatena.ne.jp/javascripter/
// @include        http*
// ==/UserScript==
var START_KEY=102;//fを押すと開始
var COLOR='white';
var BGCOLOR='rgba(0,0,0,0.5)';
var enable=false;
var keyCounter=0;
var keys=0;

function keypress(key){
  if(enable==false){
    if(key.which==START_KEY){
    showTip();
    enable=true;
    keyCounter=0;
    keys=0;
    }
  }else{
    if(key.DOM_VK_0<=key.which&&
        key.which<=key.DOM_VK_9){
      keyCounter++;
      keys=keys*10+key.which-48;
    }else{
      removeTip();
      enable=false;
       if(links.length>=keys)
        location.href=links[keys].href;
   }
    if(maxKey<=keyCounter){
      removeTip();
      enable=false;
      if(links.length>=keys)
        location.href=links[keys].href;
    }
  }
}
function showTip(){
  var template=document.createElement('span');
  template.className='_tip';
  with(template.style){
    color=COLOR;
    backgroundColor=BGCOLOR;
    zIndex='999999';
    position='absolute';
  }
  var windowLeft=window.scrollX;
  var windowRight=window.scrollX+window.innerWidth;
  var windowTop=window.scrollY;
  var windowBottom=window.scrollY+window.innerHeight;
  links=Array.filter(document.links,
    function(link){
      var linkPosition=link.getBoundingClientRect();
      return windowLeft<=linkPosition.left&&
      windowRight>=linkPosition.right&&
      windowTop<=linkPosition.top&&
      windowBottom>=linkPosition.bottom;
    });
  links.forEach(
    function(link,i){
    var linkPosition=link.getBoundingClientRect();
    var tip=template.cloneNode(true);
    tip.textContent=i;
    with(tip.style){
      top=linkPosition.top;
      left=linkPosition.left;
    }
    document.body.appendChild(tip);
    });
  maxKey=links.length,toString().length;
}
function removeTip(){
  var tips=document.getElementsByClassName('_tip');
  while(tips.length)
    tips[0].parentNode.removeChild(tips[0]);
}

document.addEventListener('keypress',keypress,false);

つまった所とか:

  1. 要素の絶対位置を求めるには、(Firefox3から追加された)getBoundingClientRect()を使う。Firefox2でも動かしたいなら、AutoPagerizeのgetElementPosition関数が参考になる。
  2. cloneNodeの引数は省略できない。trueかfalseを指定しないと、エラーが出る。
  3. Firebugのconsole関数はapplyとかcallで呼んだり、直接関数を引数として使うとXPCNativeWrapper関連のエラーになる。
  4. 似たような要素を大量に生成するときは、毎回組み立てるより、ひとつテンプレートを容易してcloneNode(true)してから必要な部分を変更すると高速。