Different ways to shuffle the arrangement of divs

Forgive me if this seems like a simple query, but I am struggling with it. Essentially, what I want to achieve is to randomize the positioning of the items, where item 1 can adopt the style of item 3 (or 2 or 4), item 2 can take on the style of 1, 3, or 4, and so forth.

Below is my code snippet:

let item = document.querySelectorAll('.item')

for (let i = 0; i < item.length; i++) {
  const getRight = item[i].style.right
  const getTop = item[i].style.top
  const getStyles = [getRight, getTop]
  console.log(`Item${i}, Style: ${getStyles}`);
}
.items--cloud {
  position: relative;
  height: 400px;
  width: 500px;
  background: #333;
}

[data-item] {
  position: absolute;
  transform: translate3d(var(--x), var(--y), 0);
}
<div class="items--cloud">
  <div data-item="item-1" class="item item-1" style="right: 0%;top: 40%;">
    <img src="https://via.placeholder.com/90x90.?text=item1" alt="">
  </div>
  <div data-item="item-2" class="item item-2" style="right: 53%;top: 28%;">
    <img src="https://via.placeholder.com/90x90?text=item2" alt="">
  </div>
  <div data-item="item-3" class="item item-3" style="right: 39%;top: 4%;">
    <img src="https://via.placeholder.com/90x90?text=item3" alt="">
  </div>
  <div data-item="item-4" class="item item-4" style="right: 79%;top: 26%;">
    <img src="https://via.placeholder.com/90x90?text=item4" alt="">
  </div>
</div>

Answer №1

To achieve this, one effective method is to establish a CSS rule for each specific position you intend to utilize.

Assign an initial position to all elements (ensure that each element possesses a distinct position class).

During the shuffling process, capture the positions applied, remove them from the elements, shuffle the array of positions, and then reapply them.

The shuffleArray function originates from this response to "How to randomize (shuffle) a JavaScript array?"

function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}

function shuffelPositions() {
  let items = document.querySelectorAll('.item')
  
  // Capture the current element positions and eliminate the existing ones
  let positions = Array.from(items).map( item => {
    // Iterate over item.classList and search for classes starting with `position-`
    let positionClass = Array.from(item.classList).find(item => item.match(/^position-/))
    // Remove the located class
    item.classList.remove(positionClass)

    // Return it to allow the `.map` to create a new array containing that class
    return positionClass
  })
  
  // Shuffle those positions
  shuffleArray(positions)
  
  // Apply the shuffled positions
  for (let i = 0; i < items.length; i++) {
    items[i].classList.add(positions[i])
  }
}

document.getElementById('shuffle').addEventListener('click', shuffelPositions)
.items--cloud {
  position: relative;
  height: 400px;
  width: 500px;
  background: #333;
}

[data-item] {
  position: absolute;
  transform: translate3d(var(--x), var(--y), 0);
}

.position-1 {
  right: 0%; top: 40%;
}

.position-2 {
  right: 53%;top: 28%;
}

.position-3 {
  right: 39%;top: 4%;
}

.position-4 {
  right: 79%;top: 26%;
}
<div class="items--cloud">
  <div data-item="item-1" class="item item-1 position-1">
    <img src="https://via.placeholder.com/90x90.?text=item1" alt="">
  </div>
  <div data-item="item-2" class="item item-2 position-2">
    <img src="https://via.placeholder.com/90x90?text=item2" alt="">
  </div>
  <div data-item="item-3" class="item item-3 position-3">
    <img src="https://via.placeholder.com/90x90?text=item3" alt="">
  </div>
  <div data-item="item-4" class="item item-4 position-4">
    <img src="https://via.placeholder.com/90x90?text=item4" alt="">
  </div>
</div>

<button id="shuffle">shuffle positions</button>

If you prefer not to use classes, utilizing the data attribute could be another approach. This has the benefit of providing additional semantic meaning, making it easier to retrieve the utilized position if necessary:

function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}

function shuffelPositions() {
  let items = document.querySelectorAll('.item')
  
  // Capture the current element positions and remove the existing ones
  let positions = Array.from(items).map( item => {
    return item.dataset.position;
  })
  
  // Shuffle those positions
  shuffleArray(positions)
  
  // Apply the shuffled positions
  for (let i = 0; i < items.length; i++) {
    items[i].dataset.position = positions[i]
  }
}

document.getElementById('shuffle').addEventListener('click', shuffelPositions)
.items--cloud {
  position: relative;
  height: 400px;
  width: 500px;
  background: #333;
}

[data-item] {
  position: absolute;
  transform: translate3d(var(--x), var(--y), 0);
}

[data-position="1"] {
  right: 0%; top: 40%;
}

[data-position="2"]{
  right: 53%;top: 28%;
}

[data-position="3"]{
  right: 39%;top: 4%;
}

[data-position="4"] {
  right: 79%;top: 26%;
}
<div class="items--cloud">
  <div data-item="item-1" class="item item-1" data-position="1">
    <img src="https://via.placeholder.com/90x90.?text=item1" alt="">
  </div>
  <div data-item="item-2" class="item item-2" data-position="2">
    <img src="https://via.placeholder.com/90x90?text=item2" alt="">
  </div>
  <div data-item="item-3" class="item item-3" data-position="3">
    <img src="https://via.placeholder.com/90x90?text=item3" alt="">
  </div>
  <div data-item="item-4" class="item item-4" data-position="4">
    <img src="https://via.placeholder.com/90x90?text=item4" alt="">
  </div>
</div>

<button id="shuffle">shuffle positions</button>

Answer №2

Check out rando.js for an easy solution with the randoSequence function.

function shuffleStyles(elements, styles){
    if(elements.length < 2) return false;
    
    var randomElements = randoSequence(elements).slice(-2).map((i) => i.value), temp = "";
    for(var i = 0; i < styles.length; i++){
        temp = randomElements[0].style[styles[i]];
        randomElements[0].style[styles[i]] = randomElements[1].style[styles[i]];
        randomElements[1].style[styles[i]] = temp;
    }
}
.abs{
  position:absolute;
  width:100px;
  height:50px;
}
<script src="https://randojs.com/2.0.0.js"></script>

<button onclick="shuffleStyles(document.getElementsByClassName('abs'), ['top', 'right']);">CLICK TO SHUFFLE!</button>
<div class="abs" style="top:10px;right:10px;background:red;"></div>
<div class="abs" style="top:60px;right:120px;background:blue;"></div>
<div class="abs" style="top:120px;right:330px;background:green;"></div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can the ordering of dynamically generated components be synchronized with the order of other components?

Currently, I'm delving into Vue 3 and encountering a specific issue. The tabs library I'm using only provides tab headers without content panels. To work around this limitation, I've come up with the following solution: <myTabs/><!- ...

What is the best method to display the content in the second response for ajax's authorization and dealing with cors?

I have successfully implemented basic authorization and enabled CORS on my VPS. Check the CORS preflight request using cURL: HTTP/1.1 200 OK Date: Sat, 15 Sep 2018 08:07:37 GMT Server: Apache/2.4.6 (CentOS) Access-Control-Allow-Origin: http://127.0.0 ...

Disabling form submission when pressing the enter key

Is there a way to prevent a submit action from occurring when the enter key is pressed within an ASP:TextBox element that triggers an asyncpostback upon text change? Instead, I would like it to click on another button. The Javascript function I am using wo ...

Execute JavaScript function on click event in NextJS

Is it possible to execute a JavaScript function on the client side without using addEventListener? This situation works with addEventListener. MyComponent.js import Script from 'next/script' export default function MyComponent({ props }) { ...

NodeJS:UncaughtPromiseError

Each time the command npm run start is executed, everything appears to be normal and the logs indicate no issues until encountering the following error: (node:4476) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'length' of und ...

The response from Axios in NodeJs is displaying incorrect encoding

Having some trouble executing a REST call using Axios and receiving an unexpected response. try { const response = await axios.get("https://api.predic8.de/shop/products/"); console.log(response.data); } catch (error) { console.log(`[Error] -> ...

Is your event listener failing to activate?

I have been working on a project where I gather array elements from user input and try to display them in an HTML table. Unfortunately, the event listener seems to not be triggering, and I can't figure out why. Here is the relevant HTML code: ...

Having trouble identifying the issue with the dependent select drop down in my Active Admin setup (Rails 3.2, Active Admin 1.0)

I am currently working on developing a Ruby on Rails application that involves three models: Games that can be categorized into a Sector (referred to as GameSector) and a subsector (known as GameSubsector) A sector consists of multiple subsectors. A Subs ...

What could be causing my data to undergo alterations when transitioning from a frontend form submission to a backend API?

In my experience with Next.js 13 and Prisma, I encountered a peculiar issue. I had set up a basic form to collect user information for an api request. Oddly enough, when I printed the data right before sending it, everything seemed fine. However, upon arri ...

Exiting a void method in JavaScript/Typescript using the return or break statement

I find myself dealing with a complex method in Typescript that contains multiple if else if else constructs. It's a void method, and I'm wondering how I can exit the method based on a specific if condition without having to execute the remaining ...

Error encountered in TypeScript's Map class

When working with TypeScript, I keep encountering an error message that reads "cannot find name Map." var myMap = new Map(); var keyString = "a string", keyObj = {}, keyFunc = function () {}; // assigning values to keys myMap.set(keyString, "val ...

Retrieve all elements from an array using jQuery

How do I extract all the elements from the array outside of the function? $.each(Basepath.Templates, function(i){ templateArray = new Array({title: Basepath.Templates[i].Template.name, src: 'view/'+Basepath.Templates[i].Template.id, descri ...

How can I manually transclude content within a directive into two separate locations?

When trying to access the result of ng-repeat, I discovered that using the transclude function and manually compiling could help. However, this method does not work in situations with two places and elements containing ng-repeat. Here is how my code is str ...

Loading STL files from a buffer instead of a path within Three.js

I'm struggling to showcase a user-uploaded STL file in Three.js. The issue arises when my file is delivered to the front-end through a GET request: res.sendFile(path). Unfortunately, I can't directly utilize this raw data to load the file withou ...

The query pertaining to Facebook redirect functionality

I have a Facebook ad with a URL encoded in it, and I need to extract the final destination URL that it redirects to using JavaScript in my Python program. The standard urllib2/mechanize methods don't work because of the JavaScript involved, and as a P ...

Assign an id attribute in KineticJS once the ajax call is successful

I have implemented KineticJS into my MVC application. To retrieve data from the database, I am utilizing ajax calls to web services in the API controller. One of the APIs returns an id that I want to assign to the current Kinetic.Group id attribute upon s ...

In Vue3, I utilize the Provide and Inject feature to handle data changes without triggering a visual update. Instead, I apply a filter() function to remove an item from an

I am currently testing the usage of the provide and inject methods. I have placed the datas and del-function in the parent component to provide, and in the child component, I am dynamically rendering using v-for='data' in datas. The objective I ...

How to direct all wildcard paths to a particular route in Next.js

I currently have a single landing page application built with nextJs. I am wondering if it is possible to redirect all paths to specific routes, similar to how we do it in react-router. How can I achieve the same functionality in nextJs? <BrowserRou ...

Retrieving information from a function beyond the scope of Mongoose

I am currently facing an issue with my function in which I need to return the Mongoose query data so that I can use it. However, I am only able to access the sum within the .exec function. How can I manage to retrieve the sum value outside of this functi ...

Pausing repetitive HTTP requests in an Angular 6 project within a do while loop

While waiting for the completion of one API call, I am recursively consuming an external API. The http calls are being made using import {HttpClient} from '@angular/common/http' As a newcomer to the framework, there may be something wrong in the ...