web-dev-qa-db-fra.com

Changer le clavier

Dans une zone de saisie ou contenteditable = true div, comment puis-je modifier une pression de touche pour la lettre "a" pour renvoyer une action-clé pour la lettre "b"? Autrement dit, chaque fois que vous tapez la lettre "a" dans le div, la sortie est en réalité la lettre "b".

Je ne suis pas concerné par une solution qui fonctionne dans IE - juste une qui fonctionne dans Safari, Chrome, et FF.

Dans Chrome, je peux voir qu'un événement de frappe a les propriétés "charCode", "keyCode" et "which", qui reçoivent toutes le numéro d'événement de frappe. Si je déclenche un événement sur un appui-clavier, je peux modifier ces valeurs, mais je ne peux pas déterminer ce qu'il faut renvoyer, de sorte que la clé tapée est différente. Par exemple:

$(window).keypress(function(e){  //$(window) is a jQuery object
    e.charCode = 102;
    e.which = 102;
    e.keyCode = 102;
    console.log(e);
    return e;
});

Je peux également voir que, avec charCode, qui, et keyCode, il existe également une propriété "originalEvent" qui, à son tour, possède également ces propriétés. Cependant, je n'ai pas été capable de les modifier (j'ai essayé avec des choses comme e.originalEvent.charCode = 102).

22
maxedison

Vous ne pouvez pas modifier le caractère ou la clé associé à un événement clé, ni simuler complètement un événement clé. Cependant, vous pouvez gérer vous-même la frappe et insérer manuellement le caractère souhaité au point/curseur d'insertion actuel. J'ai fourni du code pour le faire à plusieurs endroits sur Stack Overflow. Pour un élément contenteditable:

Voici un exemple de jsFiddle: http://www.jsfiddle.net/Ukkmu/4/

Pour une entrée:

Exemple jsFiddle inter-navigateurs: http://www.jsfiddle.net/EXH2k/6/

IE> = 9 et exemple non-IE jsFiddle: http://www.jsfiddle.net/EXH2k/7/

28
Tim Down

Eh bien, ce que vous pouvez faire pour un <input> ou un <textarea> consiste simplement à vous assurer que la valeur ne contient aucun caractère "a":

$('input.whatever').keypress(function() {
  var inp = this;
  setTimeout(function() {
    inp.value = inp.value.replace(/a/g, 'b');
  }, 0);
});

Cette approche ne pourrait probablement pas gérer toutes les astuces que vous pourriez réaliser avec quelque chose qui a vraiment échangé le caractère "pressé", mais je ne connais aucun moyen de le faire.

edit - oh, et la raison pour laquelle j’ai tapé dans cet exemple avec le "correctif" se produisant dans un gestionnaire de dépassement de délai est qu’il s’assure que le navigateur a la possibilité de gérer le comportement natif de l’événement "pression". Lorsque le code du gestionnaire de délai d'attente s'exécute, nous sommes sûrs que la valeur de l'élément aura été mise à jour. Je comprends que le code de la cargaison est un peu culte à ce code.

1
Pointy

Mon exemple de solution (changer dans input[type=text] le caractère ',' en '.'):

element.addEventListener('keydown', function (event) {
if(event.key === ','){
  setTimeout(function() {
    event.target.value += '.';
  }, 4);
  event.preventDefault();
};
1
Boyko Oleksiy

Je ne sais pas si c'est faisable "facilement", avec quelque chose comme ça:

$(window).keypress(function(e) { 
    //Captures 'a' or 'A'
    if(e.which == 97 || e.which == 65)
    {
        //Simulate a keypress in a specific field  
    }
});

Je sais que jQuery a un plug-in de simulation pour simuler des événements de pression de touche, etc., jQuery Simulate . Cela vaut peut-être la peine d’examiner - peut-être aussi un type de jQuery Trigger () event.

0
Rion Williams

Voici un exemple sans utiliser aucune bibliothèque

const input = document.querySelector('input')

// this is the order of events into an input
input.addEventListener('focus', onFocus)
input.addEventListener('keydown', keyDown)
input.addEventListener('keypress', keyPress)
input.addEventListener('input', onInput)
input.addEventListener('keyup', keyUp)
input.addEventListener('change', onChange)
input.addEventListener('blur', onBlur)

function onFocus  (event) { info(event) }
function keyDown  (event) { info(event) }
function keyPress (event) {
  info(event)
  // this 2 calls will stop `input` and `change` events
  event.preventDefault();
  event.stopPropagation();
  
  // get current props
  const target = event.target
  const start = target.selectionStart;
  const end = target.selectionEnd;
  const val = target.value;
  
  // get some char based on event
  const char = getChar(event);
  
  // create new value
  const value = val.slice(0, start) + char + val.slice(end);
  
  // first attemp to set value
  // (doesn't work in react because value setter is overrided)
  // target.value = value

  // second attemp to set value, get native setter
  const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
    window.HTMLInputElement.prototype,
    "value"
  ).set;
  nativeInputValueSetter.call(target, value);

  // change cursor position
  target.selectionStart = target.selectionEnd = start + 1;
  
  // dispatch `input` again
  const newEvent = new InputEvent('input', {
    bubbles: true,
    inputType: 'insertText',
    data: char
  })
  event.target.dispatchEvent(newEvent);
}
function keyUp    (event) { info(event) }
function onInput  (event) { info(event) }
function onChange (event) { info(event) }
function onBlur   (event) {
  // dispatch `change` again
  const newEvent = new Event('change', { bubbles: true })
  event.target.dispatchEvent(newEvent);
  info(event)
}

function info     (event) { console.log(event.type) }

function getChar(event) {
  // will show X if letter, will show Y if Digit, otherwise Z
  return event.code.startsWith('Key')
    ? 'X'
    : event.code.startsWith('Digit')
      ? 'Y'
      : 'Z'
}
<input type="text">

0
Andrew Luca