I was putting together some simple javascript to prevent characters being input in my form. I got to this stage where I was able to prevent all typing, and noticed that it prevents all characters except special ones, like å´ˆø`¨
which I can enter on my mac using: [Option]+`+[Letter key]
How can I prevent these being entered?
HTML:
<form>
<input name="myinput"></input>
</form>
JS:
document.querySelector('input').addEventListener('keypress', function (e) {
e.preventDefault();
return false;
});
fiddle: https://jsfiddle.net/6qty7dgr/
This is not working because these keystrokes actually start a composition event, i.e the full input has not yet been processed by the IME and you have "half-a-character". So calling preventDefault() on the keydown event here won't prevent the typing of this half character and the browser will insert it in the input anyway.
document.querySelector('input').addEventListener('keypress', function (e) {
e.preventDefault();
});
document.querySelector('input').addEventListener('compositionstart', function (e) {
console.log("composition start fired");
e.preventDefault(); // should have worked per specs, but doesn't...
});
<input name="myinput"></input>
By specs, you should have been able to prevent this by calling preventDefault() on the compositionstart event that does fire. However, no browser actually seems to support cancelling this event and it seems that for technical reasons they won't support it ever. However they should support cancelling the beforeinput event, but as of today only Safari does support cancelling it when it comes from a composition event...
"I was putting together some simple javascript to prevent characters being input in my form."
"How can I prevent these being entered?"
Emphasis added by me
Avoid keyboard events if you are using a form control. Form events usually work better since there is very little variation when interpreting the value of an input as opposed to keyboard events.
In the example below, the <input> listens for the "input" event. As the user types into the <input>, the .value property is being filtered by the following Regexp:
const rgx = new RegExp(/([å´ˆø`¨])*/, 'g');
(...)- Capture group: matched characters that are extracted.*----- Quantifier: zero or more matches.[...]- Class: a literal character. -, \, ], and ^ must be escaped by prefixing \ to it.å´ˆø``¨ are instantly replaced with a zero-space "".
Details are commented in example below
// Bind input tag to the input event
document.forms[0].elements.filter.oninput = dataFilter;
// Pass the Event Object
function dataFilter(e) {
// Delegate to input tag only
if (this.name == 'filter') {
/*
This matches
å´ˆø`¨
*/
const rgx = new RegExp(/([å´ˆø`¨])*/, 'g');
// Replace everything in rgx
const filtered = this.value.replace(rgx, '');
// Assign filtered string as value
this.value = filtered;
}
// Prevent input from rendering everything
e.preventDefault();
};
<form>
<input name='filter'>
</form>
Note: The onkeypress event is not fired for all keys (e.g. ALT, CTRL, SHIFT, ESC) in all browsers. To detect only whether the user has pressed a key, use the onkeydown event instead, because it works for all keys.