Build a Sorting Visualizer - Build a Sorting Visualizer

Tell us what’s happening:

this stuff isnt passing and i dont understand why.

Your code so far

<!-- file: index.html -->

/* file: styles.css */

const generateBtn = document.getElementById(‘generate-btn’)

const startingArray = document.getElementById(‘starting-array’)

const arrayContainer = document.getElementById(‘array-container’)

const sortBtn = document.getElementById(‘sort-btn’)

const generateElement = () => {

const random = Math.floor(Math.random() * 100) + 1

return random

}

const generateArray = () => {

let randomIntergers =

for (let i = 0; i < 5; i++) {

const numbers = generateElement()

randomIntergers.push(numbers)

}

return randomIntergers

}

console.log(generateArray())

const generateContainer = () => {

let emptyDiv = document.createElement(‘div’)

return emptyDiv

}

const fillArrContainer = (element, arr) => {

element.innerHTML = `${arr[0]}

${arr[1]}

${arr[2]}

${arr[3]}

${arr[4]}

`

}

const isOrdered = (first, second) => {

return first <= second

}

const swapElements = (arr, index) => {

if (arr[index] > arr[index + 1]) {

\[arr\[index\], arr\[index + 1\]\] = \[arr\[index + 1\], arr\[index\]\]

}

return arr;

}

const highlightCurrentEls = (element, index) => {

const child = element.children[index]

const secondChild = element.children[index + 1]

child.style.border = ‘dashed red’

child.style.width = ‘20px’

secondChild.style.border = ‘dashed red’

secondChild.style.width = ‘20px’

}

generateBtn.addEventListener(‘click’, () => {

// Clear previous sort steps

Array.from(arrayContainer.children).forEach(child => {

if (child.id !== 'starting-array') {

  arrayContainer.removeChild(child);

}

});

// Generate new array

const array = generateArray();

// Fill #starting-array with five elements

startingArray.innerHTML = ‘’;

array.forEach(num => {

const span = document.createElement('span');

span.textContent = num;

startingArray.appendChild(span);

});

})

sortBtn.addEventListener(‘click’, () => {

// Clear previous steps but keep #starting-array

Array.from(arrayContainer.children).forEach(child => {

if (child.id !== 'starting-array') {

  arrayContainer.removeChild(child);

}

});

// Get array from #starting-array

const spans = startingArray.querySelectorAll(‘span’);

let arr = Array.from(spans).map(span => parseInt(span.textContent));

highlightCurrentEls(startingArray,0)

const steps = ; // Array of { arr: […], highlight: index }

const initialDiv = generateContainer();

arr.forEach(num => {

const span = document.createElement(‘span’);

span.textContent = num;

initialDiv.appendChild(span);

});

arrayContainer.appendChild(initialDiv);

// Bubble Sort with swap tracking

for (let i = 0; i < arr.length; i++) {

let swapped = false;

for (let j = 0; j < arr.length - i - 1; j++) {

  if (arr\[j\] > arr\[j + 1\]) {

    arr = swapElements(arr, j);

    steps.push({ arr: \[...arr\], highlight: j }); // Track swap index

    swapped = true;

  }

}

if (!swapped) break;

}

// Always push final sorted array explicitly

steps.push({ arr: […arr], highlight: null });

// Render each step

steps.forEach(({ arr: stepArr, highlight }) => {

const stepDiv = generateContainer();

stepArr.forEach((num, idx) => {

  const span = document.createElement('span');

  span.textContent = num;



  // Highlight swapped elements

  if (highlight !== null && (idx === highlight || idx === highlight + 1)) {

    span.style.border = '2px dashed red';

    span.style.width = '20px';

    span.style.margin = '2px';

  }



  stepDiv.appendChild(span);

});

arrayContainer.appendChild(stepDiv);

});

});

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36

Challenge Information:

Build a Sorting Visualizer - Build a Sorting Visualizer

https://www.freecodecamp.org/learn/full-stack-developer/lab-sorting-visualizer/build-a-sorting-visualizer

would you be able to give your code formatted properly? right now there are many escaped characters and I am not able to know if they need to be there or not

When you enter a code block into a forum post, please precede it with three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add the backticks.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (').


```
const generateBtn = document.getElementById('generate-btn')
const startingArray = document.getElementById('starting-array')
const arrayContainer = document.getElementById('array-container')
const sortBtn = document.getElementById('sort-btn')


const generateElement = () => {
  const random = Math.floor(Math.random() * 100) + 1
  return random
}

const generateArray = () => {
  let randomIntergers = []

  for (let i = 0; i < 5; i++) {
    const numbers = generateElement()
    randomIntergers.push(numbers)
  }
  return randomIntergers
}
console.log(generateArray())

const generateContainer = () => {
  let emptyDiv = document.createElement('div')
  return emptyDiv
}

const fillArrContainer = (element, arr) => {
  element.innerHTML = `<span>${arr[0]}</span>
<span>${arr[1]}</span>
<span>${arr[2]}</span>
<span>${arr[3]}</span>
<span>${arr[4]}</span>
`
}

const isOrdered = (first, second) => {
  return first <= second
}

const swapElements = (arr, index) => {
  if (arr[index] > arr[index + 1]) {
    [arr[index], arr[index + 1]] = [arr[index + 1], arr[index]]
  }
  return arr;
}

const highlightCurrentEls = (element, index) => {
  const child = element.children[index]
  const secondChild = element.children[index + 1]
  child.style.border = 'dashed red'
  child.style.width = '20px'
  secondChild.style.border = 'dashed red'
  secondChild.style.width = '20px'
}

generateBtn.addEventListener('click', () => {
  // Clear previous sort steps
  Array.from(arrayContainer.children).forEach(child => {
    if (child.id !== 'starting-array') {
      arrayContainer.removeChild(child);
    }
  });


  // Generate new array
  const array = generateArray();

  // Fill #starting-array with five <span> elements
  startingArray.innerHTML = '';
  array.forEach(num => {
    const span = document.createElement('span');
    span.textContent = num;
    startingArray.appendChild(span);

  });
  
})

sortBtn.addEventListener('click', () => {
  // Clear previous steps but keep #starting-array
  Array.from(arrayContainer.children).forEach(child => {
    if (child.id !== 'starting-array') {
      arrayContainer.removeChild(child);
    }
  });

highlightCurrentEls(startingArray,0)
  // Get array from #starting-array
  const spans = startingArray.querySelectorAll('span');
  let arr = Array.from(spans).map(span => parseInt(span.textContent));

  const steps = [];

  // Push initial array state
  steps.push({ arr: [...arr], highlight: null });

  // Bubble Sort with step tracking
  for (let i = 0; i < arr.length; i++) {
    let swapped = false;
    for (let j = 0; j < arr.length - i - 1; j++) {
      const currentStep = { arr: [...arr], highlight: j };

      if (!isOrdered(arr[j], arr[j + 1])) {
        arr = swapElements(arr, j);
        currentStep.arr = [...arr]; // Update after swap
        swapped = true;
      }

      steps.push(currentStep); // Push every comparison step
    }
    if (!swapped) break;
  }

  // Push final sorted array
  steps.push({ arr: [...arr], highlight: null });

  // Render each step
  steps.forEach(({ arr: stepArr, highlight }) => {
    const stepDiv = generateContainer();
    stepArr.forEach((num, idx) => {
      const span = document.createElement('span');
      span.textContent = num;

      // Highlight compared elements
      if (highlight !== null && (idx === highlight || idx === highlight + 1)) {
        span.style.border = '2px dashed red';
        span.style.width = '20px';
        span.style.margin = '2px';
      }

      stepDiv.appendChild(span);
    });
    arrayContainer.appendChild(stepDiv);
  });
});

```

Please compare what your code is producing to what the example app is generating. Generate an array and sort it in the example app. Take a screenshot of that, then replace the call to generateArray() in your code with the same array generated in the example app for testing. Run your code and compare.

Your highlighting and swapping is off and you are ending the sorts too soon from what I’m seeing.

```

const generateBtn = document.getElementById('generate-btn')
const startingArray = document.getElementById('starting-array')
const arrayContainer = document.getElementById('array-container')
const sortBtn = document.getElementById('sort-btn')


const generateElement = () => {
  const random = Math.floor(Math.random() * 100) + 1
  return random
}

const generateArray = () => {
  let randomIntergers = []

  for (let i = 0; i < 5; i++) {
    const numbers = generateElement()
    randomIntergers.push(numbers)
  }
  return randomIntergers
}
console.log(generateArray())

const generateContainer = () => {
  let emptyDiv = document.createElement('div')
  return emptyDiv
}

const fillArrContainer = (element, arr) => {
  element.innerHTML = `<span>${arr[0]}</span>
<span>${arr[1]}</span>
<span>${arr[2]}</span>
<span>${arr[3]}</span>
<span>${arr[4]}</span>
`
}

const isOrdered = (first, second) => {
  return first <= second
}

const swapElements = (arr, index) => {
  if (arr[index] > arr[index + 1]) {
    [arr[index], arr[index + 1]] = [arr[index + 1], arr[index]]
  }
  return arr;
}

const highlightCurrentEls = (element, index) => {
  const child = element.children[index]
  const secondChild = element.children[index + 1]
  child.style.border = 'dashed red'
  child.style.width = '20px'
  secondChild.style.border = 'dashed red'
  secondChild.style.width = '20px'
}

generateBtn.addEventListener('click', () => {
  Array.from(arrayContainer.children).forEach(child => {
    if (child !== startingArray) {
      arrayContainer.removeChild(child);
    }
  });

  // Clear previous content in #starting-array
  startingArray.innerHTML = '';

  // Generate five random numbers and add them as <span> elements
  const array =generateArray();
  fillArrContainer(startingArray,array)

});

sortBtn.addEventListener('click', () => {
  // Get array from the first visual div in #array-container
  const spans = arrayContainer.firstElementChild.querySelectorAll('span');
  let arr = Array.from(spans).map(span => parseInt(span.textContent));

  // Clear all previous steps except the initial array
  const initialDiv = arrayContainer.firstElementChild;
  arrayContainer.innerHTML = '';
  arrayContainer.appendChild(initialDiv);

  const steps = [];
highlightCurrentEls(startingArray,0)

  // Bubble Sort with full comparison tracking
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - i - 1; j++) {
      if (!isOrdered(arr[j], arr[j + 1])) {
        arr = swapElements(arr, j);
      }

      // Push step after each comparison
      steps.push({ arr: [...arr], highlight: j });
    }
  }

  // Final step: Push sorted array
  steps.push({ arr: [...arr], highlight: null });

  // Render each step in #array-container
  steps.forEach(({ arr: stepArr, highlight }) => {
    const stepDiv = generateContainer();
    stepArr.forEach((num, idx) => {
      const span = document.createElement('span');
      span.textContent = num;
//console.log(span.textContent)
      if (highlight !== null && (idx === highlight || idx === highlight + 1)) {
        span.style.border = '2px dashed red';
        span.style.width = '20px';
        span.style.margin = '2px';
      }

      stepDiv.appendChild(span);
    });
//console.log(stepDiv.textContent)
    arrayContainer.appendChild(stepDiv);
  });
  
});

```

is it supposed to highlight exactly thesame numbers like the example app?

cuz i’ve fixed it an its left just test 18

Yes. Your code should function like the example app.

but can you give me a hint on what my code does wrong?cuz i noticed it doesnt highlight like the example app is the problem with my highlightcurrentEl func?

if it is highlighting the comparisons, your code is missing the comparisons till the end of each line

if your highlighting is not matching the comparisons, that is also an issue

its highlighting the swaped but at one point it doesnt follow the highlight trend

if it highlighting the swaps, then it’s your swaps that are not following the trend

there would not be enough lines to do all the swaps, so the issue is not the highlighting

```

const generateBtn = document.getElementById('generate-btn')
const startingArray = document.getElementById('starting-array')
const arrayContainer = document.getElementById('array-container')
const sortBtn = document.getElementById('sort-btn')


const generateElement = () => {
  const random = Math.floor(Math.random() * 100) + 1
  return random
}

const generateArray = () => {
  let randomIntergers = []

  for (let i = 0; i < 5; i++) {
    const numbers = generateElement()
    randomIntergers.push(numbers)
  }
  return randomIntergers
}
console.log(generateArray())

const generateContainer = () => {
  let emptyDiv = document.createElement('div')
  return emptyDiv
}

const fillArrContainer = (element, arr) => {
  element.innerHTML = `<span>${arr[0]}</span>
<span>${arr[1]}</span>
<span>${arr[2]}</span>
<span>${arr[3]}</span>
<span>${arr[4]}</span>
`
}

const isOrdered = (first, second) => {
  return first <= second
}

const swapElements = (arr, index) => {
  if (arr[index] > arr[index + 1]) {
    [arr[index], arr[index + 1]] = [arr[index + 1], arr[index]]
  }
  return arr;
}

const highlightCurrentEls = (element, index) => {
  const child = element.children[index]
  const secondChild = element.children[index + 1]
  child.style.border = 'dashed red'
  child.style.width = '22px'
  secondChild.style.border = 'dashed red'
  secondChild.style.width = '22px'
}

generateBtn.addEventListener('click', () => {
  Array.from(arrayContainer.children).forEach(child => {
    if (child !== startingArray) {
      arrayContainer.removeChild(child);
    }
  });

  // Clear previous content in #starting-array
  startingArray.innerHTML = '';

  // Generate five random numbers and add them as <span> elements
  const array =generateArray();
  fillArrContainer(startingArray,array)

});

sortBtn.addEventListener('click', () => {
  // Get array from the first visual div in #array-container
  const spans = arrayContainer.firstElementChild.querySelectorAll('span');
 
  let arr = Array.from(spans).map(span => parseInt(span.textContent));

  // Clear all previous steps except the initial array
  const initialDiv = arrayContainer.firstElementChild;
  arrayContainer.innerHTML = '';
  arrayContainer.appendChild(initialDiv);

  const steps = [];
  
highlightCurrentEls(initialDiv,0)

  // Bubble Sort with full comparison tracking
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - i -1; j++) {
      
      if (!isOrdered(arr[j], arr[j + 1])) {
        arr = swapElements(arr, j);
     
      }

      steps.push({ arr: [...arr], highlight: j})
    
    }
  }

  // Final step: Push sorted array
  steps.push({ arr: [...arr], highlight: null });

  // Render each step in #array-container
  steps.forEach(({ arr: stepArr, highlight }) => {
    const stepDiv = generateContainer();
    stepArr.forEach((num, idx) => {
      const span = document.createElement('span');
      span.textContent = num;
//console.log(span.textContent)

      stepDiv.appendChild(span);
     
    });
     if (highlight !== null) {
  // After all spans are appended to stepDiv
  // We'll highlight the current comparison pair
  highlightCurrentEls(stepDiv, highlight);
}
//console.log(stepDiv.textContent)
    arrayContainer.appendChild(stepDiv);
  });
  
});

```

the highlight trend always breaks i dont know why

What pattern should j return inside your second loop? Use console.log() to help you see what is going on.

{ arr: [ 76, 96, 7, 57, 7 ], highlight: 0 }
{ arr: [ 76, 7, 96, 57, 7 ], highlight: 1 }
{ arr: [ 76, 7, 57, 96, 7 ], highlight: 2 }
{ arr: [ 76, 7, 57, 7, 96 ], highlight: 3 }
{ arr: [ 7, 76, 57, 7, 96 ], highlight: 0 }
{ arr: [ 7, 57, 76, 7, 96 ], highlight: 1 }
{ arr: [ 7, 57, 7, 76, 96 ], highlight: 2 }
{ arr: [ 7, 57, 7, 76, 96 ], highlight: 0 }
{ arr: [ 7, 7, 57, 76, 96 ], highlight: 1 }
{ arr: [ 7, 7, 57, 76, 96 ], highlight: 0 }

should it go that way? 0,1,2,3 then 0,1,2 then 0,1 then 0? why does it not go to 3 all the time?

i tried to make it return this.

{ arr: [ ], highlight: 0 }
{ arr: [ ], highlight: 1 }
{ arr: [ ], highlight: 2 }
{ arr: [ ], highlight: 3 }
{ arr: [ ], highlight: 0 }
{ arr: [ ], highlight: 1 }
{ arr: [ ], highlight: 2 }
{ arr: [ ], highlight: 3 }
{ arr: [ ], highlight: 0 }
{ arr: [ ], highlight: 1 }
{ arr: [ ], highlight: 2 }
{ arr: [ ], highlight: 3 }
but the steps became too many and it failed test19
```
const generateBtn = document.getElementById('generate-btn')
const startingArray = document.getElementById('starting-array')
const arrayContainer = document.getElementById('array-container')
const sortBtn = document.getElementById('sort-btn')


const generateElement = () => {
  const random = Math.floor(Math.random() * 100) + 1
  return random
}

const generateArray = () => {
  let randomIntergers = []

  for (let i = 0; i < 5; i++) {
    const numbers = generateElement()
    randomIntergers.push(numbers)
  }
  return randomIntergers
}

const generateContainer = () => {
  let emptyDiv = document.createElement('div')
  return emptyDiv
}

const fillArrContainer = (element, arr) => {
  element.innerHTML = `<span>${arr[0]}</span>
<span>${arr[1]}</span>
<span>${arr[2]}</span>
<span>${arr[3]}</span>
<span>${arr[4]}</span>
`
}

const isOrdered = (first, second) => {
  return first <= second
}

const swapElements = (arr, index) => {
  if (arr[index] > arr[index + 1]) {
    [arr[index], arr[index + 1]] = [arr[index + 1], arr[index]]
  }
  return arr;
}

const highlightCurrentEls = (element, index) => {
  const child = element.children[index]
  const secondChild = element.children[index + 1]
  child.style.border = 'dashed red'
  child.style.width = '22px'
  secondChild.style.border = 'dashed red'
  secondChild.style.width = '22px'
}

generateBtn.addEventListener('click', () => {
  Array.from(arrayContainer.children).forEach(child => {
    if (child !== startingArray) {
      arrayContainer.removeChild(child);
    }
  });

  // Clear previous content in #starting-array
  startingArray.innerHTML = '';

  // Generate five random numbers and add them as <span> elements
  const array =generateArray();
  fillArrContainer(startingArray,array)

});

sortBtn.addEventListener('click', () => {
  // Get array from the first visual div in #array-container
  const spans = arrayContainer.firstElementChild.querySelectorAll('span');
 
  let arr = Array.from(spans).map(span => parseInt(span.textContent));

  // Clear all previous steps except the initial array
  const initialDiv = arrayContainer.firstElementChild;
  arrayContainer.innerHTML = '';
  arrayContainer.appendChild(initialDiv);

  const steps = [];

highlightCurrentEls(initialDiv,0)

  // Bubble Sort with full comparison tracking
  for (let i = 0; i < arr.length ; i++) {
    for (let j = 0; j < arr.length -1; j++) {
    
      if (!isOrdered(arr[j], arr[j + 1])) {
        arr = swapElements(arr, j);
      //steps.push({ arr: [...arr], highlight: j})
    
      }
console.log({ arr: [...arr], highlight: j})
  
     steps.push({ arr: [...arr], highlight: j})
    
     
    }
  }

  // Final step: Push sorted array
  steps.push({ arr: [...arr], highlight: null });

  // Render each step in #array-container
  steps.forEach(({ arr: stepArr, highlight }) => {
    const stepDiv = generateContainer();
    stepArr.forEach((num) => {
      const span = document.createElement('span');
      span.textContent = num;
//console.log(span.textContent)

      stepDiv.appendChild(span);
     
    });
     if (highlight !== null) {
  // After all spans are appended to stepDiv
  // We'll highlight the current comparison pair
  highlightCurrentEls(stepDiv, highlight);
}
//console.log(stepDiv.textContent)
    arrayContainer.appendChild(stepDiv);
  });
  
});

```

any help..? please.. anyone ?