Skip to content

Instantly share code, notes, and snippets.

@gryzzly
Created May 21, 2012 15:41
Show Gist options
  • Save gryzzly/2762965 to your computer and use it in GitHub Desktop.
Save gryzzly/2762965 to your computer and use it in GitHub Desktop.
Backbone touch / click events
var down = "touchup" in window ? "touchup" : "click";
var abstractView = Backbone.View.extend({
// we don't want both click and touch handlers
// delegated on touch-enabled devices
events: function () {
"click .toggler" : "foo",
"touchup .toggler" : "bar"
},
initialize: function () {
// we can do this instead
this.events = this.events || {};
this.events[down + ' .toggler'] = "foo";
// … list more events here
this.delegateEvents();
}
});
// This does solve the problem but this doesn't look good
//
// We could do something like jQuery special event, but Zepto,
// that is used on mobile devices doesn't support special events
//
// So seamless "down .toggler" : "foo", that would work by registering
// "special" jQuery event will not work with Zepto
@falsefalse
Copy link

Here is an ugly-ass piece of shit that I do

(function() {
    // this is android-only, for now
    if (!$.os.android) {
        return;
    }

    var delegate = Backbone.View.prototype.delegateEvents,
        // TODO: this might change along with Backbone updates, watch for it
        eventSplitter = /^(\S+)\s*(.*)$/,
        timeout;

    _.extend(Backbone.View.prototype, {
        delegateEvents: function(events) {
            if (!(events || (events = this.events))) return;

            for (var key in events) {
                var match = key.match(eventSplitter),
                    eventName = match[1], selector = match[2];
                if (selector && eventName === 'click') {
                    // `events` here is a reference to `this.events`, so `this.events`
                    // is indirectly modified
                    // won't work if `this.events` is a function
                    // however BB 0.5.3 doesn't support `this.events` being function, so we're good
                    events['touchstart ' + selector] = '_touchStart';
                    events['touchend '   + selector] = '_touchEnd';

                    // uncomment for debugging in desktop browsers
                    // events['mousedown ' + selector] = '_touchStart';
                    // events['mouseup '   + selector] = '_touchEnd';
                }
            }

            delegate.apply(this, arguments);
        },
        _touchStart: function(event) {
            var target = $(event.currentTarget);
            target.addClass('_active');

            // fixes long tap, browser doesn't fire touchend
            // thus, make active highlight last for not more than 350 msec
            timeout = _.delay(function() {
                target.removeClass('_active');
            }, 350);
        },
        _touchEnd: function(event) {
            if (timeout) {
                window.clearTimeout(timeout);
            }
            $(event.currentTarget).removeClass('_active');
        }
    });
})();

@gryzzly
Copy link
Author

gryzzly commented May 21, 2012

Another take on this same problem, a bit more elegant: https://gist.github.com/2763480

@tuxracer
Copy link

I created a plugin for this https://github.com/tuxracer/touchclick Then you can just do:

var FooView = Backbone.View.extend({
    events: {
        "touchclick .bar" : "bar", 
        "touchclick .baz" : "baz"
    }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment