Добавьте отображение JavaScript на главную страницу, чтобы пересчитать от 140 символов. (Rails Tutorial, 2nd Ed, Chapter 10, Упражнение 7)

Это упражнение было немного сложным. Понял, что я опубликую свое решение, чтобы узнать, кто-то сделал это по-другому или кто-нибудь, кто знает лучший способ.

Я не уверен в передовом опыте использования Asset Pipline.. например, правильный порядок, чтобы поместить вещи в файл манифеста application.js или когда нужно поместить вещи в lib против приложения. Я просто поставил следующее в lib, чтобы попытаться заставить его работать.


Из Michael Hartl Rails Tutorial 2nd ed Глава 10, Упражнение 7:

(сложный) Добавьте отображение JavaScript на главную страницу, чтобы считать от 140 символов.

Во-первых, я прочитал этот пост о jQuery Twitter-подобных обратных отсчетах, который предоставил код для этого.

Затем я обновил приложение /views/shared/ _micropost_form.html.erb, чтобы выглядеть так:

<%= form_for(@micropost) do |f| %>
    <%= render 'shared/error_messages', object: f.object %>
    <div class="field">
        <%= f.text_area :content, placeholder: "Compose new micropost..." %>
    </div>
    <%= f.submit "Post", class: "btn btn-large btn-primary" %>
    <span class="countdown"></span>

<% end %>

Затем я создал каталог javascripts в lib и добавил файл

Lib/активы/JavaScripts/microposts.js

function updateCountdown() {
    // 140 is the max message length
    var remaining = 140 - jQuery('#micropost_content').val().length;
    jQuery('.countdown').text(remaining + ' characters remaining');
}

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

Наконец, я добавил крошечный бит CSS

Приложение/активы/таблицы стилей /custom.css.scss

/* micropost jQuery countdown */

.countdown {
  display: inline;
  padding-left: 30px;
  color: $grayLight;
}

Наконец, добавьте директиву в app/assets/javascripts/application.js

//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require microposts
//= require_tree .

ЗАКЛЮЧИТЕЛЬНЫЙ РЕЗУЛЬТАТ выглядит так http://grab.by/dbC6


Вопрос: Было бы неправильно помещать строки манифеста после //= require_tree .

Например, это работает, но я не уверен, какая разница, или добавив строку над деревом.

 //= require jquery
 //= require jquery_ujs
 //= require bootstrap
 //= require_tree .
 //= require microposts

Ответы

Ответ 2

Вы можете упростить его с помощью CoffeeScript:

/app/assets/javascripts/microposts.js.coffee

updateCountdown = ->
  remaining = 140 - jQuery("#micropost_content").val().length
  jQuery(".countdown").text remaining + " characters remaining"

jQuery ->
  updateCountdown()
  $("#micropost_content").change updateCountdown
  $("#micropost_content").keyup updateCountdown

И как упоминалось jonyamo, вам не нужно прикасаться к application.js, поскольку //= require_tree . уже выполняет трюк.

Ответ 3

Я не знаю почему, но это решение работает только для меня, используя кофе script. Я попытался реализовать его с помощью javascript, но он каким-то образом ничего не отображал: ни обратный отсчет, ни фиксированная часть текста "оставшиеся символы".

Итак, вот что я сделал.

Шаг 1: создайте файл app/javascripts/microposts.js.coffee

updateCountdown = ->
  remaining = 140 - jQuery("#micropost_content").val().length
  jQuery(".countdown").text remaining + " characters remaining"

jQuery ->
  updateCountdown()
  $("#micropost_content").change updateCountdown
  $("#micropost_content").keyup updateCountdown

NB: будучи помещенным в папку app/javascripts, мне не нужно было обновлять файл application.js.

Шаг 2: обновите часть _micropost_form.html.erb:

<%= form_for(@micropost) do |f| %>
    <%= render 'shared/error_messages', object: f.object %>
    <div class="field">
        <%= f.text_area :content, placeholder: "Compose new micropost..." %>
    </div>
    <%= f.submit "Post", class: "btn btn-large btn-primary" %>
    <span class="countdown"></span>
<% end %>

шаг 3: реализовать бит css в файле custom_css.css.scss

/* micropost jQuery countdown */

.countdown {
  display: inline;
  padding-left: 10px;
  color: $grayLight;
}

Шаг 4: наслаждайтесь результатом и будьте счастливы, что все это получится:)

Ответ 4

My microposts.js.coffee использует метод jQuery . css, чтобы изменить цвет оставшихся символов в зависимости от значения переменной remaining чтобы более точно отразить поведение twitter

updateCountdown = -> 
  remaining = 140 - jQuery("#micropost_content").val().length
  jQuery(".countdown").text remaining + " characters remaining"
  jQuery(".countdown").css "color", (if (140 >= remaining >= 21) then "gray")
  jQuery(".countdown").css "color", (if (21 > remaining >= 11) then "black")
  jQuery(".countdown").css "color", (if (11 > remaining)  then "red")

jQuery ->
  updateCountdown()
  $("#micropost_content").change updateCountdown
  $("#micropost_content").keyup updateCountdown

Спасибо всем, кто раньше ответил.

Ответ 5

Я использовал код Бретта, чтобы получить это упражнение в Rails Tutorial, хотя у меня небольшие изменения. У меня возникли проблемы с текстом, исчезающим из элемента .countdown, когда я перешел на другую страницу, а затем вернулся к Home. С некоторыми незначительными исследованиями и помощь от другого ответа на SO я понял, что причиной является Turbolinks. Мое изменение кода Бретта, привязка к событию page:change вместо ready, приведено ниже. Надеюсь, это поможет некоторым другим людям.

function updateCountdown() {
  // 140 is the max message length
  var remaining = 140 - jQuery('#micropost_content').val().length;
  jQuery('.countdown').text(remaining + ' characters remaining');
}

function micropostChange() {
  $('#micropost_content').change(updateCountdown);
}

function micropostKeyup() {
  $('#micropost_content').keyup(updateCountdown);
}

jQuery(document).ready(function($) {
  updateCountdown();
  micropostChange();
  micropostKeyup();
  jQuery(document).on('page:change', function($) {
    updateCountdown();
    micropostChange();
    micropostKeyup();
  });
});

Ответ 6

Здесь моя версия coffeescript, основанная на решении Adriano. Это игнорирует пробелы, не включает добавление пустых divs в представление, а также добавляет класс ошибки, когда вы попадаете в минус номера.

updateCountdown = ->
  text =  jQuery('#micropost_content').val()
  text = text.replace(/\s/g, '');   
  remaining = 140 - text.length
  jQuery('.countdown').text remaining + ' characters remaining'
  jQuery('.countdown').addClass 'alert alert-error' if remaining < 0
  jQuery('.countdown').removeClass 'alert alert-error' if remaining > 0

jQuery(document).ready ->
  jQuery('#new_micropost').append '<span class="countdown">140 characters remaining</span>'
  jQuery('#micropost_content').change updateCountdown
  jQuery('#micropost_content').keyup updateCountdown
  return

Ответ 7

Чтобы избежать минус-символа, я добавил этот предел в _micropost_form.html.erb, поэтому он останавливает вас на 140 символов:

<%= f.text_area :content, maxlength:140, placeholder: "Compose new micropost..." %>