Add a JavaScript display to the Home page to count down from 140 characters. (Rails Tutorial, 2nd Ed, Chapter 10, Exercise 7)

泪湿孤枕 提交于 2019-12-02 23:17:43
Paul Fioravanti

I think my solution posted here in SO is different enough from yours now that I can humbly post it as an answer.

You can simplify it using CoffeeScript:

/app/assets/javascripts/microposts.js.coffee

updateCountdown = ->
  remaining = 140 - jQuery("#micropost_content").val().length
  jQuery(".countdown").text remaining + " characters remaining"

jQuery ->
  updateCountdown()
  $("#micropost_content").change updateCountdown
  $("#micropost_content").keyup updateCountdown

And as mentioned by jonyamo, you don't need to touch the application.js as the //= require_tree . already does the trick.

I don't know why, but that solution only worked for me using coffee script. I tried implementing it with javascript, but it somehow didn't display anything: nor the countdown, nor the fixed part of the text "characters remaining".

So here's a recap of what I did.

Step 1 : create a app/javascripts/microposts.js.coffee file

updateCountdown = ->
  remaining = 140 - jQuery("#micropost_content").val().length
  jQuery(".countdown").text remaining + " characters remaining"

jQuery ->
  updateCountdown()
  $("#micropost_content").change updateCountdown
  $("#micropost_content").keyup updateCountdown

NB: Being that its placed in the app/javascripts folder, I didn't need to update the application.js file.

Step 2 : update the _micropost_form.html.erb partial:

<%= form_for(@micropost) do |f| %>
    <%= render 'shared/error_messages', object: f.object %>
    <div class="field">
        <%= f.text_area :content, placeholder: "Compose new micropost..." %>
    </div>
    <%= f.submit "Post", class: "btn btn-large btn-primary" %>
    <span class="countdown"></span>
<% end %>

step 3: implement a bit of css to the custom_css.css.scss file

/* micropost jQuery countdown */

.countdown {
  display: inline;
  padding-left: 10px;
  color: $grayLight;
}

Step 4: enjoy the result and be happy that it all works out :)

My microposts.js.coffee uses the jQuery .css method to change the color of the characters remaining based on the value of the variable remaining to more closely mirror the behavior of twitter

updateCountdown = -> 
  remaining = 140 - jQuery("#micropost_content").val().length
  jQuery(".countdown").text remaining + " characters remaining"
  jQuery(".countdown").css "color", (if (140 >= remaining >= 21) then "gray")
  jQuery(".countdown").css "color", (if (21 > remaining >= 11) then "black")
  jQuery(".countdown").css "color", (if (11 > remaining)  then "red")

jQuery ->
  updateCountdown()
  $("#micropost_content").change updateCountdown
  $("#micropost_content").keyup updateCountdown

Thanks to all who answered before.

mtminogue

I used Brett's code to get me through this exercise in the Rails Tutorial, though I have a minor change. I had problems with the text disappearing from the .countdown element when I navigated to a different page, then back to Home. With some minor research and help from another answer on SO I realized that the cause was Turbolinks. My change to Brett's code, binding to page:change event instead of to ready, is below. I hope this helps some other folks.

function updateCountdown() {
  // 140 is the max message length
  var remaining = 140 - jQuery('#micropost_content').val().length;
  jQuery('.countdown').text(remaining + ' characters remaining');
}

function micropostChange() {
  $('#micropost_content').change(updateCountdown);
}

function micropostKeyup() {
  $('#micropost_content').keyup(updateCountdown);
}

jQuery(document).ready(function($) {
  updateCountdown();
  micropostChange();
  micropostKeyup();
  jQuery(document).on('page:change', function($) {
    updateCountdown();
    micropostChange();
    micropostKeyup();
  });
});

Here's my coffeescript version based on Adriano's solution. This ignores whitespace, doesn't involve adding empty divs into the view, and also adds an error class once you get to minus numbers.

updateCountdown = ->
  text =  jQuery('#micropost_content').val()
  text = text.replace(/\s/g, '');   
  remaining = 140 - text.length
  jQuery('.countdown').text remaining + ' characters remaining'
  jQuery('.countdown').addClass 'alert alert-error' if remaining < 0
  jQuery('.countdown').removeClass 'alert alert-error' if remaining > 0

jQuery(document).ready ->
  jQuery('#new_micropost').append '<span class="countdown">140 characters remaining</span>'
  jQuery('#micropost_content').change updateCountdown
  jQuery('#micropost_content').keyup updateCountdown
  return

In order to avoid minus in character count down I added this limit to _micropost_form.html.erb partial, so it stops you at 140 characters:

<%= f.text_area :content, maxlength:140, placeholder: "Compose new micropost..." %>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!