3

I'm writing a web application that displays a large number of rows of data (~2000 at present), each of which has a drop-down "select" element with ~100 options. Any of those options can be selected by default. I'm generating all the actual DOM elements client-side. My problem: rendering this beast takes ~4 seconds on my relatively recent machine, which is really suboptimal. I know the problem is specifically with all the select elements, because replacing them with a bit of static text or a single-option list causes render time to be nigh imperceptible.

The vanilla code, minus failed experiments (see below) is here.

Avoiding the suggestions of "paginate your data" and "don't have so many options in a select", what is the most efficient way I can write my append / render code, assuming I do have a legitimate reason to display that much data and have that many options? For my purposes, Firefox is the only platform I care about.

Things I have tried:

  • Using an async loop to append rows to the table (slower than a regular loop, and oddly didn't render the intermediate results)
  • Building up a string that represents the body of the table and inserting it into the DOM in a single call (almost identical performance)
  • Instead of inserting the entire options list, inserting a single-option "select" element, and then populating the entire list when the "select" element gains focus (presumably because someone is trying to change it). This was actually pretty high-performing for the initial render, but then populating the element with the full list caused some weird behavior, losing focus and never actually being able to "open" the select element.

Right now my default assumption is that the third option is the way to go, and I need to figure out how to do some bookkeeping about what has already been populated. But my suspicion is that there is a plainly better / faster / more idiomatic way to do this. Is there?

Community
  • 1
  • 1
Bryce
  • 2,157
  • 17
  • 16
  • 1
    try `slickGrid`. its awesome and it will help you. – Gyandeep Mar 03 '14 at 01:05
  • This is mostly for my own edification; I'm interested in understanding the underlying techniques. Do you know what the slickGrid solution is to these problems? – Bryce Mar 03 '14 at 01:08
  • 1
    they use virtual rendering. that means they only render those rows which are visible to the user. they also have pagination. – Gyandeep Mar 03 '14 at 01:12
  • Is there some description of how "virtual rendering" actually works in practice and how it can be implemented outside of their library? As I said, I'm interested in underlying techniques. – Bryce Mar 03 '14 at 01:17
  • Can you provide some code to demonstrate your current method for rendering? – Bradley Trager Mar 03 '14 at 01:20
  • 2
    If you use something like "infinite scroll" or something along those lines you basically don't add elements to the DOM until the page reaches a certain scroll position (See http://stackoverflow.com/questions/2481350/retrieve-scrollbar-position-with-javascript for information on that) – drew_w Mar 03 '14 at 01:23
  • Does each dropdown have the same contents as all the others, or do they have unique contents? – Matthew Lock Mar 03 '14 at 01:52
  • All of the contents are the same, but each potentially has a different selected element. – Bryce Mar 03 '14 at 02:01
  • Okay, another option then is to only have a single dropdown and use the DOM to move it to the currently selected row. – Matthew Lock Mar 03 '14 at 23:25
  • After the initial render, modifications are pretty quick - although now I'm curious whether the overhead from additional modifications is outweighed by the savings from keeping the overall document tree smaller. I'm actually modifying the lists on mouseover, to avoid having to double-click to actually open the menu, so I'm generating a fair amount of modifications anyway (a timeout could prevent some of these in the first place as well). – Bryce Mar 03 '14 at 23:42

1 Answers1

0

Yes, I would "lazily" generate and/or populate the dropdowns.

That is, only create and populate the dropdowns when the user clicks on them, as probably almost all of the dropdowns in the 2000 rows will never be used right?

Perhaps a select element might not be the best UI here too, but instead some kind of HTML menu like so: https://jqueryui.com/menu/ that is created, populated and displayed only when the user clicks on some kind of button to display it.

Matthew Lock
  • 13,144
  • 12
  • 92
  • 130
  • 1
    After some experimentation, lazy generation of the select elements drops the render time to acceptable levels. Making it faster seems to require lazily generating the actual table rows via an infinite-scroll type mechanism. There is still a de-select hiccup when the element is replaced, so it's not completely transparent, but AFAICT it's unavoidable if I'm using a select element. – Bryce Mar 03 '14 at 18:47