2

I have a set of grid boxes that when i switch color pallet to a particular color, on mouse hover it should change to that color and when i click the rgb button the random color should override the color pallet that was first initialized. But rbg button is displaying null because its outside of drawGrid() function

So the issue I am having is how to make both work at a different interval, whenever rbg button is clicked it should override the color pallet and vice versa.

function drawGrid(container, col, row) {
  const box = document.createElement('div');
  box.className = 'box';
  box.id = `box${col}${row}`;

  // Wehn color pallet is clicked mouseenter radom colors and it should ignore rbg button
  const bgColor = document.querySelector('#bg-color');
  box.addEventListener('mouseenter', () => {
  box.style.backgroundColor = bgColor.value;
  });

  container.appendChild(box);
  return (box);
}


function createBox(container) {
  const grid = document.createElement('div');
  grid.className = 'grid';

  for(let i = 0; i < 6; i++) {
    for(let j = 0; j < 5; j++) {
      drawGrid(grid, i, j);
    }
  }
  container.appendChild(grid);
}

function startupGrid() {
  const game = document.querySelector('#game');
  createBox(game)
}
startupGrid()

// Wehn rbg button is clicked mouseenter random colors and it should ignore color pallet
const rgb = document.querySelector('#rgb');
rgb.addEventListener('mouseenter', () => {
  let r = Math.floor(Math.random() * 256);
  let g = Math.floor(Math.random() * 256);
  let b = Math.floor(Math.random() * 256);
  let switchToRgb = `rgb ${r},${g},${b}`;
  box.style.backgroundColor = switchToRgb;
})
body {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.main {
  display: flex;
  justify-content: center;
  align-items: center;
  place-items: center;
  gap: 2rem;
  margin: 5rem;
}

.controls {
  display: grid;
  gap: 1rem;
}

button {
  padding: 5px 15px;
}


#game {
  display: grid;
  place-items: center;
  
}

.box {
  width: 40px;
  height: 30px;
  border: 1px solid;
}

.grid {
  display: grid;
  grid-template-columns: repeat(6, auto);
  grid-template-rows: repeat(5, auto);
  box-sizing: border-box;
  gap: 1px;
  background: rgb(255, 255, 255)
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Grid</title>
  <link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>

  <div class="main">
    <div class="controls">
      <input type="color" id="bg-color">
      <button id="rgb">RBG</button>
    </div>
     
    <div id="game"></div>
  </div>
  <script src="script.js"></script>
</body>
</html>

whereas if i add box to the addEventlistener inside drawGrid() function instead or rgb it works, but then the color pallet will stop working.

box.addEventListener('mouseenter', () => {
  let r = Math.floor(Math.random() * 256);
  let g = Math.floor(Math.random() * 256);
  let b = Math.floor(Math.random() * 256);
  let switchToRgb = `rgb ${r},${g},${b}`;
  box.style.backgroundColor = switchToRgb;
})

First image is when color pallet is changed Example image

4
  • Your button has the id rbg not rgb as your code is expecting Commented May 11, 2022 at 12:01
  • Also, rgb is a CSS function and has it's parameters surrounded by parentheses i.e. rgb(${r}, ${g}, ${b}) - link to the docs Commented May 11, 2022 at 12:04
  • Oh thanks, I just edited it. Now box is showing undefined because its outside drawGrid() function, so i tried adding it inside the function and i didn't receive any error, but the button is not working, is there a way I can call drawGrid() inside the addEventListener so that when the button is clicked the random color should display on mousehover Commented May 11, 2022 at 12:12
  • You don't need to, see my answer below Commented May 11, 2022 at 12:21

1 Answer 1

2

The first issue is the format of the color string you want to set the input as, it needs to be the right format #RRGGBB Input color value docs

let switchToRgb = `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`;

See update below about properly creating this colour string

this will create the string in the right format by converting each decimal value to hexadecimal and formatting the string with a leading #.

That's right box doesn't exist at that point, you will have to get it inside the event listener. You should also set the input's value as this will change the rendered colours in the grid.

document.getElementById('bg-color').value = switchToRgb;

It strikes me as a bit weird that you're using mouseenter event on a button. Why don't you use click like most people, this will prevent accidental changes to the colour - FIXED

UPDATE - OP wants to use either a random colour each time the background color is set or use the value from color picker

You will need to keep track of whether to use a random color or use the color picked value.

let useRandomColor = false;

We'll default this to false but update it when either a specific colour is picked or the random colour button is clicked.

document.getElementById('rgb')
  .addEventListener('click', () => {
    useRandomColor = true;
  });
  
const colorPicker = document.getElementById('bg-color');
colorPicker.addEventListener('change', () => {
  useRandomColor = false;
});

Then we just need to use this value to figure out whether the picked colour is used or whether to use a random value

We also need to make sure we do this for each box

// get all the boxes 
const boxes = document.querySelectorAll('.box');
for (let box of boxes) {
  // add an event listener to each box
  box.addEventListener('mouseenter', (e) => {
    // set default value as the current value of the colour picker
    let color = colorPicker.value;

    // Override this with a random colour if needed
    if (useRandomColor){
      let r = Math.floor(Math.random() * 256);
      let g = Math.floor(Math.random() * 256);
      let b = Math.floor(Math.random() * 256);
      color = `#${r.toString(16).padStart(2, '0'}${g.toString(16)}${b.toString(16)}`;
    }

    // Set the background colour of the hovered box
    e.target.style.backgroundColor = color;
  });
};

UPDATE - Use padded hex values

As @enhzflep pointed out, the colour value needs to be exactly either 3 or 6 hex digits, so we need to ensure the generated colour has exactly 6 hex digits.

const getColourString = (r, g, b) => {
  return '#' + [r, g, b].map(x => x.toString(16).padStart(2, '0')).join('');
};

This will take our rgb colour components and make sure the value is the correct format.

We will then use this in setting the box background colour

e.target.style.backgroundColor = color;

let useRandomColor = false;

function drawGrid(container, col, row) {
  const box = document.createElement('div');
  box.className = 'box';
  box.id = `box${col}${row}`;

  container.appendChild(box);
  return (box);
}


function createBox(container) {
  const grid = document.createElement('div');
  grid.className = 'grid';

  for(let i = 0; i < 6; i++) {
    for(let j = 0; j < 5; j++) {
      drawGrid(grid, i, j);
    }
  }
  container.appendChild(grid);
}

function startupGrid() {
  const game = document.querySelector('#game');
  createBox(game)
}
startupGrid()

// When rgb button is clicked mouseenter random colors and it should ignore color pallet
document.getElementById('rgb')
  .addEventListener('click', () => {
    useRandomColor = true;
  });
  
const colorPicker = document.getElementById('bg-color');
colorPicker.addEventListener('change', () => {
  useRandomColor = false;
})

  // Wehn color pallet is clicked mouseenter radom colors and it should ignore rbg button
const boxes = document.querySelectorAll('.box');
for (let box of boxes) {
  box.addEventListener('mouseenter', (e) => {
    let color = colorPicker.value;

    if (useRandomColor){
      let r = Math.floor(Math.random() * 256);
      let g = Math.floor(Math.random() * 256);
      let b = Math.floor(Math.random() * 256);
      color = getColourString(r, g, b);
    }

    e.target.style.backgroundColor = color;
  });
};

const getColourString = (r, g, b) => {
  return '#' + [r, g, b].map(x => x.toString(16).padStart(2, '0')).join('');
};
body {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.main {
  display: flex;
  justify-content: center;
  align-items: center;
  place-items: center;
  gap: 2rem;
  margin: 5rem;
}

.controls {
  display: grid;
  gap: 1rem;
}

button {
  padding: 5px 15px;
}


#game {
  display: grid;
  place-items: center;
  
}

.box {
  width: 40px;
  height: 30px;
  border: 1px solid;
}

.grid {
  display: grid;
  grid-template-columns: repeat(6, auto);
  grid-template-rows: repeat(5, auto);
  box-sizing: border-box;
  gap: 1px;
  background: rgb(255, 255, 255)
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Grid</title>
  <link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>

  <div class="main">
    <div class="controls">
      <input type="color" id="bg-color">
      <button id="rgb">Random Colour</button>
    </div>
     
    <div id="game"></div>
  </div>
  <script src="script.js"></script>
</body>
</html>

Sign up to request clarification or add additional context in comments.

8 Comments

When color pallet is black, if button is clicked initialize random color when mousehovers on the boxes, and when color pallet is changed to another color it should override the random color on mousehover
Does that not happen. Clicking the button sets a random colour which is used when the mouse hovers over the grid to the right. If you pick a specific colour then that colour is used. Are you saying that all the coloured boxes should change to match the color input colour when the color input's value is changed?
What if you use r=g=b=15? (#0F0F0F) Answer - you get back #FFF. (15).toString(16) = F. You need it to return 0F
@enhzflep updated to pad hex colour properly
@callmeog See updated answer
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.