Reputation: 33
Now I am checking all keydowns and look for two simultaneous hyphens. Then I insert an em dash at cursor position. But the hyphens are still there. (NB: the insertEmdash
function is a function for insertion at cursor position I found online, I don't really understand how it works)
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>
Upvotes: 0
Views: 2439
Reputation: 2642
This will check for any --
in a textarea
, input
, or [contenteditable]
and replace them with —
.
It also works even if the cursor isn't at the end of the content.
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>
As it turns out, getting and setting the cursor in a contenteditable
element isn't quite as simple as it is in an input.
Upvotes: 2
Reputation: 3
I'm assuming you want to do this on a input element, so I made my implementation work with one. I hope that the comments help understanding what the code is doing.
Also keycode 189 didn't work for me, but 173 did. Change if needed.
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">
Upvotes: 0
Reputation: 65806
This simplifies things quite a bit. It will work on any element that is receiving character input.
See the comments inline for details:
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>
Upvotes: 0