By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,528 Members | 1,330 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,528 IT Pros & Developers. It's quick & easy.

javascript event handler assignment funky functioning.

Plater
Expert 5K+
P: 7,872
Well, I'm stuck asking you all, because I cannot find a piece of code that works in multiple browsers.

I have the following code that works in google chrome and ie:
Expand|Select|Wrap|Line Numbers
  1. //Add a keypress watcher to disallow spaces, slashes, alphabetic characters, etc
  2. document.getElementById("tbSiteCodeOrSerialNumber").onkeypress=function(){return OnlyNumbers(event);};  
  3.  
FF complains that the function is not defined. Looking up I see that FF likes
the function definition to take a parameter in for this setup, aka: function(e)
Expand|Select|Wrap|Line Numbers
  1. document.getElementById("tbSiteCodeOrSerialNumber").onkeypress=function(e){return OnlyNumbers(event);};
  2.  
But then it complains that "event" is not valid. Ok I think, how about using function (event)
Expand|Select|Wrap|Line Numbers
  1. document.getElementById("tbSiteCodeOrSerialNumber").onkeypress=function(event){return OnlyNumbers(event);};  
  2.  
Hurray it works in FF and google chrome, but then IE eats it.
EDIT: No, it blocks EVERY keypress (backspace, ctrl+v, etc) in FF, but googlechrome is fine.
IE complains inside the OnlyNumbers function that a null is being passed in as the parameter.

Does anyone have a solid piece of code for attaching the onkeypress handler at runtime like that?
Sep 9 '08 #1
Share this Question
Share on Google+
12 Replies


acoder
Expert Mod 15k+
P: 16,027
Expand|Select|Wrap|Line Numbers
  1. document.getElementById("tbSiteCodeOrSerialNumber").onkeypress=OnlyNumbers;
is all you need. The event will be passed for you in Firefox/Opera, etc.
Sep 9 '08 #2

Plater
Expert 5K+
P: 7,872
.onkeypress only allows parameterless functions, but I need to pass in the event object as well, which was why I was doing the function wrapping.
Sep 9 '08 #3

acoder
Expert Mod 15k+
P: 16,027
The event will be passed without specifying it:
Expand|Select|Wrap|Line Numbers
  1. function OnlyNumbers(e) {
  2.     e = e || window.event;
  3. ...
Sep 9 '08 #4

Plater
Expert 5K+
P: 7,872
Ok I see what you did there. But it still doesn't work with IE. It doesn't get the value passed in, still says its null.

I am thinking of taking it a different way anyway, since it seems it blocks all other keyboard keys as well in FF (no backspace, no delete, not ctrl+v, etc)
But I am not sure what way to go.
Sep 9 '08 #5

acoder
Expert Mod 15k+
P: 16,027
It should work in IE because window.event is global.

You could try using parseInt/isNaN, but blocking keys onkeypress is more useful when specifying what to block, not what to allow.
Sep 9 '08 #6

Plater
Expert 5K+
P: 7,872
window.event is global, but is never defined (according to alert() boxes)

I am now using this:
Expand|Select|Wrap|Line Numbers
  1. //Add a keypress watcher to disallow spaces, slashes, alphabetic characters, etc
  2. if(window.event) // IE
  3. {
  4.    document.getElementById("tbSiteCodeOrSerialNumber").onkeypress=function(){return OnlyNumbers(event);};
  5. }
  6. else // ???Netscape/Firefox/Opera
  7. {
  8.    document.getElementById("tbSiteCodeOrSerialNumber").onkeypress=OnlyNumbers;
  9. }
  10.  
And with some work arounds for FF, I have it allowing arrow keys, delete key, and backspace, as well as numbers.
Expand|Select|Wrap|Line Numbers
  1. function OnlyNumbers(e)
  2. {
  3.     var keynum;
  4.     var keychar;
  5.     var numcheck1;
  6.  
  7.     if(window.event) // IE
  8.     {
  9.         keynum = e.keyCode;
  10.     }
  11.     else if(e.which) // Netscape/Firefox/Opera
  12.     {
  13.         keynum = e.which;   
  14.     }
  15.     if (keynum==null)
  16.     {//FF has the arrow keys and the delete key show up as null/undefined
  17.         return true;
  18.     }
  19.     keychar = String.fromCharCode(keynum);
  20.     numcheck1 = /(\d|\x08)/;
  21.     var bv1= numcheck1.test(keychar);
  22.     return (bv1 );
  23. }
  24.  
If there is a better way to do this, I am all ears. googlechrome and IE both had no problems allowing arrow keys/delete/backspace/home/end/numbers to be typed with only the /\d/ check.
Sep 9 '08 #7

acoder
Expert Mod 15k+
P: 16,027
window.event is never defined because you're not using it. You're using "e". To solve it, add this line to the beginning of the function:
Expand|Select|Wrap|Line Numbers
  1. e = e || window.event;
As for the second problem, that's a bit more complex. Either allow only allowable characters, or block all prohibited characters, or get the target of the event and check if the whole value is a number or not.
Sep 9 '08 #8

Plater
Expert 5K+
P: 7,872
Well the problem I had was that FF treats special keys as the same keycode. Such as ctrl+c is the same keycode(or e.which) as "c" and "C".
So if I disallow alpha characters, which i need to do, then it also blocks those. Unless I check for special keys also being pressed.

Here is what I currently am going with.
Expand|Select|Wrap|Line Numbers
  1. function OnlyNumbers(e)
  2. {
  3.     var keynum;
  4.     var keychar;
  5.     var numcheck1;
  6.  
  7.     if(window.event) // IE
  8.     {
  9.         keynum = e.keyCode;
  10.     }
  11.     else if(e.which) // Netscape/Firefox/Opera
  12.     {
  13.         keynum = e.which;   
  14.     }
  15.     if ((keynum==null) || (e.altKey) || (e.ctrlKey))
  16.     {
  17.         return true;
  18.     }
  19.  
  20.     keychar = String.fromCharCode(keynum);
  21.     numcheck1 = /(\d|\x08)/;
  22.     var bv1= numcheck1.test(keychar);
  23.     return bv1;
  24. }
  25.  
That seems to be doing an ok-enough job. It doesn't stop people from pasting in text that is not numbers, but I can clean that up at a later point.
All I wanted was that only numbers could be displayed in the textbox. It got complicated really quick haha.
Sep 9 '08 #9

100+
P: 428
firefox and IE return control character codes from keyup and keydown.

IE returns keyCodes from all key events, firefox returns keyCode for keyup and down, and charCode from keypress events.

The easiest way to validate keyboard input while its being typed is to look at the element's value onkeypress and replace anything that doesn't fit:
(Might as well use the same method to check pasted input onchange):

element.onkeypress=element.onchange=function(){
this.value=this.value.replace(/\D+/,'')
}
Sep 9 '08 #10

acoder
Expert Mod 15k+
P: 16,027
Of course, \D matches non-integers. I knew I was missing something simple. Thanks, mrhoo.
Sep 10 '08 #11

Plater
Expert 5K+
P: 7,872
element.onkeypress=element.onchange=function(){
this.value=this.value.replace(/\D+/,'')
}
The idea is nice, and it *does* technically work I suppose, except that until you press a 2nd key, or leave, there is still any single non valid character that was typed in the box.
Sep 10 '08 #12

100+
P: 428
this version will prevent the input from showing the nondigits at all-
except in opera, which needs the onkeyup.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>key events</title>
<!--
This code is for testing purposes only
-->
<style type="text/css">
body{font-size:125%;margin:1ex 1em}
form *{font-size:1em; font-weight:bold}
</style>

<script type="text/javascript">
Expand|Select|Wrap|Line Numbers
  1. onload=function(){
  2.     var who=document.getElementById('digitstext');
  3.     who.onkeydown=function(e){
  4.         e=window.event || e;
  5.         var c=e.keyCode || 0;
  6.         if(c<48 || c>57)return false;
  7.         return c;
  8.     }
  9.     who.onchange= function(){
  10.         this.value=this.value.replace(/\D+/,'');
  11.     }
  12.     if(window.opera){
  13.         who.onkeyup=who.onchange;
  14.     }    
  15.     who.focus();
  16. }
</script>
</head>

<body style="">
<div >

<form action='' onsubmit="return false" style="font-size:150%;width:100%">
<fieldset>

<legend>Key Events</legend>
<p>
<label>Only digits accepted<input id="digitstext" type="text" size="10" maxLength="10" value=""></label>
</p>
</fieldset>
</form>

</div>
</body>
</html>

I would just use the replace value onkeyup and onchange, and let the bad data show for an instant-

Expand|Select|Wrap|Line Numbers
  1. onload=function(){
  2.     var who=document.getElementById('digitstext');
  3.     who.onkeyup= who.onchange= function(){
  4.         this.value=this.value.replace(/\D+/,'');
  5.     }
  6.     who.focus();
  7. }
  8.  
Sep 10 '08 #13

Post your reply

Sign in to post your reply or Sign up for a free account.