Reputation: 7717
I've got a large table that lists out approximately 50 users and some simple data around their accounts, including the number of "projects" they have. When clicking on a user row more rows expand beneath to reveal detailed information about each of their projects. Most users have fewer than 20 projects, so it's not terribly taxing on the browser. However, there are a few users that have 100+ projects (one with 500+) and when clicking on the user row the browser stalls for anywhere from 1-4 seconds.
The table rows are set up so that any row with the .project
class is hidden by default, and when clicking on a user row (no .project
class) all subsequent rows with the .project
class have the class .open
added which displays them.
Suggestions on how to make this run faster? Is there a better, cleaner way to achieve the same effect?
Here is a simplified version of the HTML:
<table>
<tr>
<td>Username</td><td>Email</td><td>10 Projects</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr>
<td>Username</td><td>Email</td><td>3 Projects</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
<tr class="project">
<td> </td><td> </td><td>Project Name</td>
</tr>
</table>
... and the JS:
(function($) {
$.fn.viewProjects = function() {
this.each(function() {
$(this).click(function(){
var projects = $(this).nextUntil(':not(.project)'); // get all rows that follow and have the '.project' class
if ($(this).hasClass('focused')) { // collapse
$(this).removeClass('focused');
projects.each(function(n, proj){
$(proj).removeClass('open');
});
}
else { // expand
$(this).addClass('focused');
projects.each(function(n, proj){
$(proj).addClass('open');
});
}
});
});
};
$('tr:not(.project)').viewProjects();
})(jQuery);
Upvotes: 0
Views: 130
Reputation: 10743
This is because the DOM is loading so much added stuff in to it. What I do in similar situations is:
Alternatively, you can automatically trigger the next 50 rows to load when the user scrolls down the page. I prefer showing a link because automatically loading stuff can be confusing.
Edit - What if you use jQuery to show and hide the contents instead of adding and removing a class each time?
if ($(this).hasClass('focused')) { // collapse
$(this).removeClass('focused');
projects.hide();
}
else { // expand
$(this).addClass('focused');
projects.show();
}
Upvotes: 2
Reputation: 17743
Instead of showing/hiding 500 items, show/hide one:
Restructure the HTML into something like this:
<table>
<tr>
<td>Username</td><td>Email</td><td>10 Projects</td>
</tr>
<tr class="project">
<td colspan="3">
<ul>
<li>Project Name</li>
<li>Project Name</li>
<li>Project Name</li>
<li>Project Name</li>
<li>Project Name</li>
<li>Project Name</li>
<li>Project Name</li>
<li>Project Name</li>
<li>Project Name</li>
</ul>
</td>
</tr>
Upvotes: 0
Reputation: 29714
You don't need the each. the click function in Jquery is chainable This may speed it up:
(function($) {
$.fn.viewProjects = function() {
$(this).click(function(){
var projects = $(this).nextUntil(':not(.project)'); // get all rows that follow and have the '.project' class
if ($(this).hasClass('focused')) { // collapse
$(this).removeClass('focused');
projects.each(function(n, proj){
$(proj).removeClass('open');
});
}
else { // expand
$(this).addClass('focused');
projects.each(function(n, proj){
$(proj).addClass('open');
});
}
});
};
$('tr:not(.project)').viewProjects();
})(jQuery);
Upvotes: 0
Reputation: 6029
You can check webworker to create threads to improve performance. I know this is a vague one, but i want to suggest this direction.
Unfortunately we cannot manipulate DOM inside webworkers. But DOM can be manipulated on your client code.
It appears that you are making XMLhttprequest to get new data, and this can be done inside webworkers.
Upvotes: 0