Mathieu
Mathieu

Reputation: 4797

Lazy load bootstrap carousel without changing img src attribute

I want to lazy load the images loaded in my bootstrap 3 carousel. I found a pretty good solution but the problem is that all are relying on changing <img src=...> to <img data-lazy-load-src=...> but I can't do that as I need these " src" to all remain called "src" because of very deep third party responsive module rely on being able to read 'src' (and just precisely 'src', not ' data-lazy-load-src'.)

So I would like to do the same as this solution but without introducing a new "data-lazy-load-src" src. Could I do the same by introducing just a class "lazy-load" or another data-target or similar... either on the div "item" or on the <img> directly?

I don't know how to adjust the javascript to do that.

Source: https://stackoverflow.com/a/31564389/1467802

CURRENT CODE:

html

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>

<div class="container-fluid">

  <div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
    <!-- Indicators -->

    <!-- Wrapper for slides -->
    <div class="carousel-inner" role="listbox">
      <div class="item active">
        <img data-src="http://placehold.it/5000x1000">
      </div>
      <div class="item lazy-load"> <!-- here I add the new lazy load class -->
        <img -src="http://placehold.it/5001x1000">
      </div>
      <div class="item lazy-load"> <!-- here I add the new lazy load class -->
        <img data-src="http://placehold.it/5002x1000">
      </div>
      <div class="item lazy-load"> <!-- here I add the new lazy load class -->
        <img data-src="http://placehold.it/5003x1000">
      </div>
      <div class="item" lazy-load"> <!-- here I add the new lazy load class -->
        <img data-src="http://placehold.it/5004x1000">
      </div>
    </div>

  </div>

</div>

Javascript

var cHeight = 0;

$('#carousel-example-generic').on('slide.bs.carousel', function(e) {

  var $nextImage = $(e.relatedTarget).find('img');

  $activeItem = $('.active.item', this);

  // prevents the slide decrease in height
  if (cHeight == 0) {
    cHeight = $(this).height();
    $activeItem.next('.item').height(cHeight);
  }

  // prevents the loaded image if it is already loaded
  // here this is where I don't know how to change the code and would like to target the class I introduced
  var src = $nextImage.data('lazy-load-src');

  if (typeof src !== "undefined" && src != "") {
    $nextImage.attr('src', src)
    $nextImage.data('lazy-load-src', '');
  }
});

Upvotes: 0

Views: 4245

Answers (2)

BDS 55
BDS 55

Reputation: 11

This is final code, after stuck for a while, your code above did not work, until I find out bugs (=> $nextImage.attr not .data). Here it is, you can see the demo on my site detail story view.

    /*lazy slide*/

    var cHeight = 0;

    $('#carousel-example-generic').on('slide.bs.carousel', function(e) {

      var $nextImage = $(e.relatedTarget).find('img');

      $activeItem = $('.active.item', this);

      // prevents the slide decrease in height
      if (cHeight == 0) {
        cHeight = $(this).height();
        $activeItem.next('.item').height(cHeight);
      }

      // prevents the loaded image if it is already loaded
      //var src = $nextImage.data('lazy-load-src');
      var src = $nextImage.attr('lazy-load-src');

      if (typeof src !== "undefined" && src != "") {

        // minor tweaks here: lazy-load-src > data-src
        $nextImage.attr('lazy-load-src', '');
        $nextImage.attr('data-src',      src);
        //$nextImage.attr('src',src);
        // inform ResponsiveIO about changes on your page
        ResponsiveIO.refresh($nextImage[0]);
      }
    });

Upvotes: 1

Jaiden Snow
Jaiden Snow

Reputation: 852

If I understand you correctly - your third-party module that causes your headache is responsive.io

But it exposes an interesting method: https://responsive.io/docs#refresh-after-page-load

Especially for your case, Responsive.io has a refresh method to inform it when you add new image to markup (I think it correlates with concept of lazy load perfectly).

Try this javascript:

var cHeight = 0;

$('#carousel-example-generic').on('slide.bs.carousel', function(e) {

  var $nextImage = $(e.relatedTarget).find('img');

  $activeItem = $('.active.item', this);

  // prevents the slide decrease in height
  if (cHeight == 0) {
    cHeight = $(this).height();
    $activeItem.next('.item').height(cHeight);
  }

  // prevents the loaded image if it is already loaded
  var src = $nextImage.data('lazy-load-src');

  if (typeof src !== "undefined" && src != "") {

    // minor tweaks here: lazy-load-src > data-src
    $nextImage.data('lazy-load-src', '');
    $nextImage.data('data-src',      src);

    // inform ResponsiveIO about changes on your page
    ResponsiveIO.refresh($nextImage[0]);
  }
});

And HTML would be:

<!-- Don't forget to include responcive.io for your test ^ ^ -->

<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
    <div class="item active">
        <div class="item">
            <img data-lasy-load="http://placeholdit.imgix.net/~text?txtsize=250&txt=1&w=5000&h=1000" />
        </div>
        <div class="item">
            <img data-lasy-load="http://placeholdit.imgix.net/~text?txtsize=250&txt=2&w=5000&h=1000" />
        </div>
        <div class="item">
            <img data-lasy-load="http://placeholdit.imgix.net/~text?txtsize=250&txt=3&w=5000&h=1000" />
        </div>
    </div>
</div>

This is the bare-bone concept. Tell if it would not work.

Upvotes: 1

Related Questions