JavaScript

テキストエリア、テキストフィールドのキャレット位置に文字列挿入

テキストエリアやテキストフィールドに入力された文字のキャレット位置に新しく文字列を挿入する備忘録です。コードは、確立されているというか参考にさせていただいた元ネタがあったんですがどちら様のサイトか忘れてしまいました。

実際は古いIEのdocument.selection.createRange()が使える場合とそうでない場合で条件分岐させたコードを書いていましたがメンドクサイので端折りました。HTMLInputElementの以下のプロパティとメソッドを使用しています。

selectionStart
選択したテキストの開始インデックス。何も選択されていない場合はキャレット位置。
selectionEnd
選択したテキストの終了インデックス。
setSelectionRange(開始インデックス, 終了インデックス[, 方向])
テキストの選択範囲を設定するメソッド。テキストを挿入した後、引き続き入力作業が行いやすいように、キャレット位置を適宜設定したほうがいいと思います。
HTMLInputElement - Web APIs | MDN

キーボードによる改行を<br>タグに変換する

テキストエリア内での、キーボードによる改行をその場で<br>タグに変えてしまうサンプル。あんまり需要ないと思いますが、テキストエリアとは別のチェックボックスで切り替えられるようにしたりすると応用できるかなと思います。

// テキストエリア
var field = document.getElementById('textarea');

// チェックボックス
var checkbox = document.getElementById('checkbox');

field.addEventListener('keypress', function(e) {
  if (e.keyCode == 13 && checkbox.checked) {
    // テキスト選択の開始インデックス(キャレット位置)
    var index = field.selectionStart;

    // 開始インデックスの所に '<br>' を追加
    field.value = field.value.substr(0, index) + '<br>' + field.value.substr(index, field.value.length);

    // 新しいキャレット位置
    field.focus();
    var newCaret = index + '<br>'.length;
    field.setSelectionRange(newCaret, newCaret);
    return false;
  }
});

チェックボックスがチェックされている場合に限りEnterキーによる改行で<br>を追加します。続けて入力がしやすいように新しいキャレット位置を<br>の後ろに設定します。

選択テキストをタグで囲む、またはキャレット位置に空のまま挿入する

テキストエリア内の選択テキストをHTMLタグで囲むサンプル。サンプルは<b>タグに固定してますが引数でタグを受け取れるよう関数にすればWYSIWYGっぽいフォームにできると思います。選択テキストがない場合はキャレット位置に内容が空のままでタグを挿入します。

// テキストエリア
var field = document.getElementById('textarea');

// 挿入する開始タグと終了タグ
var tag = new Array('<b>', '</b>');

document.getElementById('button').addEventListener('click', function() {

  // 選択テキストの開始インデックス(キャレット位置)
  var start = field.selectionStart;

  // 選択テキストの終了位置
  var end = field.selectionEnd;

  // 選択テキストの長さ
  var selected = end - start;

  // 選択テキスト
  var target = selected ? field.value.substr(start, selected) : '';

  // 選択中のテキストを '<b>' で囲む
  field.value = field.value.substr(0, start) + tag[0] + target + tag[1] + field.value.substr(end, field.value.length);

  // '<b>〜</b>'の部分を選択状態にする
  field.focus();
  field.setSelectionRange(start, (start + tag[0].length + selected + tag[1].length) );
});

サンプル