cloudinary / cloudinary_js

Cloudinary JavaScript library
MIT License
328 stars 224 forks source link

Issue with Cloudinary jquery Responsive feature inside a loop #131

Closed misner closed 7 years ago

misner commented 7 years ago

I am raising here an issue i am having. I also sent a Ticket to the Support Team but I thought afterwards it could also be helpful for other people running into the same issue.

It's basically an issue when you change the data-src multiple times within a loop, then the SRC generated by Cloudinary jquery's responsive feature are not correct as they keep sending back the first src generated. It might be a "src-cache" issue but I don't know if it's the case and I did not find how to fix this so that our code works.

We have a hidden image that gets several data-src and should generate via cloudinary jquery library the relevant url that after gets sent to to a background of a div (background url() )

Here is the (simplified) code so that you can witness a very strange bug: http://jsfiddle.net/zk0nLqzt/ (sorry for the huge file in the javascript Tab which starts with your jquery library, i did not manage to make the jsfiddle work by putting it as I usually do in 'external Resources', i was geeting a "$.responsive undefined' => my custom code is in the bottom of the js part)

The goal of this simulation: if it worked , it should be that after the loop made up of 2 images (sample.jpg and sheep.jpg), the final image is the sheep.jpg but in practice, it does not work as the final image we see remains the sample.jpg

Also, other signs of the bug I created to clearly pinpoint to the fact there is an issue (maybe a bug in your library):

You can see that the browser does this timeline by reading at these alert messages: First alert: "i have just added in data-src :https://res.cloudinary.com/demo/w_auto:200/sample.jpg" -> SO FAR this is what's expected THEN Second Alert:" i have just added in src :https://res.cloudinary.com/demo/w_400/sample.jpg" -> SO FAR this is what's expected: it generated the correct url for sample.jpg and sent it back to me THEN third Alert:"i have just added in data-src :https://res.cloudinary.com/demo/w_auto:200/brown_sheep.jpg" -> SO FAR this is what's expected: it sent the second image (sheep.jpg) of the loop inside the data-src THEN fourth alert: "i have just added in src :https://res.cloudinary.com/demo/w_400/sample.jpg" HERE WE HAVE THE WEIRD ISSUE: the cloudinary jquery responsive did not generate the url with the sheep.jpg but sent back to the src the SAME url of the sample.jpg This is like it did not re-process the data-src

I even tried to remove the data-src and src between each loop (as it could be a source of bug), meaning i went back to a totally blank code between each loop, thinking that if the image is back to being without anything (no data-src, no src), the bug should not occur. so between loop the line would become: <img class="cld-responsive game-page-bckdImgCover" id="backgroundAsset-15" > But even with this, so strange, when Cloudinary sends back the src for the data-src=... sheep.jpg, it sends back the sample.jpg !!! If you want to try you can uncomment in my code //$image.removeAttr('data-src'); //$image.removeAttr('src'); But this did not do anything so i am not sure it's a good path to follow to solve this bug.

It could be a weird dat-src-cache but i am not sure. Maybe it's related to https://github.com/cloudinary/cloudinary_js/pull/119 (@eitanp461 ?)

I'm totally out of ideas !

Help very much appreciated.

HTML

<section  
  id="contentAfterIntro"
  class="game-page-bckdCover" 
  style=" background: url('') center;
          background-size:cover;">

  <img    
    class="cld-responsive game-page-bckdImgCover"
    id="backgroundAsset-15">  

</section>

JS

var i,
    s,
    RawDataSrcArray = [           'https://res.cloudinary.com/demo/w_auto:200/sample.jpg',
    'https://res.cloudinary.com/demo/w_auto:200/brown_sheep.jpg'
    ],
   len = RawDataSrcArray.length;

var $image = $('#contentAfterIntro').find('#backgroundAsset-15');

for (i=0; i<len; ++i) {
      (function(index) {
        var s = RawDataSrcArray[index];  

        //send to img shell the first raw data-src
        //which *automatically* generates src for img via CL. responsive 
        $image.attr('data-src', s);
        console.log('i have just added in data-src :'+$image.attr('data-src'))
                alert('i have just added in data-src :'+$image.attr('data-src'))

        //fire off a request to Cl. server to get responsive-adjusted url
        //and download the image when it is returned       
        $.cloudinary.responsive($image);
        console.log('i have just added in src :'+$image.attr('src'))
        alert('i have just added in src :'+$image.attr('src'))

        //store 
         bgImage = $image.attr('src');     
        //prepare for nextloop iteration
        //(does not work if data-src present when new attr('data-src')
        //comes to kick in
        //$image.removeAttr('data-src');
        //$image.removeAttr('src'); 

      })(i);       
    };

    $("#contentAfterIntro").css( {
    'backgroundImage': 'url('+bgImage+')'
    });

// General set up for Cl.
$(function() {
  $.cloudinary.config( {cloud_name: 'demo'} );
  //instantiate responsive CL. features
  $.cloudinary.responsive({
  });
});

CSS

body {
    height: 100%;
    width: 100%;
    margin: 0;
    padding: 0;
}
misner commented 7 years ago

The question was resolved by Cloudinary Team. The reason it was not working is that jQuery's data is an underlying object which is different than the HTML5 data attributes.

From https://forum.jquery.com/topic/jquery-data-caching-of-data-attributes#14737000003537186:

.data is in the cache, and .attr('data-XXX') is in the DOM.

From http://api.jquery.com/data/#data-html5:

The data- attributes are pulled in the first time the data property is accessed and then are no longer accessed or mutated (all data values are then stored internally in jQuery).

To fix the issue we replaced:

$image.attr('data-src', s);

in the loop with:

$image.data('src', s);