0

I am having a problem configuring jQuery.Lazy() to work with images that have been appended with a hash. In asp.net core Razor pages, you can use a Image Tag Helper so that the server appends the src with a hash that is checked/updated if the image is ever modified. The syntax is pretty straight forward:

For an <img>, simply add asp-append-version="true" and the server will auto-append the hash to the src. i.e.:

<img src="/images/Photo.jpg" asp-append-version="true">

Which will show up in the browser as:

<img src="/images/Photo.jpg?v=4jjcjhwsV9YZ1K8lXgg_50rci1ju_mNaz-HABqCvPFk">

The problem is: it can ONLY be applied to the src, and hence lies the issue.

So when I add .lazy to the <img> like so:

<img class="lazy" src="/images/PhotoPlaceholder.png" data-src="/images/Photo.jpg" asp-append-version="true">

.lazy works great (with the image fading in as expected), BUT the HTML is now this:

<img class="lazy" src="/images/PhotoPlaceholder.png?v=4jjcjhwsV9YZ1K8lXgg_50rci1ju_mNaz-HABqCvPFk" data-src="/images/Photo.jpg">

Obviously, now the hash will NOT work because it's attached to PhotoPlaceholder.png instead of Photo.jpg. So, how do I configure jQuery.Lazy() to work with the hash? With jQuery.Lazy() or some extra jquery? BTW: I already tried playing with the 'attribute' option, etc. but can't get it to work. Anyone have an idea on how to solve this? I CANNOT be the only one who has run into this issue.

Furthermore, is this even possible? Or do I just have to pick one feature over the other? I need the version hash check because the images may be changed by users and therefore they need to be auto-refreshed (instead of everyone having to do a cache-emptying reload by hitting <ctrl> F5 on the page). I also understand browsers use/need the <src> to display the image (and not much can be done from that perspective), but I was hoping someone may have come up with a work-around to solve this dilemma.

My jQuery.Lazy() is pretty straight forward:

$(".lazy").Lazy({
    effect: 'fadeIn',
    effectTime: 1000
});

Thanks for any help/suggestions... :)

MicJarek
  • 53
  • 6
  • 1
    Please refer [this answer](https://stackoverflow.com/a/33351942/7687666) to extend the method to implement the assignment of `data-src`. – Jason Pan Jan 24 '22 at 09:33

1 Answers1

0

As it turns out, there are 2 ways to handle this:

Solution 1:
Thanks to some help from @eisbehr, there is a way to append the data-src on the client using a hidden <link> element, as so:

<link class="hide-control" id="source-img-1" href="/images/Photo.jpg" asp-append-version="true">
<img class="lazy" id="img-1" data-loader="hashedImageLoader" src="/images/PhotoPlaceholder.png" data-src="/images/Photo.jpg" asp-append-version="true">

That will produce the following HTML markup:

<link class="hide-control" id="source-img-1" href="/images/Photo.jpg?v=AAnmbJAusQ-go5lyg9qCes4WGj8oWsp4eGH78CKKUPA">
<img class="lazy" id="img-1" data-loader="hashedImageLoader" src="/images/PhotoPlaceholder.png?v=4jjcjhwsV9YZ1K8lXgg_50rci1ju_mNaz-HABqCvPFk" data-src="/images/Photo.jpg">

And then using Jquery, update the <img> using the href from the <link> like this:

$('.lazy').Lazy({
    effect: 'fadeIn',
    effectTime: 1000,
    beforeLoad: element => {
        let source = $('#source-' + element.attr('id')).attr('href');
        element.attr('data-src', source);
    }
});

Solution 2:
The second way (and perhaps preferred as suggested by @JasonPan) is to append the data-src with the asp-append-version on the server using asp.net core. In the page (or Partial View if retrieving via AJAX), simply add:

@using Microsoft.Extensions.DependencyInjection;

var versionProvider = Context.RequestServices.GetRequiredService<IFileVersionProvider>();

// Loop as needed for each file
PathFile = "/images/Photo.jpg";
PathFileWithHash = versionProvider.AddFileVersionToPath(Context.Request.Path, PathFile);
<img class="lazy" src="/images/PhotoPlaceholder.png" data-src="@PathFileWithHash" asp-append-version="true">

And on the client, simply call .lazy:

$(".lazyLoadImage").Lazy({
    effect: "fadeIn",
    effectTime: 1000
});

Both solutions work as expected so take your pick... :)

MicJarek
  • 53
  • 6