Ahora estoy revisando todas las teclas y busco dos guiones simultáneos. Luego inserto un guión em en la posición del cursor. Pero los guiones siguen ahí. (Nota: la función insertEmdash es una función para inserción en la posición del cursor que encontré en línea, realmente no entiendo cómo funciona)

var prev_key = "";

$(window).keydown(function(event) {
  if(event.keyCode === 189) {
    prev_key === "-" ? insertEmdash() : prev_key = "-";  
  }
});

function insertEmdash() { 
  var sel, range, html;
  let time = "—";
  sel = window.getSelection();
  range = sel.getRangeAt(0); 
  range.deleteContents(); 
  var textNode = document.createTextNode(time);
  range.insertNode(textNode);
  range.setStartAfter(textNode);
  sel.removeAllRanges();
  sel.addRange(range);

  prev_key = "";        
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
0
Ronald Railgun 16 feb. 2017 a las 00:40

3 respuestas

La mejor respuesta

Esto verificará cualquier -- en textarea, input o [contenteditable] y los reemplazará con .
También funciona incluso si el cursor no está al final del contenido.

document.getElementById('a').addEventListener('keyup', listener);
document.getElementById('b').addEventListener('keyup', listener); // does not work in IE or Edge, for some reason

function listener(e) {
  if (e.keyCode === 189 || e.keyCode === 109) {
    replaceHyphens(this);
  }
}

function replaceHyphens(el) {
  var sel = el.selectionStart || getCaretPosition(el),
    replaced = false;
  var key = (el.value ? 'value' : 'textContent');
  // replace any -- with —
  el[key] = el[key].replace(/-{2}/g, function(t) {replaced = true; return '—';});
  // fix the cursor position
  if (replaced) setCaretPosition(el, sel - 1);
}
// from http://stackoverflow.com/a/3976125 - gets the cursor position in a [contenteditable]
function getCaretPosition(editableDiv) {
  var caretPos = 0,
    sel, range;
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.rangeCount) {
      range = sel.getRangeAt(0);
      if (range.commonAncestorContainer.parentNode == editableDiv) {
        caretPos = range.endOffset;
      }
    }
  } else if (document.selection && document.selection.createRange) {
    range = document.selection.createRange();
    if (range.parentElement() == editableDiv) {
      var tempEl = document.createElement("span");
      editableDiv.insertBefore(tempEl, editableDiv.firstChild);
      var tempRange = range.duplicate();
      tempRange.moveToElementText(tempEl);
      tempRange.setEndPoint("EndToEnd", range);
      caretPos = tempRange.text.length;
    }
  }
  return caretPos;
}

function setCaretPosition(el, caret) {
  if (el.value) {
    el.setSelectionRange(caret, caret);
  } else {
    // from http://stackoverflow.com/a/6249440 - sets the cursor position in a [contenteditable]
    var tNode = el.firstChild;
    var range = document.createRange();
    range.setStart(tNode, caret);
    range.setEnd(tNode, caret);
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
  }
}
<textarea id="a" rows="6" cols="30"></textarea>
<p contenteditable style="height:100px;width:230px;border:1px solid black" id="b"></p>

Como resultado, obtener y configurar el cursor en un elemento contenteditable no es tan simple como lo es en una entrada.

2
Villa7_ 16 feb. 2017 a las 00:13

Supongo que desea hacer esto en un elemento de entrada, por lo que hice que mi implementación funcione con uno. Espero que los comentarios ayuden a comprender lo que está haciendo el código.

También el código clave 189 no funcionó para mí, pero 173 sí. Cambiar si es necesario.

var last_key_dash = false;

$("#text-input").keydown(function(event) {
  if(event.keyCode === 173) {	// 173 is '-' on my keyboard
    // If the previous key was '-'
    if (last_key_dash) {
      event.preventDefault();
      // Get text
      var text = $("#text-input").val();
      // Replace the trailing '-' with '—'
      $("#text-input").val(text.substr(0, text.length-1) + "—");
      /* setSelectionRange is here to set the cursor position at the end, because
         with the event being prevented, the browser doesn't update the cursor position when
         manipulating the text */
      $("#text-input")[0].setSelectionRange(text.length, text.length);
      last_key_dash = false;
      return;
    }
    last_key_dash = true;
  } else {
    last_key_dash = false;
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="text-input">
0
zini 15 feb. 2017 a las 22:13

Esto simplifica bastante las cosas. Funcionará en cualquier elemento que esté recibiendo entrada de caracteres.

Vea los comentarios en línea para más detalles:

var prevKeyCode = "";

$(window).keyup(function(event) { 
  // There are two keys on a standard keyboard that produce a hyphen character.
  // You must check for both.
  if(event.keyCode === 109 || event.keyCode === 189) {
    // If the current pressed key is a hyphen, call the replace function and pass
    // that function a reference to the element that the character was placed into
    prevKeyCode === 109 || prevKeyCode === 189 ? replace(event.target) : prevKeyCode = "-";  
  }
  
  // Store the pressed key for comparison on the next keystroke
  prevKeyCode = event.keyCode;
});

function replace(el){
  // Remove the last two characters from the element that received the key event
  el.value = el.value.substr(0, el.value.length - 2) + "—";
  
  // Now that the operation is done, reset the storage for new input
  prevKeyCode = "";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<textarea></textarea>
0
Scott Marcus 15 feb. 2017 a las 22:13