Tagfilter through ajax for slideshow

tags

#1

Hi,
I have a onepager where the kirbysites will be loaded as snippets.
Now I have in one snippet a slideshow which is created from subsites. And the subsites have tags as categories.
Now I will filter this slideshow through the tags. As I have a onepager i need to to this though ajax.
Normally I have do a lot with ajax callings in kirby, but here I have a problem to understand how I can get this work or I have to build it up with the tag-params.

I would appreciate if someone can explain me how i can get a tagfilter with ajax working.

Cheers


#2

Are you loading all slides in the first place? If so, you might as well just filter in the frontend without dealing with Ajax stuff.

With Ajax it is the same as always:

  • Your JS reads the value of the tag filter button
  • Your Ajax request sends the value to the server
  • In your controller, you read the value from your Ajax request and filter accordingly,
  • finally, you send back the response (the filtered collection) and
  • your JS injects replaces the original snippet with the new snippet

#3

Hi,
thanks for the quickl reply.
My problem is now the controller. Because I work with snippets I have no controllerfile.
This is my slideshowsnippet:

<?php
// fetch the basic set of pages
$page = $data;
$projects = $page->children()->visible();

// add the tag filter
if($tag = param('archivements')) {
    $projects = $projects->filterBy('archivements', $tag, ',');
}
?>

<section id="<?php echo $page->uri(); ?>" class="grid-wrap-fluid content-section <?php echo $page->uri(); ?>" >
    <header>
        <h1><?php echo $page->title()->html(); ?></h1>
    </header>
    <div class="valign-middle">
        <section class="slideshow-container">
ā€¦

and this my js:

    //tagfilter
    $(document).on('click', '.taglink', function(e){
        e.preventDefault();

        var archivement = $(this).attr('href');

        $.ajax({
            type: 'POST',
            url: archivement,
            success: function(response) {
                     var htmlFiltered = $(response).find('.slideshow-container').children();

                     $('.slideshow-container').children().fadeOut(function(){
                         $('.slideshow-container').children().remove;
                     })
                     $('.slideshow-container').html(htmlFiltered);
            }
        });
    });

and now it will load my complete sourcecode for this I filter the html output and if I see it right no Content is filtered.


#4

In your home template, call the snippet and pass the projects as arguments (do not define them in the snippet:

Snippet:

<!-- don't know why you don't use the $data variable but assign $data to the `$page` variable (unnecessary), I'm using $data here -->
<!-- I'd probably use a second snippet within this one that just deals with the slideshow and then call that also in the son container, so that we reduce the amount of data to send -->
<section id="<?php echo $data->uri(); ?>" class="grid-wrap-fluid content-section <?php echo $data->uri(); ?>" >
    <header>
        <h1><?php echo $data->title()->html(); ?></h1>
    </header>
    <div class="valign-middle">
        <section class="slideshow-container">
ā€¦

home.php

//.define $projects here, in addition to data
snippet('slideshow', ['projects' => $data->children()->visible()]);

Create a home.json.php template:

<?php 
// define the pages we want to fetch, getting the param from the AJAX request
$projects = page('whatever')->children()->visible();
if($param = kirby()->request()->data()['param'] ){ // fetching the data from the post request
  $prjects = $page('whatever')->filterBy('archivements', $param);
};
return snippet('slideshow', ['projects' => $projects]); // plus the rest of the variable you use in there, i.e. $data

Finally the jQuery stuff. Iā€™d use a data attribute to pass the tag value.

$(document).on('click', '.taglink', function(e){
  var tag = $(this).data('filter'); // get the value to filter by from a data-filter attribute
  var url = window.location.href + '.json'; // here we call the JSON representation (should be the home page url + .json

  $.ajax({
            type: 'POST',
            url: url,
            data: {param: tag}, // send the data with the post request
            success: function(response) {
              console.log(response);
                // do your replacement here
            }
        });
});

#5

Hello Sonja,
thank you very much for this detailed explanation.

I had problems to load the home.json.php because this I realised it with a plugin and a routing.

If someone have also problems here are my code:
config.php:

c::set('routes', array(
    array(
        'pattern' => 'api/tagfilter',
        'method' => 'POST',
        'action' => function() {
            $data = tagfilter(kirby()->request()->data());
            return response::json($data);
        }
    ))
));

inside the pluginfolder I created a folder with name: tagfilter an da php file with name tagfilter.php with this code:

<?php
function tagfilter($data){

    $page = page('projekte')->children()->visible();
    $param = kirby()->request()->data()['param'];

    if(empty($param)){ 
        $projects = $page; //fro reseting the Tag filter
    }
    else {
        $projects = $page->filterBy('achievements', $param);
    }

    return snippet('slideshow', array('projects' => $projects), true);
}

And the javascript:

// var archivement = $(this).attr('href');
        var archivement = $(this).data('filter'); // get the value to filter by from a data-filter attribute
        var url = 'api/tagfilter'; ///window.location.href + 'home.json.php'; // here we call the JSON representation (should be the home page url + .json

        $.ajax({
            type: 'POST',
            url: 'api/tagfilter',
            data: {param: archivement},
            dataType: 'html',
            beforeSend: function() {
                console.log('beforeSend: ' + JSON.stringify({param: archivement}));
                $('#spinnerContainer').toggleClass('fadeout fadein');
            },
            success: function(response) {
                console.log('Success: ' + JSON.stringify(response));

                $('#slideshowContainer').fadeOut('slow', function(){
                    $('#slideshowContainer').children().remove;
                    $('#slideshowContainer').html(response).promise().then(function(){
                        $('#textSlidshow').cycle({
                            speed: 600,
                            manualSpeed: 100,
                            timeout: 0,
                            next: '#next',
                            prev: '#prev',
                            fx: 'fade',
                            slides: '> article',
                            caption: '#slide-caption',
                            // captionTemplate: '{{slideNum}} / {{slideCount}}'
                        });

                        $('#imageSlideshow').cycle({
                            speed: 600,
                            manualSpeed: 100,
                            timeout: 0,
                            next: '#next',
                            prev: '#prev',
                            fx: 'fade',
                            slides: '> .nested-slideshow'
                        });

                        $('.inner-slideshow').cycle({
                            timeout: 0,
                            fx: 'fade',
                            prev: '.prevSubSlide',
                            next: '.nextSubSlide'
                        });

                        $('#slideshowContainer').fadeIn('slow');
                    });
                });
            },
            error: function(response) {
                console.log('Error: ' + JSON.stringify(response));
            },
            complete: function() {
                $('#spinnerContainer').toggleClass('fadein fadeout');
                $('#slideshow-container').fadeIn('slow');
            }
        });

Cheers