How to change variables within the same function. Javascript - javascript

I want to change an input value by clicking on a div + adding a CSS effect . The issue is that I got 10 divs. I can do it by making a function for each one of them but i´m pretty sure that there is a much better way to do it without repeating the code. I´m starting at this, so it would be great if i could get some help.
I got an input and a few divs with just numbers:
<input type="text" id="screen" dir="rtl"/>
<div class="key" id="tres">3</div>
<div class="key" id="dos">2</div>
<div class="key" id="uno">1</div>
...
And then the function:
var screen = document.getElementById("screen");
var tres = document.getElementById("tres");
var dos = document.getElementById("dos");
var uno = document.getElementById("uno");
uno.onclick=function to () {
screen.value+=uno.innerHTML;
uno.style.boxShadow="none";
setTimeout(function() {
uno.style.boxShadow="0px 0px 5px 2px rgba(0, 0, 0, 0.2), inset 0px 0px 1px 1px rgba(0, 0, 0, 0.2)";
}, 220);
}
Now what i want to do is to use the same ".onclick" function on every single div, not in my newbie way (re writting the function and changing variables) but in a practical one. I've been trying with "classname" instead of "id". I´ve attempted with ".replace" by trying to replace the value names. And actually im trying with something like this:
var hell=["uno","dos","tres"];
var screen = document.getElementById("screen");
for (var i = 0; i < hell.length; i++) {
document.getElementById(hell[i]).onclick=function to() {
screen.value+=document.getElementById(hell[i]).innerHTML;
}
}
I barely know what I´m doing so a little bit of enlightenment would be grateful (avoiding jQuery if possible).
Thanks a lot! (Sorry about my bad English)

You can simply select the elements by class name, attach an eventListener to each of the elements, and you'll get what you wanted.
var screen = document.getElementById("screen");
var elements = Array.from(document.getElementsByClassName('key'));
elements.forEach(el => el.addEventListener('click', fn));
function fn(e) {
screen.value = (parseInt(screen.value, 10) || 0) + parseInt(e.target.innerText, 10);
elements.forEach(el => el.style.boxShadow = "none");
setTimeout(function() {
e.target.style.boxShadow = "0px 0px 5px 2px rgba(0, 0, 0, 0.2), inset 0px 0px 1px 1px rgba(0, 0, 0, 0.2)";
}, 220);
}
<input type="text" id="screen" dir="rtl" />
<div class="key" id="tres">3</div>
<div class="key" id="dos">2</div>
<div class="key" id="uno">1</div>

I think what you're looking for is querySelectorAll. Basically, instead of getting each one by ID, you can get all of them in an array by getting them by their class (since they all have the same class).
var myInput = document.getElementById('screen');
var inputs = document.querySelectorAll('.key');
inputs.forEach(function(input) {
input.onclick = function() {
myInput.value += input.innerHTML;
// everything else goes here
}
});
See this pen for a working example.

ES6
Here is a more optimal solution to your problem. It may seem a bit obscure if you don't know new ES6 syntax, but since you want to learn anyway, here it goes:
let screenValue = 0,
lastClickedDiv;
const screen = document.getElementById('screen'),
keys = [...document.getElementsByClassName('key')];
const toggleBoxShadow = (clickedDiv) => {
if (clickedDiv !== lastClickedDiv) {
clickedDiv.classList.add('active');
if (lastClickedDiv !== undefined) {
lastClickedDiv.classList.remove('active');
}
lastClickedDiv = clickedDiv;
}
};
const keysClickListener = (event) => {
screenValue += parseInt(event.target.textContent);
screen.value = screenValue;
setTimeout(() => toggleBoxShadow(event.target), 220);
};
keys.forEach(key => key.addEventListener('click', keysClickListener));
.key.active {
box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.2),
inset 0 0 1px 1px rgba(0, 0, 0, 0.2);
}
<input type="text" id="screen" dir="rtl"/>
<div class="key">3</div>
<div class="key">2</div>
<div class="key">1</div>
[...document.getElementsByClassName('key')] gets all elements with class name key and turns that collection into an array using spread operator.
keys.forEach(key => key.addEventListener('click', keysClickListener)) adds click listener named keysClickListener to each element of keys array.
keysClickListener function updates screenValue counter by adding number from clicked div to value it already stores and sets that as #screen's value. Then it invokes toggleBoxShadow() after 220 ms.
If you want anything else explained, let me know.

Related

How do i implement setTimeout in this code?

Here is simple javascript that changes span of letters with mouse over and mouseout. I want to make my mouseout delayed with setTimeout but im still too newbie for that. Here is the code. Appreciate the help.
function markedletter() {
this.style.boxShadow = "20px 20px 20px black";
this.style.fontSize = "52pt";
this.style.color = "cyan";
}
function unmarkedletter() {
this.style.boxShadow = "0px 0px 0px transparent";
this.style.color = "white";
}
let elems = document.getElementsByTagName("span");
for (let i = 0; i < elems.length; i++) {
elems[i].addEventListener("mouseover", markedletter, false);
elems[i].addEventListener("mouseout", unmarkedletter, false);
}
Everything above works fine. I just dont know how to implement setTimeout here. I want it to delay mouse out on each letter.
I did
try some methods but am still new to js.
function setup() {
setTimeout(nmarkedlatter, 5000);
}
I created function setup like this but it doesnt work alone and I wasnt sure how to implement it in loop nor if I even need to.I Did try some stuff in loop but even the syntax wasnt correct so here we are.
Put the call to setTimeout() in unmarkedletter.
function unmarkedletter() {
setTimeout(() => {
this.style.boxShadow = "0px 0px 0px transparent";
this.style.color = "white";
}, 5000);
}

click button (CSS) using JS script [duplicate]

This question already has answers here:
Javascript set button active
(5 answers)
Closed 1 year ago.
Im making a simon says game,
i use 4 colored buttons that works perfectly.
the process is simple- the program present the user with the colors.
the repeat the sequence by clicking the buttons.
I wish to let the program activate the button the same way a user would, with the appropriate activate effect.
.but:active{ // <-- how do i initiate this with js?
box-shadow: 0 5px #666;
transform: translateY(4px);
You mean
document.querySelector(".but").click()
or
const buts = document.querySelectorAll(".but");
const cnt = 0;
setInterval(function() {
if (cnt>= 0) cnt = 0;
but[cnt].click();
cnt++;
},2000)
let but = document.querySelector('.but');
but.addEventListener('click', () => {
but.classList.add('active');
let activeStatus = document.querySelector('.active');
activeStatus.style = `
box-shadow: 0 5px #666;
transform: translateY(4px);
`;
});

Adding variables to SVG drop-shadow for-loop in Javascript

I want to add multiple "drop-shadow" filters to an SVG, to achieve a 3D style effect, with the edges being a gradient -- similar to this (I'll later add an interval to animate it). I've used this to generate a gradient array with 70 shades.
However, I cannot get the "drop-shadow" property to work with my for-loop.
Unlike "text-shadow" style for example where I can do something like this:
var current = element.style.textShadow;
var appliedStyle = -i + 'px ' + i + 'px ' + gcolor[i];
element.style.textShadow = current+appliedStyle;
I couldn't figure out how to get the current "drop-shadow" property and concatenate another filter to it. So I came up with the idea to just add classes. This is my best attempt at coding it:
let text = document.querySelector(".brand-svg");
let gcolor = ["#ffb576","#ffb275","#ffb074","#ffad73","#ffab72","#ffa871","#ffa670","#ffa370","#ffa16f","#ff9e6e","#ff9c6d","#ff996c","#ff976b","#ff946a","#ff9269","#ff9068","#ff8d67","#ff8b66","#ff8865","#ff8664","#ff8363","#ff8163","#ff7e62","#ff7c61","#ff7960","#ff775f","#ff745e","#ff725d","#ff705c","#ff6d5b","#ff6b5a","#ff6859","#ff6658","#ff6357","#ff6156","#ff5e56","#ff5c55","#ff5954","#ff5753","#ff5452","#ff5251","#ff4f50","#ff4d4f","#ff4b4e","#ff484d","#ff464c","#ff434b","#ff414a","#ff3e49","#ff3c49","#ff3948","#ff3747","#ff3446","#ff3245","#ff2f44","#ff2d43","#ff2b42","#ff2841","#ff2640","#ff233f","#ff213e","#ff1e3d","#ff1c3c","#ff193c","#ff173b","#ff143a","#ff1239","#ff0f38","#ff0d37","#ff0a36"];
for (var i = 1; i <= 70; i++) {
text.classList.add("shadowlayer"+i);
var current = document.querySelector(".shadowlayer"+i);
current.style.setProperty(`-webkit-filter`, `drop-shadow 0px (${-i})px (${gcolor[i]})`);
};
body {
display: flex;
justify-content: center;
}
.brand-svg {
width: 400px;
}
<svg class="brand-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 748.17 433.89"><defs>
<style> .brand-svg path, polygon {fill:#fff;stroke:#ffb777;stroke-miterlimit:10;stroke-width:3px;}</style>
</defs>
<path class="svg-b-d" d="M746.37,26.21q-1.07-10.31-13.43-17.09T701.85,1.74c-1,0-2,0-3,0a142.7,142.7,0,0,0-37.5,5.51,200.39,200.39,0,0,0-43.71,18L559.68,57l86.6,47.6,57.94-31.84q21.79-12,32.51-24.13T746.37,26.21ZM694.43,46q-3.63,7.51-18.36,15.6l-10.41,5.73L627,46.1l10.4-5.72q14.73-8.1,28.39-10.09a51.29,51.29,0,0,1,7.33-.56,32,32,0,0,1,15.63,3.68Q698,38.51,694.43,46Z"/>
<polygon class="svg-b-n" points="539.34 112.27 583.62 136.62 493.18 137.64 449.59 161.6 536.18 209.2 579.78 185.24 536.24 161.31 625.93 159.87 669.53 135.91 582.93 88.31 539.34 112.27"/>
<path class="svg-b-a" d="M308.71,209.12l35.73,75.55,45.77-25.15-6.22-11,46.35-25.47,20,3.42,45.95-25.26L359,181.48Zm90.59,8.56-25.13,13.81-11.53-20.15Z"/>
<path class="svg-b-r" d="M326.64,290.81q1-8-7.66-12.75-8.07-4.43-20.48-4.66l-1.27,0q-11.94,0-26.85,4.31a160.09,160.09,0,0,0-32.6,13.82L173,327.12l86.6,47.61,43.6-24-30.88-17.18,57.2,2.72L377.4,310,314,308.37Q325.61,298.76,326.64,290.81Zm-47.71,17.27c-.91,1.81-3.46,3.85-7.65,6.16L254,323.74l-14.68-8.07,17.28-9.5a33.36,33.36,0,0,1,11.28-4.06,21.59,21.59,0,0,1,2.7-.18,12.06,12.06,0,0,1,5.93,1.37Q280.29,305.39,278.93,308.08Z"/>
<path class="svg-b-b" d="M186,353.17q-6.37-3.5-16.52-3.5c-1.16,0-2.37,0-3.61.1a84.43,84.43,0,0,0-27.06,6.61q8.9-6.78,10.07-13.14t-6.4-10.53a34,34,0,0,0-16.65-3.82,63.66,63.66,0,0,0-12.28,1.3q-17.93,3.53-39.14,15.19l-70.89,39L90.13,432,163,391.9q22.57-12.4,28.49-22.45T186,353.17ZM80.89,378.94l-12.24-6.73,16.9-9.28a33.73,33.73,0,0,1,10.27-4,15,15,0,0,1,2.45-.21,10.35,10.35,0,0,1,5.1,1.24c2,1.12,2.6,2.46,1.68,4.05s-3.35,3.45-7.27,5.61Zm58.23.6q-1.44,2.34-7.33,5.58L112,396,99.72,389.3l19.84-10.91q7.53-4.14,12.81-4.14a10.27,10.27,0,0,1,5,1.2C139.5,376.62,140.09,378,139.12,379.54Z"/></svg>
Why doesn't this work? Is there an easier way to do this?
The filter property accepts multiple filters, so you can repeat drop-shadow:
filter: drop-shadow(30px 10px 4px #44d) drop-shadow(70px 1px 4px #f0d);
All you need to do is pass correct string to style property filter.
In your case code would look something like this:
let text = document.querySelector(".brand-svg");
let gcolor = ["#ffb576","#ffb275","#ffb074"];
for (var i = 0; i < gcolor.length; i++) {
text.style.filter = `${text.style.filter} drop-shadow(0px ${-i}px 0px ${gcolor[i]})`;
}

Get color name from a text input

I'm trying to get a color name from text input using js but the code doesn't work at all. (I'm using p5.js btw)
my HTML :
<input placeholder="Type color name OR type 'Random' for a random tint!" style="width: 340px; border-radius: 5px; border: 3px rgb(0, 0, 0) solid; background-color: rgb(197, 197, 197);" id="colors"></input>
my JS :
colorss = "";
function preload() {
}
function setup() {
canvas = createCanvas(400, 400);
canvas.position(480, 300);
video = createCapture(VIDEO);
video.hide();
colorss = document.getElementById("colors").value;
console.log(colorss);
}
function draw() {
image(video, 0, 0, 400, 400);
}
function submit() {
r = random(255);
g = random(255);
b = random(255);
if(document.getElementById('colors').value == "Random") {
tint(r,g,b);
} else{
tint(colorss);
}
}
I'm using p5.js too and I tried using a different variable, so i don't understand why it isn't working... pls help
I assume your setup() function is executed ones when the page is opened and than submit() is executed once the submit button is clicked.
So what you have here is you execute setup() and load value of your input field into colorss variable. At this point the value is an empty string.
Then when you submit the form, you are using the value of colorss variable which is still an empty string.
What you need to do is use something like this:
tint(document.getElementById("colors").value);
Also, please declare variable with var, let and/or const

When using element.style = <some CSSStyleDeclaration> makes element dissapear

I use, (pls never mind the selector, I know it should be changed but it is found nevertheless).
let leftArrow = <HTMLElement> document
.querySelector('div[style="position: absolute; left: 6px; transform: skewX(22.6deg);' +
' transform-origin: 0px 0px 0px; height: 24px; width: 10px;' +
' box-shadow: rgba(0, 0, 0, 0.6) 0px 1px 6px; background-color: rgb(255, 255, 255);"]');
Then I use:
let myStyle = leftArrow.style; //this gets me a CSSStyleDeclaration object
console.log(myStyle); // those are equal objects
console.log(leftArrow.style); // those are equal objects
But when I do:
leftArrow.style = myStyle; //this should change nothing ?!
my element dissappears ?!
My goal is to use a class and then do sth like this:
leftArrow.style = this.getStyleFromClass(selector_to_find_class_name);
But after simple:
leftArrow.style = myStyle;
my element from upper one becomes :
<div></div>
which makes it basically not visible. Why ?
I think what you are trying to do is apply the original inline styles back. To do this, you can use cssText to get the values, and than you can set it back.
var div = document.getElementById("x");
var backUp = div.style.cssText;
div.style.backgroundColor = "yellow";
div.style.color = "blue";
window.setTimeout( function () {
div.style.cssText = backUp;
}, 4000);
<div id="x" style="background-color:red">Hello</div>
leftArrow.style = myStyle; //this should change nothing ?!
Yes but only if you have:
let myStyle = leftArrow.style; //this gets me a CSSStyleDeclaration object
letArrow.style = myStyle;
This is most likely not the code you have and you are generating the object on the fly. Do not assign to style directly. Instead assign to members of style e.g. letArrow.style.color = "red"

Categories