jQuery を用いたタブとスペースの相互変換アプリケーション

タブ文字とスペースの相互変換機能は昨今なら大体のエディタに機能が備わっているものですが、私なんぞは eclipseJava のコードを書くときは何も考えずにタブ文字でインデントしていまして、これをはてなダイアリーに掲載するときに半角スペースに置き換えるのに「ブログを書くときはどうせブラウザ起動してるんだし、ブラウザで動くものが欲しいなぁ」と思ってガリッと JavaScript で書いてしまったわけですが、それを jQuery で書き直したものをご紹介したいと思います。

<!doctype html>
<html>
  <head>
    <title>タブ &harr; スペース変換</title>
    <script src="lib/jquery-2.0.0.min.js"></script>
    <link rel="stylesheet" href="parseTab.css" type="text/css">
  </head>
  <body>
    <form>
      <fieldset>
        <legend>オリジナルソース</legend>
        <textarea id="source" cols="80" rows="20">ここにソースを貼り付けてください。</textarea>
      </fieldset>
      <p>
        <label><input type="radio" name="mode" value="0" checked>タブ &rarr; スペース</label>
        <label><input type="radio" name="mode" value="1">スペース &rarr; タブ</label>
      </p>
      <p>
        スペース数 <input type="text" id="spaces" size="5" value="4">
        <input type="button" value="変換" disabled>
      </p>
      <fieldset>
        <legend>変換結果</legend>
        <textarea id="text" cols="80" rows="20" readonly>ここに結果が表示されます。</textarea>
      </fieldset>
    </form>
    <script src="parseTab.js"></script>
  </body>
</html>

textarea はスタイルシート(ソース省略)で初期の文字色を gray にしています。他のスタイルはいじっていません。

$("#source").on({
  focus: function () {
    if($(this).val() == this.defaultValue) {
      $(this).val("").css("color", "black");
      $(":button").prop("disabled", false);
    }
  },
  blur: function () {
    if(!$(this).val()) {
      $(this).val(this.defaultValue).css("color", "gray");
      $(":button").prop("disabled", true);
    }
  }
});

$(":button").on("click", function () {
  var source = $("#source").val();
  var spaces = $("#spaces").val();
  var mode = $('[name = "mode"]:checked').val();
  var text;
  var parseSpaces = "";
  for(i = 0; i < spaces; i++) {
    parseSpaces += " ";
  }

  if(mode == 0) {
    text = source.replace(/\t/g, parseSpaces);
  } else {
    var re1 = new RegExp("\n" + parseSpaces, "g")
    text = source.replace(re1, "\n\t");
    var re2 = new RegExp("\t" + parseSpaces);
    while(text.match(re2)) {
      text = text.replace(re2, "\t\t");
    }
  }

  $("#text").val(text).css("color", "black");
});

on 関数にはイベントの種類とイベントに対してバインドする関数の組を map で渡すことができます。この例では、入力部の textarea にフォーカスが移ったとき(focus)に「値が初期値のままだった場合は中身を空にして文字色を黒に設定し、ボタンを有効にする」処理を、フォーカスを失ったとき(blur)に「中身が空だった場合は初期テキストを表示して文字色を灰色に設定し、ボタンを無効にする」処理をさせて*1います。prop 関数は JavaScript におけるオブジェクトのプロパティを呼び出すための jQuery 向けの関数で、この場合は Button オブジェクトが disabled プロパティを持っていますので、このプロパティの真偽値をむにゃむにゃしてボタンを有効にしたり無効にしたりしています。attr 関数と removeAttr 関数を使って同じようなことはできるんですが、true と false の切り替えなのでこっちの方がわかりやすいかな、と。変換の処理そのものは普通の JavaScript ですので説明は割愛します。

一応、きちんとインデントされたソースコードが入力されることを前提として作っているので、インデントが不揃いなソースコードだとうまく変換されませんのでご注意。

*1:早い話が「初期状態のときは変換操作ができないようにボタンは無効化しておく」ということをしたいわけです。