jQuery在taphold事件后调用click事件 [英] jQuery calling click event after taphold event
问题描述
我正在使用 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();
}
推荐答案
而不是使用 tap
和 taphold
(我曾尝试使用但遇到了同样的问题)问题,这似乎是 taphold
事件的固有问题)您可以使用 vmousedown
并设置一个标志,然后绑定到 vmouseup
来确定如果是 tap
或 taphold
:
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屋!