alec.tu
alec.tu

Reputation: 1757

jquery remove() does not work

I have the following list

<ul id="serial_list" class="list-group scroll">
    <li class="list-group-item template">template</li>
    <li class="list-group-item">SNID</li>
    <li class="list-group-item">abc</li>
    <li class="list-group-item">eee</li>
    <li class="list-group-item">SNID</li>
    <li class="list-group-item">abc</li>
</ul>

And I want to delete each item based on each element of an array.

Approach1:

numbers = ["SNID", "abc", "eee", "SNID", "abc"];
// find each li
var list = $(serial_list).find('li:not(.template)');

numbers.forEach(function(number) {
    $(list).each(function(index, item) {
        // console.log(number);
        if (number == $(item).html()) {
            $(item).remove();
            return false;
        }
    });
});

The expected result will be

<ul id="serial_list" class="list-group scroll">
    <li class="list-group-item template">template</li>
</ul>

However, the actual result is

<ul id="serial_list" class="list-group scroll">
    <li class="list-group-item template">template</li>
    <li class="list-group-item">SNID</li>
    <li class="list-group-item">abc</li>
</ul>

The number of times calling remove() is the same as the length of the array.

However, if I update the list when loop each number (Approach2) , the result is what I expect.

Approach2:

numbers = ["SNID", "abc", "eee", "SNID", "abc"];
var list;

numbers.forEach(function(number) {
    list = $(serial_list).find('li:not(.template)');
    $(list).each(function(index, item) {
        // console.log(number);
        if (number == $(item).html()) {
            $(item).remove();
            return false;
        }
    });
});

The result is expected, but this kills the performance.

Why the approach1 does not work?

I am curious about removing return false, since approach1 will work if the list have no duplicate item.

<ul id="serial_list" class="list-group scroll">
    <li class="list-group-item template">template</li>
    <li class="list-group-item">SNID</li>
    <li class="list-group-item">abc</li>
    <li class="list-group-item">eee</li>
    <li class="list-group-item">fff</li>
    <li class="list-group-item">ggg</li>
</ul>

Approach1:

numbers = ["SNID", "abc", "eee", "fff", "ggg"];
// find each li
var list = $(serial_list).find('li:not(.template)');

numbers.forEach(function(number) {
    $(list).each(function(index, item) {
        // console.log(number);
        if (number == $(item).html()) {
            $(item).remove();
            return false;
        }
    });
});

In this case, approach1 will work as I expect. Why the return false do not mess up in this case?

Thank you!

Upvotes: 2

Views: 234

Answers (6)

Taplar
Taplar

Reputation: 24965

var numbers = ["SNID", "abc", "eee", "SNID", "abc"];
var $list = $('#serial_list').find('li:not(.template)');

$list.filter(function(){
  return (numbers.indexOf(this.innerHTML) > -1);
}).remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="serial_list" class="list-group scroll">
    <li class="list-group-item template">template</li>
    <li class="list-group-item">SNID</li>
    <li class="list-group-item">abc</li>
    <li class="list-group-item">eee</li>
    <li class="list-group-item">SNID</li>
    <li class="list-group-item">abc</li>
</ul>

Upvotes: 0

Ruben  Yeghikyan
Ruben Yeghikyan

Reputation: 497

HTML

<ul id="serial_list" class="list-group scroll">
    <li class="list-group-item template">template</li>
    <li class="list-group-item">SNID</li>
    <li class="list-group-item">abc</li>
    <li class="list-group-item">eee</li>
    <li class="list-group-item">SNID</li>
    <li class="list-group-item">abc</li>
</ul>

JavaScript

var numbers = ["SNID", "abc", "eee", "SNID", "abc"];
// find each li
var list = $('#serial_list').find('li:not(.template)');

list.each(function(index, elem) {
    if (numbers.indexOf($(this).text()) != -1) {
        $(this).remove();
    }
});

Live Demo: http://jsfiddle.net/52Lckqob/

Upvotes: 0

Irvin Dominin
Irvin Dominin

Reputation: 30993

The return false breaks the each loop iteration.

Ref:

We can break the $.each() loop at a particular iteration by making the callback function return false. Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.

Remove it and will work fine.

Code:

numbers.forEach(function (number) {
    $(list).each(function (index, item) {
        if (number == $(item).html()) {
            $(item).remove();
        }
    });
});

Demo: http://jsfiddle.net/IrvinDominin/zurkd3hq/

Upvotes: 4

Karan
Karan

Reputation: 2112

remove return false; from Approach 1 and it will output as you want.

Upvotes: 0

Satpal
Satpal

Reputation: 133453

Since you are using $(item).remove(); you need to update the reference again in next iteration thus Approach 1 doesn't work

You can use filter() along with indexOf

var list = $(serial_list).find('li:not(.template)');    
list.filter(function(){
    return numbers.indexOf($(item).html()) > -1;
    //return $.inArray(numbers, $(item).html());
}).remove();

Upvotes: 1

Jai
Jai

Reputation: 74738

Can't just this has to be done:

$('#serial_list').find('li:not(.template)').remove();

instead of looping in the array.

Upvotes: 0

Related Questions