13 votes

Chargement paresseux du contenu des diapositives dans le carrousel (le contenu est constitué de oEmbeds/iframes)

Je charge en ajax une modale/popin avec un carrousel Bootstrap dans lequel chaque diapositive est (non pas une image comme dans beaucoup de questions sur le chargement paresseux) mais un iframe provenant d'oEmbed de différents réseaux sociaux ( facebook , instagram , twitter , ...).

Le problème est que lorsque je clique sur le bouton qui ouvre la modale, TOUT le contenu des diapositives est chargé, c'est-à-dire 15 à 20 oembeds (chacun d'entre eux charge le contenu texte, image et javascript...).

J'aimerais être malin et ne faire que du "lazy load" diapo par diapo ou même plus intelligent 3 diapos par 3 diapos.

Je précise également, à titre d'information, que j'utilise scrollMonitor y Hubspot Messenger . Mais je préférerais utiliser les événements slide de Bootstrap pour déclencher l'apparition/le chargement de chaque diapositive ou toute autre suggestion que vous auriez.

J'utilise ruby on rails comme langage back-end.

L'url de l'emblème change de façon programmatique lorsqu'elle est entrée à partir d'un backoffice administratif et change sur chaque article/page mais vous trouverez ci-dessous un exemple :

Page.html

//button to click to make modal appear
<a class="btn btn-primary" onclick="loadModal()" id="socialStoryModal">
      load modal
</a>

Chargement de la modale avec Hubspot Messenger dans page.js

function loadModal() {  
      var msg;
      msg = Messenger().post({
        message:  'modal.html.erb',/see below the carousel
        showCloseButton: true,
        hideAfter: false
      }); 
    }

modal.html.erb = Modal avec le carrousel et les embeds sociaux (ici il peut y en avoir jusqu'à 50)

<div id="embeds-carousel" class="carousel slide" data-ride="carousel" data-interval="false">

    <div class="carousel-inner" role="listbox">    

         <div class="item active" id="item1" >
    <script>
var url = « https://api.instagram.com/oembed?url=https://www.instagram.com/p/5456544654565/";
embed_request = {
      url: url,
      dataType: "jsonp",
      cache: false,
      success: function (data) {
        try {
          var embed_html = data.html;
          $( "div#item1").html(embed_html);
        } catch (err) {
          console.log(err);
        }
      }
    }; 
$.ajax(embed_request);
</script>
</div>

  <div class="item" id="item2" >
    <script>
var url = "https://publish.twitter.com/oembed?url=https://twitter.com/coca/status/546664465342324"; 

embed_request = {
      url: url,
      dataType: "jsonp",
      cache: false,
      success: function (data) {
        try {
           var embed_html = data.html;
          $( "div#item2").html(embed_html);
        } catch (err) {
          console.log(err);
        }
      }
    };  
$.ajax(embed_request);
</script>
</div>

<div class="item" id="item3" >
    <script>
var url = "https://publish.twitter.com/oembed?url=https://twitter.com/muse/status/65353453F"; 

embed_request = {
      url: url,
      dataType: "jsonp",
      cache: false,
      success: function (data) {
        try {
           var embed_html = data.html;
          $( "div#item3").html(embed_html);
        } catch (err) {
          console.log(err);
        }
      }
    }; 
$.ajax(embed_request);
</script>
</div>

<div class="item" id="item4" >
    <script>
var url = « https://api.instagram.com/oembed?url=https://www.instagram.com/p/cftzezeker5/";
embed_request = {
      url: url,
      dataType: "jsonp",
      cache: false,
      success: function (data) {
        try {
          var embed_html = data.html;
          $( "div#item4").html(embed_html);
        } catch (err) {
          console.log(err);
        }
      }
    };  
 $.ajax(embed_request);
 </script>
</div>

<div class="item" id="item5" >
    <script>
var url = « var url = "https://www.facebook.com/plugins/post/oembed.json/?url=https://www.facebook.com/cocacola/posts/fdgyez556Yds";
";
embed_request = {
      url: url,
      dataType: "jsonp",
      cache: false,
      success: function (data) {
        try {
          var embed_html = data.html;
          $( "div#item5").html(embed_html);
        } catch (err) {
          console.log(err);
        }
      }
    };  
 $.ajax(embed_request);
</script>
</div>

and so on…
 </div>
  <!-- Controls -->
  <a class="left carousel-control" href="#embeds-carousel" role="button" data-slide="prev">
    <i class="fa chevron fa-chevron-left "></i>
    <span class="sr-only">Previous</span>
  </a>
  <a class="right carousel-control" href="#embeds-carousel" role="button" data-slide="next">
    <i class="fa chevron fa-chevron-right "></i>
    <span class="sr-only">Next</span>
  </a>

</div>

J'ai vu des tonnes de bibliothèques pour charger paresseusement des images et même parfois des scripts/iframes mais ils ont tous besoin d'avoir directement ajouté certaines classes dans le bloc, ce qui n'est d'aucune aide pour moi car j'utilise oembed ci-dessus et je n'ai nulle part où mettre ces classes paresseuses.

Je dois le faire fonctionner avec ces iframes oEmbeds.

7voto

ablopez Points 754

Pour charger paresseusement les embeds, vous devez les ajouter à un tableau plutôt que de les rendre dans le DOM, et une fois qu'ils ont tous été chargés (avec succès ou non), vous pouvez utiliser ce tableau pour ne rendre dans le DOM que la diapositive actuelle.

Voici un exemple :

var oEmbedUrls = [
  'https://api.instagram.com/oembed?url=https://www.instagram.com/p/5456544654565/',
  'https://publish.twitter.com/oembed?url=https://twitter.com/coca/status/546664465342324',
  'https://publish.twitter.com/oembed?url=https://twitter.com/muse/status/65353453F',
  'https://api.instagram.com/oembed?url=https://www.instagram.com/p/cftzezeker5/',
  'https://www.facebook.com/plugins/post/oembed.json/?url=https://www.facebook.com/cocacola/posts/fdgyez556Yds'
];

var oEmbedsHtml = [];
var doneCount = 0;
var currentSlideIndex;

$.each(oEmbedUrls, function(i, url){
    $.ajax({
      url: url,
      dataType: "jsonp",
      cache: false,
      success: function (data) {
        var itemIndex = oEmbedsHtml.length;
        oEmbedsHtml.push(data.html);
        $('#embeds-carousel .carousel-inner').append('<div class="item" id="item' + itemIndex + '"></div>');
        oEmbedUrlResponded();
      },
      error: function(){
        console.warn('oEmbed URL could not be loaded: ', url);
        oEmbedUrlResponded();
      }
    }
});

function renderEmbedSlide(index){
  currentSlideIndex = index;
  $('#item' + index).html(oEmbedsHtml[index]);
}

function oEmbedUrlResponded(){
  doneCount ++;

  // Check if all the URLs have been loaded (successfully or not) when we can now render the carousel and the first slide as well
  if(doneCount == urls.length){
    renderEmbedSlide(0); // Render the first embed
    /*** CALL HERE THE CODE TO ACTIVATE THE CAROUSEL COMPONENT ***/
  }
}

Enfin, vous devrez ajouter un crochet à votre composant carrousel pour que renderEmbedSlide(index) est appelée chaque fois que la diapositive est changée par le carrousel, en s'assurant que l'index (basé sur zéro) de la nouvelle diapositive est passé comme paramètre à la fonction.

Il se peut que vous deviez également ajouter une largeur et une hauteur minimales par défaut à l'adresse de l'utilisateur. .carousel-inner .item Classe CSS permettant au composant carrousel de connaître les dimensions à l'avance, car les diapositives (embeds) seront chargées paresseusement par la suite.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X