Build a Sorting Visualizer (Step 18)

Hello! I’m pretty proud of my implementation of Bubble Sort below, and it appears to match the example output, but I need some help passing Steps 18 and 19.

    1. After you click #sort-btn, #array-container should contain as many div elements as the steps required by the Bubble Sort algorithm to sort the starting array, including the div representing the starting array and a div representing the sorted array.
    1. After you click #sort-btn, each div within #array-container should contain five span, each with a number as its text, and arranged to represent the steps required by Bubble Sort algorithm to sort the starting array.

FCC example output (left) my output on same array (right):

My output on presorted array

Where do you think I’m going wrong on this one?

Build a Sorting Visualizer: Build a Sorting Visualizer | freeCodeCamp.org

My code:

function generateElement() {
  return Math.floor(Math.random() * 100 + 1);
}

function generateArray() {
  let arr = []
  for (let i = 0; i < 5; i++) {
    arr.push(generateElement())
  }
  return arr;
}

function generateContainer() {
  return document.createElement("div");
}

function fillArrContainer(element, array) {

  for (let i = 0; i < 5; i++) {
      let span = element.appendChild(document.createElement("span"))
      span.textContent = `${array[i]}`
  }

}

function isOrdered(int1, int2) {
  return int1 <= int2;
}

function swapElements(array, index) {
  if (!isOrdered(array[index], array[index+1])){
      array.splice(index, 0, array[index+1])
      array.splice(index+2, 1)
  }
}

function highlightCurrentEls(htmlElement, index){
 let child = htmlElement.children[index];
 let secondChild = child.nextElementSibling;

for (const el of [child, secondChild]) {
    el.style.border = '2px dashed red';
}
}

const generateButton = document.getElementById("generate-btn");
const sortButton = document.getElementById("sort-btn");
const startingArray = document.getElementById("starting-array");
const arrayContainer = document.getElementById("array-container");

generateButton.addEventListener("click", () => {
  const divs = arrayContainer.querySelectorAll("div")
  divs.forEach((div) => {
    if (div !== startingArray) {
      div.remove()
    }

  })
  sortButton.style.display = ""
  startingArray.innerHTML = ''
  let array = generateArray();
  fillArrContainer(startingArray, array)
})

sortButton.addEventListener("click", () => {


let nodeArray = Array.from(startingArray.querySelectorAll("span"))
let array = nodeArray.map(node => node.textContent)

let count = 0;                  //Used within the loop to count how many pairs are in order

  do {                          //Execute at least once, in case a pre-sorted array is passed
      count = 0;                
      for (let i = 0; i < 4; i++) {
        if (isOrdered(array[i], array[i+1])) {
          count++               //Increment if a number pair is ordered
        }
        swapElements(array, i)              //Will swap two numbers if unordered
        let bubbled = generateContainer(); 
        fillArrContainer(bubbled, array);  
        arrayContainer.appendChild(bubbled);
      }
     
  } while (count < 4)           //If all elements are in order (count === 4), then conclude the loop

  const divs = arrayContainer.querySelectorAll("div")
  for (let i = 0; i < (divs.length/4)-1; i++) {
      for (let e = 0; e < 4; e++) {
        highlightCurrentEls(divs[(e + (4*i))], e)
      }
  } //Maybe a bad way of highlighting steps, but this implementation passes our tests

  const last = arrayContainer.lastElementChild
  last.style.border = "2px solid green"
  sortButton.style.display = "none"
})
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Sorting Visualizer</title>
    <link rel="stylesheet" href="styles.css">
</head>

<body>
    <main>
        <div id="array-container">
            <div id="starting-array"></div>
        </div>
        <div id="btn-container">
            <button id="generate-btn" type="button">Generate Array</button>
            <button id="sort-btn" type="button">Sort Array</button>
        </div>
    </main>
    <script src="script.js"></script>
</body>

</html>
* {
    box-sizing: border-box;
}

main {
    height: 100vh;
    display: flex;
    justify-content: center;
    flex-direction: column;
    align-items: center;
}

#array-container {
    max-height: 95vh;
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    gap: 2px;

}

#array-container>div {
    min-width: 8rem;
    height: 2rem;
    box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
    border-radius: 10px;
    margin-bottom: 0.2rem;
    border: 2px solid darkgray;
    display: flex;
    justify-content: space-evenly;
    align-items: center;
}

#starting-array {
    border: 4px solid darkblue !important;
}

#btn-container {
    display: flex;
    justify-content: space-around;
}

button {
    padding: 2px;
    margin: 5px;
}

span {
    border-radius: 2px;
    padding: 0.5px;
    margin: 0
}

@media (min-width: 430px) {
  #array-container>div {
    min-width: 12rem;    
  }
  span {
    padding: 1px;
    margin: 1px;
  }
}

the code runs sometimes correctly and sometimes incorrectly. I am not sure why yet.
here’s a screenshot of one of the times it ran incorrectly for me (I just ran it through 5 or 6 times till it failed)

1 Like

Look at the example project again. Does the display stop when the array is fully sorted. Instead, it stops after one full iteration with no swaps.

Weird! Yes, it seems like sometimes the sorting goes haywire when generate-btn is pressed. However, when I pass the same sequence in as an array literal, the algorithm works.

With generation:

As array literal:

Does that help us debug?

1 Like

here’s the issue.

What type of value is node.textContent?

2 Likes

Great catch! Won’t spoil the solution for future campers, but remember your data types!

2 Likes

have you learned how to use a debugger by any chance? If not, now would be a good time to learn how to use the one in Chrome Dev tools. Would have helped with this issue.

2 Likes

The debugger is covered by a lecture a few modules back, but I think we didn’t really put it into action. Kind of like the aria stuff in the HTML section, sometimes there are many lectures but I don’t retain the knowledge without a quick workshop or lab. I will look into adding the debugger to my toolkbox now, though!

1 Like

lots of videos in Chrome’s website explaining how to use dev tools (including the debugger and setting up breakpoints etc). Definitely will be worth your time to do the work now.

2 Likes