5
votes

I am using the isotope plugin (http://isotope.metafizzy.co/) with the infinite ajax scroll plugin (https://github.com/webcreate/infinite-ajax-scroll). The infinite scroll works great with the isotope filtering, however, I want to load more items into the container when a filter has been applied so that there are always 50 items being displayed.

I have the below code but am stuck at the point of loading the new items with ajax.

So every time a filter is selected, I calculate how many items are currently displayed out of 50. I then need a way to get more items using ajax and calling the same page (index.php). I imagine I need to do something similar to the infinite ajax scroll plugin in order to get the next pages results. I am not that experienced with JQuery and so am struggling to figure out exactly what their code is doing and how to implement something similar to this for my filtering.

I have tried using $.get but this loads the whole of the index.php page within the container instead of just getting the results.

I would be grateful for any help with this.

<?php

require_once('config/config.php');

$cat = (isset($_GET['cat']) ? urldecode($_GET['cat']) : '');
$type = (isset($_GET['type']) ? urldecode($_GET['type']) : '');

//get filter lists
$categories = StoreDiscounts::getCategories();
$types = StoreDiscounts::getDiscountTypes();

//get total number of discounts for search
$total_items = StoreDiscounts::countitems($cat, $type);
//pagination  - infinate scrolling
$pagelimit = 50; //items per page
$page = (int) (!isset($_GET['p'])) ? 1 : $_GET['p'];
$start = ($page * $pagelimit) - $pagelimit;
$limit = $pagelimit * $page;

if ($total_discounts > ($page * $limit)) {
    $next = ++$page;
}

//get items
$items = StoreDiscounts::getitems($cat, $type, $start, $limit);

?>
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <link rel="stylesheet" href="public/css/normalize.css">
    <!--[if (gt IE 8) | (IEMobile)]><!-->
    <link rel="stylesheet" href="public/css/style.css">
    <!--<![endif]-->
    <!--[if (lt IE 9) & (!IEMobile)]>
    <link rel="stylesheet" href="public/css/ie.css">
    <![endif]-->
    <script type="text/javascript" src="public/js/modernizr.js"></script>  
    <title>E-Store Offers.</title>
</head>
<body>
<!--#outer-wrap-->
<div id="outer-wrap">
<!--#inner-wrap-->
<div id="inner-wrap">
    <!--#header-->
    <header id="top" role="banner">
        <div class="block">
            <a class="nav-btn" id="nav-open-btn" href="#nav">Filters</a>
        </div>

    </header>
    <!--/#header-->
    <!--#filters-->
    <nav id="nav" role="navigation">
        <div class="block">
            <section id="options" class="clearfix combo-filters">
            <h3>Filters</h3>
            <p><a href="#" data-filter-value="*">[ Clear filters ]</a></p>
            <div class="option-combo categories">
                <h4>Categories</h4>
                <ul class="filter option-set clearfix" data-filter-group="cat" data-option-key="filter">
                    <?
                    echo '<li><a href="#filter-category-all" data-filter-value="" class="selected">All</a></li>';
                    foreach ($categories as $category) {
                        $category_class = functions::sanitize($category);
                        echo '<li><a href="#filter-category-'. $category_class . '" data-filter-value=".' . $category_class . '">' . $category . '</a></li>';
                    }
                    ?>
                </ul>
            </div>
            <div class="option-combo types">
                <h4>Type</h4>
                <ul class="filter option-set clearfix" data-filter-group="type" data-option-key="filter">
                <?
                echo '<li><a href="#filter-type-all" data-filter-value="" class="selected">All</a></li>';
                foreach ($types as $type) {
                    $type_class = str_replace(' off', '', strtolower($discount_type));
                    echo '<li><a href="#filter-type-' . $type_class . '" data-filter-value=".' . $type_class . '">' . $discount_type . '</a></li>';
                }
                ?>
                </ul>
            </div>

            </section>
            <a class="close-btn" id="nav-close-btn" href="#top">Return to Content</a>
        </div>
    </nav>
    <!--/#filters-->
    <!--#main content area-->    
    <div id="main" role="main">
        <!--#container for tiles--> 
       <div id="container">
                <?php

                foreach ($items as $id => $item) {

                        echo "<div class=\"element $typ $categoryisotope-item\"  data-type=\"$typ\" data-category=\"$category\" >";
                        <h4>$item[name]</h4>
                        <p class=\"category\">$item[cat]</p>
                        <img src=\"$item[url]\" width=\"230\" height=\"175\" alt=\"$item[name]\">";
                        echo " <p>$item[description]</p>";
                        echo "</div>\n";
                    }
                ?>
            </div>
        <!-- /#container for tiles -->
           <!--#pagination-->
                <?php if (isset($next)): ?>
                <div class="paginate">
                  <?php
                  echo "<a href=\"index.php?p=$next";
                  if($cat !=''){
                    echo "&cat=$cat";
                  }
                  if($type !=''){
                    echo "&type=$type";
                  }
                  echo "\">Next</a>";
                  ?>
                </div>
                <?php endif?>
                <!--/#pagination-->
    </div>
    <!--/#main content area-->
</div>
<!--/#inner-wrap-->
</div>
<!--/#outer-wrap-->

<!--/#footer-->
<footer>
    FOOTER
</footer>
<!--/#footer-->
<script src="public/js/main.js"></script>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script type="text/javascript" src="public/js/jquery.isotope.min"></script>
        <script type="text/javascript" src="public/js/jquery-ias.min.js"></script>
        <script type="text/javascript" src="public/js/MetroJs.js"></script>
        <script>

           var displayItemsNo = 50;


           $(document).ready(function() {               

                //isotope
                var $container = $('#container'),
                filters = {};
                $container.isotope({
                    itemSelector: '.element',
                });



                // filter buttons
                $('.filter a').click(function(e) {
                    var $this = $(this);
                    // don't proceed if already selected
                    if ($this.hasClass('selected')) {
                        return;
                    }

                    var $optionSet = $this.parents('.option-set');

                    // change selected class
                    $optionSet.find('.selected').removeClass('selected');
                    $this.addClass('selected');



                    // store filter value in object
                    var group = $optionSet.attr('data-filter-group');
                    filters[ group ] = $this.attr('data-filter-value');
                    // convert object into array
                    var isoFilters = [];
                    for (var prop in filters) {
                        isoFilters.push(filters[ prop ])
                    }
                    //show filters
                    var selector = isoFilters.join('');

                    //count how many results after filter
                    $container.isotope({filter: selector}, function($changedItems, instance) {
                        instance.$allAtoms.removeClass('is-filtered');
                        var itemsno = (instance.$filteredAtoms).length;
                        instance.$filteredAtoms.addClass('is-filtered');

                        if(itemsno < displayItemsNo){
                           //get more items to make up 50
                            var moreno = displayItemsNo - itemsno;


                            /******WHAT DO I DO HERE?  SOMETHING LIKE THE BELOW?
                            var getQuery = 'index.php?cat=??&type=??';

                            $.get(getQuery, null, function (data) {
                                $container.isotope('insert', data)
                                });
                            ********/    

                        }

                    });

                    //pass filter to next link for infinate scroll
                    //var filter_qry = $this.attr('href');
                    var filter_qry = $(e.target).text();

                    var paginate_url = $( '.paginate a ').attr('href');

                    if(filter_qry == 'All'){
                        filter_qry = '';
                    }
                    var next_url = UpdateQueryString(paginate_url, group, encodeURIComponent(filter_qry));

                    $(".paginate a").attr("href", next_url);

                    return false;
                });
                //end isotope

                // Infinite Ajax Scroll configuration
                jQuery.ias({
                  container : '#main', // main container where data goes to append
                  item: '.element', // single items
                  pagination: '.paginate', // page navigation
                  next: '.paginate a', // next page selector
                  loader: '<img src="public/img/ajax-loader.gif"/>', // loading gif
                  loaderDelay: 200,
                  thresholdMargin: -600,     
                  noneleft: 'No more items', //Contains the message to be displayed when there are no more pages left to load
                  triggerPageThreshold: '10', // show "load more" if scroll more than this to stop
                  trigger: "",
                  onLoadItems: function( newElements ) {
                      // hide new items while they are loading
                       var $newElems = $( newElements ).css({ opacity: 0 });
                       // ensure that images load before adding to isotope layout
                       $newElems.imagesLoaded(function(){
                       // show elems now they're ready
                        $newElems.animate({ opacity: 1 });
                        $container.isotope( 'insert', $newElems, true );
                      });
                     return true;
                   }
                });
                //end infinate
            });
        </script>
</body>
</html>

Many thanks, Leah

1
There are few points drawing my attention here. You might want to sanitize your input data (GET parameters could be anything and unless their properties are ensured by "countitems" and "getitems", I would not go further before having solved this potential security issue or the script might suffer from SQL injection). You might want to retrieve datasets (JSON documents for instance) instead of fully-integrated pages. In order to do, you shall use another PHP script dedicated to the production of these datasets consumed by the client-side of your application,Thierry Marianne
Otherwise you might want to let your PHP script to return only page fragments, and perhaps to use the .load function to fetch and insert the fragment. This would be far from being optimal but we could start from this. We shall have more exchanges if you would feel the need to.Thierry Marianne
Using a PHP script separated from your views (embedding HTML code and assets such as JavaScript or stylesheets) in order to return the datasets would help to improve the overall clarity of your application and might bring a better separation of concerns.Thierry Marianne
thanks for your comments, I am aware of what you have mentioned about using JSON and keeping PHP separate from the Jquery / html but due to time constraints am not going down that route.LeeTee

1 Answers

3
votes
        function loadMoreItems(getQuery) {
            $.get(getQuery, null, function(data) {
                container = $('#container', data).eq(0);
                if (container) {
                    var newItemsHTML = "";
                    newItemsHTML = $( container ).html();
                    var $newItems = $(newItemsHTML);
                    $('#container').isotope('insert', $newItems, true);
                }
            }, 'html');
        }