ares05
ares05

Reputation: 177

tap event fired after taphold jQuery Mobile 1.1.1

I am developing an app for iOS using Phonegap bundled with jQuery Mobile 1.1.1. I have a div on my page that is listening for both tap and taphold events.

The problem I am facing is that the tap event is fired after the taphold event once I lift my finger. How do I prevent this? A solution is provided here but is this the only way to do this? Kinda nullifies the whole point of having two different events for tap & taphold if you need to use a boolean flag to differentiate the two.

Following is my code:

$('#pageOne').live('pageshow', function(event) {
    $('#divOne').bind('taphold', function (event) {
       console.log("TAP HOLD!!");    
    });

    $('#divOne').bind('tap', function () {
      console.log("TAPPED!!");
    });
});

Would greatly appreciate the help. Thanks!

Upvotes: 5

Views: 5125

Answers (7)

Edson Filho
Edson Filho

Reputation: 66

I still have problems, with jquery-mobile's taphold, I solved the problem of the click called after taphold, putting a timeout on the element. JQM 1.4 with emitTapOnTaphold = false;

Example:

$(".element").on("taphold", function () {
        // function her

         setTimeout (function () {
             $(this).blur();
         400);
});

Upvotes: 0

Long Thanh
Long Thanh

Reputation: 1

$.event.special.tap = { tapholdThreshold: 750,

setup: function() {
    var thisObject = this,
        $this = $( thisObject );

    $this.bind( "vmousedown", function( event ) {

        if ( event.which && event.which !== 1 ) {
            return false;
        }

        var origTarget = event.target,
            origEvent = event.originalEvent,
            /****************Modified Here**************************/
            tapfired = false,
            timer;

        function clearTapTimer() {
            clearTimeout( timer );
        }

        function clearTapHandlers() {
            clearTapTimer();

            $this.unbind( "vclick", clickHandler )
                .unbind( "vmouseup", clearTapTimer );
            $( document ).unbind( "vmousecancel", clearTapHandlers );
        }

        function clickHandler( event ) {
            clearTapHandlers();

            // ONLY trigger a 'tap' event if the start target is
            // the same as the stop target.
            /****************Modified Here**************************/
            //if ( origTarget === event.target) {
             if ( origTarget === event.target && !tapfired) {
                 triggerCustomEvent( thisObject, "tap", event );
             }
        }

        $this.bind( "vmouseup", clearTapTimer )
            .bind( "vclick", clickHandler );
        $( document ).bind( "vmousecancel", clearTapHandlers );

        timer = setTimeout( function() {
            tapfired = true;/****************Modified Here**************************/
            triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );
        }, $.event.special.tap.tapholdThreshold );
    });
}

};

@Akash Budhia: Thanks for your solutions. It's great, sounds it work for me!

Upvotes: -1

Dave
Dave

Reputation: 618

Since swipe, triggers taphold then I was able to keep it simple with:

    $(c).bind("taphold",function(e){
        if(e.target.wait){
            e.target.wait = false;
        }else{
            alert("fire the taphold");
        }//eo if not waiting
    });
    $(c).bind("swipe",function(e){
            e.target.wait = true;//taphold will come next if I don't wave it off
        alert(e.target.text+"("+e.target.attributes.dataId.value+") got swiped");
        return false;
    });

To support tap too then I'd defer the wait clear until the tap event which will also always fire.

Upvotes: 0

Behnam Rasooli
Behnam Rasooli

Reputation: 722

Simply set this at the top of your document or anywhere before you define your even:

$.event.special.tap.emitTapOnTaphold = false;

Then you can use it like this:

$('#button').on('tap',function(){
    console.log('tap!');
}).on('taphold',function(){
    console.log('taphold!');
});

Upvotes: 3

goseese
goseese

Reputation: 1

put this in your taphold event handler... this suggestion assumes o is a jQuery object that fired the taphold

jQuery(o).one('tap click', function(){ return false; });

the binding to the one method will fire the event only once. returning false will stop the execution of that event if it was an < a > tag.

Upvotes: 0

Akash Budhia
Akash Budhia

Reputation: 476

[Tried and Tested] I checked jQuery Mobile's implementation. They are firing the 'tap' event after 'taphold' every time on 'vmouseup'.

Workaround would be not to fire the 'tap' event if the 'taphold' has been fired. Create a custom event or modify the source as per you need as follows:

$.event.special.tap = {
    tapholdThreshold: 750,

    setup: function() {
        var thisObject = this,
            $this = $( thisObject );

        $this.bind( "vmousedown", function( event ) {

            if ( event.which && event.which !== 1 ) {
                return false;
            }

            var origTarget = event.target,
                origEvent = event.originalEvent,
                /****************Modified Here**************************/
                tapfired = false,
                timer;

            function clearTapTimer() {
                clearTimeout( timer );
            }

            function clearTapHandlers() {
                clearTapTimer();

                $this.unbind( "vclick", clickHandler )
                    .unbind( "vmouseup", clearTapTimer );
                $( document ).unbind( "vmousecancel", clearTapHandlers );
            }

            function clickHandler( event ) {
                clearTapHandlers();

                // ONLY trigger a 'tap' event if the start target is
                // the same as the stop target.
                /****************Modified Here**************************/
                //if ( origTarget === event.target) {
                 if ( origTarget === event.target && !tapfired) {
                     triggerCustomEvent( thisObject, "tap", event );
                 }
            }

            $this.bind( "vmouseup", clearTapTimer )
                .bind( "vclick", clickHandler );
            $( document ).bind( "vmousecancel", clearTapHandlers );

            timer = setTimeout( function() {
                tapfired = true;/****************Modified Here**************************/
                triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );
            }, $.event.special.tap.tapholdThreshold );
        });
    }
};

Upvotes: 2

Melvin Joseph Mani
Melvin Joseph Mani

Reputation: 1496

You can use stopImmediatePropagation() method of jquery to solve this issue. According to the explanation in jquery api, stopImmediatePropagation() method

"Keeps the rest of the handlers from being executed and prevents the event from bubbling up the DOM tree."

Upvotes: 0

Related Questions