0

ユーザーがこのグループにstudent_group何人いるかを宣言する を追加するアプリケーションがあります。このスレッド(js2coffee.org 経由で coffeescript に変更)studentsの js を自分のアプリケーションで動作するように適応させようとしていますが、これまで js を学んだことも使用したこともないので、問題が発生しています。助けてくれてありがとう!

student_groups.js.coffee

# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
# 
# https://stackoverflow.com/questions/15130587/jquery-add-or-remove-table-row-based-on-inputs

emptyRow = ->
  row_i++
  @obj = $("<tr></tr>")
  @obj.append "<td><input type=\"text\" size=\"5\" value=\"" + row_i + "\"/></td>"
  @obj.append "<td><input type=\"text\" size=\"5\" name=\"mm" + row_i + "\" id=\"id_mm" + row_i + "\"\"/></td>"
  @obj.append "<td><input type=\"text\" size=\"5\" name=\"dd" + row_i + "\" id=\"id_dd" + row_i + "\"\"/></td>"
  @obj.append "<td><input type=\"text\" size=\"5\" name=\"ma" + row_i + "\" id=\"id_ma" + row_i + "\"\"/></td>"
  @obj.append "<td><input type=\"text\" size=\"5\" name=\"sr" + row_i + "\" id=\"id_sr" + row_i + "\" value=\"0\"\"/></td>"
# how many applications we have drawed now ?
refresh = (new_count) ->
  if new_count > 0
    $("#nos_header").show()
  else
    $("#nos_header").hide()
  old_count = parseInt($("tbody").children().length)
# the difference, we need to add or remove ?
  rows_difference = parseInt(new_count) - old_count
# if we have rows to add
  if rows_difference > 0
    i = 0

  while i < rows_difference
      $("tbody").append (new emptyRow()).obj
      i++
  else if rows_difference < 0 # we need to remove rows ..
    index_start = old_count + rows_difference + 1
    $("tr:gt(" + index_start + ")").remove()
    row_i += rows_difference
row_i = 0
$(document).ready ->
  $("#nos").change ->
    refresh $(this).val()

student_groups/new

<%= form_for(@student_group) do |f| %>

  <p>
    <%= f.label :name, "Enter a nickname for this group" %>
    <%= f.text_field :name, placeholder: "..." %>
  </p>  

  <p>
    <%= f.label :number_of_students, "How many students are in this group?" %>
    <!-- https://stackoverflow.com/questions/10038993/rails-and-forms-drop-down-with-range-of-numbers-and-unlimited -->
    <%= f.select :number_of_students, (0..60), :id => "nos" %>
  </p>

<table class="student_input_form">
  <tbody>    
    <tr>
      <td><%= f.label :name, "What is the student's name?" %></td>
      <td><%= f.label :gender, "What is the student's gender?" %></td>
    </tr>
      <%= f.fields_for :students do |builder| %>
        <%= render 'students/form', :f => builder %>
      <% end %>
  </tbody>
</table>

<%= f.submit "Submit", :class => 'big_button round unselectable' %>

<% end %>

そして最後に、「students/_form」

<tr id="nos_header" style="display:none">
  <td><%= f.text_field :name, placeholder: "..." %></td>
  <td><%= f.select :gender, ['Female', 'Male', 'Transgender'] %></td>   
</tr>

EDIT:@mu、あなたのコメントに対処するために:(1)フォーマットを修正しましたが、入力ボックスと出力は互いにほとんどまたはまったく関係がありません。SO でのテキスト/コードの書式設定に関するドキュメントを読みましたが、まだ何かがクリックされていないことは明らかです。申し訳ありません。(2) 開いたタグを取り出した<p>- 変更前の残り物だったと思います。指摘してくれてありがとう。(3) うまくいかないことについては、もっと明確にするべきでした。最初にリンクしたページで、これと同様の機能を目指しています。ユーザーが生徒数を入力すると、coffeescript が起動し、その多くの新しい生徒が入力されるのに適切な数のフィールドが表示されます。しかし、現時点ではそうはなっていません。ブラウザでエラーが発生しません (つまり、それ以外の場合は機能します)-しかし、学生の数を選択しても、ページ上で何も変化しません。ご協力いただきありがとうございます!

4

1 に答える 1

2

まず、js2coffee が作成した "CoffeeScript" は、予想どおり、かなりひどい CoffeeScript です。コードが実際に何をしているのかを理解せずに、ある言語から別の言語に音訳しただけのソフトウェアであることは明らかです。Web 開発を行う予定がある場合は、JavaScript (および必要に応じて CoffeeScript) を学習することを強くお勧めします。

コードに入ります。関数の内訳は問題ありませんが、関数の内部は非常に複雑です。

グローバル変数で追跡する必要はありませんrow_i。必要なインデックスをいつでも計算できるため、追跡する必要さえありません。だから私たちはそれを捨てて、それが起こらなかったふりをします.

メインの HTML は次のようになります。

<table class="student_input_form">
    <thead>    
        <tr>
            <th>Name</th>
            <th>Gender</th>
        </tr>
    </thead>
    <tbody>
    </tbody>
</table>

<thead>それが目的なので、テーブルヘッダーを の中に入れます<thead>。また、ヘッダー行が内側<tbody>にある場合は、実際の body を操作するときに +1/-1 の調整を多数行う必要があります<tr><th>ヘッダーにも使用できます。これにより、よりセマンティックな構造が得られ、スタイルの設定と操作が容易になります。

このemptyRow機能は大幅に簡素化することができ、また簡素化する必要があります。row_i引数として渡す必要があります。string + stringまた、CoffeeScript には文字列補間があるため、そのようなノイズは必要ありません。また、CoffeeScript で「here-strings」を使用することもできます。jQuery は、呼び出し時に HTML フラグメント全体を喜んで取得しますappend。これらの単純なことで、次のようなことができます。

emptyRow = (row_i) ->
    """
        <tr>
            <td><input type="text" size="5" value="#{row_i}"></td>
            ...
        </tr>
    """

これは、エスケープされた引用符と文字列連結の大きな混乱とは異なり、実際には読み取り可能です。パーシャルを<script>使用して を入力し、テンプレートとして使用することもできます。これにより、次のことが可能になります。

<!-- Your partial would go inside... -->
<script id="empty_row" type="text/x-template">
    <tr>
        <td><input type="text" size="5" value="{row_i}"></td>
        <td><input type="text" size="5" name="mm{row_i}" id="id_mm{row_i}"></td>
    </tr>
</script>

そして、次のようにemptyRow減少します。

emptyRow = (row_i) ->
    $('#empty_row').html().replace(/\{row_i\}/g, row_i)

実際のクライアント側のテンプレート ソリューションの方が優れていると思いますが、このような単純なケースでは、単純な正規表現マングリングで十分です。

refresh機能も大幅に簡素化できます。jQuery セレクターを数回使用する場合は、一度だけ計算して変数に保存することで、作業が楽になります。

$tbody = $('.student_input_form tbody');

上記の HTML 構造により、現在の行数を簡単に把握できます。

current_rows = $tbody.find('tr').length

引数として必要な数を取得します。

refresh = (need_rows) ->

新しい行を追加する必要がある場合は、範囲配列と組み合わせた単純なループを使用できます。

if(current_rows < need_rows)
    $tbody.append(emptyRow(i)) for i in [current_rows ... need_rows]

これ...は、Ruby Range の場合とほぼ同じであり、同時に 2 つのことが得られます。

  1. 新しい の正しい数<tr>
  2. 属性emptyRowが重複しないようにするための正しいインデックス値。id

行を削除する必要がある場合は、 jQuery の:gtセレクターをうまく活用できます。このセレクターは、末尾から数えるための負のインデックスを取ることができます (Ruby の配列のように...)。

else if(current_rows > need_rows)
    $tbody.find("tr:gt(#{need_rows - current_rows - 1})").remove()

-1私たちはまだ調整に行き詰まっていますが、それが人生です。

結果は素晴らしく、無駄がありません。

refresh = (need_rows) ->
    $tbody = $('.student_input_form tbody')
    current_rows = $tbody.find('tr').length

    if(current_rows < need_rows)
        $tbody.append(emptyRow(i)) for i in [current_rows ... need_rows]
    else if(current_rows > need_rows)
        $tbody.find("tr:gt(#{need_rows - current_rows - 1})").remove()

次に、すべてをクランクアップします。

$(document).ready ->
    $("#nos").change ->
        refresh(parseInt($(@).val(), 10))

parseInt呼び出しがここにあることに注意してください。これは、番号refreshであると想定できます。need_rowsまた、明示的な基数引数でparseInt呼び出されることに注意してください。使用するときは常に明示的な基数を指定して、 8 進数の驚きや同様の混乱を招かないようにしてください。parseInt

私のバージョンと元のバージョンを比較して、バグがどこにあったかを確認してください。

デモ: http://jsfiddle.net/ambiguous/qmVaK/


いくつかの教訓:

  1. 仕組みがわからない場合は、他人のコードを使用しないでください。
  2. CoffeeScript を作成する場合は、CoffeeScript を学び、CoffeeScript でコードを記述します。js2coffee のような翻訳ツールが存在することを忘れてください。
  3. ツールの仕組みを学びましょう。CoffeeScript と jQuery には、コードをよりコンパクトにして理解しやすくする便利な機能がたくさんあります。
于 2013-07-02T23:39:55.017 に答える