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 <option> 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.
Included the tweak from the current SelectBox.patch on ticket #3202 to speed up redisplay.
Don't run redisplay on page load or moving options between columns. Instead just move the actual DOM node and this is super fast.
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.
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.
Store a separate key map for quicker access to the cache and less iterating.
Check against selectedIndex to see if any options are selected instead of going through every option again with jQuery just to display icons.
Bonus: fixed the keyboard shortcuts and enter no longer bubbles up and submits the form.
#3202 - Large speed increases to SelectBox and Se;ectFilter2
Fix checking length of selected options
Why are you cloning here? Can't you just append the fragment?
More improvements to SelectBox and SelectFilter2
Fix for missing text nodes in IE with new options
I made some more speed improvements and it can now do about 4000 single node moves before a full redisplay is faster. Plus redisplays are faster too.
Increased the delay on the typing setTimeout because too often it fired early. I then made it so that hitting enter sets the delay to 0 and immediately filters.
The add new option popup no longer calls redisplay.
I made large option moves maintain your scroll position so that you aren't lost in the middle of nowhere afterwards.
I think there's potential for usability improvements that can be done in relation to tabindex etc but I'm not sure how people would want the form to actually behave.
Removed leftover Grappelli fix
Dropped cache and improved keyboard accessibility
The cache ended up having race issues now that it was working quickly, but I realised that it wasn't even needed anymore anyway.
I also changed the keyboard functionality to something better I believe.
When you tab in you will first land on the green plus icon if it's available. Hitting enter will cause the popup and you can add a new object using only the keyboard.
The second tab will land in the filter field. In this field you can obviously filter and use enter to to bypass the typing delay. The arrow keys no longer do anything here.
The third tab lands you in the left column where you can use the up and down arrows to select options. The wrapping from top to bottom and vice versa was removed because it interfered with the default browser abilities such as using shift to select multiple options. You can use home and end to get to the top and bottom anyway. Once you've selected some options you can move them over with either enter, space, or the left/right arrow keys. In Webkit, Ctrl + A works in here by default but other browsers can use shift + home and end anyway.
The fourth tab will land you in the right column which behaves the same.
The fifth tab will leave the widget and enter the next field.
Fixed spelling mistake
Fixed resetting selectedIndex too early
Lightweight fix for #13614
Thanks a lot for your work. Do you think you could reproduce the same performance improvements, but also rewrite the widget with jQuery? If so, then I think it'd be a better approach to kill these two birds with one stone. See this ticket for reference: https://code.djangoproject.com/ticket/15220
Fixing this issue would be hugely appreciated :) I'm currently working with a project that displays 13k items in a filter_horizontal widget and the page takes 20-30 seconds to load.
Closing this in light of @jphalip's comment above.
Makes the "create a new GitHub repository" step clearer.