フォームに文字を入力していく時、あと何文字まで打てるのか分かった方がユーザーに優しいと思ったため、文字数カウント機能を作りました。
▷今回やること
フォームに残り何文字入力できるかを表示する
#文字数カウント方法を考える
・文字を入力したり、消したりするたびフォームの文字数を数える → 残り何文字まで入力できるか表示する
・文字数がオーバーしていた場合、文字色を赤にする → ユーザーに警告する
#文字数カウントのアルゴリズムを考える
jQueryで文字数カウントをする
▷jsが読み込まれたら以下の処理をする
・処理内容(ページが読み込まれた時、フォームに残り何文字入力できるかを数えて表示する)
フォームのvalueを取得して文字数を数える
<!-- Macの改行コードは1文字(\n)であるが、Rails側では改行コードが2文字(\r\n)で保存されるため、\nは2文字とカウントするように設定 -->
最大文字数 ー 取得した文字数 (=残りの入力できる文字数)
if 最大文字数より取得文字数の方が大きい
表示する文字色を赤にする
“あと (残りの入力できる文字数)文字” と表示する
▷jQueryのkeyup()でキーボードが押されて離れるたびに処理を行う
・処理内容(キーボードを押した時、フォームに残り何文字入力できるかを数えて表示する)
フォームのvalueを取得して文字数を数える。
<!-- Macの改行コードは1文字(\n)であるが、Rails側では改行コードが2文字(\r\n)で保存されるため、\nは2文字とカウントするように設定 -->
入力最大文字数 ー 取得した文字数 (=残りの入力できる文字数)
if 最大文字数より取得文字数の方が大きい
表示する文字色を赤にする
“あと (残りの入力できる文字数)文字” と表示する
else
表示する文字色を黒にする
”あと (残りの入力できる文字数)文字” と表示する
処理終了
処理終了
#コードで文字数カウント処理を書く
###1.htmlでフォーム入力タグと文字数表示タグにclassを設定し、jsで指定できるようにする
フォーム入力タグtext_areaのクラスにjs-text
、文字数表示タグpのクラスにjs-text-count
を指定する
(フォームにbootstrapを適用しています)
<%= form_for(@profile) do |f| %>
<div class="panel-body">
<div class="form-group">
<%= f.label :yourself, '自己紹介(最大150文字)' %>
<%# js-textをclassに追加 %>
<%= f.text_area :yourself, class: 'form-control js-text', rows: 6, placeholder: '改行は反映されません' %>
<%# js-text-count をclassに追加 %>
<P class="js-text-count pull-right"></P>
</div>
<div class="text-center">
<%= f.submit '保存する', class: 'btn btn-info'%>
</div>
<% end %>
###2.jsファイルにフォームと文字数表示に対する処理を書く
js-text
のvalueを数えて、js-text-count
に結果を表示する
app/assets/javascripにcount.jsファイルを作成し、文字数カウントの処理を書いていく
(今回のフォームの最大文字数は150)
// jquery書きはじめ
$(function (){
// 処理(ページが読み込まれた時、フォームに残り何文字入力できるかを数えて表示する)
//フォームに入力されている文字数を数える
//\nは"改行"に変換して2文字にする。オプションフラグgで文字列の最後まで\nを探し変換する
var count = $(".js-text").text().replace(/\n/g, "改行").length;
//残りの入力できる文字数を計算
var now_count = 150 - count;
//文字数がオーバーしていたら文字色を赤にする
if (count > 150) {
$(".js-text-count").css("color","red");
}
//残りの入力できる文字数を表示
$(".js-text-count").text( "残り" + now_count + "文字");
$(".js-text").on("keyup", function() {
// 処理(キーボードを押した時、フォームに残り何文字入力できるかを数えて表示する)
//フォームのvalueの文字数を数える
var count = $(this).val().replace(/\n/g, "改行").length;
var now_count = 150 - count;
if (count > 150) {
$(".js-text-count").css("color","red");
} else {
$(".js-text-count").css("color","black");
}
$(".js-text-count").text( "残り" + now_count + "文字");
});
});
###3.リンクをクリックしてページ遷移した時、jacascriptを読み込むようにする
現在のままでは、ページ遷移してもjsが機能しない
▷原因
rails4.0からデフォルトで導入されたgem「turbolinks」が読み込まれているため
〜turbolinksとは〜
画面遷移を高速化させるライブラリ。
ページ遷移するとき、現在のページのtitleとbodyだけを抜き取り、
新しいhtmlのtitleとbodyに交換することで、ページ遷移を高速化させる。
→ページ読み込みを起点としたJavascriptは機能しなくなる
jQuery を使用している場合、 下記の様にページが読み込まれたときの処理を記述出来ますが、 Turbolinksによって、実行されなくなります。
$(function() {
#処理内容
});
▷解決方法
count.jsを読み込みたいリンクのtubolinksを無効にする
aタグはdata-turbolinks="false"
、link_toメソッドはdata: {"turbolinks" => false}
でtubolinksを無効化できる
リンク設定がaタグの場合
<a href=“◯◯” data-turbolinks="false">turbolinksを使わずにリンクする</a>
リンク設定がlink_toメソッドの場合
<%= link_to "turbolinksを使わずにリンクする", ◯◯_path, data: {"turbolinks" => false} %>
これでページ遷移した時、count.jsが読み込まれるようになり、文字数カウント処理が行われる。
#参考
・[簡単すぎる]Rails + jQueryで文字数カウント
・【JavaScript】文字列から改行を全て削除する方法
・turbolinksチートシート
・『Turbolinks』って、なんぞ?