Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8171903
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 6, 20262026-06-06T21:36:30+00:00 2026-06-06T21:36:30+00:00

I attempted the micropost character countdown in The Rails Tutorial (Chapter 10, Exercise 7)

  • 0

I attempted the micropost character countdown in The Rails Tutorial (Chapter 10, Exercise 7) using the information here as a base and with some help from StackOverflow answers here and here.

On screen, it looks like this, and as you get closer to the character limit, the text gradually turns redder, and once the micropost is overlimit, the Post button disables, finishing like so.

The current implementation looks like:

views/shared/_micropost_form.html.haml

= form_for @micropost do |f|
  = render 'shared/error_messages', object: f.object
  .field= f.text_area :content, placeholder: t('.compose_micropost')
  %span
    .remaining= t('.characters_remaining').html_safe
    .countdown
  = f.submit t('.post'), class: "btn btn-large btn-primary"

assets/javascripts/microposts.js.coffee

updateCountdownAttributes = (toRemove, toAdd = null) ->
  for attr in toRemove
    $(".remaining, .countdown").removeClass attr
  if toAdd
    $(".remaining, .countdown").addClass toAdd
    if toAdd is "overlimit"
      $("input.btn.btn-large.btn-primary").attr("disabled", "true")
    else
      $("input.btn.btn-large.btn-primary").removeAttr("disabled")

updateCountdown = ->
  remaining = 140 - $("#micropost_content").val().length
  toRemove = ["nearlimit", "almostlimit", "overlimit"]
  if remaining > 19
    updateCountdownAttributes(toRemove)
  if remaining < 20
    toAdd = (toRemove.filter (attr) -> attr is "nearlimit").toString()
    updateCountdownAttributes(toRemove, toAdd)
  if remaining < 11
    toAdd = (toRemove.filter (attr) -> attr is "almostlimit").toString()
    updateCountdownAttributes(toRemove, toAdd)
  if remaining < 0
    toAdd = (toRemove.filter (attr) -> attr is "overlimit").toString()
    updateCountdownAttributes(toRemove, toAdd)
  $(".countdown").text remaining

$(document).ready ->
  $(".countdown").text 140
  $("#micropost_content").change updateCountdown
  $("#micropost_content").keyup updateCountdown
  $("#micropost_content").keydown updateCountdown
  $("#micropost_content").keypress updateCountdown

assets/stylesheets/custom.css.scss

...
/* Micropost character countdown */

.remaining, .countdown {
  display: inline;
  color: $grayLight;
  float: right;
}

.overlimit {
  color: $red;
}

.almostlimit {
  color: hsl(360, 57%, 21%);
}

.nearlimit {
  color: $gray;
}

config/locales/en.yml

en:
  ...
  shared:
    ...
    micropost_form:
      compose_micropost: "Compose new micropost..."
      post: "Post"
      characters_remaining: "&nbsp;characters remaining."

From here, I have two questions/problems:

The first is, if possible, I want to be able to do proper pluralization of the “characters remaining” string. Perhaps something like:

views/shared/_micropost_form.html.haml

...
%span
  .remaining= t('.characters_remaining', count: [[.countdown value]]).html_safe
  .countdown
...

config/locales/en.yml

...
micropost_form:
  ...
  characters_remaining: 
    one: "&nbsp;character remaining."
    other: "&nbsp;characters remaining."

However, I don’t know how to retrieve the value within the .countdown div in a way that I can pass it over to the count parameter. How can I do this?

Assuming the first problem can be solved, I also want to get rid of the minus number of characters and instead change “-2 characters remaining” to “2 characters over”. Perhaps using some kind of branching logic in the view and some javascript to change the negative number to a positive number…? I’m not really sure here, so any help would be appreciated.

views/shared/_micropost_form.html.haml

...
%span
  - [[ if .countdown value < 0 ]]
    .remaining= t('.characters_over', 
                  count: [[positive .countdown value]]).html_safe
  - [[ else ]]
    .remaining= t('.characters_remaining', count: [[.countdown value]]).html_safe
  .countdown
...

config/locales/en.yml

...
micropost_form:
  ...
  characters_remaining: 
    one: "&nbsp;character remaining."
    other: "&nbsp;characters remaining."
  characters_over: 
    one: "&nbsp;character over."
    other: "&nbsp;characters over."
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-06T21:36:32+00:00Added an answer on June 6, 2026 at 9:36 pm

    I’ve found a solution to both my questions (pluralization and getting rid of the minus numbers in all locales) that I think is pretty good, so I’ll explain it in detail here and hopefully someone will find it useful.

    If you want to see what it looks like before delving into the details, you can try it out for yourself at my Sample App deployment at Heroku.

    Config

    This solution uses the i18n-js gem, which is "a small library to provide the Rails I18n translations on the Javascript." The gem is great, but unfortunately doesn’t play nice with Heroku as I would like, and doesn’t seem like it will for the foreseeable future. So, the following configurations will need to be changed:

    config/application.rb

    # ...
    config.assets.initialize_on_precompile = true
    

    This means that before every deploy to Heroku, rake assets:precompile will need to be run, and once you’ve confirmed a successful deployment, run rake assets:clean to begin developing assets again. If this is too annoying, you’ll need another solution.

    Update:

    If you enable user-env-compile in your Heroku environment, you can get Heroku to precompile your assets and still use the i18n-js gem. Instructions on how to do so are here, and I think it’s worth doing for as long as Heroku will support the functionality.

    The solution

    Gemfile

    # ...
    gem 'i18n-js', '2.1.2'
    

    app/assets/javascripts/application.js

    // ...
    //= require i18n
    //= require i18n/translations
    

    Due to the Heroku settings above, at this point I needed to run

    $ rake i18n:js:setup
    

    to copy i18n-js.yml to the config folder.

    app/views/layouts/application.html.haml

    %html
      %head
        # ...
        = render 'layouts/i18n_js'
    

    app/views/layouts/_i18n_js.html.haml

    :javascript
      I18n.defaultLocale = "#{I18n.default_locale}";
      I18n.locale = "#{I18n.locale}";
    

    app/views/shared/_micropost_form.html.haml

    # ...
    .field= f.text_area :content, placeholder: t('.compose_micropost')
    %span.countdown
    = f.submit t('.post'), class: "btn btn-large btn-primary"
    

    app/assets/stylesheets/custom.css.scss

    /* Micropost character countdown */
    
    .countdown {
      display: inline;
      color: $grayLight;
      float: right;
    }
    // ...
    

    app/assets/javascripts/microposts.js.coffee
    (I’m not that good with javascript/coffeescript, so there’s likely room for improvement/refactoring here)

    updateCountdownString = (remaining) ->
      if remaining > 1 or remaining is 0
      $(".countdown").text I18n.t('shared.micropost_form.characters_remaining.other',
                                  count: remaining)
      else if remaining is 1
        $(".countdown").text I18n.t('shared.micropost_form.characters_remaining.one',
                                    count: remaining)
      else if remaining is -1
        $(".countdown").text I18n.t('shared.micropost_form.characters_over.one',
                                    count: -remaining)
      else
        $(".countdown").text I18n.t('shared.micropost_form.characters_over.other',
                                    count: -remaining)
    
    takeFromCollection = (collection, className) ->
      (collection.filter (attr) -> attr is className).toString()
    
    updateCountdownAttributes = (remaining) ->
      toRemove = ["nearlimit", "almostlimit", "overlimit"]
      if remaining < 20
        toAdd = takeFromCollection(toRemove, "nearlimit")
      if remaining < 11
        toAdd = takeFromCollection(toRemove, "almostlimit")
      if remaining < 0
        toAdd = takeFromCollection(toRemove, "overlimit")
    
      if toAdd isnt null
        for attr in toRemove
          $(".countdown").removeClass attr
        $(".countdown").addClass toAdd
      if toAdd is "overlimit"
        $("input.btn.btn-large.btn-primary").attr("disabled", "true")
      else
        $("input.btn.btn-large.btn-primary").removeAttr("disabled")
    
    updateCountdown = ->
      remaining = 140 - $("#micropost_content").val().length
      updateCountdownString(remaining)
      updateCountdownAttributes(remaining)
    
    $(document).ready ->
      $(".countdown").text I18n.t('shared.micropost_form.characters_remaining.other',
                                  count: 140)
      $("#micropost_content").on("change keyup keydown keypress paste drop",
                                 updateCountdown)
    

    config/locales/en.yml (other locales have the same keys in the same style)

    shared:
      # ...
      micropost_form:
        characters_remaining:
          one: "%{count} character remaining."
          other: "%{count} characters remaining."
        characters_over:
          one: "%{count} character over limit."
          other: "%{count} characters over limit."
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

In listing 11.45 of Chapter 11 of The Rails Tutorial 2nd edition, the from_users_followed_by
Using the Microsoft Driver Development Kit (DDK), this error plagued me as I attempted
Attempted translation of the above question from non-native English to English: This is a
I attempted to generate a migration like: rails generate migration RemovefromGenotypes box:integer well:string but
This question is different from the questions posted here and here even though the
I attempted to re-size two buttons in MSIE, so they would be extra-large but
I attempted to render a circle in opengl es 1.1 as a test before
My attempted solution was: $date = Nov 30 2009 03:00:00:000PM; echo date(F Y, strtotime($date));
I'm attempted to install the bzip2-ruby gem on Windows 7 x64. Now I don't
I'm attempted to use deferred and hitch in order to provide a callback for

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.