Tuesday, December 20, 2005

Javascript / Firefox / onBlur / focus workaround

This is one of those issues that can waste a lot of time and makes you look like an idiot to your boss if you can't fix it.

Occasionally, I have a form where a certain type of data is possible but questionable. An example might be, entering a negative dollar amount on a purchase order. At first thought, it doesn't make sense. You generally can't order anything from a vendor and have them pay you for the privilege. If you go a little further, though, you might be able to use this as a way to correct an error on a previous purchase order.

The way I would like to handle this is to have a javascript confirm box appear warning the user that the value is normally positive. If they decide to continue, the value is accepted as is.

The problem arises when you try to run this code in Firefox. For some reason, the event model for forms in Firefox has been fubar for many years. I've been tracking this bug for 4 years.

Here is a workaround for the issue that doesn't give IE fits either:


function checkValue(fld)
{
var re = /[^\d\.\-]/g;
num = fld.value
num = num.replace(re,"");
fldID = fld.id;

if (num < 0)
{
if (confirm("This is normally a positive number. \nIs it OK to keep this negative value?"))
{
return true;
} else {
setTimeout("document.getElementById(fldID).focus();",1);
setTimeout("document.getElementById(fldID).select();",1);
return false;
}
}
return true;
}


If the code you want to execute is having trouble because of the timing of the events firing, you can wrap the code in the setTimeout function and delay it's execution just enough to get things to work as you would expect.

31 comments:

  1. I too have come up against this problem, and tried the workaround you suggest. It seems to work when moving between fields, but there ARE problems when you switch from a field validated in this way to another window - it screws Firefox up, big style.

    A bug has been raised about this - ID 297134 but this currently has a status of unconfirmed.

    ReplyDelete
  2. Thanks for the update. There are definitely some javascript/form interraction issues lingering in the Firefox code. Some of them have had extensive conversations regarding reproducability.

    This one seems like a recent entry, so I'll have to do a search to see if something similar has already been logged. If I don't find anything, I'll be sure to add a vote or two if I can.

    An interesting point, this issue might have never been found if it hadn't been for the focus/select issue.

    ReplyDelete
  3. Worked great on a similar problem I was having, thanks! Tom

    ReplyDelete
  4. Well, that saved me some time, makes me less looking like a fool to my boss ;) Tnx

    ReplyDelete
  5. Cheers Mate! Ran into this problem just this morning, and lo and behold you already have a fix for it!

    How did any of us get any work done before the Internet?

    Hamayoun

    ReplyDelete
  6. I didn't even consider that it was browser-specific. Your fix cured the problem for me, and taught me to check things out a bit more. Thanks much.

    ReplyDelete
  7. Thanks for this "bugfix" that works perfectly.

    ReplyDelete
  8. Thank you!! It's a great solution.

    ReplyDelete
  9. Thanks for your solution. I tried this on FF 2.0.0.7 and it complained that the variable fldID did not exist. I had the workaround of changing the code to be
    setTimeout("document.getElementById("+fldID+").focus();",1);
    setTimeout("document.getElementById("+fldID+").select();",1);

    where it puts in the field ID directly into the string. Hope this helps someone who comes across the same problem.

    Rasika

    ReplyDelete
  10. Thanks for sharing this solution with us! :) I run into this problem, too. I've never thought that this workaround can be a solution, but it is! Have you ever thought about sending a bugreport to the Firefox developers?

    ReplyDelete
  11. That's what makes this issue so irritating. This bug has been in the mozilla bug system since 9/21/2000. Here is the link: Bug 53579.

    ReplyDelete
  12. Thanks a lot Mike...

    I have spent a lot of of time in the same problem.. then i got your script ... and its really amazing..

    i don't know why it was not working in FireFox and how you got what the p[roblem was.. but now its working in both IE and Firefox .. thanks a lot buddy..

    Vikas Somani

    ReplyDelete
  13. Thankyou i have been fighting with this one for the best part of a day. You would think that firefox would have this licked by know given how much people dislike IE.

    But this just makes IE look good in the eye of the general public. Anyway thank you again for a great fix.

    ReplyDelete
  14. Mahalo for your help! You really safed my day...

    This fix does a great work.

    ReplyDelete
  15. Just wanted to add my thanks! Works perfectly.

    ReplyDelete
  16. Thanks man, I too had this problem, scrating my head. Thanks for the solution. It rocks

    ReplyDelete
  17. Man, 4 years after you wrote the article and I still needed the solution. Thanks.

    ReplyDelete
  18. **kent said...
    "Man, 4 years after you wrote the article and I still needed the solution. Thanks."

    Er, yes. Me too. And I just loaded the latest Firefox upgrade (Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.7) Gecko/2009030422 Ubuntu/8.04 (hardy) Firefox/3.0.7)

    ReplyDelete
  19. Thanks a ton for this solution! you rock!

    ReplyDelete
  20. Thanks, you helped someone else! This work-around does have a 'got-you' when the next field on the form has an onblur event. That onblur would get triggered when the focus is set back to the original field at the end of the timeout period. So, I stick with onchange throughout.

    ReplyDelete
  21. Thanks for your solution.

    I just change for dynamic as per Rasika. Only I need to change little bit for getElementById added ' b4 and after name insertion.

    Below works fine:

    setTimeout("document.getElementById('"+fldID+"').focus();",1);
    setTimeout("document.getElementById('"+fldID+"').select();",1);

    Thanks again

    ReplyDelete
  22. Mike you are a life saver - I started pulling my hair out because to me Firefox is much superior and standards compliant than IE, but this bug really made me eat my words. Thank you for saving my hair.

    ReplyDelete
  23. This does not work for me. I have onblur event on textbox1 which sets focus on itself on error, and i have same on textbox2. When i blur the textbox1 by clicking on textbox2, or vice versa, cursors in both text boxes blink indefinetely, with time difference of 1 ms. How can I solve this bug without setTimeout?

    ReplyDelete
  24. You need to work this issue with the Mozilla group. Any time you can create two controls on the same page that each have the focus, you're definitely talking about a bug.

    Good luck with that, since this bug is almost 10 years old and still kicking.

    ReplyDelete
  25. Great...Thanks.

    ReplyDelete
  26. Its 2011 and its still a usefull post! Thank you!

    ReplyDelete
  27. many thanks dude, I lost a lot of time tryin' to resolve this :)

    ReplyDelete
  28. 2012 and still very helpful!

    In my case I needed a more generic solution. Elements passed to the method were not guaranteed to have an id (or much of anything) so fell back to the old fashioned focus when necessary (as that still works for non FF users.) Also I found that a value of 1ms was not always enough, I could still get it to fail so upped to 50ms.

    fldID = field.id;
    if(fldID == "") {
    field.focus();
    } else {
    setTimeout("document.getElementById(fldID).focus();",50);
    }

    ReplyDelete
  29. I added a comment to the bug report. It is simply incredible that this BUG (and it is a BUG, no matter what comments were made in the bug report) has not been fixed in over a decade!

    My problem was with resetting the focus in an onchange event.

    The setTimeout() solution worked, although it took me a while before I tried more than 50 milliseconds. I tried the values other commentators did (including on other web sites and in the bug report!). I thought I'd give it one more chance and picked a really big number (1/4-second). I was surprised that it then worked.

    Thank you for stirring up the pot over at bugzilla.org

    John Goold (St. John's NL Canada)

    ReplyDelete
  30. thanks! Amazing piece of code.

    Aristos Aresti

    ReplyDelete
  31. Thanks a lot, this works for me after lost many hours to solve this issue...

    Ending 2012 and this post is a good solution for many people.

    Miguel Roldán
    Mexico

    ReplyDelete