id, name属性を表示するbookmarklet

以前よりCamino べんりセットのbookmarkletを使っていたのですが、その中の「ID/NAME を表示」が、最近ページによって動いたり動かなかったりという状況があったので、同様の機能のものを自分なりに作ってみることにしました。

(function(){
  var elements = $A(document.body.getElementsByTagName('*'));
  var i = elements.length;
  while (i--) {
    var element = elements[i];
    var tagName = element.tagName.toLowerCase();
    if (tagName == 'a') {
      var id =  element.id || element.name;
      if (!id) continue;
      var anch = makeIdAnch(id);
      element.parentNode.insertBefore(anch, element);
    }
    else if (element.id) {
      var anch = makeIdAnch(element.id);
      if ( tagName.match(/^(br|hr|area|img|object|embed|iframe|col|input|button|textarea|select)$/) )
        element.parentNode.insertBefore(anch, element);
      else
        element.insertBefore(anch, element.firstChild);
    }
  }

  function $A(list) {
    var i = list.length, array = new Array(i);
    while (i--) array[i] = list[i];
    return array;
  }

  function makeIdAnch(id) {
    var ins = document.createElement('ins');
    setStyle(ins, {
      margin: 0,
      padding: 0,
      backgroundImage: 'none',
      textDecoration: 'none'
    });
    var anch = document.createElement('a');
    setStyle(anch, {
      backgroundColor: '#ffc',
      border: 'outset 1px #ffc',
      padding: '0 2px',
      textDecoration: 'none',
      color: '#00f',
      fontSize: '12px',
      fontWeight: 'normal'
    });
    anch.appendChild( document.createTextNode(id) );
    anch.href = '#' + id;
    ins.appendChild(anch);
    return ins;
  }

  function setStyle(element, style) {
    var es = element.style;
    for (var prop in style) {
      es[prop] = style[prop];
    }
  }
})();

prototype.jsより$A()関数を拝借したのですが、リストの各要素に何か処理をする際に「最初にリストのlengthを取得し、while (length--)で逆順に回す」というやり方をしていたのを初めて見たので、自分でも使ってみました。

// 例: whileで回す場合
var i = list.length;
while (i--) {
  var item = list[i];
  // item に対して何かする
}

// 例: forで回す場合
for (var i = 0, len = list.length; i < len; i++) {
  var item = list[i];
  // item に対して何かする
}

後置の--を使っているので、例えばlengthが5だったとすると、whileの括弧内では 5, 4, 3, 2, 1 と続くのに対し、whileループ内では 4, 3, 2, 1, 0 となるのでインデックスの値として丁度よくなっています。見た目にも3項のforで書くよりすっきりしているのもよいと思いました。