Random post button?

Hey folks,

I’m trying to implement a random post button on my search page, that will take visitors to random post of mine, if they click the button. I’ve been limping along (as I often do), but it’s not working and I’m stuck.

I’m sure someone here will spot a glaring problem with my code right away, but I can’t, so any help you be really appreciated.

Here’s the javascript for my button:

document.getElementById('randomButton').addEventListener('click', function() {
    fetch('/api/random-posts') // Call the config route
        .then(response => response.json())
        .then(data => {
            // Ensure that there are blog posts available
            if (data.length > 0) {
                // Get a random index from the array
                var randomIndex = Math.floor(Math.random() * data.length);

                // Redirect the user to the random blog post
                window.location.href = data[randomIndex];
            } else {
                console.error('No blog posts available.');
            }
        })
        .catch(error => console.error('Error fetching blog posts:', error));
});

Then I have a route that links to this:

// Random blog post
        [
            'pattern' => 'api/random-posts',
            'action'  => function () {
                $blogPosts = [];
                $posts = page('blog')->children();

                foreach ($posts as $post) {
                    $blogPosts[] = $post->url();
                }

                return json_encode($blogPosts);
            }
        ]

Then to embed the button, I just have a button with an id of randomButton. Problem is, when I plug all this together and click the button, nothing happens and the browser consols spits out the “Error fetching blog posts” error from the javascript.

Does anyone have any ideas please?

Thanks,

Kev

Not a good idea to use api, as that would require authentication.

Also, wouldn’t it make more sense to already return a random post from your route, instead of returning an array of posts?

I overlooked the api requiring authentication. :man_facepalming:

I’ve thought about it (please remember I’m not a developer, so this is very crude) and I’ve come up with a way of doing this within the template, as routes still baffle me. I’m not sure if this is the best way, but it works. :man_shrugging:

Javascript:

document.getElementById('randomButton').addEventListener('click', function() {
    // Fetch the list of blog post URLs from the page
    var blogPostUrls = JSON.parse(document.getElementById('blogPostUrls').textContent);

    // Check if there are any blog posts
    if (blogPostUrls.length > 0) {
        // Get a random index from the array
        var randomIndex = Math.floor(Math.random() * blogPostUrls.length);

        // Redirect the user to the random blog post
        window.location.href = blogPostUrls[randomIndex];
    } else {
        console.error('No blog posts available.');
    }
});

Template:

<?php
    // The child catcher!
    $posts = page('blog')->children();

    // Get an array of post URLs
    $blogPostUrls = $posts->pluck('url');

    // Encode the array as JSON and output it to a hidden element
    echo '<div id="blogPostUrls" style="display:none;">' . json_encode($blogPostUrls) . '</div>';
?>

If there’s a better way (which I’m certain there is) I’m all ears. :slight_smile:

Kev

Is the JavaScript really necessary? What I would do:

  1. Create a normal, non-api route
  2. In your route code, use $pages->shuffle()->first() or nth() with a random index to pick a random page
  3. Redirect to this page in your route with go().

No Javascript stuff needed. No clutted HTML with lots of urls.

2 Likes

Ohhhhhhh ok, that’s a much nicer solution. It’s almost like you know what you’re talking about, Sonja. :slight_smile:

Here’s what I came up with, which seems to work well and my site remains JS free:

// Random post
[
  'pattern' => 'random-post',
  'action'  => function () {

  // The child collector
  $posts = page('blog')->children();

  // Randomise the children
  $randomPost = $posts->shuffle()->first();

  // Redirect to the random blog post
  go($randomPost->url());

  }
]

Thanks, Sonja. Appreciate the help and guidance as always!

Kev