3

Rails チュートリアル (第 10 章、演習 7) のマイクロポスト キャラクター カウントダウンを試みました。ここの情報をベースとして使用し、StackOverflow の回答hereおよびhereの助けを借りて使用しました。

画面上ではこんな感じ、文字数制限に近づくにつれて徐々に文字が赤くなっていき、マイクロポストがオーバーリミットになると投稿ボタンが無効になり、 のように仕上がります。

現在の実装は次のようになります。

ビュー/共有/_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

アセット/スタイルシート/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."

ここから、2 つの質問/問題があります。

1つ目は、できれば「残り文字数」の文字列を適切に複数形にしたいということです。おそらく次のようなものです:

ビュー/共有/_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."
4

2 に答える 2

2

私もこのチュートリアルを進めており、この投稿を見つけました。これを均一に見せるために追加したcssが好きですが(これを自分のものとして使用しました:))、これに対する解決策は複雑すぎると思います。私にとっては、js スクリプトとビューへのスクリプトの追加という 2 つの変更だけでした。

私の 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 %>

あなたの考えを教えてください:)

于 2013-03-21T10:17:18.030 に答える
1

私の両方の質問 (複数化とすべてのロケールでの負数の削除) の解決策を見つけたので、ここで詳しく説明します。誰かが役に立つことを願っています。

詳細を掘り下げる前に、それがどのように見えるかを確認したい場合は、Heroku のサンプル アプリのデプロイで自分で試すことができます。

設定

このソリューションでは、i18n-js gem を使用します。これは、「Javascript で Rails I18n 変換を提供する小さなライブラリ」です。gem は素晴らしいものですが、残念ながら Heroku との相性は悪く、当面はうまくいかないようです。そのため、次の構成を変更する必要があります。

config/application.rb

# ...
config.assets.initialize_on_precompile = true

これは、Heroku へのすべてのデプロイの前に、rake assets:precompileを実行する必要があることを意味します。デプロイが成功したことを確認したら、実行rake assets:cleanしてアセットの開発を再開します。これが煩わしい場合は、別の解決策が必要になります。

更新

user-env-compileHeroku 環境で有効にすると、Heroku でアセットをプリコンパイルしても i18n-js gem を使用できます。その方法についての説明はhere です。Heroku が機能をサポートしている限り、実行する価値があると思います。

ソリューション

Gemfile

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

アプリ/資産/javascripts/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."
于 2012-07-04T16:25:36.023 に答える