Monday, April 11, 2005

Client Side JavaScript

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


Most JSF components have a number of onXXX properties,
such as onClick for buttons. You can attach any JavaScript
you want here, and this JavaScript is run in the user's browser.



You can use this to improve the user interaction. For example,
let's say you have a text field which can only contain numbers.
Clearly, you should put a validator on the number field - never
trust client-side validation alone. However, rather than users
having to find out after the submit that they made a mistake they
need to correct, why not prevent them from typing anything other
than a number in the first place?



We can use JavaScript to prevent anything other than digits from
being entered into a textfield. Here's how: We need to write
a JavaScript function which is run on every keystroke which decides
whether the given key is valid, and if not, return false - this
will prevent the key from getting added into the textfield.



Did I say write JavaScript? Ooops, I meant "google for reusable
JavaScript". The internet is full of little JavaScript snippets
for doing things like this. Here's a JavaScript function I found;
we can add it to our document by embedding it in a
<script> tag, and put the actual JavaScript
code in a CDATA section to prevent the XML parser from interpreting
it as anything other than raw data:


<script type="text/javascript">
<![CDATA[
<!--
// copyright 1999 Idocs, Inc. http://www.idocs.com
// Distribute this script freely but keep this notice in place
function numbersonly(myfield, e, dec)
{
var key;
var keychar;

if (window.event)
key = window.event.keyCode;
else if (e)
key = e.which;
else
return true;
keychar = String.fromCharCode(key);

// control keys
if ((key==null) || (key==0) || (key==8) ||
(key==9) || (key==13) || (key==27) )
return true;

// numbers
else if ((("0123456789").indexOf(keychar) > -1))
return true;

// decimal point jump
else if (dec && (keychar == "."))
{
myfield.form.elements[dec].focus();
return false;
}
else
return false;
}
-->
]]>
</script>



Alternatively, you can place this code (without the surrounding
<script> tag) in a separate javascript file,
for example, digitsOnly.js under resources,
and in that case instead of including the large section above,
all you need to do is add the following line in your JSP:


<script src="resources/script.js" type="text/javascript"></script>



Warning: I have seen some reports in the
forum
that the above XML can get changed into


<script src="resources/script.js" type="text/javascript"/>

and if this happens, Internet Explorer fails. I fixed this bug
(where script and some other tags were
getting minimized when they shouldn't) in Creator late last
summer, so this shouldn't happen with the recent updates (and
I can't reproduce it) but be on the lookout for it and let me
know if you see any problems in this area.



Now the final step - select your text field, and bind the
onkeypress property to this javascript:


return numbersonly(this, event)

In other words, your JSP for the text field should look something
like this:

<h:inputText
binding="#{Page1.textField1}"
id="textField1"
onkeypress="return numbersonly(this, event)"
validator="#{Page1.textField1_validate}"/>

Notice how there is also a validator attached to this component.
Don't forget to do server-side validation - that's what counts!



P.S. You should still read the JavaScript code and see if it does
what you want. For example, the above JavaScript is not suitable
if you want to allow negative numbers (e.g. a minus sign must be allowed).
Also, the javascript has special support for jumping to another text field
when the user enters a dot, which we're not taking advantage of here - there's
a third parameter to the javascript function.


4 comments:

  1. Note that if you only wish to test your JavaScript (static, not dynamic), you don't have to deploy - simply use "Preview in Browser...".

    ReplyDelete
  2. Tor,
    Thanks for your site, its been a great help to me.
    One comment on Javascript - I've followed your instructions on how to add JavaScript to my page, however I still seem to have the problem of the <script></script> element being minimised to </script>. So it fall in IE 6. It appears I can work around it by using a dummy varable:
    <script>var x;</script>
    I'm using SSC update 7. Wonder if you can shine any further light on this.
    Thanks,
    Adrian

    ReplyDelete
  3. Hey. I was using this version for same number control:
    [code]
    var numbers = new Array( '8','9','13','46','48','49','50','51','52','53','54','55','56','57','63234','63235' );
    function checkonlynumber(e,input) {
    var key;
    if (document.all)
    key = window.event.keyCode;
    else
    key=e.keyCode;
    var hit = false;
    for( var i=0; i<numbers.length;i++ )
    if( key == numbers[i] )
    hit = true;
    return hit;
    }
    [/code]

    ReplyDelete
  4. Tor, this thing described below still happens. I'm using Creator Update 8 and IE 6.0.
    ==============================================
    Warning: I have seen some reports in the forum that the above XML can get changed into
    <script src="resources/script.js" type="text/javascript"/>
    and if this happens, Internet Explorer fails
    =================================================

    ReplyDelete