Generate random DOM element exchange (without using jQuery)

My JavaScript code is designed to randomly swap HTML elements like images or paragraphs. The swapping of positions is working, but I've encountered a strange bug that I can't seem to explain. In the example HTML provided, there are only 2 paragraph elements. The swapping works fine for a few times, but then the elements suddenly change positions in an unexpected way.


document.getElementById("pButton").addEventListener("click", () => {
  let max = document.querySelectorAll("p").length - 1;
  let min = 0;
  let x1 = Math.round((Math.random() * (max - min)) + min);
  let x2 = Math.round((Math.random() * (max - min)) + min);
  
  while (x1 === x2) {
    x2 = Math.round((Math.random() * (max - min)) + min);
  }

  let tmp1 = document.querySelectorAll("p")[x1];
  let tmp2 = document.querySelectorAll("p")[x2];
  let tmp1parent = tmp1.parentNode;
  let tmp2parent = tmp2.parentNode;
  let tmp1Index = 0;

  for (let a of tmp1parent.childNodes) {
    if (a === tmp1) {
      break;
    }
    tmp1Index += 1;
  }

  tmp2parent.insertBefore(tmp1, tmp2);
  tmp1parent.insertBefore(tmp2, tmp1parent.childNodes[tmp1Index]);
});
                
<div>
  <h1>List</h1>
  <p>p1</p>
  <ol>
    <li>first</li>
    <li>second</li>
  </ol>
  <a>example</a>
  <p>p2</p>
  <ol>
    <li>first</li>
    <li>second</li>
    <li>third</li>
  </ol>
  <a>example</a>
</div>
<button id="pButton">BUTTON</button>

Answer №1

Nice to see you again :)

document.getElementById("pButton").addEventListener("click", () => {
  let max = document.querySelectorAll("p").length - 1;
  let min = 0;
  let x1 = Math.round((Math.random() * (max - min)) + min);
  let x2 = Math.round((Math.random() * (max - min)) + min);
  while (x1 === x2) {
    x2 = Math.round((Math.random() * (max - min)) + min);
  }
  
  let tmp1 = document.querySelectorAll("p")[x1];
  let tmp2 = document.querySelectorAll("p")[x2];
  
  // Having a direct reference is great, don't you agree?
  let parentDiv = document.getElementById('parent');

  // Obtain the previous element of the first element to change
  let tmp1PrevEle = tmp1.nextElementSibling;
  // Do the same for the second one
  let tmp2PrevEle = tmp2.nextElementSibling;
  // Insert both based on the previous and next elements
  parentDiv.insertBefore(tmp2, tmp1PrevEle);
  parentDiv.insertBefore(tmp1, tmp2PrevEle);
});
<div id="parent">
  <h1>List</h1>
  <p>p1</p>
  <ol>
    <li>first</li>
    <li>second</li>
  </ol>
  <a>example</a>
  <p>p2</p>
  <ol>
    <li>first</li>
    <li>second</li>
    <li>third</li>
  </ol>
  <a>example</a>
  <!-- just to see the randomness, I've added two more elements -->
  <p>p3</p>
  <ol>
    <li>first</li>
    <li>second</li>
    <li>third</li>
  </ol>
  <a>example</a>
  <p>p4</p>
  <ol>
    <li>first</li>
    <li>second</li>
    <li>third</li>
  </ol>
  <a>example</a>
</div>
<button id="pButton">BUTTON</button>

Here's what I went ahead and did:

  1. Retrieve the next element using nextElementSibling and then insert the element that needs to be shifted.
  2. I'm storing the nextElementSibling of both nodes so they won't change in the future.

The problem lies here.

let tmp1Index = 0;
  for (let a of tmp1parent.childNodes) {
    if (a === tmp1) {
      break;
    }
    tmp1Index += 1;
  }

This index may not be accurate as once items have been repositioned, the original nodelist's position could be altered.

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

What are the important steps to properly map data prior to subscribing?

I'm working on a function that looks like this: this.localStorage.getItem('user').subscribe(user => { this.user = user; this.authSrv.getOrders(this.user.einsender).pipe(map(orders => { map(order => { order[&q ...

Customize the color of arrows within an ng-bootstrap carousel

I am currently working on a carousel using ng-bootstrap, and I need to change the color or image of the arrows from white to black because my background images are white and not visible. The issue is that I am having trouble accessing span, and I am unsure ...

How to dynamically increase vote tallies with React.js

The voting system code below is functioning well, displaying results upon page load. However, I am facing an issue where each user's vote needs to be updated whenever the Get Vote Count button is clicked. In the backend, there is a PHP code snippet ...

Is it possible to utilize AJAX to fetch code from a separate file, view, or page in order to create an experience akin to a single-page application

Essentially, I'm aiming to create a simplified version of a Single Page Application within the admin panel of my website. The idea is to organize the information by using tabs, making the panel less cluttered. Here's a rough layout of what I have ...

Exploring the Integration of Metro CSS 3 Form Validation within the MVC Framework

I am looking to implement the form validator feature from Metro CSS 3 in my MVC 5 application. Below is a snippet of my code: @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { @Html. ...

What is the best way to add an element while preserving its original placement?

I need a solution to duplicate the code of an element and transfer it to another element without removing it from its original position. Currently, I have a JavaScript function that allows you to move a picture to a box when it's clicked. However, th ...

Creating a unique HTML id using an evaluated expression

My goal was to create a minimalist version of the classic game "tic tac toe" using AngularJS. To achieve this, I had to come up with a unique solution by assigning each button a distinct ID (f+i). HTML <table> <tr ng-repeat="f in [5,10,15]"& ...

The function _path2.default.basename does not work when using convertapi within an Angular framework

I'm currently working on integrating the convertapi into my Angular 11 application by referencing the following documentation https://www.npmjs.com/package/convertapi My goal is to convert PDFs into images, However, I encountered an issue when tryi ...

JavaScript: Reversing the Sequence of XML Elements

I am looking to reverse the order of this list using JavaScript. I have tried different methods that I know, but the below code shows it in a straight manner. I am not familiar with XML nodes and how to completely reverse it. <messages> <mess ...

How can I modify the HTML code for rooms in the HTML 5 client of the bigbluebutton application?

Is it possible to customize the HTML code of rooms within the BigBlueButton source code? Additionally, how can I modify the CSS styles of elements in room sessions? For instance, I am interested in hiding the logo of BigBlueButton by setting 'display: ...

Replace a portion of text with a RxJS countdown timer

I am currently working on integrating a countdown timer using rxjs in my angular 12 project. Here is what I have in my typescript file: let timeLeft$ = interval(1000).pipe( map(x => this.calcTimeDiff(orderCutOffTime)), shareReplay(1) ); The calcTim ...

Ways to achieve a layout with 2 fixed columns and 1 dynamic column using CSS

For the past 2 days, I've been struggling with this problem. I've experimented with "display: flex" and various combinations, but none have given me the desired outcome. I require CSS code to achieve this layout (refer to the image). I have two ...

Encountered an issue while executing the npm run dev command in a React project

Hello, I am a beginner with React.js and I am currently trying to set up a simple React application locally using webpack. However, when I run the npm run dev command, I encounter the following error: An error occurs in the command prompt after running np ...

The getBBox() method of SVG:g is returning an incorrect width value

Hey there, I've been attempting to determine the width of a <g> element and it consistently returns 509.5 pixels regardless of what I do. Initially, I assumed this was the actual size and not scaled. However, upon opening the SVG in Illustrato ...

Error message: Failure to retrieve / on the Express application

Embarking on a new project using express, I've set up the foundation with an index.js file in my project folder: var express = require('express'); //App setup var app = express(); var server = app.listen(4000, function(){ console.log(&a ...

Once upon a time in the land of Storybook, a mysterious error message appeared: "Invalid version. You must provide a string

I keep encountering an issue while attempting to set up storybook. Can anyone help me figure out what's causing this problem? npx storybook@latest init • Detecting project type. ✓ TypeError: Invalid version. Must be a string. Got type "obje ...

Code snippet: Retrieve the previous and upcoming events based on the current date from an array (JavaScript/Angular)

Is there anyone who can assist me with an algorithm? I have a list of events and need to retrieve the next event and previous events based on the current date. For example: I fetch all events from an SQL database like so: events = [ {eventId:1, event ...

Ensure that PHP form validations are checked when submitting the form using jQuery

I have created a form in HTML with basic verification. Here is the code: <form class="" action="submit/save" method="POST" enctype="multipart/form-data" id="submit_form"> <input class="form- ...

Alignment of images at the center within a container div while maintaining a height of 100%

Apologies if this question has already been addressed - I have tried numerous methods to center images horizontally without success. This particular image just does not want to align in the center! For reference, here is the JSFiddle link HTML: (Please n ...

Tips for expanding a text input field vertically, not horizontally like in Facebook, while typing or by holding down the Shift key and pressing Enter

I've come across numerous plugins that enable vertical resizing of a textarea and others that allow horizontal resizing of an input field. However, I have yet to find one that enables vertical resizing of an input field similar to Facebook's comm ...