81

I am trying to preload some images with a jQuery AJAX call, but am having real problems passing a (url) string into a function within the success function of the AJAX call (if that makes sense).

Here is my code as is stands:

//preloader for images on gallery pages
window.onload = function() {
    setTimeout(function() {     
        var urls = ["./img/party/"]; //just one to get started

        for ( var i = 0; i < urls.length; i++ ) {
            $.ajax({
                url: urls[i],
                success: function(data,url) {
                    $(data).find("a:contains(.jpg)").each(function(url) {                               
                        new Image().src = url + $(this).attr("href");
                    });
                }
            });
        };  
    }, 1000);
};

One can see my (failed) attempt at passing the url through into the .each() call - url ends up takes the value of increasing integers. Not sure why or what these relate to, maybe the number of jpg files?

...anyway, it should of course take the single value in my original urls array.

Thanks for any help - I always seem to get in a bit of a twist with these callbacks.


PROGESS?

So, I mucked around a bit, taking heed of comments from @ron tornambe and @PiSquared and am currently here:

//preloader for images on gallery pages
window.onload = function() {
    var urls = ["./img/party/","./img/wedding/","./img/wedding/tree/"];

    setTimeout(function() {
        for ( var i = 0; i < urls.length; i++ ) {
            $.ajax({
                url: urls[i],
                success: function(data) {
                    image_link(data,i);
                    function image_link(data, i) {
                        $(data).find("a:contains(.jpg)").each(function(){ 
                            console.log(i);
                            new Image().src = urls[i] + $(this).attr("href");
                        });
                    }
                }
            });
        };  
    }, 1000);       
};

I tried putting the image_link(data, i) here there and everywhere (in each nested function etc.) but I get the same result: the value for i is only ever logged as 3. I suspect that this is because all references to i point to the same thing and by the time the asynchronous task actually gets to image_link(data, i) the for... loop is over and done with (and hence has a value of 3). Needless to say this gives urls[i] as 'undefined'.

Any (more) tips how I can get round this?

5
  • I am confused by the second argument (url) in the success function. This argument refers to the status of the operation and you are using it (in scope) as the url? Commented Aug 24, 2013 at 1:30
  • Yeah right. Turns out I was more confused! Thanks for that, I did not know - that'll explain why I get numbers for url in the .each() bit. Commented Aug 24, 2013 at 2:20
  • What does the returned "data" look like. Is it html? jQuery "contains" only returns the text of elements, not src or hrefs. Commented Aug 24, 2013 at 2:42
  • I got the original idea and code from here perishablepress.com/3-ways-preload-images-css-javascript-ajax - it worked all fine here (i.e. what is 'in' data). I've added a bit more complexity I guess and broken it. Anyway, I just posted my modifications above ...still broken. Commented Aug 24, 2013 at 3:07
  • Do you know the filenames of the images you want to load or are you loading all images stored in particular folders where images can be added and/or removed? Commented Aug 27, 2013 at 19:09

6 Answers 6

189

Since the settings object is tied to that ajax call, you can simply add in the indexer as a custom property, which you can then access using this in the success callback:

//preloader for images on gallery pages
window.onload = function() {
    var urls = ["./img/party/","./img/wedding/","./img/wedding/tree/"];

    setTimeout(function() {
        for ( var i = 0; i < urls.length; i++ ) {
            $.ajax({
                url: urls[i],
                indexValue: i,
                success: function(data) {
                    image_link(data , this.indexValue);

                    function image_link(data, i) {
                        $(data).find("a:contains(.jpg)").each(function(){ 
                            console.log(i);
                            new Image().src = urls[i] + $(this).attr("href");
                        });
                    }
                }
            });
        };  
    }, 1000);       
};

Edit: Adding in an updated JSFiddle example, as they seem to have changed how their ECHO endpoints work: https://jsfiddle.net/djujx97n/26/.

To understand how this works see the "context" field on the ajaxSettings object: http://api.jquery.com/jquery.ajax/, specifically this note:

"The this reference within all callbacks is the object in the context option passed to $.ajax in the settings; if context is not specified, this is a reference to the Ajax settings themselves."

Sign up to request clarification or add additional context in comments.

8 Comments

WHY WHY WHY WHY is this not documented?!?
It is in fact documented, however hidden, here api.jquery.com/jquery.ajax . See context property of settings.
@codyc4321 can you elaborate? This question has garnered me a ton of upvotes, so if it's no longer valid due to a jQuery update, perhaps I can update the answer. Thanks!
This is great. I would just change it to "that" instead of indexValue to make it more generic. var that = this.that; And load it up. By that way why send the index when you could just send the item in the array to avoid changes that might occur to the array while waiting for ajax success event to trigger?
@Erutan409 as far as I can tell, this still works using JQuery 3.2.1. jsfiddle.net/djujx97n/1 note that the field "indexValue" could read anything. I've demonstrated that in the fiddle. Hope that helps.
|
14

You can also use indexValue attribute for passing multiple parameters via object:

var someData = "hello";

jQuery.ajax({
    url: "http://maps.google.com/maps/api/js?v=3",
    indexValue: {param1:someData, param2:"Other data 2", param3: "Other data 3"},
    dataType: "script"
}).done(function() {
    console.log(this.indexValue.param1);
    console.log(this.indexValue.param2);
    console.log(this.indexValue.param3);
}); 

2 Comments

excellent answer! this is one of the best ways to pass variables
in the answer param1 string value needs to have delimiters eg indexValue: {param1:"someData", param2:"Other data 2", param3: "Other data 3"},
9

Try something like this (use this.url to get the url):

$.ajax({
    url: 'http://www.example.org',
    data: {'a':1,'b':2,'c':3},
    dataType: 'xml',
    complete : function(){
        alert(this.url)
    },
    success: function(xml){
    }
});

Taken from here

Comments

4

I'm doing it this way:

    function f(data,d){
    console.log(d);
    console.log(data);
}
$.ajax({
    url:u,
    success:function(data){ f(data,d);  }
});

Comments

0

Just to share a similar problem I had in case it might help some one, I was using:

var NextSlidePage = $("bottomcontent" + Slide + ".html");

to make the variable for the load function, But I should have used:

var NextSlidePage = "bottomcontent" + Slide + ".html";

without the $( )

Don't know why but now it works! Thanks, finally i saw what was going wrong from this post!

Comments

0

I've meet the probleme recently. The trouble is coming when the filename lenght is greather than 20 characters. So the bypass is to change your filename length, but the trick is also a good one.

$.ajaxSetup({async: false}); // passage en mode synchrone
$.ajax({
   url: pathpays,
   success: function(data) {
      //debug(data);
      $(data).find("a:contains(.png),a:contains(.jpg)").each(function() {
         var image = $(this).attr("href");
         // will loop through
         debug("Found a file: " + image);
         text +=  '<img class="arrondie" src="' + pathpays + image + '" />';
      });
      text = text + '</div>';
      //debug(text);
   }
});

After more investigation the trouble is coming from ajax request: Put an eye to the html code returned by ajax:

<a href="Paris-Palais-de-la-cite%20-%20Copie.jpg">Paris-Palais-de-la-c..&gt;</a>
</td>
<td align="right">2015-09-05 09:50 </td>
<td align="right">4.3K</td>
<td>&nbsp;</td>
</tr>

As you can see the filename is splitted after the character 20, so the $(data).find("a:contains(.png)) is not able to find the correct extention.

But if you check the value of the href parameter it contents the fullname of the file.

I dont know if I can to ask to ajax to return the full filename in the text area?

Hope to be clear

I've found the right test to gather all files:

$(data).find("[href$='.jpg'],[href$='.png']").each(function() {  
var image = $(this).attr("href");

1 Comment

Thanks for the coding presentation. I will try to be better the next time.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.