¿Cómo puedo escuchar un clic y mantener presionado en jQuery?

116

Quiero poder disparar un evento cuando un usuario hace clic en un botón y luego lo mantiene presionado durante 1000 a 1500 ms.

¿Existe una funcionalidad principal de jQuery o un complemento que ya lo habilita?

¿Debería enrollar el mío? ¿Donde debería empezar?

SnickersAreMyFave
fuente
posible duplicado de Long Press en JavaScript?
Der Hochstapler
¿Qué tal 'taphold'?
Roshdy

Respuestas:

173
var timeoutId = 0;

$('#myElement').on('mousedown', function() {
    timeoutId = setTimeout(myFunction, 1000);
}).on('mouseup mouseleave', function() {
    clearTimeout(timeoutId);
});

Editar : corrección por AndyE ... ¡gracias!

Edición 2 : usar vincular ahora para dos eventos con el mismo controlador por gnarf

cara de árbol
fuente
4
La actualización es mejor, pero también puede considerar borrar el intervalo en un mouseleavecontrolador.
Andy E
5
Puede usar la misma función para mouseup / mouseleave:.bind('mouseup mouseleave', function() {
gnarf
@gnarf ¡Buen punto! Lo he editado para incluir tu sugerencia.
treeface
¡Lindas cosas! Implementado dentro de jQuery Mobile sin ningún problema.
Anthony
@treeface Slick, pero estoy confundido dónde iría la carga útil. ¿Debería llamarse al controlador específico de la implementación en el evento mouseup?
Bob Stein
13

Aircoded (pero probado en este violín )

(function($) {
    function startTrigger(e) {
        var $elem = $(this);
        $elem.data('mouseheld_timeout', setTimeout(function() {
            $elem.trigger('mouseheld');
        }, e.data));
    }

    function stopTrigger() {
        var $elem = $(this);
        clearTimeout($elem.data('mouseheld_timeout'));
    }


    var mouseheld = $.event.special.mouseheld = {
        setup: function(data) {
            // the first binding of a mouseheld event on an element will trigger this
            // lets bind our event handlers
            var $this = $(this);
            $this.bind('mousedown', +data || mouseheld.time, startTrigger);
            $this.bind('mouseleave mouseup', stopTrigger);
        },
        teardown: function() {
            var $this = $(this);
            $this.unbind('mousedown', startTrigger);
            $this.unbind('mouseleave mouseup', stopTrigger);
        },
        time: 750 // default to 750ms
    };
})(jQuery);

// usage
$("div").bind('mouseheld', function(e) {
    console.log('Held', e);
})
gnarf
fuente
cómo seleccionar el texto con un color diferente cuando mantenemos pulsado el dispositivo
Lucky
8

Hice un complemento JQuery simple para esto si alguien está interesado.

http://plugins.jquery.com/pressAndHold/

Tony Smith
fuente
Buena esa. Pude modificar esto para detectar que un objeto había sido arrastrado para eliminar un mensaje que le decía al usuario que arrastrara el objeto.
Starfs
Complemento FANTÁSTICO. Pasé por mi proyecto y bam, funciona.
Andy
Su complemento no fue escrito para Bootstrap, ¡pero funciona MUY bien con él! Sin CSS adicional ni perder el tiempo. Simplemente funciona. Prestigio.
Andy
5

Presumiblemente, podría iniciar una setTimeoutllamada mousedowny luego cancelarla mouseup(si mouseupocurre antes de que se complete el tiempo de espera).

Sin embargo, parece que hay un complemento: longclick .

Jacob Mattison
fuente
1

Aquí está mi implementación actual:

$.liveClickHold = function(selector, fn) {

    $(selector).live("mousedown", function(evt) {

        var $this = $(this).data("mousedown", true);

        setTimeout(function() {
            if ($this.data("mousedown") === true) {
                fn(evt);
            }
        }, 500);

    });

    $(selector).live("mouseup", function(evt) {
        $(this).data("mousedown", false);
    });

}
SnickersAreMyFave
fuente
1
    var _timeoutId = 0;

    var _startHoldEvent = function(e) {
      _timeoutId = setInterval(function() {
         myFunction.call(e.target);
      }, 1000);
    };

    var _stopHoldEvent = function() {
      clearInterval(_timeoutId );
    };

    $('#myElement').on('mousedown', _startHoldEvent).on('mouseup mouseleave', _stopHoldEvent);
kayz1
fuente
0

Escribí un código para hacerlo más fácil.

//Add custom event listener
$(':root').on('mousedown', '*', function() {
    var el = $(this),
        events = $._data(this, 'events');
    if (events && events.clickHold) {
        el.data(
            'clickHoldTimer',
            setTimeout(
                function() {
                    el.trigger('clickHold')
                },
                el.data('clickHoldTimeout')
            )
        );
    }
}).on('mouseup mouseleave mousemove', '*', function() {
    clearTimeout($(this).data('clickHoldTimer'));
});

//Attach it to the element
$('#HoldListener').data('clickHoldTimeout', 2000); //Time to hold
$('#HoldListener').on('clickHold', function() {
    console.log('Worked!');
});
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<img src="http://lorempixel.com/400/200/" id="HoldListener">

Ver en JSFiddle

Ahora solo necesita establecer el tiempo de espera y agregar clickHoldevento en su elemento

Sergey Semushin
fuente
0

Prueba esto:

var thumbnailHold;

    $(".image_thumb").mousedown(function() {
        thumbnailHold = setTimeout(function(){
             checkboxOn(); // Your action Here

         } , 1000);
     return false;
});

$(".image_thumb").mouseup(function() {
    clearTimeout(thumbnailHold);
});
KR Vineeth
fuente