Home

User Input

We can capture two different types of user input in a Famo.us application: data from HTML form elements, and input events, such as mouse clicks. In this section, we’ll look at the techniques to do both.

Make sure you also read the companion to this section, which covers how to use events to create application logic.

Getting input element data

In the section on surfaces, we learned that surfaces come in a variety of flavors representing different HTML elements. This includes elements for accepting user input as part of a form: InputSurface and TextareaSurface.

Both InputSurface and TextareaSurface have a .getValue() method which will return the input value content as a string. Both also have a .setValue() method that takes a string as an argument and sets the value of the element.

var inputSurface = new InputSurface({
    value: 'Hello Input!'
});

inputSurface.getValue();
// => 'Hello Input!'

Note that unlike a plain Surface, we set the value property, not the content property, to set the content of these surfaces.

Capturing input events

We can also capture user-input events such as mouse clicks and touches. There are two places to capture these interactions: via engine events, and via surface events.

Surface events

Surface events are emitted from surfaces. We can listen to all of the familiar events that are available in vanilla DOM, including:

To listen for any of these, we use the surface’s .on() method, passing it the event name string as the first argument, and a callback function as the second. Example:

var surface = new Surface();

surface.on('click', function(event) {
   // Handle the click event here. 
});

Engine events

When an input event, such as a click, isn’t intercepted by a surface or a context, they propagate up to the engine. (As we’ll cover in the program events section, the engine can also receive and emit generic events.) We can thus use the engine as a catch-all to make sure we handle all events that occur in the application. As with surfaces, we use the .on() method:

Engine.on('click', function(event) {
    // Handle the click event that was
    // not intercepted 
});

(Note: The engine also emits several events unrelated to user input. For those, see the engine section.)

Synchronizing input

In the real world, our applications need to be able to handle input that comes from multiple elements, as well as multiple types of input. For example, we may need to listen to events from multiple surfaces. Also, we may need to handle both mouse events and touch events. However, handling all the variations in an application can get complex.

To solve this problem, Famo.us provides sync classes that can pull these different events together into one interface, and even merge event types that should be treated the same.

GenericSync

The GenericSync class is the most commonly used sync class, because it allows us to merge both mouse and touch input into a single interface. Here’s how to use it.

1. Load sync modules. We first need to load sync modules for all the types of input we want it to handle:

var MouseSync = famous.inputs.MouseSync;
var TouchSync = famous.inputs.ScrollSync;
var GenericSync = famous.inputs.GenericSync;

2. Register keys for each module. Next, we must register each of these sync modules with a special string key. This gives us a way of referencing their merged output from GenericSync later. The class’ .register() function takes an object whose property names are the keys, and whose property values are the sync classes themselves:

GenericSync.register({
    'mouse': MouseSync,
    'touch': TouchSync
});

3. Create a sync instance. Then we create a sync instance that will emit events from only the sources (keys) we specify:

// This `sync` instance will emit events from both
// mouse and touch sources.
var sync = new GenericSync(['mouse', 'touch']);

// We could create a separate sync that only emits
// events from one of the sources.
var otherSync = new GenericSync(['mouse']);

4. Pipe events to the sync instance. The sync instance isn’t very useful until we start sending it events to synchronize. We can pipe events to it from any object that emits them. For example, a surface:

var sync = new GenericSync(['mouse', 'touch']);
var surface = new Surface();
surface.pipe(sync);

5. Listen to the sync instance. Now that the sync instance is receiving events from the surface, we can listen to events from the sync, which will transparemtly merge together touch and mouse events.

Since the sync instance is an abstraction on top of direct mouse and touch events, the standard DOM events are not available. Instead, we listen for the start, update, and end events:

sync.on('start', function(event) {
    // Fires when a pointer action starts
    // (When the mouse goes down or a touch begins)
});

sync.on('update', function(event) {
    // Fires on every update of the pointer
    // (When the mouse/touch moves)
});

sync.on('end', function(event) {
    // Fires when the pointer action ends
    // (When the mouse/touch is released)
});

Sync event properties

The MouseSync and TouchSync modules both emit event objects with several convenient properties you can use when building up your application’s interactivity:

Other sync modules

Famo.us also includes several other modules you can use when capturing and synchronizing input:

Next: Using program events »