Tekan Lama di JavaScript?

117

Apakah mungkin untuk menerapkan "tekan lama" di JavaScript (atau jQuery)? Bagaimana?

teks alt
(sumber: androinica.com )

HTML

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

JavaScript

$("a").mouseup(function(){
  // Clear timeout
  return false;
}).mousedown(function(){
  // Set timeout
  return false; 
});
Randy Mayer
sumber
7
Saya mungkin akan membuat acara jQuery khusus menggunakan kode Anda sebagai basis, jadi Anda bisa melakukannyajQuery(...).longclick(function() { ... });
Matti Virkkunen
1
Pertanyaannya tidak ditandai dengan jQuery, meskipun seharusnya demikian. Pertanyaannya pertama kali menanyakan solusi Javascript murni, yang saya sukai, atau secara opsional (dalam tanda kurung), solusi jQuery. Sebagian besar jawaban tampaknya default ke jQuery sebagai asumsi standar. Saya selalu membenci jQuery dan tidak pernah menggunakannya atau merasa perlu untuk itu. Beberapa senang menggunakannya, itu bagus, untuk mereka sendiri. Jawaban yang menggunakan teknik mana pun tidak merugikan. Tetapi karena pertanyaan tersebut akan menerima solusi jQuery, tag jQuery mungkin mendapatkan lebih banyak perhatian dan semoga jawaban yang lebih baik. Jawaban jQuery di sini tampak tidak bersemangat.

Jawaban:

159

Tidak ada keajaiban 'jQuery', hanya pengatur waktu 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; 
});
Diodeus - James MacFarlane
sumber
39
Bukankah api ini juga akan melambat?
Gallal
11
@Gallal Agaknya itu akan cukup sederhana untuk melihat itu dengan menelepon clearTimeout(pressTimer)pada mousemove, kecuali jika saya melewatkan sesuatu. Yang harus diakui hampir tidak ada yang tidak terduga.
David John Welsh
5
@DavidJohnWelsh Seperti yang saya lihat, Anda tidak hanya ingin mouse bergerak - menahan jari Anda dengan mantap dan tidak menggerakkan 1px cukup sulit! Anda perlu menerapkan ambang (jika mouse belum bergerak 10px) dll. Menjadi rumit dengan cukup cepat!
Ian
6
Ingatlah bahwa jika Anda mengharapkan ini bekerja pada ponsel, mereka seringkali memiliki perilaku longpress default mereka sendiri (chrome di android, misalnya, menampilkan menu modal dengan berbagai pilihan ketika Anda menekan lama sebuah link). Saya tidak beruntung mencegah hal ini, dan sejujurnya mengganggu perilaku default browser tidak berarti apa-apa.
dartacus
4
Meskipun ini adalah jawaban yang dipilih, namun sebenarnya tidak menjawab pertanyaan tersebut. Itu terlalu sederhana dan naif. Setiap acara pers yang lama harus mengatasi banyak masalah yang diabaikan oleh jawaban ini. 1) Membedakan tekan lama dari tarik dari gerakan dari multi sentuh (mis., Zoom in atau out) 2) Batalkan jika gerakan di luar elemen atau area browser 3) Tangani perilaku default pemilihan teks pada sejumlah besar platform dan perangkat 4) Izinkan ambang batas yang dapat dikonfigurasi untuk kepekaan dan tidak bergantung pada angka ajaib. Sangat membantu untuk - tetapi tidak eksklusif untuk - masalah aksesibilitas.
34

Berdasarkan jawaban Maycow Moura, saya menulis ini. Ini juga memastikan bahwa pengguna tidak melakukan klik kanan, yang akan memicu pers lama dan berfungsi pada perangkat seluler. 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);

Anda juga harus memasukkan beberapa indikator menggunakan animasi 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; }
}
kelunik
sumber
Saya membuat versi modifikasi ini, untuk melakukan sesuatu secara konstan saat tombol ditahan jsfiddle tetapi untuk beberapa alasan di Android itu berjalan bahkan setelah Anda berhenti menyentuh tombol + ...
Xander
@ Xander: Mungkin karena :hoverstatus sticky di perangkat sentuh, mungkin itu juga berlaku di sini.
kelunik
Sial, saya ingin tahu apakah ada cara untuk membuat - / + tombol kenaikan angka berfungsi di situs seluler yang mendukung penekanan lama. Setiap metode yang saya temukan hanya mendukung keharusan mengklik berulang kali yang merupakan rasa sakit bagi banyak orang. Terimakasih Meskipun!
Xander
@ Xander: Sebenarnya, touchendjika mengaktifkan IMO, tidak ada alasan untuk membuatnya lengket ketika itu adalah kode khusus untuk perangkat sentuh, mungkin saya akan mencoba sesuatu besok.
kelunik
1
Menemukan masalah di Android. Menekan api baik mousedown dan touchstart sehingga 2 timer berjalan tetapi hanya 1 yang dibatalkan dengan mengangkat jari Anda. Membungkus presstimer dengan if (presstimer === null) untuk memastikan timer belum aktif.
Xander
16

Saya membuat acara pers-lama (JavaScript murni 0,5k) untuk menyelesaikan ini, ini menambahkan long-pressacara ke DOM.

Dengarkan long-pressdi setiap elemen:

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

Dengarkan long-presspada elemen tertentu :

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

Bekerja di IE9 +, Chrome, Firefox, Safari & aplikasi seluler hybrid (Cordova & Ionic di iOS / Android)

Demo

John Doherty
sumber
2
Luar biasa, sobat !!
Jeff T.
1
Monyet solusi ini menambal objek window.CustomEvent dengan cara yang agak serampangan, tidak lengkap dan tidak standar. Itu tidak membuat properti read-only dengan benar sebagai read-only melainkan read-write. Ini secara khusus kehilangan returnValue, type, timeStamp, dan isTrusted. Ini tidak mengatasi drag, gesture, pinch zoom in atau out, atau multi-touch misfires dari tekan lama, juga tidak mengatasi masalah sejumlah besar perangkat dan / atau platform yang secara default menekan lama untuk pemilihan teks bahkan pada 500ms. Pustaka tidak memiliki semua kasus uji untuk kondisi ini.
4
Ini Open Source, silakan berkontribusi pada proyek :)
John Doherty
@JohnDoherty bagus! tetapi apakah kita masih dapat menggunakan "onClick" dengan elemen yang sama?
Devashish
2
Anda masih harus mendapatkan peristiwa 'onclick' selama pers lama dilepaskan sebelum timer 'lama-tekan-tunda' dimulai
John Doherty
15

Meskipun terlihat cukup sederhana untuk diterapkan sendiri dengan batas waktu dan beberapa penangan peristiwa mouse, ini menjadi sedikit lebih rumit saat Anda mempertimbangkan kasus seperti klik-seret-rilis, mendukung pers dan tekan lama pada elemen yang sama , dan bekerja dengan perangkat sentuh seperti iPad. Saya akhirnya menggunakan plugin longclick jQuery ( Github ), yang menangani hal itu untuk saya. Jika Anda hanya perlu mendukung perangkat layar sentuh seperti ponsel, Anda juga dapat mencoba acara taphold jQuery Mobile .

ʇsәɹoɈ
sumber
Tautan Github berfungsi, tetapi proyek belum diperbarui sejak 2010 dan tidak berfungsi dengan versi jquery saat ini. Namun, mengganti handle.apply dengan dispatch.apply di kode sumber akan memperbaikinya.
arlomedia
11

plugin jQuery. Taruh saja $(expression).longClick(function() { <your code here> });. Parameter kedua adalah durasi penahanan; batas waktu default adalah 500 md.

(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);
piwko28
sumber
ini tidak disimpan dalam panggilan.
Champ
hai Bro, bisakah kita menggunakannya sebagai acara tulang punggung
user2075328
6

Untuk pengembang lintas platform (Catatan Semua jawaban yang diberikan sejauh ini tidak akan berfungsi di iOS) :

Mouse atas / bawah sepertinya berfungsi dengan baik di android - tetapi tidak semua perangkat (samsung tab4). Tidak berfungsi sama sekali di iOS .

Penelitian lebih lanjut tampaknya bahwa hal ini disebabkan oleh elemen yang memiliki seleksi dan pembesaran asli mengganggu pendengar.

Pemroses kejadian ini memungkinkan gambar mini dibuka dalam modal bootstrap, jika pengguna memegang gambar selama 500 md.

Ini menggunakan kelas gambar responsif oleh karena itu menampilkan versi gambar yang lebih besar. Potongan kode ini telah diuji sepenuhnya (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)
});
tyler_mitchell
sumber
solusi yang bagus untuk iOS
eric xu
bagaimana saya mencegah sentuhan yang dimulai pada gambar kecil, tetapi akhirnya menjadi gulungan. dengan kata lain, bukan touchstart / end di tempat, tetapi sentuhan yang dimulai pada elemen dengan handler, tetapi akhirnya menjadi sebuah gulungan
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

menggoda
sumber
2
Sedikit pun kode ini, longclick tidak diaktifkan di akhir 500ms. Pengguna bisa mati mengklik mouse :). Klik panjang diaktifkan hanya jika pengguna berhenti untuk mengklik tombol.
jedi
apakah ini akan mencakup kasus ketika pengguna mulai menggulir alih-alih menyelesaikan longpress mereka di tempat yang sama?
Akin Hwan
@AkinHwan Tidak, ini hanya akan dipicu jika klik mouse dilepaskan pada elemen yang sama.
razz
4

Jawaban Diodeus luar biasa, tetapi itu mencegah Anda untuk menambahkan fungsi onClick, itu tidak akan pernah menjalankan fungsi tahan jika Anda meletakkan onclick. Dan jawaban Razzak hampir sempurna, tetapi menjalankan fungsi tahan hanya pada mouseup, dan umumnya, fungsi tersebut berjalan meskipun pengguna terus menahannya.

Jadi, saya bergabung dengan keduanya, dan membuat ini:

$(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
});
Maycow Moura
sumber
bagaimana jika pengguna mulai menggulir setelah mousedown, dan tidak berniat melakukan longpress
Akin Hwan
4

Untuk peramban seluler modern:

document.addEventListener('contextmenu', callback);

https://developer.mozilla.org/en-US/docs/Web/Events/contextmenu

Kory Nunn
sumber
Atau untuk JQuery gunakan $ (selector) .bind ('contextmenu', function () {})
dfmiller
berhenti menggunakan bind()jquery 1.7+ = on()dan unbind()=off()
dbinott
2

Anda dapat menyetel batas waktu untuk elemen itu di mouse ke bawah dan menghapusnya di mouse ke atas:

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

Dengan ini, setiap elemen mendapatkan batas waktunya sendiri.

Gumbo
sumber
1
$(this).mouseup(function(){});tidak menghapus event handler, itu menambahkan yang lain. Gunakan .unbindsebagai gantinya.
Matti Virkkunen
harus digunakan off()sekarang, bukan melepaskan.
dbinott
1

Anda dapat menggunakan taphold jquery-mobile. Sertakan jquery-mobile.js dan kode berikut akan berfungsi dengan baik

$(document).on("pagecreate","#pagename",function(){
  $("p").on("taphold",function(){
   $(this).hide(); //your code
  });    
});
Prashant_M
sumber
Ini harus menjadi jawaban yang diterima karena jquery-mobile menyediakan kerangka kerja stabil yang baik
pasx
1

Paling elegan dan bersih adalah plugin jQuery: https://github.com/untill/jquery.longclick/ , juga tersedia sebagai paket: https://www.npmjs.com/package/jquery.longclick .

Singkatnya, Anda menggunakannya seperti ini:

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

Keuntungan dari plugin ini adalah, berbeda dengan beberapa jawaban lain di sini, peristiwa klik masih memungkinkan. Perhatikan juga bahwa klik lama terjadi, seperti ketukan lama pada perangkat, sebelum mouse naik. Jadi, itulah fitur.

sampai
sumber
0

Bagi saya, ini berfungsi dengan kode itu (dengan 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);
molokoloco
sumber
0

Anda dapat memeriksa waktu untuk mengidentifikasi Klik atau Tekan Lama [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);
}
} 
Derin
sumber
0

seperti ini?

doc.addEeventListener("touchstart", function(){
    // your code ...
}, false);    
翁 沈 顺
sumber
0

Anda dapat menggunakan jqueryacara Touch. ( lihat disini )

  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 );
  });
Irteza Asad
sumber
0

Saya membutuhkan sesuatu untuk acara keyboard longpress, jadi saya menulis ini.

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;
});
Brad Smith
sumber
0

Saya rasa ini dapat membantu Anda:

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;

harvansh sainy
sumber