Jump to content

Making a loading more link which displays more results with AJAX


Orkun
 Share

Recommended Posts

Let's say I have 500 Eventpages or more with differen content fields(date, title, textarea etc..).

I would display all events in a list like this:

$events = $pages->find("template=event, limit=10");

echo "<div class='event-container'>";

foreach($events as $event){
    echo "<div class='event-detail'>
          <h1>$event->title</h1>
          <p>$event->short_description</p>
          </div>";

}
echo "<a class='load-more'>LOAD MORE</a>";
echo "</div>";

Now I want to make the load-more link to display 10 or 20 more events without reloading the page and showing a loading gif/text while its rendering the other events, when clicking on it . How can i achieve this? I know that i could use pagination for displaying this heavy amount of results but the customer doesn't want that because it don't fit in the design of the website. Can I probably achieve a combination with Pagination and Ajax, or are there other ways to do it?

Link to comment
Share on other sites

You may use one of those ready to use JS Libraries for Infinite Scrolling you can found on the net. One that I know and have used myself is IAS.

In PW you must use pagination as you explained above, also have to render the NEXT button, but with display:none in CSS to make it invisible. The JS-Script will pick it up and loads the next portion when the user scrolls down.

  • Like 4
Link to comment
Share on other sites

You may use one of those ready to use JS Libraries for Infinite Scrolling you can found on the net. One that I know and have used myself is IAS.

In PW you must use pagination as you explained above, also have to render the NEXT button, but with display:none in CSS to make it invisible. The JS-Script will pick it up and loads the next portion when the user scrolls down.

I have never really delved in to this, but would love to see a fully realized example using this method. I often stumble over how one manages manual page selection by the user for seo purposes. I would love to have a page with a combination of pagination and infinite scrolling. 

  • Like 2
Link to comment
Share on other sites

I have used it only one times. If it is of any help, I can paste in some code snippets here from that site. But it isn't an infinite only solution, it is bundled together with masonry.

http://joerg-hempel.com/archiv/

JS parts:

// JS in every page that uses infinite scrolling
<script type='text/javascript'>
    var gLoaded = 0;
    var gMaxPages = 12;
    var gTriggerPageThreshold = 100;
    var gPaginationHistory = false;    // switch on / off URI updating for pages: example.com/path/page2 | /page3 | page4
    var gContainer = '#albums';
    var gItemSelector = 'article.album';
    var gColumnWidth = 228;         // 48
    var gGutter = 12;               // 12

    $(document).ready(function() {
        // make it visible if JS is supported
        $('div.ias_msg').css('display','block');
        starteMasonry();
        starteIAS();
    });
</script>

in an external JS file I have the functions for Masonry and IAS:

function starteIAS() {
    jQuery.ias({
        container            : gContainer,
        item                 : gItemSelector,
        pagination           : '.pagination',
        next                 : 'a.next-album',
        loader               : "<img src='/site/templates/styles/images/loader.gif' />",
        thresholdMargin      : -9,
        triggerPageThreshold : gTriggerPageThreshold,
        history              : gPaginationHistory,
        noneleft             : "<div class='ias_msg noneleft'><p>no more items available</p></div>",

        onLoadItems          : function(items) {
          // HNLOG
          console.log('IAS onLoadItems (' + gTriggerPageThreshold + ')');
            var newElems = $(items).show().css({ opacity:0 });
            newElems.imagesLoaded(function(){
                $('#albums').masonry('appended', newElems);
                newElems.animate({ opacity:1 });
            });
            $('#albums').masonry('reloadItems');
            return true;
        }
    });
}

function starteMasonry() {
    var items = $(gContainer + ' ' + gItemSelector).show().css({opacity:0});
    $(gContainer).masonry({
        itemSelector         : gItemSelector,
        isOriginLeft         : true,
        isOriginTop          : true,
        columnWidth          : gColumnWidth,
        gutter               : gGutter,
        isAnimated           : true,        // !Modernizr.csstransitions
        isFitWidth           : true
    });
    items.animate({opacity:1});
}

The PHP looks like:

// calculate current amounts
$limit = 100;
$max	= $pages->find("$pSelector,limit=2")->getTotal();
$cur	= $input->pageNum;
$next   = ($cur * $limit) < $max ? $cur + 1 : 1;
$prev   = $cur > 1 ? $cur - 1 : 0;
$start  = $cur < 2 ? '0' : strval($limit * ($cur -1));

    // echo prev-next links for pagination  (only next is required, prev isn't used !!)
    $pagination = "<div style='display:none' class='pagination'>";  // hide it !!
        //if($prev > 0) $pagination .= " <a href='{$archivURL}page{$prev}'>prev</a> |";
        if($next > 1) {
            if(isset($nextPageUrl)) {
                $pagination .= " <a class='next-album' href='{$nextPageUrl}page{$next}'>next</a> ";
            } else {
                $pagination .= " <a class='next-album' href='{$archivURL}page{$next}'>next</a> ";
            }
        }
    $pagination .= "</div>\n";
    echo $pagination;

    // Hinweis zum scrollen
    echo "<div class='ias_msg scrolldown".($cur)."'><p>scroll down to get more items</p></div>";

    // get PageArray
    $albums = $pages->find("$pSelector, limit=$limit, start=$start, sort=sort");

    // output albums with thumbnail and infos
    foreach($albums as $album) {
        // ... render items
    }

Using IAS, you even don't need to check for ajax request or not. just send the whole page, with header and body. The script knows the selectors and pick up the needed content and add it to the dom, after the last renderd from previuos request. Easy!

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Liam88
      Hi,
      I'm really struggling with this as it's something not in my wheelhouse. I'm creating a blog style page (a grid of cards) which has attributes.
      I have a snip of javascript which grabs values from checkboxes which are put into a value like the below:
      ?content=static_video&channel=facebook-ads_instagram-ads
      document.querySelector("form").onsubmit=ev=>{ ev.preventDefault(); let o={}; ev.target.querySelectorAll("[name]:checked").forEach(el=>{ (o[el.name]=o[el.name]||[]).push(el.value)}) console.log(location.pathname+"?"+ Object.entries(o).map(([v,f])=> v+"="+f.join("_")).join("&") ); document.location.href = location.pathname+"?"+ Object.entries(o).map(([v,f])=> v+"="+f.join("_")).join("&"); } As I'm currently refeshing the page on button click with those values the end result includes the location but can easily remove this.
      I then use this value in "input->get" to get the values which I then append to a find() rule. See code below:
      $selector = "template='adbank_pages',sort=published,include=all,status!=hidden"; // Get the channel and content inputs $channel = $input->get->channel; $content = $input->get->content; if($channel){ // Grab the channel string, explode into an array for checkbox checking and then replace _ with | to create or rules in the selector. $chanArray = explode("_", $channel); $chan = $channel = str_replace('_', '|', $channel); $selector = $selector .= ",ab_channels=$chan"; } if($content){ // Grab the content string, explode into an array for checkbox checking and then replace _ with | to create or rules in the selector. $contArray = explode("_", $content); $cont = $content = str_replace('_', '|', $content); $selector = $selector .= ",ab_content=$cont"; } if($input->get){ // If a valid input result $all = $pages->find($selector); } }else{ // If no input show them all $all = $page->children("template='adbank_pages',sort=-published,include=all,status!=hidden"); } $items = $all->find("limit=12"); // Limit the output and use pagination As mentioned above I currently refresh the page to adjust the $selector filter within the $all with a fallback $all if there are no results.
      I know I need to use AJAX to filter the content without refresh but I am really struggling with the set up. I have read multiple posts including the original by Ryan but still confused.
      If anyone can direct/help on this it would be appreciated.
      Thank you
    • By fruid
      $limit = 12; $start = $limit * ($input->pageNum() - 1); $allcasts = pages("template=cast"); $casts = $allcasts->find("has_parent=$page, sort=$sort"); $casts = sortOutEmpty($casts, $decider); $casts->setTotal($casts->count()); $casts->setStart($start); $casts->setLimit($limit); // just to test echo $casts->getStart(); // 0 or 12 or 24 or 30 respectively echo $casts->getLimit(); // 12 echo $casts->getTotal(); // 31 or whatever the total echo casts($casts); // never mind this, it's just for markup creation and works fine $pager->render($casts, $pagerOptions); // I store the name of a specific field as a string in a variable so I can dynamically sort out content of which that field is empty in the current language  function sortOutEmpty($items, $decider) {     $casts = new PaginatedArray;     foreach ($items as $item) :         if ($item->$decider != '') :             $casts->add($item);         endif;     endforeach;     return $casts; } I get the right number of pages in the pager. Pager works but the results never paginate.
      This pagination API is driving me nuts, it just doesn't work!
      I can't be the only one who's having issues with this, it's hard to find any topic where issues are discussed and the API-documentation is, as usual, very laconic.
      Thanks for help!
    • By fedeb
      Hi,
      I am trying to style the pager navigation bar based on a simple example I found on bootstrap:
      <nav aria-label="..."> <ul class="pagination"> <li class="page-item disabled"> <a class="page-link" href="#" tabindex="-1" aria-disabled="true">Previous</a> </li> <li class="page-item"><a class="page-link" href="#">1</a></li> <li class="page-item active" aria-current="page"> <a class="page-link" href="#">2</a> </li> <li class="page-item"><a class="page-link" href="#">3</a></li> <li class="page-item"> <a class="page-link" href="#">Next</a> </li> </ul> </nav> The code I am using is the following:
      <?php echo $entries->renderPager(array( 'nextItemLabel' => "Next", 'previousItemLabel' => "Prev", 'listMarkup' => "<ul class='pagination'>{out}</ul>", 'itemMarkup' => "<li class='page-item'>{out}</li>", 'linkMarkup' => "<a class='page-link' href='{url}'>{out}</a>", 'currentItemClass' => "page-item active", )); ?> which renders this result: the current page is not styled!

      If I run the original bootstrap example everything works fine, but not through the renderPager options. The problem seems trivial but since I am new to ProcessWire (also to web design) I cannot find it! My main reference is this one.
      Thanks in advance!
       
    • By fruid
      I'm having and always have a hard time building PaginatedArrays, I never know where to put the "limit=24" selector so please enlighten me.
      Here's what I'm doing…
      $categories = $page->protable('start=0, limit=999999'); // this I need in order to retrieve the pages's "categories" and I don't know how to make use of $rows instead for that purpose because of this confusing limit-API $rows = $page->protable; // put ("limit=20") here? $custom = buildSelector($input, $rows); // this function returns an array of selectors depending on the user input $items = new PaginatedArray; // or here? // or here? $items->find("limit=20") // or like this? $items("limit=20") // or like this? $items = $items("limit=20") // or like this? $items = $items->find("limit=20") foreach ($rows as $r) : if ($custom->get('selector')->matches($r)) : $items->add($r); endif; endforeach; // or at this point? and then
      if ($items) { // or maybe somewhere here?     echo '<span class="grey">'.$items->getPaginationString(array(     'label' => 'entries',     'zeroLabel' => '0 entries', // 3.0.127+ only     'usePageNum' => false,     'count' => count($items),     'start' => $items->getStart(),     'limit' => count($items),     'total' => $items->getTotal()     )); and then of course…
      $pager = $modules->get("MarkupPagerNav"); echo '<div class="uk-flex uk-flex-center">'.$pager->render($items, $options).'</div>'; I'm out of ideas and confused cause it doesn't make sense to me either way.
      ____
      The buildSelector function above returns and array…
      $selected = new Selectors("$letter, $searchterm, $category"); $custom = new Wirearray; $custom->set('selector', $selected); $built->set('sort', $sort); return $custom; and each of the new selectors are basically strings ("category=whatever")
      Also, you cannot put the "sort=title" or whatever as a selector for the Selectors function (see above). Why, I know not.
      I don't know if that is the proper way but selecting kind of works now as opposed to many other ways I tried. Selectors always require a lot of trial and error, it seems to have a very sensitive API, always depends on double quotes, single quotes and how you concatenate.
      Thanks for help!
    • By picarica
      Hello si have this gallery, pretty good website, but yesterday client uploaded over 3000 images oto the site, and it cannot handle filtering them out and showing them at the same time , i wanted some simple pagination maybe infinite scrool or onclikc load whatever, but i cannot seem to implement infinite ajax scrool and any other JS methods, nut sure why i still got stuck at the next method, like there is not next page.
      so i wanted to implement PW method of paginating i wanted to use MarkupPagerNav
      so far i have  this code for outputting images
      $pa = $pages->find("template=basic-page|art_gallery, images.tags!=''"); /* $pa = $pages->find("has_parent!=2,id!=2|7,status<".Page::statusTrash.",include=all"); */ echo "<div class='js-filter' id='gal' >"; /* row gtr-50 gtr-uniform */ $frame = $pages->get('/settings/')->watermark; foreach ($pa as $p) { foreach($p->images as $image) { if(!$image->hasTag("act")) { $options = array('quality' => 80, 'upscaling' => true, 'cropping' => 'north', 'sharpening'=>'medium'); $large = $image->size(1200, 0, $options); $wmImage = $large->pim2Load('wm1', ['quality'=>80, 'upscaling' => true, 'sharpening'=>'medium', 'defaultGamma'=>-1])->watermarkLogo($frame, $position='se',$padding=1.5)->pimSave(); /* zmazanie variacii, treba odpoznakovat ked sa menia nastavenie vyssie */ /* $image->pim2Load('wm1')->removePimVariations(); */ $thumb = $image->size(400, 300, $options); echo "<div class='$image->tags grid-item' style=''>"; echo "<span style='overflow:hidden;'class='image fit'>"; echo "<a class='hvr-reveal' href='$wmImage->url'>"; echo "<img uk-scrollspy='cls: uk-animation-fade; repeat: false' src='$thumb->url' alt='$image->tags'>"; echo "</a>"; echo "</span>"; echo "</div>"; } else { $options = array('quality' => 80, 'upscaling' => true, 'cropping' => 'north', 'sharpening'=>'medium'); $large = $image->size(1200, 0, $options); $wmImage = $large->pim2Load('wm2', ['quality'=>80, 'upscaling' => true, 'sharpening'=>'medium', 'defaultGamma'=>-1])->pixelate(25)->smooth(255)->watermarkLogo($frame, $position='se',$padding=1.5)->pimSave(); /* zmazanie variacii, treba odpoznakovat ked sa menia nastavenie vyssie */ /* $image->pim2Load('wm2')->removePimVariations(); */ $thumb = $image->size(400, 300, $options); echo "<div class='$image->tags blur grid-item' style=''>"; echo "<span style='overflow:hidden;'class='image fit'>"; echo "<a class='hvr-reveal' href='$wmImage->url'>"; echo "<img uk-scrollspy='cls: uk-animation-fade; repeat: false' src='$thumb->url' alt='$image->tags'><span>18+</span>"; /* <span>BY OPENING THIS IMAGE YOU CONSET THAT YOU'RE 18 YEARS OR OLDER</span> text copyraightova,y dat vedla obrazky potom */ echo "</a>"; echo "</span>"; echo "</div>"; } } }; to put it  simply, it first searches for sites, and then outputs all images from those sites, pretty simple, it also uses watermarking and uikit filtering
      i have filtering done like this
      $num = 1; echo "<ul class='uk-subnav uk-subnav-pill'>"; foreach(array_unique($alltags) as $key => $tag) { echo"<li uk-filter-control='filter: .$tag;group: $num' class='butt$num' uk-toggle='target: .butt$num ; animation: uk-animation-fade; queued: true'><a href='#'>$tag</a></li>"; echo"<li uk-filter-control='group: $num' class='butt$num active' aria-hidden='true' hidden='' uk-toggle='target: .butt$num; animation: uk-animation-fade'><a href='#'>remove - $tag</a></li>"; $num++; } echo "</ul>"; simple, but i have NO idea how to implement pagination, just because it seems to work that it like find all images, and stores with limit, and then just paginates them, but i cannot apply this method in my code.
      any idea how to make any JS inifite scroll work ? or just how to make this work ? with my setup, or with some modifications, it just have to work as is now
×
×
  • Create New...