Monday, November 29, 2010

An Interesting JavaScript Field Validation Problem

I've spent a bit of time trying to figure out how to combine keystroke level and field level validation with autocompletion in JavaScript.  The idea is that for each field in a form, you want to identify invalid inputs as early as possible.  You don't want to wait for the user to hit the Submit button before checking the values that he has entered.  So you really want keystroke checking, field level checking, and checking at submit time.

You check the keystrokes with the onkeyup event: onkeyup="numericOnly(this)".  It calls a JavaScript function that sees if the field contains only digits.  If you just added a non-numeric key, you remove the last character from this, then window.status="numeric only keys allowed in this field" to set the status bar of the browser, letting the user know that this wasn't okay.

You check the overall field for syntactic or semantic errors by using onblur="validateAreaCode(this, nextField)".  This function gets called when you leave the field by hitting tab, or using the mouse, or hitting enter.  Do whatever checking you need to, then use alert() to warn the user that there is something wrong with the input, and set focus back to this.  If everything worked, you set focus to nextField so that field gets control next.

Oh: but there is one other case where the onblur event happens: if you have autocompletion enabled in Internet Explorer.  As soon as you enter the field, autocompletion's menu pops up--and you probably do not want to validate your inputs yet, because you really haven't left the field--you are waiting to make a decision from the autocompletion choices.

The solution?  Add onfocus="saveRecent(this)" for this field.  The saveRecent function saves the name of the field and its value in global vars.  Then, your onblur function (validateAreaCode in the example above) calls a function mostRecentChanged(this), which compares the name of the field and the value saved by saveRecent.  If the name of the field matches, and the value matches, then you have reached onblur because of the autocompletion menu.  Only if the value has changed do you perform your validation check, because that means that you completed the field, or left the field, and that is why you are now calling onblur.

UPDATE: Dreadfully ugly.  Even if autocomplete does not bring up a menu of choices, onblur event is firing.  It turns out that the best solution was to turn off the onblur event, and do everything through onkeyup instead.  The onkeyup event calls the validation function.  Depending whether the passed in field is full length or not, we either display a complaint in the status bar, or use alert to warn the user, and set focus back to this field.  If there is no error, we set focus on the nextField instead (unless the key event causing this was Shift Tab).  However: since a user might mouse over to another field, I am now having the onclick event invoke the onkeyup validation function by saving the current field from the validation function.  The onclick event then picks up the last field, and does obj.fireEvent("onkeyup") to force the validation function to be executed for the last field before we take action in the new field.

4 comments:

  1. "You don't want to wait for the user to hit the Submit button before checking the values that he has entered."

    Don't make the submit button visible until after the values are checked.

    ReplyDelete
  2. "Do whatever checking you need to, then use alert() to warn the user that there is something wrong with the input, and set focus back to this."

    This is a bad idea. What happens when a user winds up in a field where, for whatever reason, there is no valid data that can be entered?

    Generally you should not do this. If you feel that field-level validation is critical, change the background color of the text box or something, but ALWAYS leave the user an out that isn't Alt-F4.

    (Yeah, I do UI work as a fairly significant part of my day job. Forcing users to quit an app because they can't get off a field enrages them.)

    ReplyDelete
  3. A lot of the existing code has Submit buttons always enabled. I'm fixing this as the opportunity presents itself. (You would not believe the mess I am trying to clean up.)

    Concerning the problem of no valid input: that isn't a problem with any of our fields. The worst that happens is that after they click OK, they can hit the Back or Cancel buttons on the screen.

    ReplyDelete
  4. "You would not believe the mess I am trying to clean up."

    Oh yes we would. BTDT. Still doing it, in fact, to my disappointment.

    ReplyDelete