
【JavaScript入門】入力した文字数をリアルタイムに表示する(commentArea.js)
ここでは 入力中のコメント文字数をリアルタイム表示 し、最大長を超えた場合に警告スタイルへ自動切替する commentArea.js
を実装します。
日本語 IME 変換中はカウントを一時停止し、確定後にのみ更新することで「漢字変換途中で文字数が跳ねる」不快感を無くしています。さらに、入力が変わるたびに storage.js
の saveCommentToStorage()
を呼び、途中入力をローカルストレージへ即時保存して編集再開を快適にします。

フォルダ構成(該当部分)
node-js/
└─ app/
├─ index.html
├─ style.css
└─ js/
├─ common.js
├─ storage.js
├─ imageArea.js
├─ imageEffects.js
├─ controlArea.js
├─ commentArea.js ← ★今回実装
├─ sendArea.js
├─ dateFormat.js
└─ postListArea.js
commentArea.js ― フルコード & 詳細コメント
/* ---------------------------------------------------
commentArea.js
- コメント入力の文字数カウント
- 日本語 IME 確定後にのみカウント
--------------------------------------------------- */
window.addEventListener('DOMContentLoaded', () => {
/* ===== DOM キャッシュ ===== */
const elTxt = document.querySelector('#comment'); // textarea
const elStat = document.querySelector('#commentStatus'); // 文字数表示
const lenMax = parseInt(elTxt.dataset.lenmax); // data-lenmax="100"
let inComp = false; // IME 変換フラグ: true=変換中 false=確定済
/* ----- IME 制御 (composition*) ----- */
// 変換開始: カウント停止
elTxt.addEventListener('compositionstart', () => inComp = true);
// 変換確定: カウント再開
elTxt.addEventListener('compositionend', () => {
inComp = false;
updateStatus(); // 確定直後に必ず更新
});
/* ----- 通常入力 (input) ----- */
elTxt.addEventListener('input', () => {
if (!inComp) updateStatus(); // IME 中はスキップ
});
/* ----- 文字数計算 & 表示更新 ----- */
function updateStatus(){
// [...str] 展開でサロゲートペア対応 (Emoji = 1 文字)
const len = [...elTxt.value].length;
// CSS クラス切替: 普通 or 警告
const cls = len <= lenMax
? 'inputStatus'
: 'inputStatus inputStatusWarn';
// ラベル書き換え
elStat.innerHTML =
`<span class="${cls}">(${len}文字 / 最大${lenMax}文字)</span>`;
// ローカルストレージへ即時保存 (storage.js 側で定義)
saveCommentToStorage();
}
// ページ読み込み時に初期カウントを表示
updateStatus();
});
主要イベント・メソッド早見表
要素 / API | 働き | 使い方のポイント |
---|---|---|
compositionstart | IME 変換開始 | ここで inComp = true |
compositionend | IME 確定 | ここで inComp = false → updateStatus() |
input | 値変更ごとに発火 | 変換中フラグを見て処理分岐 |
[...str].length | ユニコードコードポイント数 | Emoji を 1 文字として数える |
elStat.innerHTML | ラベルの動的更新 | css クラスで色切替 |
saveCommentToStorage() | 入力内容を localStorage へ保存 | storage.js で実装済み |
関数別の詳細解説
関数名 | 処理内容 |
---|---|
updateStatus() | 1. 現在の入力長をサロゲートペア対応で計算 2. 上限と比較し CSS クラスを切替 ( inputStatusWarn は赤文字定義)3. 文字数ラベルを更新 4. saveCommentToStorage() でローカル保存 |
匿名リスナ (input) | キータッチやペーストで発火。inComp が false のときのみ updateStatus() を呼ぶ |
匿名リスナ (compositionstart / end) | IME 状態をトグルし、確定直後に新しい文字列で再カウント |
実装ポイント & ベストプラクティス
- IME イベントの活用
変換中にカウントさせると「かな入力10文字→確定で1文字減」など挙動が不自然。composition*
を利用するとスムーズ。 - サロゲートペア安全なカウント
string.length
では絵文字😊
が 2 文字扱いになり誤判定。[...str]
でコードポイント配列化すると 1 と数えられます。 - 即時保存で入力ロス防止
1 文字ごとにsaveCommentToStorage()
を呼んでも、保存対象は短いテキストなのでパフォーマンス問題は皆無。クラッシュしても復帰が楽。 - CSS で警告色を一元管理
文字数判定ロジックは JS、色や装飾は CSS 変数/クラスに委任すると後でテーマ変更しやすい。
これでコメント入力欄の UX が大幅に向上しました。
次回はページ遷移なしで投稿データをサーバへ送信する sendArea.js
を解説し、リアルタイム投稿フローを完成させます。