Adding to opacity in javascript is not working properly - javascript

lu.style.opacity = lu.style.opacity += 0.01;
This is part of my non-jquery fade in function for a page where i want to have a fadeIn feature but not jquery.
I'm putting an alert on the function to see what the opacity is, and every time it is 0.01, so why is it only being added on one time?
The function I use
function fadein(lu,time){
if (lu.style.opacity<1)
{
lu.style.opacity = parseFloat(lu.style.opacity, 10) + 0.01; //add 0.01 to the opacity
setTimeout(function(){fadein(lu,time)},time/100) //sets a timeout to the fadeIn function every time/100 miliseconds
}
}

Opacity is a string. You are doing string concatentation when you add to it.
console.log(typeof lu.style.opacity);
// "string"
Make sure that you are adding numbers:
lu.style.opacity = parseFloat(lu.style.opacity) + 0.01;
In case parseFloat returns NaN, this may be helpful:
lu.style.opacity = (parseFloat(lu.style.opacity) || 0) + 0.01;
Now the reason why you were not seeing a value change is this:
lu.style.opacity;
// originally empty string: ''
lu.style.opacity += 0.01
// translates to: lu.style.opacity = '' + 0.01
// which equals '0.01' which is valid, but when you do it again:
lu.style.opacity += 0.01
// it is doing this: lu.style.opacity = '0.01' + 0.01
// which is: '0.010.01'
// which is an invalid value for that css style so it retains the previous value of '0.01'

Opacity is a string.
The syntax is wrong (that +=).
lu.style.opacity = parseFloat(lu.style.opacity) + 0.01;

I think you meant either
lu.style.opacity += 0.01;
or
lu.style.opacity = lu.style.opacity + 0.01;

Throw it in a while loop to monitor your progression towards your target opacity:
var TARGET_OPACITY = 60.0;
while(lu.style.opacity < TARGET_OPACITY) {
lu.style.opacity = parseFloat(lu.style.opacity, 10) + 0.01;
}

I think you are not adding up correctly
lu.style.opacity = parseFloat(lu.style.opacity) + 0.01;
as #Pointy commented, try putting alert before u add up and after you add up.

Related

Simple for loop is throwing me for a loop - decimal increment error

I'm attempting a simple for loop but getting odd results. I'm incrementing by a decimal (.02) but it seems to be adding incorrectly.
here is the loop:
for ( var a = 0; a <= 10; a += .02 ) {
console.log(a);
}
the results are fine for a bit..
0, 0.02, 0.04, 0.06, 0.08, 0.1
then it gets a little strange:
0.12000000000000001
and then it gets really far out:
0.19999999999999998 ... 9.999999999999876
Aside from the odd decimal addition it stops short of my end goal of 10.
I've tried for (var a = 0; a <= 10; a = (Math.round(a * 100)/100) + .02 ) (which gets me closest but still runs odd), parsefloating a, even a += 2/100.
Same results in a while loop.
Any ideas would be great!
EDIT: Although there are some workarounds for floating point precision in this post "How to deal with floating point number precision in JavaScript?" - I'm not sure how many would fit elegantly in a loop construct
You can use toFixed(2)
for ( var a = 0; a <= 10;) {
console.log(a);
a += 0.02;
a = +a.toFixed(2)
}
// Another possible way is
var limit = 10;
var increment = 0.02;
for ( var a = 0; a <= limit * 100; a += increment * 100) {
console.log(a / 100);
}

How can I prepend characters to a string using loops?

I have an input field that expects a 10 digit number. If the user enters and submits a number less than 10 digits, the function would simply add a "0" until the inputed value is 10 digits in length.
I haven't really used, or understand how recursive functions really work, but I'm basically looking at an efficient way of doing this. One minor issue I'm having is figuring out how to prepend the "0"s at the beginning of the string rather than appended to the end.
My thinking:
function lengthCheck(sQuery) {
for (var i = 0; i < sQuery.length; i++) {
if (sQuery.length !== 10) {
sQuery += "0";
//I'd like to add the 0s to the beggining of the sQuery string.
console.log(sQuery);
lengthCheck(sQuery);
} else return sQuery
}
}
Change:
sQuery += "0"; // added at end of string
to:
sQuery = "0" + sQuery; // added at start of string
To remove the for loop/recursion, you could slice out the desired length in one step:
function padZeros(sQuery) {
// the max amount of zeros you want to lead with
const maxLengthZeros = "0000000000";
// takes the 10 rightmost characters and outputs them in a new string
return (maxLengthZeros + sQuery).slice(-10);
}
Simple generic function using ES6 repeat:
// edge case constraints not implemented for brevity
function padZeros(sQuery = "", maxPadding = 10, outputLength = 10) {
// the max amount of zeros you want to lead with
const maxLengthZeros = "0".repeat(maxPadding);
// returns the "outputLength" rightmost characters
return (maxLengthZeros + sQuery).slice(-outputLength);
}
console.log('padZeros: ' + padZeros("1234567890"));
console.log('padZeros: ' + padZeros("123"));
console.log('padZeros: ' + padZeros(""));
Alternate version that doesn't affect strings over your set limit:
function padZerosIfShort(inputString = "", paddedOutputLength = 10) {
let inputLen = inputString.length;
// only padded if under set length, otherwise returned untouched
return (paddedOutputLength > inputLen)
? "0".repeat(paddedOutputLength - inputLen) + inputString
: inputString;
}
console.log('padZerosIfShort: ' + padZerosIfShort("1234567890", 5));
console.log('padZerosIfShort: ' + padZerosIfShort("123", 5));
console.log('padZerosIfShort: ' + padZerosIfShort("", 5));
It will ultimately depend on your needs how you want to implement this behavior.
The += operator adds things to the end of strings similar to:
sQuery=sQuery+"0"
You can add characters to the front of a string like this
sQuery="0"+sQuery
I also found something interesting here. it works like this:
("00000" + sQuery).slice(-5)
You would add zeros to the front then slice off everything except the last 5. so to get 10 characters you would use:
("0000000000" + n).slice(-10)
You don't need recursion to solve this, just a simple for loop should do the trick. Try this:
function lengthCheck (sQuery) {
for (var i = sQuery.length; i<10; i++) {
sQuery = "0" + sQuery;
}
return sQuery;
}
You're looking to pad the string with zeroes. This is an example I've used before from here and will shorten your code a little bit:
function lengthCheck (sQuery) {
while (sQuery.length < 10)
sQuery = 0 + sQuery;
return sQuery;
}
I believe this has already been answered here (or similar enough to provide you the solution): How to output integers with leading zeros in JavaScript

JavaScript - Why doesn't the addition assignment operator work as expected?

I'm currently enhancing a website with a few animations.
I tried this code:
// Opacity is 0 in the beginning. Set
// in CSS.
// 1. Parameter: Boolean - true if making the
// element visible; false if making it vanish.
// 2. Parameter: Object
var changeOpacity = function(direction, element) {
var css = element.style;
var goStep = function(signedStep) {
css['opacity'] += signedStep;
changeOpacity(direction, element);
};
if (direction) {
if (css['opacity'] < 1.0) {
setTimeout(function() {
goStep(0.1);
}, timeStep);
}
} else {
if (css['opacity'] >= 0.1) {
setTimeout(function() {
goStep(-0.1);
}, timeStep);
} else {
css['display'] = 'none';
}
}
};
It haven't worked.
I wrote a few console.logs in the code: 'opacity' always stayed at 0.1 after the assignment.
What I expected was: 0.0 - 0.1 - 0.2 - 0.3 ...
Now I use this code:
// ...
var goStep = function(signedStep) {
css['opacity'] = +css['opacity'] + signedStep;
changeOpacity(direction, element);
};
// ...
Works fine.
But I still wonder why using the combined assignment addition operator failed.
Has anyone an idea?
You are adding string with Number, so in first case you are actually concatenating the values
See here: https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Addition_assignment
The second aproach works because you are converting css['opacity'] to a number: +css['opacity']
Try this:
var test = "0.1",
test2 = "0.1";
signedStep = 0.1;
test += signedStep;
alert(test+" is a "+typeof test);
test2 = +test2 + signedStep;
alert(test2+" is a "+typeof test2);
css['opacity'] is a string. If you add a number to a string, it will convert the number into a string and concat the two final strings.
css['opactity'] = 0.1
css['opacity'] += 0.5 // => "0.10.5"

Javascript not fading in

I'm trying to create a fading effect using vanilla.js instead of jQuery. I'm using the following code to create the hide and show effect:
document.getElementById("pic-num-submit").onclick = function() {
fade();
};
var home = document.getElementById('home').style;
home.opacity = 1;
var agree = document.getElementById('agree').style;
agree.opacity = 0;
agree.display = "none";
function fade() {
if((home.opacity -= .1) < 0) {
home.display = "none";
show();
}
else {
setTimeout(fade, 40);
}
}
function show() {
if((agree.opacity += 0.2) < 1) {
agree.display = "";
}
else {
setTimeout(show, 40);
}
}
Everything is working with the fade function (in Firefox) But when I invoke the show function it only runs once, then it removes the display styling, and shows the div element at 0.2 opacity. I'm not sure what I'm doing wrong.
Here is a jsFiddle example of the problem I am having: http://jsfiddle.net/L54Aw/2/
Also it's broken in Chrome for some reason (The fade function never completes because of something to do with a js decimal subtracting problem)
Your "show" function is not correct. You only set up the timer when the opacity is not less than one. Initially, it is, so the code only runs once.
You're also running into a weirdness in JavaScript that pertains to a significant difference between the + and - operators. Subtraction is always numeric, but not so addition!
Here's a working "show" function:
function show() {
agree.display = ""; // only need this the first time anyway
agree.opacity = +(agree.opacity) + 0.2;
if (agree.opacity <= 1)
setTimeout(show, 40);
}
That unary + operator forces the "opacity" property to be interpreted as a number. Without that, it's a string! Thus adding 0.2 to the string "0.2" gives you "0.20.2", which is nonsense.
The decrementing you did for the other element worked OK because the subtraction operator coerces operands to numbers.
I can't comment on Pointy's solution, but here's what you could do with the fade function to avoid the bug that happens when you subtract low numbers:
function fade() {
home.opacity -= .05;
if(home.opacity - .05 < 0) {
home.display = "none";
show();
}
else {
setTimeout(fade, 20);
}
}
It isn't bulletproof, but it works by subtracting .05 instead of .1 and counter it by doubling the speed of the animation.
you probably want
(agree.opacity += 0.2) > 1
instead of
(agree.opacity += 0.2) < 1

javascript for loop with decimals

I'm trying to use this for loop in order to show divs. But I get a strange error from the jQuery lib.
Error: Syntax error, unrecognized expression: =10]
I have read about the problems with javascript decimals, but I still can't understand why this won't work:
for (var i = 10.00; i >= ui.value; i -= 0.25) {
$("data_id=" + Math.floor(i) + "]").show();
}
When hiding the divs, I use this and it works fine:
for (var i = 0.00; i < ui.value; i += 0.25) {
$("[data_id=" + Math.floor(i) + "]").hide();
}
You forgot the [ in the first loop, this will work:
for (var i = 10.00; i >= ui.value; i -= 0.25) {
$("[data_id=" + Math.floor(i) + "]").show();
}
You should transform this into an integer loop, if you are .floor()-ing the numbers, anyway.
You're missing your opening square bracket for the attribute equals selector:
for (var i = 10.00; i >= ui.value; i -= 0.25) {
$("[data_id=" + Math.floor(i) + "]").show();
}
As others have mentioned, however, there is absolutely no reason to be using floats for this, since the call to .floor() essentially means you are calling .show() on each of the divs 4 times unnecessarily:
for (var i = 10; i >= ui.value; i--) {
$("[data_id=" + i + "]").show();
}
This should accomplish exactly you want, in about a quarter of the work.
You are missing a [ in your selector here:
$("data_id=" + Math.floor(i) + "]").show();
Which should be:
$("[data_id=" + Math.floor(i) + "]").show();
You should probably add ' around the value of data_id as well, so the final result should be:
$("[data_id='" + Math.floor(i) + "']").show();
You should never, ever rely on floating point arithmetic for iteration/indexing variables. They may run you into strange situations, and even worse, different processors handle floating points differently. Your example doesn't seem to have any side-effects of floating points, but using floating points is really a bad practice.

Categories