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

我尝试了The Rails教程(第10章,练习7)中的微博字符倒计时,使用此处的信息作为基础,并在 此处和此处获得StackOverflow答案的帮助。

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

目前的实现如下:

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

资产/ Java脚本/ 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  attr is "nearlimit").toString() updateCountdownAttributes(toRemove, toAdd) if remaining  attr is "almostlimit").toString() updateCountdownAttributes(toRemove, toAdd) if remaining  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: " characters remaining." 

从这里,我有两个问题/问题:

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

视图/共享/ _micropost_form.html.haml

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

配置/语言环境/ en.yml

 ... micropost_form: ... characters_remaining: one: " character remaining." other: " 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: " character remaining." other: " characters remaining." characters_over: one: " character over." other: " characters over." 

我也正在阅读本教程,并发现这篇文章,虽然我喜欢你添加的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); }); 

这是我将它添加到视图中的位置

  <%= form_for(@micropost) do |f| %> <%= render 'shared/error_messages', object: f.object %> 

请让我知道你在想什么 :)

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

如果您想深入研究细节之前看看它是什么样的,您可以在Heroku的Sample App部署中亲自尝试一下。

配置

这个解决方案使用了i18n-js gem,它是“在Javascript上提供Rails I18n翻译的小型库”。 gem很棒,但遗憾的是我并没有像我想的那样和Heroku玩得很好,而且在可预见的未来它似乎不会 。 因此,需要更改以下配置:

配置/ application.rb中

 # ... config.assets.initialize_on_precompile = true 

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

更新

如果在Heroku环境中启用user-env-compile ,则可以让Heroku预编译您的资产并仍然使用i18n-js gem。 关于如何操作的说明在这里 ,我认为只要Heroku支持该function,它就值得做。

解决方案

的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; } // ... 

应用程序/资产/ JavaScript的/ 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."