Reputation: 808
I have a simple implementation of some "real time" validation for an input. The allowed characters are lower and uppercase alpha, 0-9, hyphens, period, apostrophe, and spaces. The field is limited to 15 characters. I'm using jQuery here simply for ease of use in my example, it may or may not be used for my project.
Currently when trying to place/move the cursor within the input using the arrow keys I'm always taken to the end of the string. The same happens when trying to select all text using keys (CTRL-A). Is there a better way of accomplishing what I'm looking for that avoids this? It seems like poor user experience to me.
$( '#sample' ).on( 'keyup', function( event ) {
var str = $( this ).val();
str = str.replace(/[^A-Za-z-0-9.'\s]/g, "").substring(0,15);
$( this ).val( str );
});
I also have a jsFiddle set up here
Upvotes: 4
Views: 1834
Reputation: 5060
since you listen to keyup event, the function will be executed when any key is up, including CTRL+C, arrows. so instead, you can use .on('input', foo()) which will be executed only when text has being changed.
$( '#sample' ).on('input',function( event ) {
var str = $( this ).val();
str = str.replace(/[^A-Za-z-0-9.'\s]/g, "").substring(0,15);
$( this ).val( str );
});
Upvotes: 2
Reputation: 1430
Use prevent Default for special chars like this
$( '#sample' ).on( 'keypress', function( event ) {
var ch = String.fromCharCode(event.keyCode);
ch = ch.replace(/[^A-Za-z-0-9.'\s]/g, "");
if(ch == "") {
event.preventDefault();
}
});
Upvotes: 1
Reputation: 14521
Most of the issues can be preventent just by updating the input value only if it actually changes.
$( '#sample' ).on( 'keyup', function( event ) {
var str = $( this ).val();
str = str.replace(/[^A-Za-z-0-9.'\s]/g, "").substring(0,15);
if($( this ).val() != str) {
$( this ).val( str );
}
});
To solve removing characters from the middle of the text you need to remember and reset caret position. For that you can use following functions:
$.fn.getCaretPosition = function() {
var el = $(this).get(0);
var pos = 0;
if ('selectionStart' in el) {
pos = el.selectionStart - 1;
} else if ('selection' in document) {
el.focus();
var Sel = document.selection.createRange();
var SelLength = document.selection.createRange().text.length;
Sel.moveStart('character', -el.value.length);
pos = Sel.text.length - SelLength;
}
return pos;
}
$.fn.setCaretPosition = function(pos) {
if ($(this).get(0).setSelectionRange) {
$(this).get(0).setSelectionRange(pos, pos);
} else if ($(this).get(0).createTextRange) {
var range = $(this).get(0).createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
And extend your keyup handler:
$('#sample').on('keyup', function(event) {
var str = $(this).val();
str = str.replace(/[^A-Za-z-0-9.'\s]/g, "").substring(0, 15);
if ($(this).val() != str) {
var pos = $(this).getCaretPosition();
$(this).val(str);
$(this).setCaretPosition(pos);
}
});
See updated FIDDLE.
Upvotes: 3