Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
409 views
in Technique[技术] by (71.8m points)

jquery - Micropost character countdown (Rails Tutorial, 2nd Ed, Chapter 10, Exercise 7)

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."
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I am also going through this tutorial and found this post and while I like the css you added to make this look uniform (which I have taken to use as my own :)) I think your solution for this is over-complicated. For me it was simply two changes: the js script and adding the script to my view.

My JS file: character_countdown.js

function updateCountdown() {
  // 140 characters max
  var left = 140 - jQuery('.micropost_text_area').val().length;
  if(left == 1) {
    var charactersLeft = ' character left.'
  }
  else if(left < 0){
    var charactersLeft = ' characters too many.'
  }
  else{
    var charactersLeft = ' characters left.'
  }
  jQuery('.countdown').text(Math.abs(left) + charactersLeft);
}

jQuery(document).ready(function($) {
  updateCountdown();
  $('.micropost_text_area').change(updateCountdown);
  $('.micropost_text_area').keyup(updateCountdown);
});

and here is where I added it into the view

<script src="app/assets/javascripts/character_countdown.js"></script>
<%= form_for(@micropost) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>

Please let me know what you think :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...