15

Hi friends i want to fade in a div when i click on another div and for that i am using following code. Code1 works fine but i require to use the Code2.

I know there is jQuery but i require to do this in JavaScript

Can you guide me that what kind of mistake i am doing or what i need change...

Code1 --- Works Fine

function starter() { fin(); }

function fin()
{
    for (i = 0; i <= 1; i += 0.01)
    {
        i=Math.round(i*100)/100;
        setTimeout("seto(" + i + ")", i * 1000);
    }
}

function seto(opa)
{
    var ele = document.getElementById("div1");
    ele.style.opacity = opa;
}

Code2 --- Does not work

function starter()
{
    var ele = document.getElementById("div1");
    fin(ele);
}
function fin(ele)
{
    for (i = 0; i <= 1; i += 0.01)
    {
        i=Math.round(i*100)/100;
        setTimeout("seto(" + ele + "," + i + ")", i * 1000);
    }
}

function seto(ele,opa)
{
    ele.style.opacity = opa;
}
kanudo
  • 2,119
  • 1
  • 17
  • 33
  • Here is a little gem that will help you with that http://youmightnotneedjquery.com/ – Matthew Layton Apr 23 '14 at 12:32
  • you should really use `setInterval` and `clearInterval` instead. Take a look at http://stackoverflow.com/questions/2695462/fade-html-element-with-raw-javascript – yas Apr 23 '14 at 12:40

8 Answers8

29

Based on this site

EDIT-1
Added the functionality so that user can specify the animation duration(@Marzian comment)

You can try this:

function fadeIn(el, time) {
  el.style.opacity = 0;

  var last = +new Date();
  var tick = function() {
    el.style.opacity = +el.style.opacity + (new Date() - last) / time;
    last = +new Date();

    if (+el.style.opacity < 1) {
      (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
    }
  };

  tick();
}

var el = document.getElementById("div1");
fadeIn(el, 3000); //first argument is the element and second the animation duration in ms

DEMO

laaposto
  • 11,835
  • 15
  • 54
  • 71
  • i edited it a bit to my needs... at http://jsfiddle.net/TH2dn/3/ ... and it does not work friend as i passed the value using another function – kanudo Apr 23 '14 at 13:15
  • Yes that because you dont warp your onclick function. This is working http://jsfiddle.net/TH2dn/4/ – laaposto Apr 23 '14 at 13:17
  • Read here http://stackoverflow.com/questions/9114747/onclick-event-not-firing-on-jsfiddle-net – laaposto Apr 23 '14 at 13:17
  • Can you tell me that what does "+el.style.opacity" means in "el.style.opacity = +el.style.opacity + 0.01;"... actually i have seen like "a = a+1" or "a = a + 0.1" but "a = +a + 1" i have seen this for first time – kanudo Apr 23 '14 at 14:56
  • 1
    @Kanudo `+el.style.opacity` just converts the object to a number so that you can add it with 0.01 – laaposto Apr 23 '14 at 14:59
  • @Kanudo Read here http://stackoverflow.com/questions/6682997/javascript-plus-symbol-before-variable – laaposto Apr 23 '14 at 14:59
  • nice solution. Transition can also be sped up by changing the incremental value from 0.01 to 0.05. (for example) – richardstelmach Jul 21 '16 at 10:10
  • With this method, how could I set a precise time, like the 3000 ms of the default jQuery fadeIn()? – CharlesM Mar 08 '18 at 18:03
  • 1
    @Marzian Added animation duration as a param to the function. – laaposto Mar 08 '18 at 20:07
  • A quick improvement would be `el.style.opacity = +el.style.opacity + Math.min((new Date() - last) / time, 1);` this will prevent overflowing opacity over 1 since request animation frame can be called by browser when tab is not visible with lower frequency – kasvith May 10 '21 at 11:53
15

Update: It seems that people enjoy my minimalistic and elegant approach, Updated for 2022:

No need for complex mechanisms. Just use CSS, which has it out of the box and has better performance overall.

Basically you achieve it with CSS by setting a transition for the opacity. In JavaScript that would be:

const div = document.querySelector('#my-div');
div.style.transition='opacity 1s';

and as a trigger you just set opacity to 0:

div.style.opacity=0;

This will create a 1 second fade out effect and you can use the trigger anywhere. The inverse can also be done to achieve a fade in effect.

Here's a working example:

const div = document.querySelector('#my-div');
div.style.transition='opacity 1s';

// set opacity to 0 -> fade out
setInterval(() => div.style.opacity=0, 1000);

// set opacity to 1 -> fade in
setInterval(() => div.style.opacity=1, 2000);
#my-div { background-color:#FF0000; width:100%; height:100%; padding: 10px; color: #FFF; }
<div id="my-div">Hello!</div>
Kai
  • 1,156
  • 8
  • 18
1

Seems like your attempting to convert your element, to a string. Try this instead

function starter()
{
    var ele = document.getElementById("div1");
    fin(ele);
}
function fin(ele)
{
    for (i = 0; i <= 1; i += 0.01)
    {
        i=Math.round(i*100)/100;
        setTimeout(function() { setto(ele,i); }, i * 1000);
    }
}

function seto(ele,opa)
{
    ele.style.opacity = opa;
}

What happens here is, that i call a anonnymous function when the timer hits, and from that function, execute my functioncall to setto.

Hope it helps. Jonas

Jonas m
  • 2,646
  • 3
  • 22
  • 43
  • 1
    You have a typo `setto` must be `seto` – laaposto Apr 23 '14 at 12:37
  • I tried this also but it does not give me the fade effect. the div directly goes visible – kanudo Apr 23 '14 at 12:38
  • And if the call parameter is getting converted to a string then the "Code1" also should not work... the only difference between both the code is that in "Code1" i am passing just one parameter under setTimeout while in "Code2" i am passing 2 parameters – kanudo Apr 23 '14 at 12:41
1

The problem here is you are using the pass-a-string method of using setTimeout. Which is basically just a hidden eval.

It's worth noting that this is a bad practice, slow performer, and security risk.

(see questions such as this: setTimeout() with string or (anonymous) function reference? speedwise)

The reason this is causing your problem is because "seto(" + ele + "," + i + ")" is going to evaluate to "seto('[object HTMLDivElement]', 1)". You really want to pass reference to the ele object -- but the value's being cast to a string when you tried concatenating an object onto a string. You can get around this by using the pass-a-function method of using setTImeout.

setTimeout(function() { seto(ele, i); }, i * 1000);

I believe making this change will make your Code2 behavior equivalent to Code1.

Community
  • 1
  • 1
sejordan
  • 311
  • 2
  • 5
1

Below are the complete answers to my question

ANS1 --- DEMO

function fin() {
    var i = 0;
    var el = document.getElementById("div1");
    fadeIn(el,i);
}

function fadeIn(el,i) {
    i = i + 0.01;
    seto(el,i);
    if (i<1){setTimeout(function(){fadeIn(el,i);}, 10);}
}

function seto(el,i) {
    el.style.opacity = i;
}

ANS2 --- DEMO

function fin(){
    var i = 0;
    var el = document.getElementById("div1");
    fadeIn(el,i);
}

function fadeIn(el,i) {
    var go = function(i) {
        setTimeout( function(){ seto(el,i); } , i * 1000);
    };
    for ( i = 0 ; i<=1 ; i = i + 0.01) go(i);
}

function seto(el,i)
{
    el.style.opacity = i;
}
kanudo
  • 2,119
  • 1
  • 17
  • 33
1

My version

 function fadeIn($element){
  $element.style.display="block";
  $element.style.opacity=0;
  recurseWithDelayUp($element,0,1);
}
function fadeOut($element){
  $element.style.display="block";
  $element.style.opacity=1;
  recurseWithDelayDown($element,1,0);
}

function recurseWithDelayDown($element,startFrom,stopAt){
    window.setTimeout(function(){
      if(startFrom > stopAt ){
          startFrom=startFrom - 0.1;
            recurseWithDelayDown($element,startFrom,stopAt)
            $element.style.opacity=startFrom;
      }else{
        $element.style.display="none"
      } 
  },30);
}
function recurseWithDelayUp($element,startFrom,stopAt){
    window.setTimeout(function(){
      if(startFrom < stopAt ){
          startFrom=startFrom + 0.1;
            recurseWithDelayUp($element,startFrom,stopAt)
            $element.style.opacity=startFrom;
      }else{
        $element.style.display="block"
      } 
  },30);
}
ShAkKiR
  • 863
  • 9
  • 20
0

I just improved on laaposto's answer to include a callback. I also added a fade_out function. It could be made more efficient, but it works great for what i'm doing.

Look at laaposto's answer for implementation instructions. You can replace the JS in his fiddle with mine and see the example.

Thanks laaposto! This really helped out for my project that requires zero dependencies.

let el = document.getElementById( "div1" );

function fade_in( element, duration, callback = '' ) {
    element.style.opacity = 0;
    let last = +new Date();
    let tick = function() {
        element.style.opacity = +element.style.opacity + ( new Date() - last ) / duration;
        last = +new Date();
        if ( +element.style.opacity < 1 )
            ( window.requestAnimationFrame && requestAnimationFrame( tick ) ) || setTimeout( tick, 16 );
        else if ( callback !== '' )
            callback();
    };
    tick();
}

function fade_out( element, duration, callback = '' ) {
    element.style.opacity = 1;
    let last = +new Date();
    let tick = function() {
        element.style.opacity = +element.style.opacity - ( new Date() - last ) / duration;
        last = +new Date();
        if ( +element.style.opacity > 0 )
            ( window.requestAnimationFrame && requestAnimationFrame( tick ) ) || setTimeout( tick, 16 );
        else if ( callback !== '' )
            callback();
    };
    tick();
}

fade_out( el, 3000, function(){ fade_in( el, 3000 ) } );

Cheers!

Bram Hammer
  • 363
  • 4
  • 21
Justin Waulters
  • 303
  • 2
  • 8
0
function hide(fn){
        var hideEle = document.getElementById('myElement');
        hideEle.style.opacity = 1;
        var fadeEffect = setInterval(function() {
        if (hideEle.style.opacity < 0.1)
        {
        hideEle.style.display='none';
        fn();
        clearInterval(fadeEffect);
        }
        else
        {
        hideEle.style.opacity -= 0.1;
        }
        }, 20);
}
function show(){
        var showEle = document.getElementById('myElement');
        showEle.style.opacity = 0;
        showEle.style.display='block';
            var i = 0;
            fadeIn(showEle,i);
            function fadeIn(showEle,i) {
                i = i + 0.05;
                seto(showEle,i);
                if (i<1){setTimeout(function(){fadeIn(showEle,i);}, 25);}
            }
            function seto(el,i)
            {
                el.style.opacity = i;
            }
}

hide(show);
Yoel Duran
  • 381
  • 3
  • 5