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.
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.
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.
Ohhhhhhh ok, that’s a much nicer solution. It’s almost like you know what you’re talking about, Sonja.
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!