input type="file" on Firefox OS 1.0.1

I got a developer phone! It's a geeksphone Keon. Nice colour and form-factor, I like it--but I thought I'd better spare you the unboxing part, as there have been many of those already.

Of course, the first thing I did after turning it on and installing the system update that I immediately got, was trying the app I'm working on!

I found that Firefox OS 1.0.1 didn't implement inputs with type="file" (bug). But of course, there's a solution...

Detection

First you need to detect if your input with type="file" has been "rejected" by the browser and converted into the default, which happens to be 'text'. This is a standard HTML trick of the trade, so nothing too new here. For example, if you had this HTML code:


<input id="filepicker" type="file">

you could detect whether the system supported it with this:


var input = document.getElement('filepicker');
if(input.type !== 'file') {
    // No luck
}

You can also do the same with elements created dynamically:


var input = document.createElement('input');
input.type = 'file';
if(input.type !== 'file') {
    // Noooo
}

Using Web Activities

In case you're not lucky and the type="file" is not implemented, the solution is to use a Web Activity to allow the user to pick stuff using other apps.

If you have done any Android programming, this concept will sound superfamiliar to you, although in the guise of intents! If you haven't, a basic summary would be: apps can offer their data and functionality to other apps. For example, the Gallery app allows other apps to use its 'pick' functionality and choose pictures.

If you then want to pick files, you just need to create an activity with name = 'pick', set a couple of callbacks and that's it:


// Web Activities are not standard _yet_, so they use the Moz prefix.
// We'll make sure they exist before using them, anyway
if(window.MozActivity) {
    var activity = new MozActivity({
        name: 'pick',
        data: {
            type: 'image/jpeg'
        }
    });

    activity.onsuccess = function() {
        var picture = this.result;
        var blob = picture.blob; // just a standard blob
    }

    activity.onerror = function() {
        // oh no!
    }
}

This launches the activity immediately.

Once you get the picture, you can do things the usual way with blobs. For example, create an image and set the picked image as its source:


var img = document.createElement('img');
img.src = window.URL.createObjectURL(blob);
document.body.appendChild(img);

A final thought

After I implemented this "work-around", I came to think that in some cases it might make more sense to go for Web Activities first when it comes to pick files in a phone, even if it does implement inputs with type="file".

The reason being is that when you tap on these inputs they actually end up launching a similar panel with the list of apps that allow picking, so if you replace the input with a button that launches the activity, you save the user one tap, and that means a happier user after many saved taps :-)

Feel free to mull on this thought!

Further reading