Transition smoothly with fading effects using JavaScript

I am currently working on the following code review:

I am looking for the most efficient way to detect when the fade in or fade out animation is complete before initiating a new function. I have implemented a method, but I believe there must be a better approach.

I have included alerts to help visualize the process.

The reason behind my goal is to ensure that the buttons only function correctly after the fading animation is complete.

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>

<body>
        <div>
        <span id="fade_in">Fade In</span> | 
        <span id="fade_out">Fade Out</span></div>
        <div id="fading_div" style="display:none;height:100px;background:#f00">Fading Box</div>
    </div>
</div>

<script type="text/javascript">
var done_or_not = 'done';

// fade in function
function function_opacity(opacity_value, fade_in_or_fade_out) { // fade_in_or_out - 0 = fade in, 1 = fade out
    document.getElementById('fading_div').style.opacity = opacity_value / 100;
    document.getElementById('fading_div').style.filter = 'alpha(opacity='+opacity_value+')';
    if(fade_in_or_fade_out == 1 && opacity_value == 1)
    {
        document.getElementById('fading_div').style.display = 'none';
        done_or_not = 'done';
        alert(done_or_not);
    }
    if(fade_in_or_fade_out == 0 && opacity_value == 100)
    {
        done_or_not = 'done';
        alert(done_or_not);
    }

}





window.onload =function(){

// fade in click
document.getElementById('fade_in').onclick = function fadeIn() {
    document.getElementById('fading_div').style.display='block';
    var timer = 0;
    if (done_or_not == 'done')
    {
        for (var i=1; i<=100; i++) {
            set_timeout_in = setTimeout("function_opacity("+i+",0)", timer * 10);
            timer++;
            done_or_not = 'not_done'
        }
    }
};

// fade out click
document.getElementById('fade_out').onclick = function fadeOut() {
    clearTimeout(set_timeout_in);
    var timer = 0;
    if (done_or_not == 'done')
    {
        for (var i=100; i>=1; i--) {
            set_timeout_out = setTimeout("function_opacity("+i+",1)", timer * 10);
            timer++;
            done_or_not = 'not_done'
        }
    }
};



}// END window.onload
</script>
</body>
</html>

Answer №1

I concur with some of the statements made. There are numerous impressive JavaScript libraries available that not only simplify the coding process but also handle some of the browser compatibility issues for you.

However, you have the option to tweak your fade functions to include a callback:

function fadeIn(callback) {
    return function() {
        function step() {
            // Execute one step of the animation

            if (/* check if the animation is complete*/) {
                callback();   // <-- call the callback
            } else {
                setTimeout(step, 10);
            }
        }
        setTimeout(step, 0); // <-- initiate the animation
    };
}

document.getElementById('fade_in').onclick = fadeIn(function() {
    alert("Done.");
});

In this manner, fadeIn will provide a function as output. This function will serve as the onclick handler. By passing a function to fadeIn, it will be executed after the final step of the animation. The inner function (one returned by fadeIn) will still have access to

callback</code due to JavaScript creating a <a href="https://developer.mozilla.org/en/JavaScript/Guide/Closures" rel="nofollow">closure</a>.</p>

<p>Your animation code could use some refinement, but this is essentially what most JavaScript libraries achieve:</p>

<ul>
<li>Execute the animation in steps;</li>
<li>Determine if the animation is complete;</li>
<li>Invoke the user's callback after the final step.</li>
</ul>

<p>Lastly, remember that animation can become quite intricate. For instance, if you desire a dependable method to ascertain the duration of the animation, incorporating tween functions (a practice followed by most libraries) is recommended. If math isn't your forte, this may pose a challenge...</p>

<hr>

<p>In response to your query: you wish for it to operate in the same manner; <em>"If the function is busy, nothing should occur."</em></p>

<p>So if I comprehend correctly, you prefer the animations to be blocking. Here are two points to consider:</p>

<ol>
<li>Your animations are not inherently blocking (at least, not the animations themselves -- refer below).</li>
<li>You can achieve the desired functionality even with asynchronous animations.</li>
</ol>

<p>Utilizing <code>done_or_not
for this purpose is a common practice. It's typical to use a boolean value (true or false) instead of a string, but the concept remains consistent:

// Before anything else:
var done = false;

// Define a callback:
function myCallback() {
    done = true;
    // Perform additional actions
}

// Execute the asynchronous action (e.g. animations):
done = false;
doSomething(myCallback);

I've created a simplistic example of the desired animation using jQuery exclusively. You can explore it here: http://jsfiddle.net/PPvG/k73hU/

var buttonFadeIn = $('#fade_in');
var buttonFadeOut = $('#fade_out');
var fadingDiv = $('#fading_div');

var done = true;

buttonFadeIn.click(function() {
    if (done) {
        // Set done to false:
        done = false;

        // Initiate the animation:
        fadingDiv.fadeIn(
            1500, // <- 1500 ms = 1.5 seconds
            function() {
                // Upon completion of the animation, set done to true again:
                done = true;
            }
        );
    }
});

buttonFadeOut.click(function() {
    // Similar to above, but using 'fadeOut'.
});

Thanks to the done variable, the buttons will solely respond when the animation has finished. The code is concise and easy to understand, showcasing the advantage of using a library like jQuery. Nevertheless, you are at liberty to construct your own solution.

In terms of performance, most JS libraries employ tweens for animations, which typically yield better performance than fixed steps. This results in smoother visuals for the user as the position is dictated by the duration of time passed rather than the number of steps taken.

I trust this information proves helpful. :-)

Answer №2

If you're looking to enhance your code, consider creating a separate function for your fade effects.

let alpha = 100;
function fade() { 
    if (alpha > 0) {
        alpha -= 1;    
        // Update your opacity here
        // (e.g.: .opacity = (alpha/100);
        // .style.filter = 'alpha(opacity='+alpha+')';)
    }
    else {
        // Actions to take upon completion - adjust the click event
    }
}

Additionally, you might consider including .MozOpacity along with .opacity and .filter. As noted in the previous comments, it may be more effective to cancel or complete a fade rather than preventing new clicks during the process.

By the way, kudos to you for hand-coding this. Using JavaScript libraries is often unnecessary and can lead to overuse.

Answer №3

There are several ways to address this issue. To see one solution, you can check out the code snippet on my home page:

http://marek.zielonkowski.com/thescript.js
One method involves clearing the time out by using the following code (though it's been a few years since I implemented this, so my memory is a bit fuzzy): clearInterval(isMoving);

this.fadeIn = function (){
    iCurrentAlpha = (iCurrentAlpha === null) ? alpha : iCurrentAlpha;
    clearInterval(isFading);
    isFading = setInterval(function(){changeFading(1);},timer);
}

Alternatively, you could create custom events and dispatch something like 'onFadeOutStop' to the listener.

Lastly, be cautious of using setTimeout('function_name()') with quotes, as it can lead to bad habits (set Timeout behaves similarly to eval, which is generally considered bad practice).

Answer №4

If you want to include animation in your web design, consider utilizing jQuery. You can easily trigger a function after an animation completes.

$('#clickthis').click(function(){
     //jQuery provides a simple way to animate CSS properties
     //The 5000 indicates the duration in milliseconds
     $('#animatethis').animate({opacity:0},5000,function(){

         //This code will only execute once the animation is finished
         alert('finished animating');

     });

     //Alternatively, you can use the fadeOut function
     $('#animatethis').fadeOut(5000,function(){
          //This code will only run once the animation is complete
         alert('finished fading out'); 
     });
});

That should work, although I haven't tested it myself, so please forgive any potential errors.

-L

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to navigate through images on Bootstrap Carousel using previous and next buttons

Despite following tutorials and examining the HTML code on bootstrap, I'm facing issues while trying to create a carousel. I believed that everything was done correctly, but when I click on the next button, nothing happens. <!DOCTYPE html> < ...

Deciding on the proper character formatting for each individual character within the RICHT TEXT EDITOR

After browsing numerous topics on Stackoverflow, I was able to develop my own compact rich text editor. However, one issue I encountered is that when the mouse cursor hovers over already bold or styled text, it's difficult for me to identify the styl ...

Looking to set the "min" attribute for an input type="date" in HTML5 with a specific date format preselected?

My upcoming date has a specific format as detailed below. Date_received = Tue Apr 05 2016 00:00:00 GMT+0530 (India Standard Time) To set the 'min' attribute for the HTML5 input type="date" datepicker, I need to initialize it using the following ...

I am facing an issue with the Ionic Framework where the Javascript function for JWPlayer only works after the page is reloaded. Can anyone help

I'm currently troubleshooting the use of JWPlayer for streaming videos in an Ionic app. However, I've encountered a problem. The player only seems to load when I refresh the page, rather than when I navigate through the list of videos. Here is ...

Discovering instances of a specific string within a larger string

My goal is to customize the default behavior of the alert function. Below is the code I am using: window.alert=function(txt) { waitOk='wait'; setMsgBox(txt); btnMsgOk.focus(); } However, I need this functionality to vary ba ...

Retrieving data in Next.js

Exploring various techniques to retrieve information from APIs in next.js. Options include getServerSideProps, getStaticPaths, getStaticProps, Incremental Static Regeneration, and client-side rendering. If I need to send requests to the backend when a s ...

Utilizing jQuery and CSS to make an entire div clickable, and activate an 'a' tag hover state upon hovering

Looking to create a clickable link for the .wrapper div that directs users to the location of a.icon. Want the .wrapper div to activate the a.icon:hover state when hovered over, not just when hovering over the icon itself. Any assistance would be highly a ...

Using a javascript parameter in a cshtml file to filter data in a datatable

Here is the model code public class viewCase { public List<string> lstCategory { get; set; } public DataTable dtWrkTsk { get; set; } } This is the controller code string query = "SELECT WorkFlowID,Subject,Category FROM CMSTasksWorkFlow" ob ...

Issue with displaying YouTube videos in HTML causing them to be downloaded instead of playing

I'm currently facing an issue with loading a video on my HTML page using the following code: <video v-for="(data, key) in projectData.videos" :key="key" width="320" height="240" controls> <source :src="data.url"> </video> One ...

Can we set a specific length for an array passed in as a prop?

Can we use Typescript to specify the exact length of an array coming from props? Consider the following array of objects: const sampleArray = [ { key: '1', label: 'Label 1', value: 9 }, { key: '2', label: 'Label 2&ap ...

The majority of my next.js website's content being indexed by Google consists of JSON and Javascript files

I’m facing an issue with Google indexing on Next.js (utilizing SSR). The challenge lies in ensuring that .HTML files are effectively indexed for SEO purposes. However, it seems that Googlebot predominantly indexes JSON and JavaScript files. To illustra ...

Developing a Chrome browser extension tailored for parsing unique file formats

Currently, I am working on developing a compiler for a unique conditional formatting language. My aim is to enable the capability of opening files in my language directly in Chrome by simply double-clicking on them in File Explorer (I am currently using Wi ...

Are HTML entities ineffective in innerHTML in javascript?

Take this example: <script type="text/javascript> function showText() { var text = document.getElementById("text-input").value; document.getElementById("display").innerHTML = text; } </script> <?php $text = "<html>some ...

How can you identify when an input value has been modified in Angular?

For my current project, I am developing a directive to be used with a text input field in order to format currency input. This directive has two HostListeners - one for when the input loses focus and one for when it gains focus. When the blur event occurs, ...

Changing the background color of required inputs that are empty using jQuery

I need help customizing the background color of required input fields that are left empty when a user submits a form. Some of the fields are optional, but I want only the required ones to be highlighted in red. Specifically, the required fields have been ...

Is a DOM lookup performed each time Vue's ref is utilized?

Exploring the capabilities of Vue.js, I have integrated a few refs into my current project. However, I am curious about the efficiency of calling refs in methods. Does Vue perform a DOM lookup every time a ref is called, or does it store all refs once for ...

Flex items maintaining their size when the window decreases

My goal is to arrange two plotly plots side by side within a CSS flexbox, with the ability to resize them as the window size changes. The issue I'm facing is that while the plots expand correctly when the window is enlarged, they fail to shrink when t ...

Can you tell me about some commonly used GUI widgets in Servlet-JSP?

I am new to working with Servlets, Tomcat, JSP, and I am curious about the common practices for incorporating GUI elements into JSP pages to enhance client-side interactivity. I have experience with jQuery, YUI, extJS, among others, for JavaScript scriptin ...

When attempting to send data using jQuery to PHP, an issue arises where PHP is unable to receive the information, resulting in an undefined variable

Has anyone successfully sent data from an HTML select to a PHP file using jQuery? I've tried multiple solutions suggested here, but none seem to be working for me. Below is the code I'm using: <select id="city" name="city" > <optgro ...

JavaScript tabs function malfunctioning upon page load

I attempted to implement tabs on my website using this example: http://www.w3schools.com/howto/howto_js_tabs.asp Although everything is functioning correctly, the default tab isn't opening as expected. The tab opens, but the header color does not get ...