2013-07-01 33 views
0

我有一個應用程序,用戶在其中添加一個student_group,其中他們聲明此組中有多少個students。我試圖從這個thread(我通過js2coffee.org更改爲coffeescript)來調整js以與我的應用程序一起工作,但是我從來沒有學過或使用過js,所以我遇到了一些麻煩。謝謝你的幫助!將Coffeescript改編爲rails應用程序

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

;最後,`學生/ _form」

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

編輯:@mu,以解決您的評論:(1)有固定的格式,雖然輸入框a nd輸出之間幾乎沒有任何關係。我已閱讀關於在SO上格式化文本/代碼的文檔,但顯然還沒有點擊。道歉。 (2)拿出那個標籤<p> - 認爲這一定是變化前的剩餘物。感謝您指出。 (3)至於什麼不行 - 我應該更清楚。我的目標是在我最初鏈接的頁面上的功能類似於this。當用戶輸入學生人數時,咖啡文本應該投入並顯示適當數量的字段,以便輸入許多新學生。但是,目前尚未發生。我在瀏覽器中沒有收到任何錯誤(例如,所有內容其他都有效) - 但是當我選擇了學生人數時,頁面上沒有任何更改。謝謝你的幫助!

+0

(1)清理您的格式和縮進,以便您的代碼可讀。 (2)您不能在'

'內放置'

',因此您可能需要明確指出''之前有一個隱含的'

'。 (3)問題是什麼?有什麼不行嗎?在這種情況下,「不起作用」是什麼意思? –

+0

@ muistooshort,請參閱編輯。 – dax

回答

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>以內,那麼在使用真實身體<tr> s時,您必須進行一堆+ 1/-1調整。也可以使用<th>作爲標題。這爲您提供了更多的語義結構,使得樣式和工作變得更容易。

emptyRow功能可以而且應該大大簡化。您應該通過row_i作爲參數。而且,你在CoffeeScript中有字符串插值,所以你不需要所有的噪音。您也可以在CoffeeScript中使用「here-strings」,當您致電append時,jQuery很樂意接受一個完整的HTML片段;這些簡單的事情讓你做這樣的事情:

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) 

一個真正的客戶端模板解決方案會更好我想,但只是簡單的一點正則表達式mangling會爲這樣的簡單情況。

refresh函數也可以大大簡化。如果你打算使用jQuery選擇好幾次,讓你的生活,通過計算它只有一次,它保存在一個變量簡單:

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

上面的HTML結構,可以很容易地計算出有多少行我們目前有:

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

,我們得到了我們需要多少作爲參數:

refresh = (need_rows) -> 

如果我們需要添加新行,那麼你可以使用一個簡單的循環與範圍ARR結合AY:

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

...或多或少相同的,因爲它是一個Ruby的範圍,併爲我們提供了一次兩件事情:

  1. 正確數量的新<tr>秒。
  2. emptyRow的正確索引值,以便我們不會以重複的id屬性結尾。

如果您需要刪除的行,那麼你就可以很好地利用jQuery's :gt selector可以取負指數結束計數(就像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被稱爲明確的基數自變量,始終指定明確的基數時使用parseInt,以便您不會得到八進制驚喜和類似的混淆位。

歡迎您將我的版本與您的原始版本進行比較,以查看錯誤發生的位置。

演示:http://jsfiddle.net/ambiguous/qmVaK/


一些經驗教訓:

  1. 不要用別人的代碼,當你不明白它是如何工作的。
  2. 如果您要編寫CoffeeScript,請學習CoffeeScript並在CoffeeScript上編寫代碼。忘記像js2coffee這樣的翻譯工具存在,他們沒有真正的好處。
  3. 瞭解您的工具如何工作。 CoffeeScript和jQuery中有很多有用的東西可以使你的代碼更緊湊,更易於理解。
+0

謝謝,畝。我得到了[這個答案](http://stackoverflow.com/questions/17425446/js-rails-cant-get-this-form-working)從另一個問題(我剛剛報廢咖啡因,因爲我可以告訴它wasn轉換效果不錯 - 正如你所說的那樣,轉換工具並不能代替你知道你在做什麼:p)。歡呼你的幫助,我真的很感激它!我會比較這兩個,但我已經看到你是對的 - CoffeeScript非常精簡! – dax

相關問題