Home > Mobile >  Bubble sort visualiser swap on next button click
Bubble sort visualiser swap on next button click

Time:08-09

I am creating a bubble sort visualiser and wanted to check value of two div and swipe them on next button click but not able to do

This is a bubble sort visualizer which check 1st and 2nd number from the first and second div and compare them. if found first one is greater just changes the div position on button click.

Example :- User enters 1,2,3,4,5 and clicks create array button. 5 divs with class "num" are created, each also have class "num-1", "num-2" and so on.

They are all inside the div "num-holder".

On clicking "sort-btn", "num-1" and "num-2" will be highlighted, since these are the first 2 comparisons in the algorithm, followed by "num-2" and "num-3" and so on.

This is a sorted array so all comparisons will show, but no element will change its position.

So if instead the array was 2,1,3,4,5.

On first comparison "num-1" and "num-2" will highlight and their order attribute will change to each other so they switch places.

let createBtn = document.getElementById('create-btn');
let numsArray = [];
var div;
let newArray = [];


createBtn.addEventListener('click', () => {
  //creating array of integer.
  let data = document.getElementById('numbers_input').value;
  let newData = data.split(',');
  newArray = newData.map(num => {
    return Number(num);
  })
  //console.log(newArray);
  let dataHolder = document.querySelector('.num-holder');

  // adding div element to dom 
  for (let i = 0; i < newArray.length; i  ) {

    div = document.createElement('div');
    div.innerHTML = newArray[i];
    div.className = `num num-${i}`;
    // div.style.order = `${newArray[i]}`;
    div.setAttribute('data-val', newArray[i]);
    dataHolder.appendChild(div);
    console.log(div);
  }
})

//swapping logic.
let sortBtn = document.getElementById('sort-btn');

for (let i = 0; i < newArray.length - 1; i  ) {
  for (let j = 0; j < newArray.length - i; j  ) {
    let sortBtn = document.getElementById('sort-btn');
    sortBtn.addEventListener('click', () => {
      let num1 = document.querySelector(`.num-${j}`);
      let num2 = document.querySelector(`.num-${j 1}`);
      console.log(num1, num2);

      if (num1.innerHTML > num2.innerHTML) {
        num1.style.order = `${newArray[j]}`;
        num2.style.order = `${newArray[j   1]}`;
      }

    })
  }

}
.num-holder {
  display: flex;
  justify-content: space-between;
  margin-top: 50px;
  margin-bottom: 10px;
}

.num {
  background-color: rgba(227, 130, 130, 0.53);
  font-size: 30px;
}


.as-console-wrapper { height: 40px }
<label>Enter numbers seperated by comma here</label>
<input type="text" id="numbers_input">
<button type="button" id="create-btn">Create Array</button>
<div ></div>
<button id="sort-btn"  type="button">Next</button>

<script src="index.js"></script>

CodePudding user response:

This seems a good case for a generator function: one that yields the DOM elements that need to be "swapped" (actually, their order CSS attributes). This function will be called with the original array and returns an iterator that can be used to step through the sorting process, step by step.

The "Next" button handler should only be created once, and it could take the next pair of DOM elements from the above mentioned iterator.

Here is an implementation:

function* sorter(array) {
    for (let i = 0; i < array.length - 1; i  ) {
        for (let j = 0; j < array.length - i - 1; j  ) {
            if (array[j][0] > array[j   1][0]) {
                // yield the two DOM elements that need their order swapped
                yield [array[j][1], array[j   1][1]];
                // Swap in array
                array.splice(j, 2, array[j   1], array[j]);
            }
        }
    }
}

const createBtn = document.getElementById('create-btn');
const sortBtn = document.getElementById('sort-btn');
const dataHolder = document.querySelector('.num-holder');
const inputControl = document.getElementById('numbers_input');
let swapIterator; // Initialised when creating array

createBtn.addEventListener('click', () => {
    dataHolder.innerHTML = "";
    // creating array of integers.
    const data = inputControl.value.split(',').map(Number);

    // Adding div element to dom, and
    // Creating an array of pairs (value & DOM element)
    const dataAndDivs = data.map((value, i) => {
        const div = document.createElement('div');
        div.textContent = value;
        div.className = "num";
        div.style.order = i;        
        dataHolder.appendChild(div);
        return [value, div];
    });
    // Get an iterator that will yield pairs of DOM elements
    swapIterator = sorter(dataAndDivs);
});

sortBtn.addEventListener('click', () => {
    if (!swapIterator) return; // First an array should be created
    const {value, done} = swapIterator.next();
    if (done) return; // Already sorted
    const [{style: a}, {style: b}] = value;
    [a.order, b.order] = [b.order, a.order];
});
.num-holder {
  display: flex;
  justify-content: space-between;
  margin-top: 50px;
  margin-bottom: 10px;
}

.num {
  background-color: rgba(227, 130, 130, 0.53);
  font-size: 30px;
}
<label>Enter numbers seperated by comma here
<input type="text" id="numbers_input" value="20,12,6,5,3,1"></label>
<button type="button" id="create-btn">Create Array</button>
<div ></div>
<button id="sort-btn"  type="button">Next</button>

CodePudding user response:

I fixed you code by creating a function accepting the step and and sorts for that step. I used a global variable to keep track of current step.

Take a look at logic function.

Also your implementation is confusing since order style was out of sync with actual class names, I completely removed order and also numbered class that you used, I used the actual order of the element in the container DOM instead.

let createBtn = document.getElementById('create-btn');
let numsArray = [];
var div;
let newArray = [];
let currentJ
let dataHolder = document.querySelector('.num-holder');


createBtn.addEventListener('click', () => {
    //reset all
    dataHolder.replaceChildren();
    newArray = [];
    numsArray = [];
    currentJ = 1
    
    //creating array of integer.
    let data = document.getElementById('numbers_input').value;
    let newData = data.split(',');
    newArray = newData.map(num => {
        return Number(num);
    })

    // adding div element to dom 
    for (let i = 0; i < newArray.length; i  ) {
        div = document.createElement('div');
        div.innerHTML = newArray[i];
        div.className = `num`;
        dataHolder.appendChild(div);
    }
})

//swapping logic.
let logic = (j) => {
    let num1 = document.querySelector(`.num-holder :nth-child(${j})`);
    let num2 = document.querySelector(`.num-holder :nth-child(${j 1})`);

    if (num1 == null || num2 == null) { 
      // reached the end of this pass, reset J to go to next pass
      currentJ = 1;
      //styling comparing items
      document.querySelectorAll('.num-holder div').forEach(el => {
        el.style.backgroundColor = '';
      });
      return;
    }
    
    if ( num1.innerHTML >  num2.innerHTML) {
      dataHolder.insertBefore(num2, num1)
    }
    
    //styling comparing items
    document.querySelectorAll('.num-holder div').forEach(el => {
        el.style.backgroundColor = '';
    });
    num1.style.backgroundColor = "orange"
    num2.style.backgroundColor = "orange"
}


let sortBtn = document.getElementById('sort-btn');
sortBtn.addEventListener('click', () => logic(currentJ  ) )
.num-holder {
    display: flex;
    justify-content: space-between;
    margin-top: 50px;
    margin-bottom: 10px;
}
.num {
    background-color: rgba(227, 130, 130, 0.53);
    font-size: 30px; 
    padding: 10px;
    border-radius: 30px;
}

.num-comparing {
    background-color: yellow;
}
<label>Enter numbers seperated by comma here</label>
<input type="text" id="numbers_input" value="5,4,3,2,1">
<button type="button" id="create-btn">Create Array</button>
<div ></div>
<button id="sort-btn"  type="button">Next</button>

  • Related