我正在处理DOM元素上的click和dblclick事件。每个执行一个不同的命令,但我发现双击该元素时,除了触发双击事件外,click事件也会被触发两次。防止这种行为的最佳方法是什么?
答案 0 :(得分:22)
如果其他人偶然发现(正如我所做)寻找答案,我能提出的绝对最佳解决方案如下:
Dim a As Range
Set a = ActiveSheet.Cells.Find("Part Class")
If a Is Nothing Then Exit Sub
Set a = a.EntireColumn
'Note: if any of the terms below are not found then you'll get
' a run-time error
'If you want to ignore those then uncomment the lines noted
'On Error Resume Next '<<##
With a
.Find("CONS").EntireRow.DELETE
.Find("MISC").EntireRow.DELETE
.Find("PFG").EntireRow.DELETE
.Find("PRT").EntireRow.DELETE
.Find("TOTE").EntireRow.DELETE
End With
'On Error Goto 0 '<<##
完成。如果背靠背有多个点击,第二个,第三个等等。不会开枪。我绝对更喜欢使用任何类型的计时器。
我通过阅读this让自己指向了这个方向。
顺便说一句:我第一次研究这个问题是因为我不小心双击了一个分页链接,并且在回调发生之前事件被触发并完成了两次。
在提出上述代码之前,我有
$node.on('click',function(e){
if(e.originalEvent.detail > 1){
return;
/* if you are returning a value from this
function then return false or cancel
the event some other way */
}
});
然而,我能够点击链接3次(三次点击),虽然第二次点击没有触发,但第三次点击
答案 1 :(得分:13)
在评论中,你说,
我将点击处理程序延迟了300毫秒(一个明显而烦人的延迟)甚至......
所以听起来你想要的是,当你点击时,DOM应该立即生成一个点击事件,除非点击是第一次点击双击。
要实现此功能,当您单击时,DOM需要能够预测这是否是最终点击或者是否是双击中的第一次(但我认为通常不可能用于预测用户是否即将再次点击的DOM。
点击和双击时,您尝试采取的两个不同的操作是什么? IMO,在正常的应用程序中,您可能需要两个事件:例如单击以关注元素,然后双击以激活它。
当您必须分开事件时,某些应用程序会使用双击之外的其他内容:例如,他们使用右键单击或按住Control键单击。
答案 2 :(得分:5)
在这种情况下,最好稍微延迟单击事件的执行。让双击处理程序设置单击事件将检查的变量。如果该变量具有特定值,可以是boolDoubleClick == true
,则不要fire/handle
单击。
答案 3 :(得分:4)
如果您想要检测点击元素的次数并根据该次数触发事件,则可以使用UIEvent.detail
。
一个简单的例子:
element.addEventListener("click", function (e) {
if (e.detail === 1) {
// do something if the element was clicked once.
} else if (e.detail === 2) {
// do something else if the element was clicked twice
}
});
答案 4 :(得分:3)
AFAIK DOM Level 2 Events没有双击规范。 它在IE7上对我不起作用(有震撼),但FF和Opera管理规范没有问题,我可以将所有动作附加到click事件,但是双击只是等到“detail”属性事件对象是2.从文档:“如果在同一屏幕位置发生多次点击,则重复序列,每次重复时细节属性都会递增。”
答案 5 :(得分:3)
以下是我在模块中区分的内容
node.on('click', function(e) {
//Prepare for double click, continue to clickHandler doesn't come soon enough
console.log("cleared timeout in click",_this.clickTimeout);
clearTimeout(_this.clickTimeout);
_this.clickTimeout = setTimeout(function(){
console.log("handling click");
_this.onClick(e);
},200);
console.log(_this.clickTimeout);
});
node.on('dblclick', function (e) {
console.log("cleared timeout in dblclick",_this.clickTimeout);
clearTimeout(_this.clickTimeout);
// Rest of the handler function
答案 6 :(得分:2)
感谢这里的所有其他答案,因为它们的组合似乎为我提供了一个合理的解决方案,当交互需要两者,但互相排斥时:
var pendingClick = 0;
function xorClick(e) {
// kill any pending single clicks
if (pendingClick) {
clearTimeout(pendingClick);
pendingClick = 0;
}
switch (e.detail) {
case 1:
pendingClick = setTimeout(function() {
console.log('single click action here');
}, 500);// should match OS multi-click speed
break;
case 2:
console.log('double click action here');
break;
default:
console.log('higher multi-click actions can be added as needed');
break;
}
}
myElem.addEventListener('click', xorClick, false);
更新:我添加了此方法的通用版本以及针对此Github存储库的触摸设备的点击填充,并附带示例:
答案 7 :(得分:0)
我知道这已经老了,但我想我发布的任何内容,因为我遇到了同样的问题。以下是我如何解决它。
@include imgRetina('../assets/images/logo', png, 370px, 115px);
答案 8 :(得分:0)
如果我的dblclick事件应该执行其他操作,则我将这种解决方案用于我的项目以防止点击事件操作。
注意:此解决方案仅适用于click和dblclick,而不适用于其他任何东西,例如Tripleclick等。
要查看单击和双击之间的正确时间,请参见this
对不起,我的英语不好。 希望对您有所帮助:)
var button, isDblclick, timeoutTiming;
var clickTimeout, dblclickTimeout;
//-----
button = $('#button');
isDblclick = false;
/*
the proper time between click and dblclick is not standardized,
and is cutsomizable by user apparently (but this is windows standard I guess!)
*/
timeoutTiming = 500;
//-----
button.on('dblclick', function () {
isDblclick = true;
clearTimeout(dblclickTimeout);
dblclickTimeout = setTimeout(function () {
isDblclick = false;
}, timeoutTiming);
//-----
// here goes your dblclick codes
console.log('double clicked! not click.');
}).on('click', function () {
clearTimeout(clickTimeout);
clickTimeout = setTimeout(function () {
if(!isDblclick) {
// here goes your click codes
console.log('a simple click.');
}
}, timeoutTiming);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" id="button">
click/dblclick on this to see the result
</button>
答案 9 :(得分:0)
这是防止第二次点击的简单解决方案。当然,当检测到双击时,我可以重新启动超时,但实际上我根本不需要它。
update-ca-certificates
答案 10 :(得分:0)
总结一下,要识别同一元素上的simpleClick和doubleClick事件,只需使用以下方法处理onClick事件:
var EVENT_DOUBLE_CLICK_DELAY = 220; // Adjust max delay btw two clicks (ms)
var eventClickPending = 0;
function onClick(e){
if ((e.detail == 2 ) && (eventClickPending!= 0)) {
// console.log('double click action here ' + e.detail);
clearTimeout(eventClickPending);
eventClickPending = 0;
// call your double click method
fncEventDblclick(e);
} else if ((e.detail === 1 ) && (eventClickPending== 0)){
// console.log('sigle click action here 1');
eventClickPending= setTimeout(function() {
// console.log('Executing sigle click');
eventClickPending = 0
// call your single click method
fncEventClick(e);
}, EVENT_DOUBLE_CLICK_DELAY);
// } else { // do nothing
// console.log('more than two clicks action here ' + e.detail);
}
}
答案 11 :(得分:0)
您可以使用 debounce 使单击处理程序免于检测双击/多次单击
测试:https://jsfiddle.net/L3sajybp/
HTML
<div id='toDetect'>
Click or double-click me
</div>
<hr/>
<ol id='info'>
</ol>
JS
function debounce(func, wait, immediate) {
let timeout;
return function () {
const context = this,
args = arguments;
const later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
function debounceSingleClickOnly(func, timeout = 500) {
function eventHandler (event) {
const { detail } = event;
if (detail > 1) {
console.log('no double click for you '+ func.name);
console.log('');
return;
}
func.apply(this, arguments);
}
return debounce(eventHandler, timeout);
}
window.toDetect.addEventListener('click', debounceSingleClickOnly(handleSingleClick));
window.toDetect.addEventListener('dblclick', handleDoubleClick);
function handleS() {
console.log('S func');
console.log(this.id);
}
function handleSingleClick(event) {
console.log('single click');
const divText = document.createElement('li');
divText.appendChild(document.createTextNode('single click'));
window.info.appendChild(divText)
console.group();
console.log('this element was single-clicked: ' + event.target.id);
console.log(this.id);
console.log('');
console.groupEnd();
}
function handleDoubleClick(event) {
console.log('double click');
const divText = document.createElement('li');
divText.appendChild(document.createTextNode('double click'));
window.info.appendChild(divText);
console.group();
console.log('this element was double-clicked: ' + event.target.id);
console.log(this.id);
console.log('');
console.groupEnd();
}
答案 12 :(得分:-1)
const toggle = () => {
watchDouble += 1;
setTimeout(()=>{
if (watchDouble === 2) {
console.log('double' + watchDouble)
} else if (watchDouble === 1) {
console.log("signle" + watchDouble)
}
watchDouble = 0
},200);
}