来自动态HTML表的jQuery循环的意外结果

I have a table that is created in PHP. This table is the result of a query and it generates several rows. Inside these rows are quite a few different elements, such as drop down menus (< select >s) check boxes, and text fields. I made a loop to go through the elements in jQuery and get the values, but it's not returning what I thought it would. This is a fairly complex situation, so I'm going to post the code and a fiddle to perfectly illustrate exactly what is happening, and what I expect to happen.

PHP

if(isset($_POST['aid'])) {  
    $aid = $_POST['aid'];
    $projects = getProjects($db);
    $members = getUserName($db);            
    try {
        $project_info = $db->prepare("
            SELECT  projects.id,
                    projects.project_name,                  
                    projects.pm,    
                    projects.apm,
                    projects.est_start,
                    projects.est_end,
                    projects.contact,                   
                    projects.trips,
                    projects.tasks,
                    projects.perc_complete,
                    projects.bcwp,
                    projects.actuals,
                    projects.cpi,
                    projects.bcws,
                    projects.bac,
                    projects.comments,
                    projects.status,
                    projects.project_revenue,
                    projects.profit_margin,
                    projects.pm_perc,
                    projects.audited         
            FROM projects
            WHERE account_id = ?                        
        "); 

        $project_info->bindValue(1, $aid, PDO::PARAM_STR);
        $project_info->execute();       

            echo "<table class='projects_contentTable'>";
            echo "<thead class='projects_editable_thead'>";             
            echo "<th class='content_th'>" . "Job #" . "</th>";
            echo "<th class='content_th'>" . "Project Name" . "</th>";
            echo "<th class='content_th'>" . "PM" . "</th>";
            echo "<th class='content_th'>" . "APM" . "</th>"; 
            echo "<th class='content_th'>" . "Est. Start" . "</th>";
            echo "<th class='content_th'>" . "Est. End" . "</th>";
            echo "<th class='content_th'>" . "Contact" . "</th>";
            echo "<th class='content_th'>" . "Trips" . "</th>";
            echo "<th class='content_th'>" . "Tasks" . "</th>";
            echo "<th class='content_th'>" . "% Complete" . "</th>";
            echo "<th class='content_th'>" . "BCWP" . "</th>";
            echo "<th class='content_th'>" . "Actuals" . "</th>";
            echo "<th class='content_th'>" . "CPI" . "</th>";           
            echo "<th class='content_th'>" . "Comments" . "</th>";  
            echo "<th class='content_th'>" . "Status" . "</th>";    
            echo "<th class='content_th'>" . "Project Revenue" . "</th>";   
            echo "<th class='content_th'>" . "Profit Margin" . "</th>"; 
            echo "<th class='content_th'>" . "PM%" . "</th>";   
            echo "<th class='content_th'>" . "Audited" . "</th>";
            echo "</thead>";

            echo "<tbody class='projects_editable_tbody'>";                  
            while ($row = $project_info->fetch(PDO::FETCH_ASSOC)) {             
                echo "<tr>";                            
                echo "<td class='projects_editable_content_td'>" . "<a href='#'>" . $row['id'] . "</a>" . "</td>";
                echo "<td class='projects_editable_content_td' contenteditable='true'>" . $row['project_name'] . "</td>";
                echo "<td class='projects_editable_content_td'>" . 
                        "<select id='table_edit_project_pm'>" . 
                            "<option value=''>" . $row['pm'] . "</option>" . 
                            "<option>" . "-----" . "</option>";
                        foreach($members as $key => $value) {
                            echo "<option value='".$key."'>" . $value . "</option>";            
                        } 
                echo "</select>";
                echo "</td>";               
                echo "<td class='projects_editable_content_td'>" . 
                        "<select id='table_edit_project_apm'>" . 
                            "<option value=''>" . $row['apm'] . "</option>" . 
                            "<option>" . "-----" . "</option>";
                        foreach($members as $key => $value) {
                            echo "<option value='".$key."'>" . $value . "</option>";            
                        } 
                echo "</select>";
                echo "</td>";               
                echo "<td class='projects_editable_content_td'>" . 
                    "<input type='text' id='table_edit_project_start' value='". $row['est_start'] ."'/>"; 
                echo "</td>";               
                echo "<td class='projects_editable_content_td'>" . 
                    "<input type='text' id='table_edit_project_end' value='". $row['est_end'] ."'/>";
                echo "</td>";               
                echo "<td class='projects_editable_content_td' contenteditable='true'>" . $row['contact'] . "</td>";
                echo "<td class='content_td'>" . $row['trips'] . "</td>";
                echo "<td class='content_td'>" . $row['tasks'] . "</td>";
                echo "<td class='content_td'>" . $row['perc_complete'] . "</td>";
                echo "<td class='content_td'>" . $row['bcwp'] . "</td>";
                echo "<td class='content_td'>" . $row['actuals'] . "</td>";
                echo "<td class='content_td'>" . $row['cpi'] . "</td>";             
                echo "<td class='projects_editable_content_td' contenteditable='true'>" . $row['comments'] . "</td>";
                echo "<td class='projects_editable_content_td'>" .
                        "<select>" .
                            "<option value=''>" . $row['status'] . "</option>" .
                            "<option>" . "-------" . "</option>" .
                            "<option>" . "On Hold" . "</option>" .
                            "<option>" . "In Progress" . "</option>" .
                            "<option>" . "Open" . "</option>" .
                            "<option>" . "Complete" . "</option>" .
                         "</select>"; 
                echo "</td>";
                echo "<td class='content_td'>" . $row['project_revenue'] . "</td>";
                echo "<td class='content_td'>" . $row['profit_margin'] . "</td>";
                echo "<td class='content_td'>" . $row['pm_perc'] . "</td>";
                echo "<td class='projects_editable_content_td'>";                                   
                    if ($row['audited'] == 'true') {
                        echo "<input type='checkbox' checked='checked'/>";
                    } else {
                        echo "<input type='checkbox'/>";
                    }
                echo "</td>";               
                echo "</tr>";               
            }
            echo "</tbody>";    
            echo "</table>";                
    } catch(PDOException $e) {
        die($e->getMessage());
    }   
} else {    
    echo 'could not load projects table';
}

jQuery

$('.projects_editable_tbody tr').each(function() {
        $('.projects_editable_content_td:not(:has(select)),option:selected').each(function() {
            saveEdits.push($(this).text());
        });
    }); 

    $.each(saveEdits, function(index, value) { 
        alert(index + ': ' + value); 
    });

OK end wall, so here is the fiddle to play with http://jsfiddle.net/U3nna/14/

Inside the fiddle I actually list the values I'm expecting and all you have to do is click the save button to see what is actually happening.

For those of you who don't want to use the fiddle, or perhaps can't here is your very brief summary.

I need to loop through the table and go through each table row. Inside each table row I need the text value from the < td >'s with the class " .projects_editable_content_td". Each of these values will be put into an array. However some of the values are not being stored, and also it seems that this loop does an extra iteration on the table. So sometimes I'm expecting 9 or 18 values, and I end up with 27 or 36, and the more I run it the worse it gets.

I'm wracking my brain but I can't seem to figure out why it wouldn't be picking up some of these elements text values. If anyone has the time to lend me a hand, i'd really appreciate it.

Change it so that you supply correct option values with each option (i.e. if you want Jane Doe to output Jane Doe then just use it for both the value and the content within the option).

You then need to add a third possibility for other inputs, so I'd probably just rearrange the way you're going about this to:

$('td', this).each(function() {
    var $input = $("select, input", this);
    if($input.length) {
        saveEdits.push($input.val());
    }
    else saveEdits.push($(this).text());
});

Note that I changed the selector too. It looks like you're using classes a lot where you don't need them. If you really need to use classes so much, maybe try and make them a little nicer to read too (use .projects-editable-content e.g., use dashed not underscores, and don't make them longer than they need to be).

The problem is you are getting only $(this).text() which misses the input (text/checkboxes) values Also one thing i notice that you have assigned the same id for morethan one elements , id is supposed to be unique for the html elements table_edit_project_start , table_edit_project_end

Try this

var saveEdits = [];
$('#save').click(function() {
    $('.projects_editable_tbody tr').each(function() { 
        $('.projects_editable_content_td:not(:has(select))>input')
            .each(function() {
              saveEdits.push($(this).val());
            });

        $('.projects_editable_tbody tr > .projects_editable_content_td:not(:has(select))')
            .each(function() {
              saveEdits.push($(this).text());
            });

    }); 
    $.each(saveEdits, function(index, value) { 
        alert(index + ': ' + value); 
    }); 
});

For duplicate value you can use the selector like :eq(index),:gt(index) so in the loop it will fetch the current tr's fields

var saveEdits = [];
$('#save').click(function() {
    $('.projects_editable_tbody tr').each(function(i) { 
        $('.projects_editable_tbody tr:eq('+i+') > .projects_editable_content_td:not(:has(select))>input')
            .each(function() {
              saveEdits.push($(this).val());
            });

      $('.projects_editable_tbody tr:eq('+i+') >.projects_editable_content_td:not(:has(select))')
            .each(function() {
              saveEdits.push($(this).text());
            });

   }); 
    $.each(saveEdits, function(index, value) { 
        alert(index + ': ' + value); 
    }); 
});

Fiddle