我正在使用Jquery和Jquery Mobile开发适用于Android的PhoneGap应用程序。
我有一个项目列表需要绑定到列表中每个项目的两个事件。我需要一个“taphold”活动和一个“点击”活动。我遇到的问题是当我做“taphold”时,正确的“taphold”事件被解雇了。但是,一旦我发布,click事件也会被触发。如何防止点按事件在敲击后触发?
代码:
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对象。
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();
}
答案 0 :(得分:12)
而不是使用tap
和taphold
(我试过使用但遇到同样的问题,似乎是taphold
事件的固有问题)你可以使用vmousedown
并设置一个标记,然后绑定到vmouseup
以确定它是tap
还是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(var idx in items)
{
(function (idx) {
...
})(idx);
}
IIFE =立即调用函数表达式。它允许我们对我们传递到IIFE的变量的当前状态进行“快照”。因此,当我们传入idx
时(从技术上讲,第二个实例是传入的变量,第一个实例是IIFE中可用的变量,为简单起见,可以将其更改为ids_new
),传入的值将在tap
事件处理程序触发时保存。
您还可以设置超时以确定taphold
,而不是使用vmouseup
事件:
//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
事件处理程序将仅在未发生三秒时触发。
答案 1 :(得分:5)
在定义偶数之前,只需将其设置在文档顶部或任何位置:
$.event.special.tap.emitTapOnTaphold = false;
然后你可以像这样使用它:
$('#button').on('tap',function(){
console.log('tap!');
}).on('taphold',function(){
console.log('taphold!');
});
答案 2 :(得分:1)
就个人而言,我认为这里的答案过于复杂。如果您只是想要一种简单的方法来继续使用taphold事件并忽略释放taphold时触发的click事件,那么我在自己的项目中解决了同样的问题:
// We will use this flag to ignore click events we don't want
var skipNextClick = false;
//Set up your event handler. You could do these using two handlers or one. I chose one.
$('div.element').on('click taphold', function (e) {
//set up a quick bool flag that is true if click
var isClick = (e.type == 'click');
if (isClick && !skipNextClick) {
//run your code for normal click events here...
}
else if (isClick && skipNextClick) {
//this is where skipped click events will end up...
//we need to reset our skipNextClick flag here,
//this way, our next click will not be ignored
skipNextClick = false;
}
else {
//taphold event
//to ignore the click event that fires when you release your taphold,
//we set the skipNextClick flag to true here.
skipNextClick = true;
//run your code for taphold events here...
}
});
答案 3 :(得分:0)
使用tap \ _ vclick和taphold - Tap事件在taphold之后被触发两次。
$('#my_item_'+items[idx].user_item_id).bind('vclick', ...
$('#my_item_'+items[idx].user_item_id).bind('taphold', ...
在此示例中,实际上未在taphold之后调用click。请在此处查看:http://jsfiddle.net/YL8hj/43/
修改强>
jQuery Mobile自动将触摸事件绑定到某些元素。什么时候 将iScroll与jQuery Mobile结合起来,绑定一个可能是一个好主意 将功能分开到'touchmove'事件并阻止事件发生 冒泡(event.preventDefault())。通过这个jQuery Mobile 用户进行交互时将无法处理触摸事件 使用iScroll元素。
也http://appcropolis.com/blog/jquery-wrapper-for-iscroll/ 信用https://stackoverflow.com/a/9408567/643500