2012-05-18 26 views
36

¿Es posible combinar una combinación de pulsaciones de teclas para disparar un solo evento?Detectar varias teclas en un solo evento de pulsación de teclas en jQuery

$(document).keyup(function(e){ 
    if (e.keyCode == 68 && e.keyCode == 69 && e.keyCode == 86) { 
     alert('oh hai'); 
    } 
}); 

Lo he probado en Chrome pero el evento no se dispara.

me llaman loco, pero estoy escribiendo una extensión de Chrome y quiere empujar D +E + V teclas al mismo tiempo a la fuerza en un modo de programador oculto.

+0

El código de tecla puede representar solo una clave. Intenta usar una combinación de keydown + keyup + flags para detectar esto. – yent

+0

posible duplicado de [¿Puede jQuery .keypress() detectar más de una clave al mismo tiempo?] (Http://stackoverflow.com/questions/4954403/can-jquery-keypress-detect-more-than-one-key -al mismo tiempo) –

+0

Considere cambiar la respuesta aceptada a [this] (http://stackoverflow.com/a/35249618/3853934). Presenta un enfoque más moderno y general. –

Respuesta

59

Si desea detectar que el d, e, y v llaves fueron todos hacia abajo al mismo tiempo, usted tiene que mirar tanto keydown y keyup y tener un mapa de las que están caídos Cuando todos estén bajos, dispara tu evento.

Por ejemplo: Live copy | source

var map = {68: false, 69: false, 86: false}; 
$(document).keydown(function(e) { 
    if (e.keyCode in map) { 
     map[e.keyCode] = true; 
     if (map[68] && map[69] && map[86]) { 
      // FIRE EVENT 
     } 
    } 
}).keyup(function(e) { 
    if (e.keyCode in map) { 
     map[e.keyCode] = false; 
    } 
}); 

Asumo que no le importa lo orden en que se presionan hacia abajo en (ya que sería un dolor para presionar de forma fiable), siempre y cuando todos están abajo al mismo tiempo en algún momento.

+0

mm como usted ha mencionado, creo que el orden es importante para atajos de teclado .. 'ctrl + v' no es lo mismo que' v + ctrl' –

+3

@Vega: las teclas modificadoras son una olla de pescado diferente. –

+0

@DreamWave: No, el controlador 'keyup' borra los indicadores. –

1

Debería capturar los tres eventos clave por separado y disparar su acción solo después de la tercera.

var keys = { 
     d: { code: 100, pressed: false, next: 'e' }, 
     e: { code: 101, pressed: false, next: 'v' }, 
     v: { code: 118, pressed: false, next: 'd' } 
    }, 
    nextKey = 'd'; 

$(document).keypress(function(e) { 
    if (e.keyCode === keys[nextKey].code) { 
     keys[nextKey].pressed = true; 
     nextKey = keys[nextKey].next; 
    } else { 
     keys.d.pressed = false; 
     keys.e.pressed = false; 
     keys.v.pressed = false; 
     nextKey = 'd'; 
    } 

    if (keys.d.pressed && keys.e.pressed && keys.v.pressed) { 
     alert('Entering dev mode...'); 
    } 
});​ 

Hay una serie de formas de hacerlo, por supuesto. Este ejemplo no requiere que mantenga presionadas las teclas simultáneamente, solo que las escribe en orden: dev.

Si usó esto, es posible que desee aumentarlo para borrar los indicadores pressed después de un intervalo de tiempo.

Aquí hay un working example.


responsabilidad: Me da cuenta de la pregunta original, dijo que las claves deben ser "apretados". Esta es solo una alternativa, ya que otros respondedores ya han proporcionado suficientes soluciones para que las teclas se presionen juntas.

+0

Probé esto en Chrome y no funcionaba con los códigos de tecla originales. Ya lo he visto antes, pero me olvido de por qué son diferentes. – FishBasketGordo

0

si bien entendido: ejemplo violín, http://jsfiddle.net/gAtTk/ (mirar a la consola JS)

este código le permitirá introducir la palabra "dev" (y en este ejemplo, al final se elimina el evento keyup)

(function(seq) { 
    var tmp = seq.slice(); 
    $(document).on("keyup.entersequence", function(e){ 
     if (!(e.keyCode === tmp.pop())) { 
      tmp = seq.slice(); 
     } 
     else { 
      console.log(e.keyCode); 
      if (!tmp.length) { 
       console.log('end'); 
       $(document).off("keyup.entersequence"); 
      } 
     } 
    }); 
}([68,69,86].reverse())); 
0

se debe utilizar la keydown y eventos keyup, para manejar más de una tecla "al mismo tiempo".

input.on("keydown", function (e) { 
         if (e.which == 17) { 
          isCtrl = true; // Ctrl 
          return; 
         } 

         /* Ctrl and "c" */ 
         if (isCtrl && e.which == 67) { 
          //some code 
         } 
        }).keyup(function (e) { 
         if (e.which == 17) { 
          isCtrl = false; // no Ctrl 
         } 
        }); 
+0

* No puede * asignar un valor a una variable que aún no se ha definido. –

+0

Una variable sin definir al principio sería una nueva variable en la pila global. Esto debería ser solo un ejemplo de cómo esto sería posible. Si lo desea, puedo proporcionar un JSFiddle, pero la pregunta ya está marcada como resuelta ... – kapsi

+0

Este es un error, no una función, y las variables globales son malas. –

18

Parecido al de Vega ...pero más simple

var down = {}; 
$(document).keydown(function(e) { 
    down[e.keyCode] = true; 
}).keyup(function(e) { 
    if (down[68] && down[69] && down[86]) { 
     alert('oh hai'); 
    } 
    down[e.keyCode] = false; 
});​ 
+0

violínalo aquí: http://jsfiddle.net/5QYKH/ –

+4

Esto es realmente bueno y funcionará bien. Si necesita hacer coincidir una secuencia de teclas, puede verificar el orden presionando a una matriz: en lugar de 'abajo [e.keyCode] = true', diga' down.push (e.keyCode) 'y valide en su lugar de esto: 'if (abajo [68] && down [69] && down [86])', como esto: 'if (abajo [0] === 68 && down [1] === 69 && down [2] === 86) '. – lu1s

+2

Creé un [violín] (http://jsfiddle.net/bplumb/B2efC/1/) para complementar el comentario de lu1s. –

8

Quizás una combinación de teclas más simple sería más fácil?

¿Qué tal algo como Shift + Alt + D? (Es probable que no debe utilizar la tecla de control porque la mayoría de los navegadores ya se interpretan Ctrl + D de una manera u otra)

El código para esto sería algo como esto:

if(e.shiftKey && e.altKey && e.keyCode == 68) 
{ 
    alert('l33t!'); 
} 
+1

que no es la respuesta a la pregunta, ¿verdad? –

+0

@ParthThakkar: a partir de la pregunta, puede derivar el requisito: "forzarlo a un modo de desarrollador oculto". Siendo pragmático, sugerí una alternativa simple para lograr el mismo resultado final – gplumb

+0

bien ... ese puede ser el camino a seguir ... pensé que esa no era la respuesta a la pregunta requerida, así que solo pregunté eso. ... sin ofensa!) –

-1

Si se preocupan por la y también debe mantener presionada una tecla y tocar otra (por ejemplo: Shift + DEL, DEL, DEL ...), sin tener que levantar la primera tecla para que el evento vuelva a disparar ... He modificado @ El [fiddle] comentario de BlakePlumm que extendió el comentario de @ lu1s sobre la respuesta de @ ParthThakkar.

Además, el uso de .on() de jQuery le permite escuchar la secuencia de teclas solo en ciertos elementos. Cambie 'cuerpo' a 'input.selector' o cualquier otra cosa.

var map = []; 
var down = []; 
$(document).on('keydown','body', function(e) { 
    if(!map[e.which]){ 
     down.push(e.which); 
     if(down[0] === 68 && down[1] === 69 && down[2] === 86) { 
      console.log('D + E + V'); 
     } else if(down[0] === 16 && down[1] === 46) { 
      console.log('SHIFT + DEL'); 
     } 
     /* more conditions here */ 
    } 
    map[e.which] = true; 
}).keyup(function(e) { 
    map[e.which] = false; 

    /* important for detecting repeat presses of 
     last key while holding first key(s) 
     (can be shortened. see fiddle) */ 
    var len = down.length; 
    while (len--) { 
     if(down[len] === e.which) down.splice(len,1); //removes only the keyup'd key 
    }   
    $('.alert').html(''); 
}); 

pensamientos adicionales: Si sólo un poco importa el orden - es decir, las primeras teclas sólo tiene que ser hacia abajo, siempre y cuando su clave principal evento de la cocción se pulsa el pasado (cosas como CTRL + SHIFT + TAB, TAB, TAB), agregar esta condición:

else if(down.length>2) { 
    if($.inArray(68,down)!=-1 && $.inArray(69,down)!=-1 && down[2] === 86) { 
     $('.alert').html('A hacky D+E+V was pressed'); 
    } 
} 

violín con más opciones gloriosos y demostración en vivo: - http://jsfiddle.net/kstarr/4ftL1p3k/

-1

https://github.com/JesseBuesking/jquery.hotkeys.extended

Mira esto. Es posible que esté buscando esto.

Podemos activar una función en varias pulsaciones de teclas. por ejemplo: p + t + k

$(document).hotkeys('p', 't', 'k', function(){ 
     //show blurbox 
     $('#popup').blurbox({ 
      blur: 10, animateBlur: true, bgColor: 'rgba(255,255,0,0.2)' 
     })bb.show(); 
    }); 

tal vez su buscando este.

1

Probé las tres respuestas principales (a partir de esta publicación), y ninguna de ellas funcionó para mí. No restablecieron las claves.

Si se necesitaron 3 teclas para iniciar el guión, después de dispararlo una vez, presionar cualquiera de las 3 teclas lo dispararía nuevamente.

Acabo de escribir este script y está funcionando muy bien. Utiliza Shift + S para disparar, pero puedes cambiar eso fácilmente. Se restablece después de presionar la combinación.

var saveArray = new Array(); 
saveArray[0] = false; 
saveArray[1] = false; 

$(document).ready(function(){ 

    $(document).keydown(function (f){ 
     if (f.keyCode == 16) { 
      saveArray[0] = true; 
     } 
    }); 

    $(document).keyup(function (g){ 
     if(g.which == 16){ 
      saveArray[0] = false; 
     } 
    }); 

    $(document).keydown(function (h){ 
     if (h.keyCode == 83) { 
      saveArray[1] = true; 
      if(saveArray[0] == true && saveArray[1] == true){ 
       saveArray[0] = false; 
       saveArray[1] = false; 
       keypressSaveFunction(); 
      } 
     } 
    }); 

    $(document).keyup(function (i){ 
     if (i.which == 83) { 
      saveArray[1] = false; 
     } 
    }); 
}); 

    function keypressSaveFunction(){ 
     alert("You pressed Shift+S"); 
    } 

violín: http://jsfiddle.net/9m8yswwo/13/

+0

Esto no funcionará si el usuario continúa manteniendo presionada la tecla Mayús y presiona S una segunda vez. Obligar a 'saveArray [0] = false' en el evento de keydown de S (que hace una suposición de que la tecla Shift fue liberada) es un hack bastante horrible. Por otro lado, puede ser la razón por la que esto funcionó para ti. – poshest

+0

Por favor * no * use 'new Array()'. –

0

Un poco solución más moderna, se aprovecha de arrow functions y rest parameters:

const multipleKeypress = (function($document) { 
 
    // Map of keys which are currently down. 
 
    const keymap = {} 
 
    // Update keymap on keydown and keyup events. 
 
    $document.on(
 
    "keydown keyup" 
 
    // If the key is down, assign true to the corresponding 
 
    // propery of keymap, otherwise assign false. 
 
    ,event => keymap[event.keyCode] = event.type === "keydown" 
 
) 
 
    // The actual function. 
 
    // Takes listener as the first argument, 
 
    // rest of the arguments are key codes. 
 
    return (listener, ...keys) => 
 
    $document.keydown(() => { 
 
     // Check if every of the specified keys is down. 
 
     if (keys.every(key => keymap[key])) 
 
     listener(event) 
 
    }) 
 
// Pass a jQuery document object to cache it. 
 
}($(document))) 
 

 
// Example usage: 
 
multipleKeypress(() => console.log("pressed"), 68, 69, 86) 
 

 
// Automatically focus the snippet result 
 
window.focus()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<p>Try pressing <kbd>d</kbd>, <kbd>e</kbd> and <kbd>v</kbd> at once.</p>

0

Usa este código para tener un evento desencadenado por múltiples pulsaciones de teclas + Tiempo de espera después de 100 ms para evitar los tipos erróneos. En este ejemplo: si se presionan A, Z, E dentro de un período de tiempo de 100 ms, se desencadenará el evento.

var map = {65:false,90:false,69:false}; //Modify keyCodes here 
$(document).keydown(function(e){ 
    console.log(e.keyCode); 
    map[e.keyCode] = e.keyCode in map ? true : map[e.keyCode] || false; 
    var result = Object.keys(map).filter(function(key){ 
     return map[key]; 
    }).length === Object.keys(map).length ? true : false; 
    if(result){ 
     //Your event here 
     Object.keys(map).forEach(function(key){ 
      map[key] = false; 
     }); 
    } 
    setTimeout(function(){ 
     map[e.keyCode] = false; 
    },100); 
}); 
Cuestiones relacionadas