How can I reliably preload and cache my ajax loading image across my site?

1.6k views Asked by At

I added the following code to my asp.net-mvc site.master page with the goal is making sure this image gets loaded upfront and cached (as I use it all over my site):

enter image description here

    $(document).ready(function () {

        var x = new Image();
        x.src = "/content/images/ajax-loader.gif";

I am assuming this code would force a preload and cache of this ajax loading image but when i run a page that references this image, i still see this for a few seconds. Here is an example of a jqgrid loading div

enter image description here

which uses this code for loadtext:

 $.jgrid = $.jgrid || {};
 $.extend($.jgrid,{
   defaults : {
    recordtext: "View {0} - {1} of {2}",
    emptyrecords: "No records to view",
    loadtext: "Loading Data ...<img src='/Content/Images/ajax-loader.gif' />",
    pgtext : "Page {0} of {1}"
},

before my actual ajax loading image shows like below:

enter image description here

Is there any suggestion for what could be causing this and how to ensure this image is loaded and cached prior to trying to use it? Is my solution actually redownloading the file each time?

What is the best recommendation here for how to achieve my goal?

9

There are 9 answers

2
dashtinejad On BEST ANSWER

Whenever you use an img element, the browser will request it from server. Using CSS background-image, will request the image only once, and you can use it multiple times, without seeing that problem again.

.loading {
  display: inline-block;
  width: 16px;
  height: 16px;
  background: url(https://i.stack.imgur.com/CRmPi.gif);
}
<div>Hello World <span class="loading"></span></div>
<div>Hello World <span class="loading"></span></div>
<div>Hello World <span class="loading"></span></div>

0
Oleg On

I think that the only correct way to cache the image is setting some max-age in the header of the server response (I mean something like Cache-Control: max-age=691200 or higher). You can load the GIF even from any other place in Internet/Intranet where you can more easy specify the caching attribute of the GIF file.

If your site run on IIS7 or higher you can add the section

<staticContent>
    <clientCache cacheControlMaxAge="7.00:00:00" cacheControlMode="UseMaxAge" />
</staticContent>

within <system.webserver> (see the link and here).

1
Savaratkar On

Put this image in an hidden element at top of your master page.

<div style="display: none;"><img src="/content/images/ajax-loader.gif"></div>

You are loading this image in master page on document.ready(), which gets called on complete page load. And I feel there may be chances that your new page where this gif is being showed up is not fetched from the server already.

To check if image is being downloaded every time or not, use google chrome developer screen's Network tab.

0
Amirhossein Mehrvarzi On

Since browsers may ignore relative image paths generated by Javascrip, I recommend You to use this:

$.jgrid = $.jgrid || {};
 $.extend($.jgrid,{
   defaults : {
    recordtext: "View {0} - {1} of {2}",
    emptyrecords: "No records to view",
    loadtext: "Loading Data ...<span class='ajax-loader'></span>",
    pgtext : "Page {0} of {1}"
},

And its style would be something like this:

.ajax-loader {
  background: url('Images/ajax-loader.gif');
}

Note that Configuring the Server cache is needed when you wanna avoid getting the same images in the next visits (not needed in current session).

0
adeneo On

According to the specifications given by the W3C, URL's are in fact case-sensitive.

Of course, in a windows file system, case doesn't matter, so for the server these two are the same file

/content/images/ajax-loader.gif
/Content/Images/ajax-loader.gif

The server will serve the image regardless of what case you use (on Windows).

However, all browsers actually follow the specifications for URL's, and will treat those two URL's as two different resources.

To the browser, those are two different files, caching one won't cache the other.

In other words, you're caching one resources, and then loading a completely different resource, because you're not using the same case.

Make absolutely sure that you type the URL exactly the same, and genereally just using lowercase is the way to go

$(document).ready(function () {

    var x = new Image();
    x.src = "/content/images/ajax-loader.gif";

    $.jgrid = $.jgrid || {};
    $.extend($.jgrid,{
      defaults : {
        recordtext: "View {0} - {1} of {2}",
        emptyrecords: "No records to view",
        loadtext: "Loading Data ...<img src='/content/images/ajax-loader.gif' />",
        pgtext : "Page {0} of {1}"
     },
   .......
1
guest271314 On

Try utilizing data URIs

  $.jgrid = $.jgrid || {};
  $.extend($.jgrid, {
      defaults: {
        recordtext: "View {0} - {1} of {2}",
        emptyrecords: "No records to view",
        loadtext: "Loading Data ...<img src=data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA== />",
        pgtext: "Page {0} of {1}"
      }
  });

$(document).ready(function() {
      $.jgrid = $.jgrid || {};
      $.extend($.jgrid, {
          defaults: {
            recordtext: "View {0} - {1} of {2}",
            emptyrecords: "No records to view",
            loadtext: "Loading Data ...<img src=data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA== />",
            pgtext: "Page {0} of {1}"
            }
          });
          $("#results").append($.jgrid.defaults.loadtext)
});
  
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="results"></div>

0
danny117 On

<body><img src="content/images/loader.gif" style="display: none" />

It could be simply src="i/l.gif" if you loose the content/images folder in favor of a folder named i and give common images a small name to save bandwidth.

0
Hereblur On

To pre-loading the image, you should attach your image to the document.

var x = new Image();
x.src = "/content/images/ajax-loader.gif";
x.style.width = "1px";
x.style.height = "1px";
document.getElementsByTagName("body").appendChild(x);

But to make 100% sure the image is available before use, even before preload finish. you should use data-uri image.

 $.jgrid = $.jgrid || {};
 var imageData = "data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==";
 $.extend($.jgrid,{
   defaults : {
    recordtext: "View {0} - {1} of {2}",
    emptyrecords: "No records to view",
    loadtext: "Loading Data ...<img src='" +imageData+ "' />",
    pgtext : "Page {0} of {1}"
},

There are a lot of data uri generator out there, http://dopiaza.org/tools/datauri/index.php for example.

0
Paulo Segundo On

You can preload the image:

function preloadImage(images) {
    $(arrayOfImages).each(function(){
        (new Image()).src = this;
    });
}

$(document).ready(function () {
    preloadImage([
        '/content/images/ajax-loader.gif'
    ]);
...