Display new content after x seconds with routes and ajax …


#1

Hello everyone,

back in the days of kirby 2, @texnixe posted some nice instructions for an ajax call that requests one random $thing out of an array of $things …

I tried to adapt this to kirby 3’s new routing scheme, but again it seems I failed miserably in applying this.

Seems I’m getting a 404 status code, because api/random does not exist. I’d like to use this code on my home page to display one random image (plus, later, information like title and author) …

site/config/config.php

<?php
return [
  'routes' => [
    [
      'pattern' => 'api/random',
      'action'  => function () {
        $student = page('students')->children()->shuffle()->first();
        $project = $student->children()->shuffle()->first();
        $image = $project->images()->shuffle()->first();

        return '<div class="gallery">';
        return '<img src="' . $image->url() . '" alt="' . $image->uid() . '">';
        return '</div>';
      }
    ]
  ]
];

assets/js/reloadContainer.js

var container = document.getElementById("two");
var xhr = new XMLHttpRequest();

function reloadContainer() {
  xhr.open("GET", "api/random");
  xhr.send(null);

  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status === 200) {
        container.innerHTML = xhr.responseText;
      }
    }
  };
}

window.setInterval(reloadContainer, 5000);

#2

Try using another string than “api”, because Kirby has its own api now and therefore that will conflict.


#3

Also; you might have a look at your route. You now return 3 times in a row, while only the first will be returned.


#4

@bvdputte Maybe I could use echo several times instead of return

@texnixe Unfortunately, even though changing the string to e.g. /reload-container or something else results still in a 404 status code … I mean, sure, nothings exists at that URL … think I need to understand ajax a little bit better.

I just want this to happen at the home site, so the root of my URL without any folders/files/params appended.


#5

No, create your final html, then return.

$html = '<div class="gallery">';
$html .= '<img src="' . $image->url() . '" alt="' . $image->uid() . '">';
$html .= '</div>';
return $html;

Script execution stops after a return statement, giving back control to the calling script. Everything after the first return is therefore ignored.


#6

@texnixe Alright, I see … I changed it, following your advice:

return [
  'routes' => [
    [
      'pattern' => '/reload-container',
      'action'  => function () {
        $student = page('students')->children()->shuffle()->first();
        $project = $student->children()->shuffle()->first();
        $image = $project->images()->shuffle()->first();

        $html = '<div class="gallery">';
        $html .= '<img src="' . $image->url() . '" alt="">';
        $html .= '</div>';
        $html .= '<div class="headline">';
        $html .= '<h2><a href="' . $site->url() . '/students/student:' . $student->uid() . '/project:' . $project->uid() . '">' . $student->name() . '</a>&thinsp;&mdash;&thinsp;<span class="bold">' . strip_tags($project->project()->kirbytext()) . '</span></h2>';
        $html .= '</div>';

        return $html;
      }
    ]
  ]
];

Maybe I should change

'pattern' => '/reload-container' —> 'pattern' => '(:all)'

and, in my javascript file,

xhr.open("GET", "/reload-container'"); —> xhr.open("GET", "/");

to prevent to 404 status codes?

I don’t really find any other related topic here in the forum. I’ll try duckduckgo and google on ajax …

I just wonder, because in kirby 2 it worked as it was described in the linked thread.


#7

As I already said, do not use the string “api”, not in your pattern, not in the URL you call.


#8

Excuse me, that was a typo. I changed it, meanwhile, to reload/container in both places (pattern in config.php and xhr.open in javascript).

I’m not sure why I get a 404 response … even when just doing:

return [
  'routes' => [
    [
      'pattern' => 'reload/container',
      'action'  => function () {
        return 'TEST';
      }
    ]
  ]
];

#9

Maybe you have to echo it after all…


#10

Adding echo or replacing return with echo doesn’t change anything.

This behavior cannot be reproduced, can it? So it’s likely it’s a problem here and not with routes/ajax in general.


#11

Oh … there also must not be two returns in config.php … silly error, sorry everyone!

<?php

return [
  'debug'  => true
];

return [
  'routes' => [ …

Thank you for helping out again, @texnixe.


#12

I’d have one more question to which I didn’t find any solution, yet.

Is there any way to preload the image that is written to the DOM via container.innerHTML = xhr.responseText;? To prevent flickering because of loading times.

I’m pretty sure this is not related to the xhr status. The xhr response is complete, but the image probably starts loading after the image src url has been written to innerHTML, so the text is displayed also immediately and the image is delayed for some time (dependent on internet connection). That flickering looks very strange.