Reputation: 24739
We have a part of our web app that displays a list of actionable items ("Jobs") needing to be worked on. Our model of each Job looks like this:
{
"JobUID": Number,
"State": "String",
"FirstName": "String",
"LastName": "String",
"DateOfBirth": "dateTime",
"DateReceived": "dateTime",
"LastWorked": "dateTime",
"UserName": "String",
"ProblemText": "String",
"AssignedTo": "String",
"DateAdded": "dateTime",
"CallOutStatusUID": Number,
"Notes": [
{
"NoteUID": Number,
"EntityUID": Number,
"Content": "String",
"UserName": "String",
"EntityTypeUID": Number,
"CreatedDateTime": "dateTime"
}
]
}
There can be 0..n Notes
. We ask a service through AJAX for all these jobs and use them to fill out a table. We're using the jQuery TableSorter plugin on the table these jobs are going into.
Recently the list has grown to 735 of these jobs with a total of 907 Notes, fiddler reports 450 KB of data was transferred. The table is on a different tab than the starting tab of the page. When you click on the tab that will display this table, IE freezes. To clarify, these are HTML tabs all on one page inside of IE. They are not multiple IE tabs.
IE does not steadily grow in memory when you try to switch tabs (it sits at about 98MB). The process sits at 13% processor usage (on an 8 core machine, which tells me that it's doing everything on a single core since 13% is ~1/8). The process never starts responding again and must be closed with task manager. When hooked to Visual Studio 2012, if I attempt to pause and debug while it's like this, VS reports that it's currently in Native Code. I tried setting a javascript breakpoint before the freeze and stepping into the freeze, but other than a few behind the scenes jquery calls, it does seem to actually be hanging in Native Code.
Our quick fix for awhile was to only show 200 of the jobs at a time and it worked but we want a way to be able to display all jobs. I started working with TableSorter's Pager plugin but it didn't help. The sorter is set to only show 10 rows per page. If, before attempting to change tabs, I check how many rows are in that table, it successfully reports 12 (10 rows per page + 1 header row + 1 filtering row).
Here's how I set up the table (problems
is an array of the above model):
for (var i = 0; i < problems.length; i++) {
var style = "odd";
if (i % 2) { style = "even"; }
var problem = problems[i];
rows += "<tr class='" + style + "'><td>";
rows += problem.FirstName;
rows += "</td><td>";
rows += problem.LastName;
rows += "</td><td>";
rows += problem.DateOfBirth
rows += "</td><td>";
rows += problem.ProblemText;
if (problem.CallOutStatusUID != null) {
rows += " - " + GetType(callOutStatus, problem.CallOutStatusUID).Display;
}
rows += "</td><td style='text-align:center;width:30px'>";
if (problem.Notes.length > 0) {
rows += "<a href='#' onclick='getNotes_click(this, \"JobUID\", GetJob, problems);' id='notes-" + problem.JobUID + "' JobUID='" + problem.JobUID + "' class='lnk_Notes'><img src='images/icon_note.png'></a>";
}
rows += "</td><td>";
if (problem.AssignedTo != null && problem.AssignedTo.toUpperCase() != userName.toUpperCase() && problem.State.toUpperCase() == "WORKING") {
rows += "<a href='imageviewer?JobUID=" + problem.JobUID + "'>Read Only</a>";
}
else {
rows += "<a href='imageviewer?JobUID=" + problem.JobUID + "'>Get Work</a>";
}
rows += "</td><td>";
rows += problem.LastWorked;
rows += "</td><td>";
rows += problem.AssignedTo;
rows += "</td><td>";
rows += problem.DateReceived;
rows += "</td></tr>";
}
$("#ListOfJobs tbody").html(rows).trigger('update');
Oddly enough, when setting up this same scenario in our dev environment (instead of prod where we found the problem), we could have upwards of 1000+ jobs with over 2000+ total notes and it would display properly. I've tried deleting the large array after it's put into the DOM but nothing changes. I've also tried deleting rows
but again, nothing. There are multiple tabs other and I can switch between all tabs freely and the page seems to work up until I try to open the tab containing this table. Changing browsers is not an option. I can't even test in other browsers because our AJAX calls mess up in them and we can't reach this point where we have all the data and want to switch tabs. We don't support IE<10. We do have one dev running IE11 and it also breaks in exactly the same way.
What's causing IE to freeze?
EDIT: I tried changing the last line so that it didn't call the trigger and now the tab loads just fine. Anybody know enough about TableSorter to know why this trigger would have these kinds of issues?
EDIT 2: I redownloaded the tablesorter files and it turns out I'm definitely not using the newest ones. When I switch using the newer ones, everything works fine.
Upvotes: 1
Views: 1012
Reputation: 2462
I think the next best thing to try would be to have the table update called after the tab has been switched, and if possible, remove the table and replace it with a fresh one whenever it reloads. I don't know if you have any event listeners attached to anything on the table, but if not, here's a one-liner to try:
$("#ListOfJobs").replaceWith( "<table id=\"ListOfJobs\"><tbody>" + rows + "</tbody></table>").trigger('update');
Upvotes: 0
Reputation: 324750
Internet Explorer does not support innerHTML
modifications on <table>
elements [citation]
Therefore, jQuery is having to parse out your large string of generated HTML and manually create every single element, set attributes, attach child nodes, append them... And unless they added code to detach the <tbody>
element before working on the DOM, the browser is having to recalculate the entire table with every single operation.
If possible, change your code so that you are generating a whole table, and replace whatever table you had before with it. This will allow jQuery to use innerHTML
, which is significantly faster as it uses the browser's internal parser.
Upvotes: 3