What is the best way to organize HTML Collections by child elements using basic Javascript?

   <div class="transaction-row" id= "transaction-row">
        <div class="name">Name 1</div>
        <div class="transaction-type"> Category 1</div>
        <div class="date">Date 1</div>
        <div class="amount">  1738</div>
        <div class="exp-or-inc">Exp or Inc </div>
    </div>

    <div class="transaction-row" id= "transaction-row">
        <div class="name">Name 2</div>
        <div class="transaction-type"> Category 2</div>
        <div class="date">Date 2</div>
        <div class="amount">  50</div>
        <div class="exp-or-inc">Exp or Inc </div>
    </div>

The objective here is to arrange all "transaction rows" based on the value in the child element with the class name "amount" using JavaScript. I have been exploring methods to sort multiple DOM elements by child elements with the sort() function without success.

Update:

Below is my JavaScript code:

let transEntries = document.getElementsByClassName("transaction-row");
       
let sortedEntries = [].slice.call(transEntries);

sortedEntries.sort((a,b)=> {
     
    if(a.children[3] === b.children[3]) {
            return 0;
    } else {
            return (a.children[3]  < b.children[3]) ? -1 : 1;
    }
       
});

All I require is to log the following in the console:

<div class="amount"> 50</div> 
<div class="amount"> 1738</div>

I should be able to rearrange the elements once they are stored in an array.

Answer №1

If you're looking to organize and sort elements within a container, the most efficient way is through CSS. Utilize flexbox on the parent element and apply the order property to its children. Then, manipulate the order of elements dynamically with JavaScript!

Take a look at this example:

HTML

<div id="flex">
  <div class="transaction-row" id="transaction-row">
    <div class="name">
      Name 1
    </div>
    <div class="transaction-type">
      Category 1
    </div>
    <div class="date">
      Date 1
    </div>
    <div class="amount">
      1738
    </div>
    <div class="exp-or-inc">
      Exp or Inc
    </div>
  </div>
  <div class="transaction-row" id="transaction-row">
    <div class="name">
      Name 2
    </div>
    <div class="transaction-type">
      Category 2
    </div>
    <div class="date">
      Date 2
    </div>
    <div class="amount">
      50
    </div>
    <div class="exp-or-inc">
      Exp or Inc
    </div>
  </div>
</div>

CSS

  #flex {
    display: flex;
    flex-direction: column;
  }

  .transaction-row {
    margin-block: 10px;
  }

Js

  const main = document.querySelector('#flex')
  let main_children = document.querySelectorAll('#flex > *')

  main_children = Array.from(main_children)
  main_children = main_children.sort((a, b) => {
    return   parseInt(a.querySelector('.amount').innerText) - parseInt(b.querySelector('.amount').innerText)
  })
  main_children.forEach((child, index) => child.style.order = index)

  console.log(main_children)

Note: While using the CSS flexbox's order property provides visual organization, it may not be accessible to screen readers. Keep in mind that screen readers will follow the HTML structure despite the visual arrangement!

It's recommended to stick with flexbox for structuring elements, and avoid altering order via innerHTML as it can cause issues with event listeners and functionality!

Answer №2

Upon @Teenmu's observation, if your goal is to organize the child elements and all transaction rows share a common parent without any other elements, this method should suffice

const transactionRows = [...document.querySelectorAll(".transaction-row")];

let doAllRowsShareSameParent = true;
let lastRowParent = null;

for(row of transactionRows){
  if(lastRowParent && row.parentElement !== lastRowParent){
    doAllRowsShareSameParent = true;
    break;
  }
  lastRowParent = row.parentElement;
}

const parent = lastRowParent;

if(doAllRowsShareSameParent) {
  transactionRows.sort((row1, row2) => {
    const row1Amount = parseFloat(row1.querySelector(".amount").innerText);
    const row2Amount = parseFloat(row2.querySelector(".amount").innerText);
    return  row1Amount - row2Amount;
  }).map(row => {parent.appendChild(row);});
}
<div class="transaction-row" id= "transaction-row">
       <div class="name">Name 1</div>
       <div class="transaction-type"> Category 1</div>
       <div class="date">Date 1</div>
       <div class="amount">  1738</div>
       <div class="exp-or-inc">Exp or Inc </div>
 </div>

<div class="transaction-row" id= "transaction-row">
     <div class="name">Name 2</div>
     <div class="transaction-type"> Category 2</div>
     <div class="date">Date 2</div>
     <div class="amount">  50</div>
     <div class="exp-or-inc">Exp or Inc </div>
</div>

Trust this aids you in your endeavor

Update: Following @Teenmu's note, while the previous approach works with innerHTML, it may detach event listeners from previous rows. The logic has been adjusted to address this concern.

Answer №3

let rows = document.querySelectorAll('.transaction-row');
let sortedRows = Array.from(rows).sort(sortByAmount);

for (let r of sortedRows) {
  container.append(r);
}

function sortByAmount(a, b) {
  return getAmount(a) - getAmount(b);

  function getAmount(row) {
    return row.querySelector('.amount').innerHTML.trim();
  }
}

I haven't tested it yet, but I believe it should work fine.

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

Commencement of timeline utilizing amchart's gantt feature

I am currently utilizing the Gantt chart feature in Amchart. The chart segments are organized based on dates. I am looking to specify a specific initial location for the chart's navigator between two dates, rather than having it applied across the en ...

Differences between jQuery and Google Closure in terms of handling AJAX

Recently, I've been exploring the Google Closure Library for handling ajax calls. I came across an example that piqued my interest: goog.events.listen(request, "complete", function(){ if (request.isSuccess()) { // perform a cool action } els ...

What makes Nuxt/auth so highly secure?

Picture this scenario: a visitor lands on your Nuxt.js website's homepage. They proceed to authenticate themselves using @nuxtjs/auth-next. After successfully logging in, they gain access to a protected page meant exclusively for authenticated users. ...

Exploring the handling of datetime in Bokeh when updating a datasource via Ajax

Currently, I am experimenting with a novel serverless reporting system centered around Bokeh and AJAX. However, I have encountered a challenge related to dates and times. I have successfully set up a version that streams numerical data from a cloud functio ...

When I place this in the js directory, the function does not seem to function properly

I have an add.ctp file where I can add multiple rows. However, when I place the addNumber function in app/webroot/js, it does not work. Why is that? Here is a snippet from my view file (add.ctp): <table id="mytable"> <tr id="number0" sty ...

Change not accepted

I am a beginner in Angular and still grappling with the fundamentals. On my menu, I have a cart icon with an initial value of 0 upon first load. In my product list, each product has an 'AddToCart' button. What I aim to achieve is- I want to dy ...

What is the method to execute a prototype function within another prototype?

I am facing an issue with my JavaScript class and need some help to resolve it. MyClass.prototype.foo = function() { return 0; } MyClass.prototype.bar = function() { return foo() + 1; } Unfortunately, when I try to run the program, it throws an ...

Creating a unique texture on a spherical object using THREE.js

Can a sphere be textured in sections rather than all at once? Just like we can use 6 textures on 6 sides of a cube, is it possible to apply different textures to different parts of a sphere? For example, dividing the sphere into quarters and texturing each ...

Troubleshooting EasyTabs: Localhost Issue with Ajax Tab Configurations

I've implemented EasyTabs for organizing my tabs on a webpage. I decided to use ajax-tabs functionality in order to fetch content from other pages when users click on the navigation menu buttons. However, I've encountered an issue where the conte ...

The concept of position() is often mistaken for a function

I am currently developing a slider and have included the code below: $(document).ready(function() { // MAKE SLIDER WIDTH EQUAL TO ALL SLIDES WIDTH var totalWidth = 0; $('.slide').each(function() { totalWidth = totalWi ...

Enhance a Javascript object by dynamically introducing new elements

I am currently working on a webpage using HTML and jQuery. My goal is to create a form where users can enter an email address in a textbox, and when they click a button, the email should be added to an object that displays all the emails entered so far. Th ...

Ways to display or conceal a component based on the current component being used

I am a newcomer in Angular, and I believe finding the solution to my problem will be a great learning experience. In my default component, the MainComponent is loaded in my <router-outlet>. At this stage, both the menu and the footer are displayed. H ...

Trying to assign an array to $scope is causing issues

I have an array called `arr` in a function that I want to return to `$scope.notifications` so that I can use it in the HTML within the Ionic Framework. I want to use a function to perform certain actions with the array before returning it later on. Here is ...

What is the best way to emphasize parent categories in a product table using Woocommerce?

I have a table of products used for filtering categories. My goal is to display only the parent categories in bold font. When searching results like in this link (e.g. https://demo.motorocker.gr/?swoof=1&antalaktika=scooter), we want the parent categor ...

What is the best way to secure the installation of python packages for long-term use while executing my code within a python shell on NodeJS?

I have been encountering difficulties while attempting to install modules such as cv2 and numpy. Although I have come across a few solutions, each time the shell is used the installation process occurs again, resulting in increased response times. Below i ...

Modifying the onclick function of an HTML select element - easy steps!

I have customized the click event on my select tag to trigger a specific action. However, when I click on the select tag, the default option list is also displayed. I want to bypass this default behavior and only execute my custom action when the select ta ...

Unraveling an AJAX response in JSON format using jQuery

I am a beginner in the world of Jquery and Ajax. I've crafted the code below to automatically populate a form with data after selecting an option from a combo box within a form, using guidance from this helpful post Autopopulate form based on selected ...

Troubleshooting problems encountered in Nest.js due to modifications made within a service.ts file

I'm currently working on a Nest.js project and here is the content of the automobile.service.ts file: import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Car } from './enti ...

Adjust the height of a div containing variable elements

I'm having trouble adjusting the height of a div so that it can be scrolled all the way through. This div is positioned next to another one, so I set the overflow-y to scroll. Initially, I thought setting the height to auto would solve the issue, but ...

What is the best way to append an HTML element located by its ID to the body of a webpage

Is there a way to insert a DOM element with a specific ID into the body tag while clearing out all existing body nodes? The following approach doesn't seem to be effective: var elem = document.getElementById("email"); document.body.innerHTML = elem; ...