I want to create a HTML list that will shuffle itself once a week and anybody who accesses the website will view the same shuffled list. The shuffling JavaScript is identical to the highest upvoted question on the matter so I will refrain from posting that here.
The problem with this, is that the shuffled list is inconsistent across devices. I had attempted to set a timer to control when the script activates, as you can view here:
var ul = document.querySelector("ul"), // get the list
temp = ul.cloneNode(true); // clone the list
// shuffle the cloned list (better performance)
for (var i = temp.children.length 1; i--; )
temp.appendChild(temp.children[Math.random() * i |0] );
var weekInMilliseconds = 60*1000; // == 604800000 ms
var lastInfo = parseInt(localStorage.getItem('info'), 10); // either NaN or timestamp
if(isNaN(lastInfo))
lastInfo = 0; // 1970, mind you
// if last info showed earlier than one week ago:
if(lastInfo < (Date.now() - weekInMilliseconds)){
localStorage.setItem('info',Date.now()); // set info date now
ul.parentNode.replaceChild(temp, ul); // copy shuffled back to 'ul' // display your information
}
My problems with this were that, again the list wasn't consistent, and, though it did successfully stop the script from activating until sufficient time had passed, since there was no actual alteration to the HTML, if there was a refresh before the interval the page would just load with the default, unshuffled, list order, as written in the original HTML.
I'm quite new to web design so I'm unsure what to try next and and my browsing of W3 has been unfruitful. Any help would be appreciated, thanks!
CodePudding user response:
So shuffling randomly will be inconsistent since it's differs each time you reload the page. To shuffle consistently you can try to create a pseudo random shuffle logic - so avoid using Math.random()
here.
Explanation
We need to create a seed, in this case we are calulating the calendar week index and concatting this particular number with the current year to avoid repeating the same shuffle behaviour every year.
const seed = Math.ceil((new Date().getDay() 1 Math.floor((new Date() - new Date(new Date().getFullYear(), 0, 1)) / (24 * 60 * 60 * 1000))) / 7) new Date().getFullYear();
We need a "Random"-generator like this simple method:
const getRandom = () => {
const val = seed / (2 ** 32);
seed = (1664525 * seed 1013904223) % (2 ** 32);
return val;
}
Now we can start shuffeling the entries of our list using the linked answer to this question:
for (var i = list.children.length; i >= 0; i--)
list.appendChild(list.children[getRandom() * i | 0]);
Snippet
Take a look at this working snippet, note that the order of the list will change every week:
// create seed that changes every new week and will not repeat since we concat it with the current year
let seed = Math.ceil((new Date().getDay() 1 Math.floor((new Date() - new Date(new Date().getFullYear(), 0, 1)) / (24 * 60 * 60 * 1000))) / 7) new Date().getFullYear();
// create pseudo random numbers
const getRandom = () => {
const val = seed / (2 ** 32);
seed = (1664525 * seed 1013904223) % (2 ** 32);
return val;
}
// pseudo shuffel list
const list = document.querySelector('ol');
for (let i = list.children.length; i >= 0; i--)
list.appendChild(list.children[getRandom() * i | 0]);
<ol>
<li>Al Pacino</li>
<li>Bill Gates</li>
<li>Carsten Stahl</li>
<li>David Beckham</li>
<li>Elon Musk</li>
<li>Frank Ocean</li>
</ol>