Pressione lunga in JavaScript?


117

È possibile implementare la "pressione prolungata" in JavaScript (o jQuery)? Come?

testo alternativo
(fonte: androinica.com )

HTML

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

JavaScript

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

7
Probabilmente creerei un evento jQuery personalizzato usando il tuo codice come base, quindi puoi semplicemente farlojQuery(...).longclick(function() { ... });
Matti Virkkunen

1
La domanda non è contrassegnata con jQuery, anche se dovrebbe esserlo. La domanda richiede prima una soluzione Javascript pura, che preferisco, o facoltativamente (tra parentesi), una soluzione jQuery. La maggior parte delle risposte sembra essere predefinita su jQuery come presupposto standard. Ho sempre disprezzato jQuery e non l'ho mai usato né sentito alcun bisogno impellente. Ad alcuni piace usarlo, va bene, a ciascuno il proprio. Le risposte che utilizzano entrambe le tecniche non fanno male. Ma poiché la domanda accetterà soluzioni jQuery, un tag jQuery potrebbe ottenere più occhi e, si spera, risposte migliori. Le risposte jQuery qui sembrano poco brillanti.

Risposte:


159

Non c'è magia "jQuery", solo timer 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
Anche questo incendio non sarebbe stato trascinato?
Gallal

11
@Gallal Presumibilmente sarebbe abbastanza semplice da fare in quel chiamando clearTimeout(pressTimer)in mousemove, a meno che non mi manca qualcosa. Il che certamente non sarebbe senza precedenti.
David John Welsh

5
@DavidJohnWelsh Proprio quello che stavo guardando, non vuoi solo muovere il mouse - tenere il dito fermo e non muoverti di 1px è piuttosto difficile! È necessario applicare una soglia (se il mouse non si è spostato di 10px) ecc. Si complica abbastanza rapidamente!
Ian

6
Tieni presente che se ti aspetti che funzioni sui telefoni, spesso hanno il loro comportamento di pressione lunga predefinito (Chrome su Android, ad esempio, mostra un menu modale con varie opzioni quando premi a lungo un collegamento). Non ho avuto molta fortuna a impedirlo e, ad essere onesti, interferire con il comportamento predefinito del browser non è comunque un nascondiglio.
dartacus

4
Sebbene questa sia la risposta selezionata, non risponde realmente alla domanda. È eccessivamente semplicistico e ingenuo. Qualsiasi evento di stampa prolungata deve affrontare più problemi che questa risposta ignora. 1) Distinguere la pressione prolungata dal trascinamento dal gesto dal multi touch (cioè pizzicare lo zoom avanti o indietro) 2) Annulla se il movimento al di fuori dell'elemento o dell'area del browser 3) Indirizza il comportamento predefinito della selezione del testo su un numero significativo di piattaforme e dispositivi 4) Consenti una soglia configurabile per la sensibilità e non fare affidamento su numeri magici. Particolarmente utile per - ma non esclusivo - problemi di accessibilità.

34

Basandomi sulla risposta di Maycow Moura, ho scritto questo. Garantisce inoltre che l'utente non abbia fatto clic con il pulsante destro del mouse, il che attiverebbe una pressione prolungata e funzioni sui dispositivi mobili. 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);

Dovresti anche includere alcuni indicatori che utilizzano animazioni 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; }
}

Ho creato questa versione modificata, per fare qualcosa costantemente mentre il pulsante è tenuto premuto jsfiddle ma per qualche motivo su Android funziona anche dopo aver smesso di toccare il pulsante + ...
Xander

@Xander: Forse perché lo :hoverstato è appiccicoso sui dispositivi touch, forse questo vale anche qui.
kelunik

Dang, mi chiedo se ci sia un modo per far funzionare i pulsanti di incremento del numero - / + su un sito mobile che supporta pressioni prolungate. Ogni metodo che trovo supporta solo il dover fare clic ripetutamente, il che è un problema per i numeri enormi. Grazie comunque!
Xander

@Xander: In realtà, touchenddovrebbe sparare IMO, non c'è motivo per averlo appiccicoso quando è un codice speciale per dispositivi touch, forse proverò qualcosa domani.
kelunik

1
Hai scoperto il problema su Android. Premendo si attiva sia il mousedown che il touchstart, quindi ha 2 timer in esecuzione ma solo 1 viene annullato sollevando il dito. Presstimer avvolto con if (presstimer === null) per assicurarsi che il timer non fosse già attivo.
Xander


16

Ho creato un evento di pressione prolungata (0,5k JavaScript puro) per risolvere questo problema, aggiunge un long-pressevento al DOM.

Ascolta un long-presssu qualsiasi elemento:

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

Ascolta long-pressun elemento specifico :

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

Funziona con IE9 +, Chrome, Firefox, Safari e app mobili ibride (Cordova e Ionic su iOS / Android)

dimostrazione


2
Owesome, amico !!
Jeff T.

1
Questa soluzione corregge l'oggetto window.CustomEvent in un modo alquanto casuale, incompleto e non standard. Non crea correttamente proprietà di sola lettura come sola lettura ma piuttosto lettura-scrittura. Manca specificamente returnValue, type, timeStamp e isTrusted. Non affronta il trascinamento, il gesto, lo zoom in avvicinamento o in allontanamento o il multi-touch in caso di pressione prolungata, né affronta il problema di un gran numero di dispositivi e / o piattaforme che per impostazione predefinita premono a lungo per selezionare il testo anche a 500 ms. Nella libreria mancano tutti i casi di test per queste condizioni.

4
È Open Source, sentiti libero di contribuire al progetto :)
John Doherty

@ JohnDoherty fantastico! ma possiamo ancora usare "onClick" con lo stesso elemento?
Devashish

2
Dovresti comunque ricevere l'evento "onclick" fintanto che la pressione prolungata viene rilasciata prima che il timer del "ritardo della pressione prolungata" entri in azione
John Doherty,

15

Anche se sembra abbastanza semplice da implementare da solo con un timeout e un paio di gestori di eventi del mouse, diventa un po 'più complicato se si considerano casi come clic-trascina-rilascio, supportando sia la pressione che la pressione prolungata sullo stesso elemento e lavorare con dispositivi touch come l'iPad. Ho finito per utilizzare il plugin jQuery longclick ( Github ), che si occupa di queste cose per me. Se hai solo bisogno di supportare i dispositivi touchscreen come i telefoni cellulari, potresti anche provare l' evento taphold jQuery Mobile .


Il collegamento Github funziona, ma il progetto non è stato aggiornato dal 2010 e non funziona con le attuali versioni di jquery. Tuttavia, la sostituzione di handle.apply con dispatch.apply nel codice sorgente lo risolve.
arlomedia

11

plugin jQuery. Basta mettere $(expression).longClick(function() { <your code here> });. Il secondo parametro è la durata della tenuta; il timeout predefinito è 500 ms.

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

questo non viene mantenuto nella chiamata.
Campione

ciao fratello, possiamo usarlo come evento di base
user2075328

6

Per sviluppatori multipiattaforma (Nota: tutte le risposte fornite finora non funzioneranno su iOS) :

Il mouse su / giù sembrava funzionare bene su Android , ma non su tutti i dispositivi, ad esempio (Samsung Tab4). Non ha funzionato affatto su iOS .

Ulteriori ricerche sembra che ciò sia dovuto all'elemento che ha la selezione e l'ingrandimento nativo interrompe l'ascoltatore.

Questo listener di eventi consente di aprire un'immagine in miniatura in una modalità bootstrap, se l'utente mantiene l'immagine per 500 ms.

Utilizza una classe di immagine reattiva che mostra quindi una versione più grande dell'immagine. Questo pezzo di codice è stato completamente testato su (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)
});

bella soluzione per iOS
eric xu

come impedirei i tocchi che iniziano sulla miniatura, ma diciamo che finiscono per essere uno scorrimento. in altre parole, non un tocco iniziale / finale sul posto, ma un tocco che è iniziato sull'elemento con il gestore, ma finisce per essere uno scorrimento
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
Con questo codice il clic lungo non viene sparato alla fine di 500 ms. L'utente può morire cliccando con il mouse :). Il clic lungo viene attivato solo se l'utente smette di fare clic sul pulsante.
jedi

questo coprirebbe il caso in cui un utente ha iniziato a scorrere invece di finire la pressione prolungata nello stesso punto?
Akin Hwan

@AkinHwan No, verrebbe attivato solo se il clic del mouse fosse rilasciato sullo stesso elemento.
razz

4

La risposta di Diodeus è fantastica, ma ti impedisce di aggiungere una funzione onClick, non eseguirà mai la funzione hold se metti un onclick. E la risposta di Razzak è quasi perfetta, ma esegue la funzione di attesa solo al mouseup e, in generale, la funzione viene eseguita anche se l'utente continua a tenere premuto.

Quindi, mi sono unito a entrambi e ho fatto questo:

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

cosa succede se l'utente inizia a scorrere dopo mousedown e non intende eseguire una pressione prolungata
Akin Hwan


2

Puoi impostare il timeout per quell'elemento con il mouse in basso e cancellarlo con il mouse in alto:

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

Con questo ogni elemento ottiene il proprio timeout.


1
$(this).mouseup(function(){});non rimuove il gestore eventi, ma ne aggiunge un altro. Usa .unbindinvece.
Matti Virkkunen

dovrebbe usare off()ora invece di separare.
dbinott

1

Puoi usare il taphold di jquery-mobile. Includi jquery-mobile.js e il codice seguente funzionerà correttamente

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

Questa dovrebbe essere la risposta accettata poiché jquery-mobile fornisce un buon framework stabile
pasx

1

Il più elegante e pulito è un plugin jQuery: https://github.com/untill/jquery.longclick/ , disponibile anche come pacchetto: https://www.npmjs.com/package/jquery.longclick .

In breve, lo usi così:

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

Il vantaggio di questo plugin è che, a differenza di alcune delle altre risposte qui, gli eventi di clic sono ancora possibili. Nota anche che si verifica un lungo clic, proprio come un lungo tocco su un dispositivo, prima del mouseup. Quindi, questa è una caratteristica.


0

Per me funziona con quel codice (con 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

Puoi controllare il tempo per identificare il clic o la pressione prolungata [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

come questo?

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

0

Puoi usare gli jqueryeventi Touch. ( vedi qui )

  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

Avevo bisogno di qualcosa per eventi da tastiera a pressione prolungata, quindi ho scritto questo.

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

Penso che questo possa aiutarti:

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;

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.