Here at CouchCommerce we work hard to constantly improve the shopping experience for touch devices. We want people to have a great experience when shopping with CouchCommerce.
One thing that bothered us for quite some time about our app was that one couldn’t swipe from one product to another. Or well, you could. But since there was no visual feedback the feature was hardly discoverable and rather felt like a bug than a feature.
Good news: We fixed it! Now users can swipe through the products of each category in the fashion of an infinite carousel.
In this blog post I want to walk you through the technical challenges of this feature and how we addressed them.
Our current app is built up on the awesome Sencha Touch framework. A quick look through the documentation shows us that a Carousel component does already exist within the framework. Great, let’s use that component!
Ah, wait – there’s a problem. The Sencha carousel component needs to know all the product views in advance. Since a category can contain quite a bunch of products that will hurt our performance in several ways:
1. When the user clicks on a product in the product listing it would take ages until he sees the product view since creating all views in advance takes quite some time.
2. Putting too many elements into the DOM hurts the overall app performance even if the elements aren’t visible at all. As a general advice try to keep the size of the DOM as small as possible.
The solution: Going lazy
What we need is a carousel that let’s us create new items when they are needed (so called “lazily”) and also removes those items that are not needed anymore. Ideally our carousel would only hold 3 items in the DOM at any time. The current, the previous and the next one.
Now when the user swipes from the current item to the next item, what should happen is:
1. Our current item is sliding out of the screen eventually becoming the new previous item.
2. Our previous item from before will be removed from the DOM as it doesn’t qualify anymore as either beeing the current, previous or next item.
3. The item we initially referred to as “next view” is now becoming our current view.
4. So now that all views shifted to the left it’s becoming clear that we need a new item to become our new “next item”
So we built a component that exactly works this way. We call it LazyCarousel. It actually isn’t too opinionated about how exactly it will be used. It leaves the developer more room for several use cases.
Let’s look at the public API of our LazyCarousel. First of all, it derives from “Ext.carousel.Carousel” which gives it all the power of the built in Sencha carousel. However, it adds some methods and events. Let’s first look at the events:
Notice that we don’t use camelCasing for the event name to align to the conventions of Sencha Touch (even those suck hard! Who came up with not camelCasing events?)
The first two events (movedforward, movedbackward) should be pretty obvious. Whenever the user switches the items of the carousel going either back or forth we raise the events accordingly. This is important since it gives the developer the chance to modify the pointer in a related datasource accordingly. Think of a carousel that acts as a calendar where you can swipe through the days infinetely (as in one of the demos). Obviously you need to have a chance to keep track of the current day.
Then we have headneeded and tailneeded which raise whenever the carousel needs a new item either at the head or tail. Notice that the carousel decides on it’s own when to remove items. Currently it’s hardcoded to only hold 3 items at any time. A more sophisticated implementation would make that configureable. We follow KISS though.
The last event in our list is itemremoved. As stated before the carousel decides on it’s own when to remove items. Notice that it doesn’t destroy the items. That leaves more room for different use cases. For example, you can recycle existing items to be reused instead of recreated (that’s how we use the LazyCarousel at CouchCommerce).
In addition we have two new methods on our LazyCarousel.
These methods exist to insert items at both ends of the carousel.
These events and methods are all it takes to build infinite carousels that load views lazily and go easy on resources.
Here are some examples which make use of the LazyCarousel.
1. Iterating through an array of integers where new views are created on the fly. Each view is given a random color on creation which makes it more clear that we are creating new views rather than recycling instances.
2. Similar to the previous example but recycles existing instances, hence we only see three different colors for the views.
3. Here is another example that is truly infinite as it’s an calendar that let’s you swipe through the days with no start or end
4. Last but not least you can see the carousel in action on most of our CouchCommerce shops already.
The code for the LazyCarousel itself can be found here:
Where to go from here
While we were initially searching for a infinite Carousel we stumbled across a bunch of components that just didn’t fit our needs. Either they didn’t derive from Ext.carousel.Carousel and had bugs or they didn’t work well with lazy loading the views. Our implementation is only ca. 80 lines of code and works pretty well especially since it’s built up on solid foundations (derives from Ext.carousel.Carousel).
We are not 100% satisfied with the performance of the carousel when the user swipes through the products very fast. The performance on the phone is pretty good but the performance on the tablet version could be improved. However, that’s not directly related to the LazyCarousel. It’s more that our tablet ProductView is pretty heavy weight. We are constantly looking into ways to improve the performance of our app and already have ideas for this specific case. But that’s a story for another post…