2011-08-31 87 views
1

希望我的一小會兒最後一個問題,雖然我不能肯定......jQuery的無限輸入表格

我試圖產生,即一旦數據被輸入其輸入創建一個新的區域形式數據。這似乎是一個非常微不足道的問題,我可以想到這種形式的幾種可能用途(在應用程序中輸入作業歷史記錄,輸入可以到達的電話號碼列表等)

這很容易創建一個新的行一旦輸入數據,但是我無法找到一個方法來告訴這個新行,當數據被輸入到,它應該創建另一個一行。

爲了簡單起見,並幫助得到我想要的樣子,我使用的是表我的形式,每次在任何輸入到最後一排它會創建一個新的行。下面是我使用的HTML:

<table> 

    <tr> 
     <th>Field 1</th> 
     <th>Field 2</th> 
     <th>Field 3</th> 
    </tr> 

    <tr> 
     <input type="hidden" name="id-row-0" value="0" /> 
     <td><input type="text" name="field1-row-0" value="" /></td> 
     <td><input type="text" name="field2-row-0" value="" class="date-field" /></td> 
     <td><input type="text" name="field3-row-0" value="" /></td> 
    </tr> 

</table> 

然後,我有以下的javascript:

$.spreadsheet = { 
    fields : $('#myForm').find('input,textarea,select'), // list of input HTML elements 
    rows : $('#myForm').find('tr').length - 1, // number of rows currently. Subtract 1 for table headers 
    columns : $('#myForm').find('tr')[0].cells.length // number of fields pulled from the database 
} 

$($.spreadsheet.fields).find('input,textarea,select').change(function() { 

    var index = $.spreadsheet.fields.index($(this)); 
    var row = Math.floor(index/$.spreadsheet.columns); 

    if(row == $.spreadsheet.rows - 1) { 
     // Last row was changed. Do we add a new row? 
     if($(this).val() != '') { 

      // A value was added. We ned a new row 
      new_row = $("input[name=id-row-"+row+"]").parent().clone().appendTo("#myForm table"); 

      // Now we need to change the name of every element in this row to reflect the new row number 
      new_row.find('input,textarea,select').each(function() { 
       partial_name = this.name.substring(0, this.name.indexOf('-row-'+row)); 
       this.name = partial_name + '-row-' + (row+1); 

       // If it was a datepicker before then the id will cause all sorts of issues 
       this.id = ''; 
       $(this).removeClass('hasDatepicker'); 
      }); 

      // Create date pickers 
      new_row.find('.date-field').datepicker({ dateFormat: "yy-mm-dd", changeMonth: true, changeYear: true }); 

      // Recursively set this function for change()? 
      // Help, guys =(

      // Update the total number of rows 
      $.spreadsheet.rows += 1; 
     } 
    } 

}); 

// Create date pickers 

$(".date-field").datepicker({ dateFormat: "yy-mm-dd", changeMonth: true, changeYear: true }); 

正如你所看到的,我不知道如何遞歸設置此功能爲回調.change()。我試着做類似以下的事情:

function add_new_row = function() { 
    ... 
    // Recursively set this function for change()? 
    new_row.find('input,textarea,select').change(add_new_row); 
    ... 
} 

$($.spreadsheet.fields).find('input,textarea,select').change(add_new_row); 

但它沒有奏效。 JavaScript不支持任何形式的遞歸嗎?如果不是,我們如何解決這個困境?

在@ J0HN的建議使用.delegate()後,這裏是我現在的JavaScript文件中的全部:

$(document).ready(function() { 

$.spreadsheet = { 
    fields : $('#myForm').find('input,textarea,select'), // list of input HTML elements 
    rows : $('#myForm').find('tr').length - 1,   // number of rows currently. Subtract 1 for table headers 
    columns : $('#myForm').find('tr')[0].cells.length,  // number of fields pulled from the database 
} 

// Add new rows 

$("#myForm").delegate("input, textarea, select", "change", function() { 

    var index = $.spreadsheet.fields.index($(this)); 
    var row = Math.floor(index/$.spreadsheet.columns); 
    var col = index % $.spreadsheet.columns; 

    if(row == $.spreadsheet.rows - 1) { 

     // Last row was changed. Do we add a new row? 

     if($(this).val() != '') { 

      // A value was added. We ned a new row 
      // This row should look just like the previous... A CLONE, one might say? 

      new_row = $("input[name=id-row-"+row+"]").parent().clone().appendTo("#myForm table"); 

      // Now we need to change the name of every element in this row to reflect the new row number 

      new_row.find('input, textarea, select').each(function() { 

       partial_name = this.name.substring(0, this.name.indexOf('-row-'+row)); 
       this.name = partial_name + '-row-' + (row+1); 

       // We can't initialize a datepicker if it thinks one is already initialized 

       $(this).removeClass('hasDatepicker'); 
       this.id = ''; 

      }); 

      // Create date pickers 

      new_row.find('.date-field').datepicker({ dateFormat: "yy-mm-dd", changeMonth: true, changeYear: true }); 

      // Update the total number of rows 

      $.spreadsheet.rows += 1; 

     } 

    } 

}); 

// Create date pickers 

$(".date-field").datepicker({ dateFormat: "yy-mm-dd", changeMonth: true, changeYear: true }); 

}); 

當我鍵入一些數據到第一排它成功增加了一個新的行,符合市場預期。使用Chrome的「檢查元素」功能,我可以檢查這些新元素的行號,它們都看起來是正確的,日期選擇器甚至可以正常工作。

但是當我輸入數據到這個新行沒有任何反應。沒有行被添加,沒有錯誤,JavaScript不會崩潰(日期選擇器繼續工作)......就好像「更改」方法從不被調用。

想法?

+0

請記下這個功能「add_new_row」 – cvsguimaraes

+0

沒有通過一串代碼去,如果我理解正確的,一個可能的解決方案是使用事件委託。將事件處理程序綁定到祖先並偵聽輸入字段的更改事件。如果觸發更改的字段是最後一個字段(或包含在最後一行中),請附加一個新字段(行)。 –

+0

@cvsguimaraes,'add_new_row'是(spreadsheet.fields $)的先前傳遞給'$功能的精確副本.find( '輸入,文本區域,選擇')。變化()'。我認爲,從上下文來看,這很明顯,以及上面評論的重用。 – stevendesu

回答

4

我覺得jQuery.delegate應該做的伎倆。它將事件處理程序「綁定」到現在或將來將選擇器進行套接的任何元素。

$("#myform").delegate("input, textarea, select", "change", function(){ 
    //place row adding logic here 
}); 
+0

+1正是我的想法。演示:http://jsfiddle.net/p4FP2/ –

+0

也看看做相同的live()函數。 – Ali

+0

據我瞭解,'live'有沃瑟performanse,不允許阻止事件的傳播,並有一些其他drabacks。所以,請使用'委託'代替。 – J0HN