3

I have this code:

$(function() {
  $('.delete').click(function() {
    $(this).closest('li').remove();
  });

  $('#items').change(function() {
    if ($(this).is(':empty')) {
      alert('No more conditions');
    }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="items">
  <li><a href="#" class="delete">Delete me</a></li>
</ul>

As soon as I click on the link, I will get an empty UL but using .is('empty') on .change() event doesn't trigger the alert.

Is that the correct way to check whether the element is empty or not after the DOM changes? If not what would be the right one?

Note: the solution has to be compatible with older browsers like IE8

ReynierPM
  • 17,594
  • 53
  • 193
  • 363
  • Take a look at https://stackoverflow.com/questions/1091661/detect-element-content-changes-with-jquery – Alvaro Nov 14 '16 at 21:45

7 Answers7

3

How about this solution. Hope it helps!

$(function() {
  $('.delete').click(function() {
  $(this).closest('li').remove();
  if ($('#items li').length === 0) {
  alert('No more conditions');
  }
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<ul id="items">
  <li><a href="#" class="delete">Delete me</a></li>
</ul>
HenryDev
  • 4,685
  • 5
  • 27
  • 64
2

The change event cannot be used with a plain DOM element, it can only be used by an input type element. So to answer your question, no, that would not be the appropriate way to address this and will not work.

You should probably just include the check for existence inside of the event handler doing the removal.

$('.delete').click(function() {
    $(this).closest('li').remove();
    if ($('#items').is(':empty')) {
        alert('No more conditions');
    }
});

An alternative approach would be to setup a Mutation Observer for your specific items element, but perhaps that would be overkill if simply checking after each removal suffices.

Travis J
  • 81,153
  • 41
  • 202
  • 273
  • While good information, your code does not work. The issue is that the `:empty` selector is not valid for the `#items` element. Thus, the condition in the `if` does not evaluate to `true`, and the `alert()` is never executed. – Makyen Nov 14 '16 at 21:50
  • @Makyen - You are [wrong](https://jsfiddle.net/bubc2p41/). Note that it *does* work for this element type, and what you seem to be seeing is a false result from whitespace (which is then not empty). It was a good guess, but in the future you may want to be a little more thorough. – Travis J Nov 14 '16 at 21:55
  • 1
    I put your code in a snippet and tried it prior to making the comment. The `
  • ` is deleted, but the `alert()` is not fired.
  • – Makyen Nov 14 '16 at 21:57
  • @Makyen - You are just making it worse on yourself. You are **wrong**. This code does what it is supposed to do; that the empty selector returns false when there is excessive whitespace is another issue that has to do with element composure. Your conclusions being drawn here are really based in poor assumptions. – Travis J Nov 14 '16 at 22:00
  • 2
    I suggest you try it yourself: [JSFiddle](https://jsfiddle.net/wcr5c8gL/) – Makyen Nov 14 '16 at 22:02
  • @Makyen - Did you see the example above, or do you simply not read and plow along. This is the example I already gave you: https://jsfiddle.net/bubc2p41/ . Stop trolling. – Travis J Nov 14 '16 at 22:03
  • 1
    Of course I saw the example you linked. Did you bother to try the JSFiddle example of your code which I linked? The example I linked is a cut & paste of the code from your answer with the HTML from the Question. When clicked, the `.delete` `
  • ` is deleted, but the `alert()` does not show (in Chrome, Edge, IE11, or Firefox). Your code does not work in the situation in which the OP has described in the question. I would suggest that you refrain from ad hominem arguments and just stick to the facts.
  • – Makyen Nov 14 '16 at 22:16
  • This is one of those were your both kind of right!!.. So shake hands.. :) `':empty'` does indeed work on #items, but it does require the HTML markup (DOM), be void of any whitespace. So in this respect I would say this is not the ideal way to check,. eg. If you went and made a library using this, it would be wrong to tell your users it only works after your HTML has gone through minification. – Keith Nov 14 '16 at 22:20
  • @Keith - When the dom is composed dynamically as opposed to statically (as is the implication in this scenario) then you can be guaranteed to not have whitespace. There is no need for minification. – Travis J Nov 14 '16 at 22:43
  • @TravisJ I agree, if your creating your DOM dynamically via Javascript it's a none issue, but often users also create server side dynamic pages using templating engines, and again whitespace is often present. IOW: From my POV I just think doing Dom children count way just seems more reliable. – Keith Nov 14 '16 at 22:57
  • @Keith - In general, I prefer class names for filtering, and that is the approach I would use here if this was something I was designing. That said, it just depends on composition. Aside from whitespace, there is nothing wrong with the OP using empty so long as it was working with their solution, the main issue was the event handler here. – Travis J Nov 14 '16 at 23:14
  • @TravisJ, I assume you are talking about my comment: "... the selector `:empty` is not valid for the `#items` element". A) That is a comment on another answer suggesting how that answer might be improved, which it would be improved if they explained why. B) In the context I stated that, the element `#items` does not match the selector `:empty`. Thus, it is not a "valid" test for determining *what is desired by the OP*, under the conditions specified. The writer of that answer had already determined that it was not a valid test, for what was desired, I merely suggested that *why* be explained. – Makyen Nov 14 '16 at 23:40
  • You claim I argued `:empty` does not work on some element types. I have not stated that. I have said it is not valid to use *in this situation* for what the OP desires: test that no `
  • ` exist. What I had hoped for from a person with your experience was that you would actually test your code, in this situation, and see that it does not work; that you would then change your code to be functional for the way the OP has described using it, and explain *why* testing for `:empty` the way the OP was doing does not work (the continued presence of one or more `#text` nodes after the `.remove()`).
  • – Makyen Nov 14 '16 at 23:40