i don't now how use background from js - javascript

I am a newbie to js and I would like to know how you can use background from javascript let's say I can set the color of a button by doing this:
const btnPulsado = (e) =>{
const btn= e.target;
btn.style.backgroundColor= 'red';
can I do it somehow with backgroundImage?

You can use
e.target.style.backgroundColor = __ANY_COLOR_CODE;
function genRanHex(size) {
return [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('')
}
const btn = document.querySelector("button");
btn.addEventListener("click", e => {
e.target.style.backgroundColor = `#${genRanHex(6)}`;
})
<button> click me to change color </button>

Related

Unresponsive button in a modified hoverboard for a HTML file

I'm trying to create a modified hoverboard from an Udemy project. The original included a set of 500 squares generated via a JavaScript file where a for loop was called in order to generate them.
What I want to do here is add an input and a button in order to be able to select the number of squares directly from the input (any value from 1 to 999 squares), and generate it via JS. However, when I click OK nothing happens
This is the code from the JS file below:
const container = document.getElementById('container');
const colors = ['white', 'grey', 'rebeccapurple', 'steelblue', 'darkred', 'darkgreen', 'lightblue'];
const SQUARES = document.getElementById('input');
const button = document.getElementById('button');
button.addEventListener('click', () => clickButton(SQUARES));
function clickButton() {
for (let i = 0; i < SQUARES; i++) {
if (SQUARES < 1000) {
const square = document.createElement('div');
square.classList.add('square');
square.addEventListener('mouseover', () => setColor(square));
square.addEventListener('mouseout', () => removeColor(square));
container.appendChild(square);
}
else {
alert('The input is out of bounds.');
}
}
}
function setColor(element) {
const color = getRandomColor();
element.style.background = color;
element.style.boxShadow = `0 0 2px ${color}, 0 0 10px ${color}`;
}
function removeColor(element) {
element.style.background = '#1d1d1d';
element.style.boxShadow = '0 0 2px #000';
}
function getRandomColor() {
return colors[Math.floor(Math.random() * colors.length)];
}
What should I try? I'm thinking that the button event listener is incorrectly defined, mainly that the ClickButton function should have something else in place of SQUARES, but I'm not sure at all what I should use instead.

Repetition of two variables one after the other in Math.random()

I wrote the following code to randomly change the background color, but sometimes the two colors are repeated one after the other .... How do you think I can write the code so that the two colors are not repeated one after the other?
const colors = ["green", "red", "rgba(133,122,200)", "#f15025"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
btn.addEventListener("click", function() {
const randomNumber = getRandomNumber()
document.body.style.backgroundColor = colors[randomNumber];
color.textContent = colors[randomNumber]
})
function getRandomNumber() {
return Math.floor(Math.random() * colors.length)
}
<h2>background color : <span class="color">#f1f5f8</span></h2>
<button class="btn btn-hero" id="btn">click me</button>
This will happen because since it is completely random you might get the same number again.
You can put a while loop to ensure you are getting a new color every time. Keep a loop that keeps on running unless you get a new number.
Here prevNumber is used to keep track of the previous number. Now the code keeps on generating a new number until you have a different number from the previous one.
const colors = ["green", "red", "rgba(133,122,200)", "#f15025"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
let prevNumber = 0;
btn.addEventListener("click", function() {
let randomNumber = getRandomNumber();
while(randomNumber == prevNumber){
randomNumber = getRandomNumber();
}
prevNumber = randomNumber;
document.body.style.backgroundColor = colors[randomNumber];
color.textContent = colors[randomNumber]
})
function getRandomNumber() {
return Math.floor(Math.random() * colors.length)
}
<h2>background color : <span class="color">#f1f5f8</span></h2>
<button class="btn btn-hero" id="btn">click me</button>
You could save the last number generated. If that number comes back again, get another one.
const colors = ["green", "red", "rgba(133,122,200)", "#f15025"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
let last = -1
btn.addEventListener("click", function() {
let randomNumber = getRandomIndex()
document.body.style.backgroundColor = colors[randomNumber];
color.textContent = colors[randomNumber]
})
function getRandomIndex() {
let randomIndex = Math.floor(Math.random() * colors.length)
if (randomIndex === last) {
return randomIndex = getRandomIndex()
} else {
last = randomIndex
return randomIndex
}
}
<h2>background color : <span class="color">#f1f5f8</span></h2>
<button class="btn btn-hero" id="btn">click me</button>
Both current answers are totally ok. If you want to randomize just once you can do:
const colors = ["green", "red", "rgba(133,122,200)", "#f15025"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
let currentColor = colors.pop();
btn.addEventListener("click", function() {
const randomNumber = getRandomNumber()
document.body.style.backgroundColor = colors[randomNumber];
color.textContent = colors[randomNumber]
})
function getRandomNumber() {
const chosen = Math.floor(Math.random() * colors.length)
const newColor = colors[chosen];
colors.splice(chosen,1,currentColor);
currentColor = newColor;
return chosen;
}
<h2>background color : <span class="color">#f1f5f8</span></h2>
<button class="btn btn-hero" id="btn">click me</button>
This way you prevent the current colour to be selected, and once the randomization has been done, you insert the one left out while removing the newly selected
write closure like noConsecutiveRandom to get random number but not consecutively repeat.
const colors = ["green", "red", "rgba(133,122,200)", "#f15025"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
function noConsecutiveRandom(size) {
let last;
return function rand() {
const cur = Math.floor(Math.random() * size);
return cur === last ? rand() : (last = cur);
};
}
const getRandomNumber = noConsecutiveRandom(colors.length);
btn.addEventListener("click", function() {
const randomNumber = getRandomNumber()
document.body.style.backgroundColor = colors[randomNumber];
color.textContent = colors[randomNumber]
})
<h2>background color : <span class="color">#f1f5f8</span></h2>
<button class="btn btn-hero" id="btn">click me</button>

change array element value's style

im building a to-do list but cant figure out how to keep my array values that have line-through decoration.
the moment render method is called, the array is built from the start. means that if i delete an li, all other li that have been marked by the checkbox with a line-through, losing the decoration.
what can i do to keep the line-through ?
i tried so far in the markTask method to replace the original value with the value that have line-through on it but it didn't work.
basically what im trying to accomplish is by inserting the value with line-through, to be able to check if this value have the line-through style and after the render to be able to keep the checked checkboxes as checked.
my code so far:
class Todo {
constructor() {
this.input = document.getElementById("input");
this.ul = document.getElementById("ul");
this.form = document.getElementById("form");
this.tasks = [];
this.registerEvent();
}
registerEvent() {
this.form.addEventListener("submit", (event) => {
event.preventDefault();
this.createTask(this.input.value);
this.form.reset();
});
}
createTask(task) {
if (task.trim().length === 0) {
return;
}
this.tasks.push(task);
this.render();
}
deleteTask(task) {
const myTask = task.target;
const parent = myTask.parentNode;
const taskToRemove = parent.childNodes[1].textContent;
const index = this.tasks.indexOf(taskToRemove);
this.tasks.splice(index, 1);
this.render();
}
markTask(task) {
const myTask = task.target;
const parent = myTask.parentNode;
if (myTask.checked) {
parent.style.textDecoration = "line-through";
} else {
parent.style.textDecoration = "none";
}
}
render() {
this.ul.innerHTML = "";
this.tasks.forEach((task) => {
const li = document.createElement("li");
const cb = document.createElement("input");
cb.type = "checkbox";
cb.addEventListener("click", (e) => {
this.markTask(e);
});
li.appendChild(cb);
li.append(document.createTextNode(task));
const btn = document.createElement("button");
li.appendChild(btn);
btn.textContent = "Delete";
btn.classList.add("remove");
btn.addEventListener("click", (e) => {
this.deleteTask(e);
});
this.ul.appendChild(li);
});
}
}
new Todo();
<form id="form">
<input id="input" />
<button id="add">Add</button>
</form>
<ul id="ul">
</ul>
it's because you're not tracking which tasks are done and you're just pushing strings. for your createTask method you need to push an object with a done property to indicate which tasks have been done like so
createTask(task) {
if (task.trim().length === 0) {
return;
}
this.tasks.push({title: task, done: false});
this.render();
}
update your render to account for tasks already done
render() {
this.ul.innerHTML = "";
this.tasks.forEach((task) => {
const li = document.createElement("li");
const cb = document.createElement("input");
cb.type = "checkbox";
cb.addEventListener("click", (e) => {
this.markTask(e);
});
li.appendChild(cb);
li.append(document.createTextNode(task.title));
const btn = document.createElement("button");
li.appendChild(btn);
btn.textContent = "Delete";
btn.classList.add("remove");
btn.addEventListener("click", (e) => {
this.deleteTask(e);
});
this.ul.appendChild(li);
if (task.done) {
cb.checked = true;
li.style.textDecoration = "line-through";
} else {
cb.checked = false;
li.style.textDecoration = "none";
}
});
}
in your constructor update your tasks variable to see this in effect
constructor() {
this.input = document.getElementById("input");
this.ul = document.getElementById("ul");
this.form = document.getElementById("form");
this.tasks = [{title: 'mill', done: true}, {title: 'jus', done: false}];
this.registerEvent();
}
hope you get the general idea. I won't do the entire implementation on markTask as this should be enough to give you a view of what the solution should be. good luck.
If I may, I have revised your code a bit.
The technique you need is event delegation:
any click on a child element is also a click on its parent elements. we plas the event listener on the parent and we see on which child element it occurred.
In your case, this only makes one event listerner for all your 'remove' buttons.
the other idea is not to ignore the DOM, it also keeps the list of tasks, you don't need to keep them in a table in memory, this is redundant.
here is the code: css is also helfull
class Todo
{
constructor()
{
this.form = document.getElementById('todo-form')
this.liste = document.getElementById('todo-list')
this.form.onsubmit = e => this.addTask(e)
this.liste.onclick = e => this.delTask(e)
}
addTask(e)
{
e.preventDefault()
if (this.form.task.value.trim() === '') return
let li = document.createElement('li')
, cb = document.createElement('input')
, sp = document.createElement('span')
, bt = document.createElement('button')
;
cb.type = 'checkbox'
sp.textContent = this.form.task.value
bt.textContent = 'Delete'
bt.className = 'remove'
li.appendChild(cb)
li.appendChild(sp)
li.appendChild(bt)
this.liste.appendChild(li)
this.form.reset()
}
delTask(e)
{
if (!e.target.matches('button.remove')) return // reject others clicks
e.target.closest('li').remove()
}
}
new Todo();
#todo-list li > span {
display : inline-block;
background-color : whitesmoke;
width : 20em;
}
#todo-list li input[type=checkbox]:checked + span {
text-decoration : line-through;
}
#todo-list li button.remove {
font-size: .6em;
}
<form id="todo-form">
<input name="task">
<button type="submit">Add</button>
</form>
<ul id="todo-list"></ul>
As you can see this code is shorter. You can also use a IIFE unstead of a class, like that :
(function() // IIFE
{
let form = document.getElementById('todo-form')
, liste = document.getElementById('todo-list')
;
form.onsubmit = e => // addTask
{
e.preventDefault()
if (form.task.value.trim() === '') return
let li = document.createElement('li')
, cb = document.createElement('input')
, sp = document.createElement('span')
, bt = document.createElement('button')
;
cb.type = 'checkbox'
sp.textContent = form.task.value
bt.textContent = 'Delete'
bt.className = 'remove'
li.appendChild(cb)
li.appendChild(sp)
li.appendChild(bt)
liste.appendChild(li)
form.reset()
}
liste.onclick = e => // delTask
{
if (!e.target.matches('button.remove')) return // reject others clicks
e.target.closest('li').remove()
}
}
)()
btTaskList.onclick = e =>
{
let tasks = [...document.querySelectorAll('#todo-list li')].map(li=>
{
let val = li.querySelector('span').textContent
, chk = li.querySelector('input[type=checkbox]').checked
;
return {val,chk}
})
console.clear()
console.log( tasks )
}
#todo-list li > span {
display : inline-block;
background-color : whitesmoke;
width : 20em;
}
#todo-list li input[type=checkbox]:checked + span {
text-decoration : line-through;
}
#todo-list li button.remove {
font-size: .6em;
}
<form id="todo-form">
<input name="task">
<button type="submit">Add</button>
</form>
<ul id="todo-list"></ul>
<button id="btTaskList">get task list</button>
I also added a get task list button...
After marking an element you are changing only the stayle and atrribute of element. But after delete you recreate with render whole list and in render you are not rendereing checked parameter.
Your render should be:
render() {
this.ul.innerHTML = "";
this.tasks.forEach((task) => {
const li = document.createElement("li");
const cb = document.createElement("input");
cb.type = "checkbox";
cb.addEventListener("click", (e) => {
this.markTask(e);
});
li.appendChild(cb);
// missed rendering checked
if (task.checked) {
li.style.textDecoration = "line-through";
cb.checked = 'checked';
}
li.append(document.createTextNode(task));
const btn = document.createElement("button");
li.appendChild(btn);
btn.textContent = "Delete";
btn.classList.add("remove");
btn.addEventListener("click", (e) => {
this.deleteTask(e);
});
this.ul.appendChild(li);
});
}

How can i replace from jquery to native Js

const img = document.querySelectorAll('img');
that code $(img[data-filter="${filter}"]).show(500);\ replace that code to native JavaScript(show(500) you can replace opacity or display);
i have 9 img at const img, each 3 img have different data-attribute.
Example i click on button and i need to hide or show not all img, but i need to choose 3 img with data-attribute such as I want. how can i write?
const btn = document.querySelectorAll('button');
const img = document.querySelectorAll('img');
function button() {
return function() {
if (this.dataset.check == "on") return;
btn.forEach(e => e.dataset.check = "off");
this.dataset.check = "on";
let filter = (this.dataset.filter == "all") ? "" : `="${ this.dataset.filter }"`;
$("img").hide(500);
$("img[data-filter" + filter + "]").show(500);
}
}
btn.forEach(item => {
item.onclick = button()
})

Button that assigns different color to text in javascript

I am new to javascript. I have a problem but I don't know what it could be. Iam supposed to link my javascript to my html. There are three buttons that should turn the text to a diffrent color on clicking. But it is not working.
// this is the red button
const header = document.querySelector("#header");
const clicker = document.querySelector(".clicker-red");
clicker.addEventListener("click", () => {
header.style.backgroundColor = "red";
header.classList.add("large");
});
// this is the green button
const clicker = document.querySelector(".clicker-green");
clicker.addEventListener("click", () => {
header.style.backgroundColor = "green";
header.classList.add("large");
});
// this is the purple button
const clicker = document.querySelector(".clicker-pruple");
clicker.addEventListener("click", () => {
header.style.backgroundColor = "purple";
header.classList.add("large");
});
As I have said in the comments, You cannot declare variable with same name in the same Lexical Environment (i.e, in the same block).
So, you need to change the variable name.
Here is the working example.
const header = document.querySelector("#header");
const clickerRed = document.querySelector(".clicker-red");
clickerRed.addEventListener("click", () => {
header.style.backgroundColor = "red";
});
// //this is the green button
const clickerGreen = document.querySelector(".clicker-green");
clickerGreen.addEventListener("click", () => {
header.style.backgroundColor = "green";
});
// // this is the purple button
const clickerPurple = document.querySelector(".clicker-purple");
clickerPurple.addEventListener("click", () => {
header.style.backgroundColor = "purple";
});
<div id="header">
Header</div>
<button class="clicker-red" type="button">Red</button>
<button class="clicker-green" type="button">Green</button>
<button class="clicker-purple" type="button">Purple</button>

Categories