7

I'm trying to figure out how to solve the tapped class being assigned to the elements when scrolling, but it's taking effect too quick which I need to delay it a bit when it's actually touched instead of touched while scrolling, this is my code of how it works:

$('div, a, span').filter('[tappable][data-tappable-role]').bind('touchstart', function()
{
    var self = $(this);

    self.addClass(self.data('tappable-role'));
}).bind('touchend', function()
{
    var self = $(this);
    self.removeClass(self.data('tappable-role'));
}).bind('click', function()
{
    var self = $(this),
        goTo = self.data('goto');

    if(typeof goTo !== 'undefined')
    {
        window.location = goTo;
    }
});

When scrolling, it will assign the class to the element when I've barely touched it, I want to prevent this from happening unless it's properly touched (not clicked). Although I tried experimenting with the setTimeout, but that doesn't work well as it delays but it will still assign the class later on.

This is how I did it with the setTimeout:

var currentTapped;
$('div, a, span').filter('[tappable][data-tappable-role]').bind('touchstart', function()
{
    clearTimeout(currentTapped);

    var self = $(this);

    var currentTapped = setTimeout(function()
    {
        self.addClass(self.data('tappable-role'));
    }, 60);
}).bind('touchend', function()
{
    clearTimeout(currentTapped);

    var self = $(this);
    self.removeClass(self.data('tappable-role'));
}).bind('click', function()
{
    clearTimeout(currentTapped);

    var self = $(this),
        goTo = self.data('goto');

    if(typeof goTo !== 'undefined')
    {
        window.location = goTo;
    }
});

How can I do this the effective way?

You need to view it on your iPhone/iPod/iPad or an emulator to test the fiddle.

UPDATE:

function nextEvent() 
{
    $(this).on('touchend', function(e)
    {
        var self = $(this);

        self.addClass(self.data('tappable-role')).off('touchend');
    })
    .on('touchmove', function(e)
    {
        var self = $(this);

        self.removeClass(self.data('tappable-role')).off('touchend');
    })
    .click(function()
    {
        var self = $(this),
            goTo = self.data('goto');

        if(typeof goTo !== 'undefined')
        {
            window.location = goTo;
        }
    });
}

$('div, a, span').filter('[tappable][data-tappable-role]').on('touchstart', this, nextEvent);
MacMac
  • 34,294
  • 55
  • 151
  • 222

2 Answers2

21

Here's how I did it:

Essentially, when you navigate a page you're going to tap or scroll. (Well there are other things like pinch and slide put you can figure them out later)...

So on a tap your 'touchstart' will be followed by a 'touchend' On a scroll your 'touchstart' will be followed by a 'touchmove'

Using Jq 1.7... on other versions you can use .bind()

function nextEvent() {
    //behaviour for end
    $(this).on('touchend', function(e){
        /* DO STUFF */
        $(this).off('touchend');
    });
    //behaviour for move
    $(this).on('touchmove', function(e){
        $(this).off('touchend');
    });     
}

$('div, a, span').filter('[tappable][data-tappable-role]').on('touchstart', this, nextEvent);

Basically, when a 'touchstart' happens, I bind actions to 'touchend' and 'touchmove'.

'Touchend' does whatever I would want a tap to do and then unbinds itself 'Touchmove' basically does nothing except unbind 'touchend'

This way if you tap you get action, if you scroll nothing happens but scrolling..

RESPONSE TO COMMENT: If I understand your comment properly, try this:

function nextEvent() {
    var self = $(this);
    self.addClass(self.data('tappable-role'))
    //behaviour for move
    $(this).on('touchmove', function(e){
         self.removeClass(self.data('tappable-role'));
    });     
}

$('div, a, span').filter('[tappable][data-tappable-role]').on('touchstart', this, nextEvent);
Thierry Blais
  • 2,848
  • 22
  • 41
  • Hmm, I'm not sure why, but the tapped class only gets assigned after it's clicked, when I hold my finger down without moving, it doesn't show the tapped class when it should and removed when scrolling. Check my edit of how I did it. – MacMac Mar 23 '12 at 20:26
  • That's how I would expect it to behave, nothing should happen unless you touch the screen and then take your finger off the screen without scrolling...if you want to assign a class while your finger is on the screen assign it before you bind the events in nextEvent() just remember to remove it in your touchmove bind... in fact from what your telling me get rid of the touchend bind alltogether and assign the class as soon as nextEvent() is called... – Thierry Blais Mar 23 '12 at 20:40
  • You can remove the .off('touchend') in the touchmove bind, I realize now that it's superfluous... – Thierry Blais Mar 24 '12 at 11:33
  • The .off('touchend') is not superfluous, with out it the touchend is still triggered. – Styledev Apr 01 '16 at 21:01
3

Despite this is a relatively old question with a best answer already selected, I want to share my solution. I achieved this by triggering the events just on click.

$("div, a, span").on("click", function() {
    // Your code here
}

Maybe is not the best way to do it, but this worked for me.

Mithc
  • 851
  • 8
  • 23