Reputation: 386
I make Chrome extension for removing li elements from specific UL.
for example i have
<ul>
<li id="1"><div class="l1"><p>test1</p></div></li>
<li id="2"><div class="l1"><p>test2</p></div></li>
<li id="3"><div class="l1"><p>test3</p></div></li>
.... and so on
</ul>
I have array of 3500 items(like database) which on every page reload checks this ul for matches and removes them.
my jQuery code is like this:
var remove = function remove(items){
$.each(items, function(index,value){
if( $("div.l1 p").filter(function() { return $(this).text() == value; }).length ) // if there is match {
$("div.l1 p").filter(function(){ return $(this).text() == value; }).parent().parent().remove(); // delete li element
}
}
}
and i call it like:
var initi = function initi() // called when page is loaded
{
remove(Array("test1","test2","test3",...,"testonemilion"));
}
my problem which happens is sometimes chrome randomly runs out of memory and requires reloading the page. I think this will happen more often when "database" becomes bigger.
so i wanted to ask are there possible ways to optimize my jQuery function, to lower that memory stress?
i use latest chrome 40.0.2214.115 m and have 8GB RAM on my computer(which never gets to 100%)
Thanks!
EDIT: Also are there debugging tools which will display how different versions of function will perform(for example function1() executes for 1 sec, function2() executes for 0.8sec and so on)
Upvotes: 1
Views: 80
Reputation: 171679
You could use filter()
to see if text is in an array and therefore only loop through the elements once instead of many times as you are doing
var remove = function remove(items){
$("div.l1 p").filter(function(){
return $.inArray( $(this).text(), items) !==-1;
}).parent().parent().remove();
}
Upvotes: 3
Reputation: 36784
Your code can be made more efficient. Since filter()
will return an object with the matching elements, there is no need for your if
statement.
You should also keep your jQuery object by in a variable, to save having to select all your paragraphs for every iteration of your .each()
method.
var remove = function remove(items){
var $p = $("div.l1 p");
$.each(items, function(index,value){
$p.filter(function(){
return $(this).text() == value;
}).parent().parent().remove();
}
}
}
Having said that, this won't make things much quicker for you; 3500+ elements is a lot of elements to loop through by any measure. Paginate your results.
Upvotes: 1
Reputation: 131
You are running 2 filters and then accessing the parent's twice of each filter.
Is it possible that you could do:
<ul>
<li id="1" class="test1"><div class="l1"><p>test1</p></div></li>
<li id="2" class="test2"><div class="l1"><p>test2</p></div></li>
<li id="3" class="test3"><div class="l1"><p>test3</p></div></li>
.... and so on
</ul>
OR
<ul>
<li id="1" data-text="test1"><div class="l1"><p>test1</p></div></li>
<li id="2" data-text="test2"><div class="l1"><p>test2</p></div></li>
<li id="3" data-text="test3"><div class="l1"><p>test3</p></div></li>
.... and so on
</ul>
This way you could use simple selectors on the LIs that you actually want to remove?
var remove = function remove(items){
$.each(items, function(index,value){
$('.'+value).remove();
});
}
Upvotes: 1