I tried doing a JS fade effect with the setTimeout() function and it appeared to work to some extent, but I can't seem to figure out what's wrong with the code below:
<html>
<head>
<title></title>
<script type="text/javascript">
function FadeEffect(n)
{
var i=1;
fade = document.getElementById("box");
if (n===1)
{
fade.style.opacity=i/10;
i++;
setTimeout("FadeEffect(1)",50);
if (fade.style.opacity=1)
{
var i=1;
}
}
else if (n===0)
{
fade.style.opacity=1-i/10;
i++;
setTimeout("FadeEffect(0)",50);
if (fade.style.opacity=0)
{
var i=1;
}
}
}
</script>
<style type="text/css">
#box{
width: 200px;
height: 50px;
border: 1px solid black;
background-color: #ccc;
opacity: 0;
}
</style>
</head>
<body>
<div onMouseOver="FadeEffect(1)" onMouseOut="FadeEffect(0)" id="box">Menu</div>
</body>
</html>
Edit: updated the code with setTimeout() functions.
There are two problems with the function that I can see.
First, your if statements both do an assignment rather than a comparison. You are saying if (n=0) (one =, assignment) when you should be saying if (n===0) (three ===, comparison, or you can use two == for a type-converting comparison).
Second, using a for loop to repeatedly change the style isn't going to fade because the browser doesn't update the display at the same time as your code is executing - essentially it uses the same thread for display and for JavaScript. So the page will be updated after the function exits. You need to give the browser a chance to update after each iteration by using setTimeout() - something like:
function fadeEffect(element,startValue,target,delay){
element.style.opacity = startValue;
if (startValue < target)
startValue = Math.min(startValue + 0.1, target);
else
startValue = Math.max(startValue - 0.1, target);
if (startValue != target)
setTimeout(function(){fadeEffect(element,startValue,target,delay);}, delay);
}
<div onMouseOver="fadeEffect(this, 1, 0, 100);"
onMouseOut="fadeEffect(this, 0, 1, 100);" id="box">Menu</div>
Demo: http://jsfiddle.net/hLQ6y/2/
EDIT: Note that this code doesn't cope all that brilliantly if you move the mouse in and out too quickly, i.e., if you trigger the fade in before the fade out has finished. (You can see what I mean in my jsfiddle.) You can solve this by saving the return from .setTimeout() and calling .clearTimeout() if required. Given that I've already covered the essence of the question I'll leave the fine-tuning as an exercise for the reader...
UPDATE: Your updated code has introduced new if statements with the same assignment-instead-of-comparison problem. Also it is calling setTimeout() forever - you should do that conditionally as in the answers Pointy and I gave. Also you seem to be relying on the variable i which, as a local variable, will not retain its value between calls - you could make it a global, but better to manage it as a parameter like I did or as a local variable in an outer function like Pointy did.
The problem is that all those changes to the style will happen before the browser bothers to update the display. What you need to do is space out the changes over a much, much longer period of time using "setTimeout()".
function fadeIn() {
function increment() {
box.style.opacity = Math.min(1.0, (opacity += 0.1));
if (opacity < 1.0) {
setTimeout(increment, 100);
}
}
var box = document.getElementById('box'), opacity = 0;
box.style.opacity = opacity;
setTimeout(increment, 100);
}
edit — Here is a jsfiddle to demonstrate.
If you want it to fade, you need to create a function that sets the opacity -0.1 or +0.1 and then calls itself with setTimeout in 100ms (or fewer). If you don't let the script wait, it will be too fast and immediately set the opacity to 1.0.
Anyways, you could do this a lot easier using jQuery.
Related
I am using setInterval(fname, 10000); to call a function every 10 seconds in JavaScript. Is it possible to stop calling it on some event?
I want the user to be able to stop the repeated refresh of data.
setInterval() returns an interval ID, which you can pass to clearInterval():
var refreshIntervalId = setInterval(fname, 10000);
/* later */
clearInterval(refreshIntervalId);
See the docs for setInterval() and clearInterval().
If you set the return value of setInterval to a variable, you can use clearInterval to stop it.
var myTimer = setInterval(...);
clearInterval(myTimer);
You can set a new variable and have it incremented by ++ (count up one) every time it runs, then I use a conditional statement to end it:
var intervalId = null;
var varCounter = 0;
var varName = function(){
if(varCounter <= 10) {
varCounter++;
/* your code goes here */
} else {
clearInterval(intervalId);
}
};
$(document).ready(function(){
intervalId = setInterval(varName, 10000);
});
I hope that it helps and it is right.
Already answered... But if you need a featured, re-usable timer that also supports multiple tasks on different intervals, you can use my TaskTimer (for Node and browser).
// Timer with 1000ms (1 second) base interval resolution.
const timer = new TaskTimer(1000);
// Add task(s) based on tick intervals.
timer.add({
id: 'job1', // unique id of the task
tickInterval: 5, // run every 5 ticks (5 x interval = 5000 ms)
totalRuns: 10, // run 10 times only. (omit for unlimited times)
callback(task) {
// code to be executed on each run
console.log(task.name + ' task has run ' + task.currentRuns + ' times.');
// stop the timer anytime you like
if (someCondition()) timer.stop();
// or simply remove this task if you have others
if (someCondition()) timer.remove(task.id);
}
});
// Start the timer
timer.start();
In your case, when users click for disturbing the data-refresh; you can also call timer.pause() then timer.resume() if they need to re-enable.
See more here.
In nodeJS you can you use the "this" special keyword within the setInterval function.
You can use this this keyword to clearInterval, and here is an example:
setInterval(
function clear() {
clearInterval(this)
return clear;
}()
, 1000)
When you print the value of this special keyword within the function you output a Timeout object Timeout {...}
The Trick
setInterval returns a number:
Solution
Take this number. Pass it to the function clearInterval and you're safe:
Code:
Always store the returned number of setInterval in a variable, so that you can stop the interval later on:
const intervalID = setInterval(f, 1000);
// Some code
clearInterval(intervalID);
(Think of this number as the ID of a setInterval. Even if you have called many setInterval, you can still stop anyone of them by using the proper ID.)
Why not use a simpler approach? Add a class!
Simply add a class that tells the interval not to do anything. For example: on hover.
var i = 0;
this.setInterval(function() {
if(!$('#counter').hasClass('pauseInterval')) { //only run if it hasn't got this class 'pauseInterval'
console.log('Counting...');
$('#counter').html(i++); //just for explaining and showing
} else {
console.log('Stopped counting');
}
}, 500);
/* In this example, I'm adding a class on mouseover and remove it again on mouseleave. You can of course do pretty much whatever you like */
$('#counter').hover(function() { //mouse enter
$(this).addClass('pauseInterval');
},function() { //mouse leave
$(this).removeClass('pauseInterval');
}
);
/* Other example */
$('#pauseInterval').click(function() {
$('#counter').toggleClass('pauseInterval');
});
body {
background-color: #eee;
font-family: Calibri, Arial, sans-serif;
}
#counter {
width: 50%;
background: #ddd;
border: 2px solid #009afd;
border-radius: 5px;
padding: 5px;
text-align: center;
transition: .3s;
margin: 0 auto;
}
#counter.pauseInterval {
border-color: red;
}
<!-- you'll need jQuery for this. If you really want a vanilla version, ask -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="counter"> </p>
<button id="pauseInterval">Pause</button></p>
I've been looking for this fast and easy approach for ages, so I'm posting several versions to introduce as many people to it as possible.
I can see there are a couple of similar questions asked here but unfortunately I couldn't find the answer I expect.
I am quite new to Programming and trying my hands on Javascript Progress Bar. I have a counter to countdown whenever the progress bar runs out of width but i got the problem, when the tab in focus is inactive, the progress bar pauses thereby keeping counter not to countdown.
I got the idea of using web workers http://www.tutorialspoint.com/html5/html5_web_workers.htm but I couldn't get that to work. I would appreciate any form of help I get here.
Below is my Code.
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/
jquery.min.js">
</script>
<style>
#progressContainer {
position: relative;
width: 97%;
height: 25px;
background-color: #ddd;
margin-bottom: 15px;
}
#progressBar {
position: absolute;
width: 0%;
height: 100%;
background-color: #A9A9A9;
}
#container{
width: 200px;
height: 200px;
border: 1px solid black;
padding: 10px
}
</style>
<script>
$(document).ready(function(){
$("#countDownBtn").click(function(){
var cdNumber = $("#countDownId").val();
var id = setInterval(frame, 100);
var elem = document.getElementById("progressBar");
var progressBarWidth = 101;
function frame() {
if (progressBarWidth === 0) {
clearInterval(id);
cdNumber--;
$("#countDownId").val(cdNumber);
console.log(cdNumber);
if (cdNumber === 0) {
clearInterval(id);
}
else {
elem.style.width = '100%';
progressBarWidth = 100;
//alert("Hi");
}
}
else {
progressBarWidth--;
elem.style.width = progressBarWidth + '%';
}
}
});
});
</script>
</head>
<body>
<div id="container">
<div>
<input type="text" id="countDownId" value="">
<button id="countDownBtn" class="btn">Click</button>
</div><br>
<div id="progressContainer">
<div id="progressBar"></div>
</div>
</div>
</body>
You'll always run into such problems when depending on the precision of some interval; even requestAnimationFrame. They ain't precise.
The better approach (not just in this case, but pretty much every time you have to transition a value over time) is to save the startTime and compute the passed time in the interval (as #Nosyara already suggested).
When dealing with scaling-factors and/or pausing of this stuff, things can get messy again. Here a utility for this task:
// The basic concept of this "Clock" is a linear equation over Date.now()
// plus the logic to make this equation pausable.
// therefore it's completely independant of **any** interval; it's just math.
function Clock(v){
var p=true,m=1,b=+v||0,n=Clock.now;
return Object.assign(Object.create(Clock.prototype),{
// getter() / setter(value)
// I don't use real getter and setter, because this syntax
// allows/implements method-chaining
value(v){return arguments.length?(b=(+v||0)-(!p&&m*n()),this):b+(!p&&m*n())},
speed(v){return arguments.length?(v=+v||0,p||v===m||(b+=n()*(m-v)),m=v,this):m},
paused(v){return arguments.length?(((v=!!v)===p)||(b+=n()*((p=v)?m:-m)),this):p},
});
}
Object.assign(Clock.prototype,{
valueOf(){return this.value()},
//aliases for setting the paused() state; doesn't matter if you call them repeatedly.
start(){return this.paused(false)},
stop(){return this.paused(true)},
});
Clock.now=Date.now; //the function used for timing
//Clock.now=performance&&performance.now?performance.now.bind(performance):Date.now;
Now to your code:
$(function(){
function frame(){
//yes, countDown get's converted to Number
var value = Math.max(0, countDown);
var count = Math.ceil(value);
var progress = value % 1;
$progressBar.width( progress * 100 + "%" );
//so that I don't update $countDown.val() on every frame, but only if necessary
//on the other hand, it wouldn't be that bad.
if(count !== lastCount) $countDown.val( lastCount = count );
//either stop the countDown or request the next frame.
if(value > 0) requestAnimationFrame(frame);
else countDown.stop();
}
//create a Clock and set speed. Clock is paused by default.
var countDown = Clock().speed( -1 / 10000/*ms*/ );
var $progressBar = $("#progressBar");
var $countDown = $("#countDownId");
var lastCount;
$("#countDownBtn").click(function(){
//if !countDown.paused() then there already is a pending `requestAnimationFrame(frame)`
//from the last call of frame()
if(countDown.paused()) requestAnimationFrame(frame);
countDown.value( $countDown.val() ).start();
});
})
I had similar problems in one of my projects in Chrome browser. The root of problem, that Chrome allows up to 1 timer event per second (setTimeout or setInterval) if tab is not active. In case there more than 1 call per second - it creates queue, than behavior of page depends on logic inside events and may look not as expected. One of solutions is to check visibility of the page and manage intervals Check here
As #ManoDestra pointed out in the comment, you should use requestAnimationFrame instead of setInterval.
The best solution I would propose is utilizing the HTML5 Visibility API to detect when a tab becomes active again after being inactive, and then update the progress bar accordingly. Perhaps you could store the timestamp of the countdown when it is initialized, and when the tab becomes active again, you look at the new timestamp and make a comparison.
You can use setTimeout instead and use recursion. It could look something like this:
var stopInterval = false;
frame();
function frame() {
if(stopInterval) return;
// Your stuff to run in interval HERE
setTimeout(frame, 100);
}
Webworkers are not supported in older browsers. Also browsers specify how they handle setTimeout and setInterval on inactive tab individually, so the behavior may differ. Chrome seems to slow down the recursion alot (1 per second?).
Specifically in your case you can use clock time to represent right progress. When you don't want trust browser about interval events.
Let say you want 10 sec countdown:
var tm = new Date().getTime() + 10000; // 10 sec in milliseconds
setInterval(function(){
var secondsPassed = (tm - new Date().getTime()) / 1000;
// update UI
}, 100); // You can use variable here in different visibility modes
Trying to do a simple fade in using the opacity property of an h1 element. I'm learning javascript, so would like to try this using plain javascript (yes, I know it is much easier using jQuery).
Pasting only relevant snippets:
<body onload="fadeIn()">
...
<div class = "container">
<div class = "row">
<div class = "col-md-3">
<img class = "img-responsive" src="icons/Website_Logo.png">
</div>
<div class = "col-md-9 page-header">
<h1 id="welcomeHeader" style="opacity:0">
Welcome to the world!
</h1>
</div>
</div>
</div>
...
<script>
function fadeIn() {
var el = document.getElementById("welcomeHeader");
var op = parseFloat(el.style.opacity);
var timer = (function () {
if(op >= 1.0)
clearInterval(timer);
op += 0.1;
el.style.opacity = op;
}, 50);
}
</script>
</body>
Help is much appreciated! Thanks!
jsFIDDLE
You need to call the setInterval function first in order to invoke a timer. Rest is fine. Here is a working fiddle
Code Snippet:
function fadeIn() {
var el = document.getElementById("welcomeHeader");
var op = parseFloat(el.style.opacity);
var timer = setInterval(function () {
console.log('here');
if(op >= 1.0)
clearInterval(timer);
op += 0.1;
el.style.opacity = op;
}, 50);
}
You need to change your function to use setInterval like so:
var timer = setInterval(function () { // notice the setInterval added.
if(op >= 1.0)
clearInterval(timer);
op += 0.1;
el.style.opacity = op;
}, 50);
Notes:
I give you this answer to help you LEARN javascript as you mentioned, otherwise,
it would be better done with pure css of course.
Also, make sure your opacity is set to 0 in your css as a starting point.
You don't need a timer for this - all you need to do is change the class. Here's an example:
the CSS:
element{
/* whatever styles you have */
}
element_faded{
transition: opacity .5s;
opacity: 50%; /* or whatever values you want */
}
the javascript
var element = document.getElementById('element');
// in order to trigger the fade, just change the class
element.className = "element_faded";
In the transition will happen between the values of the original and new class, so if you want a fade-in, have the original opacity be 0% and the new one be 100% or something higher than zero, depending on what you want the final opacity to be. Also, remember that the transition characteristics are determined by the transition attribute in the new class.
Doing this without CSS will just make things more complicated unless you need to do something more sophisticated than just plain fading in or out. If that's the case, then use setInterval or perhaps even something like requestAnimationFrame if you're feeling adventurous.
Honestly, this isn't really the kind of thing you need to learn when first learning javascript. Eventually this will be really easy once you get some confidence under your belt doing things that work more easily in javascript (setTimeout and the like can have their own weird caveats). Try to set a meaningful, practical goal and fulfill it first, using whatever mix of javscript/css/html you can and you'll soon have the basics down well enough to find things like this obvious.
I created an image slider that ends on one image, but now I'd like to take it a step further and make it loop.
Here is my code in the head tag
<style>
#picOne, #picTwo, #picThree, #picFour, #picFive{
position:absolute;
display: none;
}
#pics {
width:500px;
height:332px;
}
</style>
<script src="http://code.jquery.com/jquery-1.4.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#picOne').fadeIn(1500).delay(3500).fadeOut(1500);
$('#picTwo').delay(5000).fadeIn(1500).delay(3500).fadeOut(1500);
$('#picThree').delay(10000).fadeIn(1500).delay(3500).fadeOut(1500);
$('#picFour').delay(15000).fadeIn(1500).delay(3500).fadeOut(1500);
$('#picFive').delay(20000).fadeIn(1500).delay(3500);
});
</script>
and here is where it is implemented in the body code
<div id="pics">
<center>
<img src="img/dolllay.jpg" width="500" height="332" id="picFive" />
<img src="img/dye.jpg" width="500" height="332" id="picTwo" />
<img src="img/dollsit.jpg" width="500" height="332" id="picThree" />
<img src="img/heirloom.jpg" width="500" height="332" id="picFour" />
<img src="img/heritage.jpg" width="500" height="332" id="picOne" />
</center>
</div>
Could I turn it into a function and then loop it? Can I get any guidance on that? Thank you very much
Everyone's answering the question, but not solving the problem.
Sure, you can just put a loop wrapper around it (preferably one that doesn't terminate), but why not just program it right? Why have all the hardcoded times, and why not make it more robust?
Try rewriting your code like this. It makes it much easier to modify the pictures you loop through:
var pictures = ["picOne", "picTwo", "picThree", "picFour", "picFive"];
var index = 0;
var displayImage = function() {
if (index == pictures.length) { return; }
$("#" + pictures[index++]).fadeIn(1500).delay(3500).fadeOut(1500, displayImage);
};
displayImage();
Then, if you want to loop back, you simply tweak the displayImage function:
var displayImage = function() {
if (index == pictures.length) { index = 0; }
$("#" + pictures[index++]).fadeIn(1500).delay(3500).fadeOut(1500, displayImage);
};
TRY IT at jsfiddle
EDIT
On more careful reading of your question, I see that my original answer didn't do exactly what you needed. You have it set so that every five seconds, one will have faded out and the other one will have faded in. Currently, mine takes 6.5 seconds, since mine is all operating sequentially instead of concurrently. To make it come close to matching yours, just change the 1500s to 750s:
$("#" + pictures[index++]).fadeIn(750).delay(3500).fadeOut(750, displayImage);
This will take the right amount of time. It's slightly different from yours, in that one fades out all the way before the other fades in. The alternative is to actually skip the fadeIn and keep the fadeout. This is a lot closer to the way yours looks.
$("#" + pictures[index++]).show().delay(3500).fadeOut(1500, displayImage);
Or, make a very small fadein, to help reduce the flash of the new image:
$("#" + pictures[index++]).fadeIn(100).delay(3500).fadeOut(1400, displayImage);
Final Edit (really!)
Ok, to get the fadeIn and fadeOut to work reliably at the same time, the solution was to use neither. I went back to using animate, instead. As a result, I had to completely rewrite the displayImage function, but this is exactly what you need:
var displayImage = function () {
if (index == pictures.length) {
index = 0;
}
$("#" + pictures[index]).show().delay(3500).animate({
opacity: 0.2
}, {
step: function (now) {
var idx = (index + 1) % pictures.length;
var val = 1.2 - now;
$("#" + pictures[idx]).show().css("opacity", val);
},
complete: function () {
$("#" + pictures[index++]).hide();
displayImage();
}
});
};
What this does is move the sequence to "show->fadeIn and Out" instead of "fade in -> show -> fade out". To make your transition smooth, I only fade it out to 0.2 instead of 0. The step function is what fades the other one in at the same time. Once the new pic is visible, I completely hide the old pic.
Here's the working fiddle for it.
$(document).ready(function() {
setInterval(example, 10000); // repeat every 10 seconds
});
function example() {
$('#picOne').fadeIn(1500).delay(3500).fadeOut(1500);
$('#picTwo').delay(5000).fadeIn(1500).delay(3500).fadeOut(1500);
$('#picThree').delay(10000).fadeIn(1500).delay(3500).fadeOut(1500);
$('#picFour').delay(15000).fadeIn(1500).delay(3500).fadeOut(1500);
$('#picFive').delay(20000).fadeIn(1500).delay(3500);
}
A better way would be to give each pic the same class such as 'fadeinout'. This will mean you don't have to re-write your code when you add/remove more pics.
eg
<img id="picFive" class="fadeinout" ....
/* not sure if they are even <img>s but whatever they are*/
Then do
$(document).ready(function() {
beginFades();
});
function beginFades() {
$('.fadeinout').each( function(i,el) { // find all elements with fadeinout
//for each one, trigger the start of the fading after i*5000 milliseconds
//i is the index of the element as it was found by jQuery - this will be in
//document order (which actually may not be what you have but I'm guessing
//it is)
setTimeout(function(){
makeImgFadeInOut($(el))
}, i*5000);
});
}
function makeImgFadeInOut(el) {
//trigger a single fadeIn, fadeOut.
//But add a callback function to the end of fadeOut which retriggers the whole
//thing
el.fadeIn(1500).delay(3500).fadeOut(1500, function(){makeImgFadeInOut(el);});
}
WORKING DEMO (WITH DIVS)
You can use setInterval to loop it forever, or setTimeout to loop it for a specific duration.
<script type="text/javascript">
$(document).ready(function() {
setInterval(ImageSlider, 1000);
});
function ImageSlider() {
$('#picOne').fadeIn(1500).delay(3500).fadeOut(1500);
$('#picTwo').delay(5000).fadeIn(1500).delay(3500).fadeOut(1500);
$('#picThree').delay(10000).fadeIn(1500).delay(3500).fadeOut(1500);
$('#picFour').delay(15000).fadeIn(1500).delay(3500).fadeOut(1500);
$('#picFive').delay(20000).fadeIn(1500).delay(3500);
}
</script>
If you want to have total control upon your elements you can use this:
var elements = [{
el: '#pic1',
delay: 3500,
fadeIn: 1500,
fadeOut: 1500
},
{
el: '#pic2',
delay: 3500,
fadeIn: 1500,
fadeOut: 1500
}
//... other elements
]
var index = null;
(function loop(){
index = index || 0;
index = index % elements.length();
$(elements[index].el).fadeIn(elements[index].fadeIn, function(){
$(this).delay(elements[index].delay)
.fadeOut(elements[index].fadeOut, function(){
index++;
window.setTimeout(loop, 5000);
});
})();
Edit : forgot to execute the first iteration of the loop function and removing the useless call for index inside the loop
The good thing about how this loop works is that it doesn't use the SetInterval function.
and the code inside the loop need to finish what it does inside before iterating again.
(you won't have this hideous bug if you click an other tab and go back to your carousel)
#ElRoconno answer is pretty good too if you require less configuration
Use any of this-
setInterval() - executes a function, over and over again, at specified time intervals
setInterval(function(){alert("Hello")},3000);
setTimeout() - executes a function, once, after waiting a specified number of milliseconds.
setTimeout(function(){alert("Hello")},3000);
What is the difference between both setInterval and setTimeout
for you may be the setTimeout will not work as it will run only once after a delay and setInterval will go on to make continuous repetitive call until the window.clearInterval(intervalVariable) is been called
I have created an example on jsfiddler here. Basically you don't have to do this one at a time. Just get the whole collection of images as an array and loop over them. Hope this helps
$(document).ready(function () {
var arr = $('.pics')
arr.hide();
$(arr[0]).fadeIn(1500).delay(3500).fadeOut(1500);
var index = 1;
var maxIndex = arr.length - 1;
setInterval(function () {
/*arr.hide();
var pic = $(arr[index]);
pic.show();
*/
var pic = $(arr[index]);
pic.fadeIn(1500).delay(3500).fadeOut(1500);
index++;
if (index >= maxIndex) {
index = 0;
}
}, 6500);
});
There's really no need for setInterval here since you can use the callback built-into .fadeOut(), nor having to enumerate an array of images. You can do something as simple as:
var idx = 0;
fade();
function fade() {
if (idx >= $('img').length) idx = 0;
$('img').eq(idx).fadeIn(1500).delay(3500).fadeOut(1500, fade);
idx++;
}
jsFiddle example
This might be a dumb question but I can't get this super simple script to work.
I need a button that will reduce opacity by .1. every time it is clicked.
I've tried all of these.
x.style.opacity-.3; //This doesn't work. Doesn't do anything.
x.style.opacity=.3; //This gives me an opacity of .3.
x.style.opacity-=.3; //This gives an opacity of 0. Why?
x.style.opacity--; //This will give opacity of 0 as expected.
I even tried this:
var timesTen = x.style.opacity*10;
timesTen--;
timeTen/10;
x.style.opacity=timesTen; // This gives opacity of 0;
I would expect the answer to this problem to have something to do with a lack of understanding of the operators. But I've looked trough tons of arithmetic tutorials and they all seem full of integer examples that work perfectly fine for me. I've even copy pasted some of them and changed the numbers only to find that they stop working. I'm sorry if this is a noob question (As I am sure it is). Thank you
When I tested, you have to set opacity first, then you can read it to change it.
<div id="x" style="opacity:1.0">Hello</div>
x.style.opacity -= 0.3;
Because the above is not part of a standard (nor works in Firefox,) write as follows:
document.getElementById("x").style.opacity -= 0.3;
In the case of adding to the opacity, parseFloat is necessary, because string concatenation will happen otherwise. Or write -= -0.3 :)
x.style.opacity = parseFloat(x.style.opacity) - 0.1;
Why do it so difficult?
It doesn't work because the x.style.opacity property doesn't exist at this time, it is just applied thanks to css. Here is a workaround:
HTML:
<div id="t" style="background: black; opacity: 1;">Hello</div>
<div id="c" style="background: black;">Hello</div>
JS:
document.getElementById( 't' ).onclick = function() {
// This works
this.style.opacity = this.style.opacity - 0.1;
};
document.getElementById( 'c' ).onclick = function() {
var opacity = this.style.opacity;
// If the property exists, just decrement it
if ( opacity ) {
opacity -= 0.1;
}
// Else, set it (it will only be set once)
else {
opacity = 0.9;
}
};
Demo: http://jsfiddle.net/Ralt/xDFBY/