Limiting characters in a text box

R

Rogue Chameleon

Hi all

I have a input filed of type "textbox" into which I am expecting to get
currency values (ie. 199.99). Is there a way that I can restrict the
user to only entering 2 values after the decimal point?

I can restrict the maxlength to 5, but that wouldn't stop the user from
type in 1.987.

tia
rogue chameleon
 
M

Martin Honnen

Rogue Chameleon wrote:

I have a input filed of type "textbox" into which I am expecting to get
currency values (ie. 199.99). Is there a way that I can restrict the
user to only entering 2 values after the decimal point?

I can restrict the maxlength to 5, but that wouldn't stop the user from
type in 1.987.

Your best bet is to use the onchange handler e.g.
<input type="text"
onchange="validateCurrency(this);"
to validate the value entered in the text control, that works reliably
in current browsers. It might even be better to validate all controls in
the onsubmit handler of the form. You have to write the function
validateCurrency of course.
Restricting the user while he types is more difficult, there are key
events fired and you can even cancel them but in many browsers there is
no API to keep track of the caret in the text control while the key
events fire. And pasting into the text control is also not covered by
key events.
 
M

McKirahan

Rogue Chameleon said:
Hi all

I have a input filed of type "textbox" into which I am expecting to get
currency values (ie. 199.99). Is there a way that I can restrict the
user to only entering 2 values after the decimal point?

I can restrict the maxlength to 5, but that wouldn't stop the user from
type in 1.987.

tia
rogue chameleon

JavaScript can be used though some visitor's browsers may have it disabled.

Try this though there may be a better solution that uses a regular
expression.

<html>
<head>
<title>decimals.htm</title>
<script type="text/javascript">
function decimals(that) {
var s = that.value;
var i = s.indexOf(".");
if (i >= 0 && s.substr(i+1).length > 2) {
alert("Only 2 digits to the right of the decimal are allowed!");
that.value = s.substring(0,s.length-1);
}
}
</script>
</head>
<body>
<form>
<input type="text" size="5" maxlength="5" onkeyup="decimals(this)">
</form>
</body>
</html>
 
M

McKirahan

[snip]

This version is better as it handles the issue of cut-and-pasting a value
"1.234".

<html>
<head>
<title>decimals.htm</title>
<script type="text/javascript">
function decimals(that) {
var s = that.value;
var i = s.indexOf(".");
if (i < 0 || s.substr(i+1).length < 3) return;
alert("Only 2 digits to the right of the decimal are allowed!");
that.value = s.substring(0,i+3);
}
</script>
</head>
<body>
<form>
<input type="text" size="5" maxlength="5" onkeyup="decimals(this)">
</form>
</body>
</html>
 
R

Rogue Chameleon

Thanks everyone.... I'll try all posted solutions, and see which one
reacts the way I need.

rc
 
R

RobB

Rogue Chameleon said:
Hi all

I have a input filed of type "textbox" into which I am expecting to get
currency values (ie. 199.99). Is there a way that I can restrict the
user to only entering 2 values after the decimal point?

I can restrict the maxlength to 5, but that wouldn't stop the user from
type in 1.987.

tia
rogue chameleon

I concur with M. Honnen's caveats in re key handlers - although
onchange can be circumvented by pasting in a copy of the same string.
Similarly, onkeyup alone will fire for mouse/keystroke pasting, but
not for menu pastes. Just for the heck of it...

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>untitled</title>
<script type="text/javascript">
//<![CDATA[

chkfld.running = false; //keep handlers separate
function chkfld(oText)
{
if (chkfld.running) //one at a time
return;
chkfld.running = true;
var msg = '', v = oText.value;
if (!/^\d*\.?\d*$/.test(v))
msg += 'Only numbers, please !';
else if (/\.\d{3,}$/.test(v))
msg += 'Only two decimal places, please !';
if (msg != '')
{
alert(msg);
oText.value = v.replace(/[^\d.]/g,
'').replace(/(\d*)(\.)(\d*)\.(\d*)/g,
'$1$2$3$4').replace(/^(\d*\.\d{2}).+$/,'$1');
return (chkfld.running = false);
}
chkfld.running = false;
}

//]]>
</script>
</head>
<body>
<form>
<input type="text" size="5" maxlength="5" onkeyup="return
chkfld(this)" onblur="return chkfld(this)" />
</form>
</body>
</html>

Tested iewin, NS7.2, Op7 - no mac handy at the moment. I'd shop this
around before using, if at all. Price is right, tho....
 
J

J. J. Cale

You can use a regex to check the format.
The following should allow any number of digits before and including the
decimal point, and only two after it.
/^\d+.\d{2}$/ Checked briefly in IE6.
You can limit the user input to only digits and/or periods but that is
tantamount to terrorizing the user. Unless you have a serious reason, it is
totally unnecessary and should be avoided.

Take Martin Honnens advice and do the validation on form submission.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HEAD><TITLE>validate currency</TITLE>
<script type=text/javascript>
function validateCurrency(sText) {
if(!/^\d+.\d{2}$/.test(sText)) {
alert('not formatted correctly');
document.forms[0].elements[0].focus();
return false;
}
return true;
}
</script>
</HEAD>
<BODY>
<form onsubmit="return validateCurrency(this.elements[0].value)">
<input type=text)></form>
</BODY></HTML>
Finally read Martins post 2 or 3 more times. Though he tends to be brief ALL
of his points are significant.
HTH
Jimbo
 
R

RobB

Rogue Chameleon said:
Thanks everyone.... I'll try all posted solutions, and see which one
reacts the way I need.

rc

OK, somewhat better imo. Also minus a linefeed error inflicted by this board. :(

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>untitled</title>
<script type="text/javascript">
//<![CDATA[

$format.running = false; //keep handlers separate
function $format(fld, leaving)
{
if ($format.running) //one at a time
return;
$format.running = true;
var v = fld.value;
if (!/^\d*\.?\d*$/.test(v) || /\.\d{3,}$/.test(v))
{
fld.value = v.replace(/[^\d.]/g,'').
replace(/\.(.*)\./g,'$1.').
replace(/^(\d*\.\d{2}).+$/,'$1');
return ($format.running = false);
}
if (leaving && /\.\d$/.test(fld.value))
fld.value += '0';
$format.running = false;
}

//]]>
</script>
</head>
<body style="font-family:arial;margin:100px;"
onload="document.forms[0].foo.focus()">
<form style="font-size:100%;" onreset="foo.focus()">
$ <input type="text" name="foo" value="" size="8" maxlength="8"
onkeyup="return $format(this,false)"
onblur="return $format(this,true)" />
<input type="reset" value="clear" />
</form>
</body>
</html>
 
R

Rob B

OK...final answer.

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>untitled</title>
<script type="text/javascript">
//<![CDATA[

$format.RE1 = /^\d*\.?\d*$/;
$format.RE2 = /\.\d{3,}$/;
$format.RE3 = /\.(?=[^.]*\.)/g;
$format.RE4 = /[^\d.]/g;
$format.RE5 = /\.(?=[^.]*\.)/g;
$format.RE6 = /^(\d*\.\d{2}).+$/;
$format.RE7 = /(\.\d{0,1})$/;

function $format(fld, leaving)
{
function sReverse(str)
{
for (var s = '', i = str.length - 1; i != -1; --i)
s += str.charAt(i);
return s;
}

var v = fld.value;
if (!$format.RE1.test(v) || $format.RE2.test(v))
{
var ltdot = (fld.dotpos == v.indexOf('.') ?
v.lastIndexOf('.') < fld.dotpos :
v.indexOf('.') < fld.dotpos);
if (ltdot)
v = sReverse(v);
v = v.replace($format.RE3,'');
if (ltdot)
v = sReverse(v);
v =
v.replace($format.RE4,'').replace($format.RE5,'').replace($format.RE6,'$
1');
fld.value = v;
}
fld.dotpos = v.indexOf('.');
if (leaving)
fld.value = v.replace($format.RE7, '$10').replace($format.RE7, '$10');
}

//]]>
</script>
</head>
<body style="font:110% arial;margin:100px;"
onload="f=document.forms[0];f.reset();f.foo.focus()">
<form onreset="foo.focus()">
$ <input type="text" name="foo" value="" size="10" maxlength="8"
style="text-align:center;border:1px black solid;"
onkeyup="return $format(this,false)"
onblur="return $format(this,true)" />
<input type="reset" value="clear" />
</form>
</body>
</html>

The O.P. seems to be long gone, so, maybe someone else can use
this...good exercise, in any event.
 
R

Rogue Chameleon

LOL, RobB!
Thanks for looking into this so much... your dedication is admirable :)
 
R

Rob B

The Chameleon Lives! :)
Your welcome, Rogue.

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>untitled</title>
<script type="text/javascript">
//<![CDATA[

cF.RE1 = /^\d*\.?\d*$/;
cF.RE2 = /\.\d{3,}$/;
cF.RE3 = /\.(?=[^.]*\.)/g;
cF.RE4 = /[^\d.]/g;
cF.RE5 = /\.(?=[^.]*\.)/g;
cF.RE6 = /^(\d*\.\d{2}).+$/;
cF.RE7 = /(\.\d{0,1})$/;
cF.RE8 = /^([^.]+)$/;

String.prototype.reverse = function()
{
return this.split('').reverse().join('');
}

function cF(fld, onblur)
{
var v = fld.value;
if (!cF.RE1.test(v) || cF.RE2.test(v))
{
var ltdot = (fld.dotpos == v.indexOf('.') ?
v.lastIndexOf('.') < fld.dotpos :
v.indexOf('.') < fld.dotpos);
if (ltdot)
v = v.reverse();
v = v.replace(cF.RE3,'');
if (ltdot)
v = v.reverse();
v = v.replace(cF.RE4,'').
replace(cF.RE5,'').
replace(cF.RE6,'$1');
fld.value = v;
}
fld.dotpos = v.indexOf('.');
if (onblur)
fld.value = v.replace(cF.RE7, '$10').
replace(cF.RE7, '$10').
replace(cF.RE8, '$1.00');
}

//]]>
</script>
</head>
<body style="font:100% arial;margin:300px;"
onload="f=document.forms[0];f.reset();f.foo.focus()">
<form onreset="foo.focus()">
$ <input type="text" name="foo" value="" size="10" maxlength="8"
style="font:75% arial;text-align:center;border:1px black solid;"
onkeyup="return cF(this,false)"
onblur="return cF(this,true)" />
<input type="reset" value="clear" style="font:75% arial;border:1px black
solid;" />
</form>
</body>
</html>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top