Some motivation

Django has a field called ChoiceField which lets you very easily create a <select> dropdown in your forms. A great feature is the ability to transform nested choices into appropriate <optgroup> groups. For instance, the following code:

The problem

As it turns out, ChoiceField only supports one level of nesting. Five years ago someone submitted a patch to correct the problem, but it was rejected for good reason: HTML itself only officially supports one level of <optgroup> nesting.

To see if it would work anyway, I manually applied the patch to my Django installation. Although the patch itself worked (Django produced the nested option groups), Chrome wasn’t having any of it. My dropdown displayed incorrectly, and developer tools showed that the HTML got mangled during parsing.

Emulating nested optgroups

My solution to the problem is to fake it by using disabled <option> elements as group headers. Then, we apply indentation to the actual options to make them appear to belong to the groups. This is accomplished by a custom widget called NestedSelect (below), which is a cross between the original Select widget and the patch I linked to above.

Improving the aesthetics

The solution above works, but it can be improved in two ways:

The manual addition of padding results in an ugly side-effect – that padding is visible in the selected option. Look at the difference when Choice 1 and Choice 5 are selected (below). Choice 5 is aligned correctly, but Choice 1 appears to be floating out in no-man’s land.

We no longer have the nice bolding effect on the option group headers. It’s not possible for us to individually style the elements that are supposed to be headers.

To overcome these shortcomings of HTML, we must turn a JavaScript based replacement: Select2. With that plugin installed, the fix is just a little bit of JavaScript:

Finished product

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.

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:

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.

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.

jQuery UI 1.9 is finally here! What does that mean for dialogWrapper? Well, it would seem like the answer to that question is: nothing. A redesign of the dialog API is not present in version 1.9, and it doesn’t look like it will happen until the 2.0 release, according to the official site.

The planned changes for the 2.0 release are something to get excited about now, however. Some of the changes discussed add some nice functionality and improve the overall design of the API. Heads up: so far, it doesn’t sound like the 2.0 release will make dialogWrapper irrelevant.

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.

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.

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.

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.

Click Ok twice to get out of both dialogs.

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).

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.

VirtualScroller

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

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.

Changes, changes. I’ve just finished adding the grunt build system to all my JavaScript projects. This has made it so much easier to manage them.

Now instead of manually generating the minified versions (copy-pasting to Google Closure Compiler), worrying about the license files being up to date, etc., I can issue a single command and everything is taken care of.

This also means that JSLint is run whenever I build my projects. So naturally, in the span of a few hours I caught a bunch of warnings and errors that I had previously never seen. I’ll go through the projects one at a time.

Textarea Line Count

Very important fixes. Updated to version 1.4. Let me say, I’m surprised that I didn’t receive any bug reports on version 1.3. Running JSLint revealed variables that didn’t exist, or that were named incorrectly. Oops. That’s what I get for not using a build system sooner.