Affects Version/s: 5.0.15
Fix Version/s: 5.0.16
While working with forms I noticed a gotcha that is caused by the onblur display of error popups.
Think about a form where the first field is "required". As it is the first field, the cursor is placed in it automatically after page load.
If the user performs any action on the page the onblur event is triggered and a validation error popup is shown, as he has not yet entered any data.
That's ok if the user is focused on working with the form. But it's problematic if he doesn't care about the form but clicks any other link or anywhere else on the page.
E.g. consider a login form which is always placed on top of the page. The use will always see the validation error when doing something on the page.
Or even stranger (at least for the user): The form itself is in a zone and there is a link that triggers the zone reload to hide the form.
If the user selects this link, the onblur is fired, the validation popup appears and the form disappears. The user is left with only a validation error popup in place.
I think the blur event must be restricted somehow:
1) Do not select the first element automatically. Cons: negative user experience and I guess some browser do this by default.
2) Do not trigger the validation on onblur when the field is empty. Cons: The user has to press "Submit" to get the "required" errors
3) Only trigger validation on onblur when the focus was shifted within the form. That guaranties that the user is busy editing the form and he cares about validation messages.
4) Only accept onblur validation if there was an explicit focus before (listen for keypress&foucs)
Nr. 3) is my personal favorite. However as blur is triggered before the focus event of other elements, it is quite hard to accomplish.
Nr. 2) is easy to implement (an additional if) and I find it sufficient for my use cases. It certainly improves the usability. To add this just modify the initialize method of the FieldEventManager like this:
Tapestry.FieldEventManager.prototype.initialize = function(field)
this.field = $(field);
this.field.fieldEventManager = this;
var id = this.field.id;
this.label = $(id + ':label');
this.icon = $(id + ':icon');