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

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

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

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


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 .


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

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

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


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

bagaimana jika pengguna mulai menggulir setelah mousedown, dan tidak berniat melakukan longpress
Akin Hwan


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.


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

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.


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

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

0

seperti ini?

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

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

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

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;

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.