Philip
Philip

Reputation: 3799

Counting class occurrences within a parent element

I'd like to be able to delete rows from a table with the additional check that a user must not be able to delete the last row in the table.

I have a table which is set up similar to this:

<table id="columns" class="dynamicadd">
    <thead><tr>
            <th>Period</th>
            <th>Result</th>
            <th>Show</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><select name="colperiod[]"><!-- options --></select></td>
            <td><select name="colresult[]"><!-- options --></select></td>
            <td><select name="colshow[]"><!-- options --></td>
            <td><a class="delete" href="#">X</a></td>
        </tr>
    </tbody>
</table>

I have a second table with a very similar structure, different ID, on the same page:

<table id="aggregate" class="dynamicadd">
    <thead><tr>
            <th>Period</th>
            <th>Result</th>
            <th>Show</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><select name="acolperiod[]"><!-- options --></select></td>
            <td><select name="acolresult[]"><!-- options --></select></td>
            <td><select name="acolshow[]"><!-- options --></td>
            <td><a class="delete" href="#">X</a></td>
        </tr>
    </tbody>
</table>

I then have some javascript for cloning rows: which is working.

I am interested in having a single row removing function that can work across the tables. If I need to add a new table, I'd like to be able to do so without having to add JavaScript. I can get this working if I use different classes for the "delete" option. However, this is my attempt at a single function that can delete rows from either table:

$(document).on ('click', '.delete', function (event) {
    event.preventDefault();
    // count the number of rows in the current table
    var delCount = $(this).closest('table').children ('.delete').length;
    console.log (delCount); // 0 ??
    if (delCount > 1)
    {
        $(this).closest ('tr').remove();
    }
    else
    {
        // don't delete the last row.
        $(this).effect ("shake", {distance: 5});
    }
});

The variable delCount is 0, which leads me to believe that there is something wrong with my selectors.

Upvotes: 0

Views: 42

Answers (2)

charlietfl
charlietfl

Reputation: 171679

Less complicated and more efficient to just check if the row has any siblings within the <tbody>;

$(document).on ('click', '.delete', function (event) {
    event.preventDefault();

    var $btn = $(this),// cache `$(this)` to avoid calling it more than once
        $row = $btn.closest('tr');

    if ($row.siblings().length)
    {
        $row.remove();
    }
    else
    {
        $btn.effect ("shake", {distance: 5});
    }
});

Upvotes: 2

Philip
Philip

Reputation: 3799

In writing this question, I did some "accidental learning".

.children should be .find:

$(document).on ('click', '.delete', function (event) {
    event.preventDefault();
    // count the number of rows in the current table
    var delCount = $(this).closest('table').find ('.delete').length;
    console.log (delCount);
    if (delCount > 1)
    {
        $(this).closest ('tr').remove();
    }
    else
    {
        // don't delete the last row.
        $(this).effect ("shake", {distance: 5});
    }
});

Edit:

For an explanation on how .children and .find differ, I found this explanation by mkyong which helped. tl;dr: .children looks one level down, .find does a full search of any child, grandchild, great... elements

Upvotes: 0

Related Questions