Langes Drücken in JavaScript?

117

Ist es möglich, "Long Press" in JavaScript (oder jQuery) zu implementieren? Wie?

Alt-Text
(Quelle: 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
quelle
7
Ich würde wahrscheinlich ein benutzerdefiniertes jQuery-Ereignis erstellen, das Ihren Code als Basis verwendet, damit Sie es einfach tun könnenjQuery(...).longclick(function() { ... });
Matti Virkkunen
1
Die Frage ist nicht mit jQuery markiert, obwohl dies der Fall sein sollte. Die Frage fragt zuerst nach einer reinen Javascript-Lösung, die ich bevorzuge, oder optional (in Klammern) nach einer jQuery-Lösung. Die meisten Antworten scheinen standardmäßig jQuery zu verwenden. Ich habe jQuery immer verachtet und es nie benutzt oder ein zwingendes Bedürfnis danach verspürt. Einige benutzen es gerne, das ist in Ordnung, für jeden das Richtige. Antworten mit beiden Techniken schaden nichts. Da die Frage jedoch jQuery-Lösungen akzeptiert, erhält ein jQuery-Tag möglicherweise mehr Augäpfel und hoffentlich bessere Antworten. Die Antworten von jQuery hier scheinen glanzlos.

Antworten:

159

Es gibt keine "jQuery" -Magie, nur JavaScript-Timer.

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
quelle
39
Würde das nicht auch auf einen Zug schießen?
Gallal
11
@Gallal Vermutlich wäre es ziemlich einfach, dies durch Aufrufen clearTimeout(pressTimer)zu erreichen mousemove, es sei denn, ich vermisse etwas. Was zugegebenermaßen kaum beispiellos wäre.
David John Welsh
5
@DavidJohnWelsh Genau das, was ich mir angesehen habe, du willst aber nicht nur eine Mausbewegung - es ist ziemlich schwer, deinen Finger absolut ruhig zu halten und 1px nicht zu bewegen! Sie müssen einen Schwellenwert anwenden (wenn sich die Maus nicht um 10 Pixel bewegt hat) usw. Wird ziemlich schnell kompliziert!
Ian
6
Denken Sie daran, dass, wenn Sie erwarten, dass dies auf Telefonen funktioniert, diese häufig ihr eigenes Standard-Longpress-Verhalten haben (Chrome auf Android zeigt beispielsweise ein modales Menü mit verschiedenen Optionen an, wenn Sie lange auf einen Link drücken). Ich hatte nicht viel Glück, dies zu verhindern, und um ehrlich zu sein, ist es sowieso ein Versteck, das Standardverhalten des Browsers zu stören.
Dartacus
4
Obwohl dies die ausgewählte Antwort ist, beantwortet sie die Frage nicht wirklich. Es ist zu simpel und naiv. Jedes lange Presseereignis muss mehrere Probleme behandeln, die in dieser Antwort ignoriert werden. 1) Unterscheiden Sie langes Drücken von Ziehen von Geste von Multi-Touch (dh Vergrößern oder Verkleinern). 2) Abbrechen, wenn Bewegung außerhalb des Elements oder des Browserbereichs erfolgt. 3) Standardverhalten der Textauswahl auf einer signifikanten Anzahl von Plattformen und Geräten adressieren. 4) Zulassen Ein konfigurierbarer Schwellenwert für die Empfindlichkeit und nicht auf magische Zahlen angewiesen. Besonders hilfreich für - aber nicht ausschließlich - Zugänglichkeitsprobleme.
34

Basierend auf der Antwort von Maycow Moura habe ich dies geschrieben. Außerdem wird sichergestellt, dass der Benutzer keinen Rechtsklick ausführt, was ein langes Drücken auslösen und auf Mobilgeräten funktioniert. 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);

Sie sollten auch einige Indikatoren mit CSS-Animationen einfügen:

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
quelle
Ich habe diese modifizierte Version gemacht, um ständig etwas zu tun, während die Taste gedrückt gehalten wird. Jsfiddle, aber aus irgendeinem Grund läuft sie unter Android auch dann, wenn Sie aufhören, die + -Taste zu berühren ...
Xander
@Xander: Vielleicht, weil der :hoverStatus auf Touch-Geräten klebrig ist, vielleicht gilt das auch hier.
Kelunik
Dang, ich frage mich, ob es eine Möglichkeit gibt, - / + Nummerninkrement-Schaltflächen auf einer mobilen Site zum Laufen zu bringen, die langes Drücken unterstützen. Jede Methode, die ich finde, unterstützt nur das wiederholte Klicken, was für große Zahlen ein Schmerz ist. Trotzdem danke!
Xander
@Xander: Sollte touchendIMO ausgelöst werden, gibt es keinen Grund, es klebrig zu machen, wenn es sich um einen speziellen Code für Touch-Geräte handelt. Vielleicht werde ich morgen etwas ausprobieren.
Kelunik
1
Ich habe das Problem unter Android herausgefunden. Durch Drücken von wird sowohl Mousedown als auch Touchstart ausgelöst, sodass 2 Timer ausgeführt werden, aber nur 1 durch Anheben des Fingers abgebrochen wird. Presstimer mit if (presstimer === null) umwickelt, um sicherzustellen, dass der Timer noch nicht aktiv war.
Xander
25

Sie können das Taphold- Ereignis der mobilen jQuery-API verwenden.

jQuery("a").on("taphold", function( event ) { ... } )
Doganak
quelle
2
Bitte beachten Sie: jquery mobile steht in Konflikt mit jquery ui. Siehe auch stackoverflow.com/questions/24379514/…
Marcel Verwey
16

Ich habe ein Long-Press-Ereignis (0,5 KB reines JavaScript) erstellt , um dieses Problem zu lösen. Es fügt long-pressdem DOM ein Ereignis hinzu .

Hören Sie ein long-pressauf jedem Element:

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

Hören Sie long-pressauf ein bestimmtes Element:

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

Funktioniert in IE9 +, Chrome, Firefox, Safari und hybriden mobilen Apps (Cordova & Ionic unter iOS / Android)

Demo

John Doherty
quelle
2
Super, Kumpel !!
Jeff T.
1
Dieser Lösungsaffe patcht das window.CustomEvent-Objekt auf eine etwas zufällige, unvollständige und nicht standardmäßige Weise. Es werden schreibgeschützte Eigenschaften nicht ordnungsgemäß als schreibgeschützt, sondern als schreibgeschützt erstellt. Es fehlen speziell returnValue, type, timeStamp und isTrusted. Es wird weder das Ziehen, Gestikulieren, das Vergrößern oder Verkleinern oder das Aussetzen von Mehrfachberührungen bei langem Drücken angesprochen, noch das Problem einer großen Anzahl von Geräten und / oder Plattformen, bei denen das lange Drücken standardmäßig auch bei 500 ms auf Textauswahl angewendet wird. In der Bibliothek fehlen alle Testfälle für diese Bedingungen.
4
Es ist Open Source, zögern Sie nicht, zu dem Projekt beizutragen :)
John Doherty
@ JohnDoherty großartig! Aber können wir trotzdem "onClick" mit demselben Element verwenden?
Devashish
2
Sie sollten immer noch das "Onclick" -Ereignis erhalten, solange die lange Presse losgelassen wird, bevor der Timer für die "lange Druckverzögerung" startet
John Doherty,
15

Es sieht zwar einfach genug aus, um es mit einem Timeout und einigen Maus-Ereignishandlern selbst zu implementieren, wird jedoch etwas komplizierter, wenn Sie Fälle wie Click-Drag-Release betrachten, bei denen sowohl Drücken als auch Langes Drücken auf dasselbe Element unterstützt werden und Arbeiten mit Touch-Geräten wie dem iPad. Am Ende habe ich das LongQick-jQuery-Plugin ( Github ) verwendet, das sich für mich um dieses Zeug kümmert. Wenn Sie nur Touchscreen-Geräte wie Mobiltelefone unterstützen müssen, können Sie auch das Ereignis jQuery Mobile taphold ausprobieren .

ʇSәɹoɈ
quelle
Der Github-Link funktioniert, aber das Projekt wurde seit 2010 nicht mehr aktualisiert und funktioniert nicht mit aktuellen JQuery-Versionen. Das Ersetzen von handle.apply durch dispatch.apply im Quellcode behebt dies jedoch.
Arlomedia
11

jQuery-Plugin. Einfach gesagt $(expression).longClick(function() { <your code here> });. Der zweite Parameter ist die Haltedauer. Das Standardzeitlimit beträgt 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);
piwko28
quelle
Dies wird im Anruf nicht beibehalten.
Champ
Hallo Bro, können wir es als Backbone-Ereignis verwenden
user2075328
6

Für plattformübergreifende Entwickler (Hinweis Alle bisher gegebenen Antworten funktionieren unter iOS nicht) :

Mouseup / Down schien auf Android in Ordnung zu funktionieren - aber nicht auf allen Geräten, dh (Samsung Tab4). Funktionierte unter iOS überhaupt nicht .

Weitere Untersuchungen scheinen darauf zurückzuführen zu sein, dass das Element eine Auswahl aufweist und die native Vergrößerung den Hörer unterbricht.

Dieser Ereignis-Listener ermöglicht das Öffnen eines Miniaturbilds in einem Bootstrap-Modal, wenn der Benutzer das Bild 500 ms lang hält.

Es wird eine reaktionsfähige Bildklasse verwendet, die eine größere Version des Bildes anzeigt. Dieser Code wurde vollständig getestet auf (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
quelle
schöne Lösung für iOS
Eric Xu
Wie würde ich verhindern, dass Berührungen auf dem Miniaturbild beginnen, aber am Ende eine Schriftrolle sind? Mit anderen Worten, kein Touchstart / Ende an Ort und Stelle, sondern eine Berührung, die mit dem Handler am Element begann, aber am Ende eine Schriftrolle ist
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

Razz
quelle
2
Mit diesem Code wird der Longclick am Ende von 500 ms nicht ausgelöst. Der Benutzer kann durch Klicken mit der Maus sterben :). Der lange Klick wird nur ausgelöst, wenn der Benutzer aufhört, auf die Schaltfläche zu klicken.
Jedi
Würde dies den Fall abdecken, in dem ein Benutzer mit dem Scrollen begann, anstatt seine Langpresse an derselben Stelle zu beenden?
Akin Hwan
@AkinHwan Nein, es würde nur ausgelöst, wenn der Mausklick über dasselbe Element losgelassen würde.
Razz
4

Die Antwort des Diodeus ist fantastisch, aber es verhindert, dass Sie eine onClick-Funktion hinzufügen. Wenn Sie einen onclick ausführen, wird die Hold-Funktion niemals ausgeführt. Die Antwort des Razzak ist fast perfekt, aber die Hold-Funktion wird nur beim Mouseup ausgeführt, und im Allgemeinen wird die Funktion auch ausgeführt, wenn der Benutzer die Hold-Funktion beibehält.

Also habe ich mich beiden angeschlossen und folgendes gemacht:

$(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
quelle
Was ist, wenn der Benutzer nach dem Mousedown mit dem Scrollen beginnt und nicht beabsichtigt, eine Langpresse auszuführen
Akin Hwan,
3

Für moderne, mobile Browser:

document.addEventListener('contextmenu', callback);

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

Kory Nunn
quelle
Oder für JQuery verwenden Sie $ (Selektor) .bind ('Kontextmenü', Funktion () {})
dfmiller
Verwenden Sie nicht mehr bind()jquery 1.7+ = on()und unbind()=off()
dbinott
2

Sie können das Zeitlimit für dieses Element mit der Maus nach unten einstellen und mit der Maus nach oben löschen:

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

Damit erhält jedes Element seine eigene Zeitüberschreitung.

Gumbo
quelle
1
$(this).mouseup(function(){});entfernt den Ereignishandler nicht, sondern fügt einen weiteren hinzu. Verwenden Sie .unbindstattdessen.
Matti Virkkunen
sollte off()jetzt verwenden anstatt zu lösen.
Dbinott
1

Sie können den Taphold von jquery-mobile verwenden. Fügen Sie die Datei jquery-mobile.js hinzu, und der folgende Code funktioniert einwandfrei

$(document).on("pagecreate","#pagename",function(){
  $("p").on("taphold",function(){
   $(this).hide(); //your code
  });    
});
Prashant_M
quelle
Dies sollte die akzeptierte Antwort sein, da jquery-mobile ein gutes stabiles Framework bietet
pasx
1

Am elegantesten und saubersten ist ein jQuery-Plugin: https://github.com/untill/jquery.longclick/ , das auch als Paket erhältlich ist: https://www.npmjs.com/package/jquery.longclick .

Kurz gesagt, Sie verwenden es so:

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

Der Vorteil dieses Plugins ist, dass im Gegensatz zu einigen anderen Antworten hier Klickereignisse weiterhin möglich sind. Beachten Sie auch, dass ein langer Klick auftritt, genau wie ein langes Tippen auf ein Gerät vor dem Mouseup. Das ist also eine Funktion.

bis
quelle
0

Für mich funktioniert es mit diesem Code (mit 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
quelle
0

Sie können die Zeit überprüfen, um Click oder Long Press [jQuery] zu identifizieren.

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
quelle
0

so was?

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

Sie können jqueryTouch-Ereignisse verwenden. ( siehe hier )

  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
quelle
0

Ich brauchte etwas für Longpress-Tastaturereignisse, also schrieb ich dies.

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
quelle
0

Ich denke, das kann dir helfen:

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
quelle