Question

I'm wondering how to bind both events "click" and "touchstart" within a single line:

Engine.on("click"), function(){ aCode() }
Engine.on("touchstart", function(){ aCode() }

I expected something like this (as it is implemented in some other frameworks):

Engine.on("click touchstart", function(e){ aCode() });

My current workaround is chaining them:

Engine.on("click", function(){Engine.emit("touchstart")});
Engine.on("touchstart", function() { aCode() }

Is there a better practice for this ? The problem is that click is not caught on iOS nor the touchstart with a mouse on desktop… obviously I would like to handle the event the same way whatever the device.

Was it helpful?

Solution

[EDIT] For handling the click and touchstart->touchend in the same way, just use the FastClick override shim.

just add:

FastClick = require('famous/inputs/FastClick');

then this will also work on tablet:

anElement.on("click", function(){alert("Click caught")})

Another alternative is using this helper:

function onEvent(source, events, callback)
{
    for (var event in events)
    {
        source.on(events[event], function(e) {
            callback(e);
        });
    }
}

Then:

onEvent(Famous.Engine, ["click","touchstart"],function(){});

OTHER TIPS

The on() method in Famo.us only accepts one event type. It doesn't do any jQuery style string processing to determine separate events. In theory you could have an event named get to the chopper

What I do when creating my custom views however is create a bindEvents() function which groups all the event listeners together. The only code in these handlers are other functions. If I wanted to react to two different events in the same way, I'd just use the same function for both of them.

// An example Class demonstrating events - some off-topic parts omitted
function myLovelyHorseButton() {

    // Recomended Reading: https://famo.us/guides/dev/events.html

    this._eventInput = new EventHandler();
    this._eventOutput = new EventHandler();

    this._eventInput.pipe(this.sync);
    this.sync.pipe(this._eventInput);

    EventHandler.setInputHandler(this, this._eventInput);
    EventHandler.setOutputHandler(this, this._eventOutput);

    /** Set options & variables
    /* ...
    */

    // create event listeners for this specific instance
    _bindEvents.call(this);
};

// bind all the events for the button
function _bindEvents() {
    //Call event handlers with this set to owner.
    this._eventInput.bindThis(this);
    // listen for events
    this._eventInput.on('click', _handleClick);
    this._eventInput.on('touchstart', _handleClick);    //Same as 'click'
};

//  Nay to the console on click/touch
function _handleClick(event) {
    console.log('Nayyyyy!!!');
};


// create an instance of myLovelyHorseButton
var button = new myLovelyHorseButton;

// We would then add the button to the Render Tree
mainContext.add(button);

There is a big reason why you don't want to do the chaining pattern you're currently using. And that's because by emitting a touchstart event on a click, you're inferring that there's going to be some code there to act upon it. One day you might get drunk and decide "Nobody on touch devices is using this!" and delete the ontouchstart handler. And in an instant, your code doesn't work for anybody, touch or mouse.

TL;DR There is nothing wrong with using multiple on() calls.

I hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top