JavaScript'te Uzun Basıyor musunuz?


117

JavaScript'te (veya jQuery'de) "uzun basış" uygulamak mümkün müdür? Nasıl?

alternatif metin
(kaynak: androinica.com )

HTML

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

JavaScript

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

7
Muhtemelen kodunuzu temel olarak kullanarak özel jQuery olayı oluşturabilirim, böylece yapabilirsinizjQuery(...).longclick(function() { ... });
Matti Virkkunen

1
Soru, olması gerektiği halde jQuery ile etiketlenmemiş. Soru önce, tercih ettiğim saf bir Javascript çözümünü veya isteğe bağlı olarak (parantez içinde) bir jQuery çözümünü soruyor. Çoğu yanıt, standart bir varsayım olarak jQuery'yi varsayılan olarak kullanır. JQuery'yi her zaman küçümsedim ve bir kez bile kullanmadım ve buna zorlayıcı bir ihtiyaç hissetmedim. Bazıları bunu kullanmaktan hoşlanıyor, bu sorun değil, herkes için sorun değil. Her iki tekniği kullanan cevaplar hiçbir şeye zarar vermez. Ancak soru jQuery çözümlerini kabul edeceğinden, bir jQuery etiketi daha fazla göze çarpabilir ve umarız daha iyi yanıtlar alabilir. Buradaki jQuery yanıtları yetersiz görünüyor.

Yanıtlar:


159

'JQuery' büyüsü yoktur, sadece JavaScript zamanlayıcıları vardır.

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
Bu da ateş etmeyecek mi?
Gallal

11
Herhalde arayarak bunu sağlardı oldukça basit olurdu @Gallal clearTimeout(pressTimer)üzerinde mousemoveben bir şey eksik sürece,. Kuşkusuz ki beklenmedik bir şey olmazdı.
David John Welsh

5
@DavidJohnWelsh Tam da baktığım şey, sadece fareyi hareket ettirmek istemiyorsunuz - sizi parmak ölüsünde sabit tutmak ve 1px'i hareket ettirmemek oldukça zor! Bir eşik uygulamanız gerekir (eğer fare 10px hareket etmediyse) vb. Oldukça hızlı bir şekilde karmaşıklaşır!
Ian

6
Bunun telefonlarda çalışmasını bekliyorsanız, genellikle kendi varsayılan uzun basma davranışlarına sahip olduklarını unutmayın (örneğin, android'de krom, bir bağlantıya uzun bastığınızda çeşitli seçenekler içeren kalıcı bir menü gösterir). Bunu önleme konusunda pek şansım olmadı ve dürüst olmak gerekirse, tarayıcının varsayılan davranışına müdahale etmek hiçbir şekilde saklanmıyor.
dartacus

4
Bu seçilen cevap olmasına rağmen, soruyu gerçekten cevaplamıyor. Aşırı derecede basit ve saf. Herhangi bir uzun basın etkinliği, bu cevabın görmezden geldiği birden çok sorunu ele almalıdır. 1) Uzun basmayı, çoklu dokunma hareketinden sürüklemeden ayırın (yani sıkıştırarak yakınlaştırma veya uzaklaştırma) 2) Öğenin veya tarayıcı alanının dışına çıkarsanız iptal edin 3) Önemli sayıda platform ve cihazda metin seçiminin varsayılan davranışını ele alın 4) İzin ver duyarlılık için yapılandırılabilir bir eşiktir ve sihirli sayılara dayanmaz. Erişilebilirlik endişeleri için özellikle yararlıdır - ancak bunlarla sınırlı değildir.

34

Maycow Moura'nın cevabına dayanarak bunu yazdım. Ayrıca, kullanıcının bir sağ tıklama yapmamasını sağlar, bu da uzun bir basmayı tetikler ve mobil cihazlarda çalışır. DEMO

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 animasyonlarını kullanan bazı göstergeleri de eklemelisiniz:

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; }
}

Bu değiştirilmiş sürümü, düğme jsfiddle basılıyken sürekli bir şeyler yapmak için yaptım, ancak Android'de herhangi bir nedenle + düğmesine dokunmayı bıraktıktan sonra bile çalışıyor ...
Xander

@Xander: Belki :hoverdurum dokunmatik cihazlarda yapışkan olduğundan , belki bu burada da geçerli.
kelunik

Dang, uzun basışları destekleyen bir mobil sitede çalışan - / + sayı artırma düğmelerini almanın bir yolu olup olmadığını merak ediyorum. Bulduğum her yöntem sadece tekrar tekrar tıklamak zorunda kalmayı destekliyor ki bu çok büyük sayılar için bir acı. Yine de teşekkürler!
Xander

@Xander: Aslında, IMO'yu touchendateşlemelisiniz, dokunmatik cihazlar için özel kod olduğunda yapışkan olması için bir neden yok, belki yarın bir şeyler deneyeceğim.
kelunik

1
Android'de sorunu çözdüm. Düğmeye basmak hem fareyi indirmeyi hem de dokunmatik başlatmayı ateşler, böylece 2 zamanlayıcı çalışır, ancak yalnızca 1 tanesi parmağınızı kaldırarak iptal edilir. Zamanlayıcının halihazırda etkin olmadığından emin olmak için önstimer if (presstimer === null) ile sarıldı.
Xander


16

Bunu çözmek için uzun basış olayı (0,5k saf JavaScript)long-press oluşturdum, DOM'a bir olay ekliyor .

Bir dinleyin long-pressüzerinde herhangi elemanı:

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

Bir dinleyin long-pressbir üzerinde belirli elemanı:

// 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 ve hibrit mobil uygulamalarda çalışır (iOS / Android'de Cordova ve Ionic)

gösteri


2
Owesome, dostum !!
Jeff T.

1
Bu çözüm maymunu, window.CustomEvent nesnesini biraz gelişigüzel, eksik ve standart olmayan bir şekilde yamalar. Salt okunur özellikleri salt okunur olarak değil, okuma-yazma olarak doğru şekilde oluşturmaz. Özellikle returnValue, type, timeStamp eksik ve isTrusted. Sürükleme, hareket etme, sıkıştırarak yakınlaştırma veya uzaklaştırma veya uzun basmanın çoklu dokunma yanlış ateşlemelerini ele almaz ve 500 ms'de bile metin seçimine varsayılan olarak uzun süre basan çok sayıda cihaz ve / veya platform sorununu ele almaz. Kitaplıkta bu koşullar için tüm test senaryoları eksik.

4
Açık Kaynak, projeye katkıda bulunmaktan çekinmeyin :)
John Doherty

@JohnDoherty harika! ancak "onClick" i yine de aynı öğeyle kullanabilir miyiz?
Devashish

2
Uzun basma 'uzun basma-geciktirme' zamanlayıcı devreye girmeden önce serbest bırakıldığı sürece 'onclick' etkinliğini almaya devam etmelisiniz
John Doherty

15

Bir zaman aşımı ve birkaç fare olay işleyicisi ile kendi başınıza uygulamak için yeterince basit görünse de, aynı öğeye hem basmayı hem de uzun basmayı destekleyen tıklama-sürükle-bırak gibi durumları düşündüğünüzde biraz daha karmaşık hale geliyor. ve iPad gibi dokunmatik cihazlarla çalışma. Bu şeyleri benim için halleden longclick jQuery eklentisini ( Github ) kullandım. Yalnızca cep telefonları gibi dokunmatik ekranlı cihazları desteklemeniz gerekiyorsa, jQuery Mobile taphold olayını da deneyebilirsiniz .


Github bağlantısı çalışıyor, ancak proje 2010'dan beri güncellenmedi ve mevcut jquery sürümleriyle çalışmıyor. Bununla birlikte, kaynak kodda handle.apply yerine dispatch.apply kullanılması sorunu düzeltir.
arlomedia

11

jQuery eklentisi. Sadece koyun $(expression).longClick(function() { <your code here> });. İkinci parametre tutma süresidir; varsayılan zaman aşımı 500 ms'dir.

(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);

bu görüşmede saklanmaz.
Şampiyon

merhaba Bro bunu bir omurga etkinliği olarak kullanabilir miyiz
user2075328

6

Çapraz platform geliştiricileri için (Not Şimdiye kadar verilen tüm yanıtlar iOS'ta çalışmayacaktır) :

Fare yukarı / aşağı, android üzerinde iyi çalışıyor gibi görünüyordu - ancak tüm cihazlarda değil, yani (samsung tab4). Üzerinde hiç çalışmaz mı iOS .

Daha fazla araştırma, bunun seçime sahip öğeden kaynaklandığı ve yerel büyütmenin dinleyiciyi rahatsız ettiği görülüyor.

Bu olay dinleyici, kullanıcı görüntüyü 500 ms tutarsa, bir önyükleme modelinde bir küçük resim görüntüsünün açılmasını sağlar.

Duyarlı bir görüntü sınıfı kullanır, bu nedenle görüntünün daha büyük bir versiyonunu gösterir. Bu kod parçası (iPad / Tab4 / TabA / Galaxy4) üzerinde tam olarak test edilmiştir:

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 için güzel çözüm
eric xu 03

küçük resimde başlayan dokunuşları nasıl önleyebilirim, ancak sonunda bir kaydırma olduğunu söyleyin. başka bir deyişle, yerinde bir touchstart / son değil, ancak işleyiciyle öğede başlayan ancak bir kaydırma olarak sonuçlanan bir dokunuş
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;
    });
});

DEMO


2
Bu kodla birlikte, uzun tıklama 500ms sonunda ateşlenmez. Kullanıcı fareye tıklayarak ölebilir :). Uzun tıklama, yalnızca kullanıcı düğmeyi tıklamayı bıraktığında tetiklenir.
jedi

Bu, bir kullanıcının uzun basışını aynı noktada bitirmek yerine kaydırmaya başlaması durumunu kapsar mı?
Akin Hwan

@AkinHwan Hayır, yalnızca fare tıklaması aynı öğenin üzerine bırakılırsa tetiklenir.
razz

4

Diodeus'un cevabı harika, ancak bir onClick işlevi eklemenizi engelliyor, bir onclick yaparsanız asla bekletme işlevini çalıştırmaz. Ve Razzak'ın cevabı neredeyse mükemmel, ancak bekletme işlevini yalnızca mouseup üzerinde çalıştırıyor ve genellikle işlev, kullanıcı tutmaya devam etse bile çalışıyor.

Böylece ikisine de katıldım ve şunu yaptım:

$(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
});

ya kullanıcı fare indirdikten sonra kaydırmaya başlarsa ve uzun basma niyetinde değilse
Akin Hwan


2

Bu öğe için zaman aşımını fareye basılıyken ayarlayabilir ve fareyi yukarı kaydırdığınızda temizleyebilirsiniz:

$("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;
});

Bununla her öğe kendi zaman aşımına sahip olur.


1
$(this).mouseup(function(){});olay işleyicisini kaldırmaz, başka bir tane ekler. .unbindBunun yerine kullanın .
Matti Virkkunen

Bağlantısını off()çözmek yerine şimdi kullanmalısınız.
dbinott

1

Jquery-mobile'ın tafoldunu kullanabilirsiniz. Jquery-mobile.js'yi ekleyin ve aşağıdaki kod sorunsuz çalışacaktır

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

Jquery-mobile iyi bir kararlı çerçeve sağladığı için kabul edilen yanıt bu olmalıdır
pasx

1

En zarif ve temiz bir jQuery eklentisidir: https://github.com/untill/jquery.longclick/ , ayrıca packacke olarak da mevcuttur: https://www.npmjs.com/package/jquery.longclick .

Kısacası, bunu şu şekilde kullanıyorsunuz:

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

Bu eklentinin avantajı, buradaki diğer bazı cevapların aksine tıklama olaylarının hala mümkün olmasıdır. Ayrıca fareyi kaldırmadan önce, bir cihaza uzun bir dokunma gibi uzun bir tıklama gerçekleştiğini de unutmayın. Yani bu bir özellik.


0

Benim için bu kodla çalışır (jQuery ile):

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

Tıklama veya Uzun Basma [jQuery] 'yi belirleme süresini kontrol edebilirsiniz

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

bunun gibi?

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

0

jqueryDokunma olaylarını kullanabilirsiniz . ( buraya bakın )

  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

Uzun süreli klavye olayları için bir şeye ihtiyacım vardı, bu yüzden bunu yazdım.

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

Bunun size yardımcı olabileceğini düşünüyorum:

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;

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.