setTimeout issue - javascript

I'm trying to create a jquery fadeto type of effect in Javascript, but am having an issue with my setTimeout command.
Here is the code:
function textfade(y) {
var x = document.getElementById("test");
var y;
if (y == undefined) {
y = 1.0;
}
x.style.opacity = y;
y -=0.1;
setTimeout(function(){ textfade(y); }, 50);
}
The problem is x.style.opacity = y.
Without that, the timeout runs fine. With it, however, it runs through the function one time and then dies. While I feel like it's a simple error, I am out of ideas for fixing it.
Any advice would be greatly appreciated.
Thank you in advance.

You're re-declaring y each time textfade() is executed, effectively destroying / resetting the passed parameter.
Remove:
var y;

Ensure that you are running it after test element is already available. Here it works fine: http://jsfiddle.net/3yDMP/ . And here: http://jsfiddle.net/3yDMP/3/ - no , because function is called in head, not in onload (like in first fiddle), when dom is not ready yet and is not available.
So, in your could be
<head>
<script>
function textfade() {...}
</script>
</head>
<body onload="textfade()">
<div id="test"> ... </div>

IMHO this would be better with the setTimeout calling an internal closure where the current opacity level is maintained outside of the fade function itself, so you don't have to pass it around.
function textfade(el) {
if (typeof el === "string") {
el = document.getElementById(el);
}
var opacity = 1.0;
(function fade() {
el.style.opacity = opacity;
opacity -= 0.1;
if (opacity > 0) {
setTimeout(fade, 50);
}
})();
}
demo at http://jsfiddle.net/alnitak/TQHYj/

Related

Javascript fade in doesn't visibly animate

So I've created the following function to fade elements in and passed in a div that I want to fade in which in this case is an image gallery popup that I want to show when a user clicks an image thumbnail on my site. I'm also passing in a speed value (iSpeed) which the timeout uses for it's time value. In this case I'm using 25 (25ms).
I've stepped through this function whilst doing so it appears to be functioning as expected. If the current opacity is less than 1, then it is incremented and it will recall itself after the timeout until the opacity reaches 1. When it reaches one it stops fading and returns.
So after stepping through it, I take off my breakpoints and try to see it in action but for some reason my gallery instantly appears without any sense of fading.
var Effects = new function () {
this.Fading = false;
this.FadeIn = function (oElement, iSpeed) {
//set opacity to zero if we haven't started fading yet.
if (this.Fading == false) {
oElement.style.opacity = 0;
}
//if we've reached or passed max opacity, stop fading
if (oElement.style.opacity >= 1) {
oElement.style.opacity = 1;
this.Fading = false;
return;
}
//otherwise, fade
else {
this.Fading = true;
var iCurrentOpacity = parseFloat(oElement.style.opacity);
oElement.style.opacity = iCurrentOpacity + 0.1;
setTimeout(Effects.FadeIn(oElement, iSpeed), iSpeed);
}
}
}
Here's where I'm setting up the gallery.
this.Show = function (sPage, iImagesToDisplay, oSelectedImage) {
//create and show overlay
var oOverlay = document.createElement('div');
oOverlay.id = 'divOverlay';
document.body.appendChild(oOverlay);
//create and show gallery box
var oGallery = document.createElement('div');
oGallery.id = 'divGallery';
oGallery.style.opacity = 0;
document.body.appendChild(oGallery);
//set position of gallery box
oGallery.style.top = (window.innerHeight / 2) - (oGallery.clientHeight / 2) + 'px';
oGallery.style.left = (window.innerWidth / 2) - (oGallery.clientWidth / 2) + 'px';
//call content function
ImageGallery.CreateContent(oGallery, sPage, iImagesToDisplay, oSelectedImage);
//fade in gallery
Effects.FadeIn(oGallery, 25);
}
Could anyone help me out?
Also, I'm using IE10 and I've also tried Chrome, same result.
Thanks,
Andy
This line:
setTimeout(Effects.FadeIn(oElement, iSpeed), iSpeed);
calls Effects.FadeIn with the given arguments, and feeds its return value into setTimeout. This is exactly like foo(bar()), which calls bar immediately, and then feeds its return value into foo.
Since your FadeIn function doesn't return a function, that would be the problem.
Perhaps you meant:
setTimeout(function() {
Effects.FadeIn(oElement, iSpeed);
}, iSpeed);
...although you'd be better off creating that function once and reusing it.
For instance, I think this does what you're looking for, but without recreating functions on each loop:
var Effects = new function () {
this.FadeIn = function (oElement, iSpeed) {
var fading = false;
var timer = setInterval(function() {
//set opacity to zero if we haven't started fading yet.
if (fading == false) { // Consider `if (!this.Fading)`
oElement.style.opacity = 0;
}
//if we've reached or passed max opacity, stop fading
if (oElement.style.opacity >= 1) {
oElement.style.opacity = 1;
clearInterval(timer);
}
//otherwise, fade
else {
fading = true;
var iCurrentOpacity = parseFloat(oElement.style.opacity);
oElement.style.opacity = iCurrentOpacity + 0.1;
}
}, iSpeed);
};
};
Your code has a lot of problems. The one culpable for the element appearing immediately is that you call setTimeout not with a function but with the result of a function, because Effects.FadeIn will be executed immediately.
setTimeout(function(){Effects.FadeIn(oElement, iSpeed)}, iSpeed);
will probably act as you intend.
But seriously, you probably should not re-invent this wheel. jQuery will allow you to fade elements in and out easily and CSS transitions allow you to achieve element fading with as much as adding or removing a CSS class.
T.J. and MoMolog are both right about the bug: you're invoking the Effects.FadeIn function immediately before passing the result to setTimeout—which means that Effects.FadeIn calls itself synchronously again and again until the condition oElement.style.opacity >= 1 is reached.
As you may or may not know, many UI updates that all take place within one turn of the event loop will be batched together on the next repaint (or something like that) so you won't see any sort of transition.
This jsFiddle includes the suggested JS solution, as well as an alternate approach that I think you may find to be better: simply adding a CSS class with the transition property. This will result in a smoother animation. Note that if you go this route, though, you may need to also include some vendor prefixes.

How to make a Div's height change slower

I want to make a Div appear by scrolling down on a button click slowly from the top of the page. But when I do it with what I have now, it just appears very fast and does not really slide down. What am I doing wrong?
function showstuff(inquiryForm){
document.getElementById(inquiryForm).style.visibility="visible";
for (var i=0;i<300;i++)
{
document.getElementById(inquiryForm).style.height= i + "px";
}
}
You are looping 300 items and you try to find the element with getELementById and then trying to style the selected item
I think that makes the process really slow and laggy.
Here is an example that should help you understand the event loop,
and the use of setTimeout.
<div id="myDiv" style="width:10px;height:50px;background:#f00;"></div>
<button class="btn" onclick="start();">Start</button>
<button class="btn" onclick="stop();">Stop</button>
<button class="btn" onclick="reset();">Reset<button>
var timeout;
function start() {
var div = document.getElementById("myDiv");
var size = 10;
var func = function () {
timeout = setTimeout(func, 0);
div.style.width = size + "px";
if (size++ == 600) stop();
}
func(); // starts the process
}
function stop() {
clearInterval(timeout);
}
function reset() {
var div = document.getElementById("myDiv");
div.style.width = "10px";
}
this sort of thing is often handled using jquery, as it includes various animation functions, including a convenient short form that would be useful here:
once you've included the jquery library, you can use a function like this:
$(inquiryForm).slideDown( 500 );
where the argument is duration of the effect in ms
like so:
function showstuff(inquiryForm){
$(inquiryForm).slideDown( 500 );
}

Showing/hiding <div> using javascript

For example I have a function called showcontainer. When I click on a button activating it, I want a certain div element, in this case <div id="container">, to fade in. And when I click it again, fade out.
How do I achieve this?
Note: I am not accustomed with jQuery.
So you got a bunch of jQuery answers. That's fine, I tend to use jQuery for this kind of stuff too. But doing that in plain JavaScript is not hard, it's just a lot more verbose:
var container = document.getElementById('container');
var btn = document.getElementById('showcontainer');
btn.onclick = function() {
// Fade out
if(container.style.display != 'none') {
var fade = setInterval(function(){
var opacity = parseFloat(container.style.opacity);
opacity = isNaN(opacity) ? 100 : parseInt(opacity * 100, 10);
opacity -= 5;
container.style.opacity = opacity/100;
if(opacity <= 0) {
clearInterval(fade);
container.style.opacity = 0;
container.style.display = 'none';
}
}, 50);
// Fade in
} else {
container.style.display = 'block';
container.style.opacity = 0;
var fade = setInterval(function(){
var opacity = parseFloat(container.style.opacity);
opacity = isNaN(opacity) ? 100 : parseInt(opacity * 100, 10);
opacity += 5;
container.style.opacity = opacity/100;
if(opacity >= 100) {
clearInterval(fade);
container.style.opacity = 1;
}
}, 50);
}
};
Check the working demo.
Provided you're not opposed to using jQuery per se, you can achieve this easily:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#showcontainer').click(function() {
$('#container').fadeToggle();
});
});
</script>
...
<div id="container">
...
</div>
...
<input type="button" id="showcontainer" value="Show/hide"/>
...
Note the missing http: in the beginning of the source of jQuery. With this trick the browser will automatically use http: or https: based on whether the original page is secure.
The piece of code after including jQuery assigns the handler to the button.
Best thing you could do is start now and get accustomed to jQuery.
The page http://api.jquery.com/fadeIn/ has all the example code that could be written here. Basically you want to have the call to fadeIn in your showcontainer function.
function showcontainer() {
$('#container').fadeIn();
}
You can have a look at jQuery UI Toggle.
The documentation turns the use of the library very simple, and they have many code examples.
You'd be as well off learning jQuery as it makes it a lot easier to do things!
From the sounds of it, you could have the container div already in the HTML but with a style of "display:none;", and then simply show it in your click event using (jQuery):
$('#container').fadeIn('slow', function() {
//Any additional logic after it's visible can go here
});

javascript change image slowly with fade using timer and opacity

i am looking for some help with this script i have been working on. here is my file fade.js
the problem is with the changing, it is messed up. please help me find the problem and solution for this, thanks.
JS-file
//image fade script
var opacity = 0;
function changeimg(currentimage){
rnumb = Math.floor(Math.random()*2);
var newimage = "./images/" + rnumb + ".jpg";
if (newimage !== currentimage)
{
document.getElementById("fadeImg").src= newimage;
}
}
function fadein()
{
var fadeImg = document.getElementById('fadeImg');
var browserName=navigator.appName;
if(browserName=="Microsoft Internet Explorer")
{
browserOpacity = opacity / 10;
fadeImg.filters.alpha.opacity = browserOpacity;
}
else
{
browserOpacity = opacity / 1000;
fadeImg.style.opacity = browserOpacity;
}
if(opacity < 1000)
{
initiate();
}
else if(opacity == 1000)
{
changeimg(document.getElementById("fadeImg").src);
opacity = 0;
}
}
function initiate()
{
opacity++;
setInterval("fadein()", 500);
}
index.html
<script type="text/javascript" src="fade.js"></script>
<body onload="initiate()">
<img id="fadeImg" src="images/1.jpg" style="opacity:0.0; filter:alpha(opacity=0)"/>
</body>
JS-fiddle
Here is a Fiddle of the code as well: http://jsfiddle.net/epqKr/2/ (Notice that the code, as it is in the fiddle, may make your browser freeze after a while.
I think you should use a cross-browser library to accomplish things like this.
Microsoft Internet Explorer, especially in versions < 9, is most likely to not behave
as you would expect it does, particularly when you try to use functions which makes use of opacity, alpha-filter and timing. You could try to use jQuery, or Prototype, or MooTools and such frameworks. They all make what you're looking for in simple, secure, better way.
Don't call initiate() from within the fadeIn() function, instead just increment your opacity control variable (i.e, opacity += 1;).
You will probably want to save your setInterval return value to kill the callbacks when you have finished your animation.
You also probably will want to increase the animation speed by lowering the interval.
animId = setInterval("fadeIn()", 5);
i am working on this still, heres what i have now: it doesnt work whatsoever but it looks better.
html
<html>
<head>
<script type="text/javascript" src="fade1.js"></script>
</head>
<body onload="fadetimer()">
<img id="fadeImg" src="1.jpg" style="opacity:0.0; filter:alpha(opacity=0)"/>
</body>
</body>
</html>
script
//image fade script
var opacity = 0;
function changeimg(currentimage){
rnumb = Math.floor(Math.random()*2);
var newimage = rnumb + ".jpg";
if (newimage !== currentimage)
{
document.getElementById("fade").src= newimage;
}
}
function fadein()
{
var fade = document.getElementById('fade');
if(fade.filters.alpha.opacity >= 100 || fade.style.opacity >= 1.0)
{
changeimg(fade.src);
fade.filters.alpha.opacity = 0;
fade.style.opacity = 0;
}
else
{
fade.filters.alpha.opacity += 10;
fade.style.opacity += 0.1;
}
}
function fadetimer()
{
setInterval("fadein()", 500);
}

Simple nested setTimeout() only runs once (JavaScript)

For some reason my galleryScroll() function only runs once, even though the function calls itself using setTimeout(). I'm thinking the issue may be related to scope, but I'm not sure:
http://jsfiddle.net/CYEBC/2/
$(document).ready(function() {
var x = $('#box').offset().left;
var y = $('#box').offset().top;
galleryScroll();
function galleryScroll() {
x = x + 1;
y = y + 1;
$('#box').offset({
left: x,
top: y
});
setTimeout('galleryScroll()', 100);
}
});​
The HTML:
<html>
<head>
</head>
<body>
<div id="box">
</div>
</body>
</html>​
The function galleryScroll() isn't defined in the correct scope to be evaluated in setTimeout(). If you want it running in a loop, call it in setInterval() after the function.
$(document).ready(function() {
var x = $('#box').offset().left;
var y = $('#box').offset().top;
galleryScroll();
function galleryScroll() {
x = x + 1;
y = y + 1;
$('#box').offset({
left: x,
top: y
});
}
// Call in setInterval() outside the function definition.
// Note also, I've changed the eval string 'gallerySroll()' to the function reference galleryScroll
setInterval(galleryScroll, 100);
});​
Here is the updated fiddle.
Your problem is how you're calling the galleryScroll() function in your setTimeout. Change that line to this:
setTimeout(galleryScroll, 100);
The result: http://jsfiddle.net/CYEBC/12/
Note: I'm not sure if this is the desired behavior, but it's what happens when your code is called properly.

Categories

Resources