Javascript:文字数を全角/半角別にカウントしてはみ出し処理。

〽️ 画面幅の変化にも対応。





前回の問題点、解消に踏み切る。

こんにちは、「ふ」です。テキストボックスから文字数がはみ出した時「…」で表示するの続編になります。

前回の記事はこちら⬇︎

JavaScript/CSS: 文字数オーバーしたときに「…」で表示する。



前回作成したコードは、全角文字で構成されているテキストにおいてのみ有効なものでした。

続編ではテキストの各文字を全角/半角別にカウントし、要素内にちょうどよく収めようと思います。また、初期読み込み後、ユーザの手動による画面幅の変化にも対応させていきましょう。



半角を0.5として文字数をカウント。

半角英数字および記号は次の正規表現パターンで表すことができます。

[ -~]

半角スペース「 」からチルダ「~」までを指定すると、その中に半角英数字および半角記号も含まれることになります。

あるテキストの1文字1文字を順に取り出し、半角パターンにマッチすれば「nagasa」に0.5を加算。マッチしない〜つまり全角文字であれば1を加算するようにします。そして最後に合計の長さ「nagasa」を出力。

function count(n) { var nagasa = 0; for (i = 0; i < n.length; i++) { if(n[i].match(/[ -~]/) ) { nagasa += 0.5; } else { nagasa += 1; } } return nagasa; }

関数が定義できたらちょっと試してみます。



「「3//半角文字(0.5)が3つ」」 var str = "abc"; console.log(count(str)); 「「1▶︎ 1.5」」 「「3//全角文字(1)が5つ」」 str = "あいうえお"; console.log(count(str)); 「「1▶︎ 5」」

うまくいってるようですね。



「文字数オーバー」の場合分け。

扨(さて)ここで考えておきたいのが、「文字数オーバー」した時の対処の仕方が2通り存在する、ということです。

全角3文字が収納できるテキストボックスでやってみましょう。




CASE1


全角文字のテキストがはみ出しました。対処としては、

ボックス内の末尾1文字をカットして「…」に置き換え。





CASE2


半角文字のテキストがはみ出しました。今度は、

ボックス内の末尾2文字をカットして「…」に置き換え。





と、このようにテキストの末尾が半角文字か全角文字かによって、「カットする文字数」は変わってきてしまいます。

var array = ["あ","い","う","a",「「4"b","c"」」]

⬆︎取り出した文字を配列にぶち込んで末尾要素の2文字を取り出し〜全角/半角を判定・処理することもできるのでしょうが、コードが複雑になりすぎて今回説明したかったことの焦点がずれる恐れあり。
したがって、



「2文字カット」に統一したいと思います。

…で、お付き合い願います。では進めていきましょう。



収納可能文字数を全角で取得。


以下のHTMLを元に実装していくことにします。

HTML

長い長いtext。longすぎる。いったいどこまで続くのか。進んでも進んでもまだ出口は見えない。

CSS

#sample { width:40%; 「「3/*短いテキストでも2行分の高さを保持*/」」 min-height:3.2em; border:solid 1px; font-size:150%; }

ブラウザ

サンプルとして、半角文字が含まれたテキストを用意しました。見やすいようにfont-sizeを大きくしています。

これを2行サイズに統一してはみ出し処理を行なっていきます。まづは要素の幅を取得し、2行サイズに収まる全角文字数を返す関数を定義します。

JavaScript

function capacity(s) { 「「3//算出されたCSSを取得」」 var style = window.getComputedStyle(s); 「「3//フォントサイズとボックスの幅を数値で取得」」 var fontsize = parseInt(style.fontSize); var width = parseInt(style.width); 「「3//2行分のボックスに収納できる文字数」」 var mojisuu = Math.floor(width/fontsize)*2; return mojisuu; }

ちょっと試しておきましょう。

var sample = document.getElementById("sample"); console.log(capacity(sample)); 「「1▶︎ 24」」


ブラウザ通りの文字数が取り出せました。



元のテキストが何文字収まるか。


全角24文字ぶんのスペースに対して、「sample」の半角混じりのテキストが実際何文字収まるのかを調べます。
上で作成したcount関数を少し改造した、newcount関数を作りましょう。capacity関数の返り値(今回は全角で24文字)の範囲を超えたら、for文をbreak。その時点で何文字マッチテストさせたかを返せば、イコール「全角24文字ぶんに収まる文字数」が得られます。

function newcount(n,l) { var nagasa = 0; 「「3//マッチテストした回数」」 「「1var mojisuu = 0;」」 for (i = 0; i < n.length; i++) { 「「3//指定された全角文字範囲を超えたら処理を抜けだす」」 「「1if (nagasa >= l) { break; }」」 if(n[i].match(/[ -~]/) ) { nagasa += 0.5; } else { nagasa += 1; } 「「3//マッチテストした回数をカウントしていく」」 「「1mojisuu++;」」 } return 「「1mojisuu」」; }

引数「n」にはテストに掛けるテキスト、「l」にはcapacity関数で得られた全角文字範囲を代入できるようにしておきます。




ちょっと整理しましょう。

関数定義をしたので実行・検証してみる前に、ここまで断片的に説明してきたので、ちょっとコード全体の配置を確認しましょう。

JavaScript

「「3//関数定義。」」 function capacity(s) { 「「3〜略〜」」 } function newcount(n,l) { 「「3〜略〜」」 } 「「3//ここからグローバル変数を宣言。」」 var sample = document.getElementById("sample"); var str = sample.innerHTML;

・・と、ここまでOKでしょうか?
ではHTMLに対して実行させてみますね。



console.log(newcount(str,capacity(sample))); 「「1▶︎ 28」」

「sample」に書かれたテキストの内、「半角24文字」の範囲内で表示できる文字数は28文字と判定されました。



2文字分カットしてtextを書き直す。


諸々の準備が整ったところで、実際に「はみ出し処理」を行なっていきましょう、あともうちょっとですよ!

もうひとつ関数を定義します。「文字数オーバーの場合分けの」ところでの計画どおり、末尾2文字をカットして「…」に置き換えます。

function tenten() { 「「3//strを直接減らすとどんどん切り出されるので、関数実行のたびに初期化。」」 var kstr = str;「「1 ・・・①」」 「「3//newcountの結果を変数に入れておきましょう。」」 var count = (newcount(kstr,capacity(sample))); 「「3文字数オーバーした場合」」 if (kstr.length > count) { 「「3//テキストから(count-2)文字を切り出し。」」 kstr = kstr.substr(0,(count-2)); 「「3//「…」と連結し、元のテキストを置き換える」」 sample.innerText = kstr + "…"; } 「「3//要素の幅が十分にあればそのまま表示」」 else { sample.innerText = kstr; } }

重要なのがの部分です。画面幅が変化した時にこのtenten()関数を繰り返し実行されるようにしたいので、その都度「kstr」を元となるテキストに初期化します。



画面幅の変更にリアルタイムで対応。


扨(さて)このtenten()関数を、ブラウザの初期読み込み時および ユーザ手動による画面幅変更時に実行させます。
画面幅の変更に順応するイベントハンドラについてはこちらを参考にしてください。

JavaScript : 要素幅をリアルタイムに取得。

関数の中身は省略していますが、以下がコードの全貌です。

「「3//関数定義。」」 function capacity(s) { 「「3〜略〜」」 } function newcount(n,l) { 「「3〜略〜」」 } 「「3//ここからグローバル変数を宣言。」」 var sample = document.getElementById("sample"); var str = sample.innerHTML; 「「3//はみ出し処理関数。」」 function tenten() { 「「3〜略〜」」 } 「「3//初期ページ読み込み時に実行」」 tenten(); 「「3//画面幅が変わるたびに実行」」 window.onresize = function () { tenten(); } ;

いよいよ実行してみましょう。左上の値はbodyのwidthを表しています。





450px

800px

1400px

上手くいきましたね!要素の幅が十分広くなった時には、テキストのはみ出し処理は行われずにそのまま表示されます。







おつかれさまでした。


今回は4500文字に及ぶ長いページとなってしまいました。お付き合いいだだいてありがとうございました。
ちなみに今回の方法は、絵文字や半角カタカナには対応していません。させるとなるとただでさえ長いページがどえらいことになります。

然し乍ら、「ふ」はその辺についてもいずれ追求していきたいと思いますので、「…」シリーズの続編をまた発信させてもらうかもです ♪













「ふ」です。

swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。

🐧 twitter 🐧