views:

61

answers:

2

Hello,

I have this script provided by @Felix Kling in this post HERE, but is crashing my IE when I use it; on FF 3.6, Opera, Chrome, Safari work fine.

Any idea why is this happening? A fix maybe?

var ajaxTimeout;

function autorun() {
    if ($("#contactForm").is(":visible")){
        if(ajaxTimeout) {
            clearInterval(ajaxTimeout);
            ajaxTimeout = false;
        }
    }
    else if(!ajaxTimeout) {
        ajaxTimeout = setInterval("refreshAjax();", 15000);
    }
}


$(function autorun() {
    setInterval("autorun();", 2000)
});

Thanks,

Cristian.

LE. Sorry, forgot to add details about that.

IE just closes, "encounter an error and needs to close, looking for a solution ...". IE 8.0 Windows7. If I load the page, I cannot open the debugger from the developer tools, but if I open the debugger before I load that page and press Start debug it doesn't show any errors or anything, but the page is not refreshing the grid as it was suppose to.

A: 

I suspect that this is the culprit:

$(function autorun() {
    setInterval("autorun();", 2000)
});

That's not really valid javascript. I think it's probably supposed to be something like:

$(document).ready(function() {
   setInterval("autorun();", 2000);
});

[edit: there was an error in my suggestion above, and I have corrected it. I was incorrectly assigning the result of setInterval(...) to the variable ajaxTimeout. This ultimately caused the logic inside the main autorun() function to never initiate its interval on refreshAjax(), thus causing the code to appear to "do nothing".]


[edit: some have indicated that my suggestion was offered without enough explanation, so I'll try to provide that here.]

  • you were declaring function autorun() twice. Once at the top, and again in the bottom section where I've suggested that you should make changes. Both declarations are in the same scope, so the names will collide and behavior will be browser-dependent. Some browsers will let one function "hide" the other, while other browsers will (probably) refuse to compile it.

  • you have used a named function declaration (the second declaration of autorun) in an "inline" context. This may be allowed by some browsers (and some have suggested that it is actually valid by the standard -- though admittedly I thought it was not), but it will definitely cause problems in IE.

  • My suggestion changes the second declaration into an anonymous declaration so as to kill two birds with one stone: avoid a name collision, and use syntax that is supported across all browsers.

  • finally, I introduced the use of $(document).ready(...), because it's standard practice these days, when programming with jQuery. You can read more about it on jQuery's site. Long story short - it is directly equivalent to the $(function() {...}) syntax that you've used, so you can take it or leave it as you please.

Lee
I'd recommend just passing the function in too instead of a string to eval
Russ Cam
Capturing the return value is useful if you want to step the timer at some point, but otherwise entirely optional.
David Dorward
Nope, doesn't work. Is not even refreshing the grid anymore in FF or chrome.
Chris19
It is probably a good idea to *not* make three separate changes to a piece of code and describe them with nothing more than "That's not really valid javascript" — it obscures the point.
David Dorward
@David - You're right in that it's not technically invalid, however it may as well be since it's an IE bug. I provided one link in my answer about this, but there are hundreds out there describing this particular bug with IE function scoping.
Nick Craver
@Russ Cam - I agree, best to pass the function instead of string, but I was trying to introduce as few changes as possible to the OP's code. passing a string is technically allowed, so I left it alone.
Lee
@Chris19 - yes, the core of my suggested change was sound but I added an assignment to `ajaxTimeout`, when I should have left it as it was. I'm making an edit to fix this (just in case anyone stumbles upon it in the future) - so, for what it's worth, it should work now. I'm glad you got it solved in the meantime though -- @Nick's approach is good too.
Lee
@David Dorward - I take issue with your down-vote, but I guess you're entitled to your opinion. The named inline function *is* invalid (at least as far as IE is concerned). And declaring two named functions with colliding names is *at least semantically* invalid (if it's not also something that the compiler or runtime would complain about). In any case, I've removed the assignment to `ajaxTimeout` (which was why my suggestion didn't work for the OP), and I've added a detailed explanation of the issues that my answer addresses.
Lee
@Lee — Don't make assumptions about where down votes come from.
David Dorward
@David Dorward - Fair enough. My apologies. (+1 on your comment) :)
Lee
+3  A: 

Here's what you're after:

$(function () {
  var ajaxTimeout;
  function autorun() {
    if ($("#contactForm").is(":visible")){
      if(ajaxTimeout) {
        clearInterval(ajaxTimeout);
        ajaxTimeout = false;
      }
    }
    else if(!ajaxTimeout) {
      ajaxTimeout = setInterval(refreshAjax, 15000);
    }
  }
  setInterval(autorun, 2000);
});

IE doesn't at all like named functions used like this, and it's overriding the previously defined one. This is a long-standing bug not fixed until IE9. The core of the problem is that $(function autorun() { is taking over the autorun name, which is just queuing more and more runs of itself.

Also, it's better to pass function references to setInterval() directly, not strings.

Nick Craver
Spot on, Nick. Works perfectly. Thanks so much, was driving me crazy.
Chris19
@Chris19 - you're certainly not the first, *many* developers got a little balder with this one :)
Nick Craver