Oct 192013

I just released version 1.2.1 of VirtualScroller. This minor update adds two enhancements:

  • Any number of items (at least 1) is supported. If less than 6 items are specified, the VirtualScroller falls back on a standard ScrollableView with the fancy scroll logic disabled. This is transparent to developers and users. Resolves issue 3.
  • VirtualScroller automatically detects whether you want finite or infinite scrolling. If the itemCount property is omitted, infinite scrolling is assumed. Otherwise finite scrolling is used. As such, the infinite property is no longer used. Resolves issue 4.

Download the latest version
Visit the Wiki


 Posted by at 8:51 pm
Aug 172013

It’s been almost a year (exactly a year in seven days), but I finally have a new version of VirtualScroller! Version 1.2 is versioned as a minor update (in the 1.x family), but it contains some significant bug fixes and stability improvements. With the exception of a change in default options (see below), this is a drop-in replacement for version 1.1.1 and 1.1.

Glitch free, smooth scrolling

Previously, scrolling through a VirtualScroller too fast could leave the control in a transient state. Before version 1.2, I had worked around this issue by essentially limiting the scrolling speed. This resulted in an annoying user experience, because it was impossible to quickly swipe through pages. In fact, it was only possible to scroll through one page at a time, with a short pause in between pages.

This is no longer the case with 1.2. Users should not notice any jittering as they swipe along, thanks to vastly improved scrolling logic and event handling.

Two important internal changes made this possible:

  1. Increased view cache: Previously, only three views were maintained in memory which meant that the active view was padded on both sides by only a single view. Because of this, it was possible to scroll to the end of the in-memory views before the VirtualScroller had loaded the next views. Version 1.2 works around this problem by using a cache size of five. This makes it harder to outpace the VirtualScroller’s caching. Note: This means that your VirtualScroller itemCount MUST be at least five (or infinite), or else the VirtualScroller constructor will return null.
  2. Simplified scrolling logic: The code, in general, has been heavily refactored and simplified. For example, VirtualScroller now has a much easier check to determine if a scrollEnd event actually resulted in a page advance. As a consequence, there is much less that can go wrong.

Touch support is assumed

A minor change: previously, the touch option defaulted to false. Since all Google Play apps require touch support, I realize it is more convenient to default it to true instead. In version 1.2, touch now defaults to true.

Updated documentation

The (previously neglected) Wiki has been updated to reflect the new changes. Also, the code example should actually work now.

Download and documentation

Download the latest release here, and get the documentation here. As usual, if you encounter any issues or have any suggestions, please report them here.

Future development

I’m in the process of adding methods for advancing the control forwards and backwards, but I don’t have estimates for when that will be done.


 Posted by at 9:11 pm
Aug 242012

I’ve updated VirtualScroller (grab the latest download here). Here is the change log for the new version:

  • Breaking change: The return value of the factory method now returns an object, not a View. To access the VirtualScroller view (to add it to your view or window), you need the view property of the return value. See the Wiki for more information.
  • Dispose method: Call the dispose method to clean up event listeners and views used by the VirtualScroller instance. Not required but highly suggested.
  • Improved anti-jitter: With this new update I can almost guarantee that your VirtualScroller instance will never end up in an invalid state. In the past, this has happened when someone scrolls the VirtualScroller too fast.
  • Improved options handling: Internally, I’ve added deep option defaulting, which gives you the ability to override properties in sub-options (like top in containerDef, for example) without overriding the entire object. This functionality is similar to jQuery’s $.extend.
  • Accessibility: Set touchSupported to false (the default is true) to enable support for trackball navigation of the VirtualScroller. This is useful if you plan to publish your app on Amazon Appstore, or another app store that doesn’t require devices to have touchscreens.
  • Auto-focus: Set autoFocus to true and the first child of each view will be focused automatically upon viewing.

Access the updated documentation here.

 Posted by at 4:04 pm
Aug 152012

I looked through the Titanium documentation and user boards, but I couldn’t find a simple way to detect whether a device has a touch screen (as opposed to a trackball). Obviously, all iDevices will have touch screens, so this code is really meant for Android and web deployments.

Here is my very primitive (but functional) solution. Place this code where the first window that your user interacts with is created.

    Titanium.App.Properties.setBool("touch", false);

    function touchStart(){
        Titanium.App.Properties.setBool("touch", true);
        self.removeEventListener("touchstart", touchStart);

    self.addEventListener("touchstart", touchStart);

The first time the user touches the screen (indicating that a touch screen is present), an application-wide setting is written indicating touch support.

In the rest of your application, check for touch support with:

var hasTouchSupport = Titanium.App.Properties.setBool("touch", false);

Note: I found that it was necessary to first clear the setting, for some reason, at least during debugging on an emulator. You could probably get rid of that first line.

 Posted by at 12:28 pm
Aug 032012

If anyone else is having trouble with the combo of Titanium, the Android SDK, and Windows 7 64-bit, then maybe this post if for you. It took me a few hours to get right.

Upon clicking “Android Emulator” under the Run button, I was receiving errors about jarsigner and java missing. Here’s what you have to do:

  1. Titanium requires the 32-bit version of the Java SDK, even if you are running on 64-bit Windows. Furthermore, it requires Java 6; Java 7 is the default.
  2. Uninstall all other versions of Java, and download Java 6 (which appears to be version 1.6, as opposed to Java 7 which appears as 1.7) for 32-bit from here: http://www.oracle.com/technetwork/java/javase/downloads/index.html
  3. Install that.
  4. Set your JAVA_HOME path by following these steps: Go to your Start Menu, right click on Computer, click Properties. Click Advanced System Settings on the left, go to the Advanced tab, and click the Environment Variables… button at the bottom. Under System Variables, and click New… Name is JAVA_HOME, and value is something like C:Program Files (x86)Javajdk1.6.0_33, with the path possibly varying depending on the exact version of Java you installed.
  5. Now, add the bin directory to your PATH variable. Still in Environment Variables, under the System Variables section, find Path. Click Edit…, and in the Value box, append a semicolon if one isn’t already there. Then, append C:Program Files (x86)Javajdk1.6.0_33bin, taking note that your exact path might be a little different.
  6. Click Ok twice to get out of both dialogs.
  7. Restart your computer – yes, really. It simply won’t work if you don’t.

Side-rant: Why can’t Java configure the damn path variables for me? It couldn’t possibly be that hard to have the installer perform these two simple steps. I propose a new slogan. Java™ : Complexity for the sake of tradition.

Further troubleshooting

If you still get errors, then make sure you got all the paths to your JDK right. Actually navigate to the exact directory and copy the path from the address bar, instead of relying on the exact paths that I posted above.

If you still get errors, then make sure you have the right version of the JDK installed. Remember: 32-bit, Java 6 (1.6).

 Posted by at 9:40 pm
Jul 272012

Time to release something new. I’ve been working on a little project to develop an Android app. I’ve chosen Titanium because the app is simple (no network connectivity, sensor interaction, maps, etc.) and the learning curve for Titanium is low.

I had been working with the Android SDK for about a week (very frustrating), and one feature I found to be missing from Titanium is a decent way to scroll through large datasets horizontally. In my case, I had a few dozen pages that needed to be scrolled. I didn’t want to plop all of them into a ScrollableView, since that would put a strain on Android. So, I created this little module.

It is based off of this GitHub gist, though it doesn’t bear much resemblance anymore. Scroll down for links to my project.


The module I created is called VirtualScroller, and you use it like this:

// Replace the path as necessary
var VirtualScroller = require('ui/common/VirtualScroller');

var virtualScroller = VirtualScroller({
    itemCount: 10,
    getView: function(i) {
        return Titanium.UI.createLabel({
            width: Titanium.UI.FILL,
            height: Titanium.UI.FILL,
            text: "This is item " + (i + 1)
    infinite: false


I’ll steal the description from my BitBucket page, since I don’t feel like writing a new one:

VirtualScroller is an easy to use Titanium module that wraps around a ScrollableView and provides finite and infinite scrolling. All items (which are actually Views) are created on-demand, and only remain in memory when needed. The ScrollableView instance has three Views, which act as containers for the actual items.

This method permits memory-efficient scrolling of large sets of views.

So, if you have a large amount of views to scroll through, but don’t want to load them into memory until they’re needed, check out my module. It supports finite and infinite scrolling, and uses a callback to generate each view only when needed.

On BitBucket:
Wiki (instructions and information)

 Posted by at 12:24 pm