jQuery无限输入表单

时间:2011-08-31 11:38:53

标签: javascript jquery recursion

希望我的最后一个问题,虽然我不能确定......

我正在尝试生成一个表单,一旦输入数据,它就会创建一个用于输入数据的新区域。这似乎是一个非常微不足道的问题,我可以想到这样一种形式的几种可能用途(在应用程序上输入作业历史记录,输入可以联系到的电话号码列表等)。

输入数据后很容易创建一个新行,但是我找不到告诉这个新行的方法,当数据输入时,它应该创建另一行

为了简单起见,为了帮助获得我想要的外观,我正在为表单使用表格,每次输入任何内容到最后一行时,它都会创建一个新行。这是我正在使用的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不会崩溃(datepickers继续工作)......就好像永远不会调用“更改”方法一样。

想法?

1 个答案:

答案 0 :(得分:4)

我认为jQuery.delegate应该可以解决问题。它将事件处理程序“绑定”到现在或将来适合选择器的任何元素。

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