DOM Rangeを簡単に扱うexRangeのサンプル

テスト用のbookmarklet書きました。
IE8, Firefox3.0, Safari3.2, Google Chrom1.0で動作確認。
Opera orz

javascript:(function(d){s=d.createElement('script');s.type='text/javascript';s.src='http://github.com/TakiTake/js/raw/d1197b42fa16b5d7d7e423b502cf9a8c5e9fc85e/exRangeTest.js';d.getElementsByTagName('head')[0].appendChild(s);})(document)
  1. 適当なWebページのアドレス欄に上記ブックマークレットをペーストして実行
  2. 文字を範囲選択すると、マーカーを引くことができます。

exRangeTest.js

(function(){
  // ブラウザをIEとそれ以外で分ける
  var userAgent = navigator.userAgent.toLowerCase();
  var msie = /msie/.test( userAgent ) && !/opera/.test( userAgent );

  var head = document.getElementsByTagName('head')[0];

  // scriptタグ作成関数
  function script (src) {
    var s = document.createElement('script');
    s.src = src;
    s.type = 'text/javascript';

    return s;
  }; 

  // spanタグ作成関数
  function span () {
    var s = document.createElement('span');
    s.style.backgroundColor = this.getColor();
    return s;
  };

  // spanの背景色を無駄にランダムにする関数
  span.prototype.getColor = function() {
    var n = Math.floor(Math.random() * 3);
    var color = null;

    switch (n) {
      case 0:
        color = 'red';
        break;
      case 1:
        color = 'blue';
        break;
      case 2:
        color = 'green';
        break;
    }

    return color;
  };

  // イベント割り当て関数
  function observe (elem, type, fnc) {
    if (elem.addEventListener)
      elem.addEventListener(type, fnc, false);
    else if (elem.attachEvent)
      elem.attachEvent('on' + type, fnc);
  };

  // IEのみRange, TreeWalkerラッパー読み込む
  if (msie) {
    head.appendChild(script('http://ierange.googlecode.com/files/ierange-m2-packed.js'));
    head.appendChild(script('http://github.com/TakiTake/js/raw/9a2707e5daeaf6f9249739f77b85e37698129542/TreeWalker.js'));
  }

  head.appendChild(script('http://github.com/TakiTake/js/raw/95fa051baff45624f9fa7c7b9c8e7592b2aaa4d0/exRange.js'));

  // マウスアップイベントで文字への色つけ処理実行
  observe(document.body, 'mouseup', function() {
    var sel = window.getSelection();
    if (sel.toString().length) {
       // exRangeがお仕事している部分。この2行でマーカー引いてます。
       // タグまたいでいても、大丈夫!
       exRange(sel)
         .wrap(new span());

      sel.removeAllRanges();
    }
  });
})()

こんな感じ