Combination of onblur event and .focus() can cause recusion errors
We had a strange and irritating recusrsive popup problem in our web application during our last release.
User scenario:
We have a grid with a text box in each row for tax value. On page load, this is populated with default tax values:
User can edit the tax amount in each textbox. Now, the requirement is that the user should not be able to set all the textboxes to zero. Further, when the user tries to do that, a message should be shown and the focus should go back to this textbox whose value was being set to zero.
How we were doing this
We were using onBlur event of textbox, check if all text boxes set to zero and set the focus back if yes.
User scenario:
We have a grid with a text box in each row for tax value. On page load, this is populated with default tax values:
User can edit the tax amount in each textbox. Now, the requirement is that the user should not be able to set all the textboxes to zero. Further, when the user tries to do that, a message should be shown and the focus should go back to this textbox whose value was being set to zero.
How we were doing this
We were using onBlur event of textbox, check if all text boxes set to zero and set the focus back if yes.
.....
checkAllTextsBlank(movedAwayFrom)
{
var allTextboxesZero = areAllTextboxesZero();
if(allTextboxesZero)
{
alert("You cannot set all taxes to zero");
movedAwayFrom.focus();
}
Where areAllTextboxesZero used to iterate through each textbox and see if all have zero value.
Problem in this approach
Consider this scenario: We set the first textbox - say T1 - to zero, then moved to the next textbox - say T2 - and set this too as zero. Now if we click on some other control (other than T1) or form there is no problem. We get an alert message and the focus goes back to T2.
But after setting T2 to zero, if we click on T1, we keep getting non-stop alert messages "you cannot set all texts to zero". The problem here is that when you click on T1,onblur of T2 gets called - but the focus is now on T1 till the T2.onblur javascript is being executed. So when you call T2.focus() in your javascript, onblur of T1 gets called and so on. So we were triggering onblr of T1 and then onblur of T2 continuously indirectly because of the call to focus().
Resolution:
Obvious solution to this is to check if any of the textboxes already has focus and if so, do not call focus method again.
if(allTextboxesZero)
{
alert("You cannot set all taxes to zero");
if(!anyTextboxInGridHasFocus())
{
movedAwayFrom.focus();
}
}
Writing the function anyTextBoxInGridHasFocus is not easy. Followig is the pseudocode
Writing the function anyTextBoxInGridHasFocus is not easy. Followig is the pseudocode
function anyTextboxHasFocus()
{
foreach text tax control in grid
{
if (element.name == document.activeElement.name)
{
return true;
}
}
return false;
}
Limitations:
document.activeELement is not fuly supported by browsers other than IE (firefox<3.0)
Comments
Post a Comment