I’ve been working on lots of different projects lately. On several of them, I’ve had the need for a reusable list component. In some cases, it needed to handle a large data set, in others it just needed to be self-contained and easy to use. Out of these projects came MegaList: a reusable list component for jQuery, which I’ve released as open source on Github.
MegaList is a jQuery plugin that creates a touch-enabled list component, capable of very large datasets, complete with data virtualization. It was originally intended for touch-enabled devices, however it also works in many desktop browsers.
For performance optimizations, the list component uses data virtualization techniques, so there are never more list elements in the HTML DOM than what is currently visible on the screen. As the user scrolls through content, the list updates the DOM elements accordingly. This makes scrolling lists of thousands of items extremely fluid. This works in a very similar way to ItemRenderer classes in Flex list and grid components.
You can employ the list component using one of two approaches. One option is to declare the list structure in HTML markup, another option is to specify a dataProvider array, from which the list will create DOM elements.
Sometimes you need a pre-built list that you can reuse. Sometimes you need to scroll through big data sets, and other times you just need component logic kept away from your app logic. It doesn’t fit every scenario, but it certainly fits a few.
Data virtualization techniques allow you to quickly scroll through massive lists, without performance degradation. However, if your app really has 100K list items to scroll through, you should fire your UX designer.
View the “samples” directory to see the scrollable list component in action. All samples are interactive, and scrollable via touch or mouse events, with function event handlers.
Each of these examples can be scrolled using either the mouse or finger, and just tap/click on a row to select it, invoking the selection handler (alert message). On the desktop, you can also scroll with the scrollbar. Note: I originally intended this for mobile – on the desktop, I’ve only tested in Chrome and Safari.
Simple List Created With Inline LI Elements
This is a basic example with a list of 50 LI elements.
Simple List Created With A DataProvider of 100,000 items:
This is a more complex example using a massive data provider (100,000 elements!) with a label function.
Styled Dynamic List Created With Remote Data:
This is a dynamic example pulling data from twitter for a dataprovider, with a label function that returns HTML, instead of plain text strings.
Note: These inline/embedded examples are contained inside of iframes – if you mouse-up outside of the iframe, the iframe contents won’t receive the event. If MegaList is used in a page, without a wrapping iframe, you don’t run into this issue. Follow the “View Sample” links above to see them without the iframe issue.
- Contrary to my expectations, using CSS3 translate3d is actually slower than using CSS top/left when placing the virtualized content. If you enable CSS3 translate3d and set backface visibility, there is an extremely noticeable performance degradation on both desktop and mobile devices.
- I’ve experimented with lots of permutations to get the best performance possible. I’m not finished yet, but I’ve found that you can achieve significantly faster performance of DOM manipulation by removing elements from the DOM, manipulating them, then re-adding them. This is what is done within the updateLayout() method. The <ul> is removed from the DOM, <li> elements are added or removed, and then the <ul> is added back to the DOM. You may see a flicker on rare occasions, but I didn’t find this overly intrusive.
- For small data sets, this may not be much advantage – you can get better performance by just using something like iScroll in a <div> containing a <ul>. With large data sets, this is definitely faster.
- The more complex the HTML inside of your label function, the slower the animation will be.