Shuffle a list

Sometimes we want to output our content in random order, and most Textpattern list tags accept sort="rand()" attribute, which often does the trick. But in a recent Forum conversation the following challenge was submitted:

How do I output article images in random order in an article list without the images ending up grouped by article? In other words, how do I gather all the image id’s from a group of articles and display them randomly so that the images aren’t grouped by article, but still maintain the ability to permlink each image to it’s respective article?

The initial block

The solutions seems immediate (let’s store it in a variable):

<txp:variable name="image_links">
	<txp:article_custom limit="9999" sort="rand()" break="br">
		<txp:images sort="rand()" break="br">
			<txp:permlink><txp:image /></txp:permlink>
		</txp:images>
	</txp:article_custom>
</txp:variable>

But it leaves images grouped by article, though randomizing their order inside each group. One could also try to gather all images id’s first, then pass them to <txp:images id="gathered_image_ids" sort="rand()" /> tag, but how to permlink images back to articles?

Shuffle the output

Well, if we can not shuffle items before the tag output, why not shuffle the output itself? The content of <txp:variable name="image_links" /> is something like:

<a href="art-1"><img src="img-1" /></a><br />
<a href="art-1"><img src="img-2" /></a><br />
...
<a href="art-100"><img src="img-999" /></a>

Add some PHP

All we have to do is to split it by <br />, mix the chunks and display the result. This takes three lines of PHP code:

<txp:php>
	$links = do_list(parse('<txp:variable name="image_links" />'), '<br />');	//split the links by '<br />'
	shuffle($links);													//mix the array
	echo implode('<br />', $links);										//join mixed links by '<br />' again
</txp:php>

And you can even remove sort="rand()" attribute from image_links construction, for better performance.

Other (plugin-based) solutions were proposed on the Forum thread, but ultimately Rome lead to all roads!

comments powered by Disqus