Now, in my implementation, I've decided to perform the auto-injection at the moment the user requests the second dash (essentially canceling and replacing their keydown event). Other implementations may wait for a space to be entered before executing the replacement. There's no right or wrong approach here - this was just an arbitrary decision.
As a fun caveat to this experiment, I've decided to use event-delegation on the document, targeting any and all inputs that have the ".emdashify" class. And, to demonstrate said targeting, I've included both activated and non-activated inputs in my demo:
As you can see, the algorithm is such that when I detect a "-" key is about to be entered, I look to see if the existing character at the given selection-start is also a dash. If it is, I cancel the current keydown behavior (thereby preventing the requested "-" character from getting added to the input); and, I replace the existing dash with an em dash.
If we run this code and enter some double-dashes, we get the following output:
As you can see, the first two inputs, which have the "emdashify" class, successfully auto-replace the double-dash with an em dash. And, the third input, which is not "emdashified", allows double-dashes to be entered just as the user typed them.
One thing to keep in mind is that an input doesn't emit an "input" event when the value is changed programmatically. As such, if you override the value being entered, other handlers that are watching for "input" events won't see the change you added. This isn't a problem, per-say; it's just something to be aware of in the context of a larger application interface.
Want to use code from this post? Check out the license.
After posting this, I got some great feedback from a few people at work:
Johannes Hoff suggested that I should include
target.selectionEnd when slicing the text so that I remove any highlighted text, which would be more in line with the user's intent.
Don Abrams suggested that there should be a way to undo the auto-replacement in cases where a user actually does want to type
I'll let this marinate in the back of my mind and see what I can come up with.