长按JavaScript吗?


117

是否可以在JavaScript(或jQuery)中实现“长按”?怎么样?

替代文字
(来源:androinica.com

的HTML

<a href="" title="">Long press</a>

的JavaScript

$("a").mouseup(function(){
  // Clear timeout
  return false;
}).mousedown(function(){
  // Set timeout
  return false; 
});

7
我可能会以您的代码为基础创建自定义jQuery事件,所以您可以做jQuery(...).longclick(function() { ... });
Matti Virkkunen 2010年

1
这个问题没有用jQuery标记,尽管应该。该问题首先要求一个纯Javascript解决方案,我更喜欢该解决方案,或者可选地(在括号中)一个jQuery解决方案。大多数答案似乎默认使用jQuery作为标准假设。我一直鄙视jQuery,从未使用过它,也从未感到过任何迫切的需求。有些人喜欢对每个人使用它,这很好。使用这两种技术的答案都没有任何伤害。但是由于该问题将接受jQuery解决方案,因此jQuery标签可能会引起更多关注,并希望有更好的答案。jQuery的答案在这里似乎很乏味。

Answers:


159

没有“ jQuery”魔术,只有JavaScript计时器。

var pressTimer;

$("a").mouseup(function(){
  clearTimeout(pressTimer);
  // Clear timeout
  return false;
}).mousedown(function(){
  // Set timeout
  pressTimer = window.setTimeout(function() { ... Your Code ...},1000);
  return false; 
});

39
难道这也不会发火吗?
Gallal 2012年

11
@Gallal据推测这将是通过打电话给于相当简单clearTimeout(pressTimer)mousemove,除非我失去了一些东西。诚然,这几乎是无与伦比的。
大卫·约翰·威尔士

5
@DavidJohnWelsh就像我一直在看的那样,您不只是想让鼠标移动-让您的手指不动并保持不动1px非常困难!您需要应用一个阈值(如果鼠标没有移动10px)等等。变得非常复杂!
伊恩

6
请记住,如果您希望此功能在手机上可以正常使用,则它们通常具有自己的默认长按行为(例如,在Android上为Chrome,长按链接时会显示带有各种选项的模式菜单)。我没有很多运气可以阻止这种情况,老实说,干扰浏览器的默认行为对任何人来说都是一个隐患。
dartacus

4
尽管这是选择的答案,但实际上并不能回答问题。它过于简单和天真。任何长按事件都必须解决该答案忽略的多个问题。1)区分长按是否来自多点触控手势拖动(即,放大或缩小)2)如果移动超出元素或浏览器区域,则取消; 3)解决大量平台和设备上文本选择的默认行为4)允许可配置的阈值以提高敏感度,而不依赖于幻数。对于可访问性问题特别有用,但不仅限于此。

34

根据Maycow Moura的回答,我写了这个。它还可以确保用户没有单击右键,这将触发长按并在移动设备上工作。演示

var node = document.getElementsByTagName("p")[0];
var longpress = false;
var presstimer = null;
var longtarget = null;

var cancel = function(e) {
    if (presstimer !== null) {
        clearTimeout(presstimer);
        presstimer = null;
    }

    this.classList.remove("longpress");
};

var click = function(e) {
    if (presstimer !== null) {
        clearTimeout(presstimer);
        presstimer = null;
    }

    this.classList.remove("longpress");

    if (longpress) {
        return false;
    }

    alert("press");
};

var start = function(e) {
    console.log(e);

    if (e.type === "click" && e.button !== 0) {
        return;
    }

    longpress = false;

    this.classList.add("longpress");

    if (presstimer === null) {
        presstimer = setTimeout(function() {
            alert("long click");
            longpress = true;
        }, 1000);
    }

    return false;
};

node.addEventListener("mousedown", start);
node.addEventListener("touchstart", start);
node.addEventListener("click", click);
node.addEventListener("mouseout", cancel);
node.addEventListener("touchend", cancel);
node.addEventListener("touchleave", cancel);
node.addEventListener("touchcancel", cancel);

您还应该包括一些使用CSS动画的指标:

p {
    background: red;
    padding: 100px;
}

.longpress {
    -webkit-animation: 1s longpress;
            animation: 1s longpress;
}

@-webkit-keyframes longpress {
    0%, 20% { background: red; }
    100% { background: yellow; }
}

@keyframes longpress {
    0%, 20% { background: red; }
    100% { background: yellow; }
}

我做了这个修改后的版本,可以在按住jsfiddle的同时不断地执行某些操作,但是由于某种原因,即使您停止触摸+按钮,它也可以在Android上运行...
Xander

@Xander:也许是因为:hover状态在触摸设备上很粘,也许在这里也适用。
kelunik 2015年

Dang,我想知道是否有任何方法可以使支持长按的移动网站上的-/ +数字增加按钮起作用。我发现的每种方法仅支持必须重复单击,这对于大量用户来说是一个痛苦。不过谢谢!
Xander

@Xander:实际上,touchend应该触发IMO,当它是用于触摸设备的特殊代码时,没有理由让它发粘,也许我明天会尝试一些。
kelunik 2015年

1
找出Android上的问题。按下会同时按下鼠标并触发touchstart,因此它有2个计时器在运行,但是只有1个通过举起手指被取消。用if(presstimer === null)包装presstimer,以确保计时器尚未激活。
Xander


16

我创建了长按事件 (0.5k纯JavaScript)来解决此问题,它long-press向DOM 添加了一个事件。

long-press任何元素上侦听:

// the event bubbles, so you can listen at the root level
document.addEventListener('long-press', function(e) {
  console.log(e.target);
});

侦听long-press一个在特定的元素:

// get the element
var el = document.getElementById('idOfElement');

// add a long-press event listener
el.addEventListener('long-press', function(e) {

    // stop the event from bubbling up
    e.preventDefault()

    console.log(e.target);
});

适用于IE9 +,Chrome,Firefox,Safari和混合移动应用程序(iOS / Android上为Cordova和Ionic)

演示版


2
太棒了,伙计!
杰夫T.

1
该解决方案以某种偶然,不完整和非标准的方式修补window.CustomEvent对象。它不能正确地将只读属性创建为只读,而是以读写方式创建。特别是缺少returnValue,type,timeStamp和isTrusted。它没有解决长按的拖动,手势,捏放大或缩小或多点触摸失火的问题,也没有解决大量设备和/或平台的问题,这些设备和/或平台默认甚至在500毫秒时仍会长按以选择文本。对于这些情况,该库缺少任何和所有测试用例。

4
它是开源的,随时为该项目做出贡献:)
John Doherty

@JohnDoherty太好了!但是我们仍然可以将“ onClick”与相同的元素一起使用吗?
Devashish

2
只要在“长按延迟”计时器启动之前释放长按,您就仍然应该获得“ onclick”事件
John Doherty

15

虽然看起来很简单,可以通过超时和几个鼠标事件处理程序自行实现,但是当您考虑单击-拖动-释放之类的情况时,它会变得稍微复杂一些,同时支持在同一元素上按下和长按,并与iPad等触控设备配合使用。我最终使用了longclick jQuery插件Github),它为我处理了这些事情。如果您只需要支持触摸屏设备(例如手机),则还可以尝试jQuery Mobile taphold事件


Github链接有效,但该项目自2010年以来未进行更新,并且不适用于当前的jquery版本。但是,在源代码中用handle.apply替换handle.apply可以解决此问题。
arlomedia '16

11

jQuery插件。刚放$(expression).longClick(function() { <your code here> });。第二个参数是保持时间;默认超时为500毫秒。

(function($) {
    $.fn.longClick = function(callback, timeout) {
        var timer;
        timeout = timeout || 500;
        $(this).mousedown(function() {
            timer = setTimeout(function() { callback(); }, timeout);
            return false;
        });
        $(document).mouseup(function() {
            clearTimeout(timer);
            return false;
        });
    };

})(jQuery);

这不会保留在通话中。
2015年

喜兄弟,我们可以使用它作为一个支柱事件
user2075328

6

对于跨平台开发人员(请注意,到目前为止给出的所有答案均不适用于iOS)

Mouseup / down似乎在android上可以正常工作-但并非所有设备(例如,三星tab4)。在iOS上根本无法使用。

进一步的研究看来,这是由于元素具有选择性,并且自然放大率干扰了听众。

如果用户按住图片500毫秒,则此事件侦听器可以以自举模式打开缩略图。

它使用了响应式图像类,因此显示了较大版本的图像。此代码段已在(iPad / Tab4 / TabA / Galaxy4)上经过全面测试:

var pressTimer;  
$(".thumbnail").on('touchend', function (e) {
   clearTimeout(pressTimer);
}).on('touchstart', function (e) {
   var target = $(e.currentTarget);
   var imagePath = target.find('img').attr('src');
   var title = target.find('.myCaption:visible').first().text();
   $('#dds-modal-title').text(title);
   $('#dds-modal-img').attr('src', imagePath);
   // Set timeout
   pressTimer = window.setTimeout(function () {
      $('#dds-modal').modal('show');
   }, 500)
});

iOS的不错解决方案
eric xu

我如何防止从缩略图开始的触摸,但最终以滚动显示。换句话说,不是触摸开始/结束,而是在带有处理程序的元素上开始的触摸,但最终变成滚动
Akin Hwan

5
$(document).ready(function () {
    var longpress = false;

    $("button").on('click', function () {
        (longpress) ? alert("Long Press") : alert("Short Press");
    });

    var startTime, endTime;
    $("button").on('mousedown', function () {
        startTime = new Date().getTime();
    });

    $("button").on('mouseup', function () {
        endTime = new Date().getTime();
        longpress = (endTime - startTime < 500) ? false : true;
    });
});

演示


2
这段代码不会在500ms结束时触发longclick。用户可以通过单击鼠标来死:)。仅当用户停止单击按钮时,才会触发长按。
绝地武士

当用户开始滚动而不是在同一位置完成长按时,是否可以涵盖这种情况?
阿金焕

@AkinHwan不,只有在同一元素上释放鼠标单击时,它才会被触发。
拉兹

4

Diodeus的答案很棒,但是它阻止您添加onClick函数,如果您放置onclick,它将永远不会运行hold函数。Razzak的答案几乎是完美的,但是它仅在mouseup上运行保持功能,并且通常,即使用户保持保持状态,该功能也会运行。

因此,我同时加入了这两个团队,并做到了:

$(element).on('click', function () {
    if(longpress) { // if detect hold, stop onclick function
        return false;
    };
});

$(element).on('mousedown', function () {
    longpress = false; //longpress is false initially
    pressTimer = window.setTimeout(function(){
    // your code here

    longpress = true; //if run hold function, longpress is true
    },1000)
});

$(element).on('mouseup', function () {
    clearTimeout(pressTimer); //clear time on mouseup
});

如果用户在鼠标按下后开始滚动并且不打算进行长按操作该怎么办
Akin Hwan


2

您可以在按下鼠标时设置该元素的超时,并在按下鼠标时清除它:

$("a").mousedown(function() {
    // set timeout for this element
    var timeout = window.setTimeout(function() { /* … */ }, 1234);
    $(this).mouseup(function() {
        // clear timeout for this element
        window.clearTimeout(timeout);
        // reset mouse up event handler
        $(this).unbind("mouseup");
        return false;
    });
    return false;
});

有了这个,每个元素都有自己的超时时间。


1
$(this).mouseup(function(){});不删除事件处理程序,而是添加另一个事件处理程序。使用.unbind代替。
Matti Virkkunen

应该off()现在使用而不是取消绑定。
dbinott

1

您可以使用jquery-mobile的Taphold。包括jquery-mobile.js,以下代码将正常工作

$(document).on("pagecreate","#pagename",function(){
  $("p").on("taphold",function(){
   $(this).hide(); //your code
  });    
});

这应该是公认的答案,因为jquery-mobile提供了一个很好的稳定框架
pasx 2015年

1

最优雅,最简洁的是一个jQuery插件:https : //github.com/untill/jquery.longclick/,也可以作为packacke使用:https ://www.npmjs.com/package/jquery.longclick 。

简而言之,您可以这样使用它:

$( 'button').mayTriggerLongClicks().on( 'longClick', function() { your code here } );

与此处的其他一些答案相比,此插件的优点是单击事件仍然可能。还要注意的是,长按会发生,就像在设备上长按鼠标一样,然后单击鼠标。因此,这是一个功能。


0

对我来说,它可以使用该代码(使用jQuery):

var int       = null,
    fired     = false;

var longclickFilm = function($t) {
        $body.css('background', 'red');
    },
    clickFilm = function($t) {
        $t  = $t.clone(false, false);
        var $to = $('footer > div:first');
        $to.find('.empty').remove();
        $t.appendTo($to);
    },
    touchStartFilm = function(event) {
        event.preventDefault();
        fired     = false;
        int       = setTimeout(function($t) {
            longclickFilm($t);
            fired = true;
        }, 2000, $(this)); // 2 sec for long click ?
        return false;
    },
    touchEndFilm = function(event) {
        event.preventDefault();
        clearTimeout(int);
        if (fired) return false;
        else  clickFilm($(this));
        return false;
    };

$('ul#thelist .thumbBox')
    .live('mousedown touchstart', touchStartFilm)
    .live('mouseup touchend touchcancel', touchEndFilm);

0

您可以检查时间来确定单击或长按[jQuery]

function AddButtonEventListener() {
try {
    var mousedowntime;
    var presstime;
    $("button[id$='" + buttonID + "']").mousedown(function() {
        var d = new Date();
        mousedowntime = d.getTime();
    });
    $("button[id$='" + buttonID + "']").mouseup(function() {
        var d = new Date();
        presstime = d.getTime() - mousedowntime;
        if (presstime > 999/*You can decide the time*/) {
            //Do_Action_Long_Press_Event();
        }
        else {
            //Do_Action_Click_Event();
        }
    });
}
catch (err) {
    alert(err.message);
}
} 

0

像这样?

doc.addEeventListener("touchstart", function(){
    // your code ...
}, false);    

0

您可以使用jquery触摸事件。(见这里

  let holdBtn = $('#holdBtn')
  let holdDuration = 1000
  let holdTimer

  holdBtn.on('touchend', function () {
    // finish hold
  });
  holdBtn.on('touchstart', function () {
    // start hold
    holdTimer = setTimeout(function() {
      //action after certain time of hold
    }, holdDuration );
  });

0

我需要一些用于长按键盘事件的东西,所以我写了这个。

var longpressKeys = [13];
var longpressTimeout = 1500;
var longpressActive = false;
var longpressFunc = null;

document.addEventListener('keydown', function(e) {
    if (longpressFunc == null && longpressKeys.indexOf(e.keyCode) > -1) {
        longpressFunc = setTimeout(function() {
            console.log('longpress triggered');
            longpressActive = true;
        }, longpressTimeout);

    // any key not defined as a longpress
    } else if (longpressKeys.indexOf(e.keyCode) == -1) {
        console.log('shortpress triggered');
    }
});

document.addEventListener('keyup', function(e) {
    clearTimeout(longpressFunc);
    longpressFunc = null;

    // longpress key triggered as a shortpress
    if (!longpressActive && longpressKeys.indexOf(e.keyCode) > -1) {
        console.log('shortpress triggered');
    }
    longpressActive = false;
});

0

我认为这可以帮助您:

var image_save_msg = 'You Can Not Save images!';
var no_menu_msg = 'Context Menu disabled!';
var smessage = "Content is protected !!";

function disableEnterKey(e) {
    if (e.ctrlKey) {
        var key;
        if (window.event)
            key = window.event.keyCode; //IE
        else
            key = e.which; //firefox (97)
        //if (key != 17) alert(key);
        if (key == 97 || key == 65 || key == 67 || key == 99 || key == 88 || key == 120 || key == 26 || key == 85 || key == 86 || key == 83 || key == 43) {
            show_wpcp_message('You are not allowed to copy content or view source');
            return false;
        } else
            return true;
    }
}

function disable_copy(e) {
    var elemtype = e.target.nodeName;
    var isSafari = /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor);
    elemtype = elemtype.toUpperCase();
    var checker_IMG = '';
    if (elemtype == "IMG" && checker_IMG == 'checked' && e.detail >= 2) {
        show_wpcp_message(alertMsg_IMG);
        return false;
    }
    if (elemtype != "TEXT" && elemtype != "TEXTAREA" && elemtype != "INPUT" && elemtype != "PASSWORD" && elemtype != "SELECT" && elemtype != "OPTION" && elemtype != "EMBED") {
        if (smessage !== "" && e.detail == 2)
            show_wpcp_message(smessage);

        if (isSafari)
            return true;
        else
            return false;
    }
}

function disable_copy_ie() {
    var elemtype = window.event.srcElement.nodeName;
    elemtype = elemtype.toUpperCase();
    if (elemtype == "IMG") {
        show_wpcp_message(alertMsg_IMG);
        return false;
    }
    if (elemtype != "TEXT" && elemtype != "TEXTAREA" && elemtype != "INPUT" && elemtype != "PASSWORD" && elemtype != "SELECT" && elemtype != "OPTION" && elemtype != "EMBED") {
        //alert(navigator.userAgent.indexOf('MSIE'));
        //if (smessage !== "") show_wpcp_message(smessage);
        return false;
    }
}

function reEnable() {
    return true;
}
document.onkeydown = disableEnterKey;
document.onselectstart = disable_copy_ie;
if (navigator.userAgent.indexOf('MSIE') == -1) {
    document.onmousedown = disable_copy;
    document.onclick = reEnable;
}

function disableSelection(target) {
    //For IE This code will work
    if (typeof target.onselectstart != "undefined")
        target.onselectstart = disable_copy_ie;

    //For Firefox This code will work
    else if (typeof target.style.MozUserSelect != "undefined") {
        target.style.MozUserSelect = "none";
    }

    //All other  (ie: Opera) This code will work
    else
        target.onmousedown = function() {
            return false
        }
    target.style.cursor = "default";
}
// on_body_load

window.onload = function() {
    disableSelection(document.body);
};



// disable_Right_Click



document.ondragstart = function() {
    return false;
}

function nocontext(e) {
    return false;
}
document.oncontextmenu = nocontext;

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.