views:

74

answers:

3

I have this piece of code

// TR Fading when deleted
$('.delete').live('click', function() {
    $.ajax({
    type: 'POST',
    url: 'history/delete/id/'+$(this).attr('id')
    });
    $(this).closest('tr').fadeOut('slow', function() {
        $(this).remove();
        if($(this).closest('table').find('tbody').is(':empty'))
            $('#latest').remove();
    });
    return false;
});

It triggers when I want to delete a table row through the delete button (as shows the image) image

It may happen that the table becomes empty of table rows. I want to delete the whole table when this occurs, but the table isn't being removed. The line code $(this).remove(); works and this seems to refer to the tr element in that scope 'cause the whole row is being removed but the next 2 lines doesn't work. The table isn't being removed.

EDIT

I changed the if($(this).closest('table').find('tbody').is(':empty')) to if(!$(this).closest('table').find('tbody').is(':empty')) (exclamation mark) to see if it removes and it removed the whole table, but I inspected the table element before and after deleting the last row and got this

image

JS says that tbody is not empty, google chrome says otherwise. I don't know how to fix it

A: 

Try changing:

$(this).remove();
if($(this).closest('table').find('tbody').is(':empty'))
    $('#latest').remove();

To:

var table = $(this).closest('table');
$(this).remove();
if(table.find('tbody').is(':empty'))
    table.remove();

I think when you're doing $(this).closest you've already lost the reference to the element as you've just removed it from the DOM.

roguepixel
This won't work...see my answer on why `:empty` isn't doing what you think here :)
Nick Craver
Yap, does not work.
jAndy
@Nick - Yeah saw your answer afterwards, good call.
roguepixel
+1  A: 

It looks like remove() and detach() do leave some kind of crud behind after they remove a tr element. It's like a whitespace or a linebreak, so since the :empty selector also checks for textnodes, it's not empty at all.

so

if($('#latest tbody').children().length() < 1)
   $('#latest').remove();

should do the trick.

Reference: http://jsbin.com/esaye3/2/edit

update

Like Nick Craver mentioned, this behavior is caused by the HTML markup itself.

<tbody><tr><td>Something</td><td>Anything?</td><td><button class="delete">delete</button></td></tr></tbody>

for instance, WILL work with :empty aswell.

jAndy
Yep! there is also http://jsfiddle.net/ which I think is better
Rodrigo Alves
Your way also worked! Thanks
Rodrigo Alves
+2  A: 

The problem is that once you remove it, relative selectors like .closest() won't do anything, since that element doesn't have a parent anymore. Also :empty isn't working because it includes text nodes, from the docs:

Select all elements that have no children (including text nodes).

So :empty won't match if there's any white-space left (alert or log $("latest tbody").html()) to see what I mean), which is almost certainly the case, the same goes for my example below. Instead you can use :has(tr) to check for table rows, and :not() to negate that, like this:

$('.delete').live('click', function() {
    $(this).closest('tr').fadeOut('slow', function() {
        $(this).remove();
        $("#latest tbody:not(:has(tr))").parent().remove();
    });
    return false;
});

You can view a quick demo here, if the :not(:has(tr)) selector doesn't match anything...and it won't if there's not a row-less <tbody>, it just won't remove anything.

Nick Craver
@Nick: `which is likely the case.` why is that likely the case? It looks like `remove()` itself creates a whitespace ?
jAndy
@jAndy - There was whitespace before the `.remove()`...unless your `<tr>` elements budded right up to each other (no new-line characters) this will be the case, most pages render a row per line though, leaving at least a `\n` in there...remove doesn't remove this text node, just the `<tr></tr>` you told it to :)
Nick Craver
@Nick: I told it just because out of testing, I had/have not explanation why that is the case.
jAndy
@Nick: Ok, I got it. It's really caused because of the markup. Concatenating all together works with `:empty`.. doh what a mess!
jAndy
@jAndy - Yup, for anyone interested, here's a comparison of `.children().length` (number of `<tr>`) to `.contents().length` (all children, what `:empty` checks): http://jsfiddle.net/ZmJqS/2/
Nick Craver