taphold事件后的jQuery调用点击事件 [英] 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事件和一个点击事件。我遇到的问题是当我做一个taphold,正确的taphold事件被触发。但是,一旦我释放,点击事件也被触发。如何防止点击事件在点击后触发?
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();
}
推荐答案
$ c>点击和 taphold
(我试图使用但遇到相同的问题,它似乎是一个固有的问题, taphold
事件),您可以使用 vmousedown
并设置一个标志,然后绑定到 vmouseup
以确定它是
点击
还是 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, code> 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 = Immediately-Invoked-函数表达式。它允许我们对我们传入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;
}
});
这样,用户按住手指三秒钟后,事件将触发。然后点击
事件处理程序只有在三秒没有发生时才会触发。
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.
这篇关于taphold事件后的jQuery调用点击事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!