0

I am try to set the order of several elements via jQuery.

The base date is the date hard-coded.

The code I have is as follows.

$temp1 = "1";
$temp2 = "2";
$temp3 = "3";
$temp4 = "4";
$temp5 = "5";

$(document).ready(function () {
    $("#flex").css("display", "flex");
    $("#flex").css("flex-direction", "column");
    $("#a").css("order", $temp1);
    $("#b").css("order", $temp2);
    $("#c").css("order", $temp3);
    $("#d").css("order", $temp4);
    $("#e").css("order", $temp5);
});

First a-b-c-d-e.
After three days b-c-d-e-a.
Six days later, c-d-e-a-b.
Nine days later, d-e-a-b-c.
Twelve days later, e-a-b-c-d.
I want to be a-b-c-d-e again in 15 days.

Additional temps may be added.

If there's one more, First a-b-c-d-e-f.
After three days b-c-d-e-f-a.
Six days later, c-d-e-f-a-b.
Nine days later, d-e-f-a-b-c.
Twelve days later, e-f-a-b-c-d.
Fifteen days later, a-b-c-d-e-f.
I want to be a-b-c-d-e-f again in 21 days.

jan
  • 31
  • 6
  • 2
    Are you imagining the user will have their machine on and running on your page for three days? Or is this something you want to work for any visitor at any time (for instance, if I visited your page on day six would you expect me to see 'a-b-c-d-e' because I'm just loading it or would you expect me to see 'c-d-e-a-b' because it is six days after the "start time")? – Alexander Nied Aug 09 '21 at 16:16
  • You could so something like take the [day of the year](https://stackoverflow.com/a/8619946/2181514) (or a specific date, rather than 1st day of current year) divide by 3, mod 5 (number of items) to get your "start position" then move the first to the last that number of times. Or something like that. – freedomn-m Aug 09 '21 at 16:43
  • 15 days _from when?_ From when they open the page? From some hard-coded date (day, January 1st?) – romellem Aug 09 '21 at 16:55
  • @AlexanderNied It will be based on the hard-coded date. – jan Aug 09 '21 at 17:05
  • @freedomn-m Can you explain it in more detail? – jan Aug 09 '21 at 17:06
  • @romellem From some hard-coded date – jan Aug 09 '21 at 17:06
  • a-f would be 18 days, not 21? – freedomn-m Aug 09 '21 at 17:16

2 Answers2

1

Here is a mathematical concept that you can use. The basic idea is this: have an order array, calculate how many times it needs to be shifted based on current date with this formula: date / interval % array length

const itemsList = document.getElementById("flex").children; //list of elements to order
const origOrder = [...Array(itemsList.length).keys()]; //get initial order

const initDate = new Date("08-09-2021 13:00:00").getTime(); //initial date to start the count from
const interval = 4; // 4 seconds interval, 60*60*24*3 = 3 days;

function orderIt()
{
  const date = (new Date().getTime() - initDate)/1000, //get seconds for our calculation
        newOrder = [...origOrder]; //clone original order

  //calculate how many times we need to shift the order
  //shift to the right
  const shift = ~~(date / interval) % newOrder.length;
  //or shift to the left
//  const shift = newOrder.length - ~~(date / interval) % newOrder.length;

  newOrder.unshift.apply( newOrder, newOrder.splice( shift, newOrder.length ) ); //shift order NN times
  for(let i = 0; i < itemsList.length; i++)
    itemsList[i].style.order = newOrder[i]; //apply order to the elements

  //display message
  document.getElementById("countdown").textContent = "Shifted by " + shift + " (" + interval + "sec interval) [" + Date(date) + "]";
}

orderIt(); //change order immediately
setInterval(orderIt, 1000); //initial demo loop;
#flex
{
  display: flex;
  flex-direction: column;

  list-style-type: none;
}
<ul id="flex">
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
  <li>E</li>
</ul>

<div id="countdown"></div>
vanowm
  • 9,466
  • 2
  • 21
  • 37
1

Can you explain it in more detail?

  • pick your start date
var fromDate = new Date(2021, 07, 01) // 07 for Aug
  • calculate how many days it's been since that date Using this answer

  • how many times to rotate, is ([days since start] / [number of days]) % [how many items]

var pos = Math.floor((dayIndex / dayChange) % items.length)
  • "rotate" them by simply moving the first to the last that number of times
$("#wrapper > div:first").appendTo("#wrapper");

in a loop below, for simplicity, but you could also use .slice and move them all in a single operation if there's 100s

Example code snippet, change the start date in the code to see the effect

var dayChange = 3 // change every 3 days
var fromDate = new Date(2021, 07, 01) // 07 for Aug
console.log(fromDate)

var today = new Date();
var diff = (today - fromDate) + ((fromDate.getTimezoneOffset() - today.getTimezoneOffset()) * 60 * 1000);
var oneDay = 1000 * 60 * 60 * 24;
var dayIndex = Math.floor(diff / oneDay);
console.log('Day Index: ', dayIndex);

var items = $("#wrapper>div");

var pos = Math.floor((dayIndex / dayChange) % items.length)
console.log(dayIndex, dayChange, items.length, pos)

while (pos > 0) {
  $("#wrapper > div:first").appendTo("#wrapper");
  pos--;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="wrapper">

  <div>a</div>
  <div>b</div>
  <div>c</div>
  <div>d</div>
  <div>e</div>

</div>
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
  • Thanks a lot. It worked out well. However, I have a question. The code "new Date(2021, 07, 01) // 07 for Aug" 07 It's July. But why is it display August when it's 07? – jan Aug 10 '21 at 04:30
  • The month in javascript dates is 0-based, so 0=Jan, 11=Dec - so 07=Aug. – freedomn-m Aug 10 '21 at 07:51
  • Thank you very much. I solved problem. very very very Thanks – jan Aug 13 '21 at 01:04