Rick, based on what I've learned from testing, you have another option now...
Here is a modified version of Mike's code - without generating the table. function populateDutyTable(response) { var currentDay = ''; var rows = response.QGETDUTYSCHEDULE.DATA; var out = [], o = -1; out[++o] = '<tbody>'; // CHANGED for( var row, i = -1; row = rows[++i]; ) { var day = row[1]; if( currentDay != day ) { currentDay = day; out[++o] = '<tr><td class="cell-day">'; out[++o] = row[1]; out[++o] = '</td><td class="cell-date">'; out[++o] = row[2]; out[++o] = '</td><td class="cell-blank" colspan="5"> </td></tr>'; } out[++o] = '<tr><td class="cell-blank-day"> </td><td class="cell-blank-date"> </td><td class="cell-am-am">'; out[++o] = row[3]; out[++o] = '</td><td class="cell-position">'; out[++o] = row[4]; out[++o] = '</td><td colspan="3">Cell Content</td></tr>'; } out[++o] = '</tbody>'; // CHANGED $('#scheduleBody').append( out.join('') ); // CHANGED } A container around the table is no longer required because wrapping the rows in a tbody achieves the same performance as wrapping them in a table. Plus, you could now add rows without regenerating the entire table. This provides more options with no penalty. For example, now you could hard-code the table with column headers - for example... <table id="scheduleBody"> <thead> <tr> <th>ID</th> <th>Day</th> <th>Date</th> <th>Name</th> </tr> </thead> </table> This is cleaner and faster than adding column headers inside your Javascript loop. I suggest you try both methods, Rick. Use a timer (like MIike's sample pages) to confirm whether both are equally fast. Based on my tests, you may find appending to the table even faster, with cleaner markup as a bonus. Ciao, /Kevin On Feb 7, 3:20 pm, "Rick Faircloth" <r...@whitestonemedia.com> wrote: > Hey, thanks Michael for taking the time to provide the > explanation and the re-write. I'll put this into place > and see how it performs. I'm sure it'll be *much* better! > > Rick