[javascript] textareaに入力した文字数や行数をリアルタイムにカウントして画面に表示する方法

javascript

Twitterやinstagramなどフォームに文字制限が付いているのをみたことがある人は多いかと思います。

今回はこの文字数のカウントと行数のカウント方法をjavascriptを利用して表現します。

\プログラミングを学びたい方におすすめ/

  • セール時は最大90%以上OFFの超お得価格
  • 30日間返金保証あり
  • 新規の方は新規受講生割引あり!

Udemy公式サイト

textareaにキーが入力されたかどうかのイベントを実装する

今回はリアルタイムに文字数をカウントしてくれるようにするために、textareaにキー入力イベントを実装します。

キーが入力されたかどうかのイベントは「keyup」で実装することができます。

<textarea id="text" class="txt-counter" placeholder="Please write something....." spellcheck="true" autofocus></textarea>
const textarea = document.getElementById('text');
textarea.addEventListener('keyup', () => {
    console.log(textarea.value)
}

上記により、textareaに入力されるごとにコンソール常にそのテキスト情報が出力されます。

文字数のカウントと行数のカウント

文字数は2バイト文字と1バイト文字の区別をせず、どちらも1文字として扱うように実装します。

空白は今回は文字数カウントに含めずあくまで「文字」をカウントさせます。そのため正規表現で「空白」があった場合は「”」に置換した文字の長さを取得します。

行数のカウントは「\r\n」で分割した時の配列の長さを取得します。

function wordCount(val) {
  return {
    charactersNoSpaces: val.replace(/\s+/g, '').length,
      // 空白を含める場合は下記を利用
    characters: val.length,
    lines: val.split(/\r*\n/).length
  };
}

実装例

では、先ほど説明してきたコードを合わせて実際にリアルタイムで文字数と行数をカウントするフォームを作成したいと思います。

<div class="container">
    <h1>Characteters and Lines Counter</h1>
    <textarea id="text" class="txt-counter" placeholder="Please write something....." spellcheck="true" autofocus></textarea>
    <div class="counter-container">
        <div class="counter">
            <div class="counter-box"></div>
            <label>Total Characteters: <span id="charCounting">0</span></label>
        </div>
        <div class="counter">
            <div class="counter-box"></div>
            <label>Total Lines: <span id="lineCounting">0</span></label>
        </div>
    </div>
</div>
body {
    font-family: "Open Sans", "Segoe WP", "Segoe UI", Helvetica, Arial, sans-serif;
    text-align: center;
    color: #34495E;
    background: #FCFDFD;
}

.container {
    height: 100vh;
    width: 100%;
    display: flex;
    align-items: center;
    flex-direction: column;
}

.txt-counter {
    height: 322px;
    width: 707px;
    padding: 20px;
    color: #000;
    margin: 0 0 15px 0;
}

.counter {
    display: flex;
    align-items: center;
}

.counter .counter-box {
    height: 10px;
    width: 10px;
    margin: 0 10px 0 0;
    border-radius: 50%;
    background: rgb(69, 102, 164);
}
function wordCount(val) {
  return {
    charactersNoSpaces: val.replace(/\s+/g, '').length,
    characters: val.length,
    lines: val.split(/\r*\n/).length
  };
}
const textarea = document.getElementById('text');
const charCounting = document.getElementById('charCounting');
const lineCounting = document.getElementById('lineCounting');
textarea.addEventListener('keyup', () => {
  console.log(textarea.value);
  let wc = wordCount(textarea.value);
  charCounting.innerText = wc.charactersNoSpaces;
  lineCounting.innerText = wc.lines;
});

(補足) 文字数制限を設ける

実際に実装しましたが、文字数制限の処理を入れてみます。今回は100文字以上入力した場合は、オーバーした分をカウントして表示します。(今回は空白も文字にカウントしています)

まずは、HTML側に制限をオーバーした文字数をカウントする部分を用意します。

<!-- 省略 -->
<div class="counter">
    <div class="counter-box"></div>
    <label>Over Characters: <span id="overCharCounting">0</span></label>
</div>
<!-- 省略 -->

次に、文字数制限周りの処理を先ほど作ったjavascriptコードに付け加えます。

function wordCount(val) {
  // maxの文字数を100とする
    const maxCharacters = 100;
  let overCharactersCount = 0;

    // 文字数制限を超えた場合はカウントする
  if (val.length > maxCharacters) {
    overCharactersCount = val.length - maxCharacters;
  }

  return {
    charactersNoSpaces: val.replace(/\s+/g, '').length,
    characters: val.length,
    overCharacters: overCharactersCount,
    lines: val.split(/\r*\n/).length
  };
}

const overCharCounting = document.getElementById('overCharCounting');
textarea.addEventListener('keyup', () => {
  let wc = wordCount(textarea.value);
  charCounting.innerText = wc.characters;
  lineCounting.innerText = wc.lines;
  overCharCounting.innerText = wc.overCharacters;
});

問題なく、文字数制限に関する処理が行えました。

(補足) 全角(2バイト)文字の場合は2文字分としてカウントする

DBによってはVarcharやNVarcharなど2バイト許容している場合とそうでない場合があります。また、全角の場合は2文字として扱うケースもあります。

ここでは、全角の場合は2文字、半角の場合は1文字としてカウントする処理の実装です。

function wordCountForFullHalfSize(val){
  let charCount = 0;
  for (let i = 0; i < val.length; i++) {
    (val[i].match(/[ -~]/)) ? charCount += 1 : charCount += 2;
  }
  return charCount;
}

文字を分解し、正規表現を利用し、半角だった場合は 1文字分をカウントしそうでなかった場合は2文字分をカウントします。

実際の実装例は下記の通りです(一部省略)

<div class="counter">
    <div class="counter-box"></div>
    <label>Full/Half Size Count: <span id="fullHalfSizeCounting">0</span></label>
</div>
function wordCount(val) {
    let FullHalfSizeCount = wordCountForFullHalfSize(val);
    return {
        fullHalfSizeCount: FullHalfSizeCount
    };
}

const fullHalfSizeCounting = document.getElementById('fullHalfSizeCounting');
textarea.addEventListener('keyup', () => {
    let wc = wordCount(textarea.value);
    fullHalfSizeCounting.innerText = wc.fullHalfSizeCount;
}

問題なく、全角/半角を区別して文字数をカウントできました。

最後に

問い合わせフォームなど含め文字制限は必要な機能です。

ユーザインターフェースを考慮し、リアルタイムで文字数をカウントするような動きを作ってみると良いかと思います。

タイトルとURLをコピーしました