Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript looping over items and swapping out items into HTML

I'm using the following code i found from CodePen ... Im terrible at JS and I was hoping someone could help me out.

  1. How do I make it so the items don't repeat, at the moment, they scroll forever with 20 to a 'page' before the infinite scroll kicks in, what i would like is if there is 50 images in the array, then display those images, 20 to a page and then stop.
  2. I want to put the JS in a seperate file and then use PHP to loop over some results and output the images, is it possible to somehow move the div that is rendering the images out of the javascript function? so that i can put them in actually in the block in the html?

This is the code i have in the HTML portion

<div id="SlideMiddle">
    <div id="grid">
        <div id="grid-content"></div>
    </div>
</div>

and this is the javascript

<script>
    var Imgs = [
        'https://tympanus.net/Development/GridLoadingEffects/images/1.jpg',
        'https://tympanus.net/Development/GridLoadingEffects/images/3.jpg',
        'https://d13yacurqjgara.cloudfront.net/users/64706/screenshots/1167254/attachments/152315/SUGARSKULL-01.png',
        'https://tympanus.net/Development/GridLoadingEffects/images/8.jpg',
        'https://tympanus.net/Development/GridLoadingEffects/images/10.png',
        'https://tympanus.net/Development/GridLoadingEffects/images/14.png',
        'https://tympanus.net/Development/GridLoadingEffects/images/9.jpg',
        'https://tympanus.net/Development/GridLoadingEffects/images/13.png',
        'https://tympanus.net/Development/GridLoadingEffects/images/12.png',
        'https://tympanus.net/Development/GridLoadingEffects/images/4.jpg',
        'http://www.thedrum.com/uploads/news/172673/DzrMPF_DeezerPoster_MusicSoundBetterWithYou_03.jpg'
    ];

    $(document).ready(function(){
        $grid = $('#grid-content');

        $.fn.revealItems = function($items){

            var iso = this.data('isotope');
            var itemSelector = iso.options.itemSelector;
            $items.hide();
            $(this).append($items);
            $items.imagesLoaded().progress(function(imgLoad, image){
                var $item = $(image.img).parents(itemSelector);
                $item.show();
                iso.appended($item);
            });

            return this;
        }
        $grid.isotope({
            containerStyle: null,
            masonry:{
                columnWidth: 300,
                gutter: 15
            },
            itemSelector: '.grid-item',
            filter : '*',
            transitionDuration: '0.4s'
        });


        $grid.imagesLoaded().progress(function(){
            $grid.isotope();
        })

        function GenerateItems(){
            var items = '';
            for(var i=0; i < 20; i++){
                items += '<div class="grid-item c'+(i%9)+' wow fadeInUp" ><a href=""><img src="'+Imgs[i%Imgs.length]+'" /></a></div>';
            }
            return $(items);
        }

        // SimpleInfiniteScroll
        function Infinite(e){
            if((e.type == 'scroll') || e.type == 'click'){
                var doc = document.documentElement;
                var top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
                var bottom = top + $(window).height();
                var docBottom = $(document).height();

                if(bottom + 50 >= docBottom){
                    $grid.revealItems(GenerateItems());
                }
            }
        }

        $grid.revealItems(GenerateItems());

        $(window).resize(function(){
            var margin=40;
            var padding=15;
            var columns=0;
            var cWidth=300;
            var windowWidth = $(window).width();

            var overflow = false;
            while(!overflow){
                columns++;
                var WidthTheory = ((cWidth*columns)+((columns+1)*padding)+margin);
                if(WidthTheory > windowWidth)
                    overflow = true;
            }
            if(columns > 1)
                columns--;

            var GridWidth = ((cWidth*columns)+((columns+1)*padding)+margin);

            if( GridWidth != $('#grid').width()){
                $('#grid').width(GridWidth);
            }
        });
        $(window).scroll(Infinite);
        new WOW().init();

    })
</script>
like image 384
BigJobbies Avatar asked Nov 22 '17 03:11

BigJobbies


1 Answers

Images Repeating

There are two things contributing to the image repeating behavior. First, as pointed out in another answer, the loop counter is hard coded to 20. So if you pass in five images, each will repeat four times. Changing 20 to the length of the Imgs array will prevent this.

Second, the GenerateItems() function always returns results.

if there is 50 images in the array, then display those images, 20 to a page and then stop

This implies that GenerateItems() will need to return an empty set (or not be called) after all 50 images have been displayed. A naive approach might involve a global page counting variable. In this codepen, I added such a variable to limit the number of pages, like so:

var pagesServed = 0;

$(document).ready(function(){ 
    $grid = $('#grid-content');
.....
function GenerateItems(){
    console.log("generating items");
    var items = '';
    if (++pagesServed > 2) {
       return items; 
    }
    for(var i=0; i < Imgs.length; i++){
      ....

Server side rendering

In a real life use case, you're probably fetching this list of image links from your server, which ties into the second part of your question.

You can easily render these divs on the server side instead. The GenerateItems() function would make an AJAX call to your back end to get the divs, rather than building them in javascript. That PHP code might look something like this:

<?php
require_once __DIR__.'/vendor/autoload.php';

session_start();

$Imgs = [
    'https://tympanus.net/Development/GridLoadingEffects/images/1.jpg',
    'https://tympanus.net/Development/GridLoadingEffects/images/3.jpg',
    'https://d13yacurqjgara.cloudfront.net/users/64706/screenshots/1167254/attachments/152315/SUGARSKULL-01.png',
    'https://tympanus.net/Development/GridLoadingEffects/images/8.jpg',
    'https://tympanus.net/Development/GridLoadingEffects/images/10.png',
    'https://tympanus.net/Development/GridLoadingEffects/images/14.png',
    'https://tympanus.net/Development/GridLoadingEffects/images/9.jpg',
    'https://tympanus.net/Development/GridLoadingEffects/images/13.png',
    'https://tympanus.net/Development/GridLoadingEffects/images/12.png',
    'https://tympanus.net/Development/GridLoadingEffects/images/4.jpg',
    'http://www.thedrum.com/uploads/news/172673/DzrMPF_DeezerPoster_MusicSoundBetterWithYou_03.jpg'
];

$items = '';

for ($i=0; $i < 20; $i++){
    $items .= '<div class="grid-item c' . ($i % 9) . ' wow fadeInUp" ><a href=""><img src="' . $Imgs[$i % count($Imgs)] . '" /></a></div>';
}
header('Access-Control-Allow-Origin: *');
printf($items);

Then GenerateItems() would look roughly like this:

  function GenerateItems(){
      console.log("generating items");
      var fetched =  fetch('http://localhost:8000').then(function(data) {
          return data.text();
      });

      return fetched;
    }

And revealItems is modified to deal with the Promise:

$.fn.revealItems = function($items){
    var self = this;
    var iso = this.data('isotope');
    var itemSelector = iso.options.itemSelector;
    $items.then(function($fetcheditems) {
        console.log($fetcheditems);
        $($fetcheditems).hide();
        $(self).append($fetcheditems);
        $($fetcheditems).imagesLoaded().progress(function(imgLoad, image){
            var $item = $(image.img).parents(itemSelector);
            $item.show();
            iso.appended($item);
        });
    });
    return this;
}

I put an example that renders these divs on the server side on GitHub. Disclaimer - It's a minimal example - I didn't bother getting the WOW styling to work, and the CORS support is minimal (e.g. no Access-Control-Allow-Credentials header is set).

You'd need to implement your own server side logic to decide which images to return on each call. For example, you could use session to keep track of which ones have already been served, or you could accept query string parameters that define the range of images being requested.

like image 185
Mike Patrick Avatar answered Oct 09 '22 15:10

Mike Patrick