django/django — pull request #222 by kylemacfarlane (2012-07-21 02:34:22+00:00)
Title: #3202 - Large speed increases to SelectBox and SelectFilter2

I have an admin page with two filter_horizontal widgets on it. One has almost 800 options and the other 11,500. As you can imagine it's pretty slow but also it sometimes copies the wrong selections if you have a lot of them, plus it crashes on page load in IE and Opera. The scripts in 1.4 make it even slower by using a slow jQuery selector to check if anything is selected when deciding what icons to use.

The tweaks to redisplay from #3202 will cut a second or so off of every action but the code still calls redisplay way too often which means doing anything takes 2-5 seconds. Ticket #9102 attempted to avoid redisplay but its method of hiding ``
`` tags doesn't work in Chrome.

I've come up with the following which will generally transfer options instantly on my 11,500 list. It starts to slow down if you're moving stuff from side to side in bulk but it's still faster than what's currently in Django. It works excellently in Chrome, Firefox, and Safari, but Opera and IE are still slow but no longer crash.

1. Included the tweak from the current SelectBox.patch on ticket #3202 to speed up redisplay.

2. Don't run redisplay on page load or moving options between columns. Instead just move the actual DOM node and this is super fast.

3. However, when moving large numbers of options then keeping them in alphabetical order is often slower than redisplaying, so redisplay instead. I currently set it to redisplay on any movement of more than 100 options but that number is just a guess and involved little testing. The number really depends on the amount of options being moved, how many options are in the destination column, how fast the user's browser is, etc.

4. Only redisplay filter results 250ms after you've stopped typing. This prevents the major lag on the first 1-3 letters when you try to filter something on medium to large lists.

5. Store a separate key map for quicker access to the cache and less iterating.

6. Check against selectedIndex to see if any options are selected instead of going through every option again with jQuery just to display icons.

7. Every browser except Firefox will lock up for 2-3 minutes if you have too many `selected="selected"` (even in a plain HTML file). So while you can use this javascript to select 10,000 options in 2 seconds your tab might crash after the form submit.

8. Bonus: fixed the keyboard shortcuts and enter no longer bubbles up and submits the form.