JQuery: fadeOut (). empty (). append (...). fadeIn () does not work correctly for the first time only

I am trying to understand why I get the behavior that I see. I have a piece of code whose purpose is to fadeOut the container, replace the contents, and then extinguish it again when it is done.

I am using jQuery, so the code looks like this:

var transitionToNewContent = function(container, new_content) { container.fadeOut().delay(1000).empty().append(new_content).fadeIn(); }; transitionToNewContent($('#id'), "<p>magic</p>"); 

The first time you click on a link that activates this transition, the content is instantly replaced, then there is a fading, then it disappears again.

Each time after that, when the link is clicked, I see the correct behavior: fadeout, then fadein with new content.

Any idea why this is happening?

I attached a full html file that shows the behavior:

I am new to jquery and I try to do everything right. Any style comments would be appreciated.

 <doctype html> <html> <head> <style type="text/css"> #main_container { width: 800px; margin-left: auto; margin-right: auto; margin-bottom: 3em; margin-top: 0; height: 100%; position: relative; top: 0px; bottom: 0px; } #loading { float: right; position: relative; top: 10px; left: 10px; z-index: 1; } #sidebar { float: left; width: 240px; border: #078600 1px dashed; position: relative; top: 10px; left: -250px; margin-right: 20px; background: #cccccc; z-index: 1; padding: 10px; font-size: 0.65em; display: none; } #main_content { z-index: 0; position: absolute; top: 0px; left: 5px; width: 100%; height: 100%; float: right; background: white; padding-top: 0; padding-bottom: 3em; padding-left: 20px; border-right: 1px dotted #078600; border-left: 1px dotted #078600; border-top: 3px solid white; } </style> <link rel="stylesheet" type="text/css" href="/main.css" /> </head> <body> <div id="main_container"> <div id="sidebar"><h1>Sidebar</h1><p>some text</p></div> <div id="loading" style="display: none">&nbps;</div> <div id="main_content"> <h1 id="page_title">Title</h1> <div id="page_content"><h2>heading</h2><p>Some testing text</p></div> </div> </div> <script type="text/javascript"> var include = function(src) { document.write('<script type="text/javascript" src="' + src + '"></scr' + 'ipt>'); }; include("http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"); include("http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js"); var bootStrapSites = function() { var sideBar = $('#sidebar'); sideBar.delay(1000).fadeIn(); loadSiteList(sideBar); }; var transitionToNewContent = function(container, new_content) { container.fadeOut().delay(1000).empty().append(new_content).fadeIn(); }; var editSite = function(site) { transitionToNewContent($('#page_content'), "<p>This is where the magic will happen</p>"); }; var loadSiteList = function(container) { // $.getJSON("/sites/list.json", function(data) { var data = $.parseJSON('[{"id": "1", "name": "cool name"}]'); container.empty(container); container.append("<h2>new heading</h2>"); container.append("<ul id='sitesList'></ul>"); var sitesList = $('#sitesList'); $.each(data, function(idx, site) { var id = 'show_site_id_' + site._id; sitesList.append("<li><a id='" + id + "' href='#'>" + site.name + "</a></li>"); $('#' + id).click(function() { editSite(site); }); }); // }); }; </script> <script type="text/javascript"> $(document).ready(function() { bootStrapSites(); }); </script> </body> </html> 
+8
javascript jquery jquery-ui
source share
2 answers

The problem is that there are two different types of functions in jQuery: those that take effect immediately and those that add effects to the effects queue.

Look at your code:

 container.fadeOut().delay(1000).empty().append(new_content).fadeIn(); 
  • fadeOut adds a fade operation to the queue
  • delay adds delay to the queue
  • empty immediately empties the item
  • append immediately adds content
  • fadeIn adds a fade operation to the queue

Functions that add items to the queue are returned immediately - they do not wait for completion before they take effect. This means that all functions are called at the same time (to a large extent) - they do not wait for the completion of animation functions.

Instead, you need to use the fadeOut callback argument:

 container.fadeOut(1000, function(){ container.empty().append(new_content).fadeIn(); }); 

The function is triggered when the decay operation is completed, so emptying and adding are delayed until the element is hidden.

+30
source share

You need to use the callback function to get the effect you are looking for.

 var transitionToNewContent = function(container, new_content) { container.fadeOut(1000, function(){ $(this).empty().append(new_content).fadeIn(); }); }; 

This ensures that the container will not be replaced until AFTER the animation is complete.

+2
source share

All Articles