Handle tab in textarea - javascript

I need to insert a tab into a textarea when a tab is clicked rather than moving the focus to the next element.
I've done some research but found no solutions that actually use tab instead of a series of spaces.
How would I do this and how would I insert a true tab instead of 4 spaces?

jsFiddle example.
JavaScript:
function insertTab(o, e) {
var kC = e.keyCode ? e.keyCode : e.charCode ? e.charCode : e.which;
if (kC == 9 && !e.shiftKey && !e.ctrlKey && !e.altKey) {
var oS = o.scrollTop;
if (o.setSelectionRange) {
var sS = o.selectionStart;
var sE = o.selectionEnd;
o.value = o.value.substring(0, sS) + "\t" + o.value.substr(sE);
o.setSelectionRange(sS + 1, sS + 1);
o.focus();
}
else if (o.createTextRange) {
document.selection.createRange().text = "\t";
e.returnValue = false;
}
o.scrollTop = oS;
if (e.preventDefault) {
e.preventDefault();
}
return false;
}
return true;
}​
Ripped without shame from here.

Wherever the code says to add those four spaces, replace the four spaces either with a literal tab character, or with the escape sequence \t.

Related

best way to restrict special characters in text field input [duplicate]

How do I block special characters from being typed into an input field with jquery?
A simple example using a regular expression which you could change to allow/disallow whatever you like.
$('input').on('keypress', function (event) {
var regex = new RegExp("^[a-zA-Z0-9]+$");
var key = String.fromCharCode(!event.charCode ? event.which : event.charCode);
if (!regex.test(key)) {
event.preventDefault();
return false;
}
});
I was looking for an answer that restricted input to only alphanumeric characters, but still allowed for the use of control characters (e.g., backspace, delete, tab) and copy+paste. None of the provided answers that I tried satisfied all of these requirements, so I came up with the following using the input event.
$('input').on('input', function() {
$(this).val($(this).val().replace(/[^a-z0-9]/gi, ''));
});
Edit:
As rinogo pointed out in the comments, the above code snippet forces the cursor to the end of the input when typing in the middle of the input text. I believe the code snippet below solves this problem.
$('input').on('input', function() {
var c = this.selectionStart,
r = /[^a-z0-9]/gi,
v = $(this).val();
if(r.test(v)) {
$(this).val(v.replace(r, ''));
c--;
}
this.setSelectionRange(c, c);
});
Short answer: prevent the 'keypress' event:
$("input").keypress(function(e){
var charCode = !e.charCode ? e.which : e.charCode;
if(/* Test for special character */ )
e.preventDefault();
})
Long answer: Use a plugin like jquery.alphanum
There are several things to consider when picking a solution:
Pasted text
Control characters like backspace or F5 may be prevented by the above code.
é, í, ä etc
Arabic or Chinese...
Cross Browser compatibility
I think this area is complex enough to warrant using a 3rd party plugin. I tried out several of the available plugins but found some problems with each of them so I went ahead and wrote jquery.alphanum. The code looks like this:
$("input").alphanum();
Or for more fine-grained control, add some settings:
$("#username").alphanum({
allow : "€$£",
disallow : "xyz",
allowUpper : false
});
Hope it helps.
Use simple onkeypress event inline.
<input type="text" name="count" onkeypress="return /[0-9a-zA-Z]/i.test(event.key)">
Use HTML5's pattern input attribute!
<input type="text" pattern="^[a-zA-Z0-9]+$" />
Use regex to allow/disallow anything. Also, for a slightly more robust version than the accepted answer, allowing characters that don't have a key value associated with them (backspace, tab, arrow keys, delete, etc.) can be done by first passing through the keypress event and check the key based on keycode instead of value.
$('#input').bind('keydown', function (event) {
switch (event.keyCode) {
case 8: // Backspace
case 9: // Tab
case 13: // Enter
case 37: // Left
case 38: // Up
case 39: // Right
case 40: // Down
break;
default:
var regex = new RegExp("^[a-zA-Z0-9.,/ $#()]+$");
var key = event.key;
if (!regex.test(key)) {
event.preventDefault();
return false;
}
break;
}
});
Your textbox:
<input type="text" id="name">
Your javascript:
$("#name").keypress(function(event) {
var character = String.fromCharCode(event.keyCode);
return isValid(character);
});
function isValid(str) {
return !/[~`!##$%\^&*()+=\-\[\]\\';,/{}|\\":<>\?]/g.test(str);
}
Take a look at the jQuery alphanumeric plugin. https://github.com/KevinSheedy/jquery.alphanum
//All of these are from their demo page
//only numbers and alpha characters
$('.sample1').alphanumeric();
//only numeric
$('.sample4').numeric();
//only numeric and the .
$('.sample5').numeric({allow:"."});
//all alphanumeric except the . 1 and a
$('.sample6').alphanumeric({ichars:'.1a'});
this is an example that prevent the user from typing the character "a"
$(function() {
$('input:text').keydown(function(e) {
if(e.keyCode==65)
return false;
});
});
key codes refrence here:
http://www.expandinghead.net/keycode.html
I use this code modifying others that I saw. Only grand to the user write if the key pressed or pasted text pass the pattern test (match) (this example is a text input that only allows 8 digits)
$("input").on("keypress paste", function(e){
var c = this.selectionStart, v = $(this).val();
if (e.type == "keypress")
var key = String.fromCharCode(!e.charCode ? e.which : e.charCode)
else
var key = e.originalEvent.clipboardData.getData('Text')
var val = v.substr(0, c) + key + v.substr(c, v.length)
if (!val.match(/\d{0,8}/) || val.match(/\d{0,8}/).toString() != val) {
e.preventDefault()
return false
}
})
$(function(){
$('input').keyup(function(){
var input_val = $(this).val();
var inputRGEX = /^[a-zA-Z0-9]*$/;
var inputResult = inputRGEX.test(input_val);
if(!(inputResult))
{
this.value = this.value.replace(/[^a-z0-9\s]/gi, '');
}
});
});
Write some javascript code on onkeypress event of textbox.
as per requirement allow and restrict character in your textbox
function isNumberKeyWithStar(evt) {
var charCode = (evt.which) ? evt.which : event.keyCode
if (charCode > 31 && (charCode < 48 || charCode > 57) && charCode != 42)
return false;
return true;
}
function isNumberKey(evt) {
var charCode = (evt.which) ? evt.which : event.keyCode
if (charCode > 31 && (charCode < 48 || charCode > 57))
return false;
return true;
}
function isNumberKeyForAmount(evt) {
var charCode = (evt.which) ? evt.which : event.keyCode
if (charCode > 31 && (charCode < 48 || charCode > 57) && charCode != 46)
return false;
return true;
}
To replace special characters, space and convert to lower case
$(document).ready(function (){
$(document).on("keyup", "#Id", function () {
$("#Id").val($("#Id").val().replace(/[^a-z0-9\s]/gi, '').replace(/[_\s]/g, '').toLowerCase());
});
});
Yes you can do by using jQuery as:
<script>
$(document).ready(function()
{
$("#username").blur(function()
{
//remove all the class add the messagebox classes and start fading
$("#msgbox").removeClass().addClass('messagebox').text('Checking...').fadeIn("slow");
//check the username exists or not from ajax
$.post("user_availability.php",{ user_name:$(this).val() } ,function(data)
{
if(data=='empty') // if username is empty
{
$("#msgbox").fadeTo(200,0.1,function() //start fading the messagebox
{
//add message and change the class of the box and start fading
$(this).html('Empty user id is not allowed').addClass('messageboxerror').fadeTo(900,1);
});
}
else if(data=='invalid') // if special characters used in username
{
$("#msgbox").fadeTo(200,0.1,function() //start fading the messagebox
{
//add message and change the class of the box and start fading
$(this).html('Sorry, only letters (a-z), numbers (0-9), and periods (.) are allowed.').addClass('messageboxerror').fadeTo(900,1);
});
}
else if(data=='no') // if username not avaiable
{
$("#msgbox").fadeTo(200,0.1,function() //start fading the messagebox
{
//add message and change the class of the box and start fading
$(this).html('User id already exists').addClass('messageboxerror').fadeTo(900,1);
});
}
else
{
$("#msgbox").fadeTo(200,0.1,function() //start fading the messagebox
{
//add message and change the class of the box and start fading
$(this).html('User id available to register').addClass('messageboxok').fadeTo(900,1);
});
}
});
});
});
</script>
<input type="text" id="username" name="username"/><span id="msgbox" style="display:none"></span>
and script for your user_availability.php will be:
<?php
include'includes/config.php';
//value got from the get method
$user_name = trim($_POST['user_name']);
if($user_name == ''){
echo "empty";
}elseif(preg_match('/[\'^£$%&*()}{##~?><>,|=_+¬-]/', $user_name)){
echo "invalid";
}else{
$select = mysql_query("SELECT user_id FROM staff");
$i=0;
//this varible contains the array of existing users
while($fetch = mysql_fetch_array($select)){
$existing_users[$i] = $fetch['user_id'];
$i++;
}
//checking weather user exists or not in $existing_users array
if (in_array($user_name, $existing_users))
{
//user name is not availble
echo "no";
}
else
{
//user name is available
echo "yes";
}
}
?>
I tried to add for / and \ but not succeeded.
You can also do it by using javascript & code will be:
<!-- Check special characters in username start -->
<script language="javascript" type="text/javascript">
function check(e) {
var keynum
var keychar
var numcheck
// For Internet Explorer
if (window.event) {
keynum = e.keyCode;
}
// For Netscape/Firefox/Opera
else if (e.which) {
keynum = e.which;
}
keychar = String.fromCharCode(keynum);
//List of special characters you want to restrict
if (keychar == "'" || keychar == "`" || keychar =="!" || keychar =="#" || keychar =="#" || keychar =="$" || keychar =="%" || keychar =="^" || keychar =="&" || keychar =="*" || keychar =="(" || keychar ==")" || keychar =="-" || keychar =="_" || keychar =="+" || keychar =="=" || keychar =="/" || keychar =="~" || keychar =="<" || keychar ==">" || keychar =="," || keychar ==";" || keychar ==":" || keychar =="|" || keychar =="?" || keychar =="{" || keychar =="}" || keychar =="[" || keychar =="]" || keychar =="¬" || keychar =="£" || keychar =='"' || keychar =="\\") {
return false;
} else {
return true;
}
}
</script>
<!-- Check special characters in username end -->
<!-- in your form -->
User id : <input type="text" id="txtname" name="txtname" onkeypress="return check(event)"/>
just the numbers:
$('input.time').keydown(function(e) { if(e.keyCode>=48 &&
e.keyCode<=57) {
return true; } else {
return false; } });
or for time including ":"
$('input.time').keydown(function(e) { if(e.keyCode>=48 &&
e.keyCode<=58) {
return true; } else {
return false; } });
also including delete and backspace:
$('input.time').keydown(function(e) { if((e.keyCode>=46 &&
e.keyCode<=58) || e.keyCode==8) { return true; } else {
return false; } });
unfortuneatly not getting it to work on a iMAC
Wanted to comment on Alex's comment to Dale's answer. Not possible (first need how much "rep"? That wont happen very soon.. strange system.)
So as an answer:
Backspace can be added by adding \b to the regex definition like this: [a-zA-Z0-9\b].
Or you simply allow the whole Latin range, including more or less anything "non exotic" characters (also control chars like backspace): ^[\u0000-\u024F\u20AC]+$
Only real unicode char outside latin there is the euro sign (20ac), add whatever you may need else.
To also handle input entered via copy&paste, simply also bind to the "change" event and check the input there too - deleting it or striping it / giving an error message like "not supported characters"..
if (!regex.test($j(this).val())) {
alert('your input contained not supported characters');
$j(this).val('');
return false;
}
Restrict specials characters on keypress. Here's a test page for key codes: http://www.asquare.net/javascript/tests/KeyCode.html
var specialChars = [62,33,36,64,35,37,94,38,42,40,41];
some_element.bind("keypress", function(event) {
// prevent if in array
if($.inArray(event.which,specialChars) != -1) {
event.preventDefault();
}
});
In Angular, I needed a proper currency format in my textfield. My solution:
var angularApp = angular.module('Application', []);
...
// new angular directive
angularApp.directive('onlyNum', function() {
return function( scope, element, attrs) {
var specialChars = [62,33,36,64,35,37,94,38,42,40,41];
// prevent these special characters
element.bind("keypress", function(event) {
if($.inArray(event.which,specialChars) != -1) {
prevent( scope, event, attrs)
}
});
var allowableKeys = [8,9,37,39,46,48,49,50,51,52,53,54,55,56
,57,96,97,98,99,100,101,102,103,104,105,110,190];
element.bind("keydown", function(event) {
if($.inArray(event.which,allowableKeys) == -1) {
prevent( scope, event, attrs)
}
});
};
})
// scope.$apply makes angular aware of your changes
function prevent( scope, event, attrs) {
scope.$apply(function(){
scope.$eval(attrs.onlyNum);
event.preventDefault();
});
event.preventDefault();
}
In the html add the directive
<input only-num type="text" maxlength="10" id="amount" placeholder="$XXXX.XX"
autocomplete="off" ng-model="vm.amount" ng-change="vm.updateRequest()">
and in the corresponding angular controller I only allow there to be only 1 period, convert text to number and add number rounding on 'blur'
...
this.updateRequest = function() {
amount = $scope.amount;
if (amount != undefined) {
document.getElementById('spcf').onkeypress = function (e) {
// only allow one period in currency
if (e.keyCode === 46 && this.value.split('.').length === 2) {
return false;
}
}
// Remove "." When Last Character and round the number on blur
$("#amount").on("blur", function() {
if (this.value.charAt(this.value.length-1) == ".") {
this.value.replace(".","");
$("#amount").val(this.value);
}
var num = parseFloat(this.value);
// check for 'NaN' if its safe continue
if (!isNaN(num)) {
var num = (Math.round(parseFloat(this.value) * 100) / 100).toFixed(2);
$("#amount").val(num);
}
});
this.data.amountRequested = Math.round(parseFloat(amount) * 100) / 100;
}
...
You don't need jQuery for this action
You can achieve this using plain JavaScript, You can put this in the onKeyUp event.
Restrict - Special Characters
e.target.value = e.target.value.replace(/[^\w]|_/g, '').toLowerCase()
Accept - Number only
e.target.value = e.target.value.replace(/[^0-9]/g, '').toLowerCase()
Accept - Small Alphabet only
e.target.value = e.target.value.replace(/[^0-9]/g, '').toLowerCase()
I could write for some more scenarios but I have to maintain the specific answer.
Note It will work with jquery, react, angular, and so on.
$(this).val($(this).val().replace(/[^0-9\.]/g,''));
if( $(this).val().indexOf('.') == 0){
$(this).val("");
}
//this is the simplest way
indexof is used to validate if the input started with "."
[User below code to restrict special character also
$(h.txtAmount).keydown(function (event) {
if (event.shiftKey) {
event.preventDefault();
}
if (event.keyCode == 46 || event.keyCode == 8) {
}
else {
if (event.keyCode < 95) {
if (event.keyCode < 48 || event.keyCode > 57) {
event.preventDefault();
}
}
else {
if (event.keyCode < 96 || event.keyCode > 105) {
event.preventDefault();
}
}
}
});]
Allow only numbers in TextBox (Restrict Alphabets and Special Characters)
/*code: 48-57 Numbers
8 - Backspace,
35 - home key, 36 - End key
37-40: Arrow keys, 46 - Delete key*/
function restrictAlphabets(e){
var x=e.which||e.keycode;
if((x>=48 && x<=57) || x==8 ||
(x>=35 && x<=40)|| x==46)
return true;
else
return false;
}
/**
* Forbids special characters and decimals
* Allows numbers only
* */
const numbersOnly = (evt) => {
let charCode = (evt.which) ? evt.which : evt.keyCode;
if (charCode === 46 && charCode > 31 && (charCode < 48 || charCode > 57)) {
return false;
}
let inputResult = /^[0-9]*$/.test(evt.target.value);
if (!inputResult) {
evt.target.value = evt.target.value.replace(/[^a-z0-9\s]/gi, '');
}
return true;
}
In HTML:
<input type="text" (keypress)="omitSpecialChar($event)"/>
In JS:
omitSpecialChar(event) {
const keyPressed = String.fromCharCode(event.keyCode);
const verifyKeyPressed = /^[a-zA-Z\' \u00C0-\u00FF]*$/.test(keyPressed);
return verifyKeyPressed === true;
}
In this example it is possible to type accents.
$(document).ready(function() {
$('#Description').bind('input', function() {
var c = this.selectionStart,
r = /[^a-z0-9 .]/gi,
v = $(this).val();
if (r.test(v)) {
$(this).val(v.replace(r, ''));
c--;
}
this.setSelectionRange(c, c);
if (!(checkEmpty($("#Description").val()))) {
$("#Description").val("");
} //1Apr2022 code end
});
$('#Description').on('change', function() {
if (!(checkEmpty($("#Description").val()))) {
$("#Description").val("");
} //1Apr2022 code end
});
});
function checkEmpty(field) { //1Apr2022 new code
if (field == "" ||
field == null ||
field == "undefinied") {
return false;
} else if (/^\s*$/.test(field)) {
return false;
} else {
return true;
}
}
A more enhanced form would be
$('input[type=text]').on('input', function() {
var c = this.selectionStart,
r = /[^a-z ]/gi,
v = $(this).val();
if(r.test(v)) {
$(this).val(v.replace(r, ''));
c--;
}
this.setSelectionRange(c, c);
});
Because it will allow you to enter space as well and it will only target the input fields with type text and wont bother the other input fields like email, password etc as normally we need special characters in email and password field

How to make letter replace after it has been added?

I have a working script to replace non alphanumerical letters from the text input. If you add special chars to text input, it doesnt let you to add to there. However, I want this script delete the special char after you add the letter, means that you can see the letter there but just after that it hs been removed (like when you try to upvote your own question on stackoverflow)
$("#nick").on("keypress", function(event) {
var englishAlphabetAndWhiteSpace = /[A-Za-z]/g;
var key = String.fromCharCode(event.which);
if (event.keyCode == 8 || event.keyCode == 37 || event.keyCode == 39 || englishAlphabetAndWhiteSpace.test(key)) {
return true;
}
return false;
});
What is the correct way to do it ?
You want to show the letter and then remove it, use 'keyup' event
$('#test').on('keyup keypress', function(e) {
var reg = /[A-Za-z]/;
var value = $(this).val();
if (value && !reg.test(value[value.length - 1])) {
$(this).val(value.slice(0, value.length - 1));
}
})
Code on jsfiddler
You can use regex that'll replace all the non-alphabetic characters in the input value.
Use HTML5 pattern attribute on input to give regex
Use keyup and input event handlers to capture events
Use negated class regex to remove all non-alphabet symbols
Use setTimeout to clear the special characters after a delay
var timeout;
$("#nick").on("keypress input", function(e) {
var keyCode = e.keyCode || e.which; // Browser-independant
// If left or right arrow, then don't do anything
if (keyCode === 8 || keyCode === 37 || keyCode === 39) {
return true;
}
var $this = $(this); // Cache this
clearTimeout(timeout); // Clear previous timeouts
timeout = setTimeout(function() {
$this.val($this.val().replace(/[^A-Za-z]/g, ''));
}, 500);
});
input:valid {
color: green;
}
input:invalid {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="nick" pattern="[A-Za-z]+" />
Regex Explanation:
The regex on pattern, [A-Za-z]+ only matches one or more of the alphabet characters both uppercase and lowercase.
If I read it correctly, you are talking about inserting a delay before the invalid character vanishes?
It's a bit trickier as there is the clause of how long you want to see it before it vanishes & also what if you are faster than typing the next letter before it does.
After taking care of these, it should look something like this :
var removelast = false, remover;
var nick = $("#nick").on("keypress", function(event) {
function remove() {
nick.val(nick.val().slice(0,-1));
removelast = false;
}
clearTimeout(remover);
if(removelast) remove();
var englishAlphabetAndWhiteSpace = /[A-Za-z]/g;
var key = String.fromCharCode(event.which);
var allowed = event.keyCode == 8 || event.keyCode == 37 || event.keyCode == 39 || englishAlphabetAndWhiteSpace.test(key);
if (!allowed) {
removelast = true;
remover = setTimeout(remove, 100);
}
return true;
});
<input type="text" id="nick" >
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

How do I know, via key event code, if the character just entered in a <textarea> is lower or upper case?

I'm trying to capture the character just entered into a <textarea>, but I can only get which key is pressed via key event like keydown or keyup, not knowing if it's lower case or upper case.
For example, when I input A or a, the event key codes for keydown are all 65.
I thought of using val() to get the string in the <textare> and get the last character of it, but that is too slow and memory consuming, since I want to record every keyboard event while the user is typing.
So is there a way I can simply get the last entered character?
Try this:
var p = $('#log')[0];
$("#textarea").on("keypress", function(e) {
p.textContent = '';
var k = e.keyCode || e.which;
var character = String.fromCharCode(k);
if (!isNaN(character * 1)) {
p.textContent += 'character is numeric';
} else {
if (character == character.toUpperCase()) {
p.textContent += 'UPPER case true';
}
if (character == character.toLowerCase()) {
p.textContent += 'lower case true';
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="textarea"></textarea>
<p id="log"></p>
I see what you mean about the shiftKey
var myObj = $('#myTextarea');
function isLetter(char){
if ((char.toLowerCase() !== char) || (char.toUpperCase() !== char)) {
return true;
}
return;
}
myObj.keypress(function( event ){
var text = myObj.val();
var char = text.charAt(text.length-1);
if (!event.shiftKey && isLetter(char)) {
if (char == char.toUpperCase()) {
console.log('Upper');
}
if (char == char.toLowerCase()) {
console.log('Lower');
}
}
});
try:
<textarea id="area1"></textarea>
window.onload = function () {
document.getElementById("area1").onkeypress = function(event){
var code = event.which;
if ((code >= 65) && (code <= 90)) {
alert('Upper');
}
else if ((code >= 97) && (code <= 122)) {
alert('Lower');
}
}
}

Capitalize first letter of words in sentence, except on manual replacement

I have an input field that the user will fill in and I want to automatically capitalize the first letter of each word as they're typing. However, if they manually delete a capital letter and replace it with a lower case, I want that to remain (basically capitalizing the letters is what we recommend, but not required). I'm having trouble implementing something that will leave the letters they manually typed alone and not change them.
Here is the code I have along with a Jsfiddle link to it.
<input class="capitalize" />
and JS:
lastClick = 0;
$(document).ready(function() {
$(".capitalize").keyup(function() {
var key = event.keyCode || event.charCode;
if (!(lastClick == 8 || lastClick == 46)) {
//checks if last click was delete or backspace
str = $(this).val();
//Replace first letter of each word with upper-case version.
$(this).val(str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}));
}
lastClick = key;
});
});
I haven't allowed for preserving the user's manual corrections, but as it is you can see in the jsfiddle that the input jumps around and doesn't work correctly. Can anyone help me or recommend a best way to do this? Thank you.
$(document).ready(function() {
var last;
$(".capitalize").on('keyup', function(event) {
var key = event.keyCode || event.which,
pos = this.value.length,
value = this.value;
if (pos == 1 || last == 32 && (last !== 8 || last !== 46)) {
this.value = value.substring(0, pos - 1) +
value.substring(pos - 1).toUpperCase();
}
last = key;
});
});
http://jsfiddle.net/userdude/tsUnH/1
$(document).ready(function() {
$(".capitalize")
.keyup(function(event) {
var key = event.keyCode || event.charCode;
// store the key which was just pressed
$(this).data('last-key', key);
})
.keypress(function(event) {
var key = event.keyCode || event.charCode;
var lastKey = $(this).data('last-key') ? $(this).data('last-key') : 0; // we store the previous action
var $this = $(this); // local reference to the text input
var str = $this.val(); // local copy of what our value is
var pos = str.length;
if(null !== String.fromCharCode(event.which).match(/[a-z]/g)) {
if ((pos == 0 || str.substr(pos - 1) == " ") && (!(lastKey == 8 || lastKey == 46))) {
event.preventDefault();
$this.val($this.val() + String.fromCharCode(event.which).toUpperCase());
}
}
// store the key which was just pressed
$(this).data('last-key', key);
});
});
I have updated your fiddle http://jsfiddle.net/nB4cj/4/ which will show this working.

Block characters from input text field, mirror input into span or div

I have some html
<input type="text" name="name" value="" id="name">
<div id="preview"></div>
The rules for entry into the field:
Letters A-Z a-z 0-9 space and dash, no other characters allowed
Entry of forbidden characters should do nothing
The rules for the div:
Show each characters as it is entered into the input field
Do not show characters that are forbidden
When a space is encountered, show it as a dash
I have had various potions working, not working, or misbehaving. This version seems to work in all cases I can test other than backspace/delete is non functional. Only tested in Safari so far.
There are other "gotcha" areas, like entering in text in-between already entered text, select all, using the arrow keys, all these play a role in this problem.
$(document).ready(function(){
$('#name').keypress(function(e) {
// get key pressed
var c = String.fromCharCode(e.which);
// var d = e.keyCode? e.keyCode : e.charCode; // this seems to catch arrow and delete better than jQuery's way (e.which)
// match against allowed set and fail if no match
var allowed = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890- ';
if (e.which != 8 && allowed.indexOf(c) < 0) return false; // d !== 37 && d != 39 && d != 46 &&
// just replace spaces in the preview
window.setTimeout(function() {$('#preview').text($('#name').val().replace(/ /g, '-'));}, 1);
});
});
If there is a way to put a monetary bounty on this post, let me know. Yes, that is where I am at with this one :)
I tested the following in Firefox, Safari and Internet Explorer. Unless I didn't fully understand your objective, I believe this should solve your problem.
I ended up writing a jQuery plugin to handle the input caret position. The plugin source is included below, or available on the jQuery plugin site (http://plugins.jquery.com/project/caret-range).
$(document).ready(function () {
var InvalidPattern = /[^a-z0-9\- ]+/gi;
var SpacePattern = / /g;
var name = $("#name");
var preview = $("#preview");
var callback = function (e) {
setTimeout(function () {
// Get range and length to restore caret position
var range = name.caret();
var len = name.val().length;
// Blur element to minimize visibility of caret jumping
name.get(0).blur();
// Remove invalid characters, and update preview
name.val(name.val().replace(InvalidPattern, ""));
preview.text(name.val().replace(SpacePattern, "-"));
// Restore caret position
var diff = len - name.val().length;
name.caret(range.start - diff, range.end - diff);
}, 0);
};
name.keypress(callback);
name.keydown(callback); // Needed by IE to update preview for Delete and Backspace
});
/*
* jQuery Caret Range plugin
* Copyright (c) 2009 Matt Zabriskie
* Released under the MIT and GPL licenses.
*/
(function($) {
$.extend($.fn, {
caret: function (start, end) {
var elem = this[0];
if (elem) {
// get caret range
if (typeof start == "undefined") {
if (elem.selectionStart) {
start = elem.selectionStart;
end = elem.selectionEnd;
}
else if (document.selection) {
var val = this.val();
var range = document.selection.createRange().duplicate();
range.moveEnd("character", val.length)
start = (range.text == "" ? val.length : val.lastIndexOf(range.text));
range = document.selection.createRange().duplicate();
range.moveStart("character", -val.length);
end = range.text.length;
}
}
// set caret range
else {
var val = this.val();
if (typeof start != "number") start = -1;
if (typeof end != "number") end = -1;
if (start < 0) start = 0;
if (end > val.length) end = val.length;
if (end < start) end = start;
if (start > end) start = end;
elem.focus();
if (elem.selectionStart) {
elem.selectionStart = start;
elem.selectionEnd = end;
}
else if (document.selection) {
var range = elem.createTextRange();
range.collapse(true);
range.moveStart("character", start);
range.moveEnd("character", end - start);
range.select();
}
}
return {start:start, end:end};
}
}
});
})(jQuery);
After tinkering around I have refactored my previous solution. This version should behave identical to Twitter. I am keeping my old answer alive simply b/c it is technically valid, and this allows comparing the different approaches.
$(document).ready(function () {
var SpacePattern = / /g;
var name = $("#name");
var preview = $("#preview");
var updatePreview = function () {
preview.text(name.val().replace(SpacePattern, "-"));
};
name.keypress(function (e) {
if (e.which > 0 && // check that key code exists
e.which != 8 && // allow backspace
e.which != 32 && e.which != 45 && // allow space and dash
!(e.which >= 48 && e.which <= 57) && // allow 0-9
!(e.which >= 65 && e.which <= 90) && // allow A-Z
!(e.which >= 97 && e.which <= 122) // allow a-z
) {
e.preventDefault();
}
else {
setTimeout(updatePreview, 0);
}
});
name.keyup(updatePreview); // Needed by IE for Delete and Backspace keys
});
Try this:
1. When key down, copy the previous TextField value.
2. When key up, use RegEx to validate the text (something like /^[a-zA-Z0-9 -]*$/), if unmatch, replace the value with the old one.
Here is the code:
var ValidPattern = /^[a-zA-Z0-9\- ]*$/;
$(document).ready(function(){
$('#name').keydown(function(e) {
var aValue = $('#name').val();
$('#name').attr("oldValue", aValue);
return true;
});
$('#name').keyup(function(e) {
var aValue = $('#name').val();
var aIsMatch = aValue.search(ValidPattern) != -1;
if(aIsMatch) {
$('#preview').text(aValue);
} else {
var aOldValue = $('#name').attr("oldValue");
$('#name') .val (aOldValue);
$('#preview').text(aOldValue);
}
});
});
Try it.
I think the best method will be to keep a button and after entering the text inside the text box and clicking on the button show it in the div. It will be much more easier and user friendly.
It would be better not to try hindering the default actions of a user with the keyboard.

Categories