I am working on a basic sorting visualizer with using only HTML, CSS, and JS, and I've run into a problem with the animation aspect. To initialize the array, I generate random numbers within some specified range and push them on to the array. Then based on the webpage dimensions, I create divs for each element and give each one height and width dimensions accordingly, and append each to my "bar-container" div currently in the dom.
function renderVisualizer() {
var barContainer = document.getElementById("bar-container");
//Empties bar-container div
while (barContainer.hasChildNodes()) {
barContainer.removeChild(barContainer.lastChild);
}
var heightMult = barContainer.offsetHeight / max_element;
var temp = barContainer.offsetWidth / array.length;
var barWidth = temp * 0.9;
var margin = temp * 0.05;
//Creating array element bars
for (var i = 0; i < array.length; i++) {
var arrayBar = document.createElement("div");
arrayBar.className = "array-bar"
if (barWidth > 30)
arrayBar.textContent = array[i];
//Style
arrayBar.style.textAlign = "center";
arrayBar.style.height = array[i] * heightMult + "px";
arrayBar.style.width = barWidth;
arrayBar.style.margin = margin;
barContainer.appendChild(arrayBar);
}
}
I wrote the following animated selection sort and it works well, but the only "animated" portion is in the outer for-loop, and I am not highlighting bars as I traverse through them.
function selectionSortAnimated() {
var barContainer = document.getElementById("bar-container");
var barArr = barContainer.childNodes;
for (let i = 0; i < barArr.length - 1; i++) {
let min_idx = i;
let minNum = parseInt(barArr[i].textContent);
for (let j = i + 1; j < barArr.length; j++) {
let jNum = parseInt(barArr[j].textContent, 10);
if (jNum < minNum) {
min_idx = j;
minNum = jNum;
}
}
//setTimeout(() => {
barContainer.insertBefore(barArr[i], barArr[min_idx])
barContainer.insertBefore(barArr[min_idx], barArr[i]);
//}, i * 500);
}
}
I am trying to use nested setTimeout calls to highlight each bar as I traverse through it, then swap the bars, but I'm running into an issue. I'm using idxContainer object to store my minimum index, but after each run of innerLoopHelper, it ends up being equal to i and thus there is no swap. I have been stuck here for a few hours and am utterly confused.
function selectionSortTest() {
var barContainer = document.getElementById("bar-container");
var barArr = barContainer.childNodes;
outerLoopHelper(0, barArr, barContainer);
console.log(array);
}
function outerLoopHelper(i, barArr, barContainer) {
if (i < array.length - 1) {
setTimeout(() => {
var idxContainer = {
idx: i
};
innerLoopHelper(i + 1, idxContainer, barArr);
console.log(idxContainer);
let minIdx = idxContainer.idx;
let temp = array[minIdx];
array[minIdx] = array[i];
array[i] = temp;
barContainer.insertBefore(barArr[i], barArr[minIdx])
barContainer.insertBefore(barArr[minIdx], barArr[i]);
//console.log("Swapping indices: " + i + " and " + minIdx);
outerLoopHelper(++i, barArr, barContainer);
}, 100);
}
}
function innerLoopHelper(j, idxContainer, barArr) {
if (j < array.length) {
setTimeout(() => {
if (j - 1 >= 0)
barArr[j - 1].style.backgroundColor = "gray";
barArr[j].style.backgroundColor = "red";
if (array[j] < array[idxContainer.idx])
idxContainer.idx = j;
innerLoopHelper(++j, idxContainer, barArr);
}, 100);
}
}
I know this is a long post, but I just wanted to be as specific as possible. Thank you so much for reading, and any guidance will be appreciated!
i, using closure to preserve its value at time of calling setTimeout instead of function execution time. lookup about using setTimeout in loops.