背景の説明
あるPHP+Laravelで動作するシステムにて入力情報として渡された文字列を下記のように変換していた。
nl2br(e(mb_substr('渡された文字列', 0, 10)))
全く違う構成で動くシステムにて、これと全く同じ文字列編集&整形を実現させねばならなくなり、現状のままでも利用可能なjavascriptを使い構築しました。
その試行錯誤の中で、熟年者でない故の思い込みではまった箇所があり、備忘録も兼ねて記事にしました。
問題概要
javascript上で実現する際に、一般的によく知られるsubstringとinnerHTMLを使いましたが、表示結果を見ると文字の中身によっては改行コード(<br>
や\n)で文字がぶった切られる事に。。
詳細説明
冒頭のPHPソースコードの意味を解説する所から始めます。
上記で登場する関数のそれぞれの意味はこのようになり
1. nl2br → 文字列内に登場する全改行文字 (\r\n、 \n\r、\n および \r)を<br>
に置換して返します。
2. e → laravelフレームワークのヘルパ関数、PHPのhtmlspecialchars関数をdouble_encodeオプションにデフォルトでtrueを指定し実行される
3. mb_substr → 入力文字列を指定した範囲で切り出す事ができる(日本語のようにマルチバイトであるときはこれ)
プログラムでは3→2→1の順に行われる事になります。
参考リンク
・https://readouble.com/laravel/9.x/ja/helpers.html#method-e
・https://www.php.net/manual/ja/
・https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference
この動作を再現させようとして下記プログラムを組みました。
// 値は適当なサンプル
var stationInfo = "3月15日に開業する上所駅。<br><br>JR越後線の新潟駅と白山駅の間に設置されます。<br><br>JR新潟支社管内の在来線で、新しい駅が誕生するのは20年ぶり。<br><br>地元住民にとって悲願の新駅です。<br>";
if (stationInfo.length > 20) {
stationInfo = stationInfo.substring(0, XX);
stationInfo += "...etc";
}
// HTML上のある領域を指定して記述
$("#main .prefecture_15 li dd.detail")[0].innerHTML = stationInfo;
substringを使う時に切り出し終点位置(第2引数)を指定しますが、そこがこの文字列で<br>
に当たる20や50が指定されると改行を理解せずそのまま切り出してしまう。
3月15日に開業する上所駅。<br><b
解決する方法
・substringを使用する前にreplaceを用いて<br>
を\n
などに置換しておく。
・切り出した文字列を代入する際は、innerTextを用いる。
// 値は適当なサンプル
var stationInfo = "3月15日に開業する上所駅。<br><br>JR越後線の新潟駅と白山駅の間に設置されます。<br><br>JR新潟支社管内の在来線で、新しい駅が誕生するのは20年ぶり。<br><br>地元住民にとって悲願の新駅です。<br>";
stationInfo = stationInfo.replace(/<br>/g, "\r\n");
if (stationInfo.length > 20) {
stationInfo = stationInfo.substring(0, XX);
stationInfo += "...etc";
}
// HTML上のある領域を指定して記述
$("#main .prefecture_15 li dd.detail")[0].innerText = stationInfo;
理由について
デベロッパー向け公式サイトでも述べられていますが、innerTextで渡された値に改行コードにあたるものはサイトレンダリング時に<br>
に置換するので、その仕組みを活用します。
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText
検証とまとめ
仮に50文字目で切り出した場合の実行結果は次のようになります。最初と違い不自然な切り方も無く改行コードを理解した文字列情報として出力されます。
3月15日に開業する上所駅。
JR越後線の新潟駅と白山駅の間に設置されます。
JR新潟支...etc
今のところsubstringは、改行(<br>、\n、\r\nなど
)は全て1文字扱いで計算しているので、そこを考慮して切り出し位置を考えれば想定通りになります。