1

I have a div which contains several li elements. Each li has a close icon. Once you click on it, the entire li item related to it is then removed.

However, once all li elements have been removed, then div still remains. In my project, it has a background-color so when li elements have been removed, then empty div area is visible.

I have tried all options on this link, but none of them worked. Remove class when no inner elements exist

HTML code:

<div class="divArea">
    <li class="li-item" id="li-item1">Item 1 <span class="icon icon-close 
item-close" id="item-close1"></span></li>
    <li class="li-item" id="li-item2">Item 2 <span class="icon icon-close 
item-close" id="item-close2"></span></li>
</div>

Jquery code:

$( "#item-close1" ).click(function() {
    $("#li-item1").remove();
});
$( "#item-close2" ).click(function() {
    $("#li-item2").remove();
});

How can I make it that when the last li element has been removed, then div area will be removed as well?

rrrrrauno
  • 41
  • 1
  • 7

6 Answers6

3

Have a function that checks, which is called from each handler:

function removeAndRemoveParentIfEmpty(element) {
    var parent = element.parent();
    element.remove();
    if (!parent[0].firstElementChild) {
        parent.remove();
    }
}

each of you rhandlers would call it like this:

$( "#item-close1" ).click(function() {
    removeAndRemoveParentIfEmpty($("#li-item1"));
});

Side note: Rather than using ids, just use the structure of the list. Among other things, that means you can hook up a single handler (to the list) and then handle this in that single handler:

$(".divArea").on("click", ".item-close", function() {
    var $this = $(this);
    var li = $this.closest("li");
    var parent = li.parent();
    li.remove();
    if (!parent[0].firstElementChild) {
        parent.remove();
    }
});

Side note 2: Your HTML is invalid. You can't have li as a direct child of div, it can only be the direct child of ul or ol (or template, but...). You'll need to fix that as well.


Live example fixing the markup and using the non-id event delegation solution:

$(".divArea").on("click", ".item-close", function() {
    var $this = $(this);
    var li = $this.closest("li");
    var parent = li.parent();
    li.remove();
    if (!parent[0].firstElementChild) {
        parent.remove();
    }
});
.divArea {
    border: 1px solid black;
}
<ul class="divArea">
    <li class="li-item">Item 1 <span class="icon icon-close 
item-close">[x]</span></li>
    <li class="li-item">Item 2 <span class="icon icon-close 
item-close">[x]</span></li>
</ul>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
0

Simply check that the item is the last:

$( "#item-close1" ).click(function() {
    if ($(".divArea > li").length === 1) {
      $("#li-item1").remove();
    } else {
      $(".divArea").remove();
    }
});
Mosè Raguzzini
  • 12,776
  • 26
  • 36
0
$( "#item-close1" ).click(function() {
    $("#li-item1").remove();
    // check if there are any other <li>'s
    if(!$(this).parent().find("li").length){
        // if not, remove the parent element
        $(this).parent().remove();
    }
});

That said, your markup is semantically incorrect. All <li>'s must be a child of either a <ul> or an <ol> or a <menu>.

See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li

I wrestled a bear once.
  • 19,489
  • 16
  • 63
  • 110
0

Firstly, note that your HTML is invalid. You cannot have an li as a child of a div. They need to be within a ul. This changes your logic slightly, as you need to determine if the ul is then empty when an li is removed, and if so, remove the parent div.

Secondly, don't use incremental id attributes. They end up making you repeat your code, or make it more convoluted. Use the common classes on the elements instead and traverse the DOM to find the related elements.

With regard to the actual issue, after removing an li, check the length of the children() of the ul and then remove the div if none remain. Try this:

var $div = $('.divArea');
var $ul = $div.find('ul');

$(".item-close").click(function() {
  $(this).closest('.li-item').remove();
  if ($ul.children().length === 0)
    $div.remove();
});
ul {
  border: 2px solid #C00;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="divArea">
  <ul>
    <li class="li-item">
      Item 1
      <span class="icon icon-close item-close">X</span>
    </li>
    <li class="li-item">
      Item 2
      <span class="icon icon-close item-close">X</span>
    </li>
  </ul>
</div>

Note that the :empty selector would be an alternative, but due to the textNodes between the element tags, resulting from the line breaks in your HTML, it won't work in this case.

Rory McCrossan
  • 306,214
  • 37
  • 269
  • 303
0

Tested and this works Use a shape like this: Note: I fixed your html to include the

<div class="divArea">
  <ul class="lis">
    <li class="li-item" id="li-item1">Item 1 <span class="icon icon-close item-close" id="item-close1"></span></li>
    <li class="li-item" id="li-item2">Item 2 <span class="icon icon-close item-close" id="item-close2"></span></li>
  </ul>
</div>

js

$( ".lis .li-item" ).on( "click", function() {
   var litm = $( this );
   litm.remove();
   var items = $(".lis").children().length;

  if (items == null || items <= 0) {
    $(".divArea").remove();
  }

});
Joe Johnston
  • 2,218
  • 1
  • 25
  • 48
-1

I'm not 100% sure what situation are you facing, but here is some code fixing:

$(document).ready(function(){
  $( "#item-close1" ).click(function() {
   $("#li-item1").remove();
  });
  $( "#item-close2" ).click(function() {
   $("#li-item2").remove();
  });  
  $(".divArea").each(function() {
     if($(this).children().length == 0) {
       $(this).remove();
     }
  });
});
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head

<body>

<div class="divArea">
    <li class="li-item" id="li-item1">Item 1 <span class="icon icon-close item-close" id="item-close1">X</span></li>
    <li class="li-item" id="li-item2">Item 2 <span class="icon icon-close item-close" id="item-close2">X</span></li>
</div>

</body>

Is this what you want?

Pablo D.
  • 164
  • 1
  • 2
  • 9