views:

94

answers:

4

I'm using jQuery in my ASP.NET MVC 2 page. It's a super simple post that gets a date in return. The process itself runs very quickly. I want to use a spinner image to show the user something is going on. All works fine in Firefox, testing locally. However, in IE 8, the spinner image doesn't display long enough; it just flickers. This might confuse the end user if they do not see an indication that the process is working/done. What would be the best way to fix this problem?

Thanks.

 <img id="signedout<%: item.Id %>" src="/Content/Images/signed_out.png" alt="Signed Out" title="Signed Out" style="display:none" />
                <div id="ajaxloader<%: item.Id %>" style="display:none;text-align:center"><img src="/Content/Images/ajax-loader.gif" alt="loading..." title="loading..." /></div>

                <script type="text/javascript">
                    $(function () {
                        var id = "<%: item.Id %>";

                        $("#signout" + id).click(function () {
                            if (confirm("Are you sure you want to sign this visitor out?")) {

                                $(this).hide();
                                //$("#signout" + id).hide();
                                $("#ajaxloader" + id).show();

                                var url = '<%: Url.Action("signout") %>';

                                $.ajax({
                                    type: "POST",
                                    url: url,
                                    data: "id=" + id,
                                    success: function (result) {
                                        $("#timeout" + id).append(result);
                                        $("#ajaxloader" + id).hide();
                                        $("#signedout" + id).show();
                                        $("#row" + id).css("background", "#E8E8E8");
                                    },
                                    error: function () {
                                        alert("There was an unexpected error.  Please try again later.");
                                        $("#ajaxloader" + id).hide();
                                        $("#signout" + id).show();
                                    }
                                });
                            }
                        });
                    });   
                </script>
+1  A: 

Can't you just show "Data loaded" message in bright background with fades off in few seconds after reload?

Im0rtality
I could but that's not what I'm setting out to do. I shouldn't do y because I can't figure out x when there *should* be a way to get x to work.
Beavis
And your problem is that data gets loaded too fast... Then you could add sleep in logout script, or setTimeout in js to delay data printing/animation hiding... But why to SLOW DOWN process as people usually prefer fast apps
Im0rtality
I see where you're coming from. But I want to show the spinner. Do you have a solution for that? If so, please share your idea in code with us.
Beavis
Maybe something like this then? Not guaranteed to be w/o mistakes:function ajaxSuccess() { // your success code}function ajaxError() { // your error code} $.ajax({ ... success: function(result) { setTimeout('ajaxSuccess', 1000); }, error: function() { setTimeout('ajaxError', 1000); }
Im0rtality
+1  A: 

You could set a timeout in js and that would guarantee that the spinner wouldn't be hidden till after the timeout had expired:

    function HideLoadingSpinner() {
        $("#ajaxloader" + id).hide();
    }

Then replace your ajax call with this one:

    $.ajax({type: "POST",
            url: url,
            data: "id=" + id,
            success: function (result) {
               $("#timeout" + id).append(result);
               setTimeout(HideLoadingSpinner, 2000);
               $("#signedout" + id).show();
               $("#row" + id).css("background", "#E8E8E8");
            },
            error: function () {
                alert("There was an unexpected error.  Please try again later.");
                setTimeout(HideLoadingSpinner, 2000);
                $("#signout" + id).show();
            }
    });

You could also move the other logic in the success callback into the HidingLoadingSpinner function if you get weird behavior due to the timer.

amurra
Thanks. This is what I was looking for. The process isn't being delayed, we're just making sure the spinner image is being displayed for at least 2 seconds (in your example).
Beavis
+2  A: 

It would probably be a better idea to give some other indication that the process has finished rather than misleadingly displaying the spinner when nothing is actually being processed. However you seem set on this.

This is based on amurra's answer and is designed to either hide the spinner once the process is loaded if and only if the timeout has already been returned. Therefore, if the AJAX request returns "too fast" it will wait for the timeout.

var timeoutComplete=false;
var requestComplete=false;

function HideLoadingSpinner() {
   if(requestComplete) {
      $("#ajaxloader" + id).hide();
   } else {
      timeoutComplete=true;
   }
}

Meanwhile, inside the click handler...

setTimeout(HideLoadingSpinner, 2000);

$.ajax({type: "POST",
   url: url,
   data: "id=" + id,
   success: function (result) {
      $("#timeout" + id).append(result);
      $("#signedout" + id).show();
      $("#row" + id).css("background", "#E8E8E8");
      if(timeoutComplete) {
         $("#ajaxloader" + id).hide();
      } else {
        requestComplete=true;
      }
   },
   error: function () {
      alert("There was an unexpected error.  Please try again later.");
      $("#ajaxloader" + id).hide();
      $("#signout" + id).show();
   }
});

EDIT: I just removed the if(timeoutComplete) stuff from the error function, since there will be an alert before it anyway.

DLH
+1  A: 

I've seen this before. Actually what you're seeing is IE taking a normal amount of time to run the request and FF taking longer than it should. You can set network.dns.ipv4OnlyDomains to localhost in about:config to dramatically speed up FF on localhost. Source.

In my own applications, I follow @Im0rtality's suggestion and have a notification that an ajax request is complete and show a spinner while it's happening. Many times I don't even see the spinner. I use a custom implementation of JBar for my notifications which is very professional looking.

As far as showing a spinner during AJAX calls, you include this in your master page to show a spinner during all JQuery AJAX calls:

$(function () {
    $('.spinner')
    .hide()
    .ajaxStart(function () {
        $(this).show();
    })
    .ajaxStop(function () {
        $(this).hide();
    });
});

Then you don't have to include showing and hiding the spinner w/ every call to $.ajax.

Ryan