Micropost字符倒计时(Rails教程,第2版,第10章,练习7)

时间:2012-06-08 20:47:22

标签: jquery ruby-on-rails-3 internationalization coffeescript railstutorial.org

我尝试使用信息here作为基础并在StackOverflow回答herehere的帮助下,使用Rails教程(第10章,练习7)中的微博字符倒计时。

在屏幕上,它看起来像this,当你接近字符限制时,文本逐渐变红,一旦微博超过限制,Post按钮就会禁用,完成like so

目前的实施方式如下:

视图/共享/ _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"

资产/ Javascript角/ 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

资产/样式表/ 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;
}

配置/区域设置/ en.yml

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

从这里开始,我有两个问题:

首先,如果可能的话,我希望能够对“剩余字符”字符串进行适当的复数化。也许是这样的事情:

视图/共享/ _micropost_form.html.haml

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

配置/区域设置/ en.yml

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

但是,我不知道如何在.countdown div中检索值,我可以将其传递给count参数。我怎么能这样做?

假设第一个问题可以解决,我也想摆脱减号字符,而是将“-2个字符剩余”更改为“2个字符以上”。也许在视图中使用某种分支逻辑和一些javascript来将负数更改为正数...?我在这里不太确定,所以任何帮助都会受到赞赏。

视图/共享/ _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
...

配置/区域设置/ en.yml

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

2 个答案:

答案 0 :(得分:2)

我也正在阅读本教程并发现这篇文章,虽然我喜欢你添加的css使这看起来一致(我已经把它作为我自己使用:))我认为你的解决方案过于复杂。对我来说,这只是两个变化:js脚本并将脚本添加到我的视图中。

我的JS文件: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);
});

这是我将其添加到视图中的地方

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

请让我知道你的想法:)

答案 1 :(得分:1)

我已经找到了解决我的问题(复数化和摆脱所有语言环境中的减号)的解决方案,我觉得这很好,所以我会在这里详细解释,希望有人会觉得它很有用。

如果您希望在深入研究细节之前了解它的样子,可以在my Sample App deployment at Heroku自行试用。

配置

此解决方案使用i18n-js gem,它是“在Javascript上提供Rails I18n翻译的小型库”。宝石很棒,但遗憾的是我并没有像我想的那样和Heroku玩得很好,doesn't seem like it will for the foreseeable future。因此,需要更改以下配置:

<强>配置/ application.rb中

# ...
config.assets.initialize_on_precompile = true

这意味着在每次部署到Heroku之前,需要运行rake assets:precompile,并且一旦确认部署成功,请运行rake assets:clean以再次开始开发资产。如果这太烦人了,你需要另一个解决方案。

  

更新

     

如果你在Heroku环境中启用user-env-compile,你可以让Heroku预先编译你的资产并仍然使用i18n-js gem。有关如何执行此操作的说明是here,我认为只要Heroku支持该功能,它就值得一试。

解决方案

<强>的Gemfile

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

应用/资产/ Javascript角/ application.js中

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

由于上面的Heroku设置,此时我需要运行

$ rake i18n:js:setup

将i18n-js.yml复制到 config 文件夹。

应用/视图/布局/ application.html.haml

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

应用/视图/布局/ _i18n_js.html.haml

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

应用/视图/共享/ _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"

应用/资产/样式表/ custom.css.scss

/* Micropost character countdown */

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

app / assets / javascripts / microposts.js.coffee
(我对javascript / coffeescript不太好,所以这里有改进/重构的空间)

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 (其他语言环境在相同样式中具有相同的键)

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."