Posted at

textarea は送信前と送信後で文字列の内容が変化する

More than 1 year has passed since last update.


発端


  1. 文字数制限のある textarea があった

  2. サーバ側(Rails)で文字列の長さを検証

  3. クライアント側(JS)で文字列の長さを確認しつつ、あと何文字入力できるかを表示

  4. クライアント側では規定文字数に収まっていたテキストがサーバ側のバリデーションで弾かれた :scream:


原因

調べてみたところ、W3Cによると


For historical reasons, the element's value is normalised in three different ways for three different purposes. The raw value is the value as it was originally set. It is not normalized. The API value is the value used in the value IDL attribute. It is normalized so that line breaks use "LF" (U+000A) characters. Finally, there is the form submission value. It is normalized so that line breaks use U+000D CARRIAGE RETURN "CRLF" (U+000A) character pairs, and in addition, if necessary given the element's wrap attribute, additional line breaks are inserted to wrap the text at the given width.


とあって、実は textarea には歴史的経緯により


  • raw value

  • API value


    • LF



  • form submission value


    • CRLF



の3種類の値がある。

そして、JavaScript は API value を、サーバサイドでは form submission value を用いて文字数のカウントを行なうため、改行1つにつき CR 1文字分ずつカウントがズレる。


対策

JS の文字数カウント時に改行コードを CRLF に揃える。

- length = $("something").val().length;

+ length = $("something").val().replace(/\r/g, '').replace(/\n/g, '\r\n').length; // 本当は`s/(<!\r)\n/\r\n/g`したい


所感

調べてみるとなるほどという感じだった。

ただ、さくっと調べてみた感じだと困っている人がインターネットにあまりいない感じがしたので、もっとスマートに解決する方法がありそう。