i want to expand a division with data that should be loaded from another server.
the problem is if i start expanding the division (toggleslide) and the load method finishs the height is jumping and the effect is destroyed.
what i want is that jquery starts expanding AFTER the data-transfer finished but my following code does not work:
// divison name = details
details.load("index.php", expandLastResultDetails3(details));
function expandLastResultDetails3(details) {
$(details).slideToggle('slow', function () {
ready();
});
}
the box is jumping because (i guess) the slidetoggle starts to early.
.load() expects a function callback to be called upon the completion of the request. However, instead of passing a callback, you are executing the function. Try the following:
details.load("index.php", function () {
expandLastResultDetails3(details);
});
Related
I am working on a font-test page that should switch the font of the header and paragraph tags on click. Which works fine but the experience is really jarring so I want to smooth it out with the following path:
fadeout -> do the font swap -> fade in
But the code runs the font swap first, then the animation.
I have the following code snippet, I am only including the jQuery because it's the root cause of my problem.
// Anytime a card is clicked
$('.card').click(function(){
// Call card by id and switch the fonts
var id = "#" + this.parentElement.id;
$(this).fadeOut(900,swapFont(id));
$(this).fadeIn(500);
// attach the above to some sort of transition callback
});
// Function to swap the font around so that the header is now the body font and the body font is now the header font
function swapFont(id) {
// font-swap logic in here which works fine
}
The issue is because the fadeOut() animation is (effectively) asynchronous. This means the next statement will be evaluated while the animation is in progress - hence the behaviour you're seeing. To fix this you need to use the callback pattern that the fadeX() methods provide.
Also, you're passing the result of the immediate execution of swapFont() to the callback, instead of a function reference to run when the event occurs. Try this:
$('.card').click(function(){
var id = "#" + this.parentElement.id;
$(this).fadeOut(900, function() {
swapFont(id);
$(this).fadeIn(500);
});
});
You are currently passing the result of the swapFont() call, instead you need to point to the function itself.
So this:
$(this).fadeOut(900,swapFont(id));
is the same as:
var x = swapFont(id);
$(this).fadeOut(900, x);
Easiest way is to wrap it in an anonymous function:
$(this).fadeOut(900, function() { swapFont(id) });
Edit:
The fadeIn will also execute before the fadeOut has completed. You can add a .delay or, better, call the fadeIn in the callback as per Rory's answer (so I won't repeat here).
I populate many parts of my website using
$("#theDivToPopulate").load("/some/api/call.php", callBackToBindClickEventsToNewDiv);
Where /some/api/call.php returns a built list, div, or some other HTML structure to place directly into my target div. The internet has been running slow lately and I've noticed that the time between a button click (which kicks off these API calls) and the div populating is several seconds. Is there an easy way to globally wrap all the load calls so that a div containing "Loading..." is displayed before the call is even made and hidden once the API call is complete.
I can not simply put the code to hide the div into the callBackToBindClickEventsToNewDiv as some load events have different call backs. I would have to copy the code into each function which is ugly and defeats the purpose. I want the flow of any .load to go as follows:
1) dispplayLoadingDiv()
2) Execute API call
3) Hide loading div
4) do callback function.
The loading div must be hidden first as the callback contains some animations to bring the newly loaded div in nicely.
EDIT:
Expanding on jacktheripper's answer:
var ajaxFlag;
$(document).ajaxStart(function(){
ajaxFlag = true;
setTimeout(function (e) {
if(ajaxFlag) {
hideAllDivs();
enableDivs(['loading']);
}
}, 500);
}).ajaxStop(function(){
ajaxFlag = false;
var load = $("#loading");
load.css('visibility','hidden');
load.css('display','none');
load.data('isOn',false);
});
This way loading is only displayed if the page takes more than 500 MS to load. I found the loading flying in and out real fast made things kind of choppy for fast page loads.
Use the following jQuery:
$(document).ajaxStart(function(){
$('#loader').show();
}).ajaxStop(function(){
$('#loader').hide();
});
Where you have an element called #loader that contains what you want to show when an AJAX request is being performed. It could be a span with text, an image (eg a gif), or anything similar. The element should be initially set to display: none
You do not even need to call the function anywhere else.
Try this
$("#someButtonId").click(function(e){
e.preventDefault();
$("#theDivToPopulate").html("Loading...");
$.get("/some/api/call.php",function(data){
$("#theDivToPopulate").fadeOut(100,function(){
$("#theDivToPopulate").html(data).fadeIn(100,function(){
//Do your last call back after showing the content
});
});
});
});
I have probably a simple problem to solve but I don't know what's the right approach on that.
I have a div.notification bar on top of my website that is hidden by default. The bar does get an additional class of either success or warning that sets it to display:block; if needed.
So, there are two cases. Either an output message is rendered directly to the .notification bar on page-load (and it gets a class of success or warning right with it) OR the .notifcation bar is sliding down from top and is fed with json data.
Any way, the notification bar should always be visible for 10 seconds and than slide back up.
Therefore I wrote two functions that handle this bar.
var timing = 10000;
function notificationOutput(type, message) {
var note = $('.notification');
note.hide();
note.find('.message').html(message);
note.stop(true,true).slideDown().delay(timing).slideUp();
}
function notificationSlideUp(slideUp) {
var note = $('.notification');
if ( slideUp ) note.delay(timing).slideUp();
else note.stop(true,true).slideUp();
}
So the notificationOutput() function is triggered from various other functions that return json data and render that into the box.
And the notificationSlideUp() function is right now called on every page load because in my header I have this …
<script type="text/javascript">
$(document).ready(function(){
notificationSlideUp(true);
});
</script>
And there is a reason for that! Remember the case where the .notification is directly set to visible on page-load … e.g. when a user logs-in on my platform the .notification bar is immediately visibile and says "Welcome Username, you've successfully logged in".
I call the notifictaionSlideUp() function in my header to make sure the currently visible .notification bar will slideUp() again after 10 seconds.
And here occurs the problem …
Somehow this causes the entire notifcation timing and sliding up and down to be "confused". So there must happen some queuing of the slide-functions and or of the delay() function, because without the note.stop(true,true) in the notificationOutput() function the notification wouldn't slideDown() immediately if it's triggered within the first 10 seconds after the page load. That is because the notificationSlideUp() function has already triggered the slideUp() and the delay() of the object.
And the same happens to the delay. If a .notification is put out within the first 10 seconds the delay timing isn't right because the delay counter already started on page-load.
Any idea how to solve that so that it always works?
Update:
var notificationTimer;
function notificationOutput(type, message) {
var note = $('.notification');
note.hide();
note.find('.message').html(message);
note.stop(true,true).slideDown();
clearTimeout(notificationTimer);
notificationTimer = setTimeout(function() {
note.stop(true,true).slideUp();
}, 10000);
}
function notificationSlideUp(slideUp) {
var note = $('.notification');
if ( slideUp ) {
clearTimeout(notificationTimer);
notificationTimer = setTimeout(function() {
note.stop(true,true).slideUp();
}, 10000);
} else {
note.stop(true,true).slideUp();
}
}
Unfortunately, jQuery's delay() function doesn't offer any method for canceling a delay the way setTimeout() does with clearTimeout(). I'd suggest replacing your delay()s with named setTimeout()s, and writing a condition to clearTimeout() for cases in which you need to cancel/trigger a queued animation right away.
http://api.jquery.com/delay/
The .delay() method is best for delaying between queued jQuery
effects. Because it is limited—it doesn't, for example, offer a way to
cancel the delay—.delay() is not a replacement for JavaScript's native
setTimeout function, which may be more appropriate for certain use
cases.
But you can use the following 'hint' - replace delay with some animation which does not change anything. For example with .animate({opacity:1},timing)
I am running a bit of code once the page load so in the footer i have got:
$(function(){
//code to run on page load
});
But then i need to stop that code to run on a
.click()
I was thinking of having a custom function which runs on page load and then be able to disabale that function on a click.
How to create a custom function which i can turn it off on a click?
A simple way would be to add a flag/preference variable to your page, which dictates which logic can be executed and when.
Whenever code is then executed, just check the preference, i.e.
function myfunction () {
....
if (code_may_run) {
....
code_may_run = false;
}
....
}
I am trying to hide a result div. Modify it. Then Show it with animation.
I have the following:
$("#SearchButton").button().click(function() {
$("#resultContainer").hide();
$("#resultContainer").empty();
searchResults();
$("#resultContainer").show("slow");
});
Where searchResults() makes an ajax call to load some stuff into the div #resultContainer
However, even if I comment out the line //searchResults(); I still end up with a blank div when I click the button.
However if I switch $("#resultContainer").show("slow"); to $("#resultContainer").show(); It works fine. But I want the animation. .show("slow") works fine elsewhere...
Update: I now have:
$("#SearchButton").button().click(function() {
$("#resultContainer").hide(0);
searchResults();
});
And searchResults does the ajax call with the following callback:
//appending something to the div here
$("#resultContainer").show(600);
alert("test");
I get the alert but the div never shows back up...
You code can be improved, try this:
$(function() {
var $resultContainer = $("#resultContainer");
$("#SearchButton").click(function() {
$resultContainer.hide();
//$resultContainer.empty(); // BTW, no need to empty since the ajax will replace its content anyway!
searchResults();
});
function searchResults() {
$.ajax({
url: "yourRequest.php",
success: function(resp) {
$resultContainer.html(resp);
$resultContainer.show("slow");
}
});
}
});
You don't need the empty the container since it's content will be replaced in the ajax call anyway and it's already hidden anyway!
Remove your show method to the ajax success callback
store the container in a var $resultContainer and use it for faster access.
And here's a live example.
Your code showing the resulting div:
$("#resultContainer").show("slow");
should be chained in the callback of the ajax call; that's the only way you can be sure it will get executed after the ajax result is there. See the optionnal function callback at the end of the load() function. or the callbacks in the ajax functions of jQuery.
You could use something like a jquery queue to queue your events and get that queue paused. Then un-pause the queue in your ajax callback.
Or define some named functions and test that theses callbacks exists before calling them in the ajax callback.
Last thing, please store your selector results var $foo=$("#resultContainer") and use $foo variable after that and avoid calling the $() selector each time you need that div. This can speed up a lot your code.