jQuery在taphold事件后调用click事件 [英] jQuery calling click event after taphold event

查看:24
本文介绍了jQuery在taphold事件后调用click事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Jquery 和 Jquery Mobile 为 Android 开发 PhoneGap 应用.

I'm developing a PhoneGap app for Android using Jquery and Jquery Mobile.

我有一个项目列表,需要将两个事件绑定到列表中的每个项目.我需要一个taphold"事件和一个click"事件.我遇到的问题是当我执行taphold"时,会触发正确的taphold"事件.但是,一旦我释放,click 事件也会被触发.如何防止点击事件在点击后触发?

I've got a list of items that need two events bound to each item in the list. I need a "taphold" event and a "click" event. The problem I'm having is when I do a "taphold", the correct "taphold" event is fired. However, as soon as I release, the click event is also fired. How can I prevent the click event from firing after a taphold?

代码:

function LoadMyItems(items) {

for(var idx in items)
{
    var itemLine = '<div class="my_item" id="my_item_'+items[idx].user_item_id+'">' +
           '<img class="item_icon_32" src=./images/graphicFiles/Icon48/'+items[idx].item.graphic.graphicFiles.Icon48.filename+' />' +
           items[idx].item.name+    
           '</div>';
    $('#my_list').append('<li>'+itemLine+'</li>');
        $('#my_item_'+items[idx].user_item_id).bind('taphold', {userItem:items[idx]},ShowMyItemInfo);
        $('#my_item_'+items[idx].user_item_id).bind('click tap', {userItem:items[idx]},FitMyUpgradeItem);
        console.log('UserItem '+items[idx].user_item_id+' loaded and events bound');
    }
    $('#my_items_loader').hide();
    myScroll.refresh();
}

根据下面的建议,这就是我的结论.这适用于 iScroll 对象.

After the advice below, Here is what I ended up with. This works inside the iScroll object.

function LoadMyItems(items) {

for(var idx in items)
{
    var itemLine = '<div class="my_item" id="my_item_'+items[idx].user_item_id+'">' +
                   '<img class="item_icon_32" src=./images/graphicFiles/Icon48/'+items[idx].item.graphic.graphicFiles.Icon48.filename+' />' +
                   items[idx].item.name+    
                   '</div>';
    $('#my_list').append('<li>'+itemLine+'</li>');

    (function(index) {
        var tapTime = 0;
        var xPos = 0;
        var yPos = 0;
        $('#my_item_'+items[index].user_item_id).bind('vmousedown vmouseup', function (event) {
            if (event.type == 'vmousedown') {

                tapTime = new Date().getTime();
                xPos = event.pageX;
                yPos = event.pageY;

                var timer = setTimeout(function() {
                    var duration = (new Date().getTime() - tapTime);
                    var xDiff = Math.abs(mouseXPos - xPos);
                    var yDiff = Math.abs(mouseYPos - yPos);
                    if(duration >= 700 && (yDiff <= 40 || mouseXPos == 0))
                        ShowItemInfo(items[index].item);
                },750);
            } else {
                //event.type == 'vmouseup'
                var duration = (new Date().getTime() - tapTime);
                var xDiff = Math.abs(event.pageX - xPos);
                var yDiff = Math.abs(event.pageY - yPos);
                tapTime = new Date().getTime();
                if (duration < 699 && yDiff <= 40) {
                    //this is a tap
                    FitMyUpgradeItem(items[index]);
                }
            }
        });

        $('#my_item_'+items[index].user_item_id).bind('touchmove',function(event) {
            event.preventDefault();
        });
    })(idx);

    console.log('UserItem '+items[idx].user_item_id+' loaded and events bound');
}
$('#my_items_loader').hide();
myScroll.refresh();
}

推荐答案

而不是使用 taptaphold(我曾尝试使用但遇到了同样的问题)问题,这似乎是 taphold 事件的固有问题)您可以使用 vmousedown 并设置一个标志,然后绑定到 vmouseup 来确定如果是 taptaphold:

Rather than use tap and taphold (which I've tried to use but ran into the same problems, it seems to be an inherent issue with the taphold event) you can use vmousedown and set a flag, then bind to vmouseup to determine if it was a tap or a taphold:

var tapTime = 0;
$('#my_item_'+items[idx].user_item_id).bind('vmousedown vmouseup', function (event) {
    if (event.type == 'vmousedown') {
        tapTime = new Date().getTime();
    } else {
        //event.type == 'vmouseup'
        //here you can check how long the `tap` was to determine what do do

        var duration = (new Date().getTime() - tapTime);
        if (duration > 3000) {
            //this is a tap-hold
            ShowMyItemInfo(items[idx]);
        } else {
            //this is a tap
            FitMyUpgradeItem(items[idx]);
        }
    }
});

为了使其正常工作,您必须在循环代码周围添加 IIFE 或更改 ShowMyItemInfo(items[idx]); 以在不引用更改每次迭代的变量的情况下工作环形.创建 IIFE 的一个简单方法是使用 $.each().否则你的循环看起来像这样:

For this to work properly you'll have to add an IIFE around the loop-code or change ShowMyItemInfo(items[idx]); to work without referencing the variable that changes each iteration of the loop. An easy to create an IIFE is to just use $.each(). Otherwise your loop would look something like this:

for(var idx in items)
{
    (function (idx) {
        ...
    })(idx);
}

IIFE = 立即调用函数表达式.它允许我们拍摄快照"我们传递给 IIFE 的变量的当前状态.因此,当我们传入 idx(从技术上讲,第二个实例是传入的变量,第一个实例是 IIFE 内部可用的变量,可以更改为类似 ids_new 为简单起见),传入的值将在 tap 事件处理程序触发时保存.

IIFE = Immediately-Invoked-Function-Expression. It allows us to take a "snapshot" of the current state of variables we pass into the IIFE. So as we pass in idx (technically the second instance is the variable that's being passed in, and the first instance is the variable available inside the IIFE, which could be changed to something like ids_new for simplicity sake), the value passed in is saved for when the tap event handler fires.

您还可以设置超时来确定 taphold 而不是使用 vmouseup 事件:

You can also set a timeout to determine taphold rather than using the vmouseup event:

//setup a timer and a flag variable
var tapTimer,
    isTapHold = false;
$('#my_item_'+items[idx].user_item_id).bind('vmousedown vmouseup', function (event) {
    if (event.type == 'vmousedown') {

        //set the timer to run the `taphold` function in three seconds
        //
        tapTimer = setTimeout(function () {
            isTapHold = true;
            ShowMyItemInfo(items[idx]);
        }, 3000);
    } else {
        //event.type == 'vmouseup'
        //clear the timeout if it hasn't yet occured
        clearTimeout(tapTimer);    

        //if the flag is set to false then this is a `tap` event
        if (!isTapHold) {
            //this is a tap, not a tap-hold
            FitMyUpgradeItem(items[idx]);
        }

        //reset flag
        isTapHold = false;
    }
});

这样事件就会在用户按住手指三秒钟后触发.然后 tap 事件处理程序只会在这三秒没有发生时触发.

This way the event will fire after the user holds down their finger for three seconds. Then the tap event handler will only fire if that three seconds did not occur.

这篇关于jQuery在taphold事件后调用click事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆