views:

405

answers:

7

Hey guys I'm trying to make a HTML text box that: 1) only accepts numbers 2) after 3 digits, adds a '.' 3) after 6 digits, adds another '.'

So for example, by only typing numbers, you'll get 555.323.7637

4) If you're after a '.', like '555.', then a backspace would change it to '55'.

I've been googling around but don't know the exact term I'm looking for.

Thanks!

A: 

What you're wanting to do would probably involve Javascript acting on the onKey___ events of the text field in question to validate and (if necessarily) modify the value of the field.

In order to modify the behavior of the backspace key, you'd probably also need to do things with the onKeyDown event to take into account the contents of the field.

An alternative option alluded to in another answer is to simply use 3 separate text boxes - you can use Javascript to make the cursor automatically "jump" to the next box after each one is filled, which is a fairly standard solution for things like phone number input.

Amber
`onchange` would be insufficient as it is only fired after the element loses focus. An onkey* listener is more appropriate in this case.
Justin Johnson
That's a valid point.
Amber
perhaps an edit of your answer is in order?
nickf
+1  A: 

This seems like an annoying user experience, but if you insist then you can use the onkeyup/onkeydown/onkeypress listeners (onkeyup is likely sufficient).

If you're users 1) understand the format, or 2) the format is unimportant for actual use, then 1) let them format it, or 2) format it after receiving it.

Justin Johnson
I agree about annoying to the user experience. Consider multiple text boxes and send the focus to the next text box after three characters
David Archer
A: 

HTML:

<textarea id="messageBox"></textarea>

JavaScript (JQuery):

$(document).ready(function() {
    var num_of_digits = 0;
    var textarea = $("#messageBox");
    textarea.keydown(
        function(e){
            var key = e.charCode || e.keyCode || 0;
            if (
                (key >= 48 && key <= 57)
                || (key >= 96 && key <= 105) 
               ) { // Number pressed (top row and numpad)
                if (num_of_digits++ % 3 == 0 && num_of_digits != 1) {
                    // Insert a period into the back
                    textarea.val(textarea.val() + '.');
                }
            } else {
                // non-number pressed
                if (key == 8) { // backspace
                    var last_char = textarea.val().slice(-1);
                    if (last_char == '.') {
                        textarea.val(textarea.val().slice(0, -1));
                    }
                    num_of_digits--;
                } else if (key == 46) { // delete key
                    // delete logic in here
                } else if (key >= 37 && key <= 40) { // arrow keys
                    // pass
                } else {
                    e.preventDefault();
                }
            }
        }
    );
});

This was quickly written and not tested so YMMV but that is how you could do it.

EDIT: It appears to do what you want. shrug It does not allow for any other keys but numbers (no backspace, spaces, enters, home/end, etc). If you need it to do that, please add that to your question so I can modify my answer.

EDIT 2: Backspace now works as described in the OP's question. Delete is a little trickier and is left as an exercise to the OP.

Nick Presta
Please, for the sake of user-sanity, allow *at least* backspace and delete in addition to numeric keys.
David Thomas
A: 

You can use the same method that Stack Overflow uses in this very 'Your Answer' text box.

You can have the user enter their text in the text box (validate for numeric characters only using REGEX) and then display the formatted text below with the onkeypress JavaScript event in another text box with a read only attribute so the user cannot change the text.

Thanks

mlevit
A: 

Playing around with how input fields work is dangerous territory. By using a series of event handlers to listen for key presses you could probably make it work 95% of the time. The other five percent of the time your users will be cursing your name. Consider those who will copy and paste into the text box (probably quite a few since it's 9 digits?). I'm sure there's plenty of other cases where the normal events wouldn't fire as expected.

Here's another method which might work: when the input is blurred (that is, loses focus) after the user has typed their input, then apply your masking and formatting to the element. If it gets focus again, then strip out your extra punctuation so the user can just deal with the numbers. eg:

1: user enters numbers, it will look like this:
________________
| 123456789    |
________________

2: user moves to the next input, it will change to this:
________________
| 123.456.789  |
________________

3: user comes back to the element, it changes to:
________________
| 123456789    |
________________
nickf
A: 

I have tried doing this before, but was unable to get it working as completely as I wanted. I found that capturing the "keypress" event (or better yet "keyup" event) and re-writing the field value on that was FAIRLY good. (This is what most "masking" libraries do, and others have posted sample code already.) What I'll recount here is the PROBLEMS I had with this approach:

(1) It was difficult to manage the problem of people using the cursor keys to move back and forth through the field. There are notes out there on how to capture cursor keys in a cross-platform fashion but it's slightly tricky.

(2) Handling pressing of the delete key was even more of a pain (especially since they can cursor or click to anywhere in the field). Just removing the character before the cursor when they hit delete was NOT a good user experience: you would get situations where people couldn't delete stuff! Imagine they type "123.4", then hit delete 6 times in a row. The first delete removes the "4" (good so far), the next one removes the ".". Now your formatting rules see "123" and they add in the decimal for "123." The user can hit delete as often as they like and it won't go anywhere! We solved this by having delete remove the previous important character (digits in your case) instead of the previous character.

(3) Handling paste was one we never solved. Pasting via "ctrl-v" generate a key event that can be caught on different platforms, but pasting via the edit menu just couldn't be caught consistently across platforms. Eventually we just gave up on it.

I hope some of this experience helps. I'd love to share my code, but unfortunately it was for work and I'm not permitted to.

mcherm
A: 

Check out MeioMask http://www.meiocodigo.com/ it is a JQuery plugin that does most of what you are after.

David McEwing