3

I'm looking for a super simple jQuery extension. Basically I need to use some events that jQuery does not explicitly support. These events are the iPhone touch events like ontouchstart, ontouchend, and ontouchmove.

I have it working via this:

// Sucks
$('.clickable').each(function() {
  this.ontouchstart = function(event) {
    //do stuff...
  };
}

Which kind of sucks and is unjqueryish. Here is what I would like:

// Better
$('.clickable').touchstart(function() {
  //do stuff...
}

Or even better with 1.4

// Awesome
$('.clickable').live('touchstart', function() {
  //.. do stuff
}

These events need no special handling and should work just like any other events, but I can't seem to figure out how to extend jquery to make them work just like all the other events do.

Alex Wayne
  • 178,991
  • 47
  • 309
  • 337

5 Answers5

5

I wrote the plugin, if the user does have touch available, use, otherwise, call click

jQuery.event.special.tabOrClick = {
    setup: function (data, namespaces) {
        var elem = this, $elem = jQuery(elem);

        if (window.Touch) {
            $elem.bind('touchstart', jQuery.event.special.tabOrClick.onTouchStart);
            $elem.bind('touchmove', jQuery.event.special.tabOrClick.onTouchMove);
            $elem.bind('touchend', jQuery.event.special.tabOrClick.onTouchEnd);
        } else {
            $elem.bind('click', jQuery.event.special.tabOrClick.click);
        }
    },

    click: function (event) {
        event.type = "tabOrClick";
        jQuery.event.handle.apply(this, arguments);
    },

    teardown: function (namespaces) {
        var elem = this, $elem = jQuery(elem);
        if (window.Touch) {
            $elem.unbind('touchstart', jQuery.event.special.tabOrClick.onTouchStart);
            $elem.unbind('touchmove', jQuery.event.special.tabOrClick.onTouchMove);
            $elem.unbind('touchend', jQuery.event.special.tabOrClick.onTouchEnd);
        } else {
            $elem.unbind('click', jQuery.event.special.tabOrClick.click);
        }
    },

    onTouchStart: function (e) {
        this.moved = false;
    },

    onTouchMove: function (e) {
        this.moved = true;
    },

    onTouchEnd: function (event) {
        if (!this.moved) {
            event.type = "tabOrClick";
            jQuery.event.handle.apply(this, arguments)
        }
    }
};

$("#xpto").bind("tabOrClick", function () {
    alert("aaaa");
});
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
Alexandre
  • 7,004
  • 5
  • 54
  • 72
4

I've made a small update to Alexandre's plugin to include Android support. Android's browser does not currently support the window.Touch method of detecting touch support.

I love how Alexandre's script waits to ensure movement didn't occur to prevent triggering the event when the user swipes to scroll across the screen. However a downfall of that approach is that it causes its own delay by waiting for the user to lift their finger off of the screen before triggering. I've updated his plugin to include a "touchactive" class that gets applied to items that a user is currently touching. If you take advantage of that class you can provide immediate visual feedback to users without causing an actual event to get triggered until after movement check has completed.

jQuery.event.special.touchclick = {
    setup: function (data, namespaces) {
    var elem = this, $elem = jQuery(elem);

    var ua = navigator.userAgent.toLowerCase();
    var isAndroid = ua.indexOf("android") > -1;

    if (window.Touch || isAndroid) {
            $elem.bind('touchstart', jQuery.event.special.touchclick.onTouchStart);
            $elem.bind('touchmove', jQuery.event.special.touchclick.onTouchMove);
            $elem.bind('touchend', jQuery.event.special.touchclick.onTouchEnd);
        } else {
            $elem.bind('click', jQuery.event.special.touchclick.click);
        }
    },

    click: function (event) {
        event.type = "touchclick";
        jQuery.event.handle.apply(this, arguments);
    },

    teardown: function (namespaces) {
        var elem = this, $elem = jQuery(elem);
        if (window.Touch) {
            $elem.unbind('touchstart', jQuery.event.special.touchclick.onTouchStart);
            $elem.unbind('touchmove', jQuery.event.special.touchclick.onTouchMove);
            $elem.unbind('touchend', jQuery.event.special.touchclick.onTouchEnd);
        } else {
            $elem.unbind('click', jQuery.event.special.touchclick.click);
        }
    },

    onTouchStart: function (e) {
        this.moved = false;

        $(this).addClass('touchactive');
    },

    onTouchMove: function (e) {
        this.moved = true;

        $(this).removeClass('touchactive');
    },

    onTouchEnd: function (event) {
        if (!this.moved) {
            event.type = "touchclick";
            jQuery.event.handle.apply(this, arguments)
        }

        $(this).removeClass('touchactive');
    }
};

I've also posted this to github in case there are further caveats that are discovered https://github.com/tuxracer/jquery-touchclick

chris
  • 2,467
  • 2
  • 25
  • 25
tuxracer
  • 201
  • 2
  • 5
2

This now works, just like it's stubbed out above, on the latest jQuery release. Go jQuery!

Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
  • In my original post. `$('.clickable').live('touchstart', fn)` works awesome on jquery 1.4.2 and up. `bind` works as well. – Alex Wayne Nov 06 '10 at 06:05
1

Here's a start:

$.fn.touchstart = function(fn) { return this[fn ? "bind" : "trigger"]("touchstart", fn); };
$.event.special.touchstart = {
    setup: function() {
        $.event.add(this, "mouseenter", extendedClickHandler, {});
    },
    teardown: function() {
        $.event.remove(this, "mouseenter", extendedClickHandler);
    }
};

Where extendedClickHandler is the function that does what it's suppose to do.

More info here: http://brandonaaron.net/blog/2009/03/26/special-events

jerone
  • 16,206
  • 4
  • 39
  • 57
0

jQuery.com is a great source of information like this.

If you build your own plugin you'll be able to use whatever naming you like on your method calls.

Tristan Warner-Smith
  • 9,631
  • 6
  • 46
  • 75
  • I was hoping to simply piggy back all the existing event handling and just add support for a few more event types. There is nothing special about these that would require special handling beyond what click or mousedown do. – Alex Wayne Jan 25 '10 at 19:49