Twitterのようなアプリを作成しています。
ご回答いただけるとありがたいです。よろしくお願いします!
実現したいこと
ツイート投稿画面で、文字を入力するとそれに合わせて以下の条件で文字数をカウントできるようにしたいです。
全角は2文字分でカウント、他(半角英数字と改行)は1文字分でカウント。
狙い
日本語での投稿量と英語での投稿量を同じぐらいにするためです。メモリの大きさとかを考慮したいわけではありません。あくまで言語が変わっても最大投稿量を同じぐらいにしたいと考えています。
現状
バリデーションの設定で全角2文字、半角英数字と改行は1文字カウントの設定はできています。
model
1#tweet.rb 2class Tweet < ApplicationRecord 3 belongs_to :group 4 belongs_to :user 5 has_one_attached :image 6 7 validates :content, presence: true, unless: :was_attached?, 8 length_with_wide_char: { maximum: 400 } 9 10 def was_attached? 11 self.image.attached? 12 end 13end 14 15#length_with_wide_char_validator.rb 16class LengthWithWideCharValidator < ActiveModel::EachValidator 17 def validate_each(object, attribute, value) 18 value = value.gsub(/\r\n/,"\n") 19 count = 0 20 value.split(//).each do |v| 21 v.bytesize > 1 ? count += 2 : count += 1 22 end 23 object.errors[attribute] << (options[:content] || "is too long (maximum is %d characters)" % options[:maximum]) if count > options[:maximum] 24 end 25end
しかし、現状ではjqueryを用いた目に見える部分での文字数カウントは何を入力しても1文字扱いになっています。
これを全角と半角・改行でカウントを変更したいです。
該当のソースコード
views
1#new.html.erb 2<div class="tweet-form"> 3 <%= form_with model: [@group, @tweet], local: true do |f| %> 4 <div class="tweet-form-container"> 5 <div class="tweet-form-wrapper"> 6 <div class="tweet-form-upper"> 7 <%= f.text_area :content, class: "tweet-form-upper-input input-text", autofocus: true %> 8 </div> 9 <div id="image-list"></div> 10 <div class="tweet-form-lower"> 11 <label class="tweet-form-lower-left"> 12 <div class="tweet-form-lower-left-icon"> 13 <span class="camera-icon"><i class="fa fa-camera-retro fa-fw"></i></span> 14 <%= f.file_field :image, class: 'hidden' %> 15 </div> 16 </label> 17 <div class="tweet-form-right"> 18 <div class="input-text-count"></div> 19 <div class="tweet-form-submit"> 20 <%= f.submit 'ツイート', class: "tweet-form-submit-btn" %> 21 </div> 22 </div> 23 </div> 24 </div> 25 </div> 26 <% end %> 27</div>
js
1#count.js 2if (document.URL.match( "tweets/new" ) || document.URL.match(/groups/\d+/tweets/\d+/edit/)) { 3 $(function (){ 4 var count = $(".input-text").text().length; 5 6 var now_count = 400 - count; 7 8 if (count > 400) { 9 $(".input-text-count").css("color","red"); 10 } 11 $(".input-text-count").text(now_count); 12 13 $(".input-text").on("keyup", function() { 14 var count = $(this).val().length; 15 var now_count = 400 - count; 16 17 if (count > 400) { 18 $(".input-text-count").css("color","red"); 19 } else { 20 $(".input-text-count").css("color","black"); 21 } 22 $(".input-text-count").text(now_count); 23 }); 24 }); 25}
###試したこと・調べたこと(1)
Jqueryで動的に全角改行2文字 半角1文字で文字数カウント
を参考に以下のようにコードを書いてみましたが、全文字1カウントになります。
if (document.URL.match( "tweets/new" ) || document.URL.match(/groups/\d+/tweets/\d+/edit/)) { $(function (){ var result = 0; var count = $(".input-text").text().length; for (var i = 0; i < count ; i++){ var chr = text.charCodeAt(i); if ((chr >= 0x00 && chr < 0x81) || (chr === 0xf8f0) || (chr >= 0xff61 && chr < 0xffa0) || (chr >= 0xf8f1 && chr < 0xf8f4)) { result += 1; } else { result += 2; } } var now_count = 400 - count; if (count > 400) { $(".input-text-count").css("color","red"); } $(".input-text-count").text(now_count); $(".input-text").on("keyup", function() { var count = $(this).val().length; var now_count = 400 - count; if (count > 400) { $(".input-text-count").css("color","red"); } else { $(".input-text-count").css("color","black"); } $(".input-text-count").text(now_count); }); }); }
###試したこと・調べたこと(2)
【jQuery】全角を半角2つとして文字数カウントする
を参考に以下のようなコードを書きました。
if (document.URL.match( "tweets/new" ) || document.URL.match(/groups/\d+/tweets/\d+/edit/)) { $(function(){ $('.input-text').on('keyup', function(){ var len = textLength($(this).val()); $('.input-text-count').text(len); }); }); function textLength(text){ var regexp = /[\x01-\x7E\u{FF65}-\u{FF9F}]/mu; var len = 0; for(i = 0; i < text.length; i++){ var ch = text[i]; len += regexp.test(new String(ch)) ? 1 : 2; } return len; } }
これで全角を2文字、他を1文字カウントをすることができました。
次にカウントダウン形式にしたいので、以下のようにしました。
if (document.URL.match( "tweets/new" ) || document.URL.match(/groups/\d+/tweets/\d+/edit/)) { $(function(){ $('.input-text').on('keyup', function(){ var len = textLength($(this).val()); $('.input-text-count').text(len); }); }); function textLength(text){ var regexp = /[\x01-\x7E\u{FF65}-\u{FF9F}]/mu; var len = 0; for(i = 0; i < text.length; i++){ var ch = text[i]; len += regexp.test(new String(ch)) ? 1 : 2; } var count = $(".input-text").text().length; var now_count = 400 - count; if (count > 400) { $(".input-text-count").css("color","red"); } $(".input-text-count").text(now_count); $(".input-text").on("keyup", function() { var count = $(this).val().length; var now_count = 400 - count; if (count > 400) { $(".input-text-count").css("color","red"); } else { $(".input-text-count").css("color","black"); } $(".input-text-count").text(now_count); }); } }
こうすると全文字1カウントになってしまいます。
カウントダウン方式で全角2文字・他1文字カウントになるようにご助言いただきたいです。
以上になります。
回答1件
あなたの回答
tips
プレビュー