Let me preface this by saying I have addressed this thread trying to resolve my issue, but to no avail:
Fade in each element - one after another
I thought it would work quite handily if the elements weren't dynamic content, but I made a test div and filled it with thumbnails, and a button to click and assigned similar code, but it still just flat out removed all of the elements without animation or hesitation.
Right now, what I have looks like this:
function OnThumbSuccess(response) {
var $thumbs = $('#Gallery .thumbWindow .thumbReel');
var files = $.parseJSON(response.d);
$thumbs.children().each(function (i) {
$(this).delay(i*300).animate({ 'opacity': '0' }, 500, 'easeOutSine');
$(this).remove();
})
//make sure the thumb reel resets to its original position
$thumbs.css('left', '0px');
//loop through the array of json objects
for (var i = 0; i < files.length; i++) {
//images[i] = files[i].fileHREF;
InsertHTML(files[i].thumbHref, i);
}
}
So, it's supposed to fade that element out, then remove it. It has no problem removing it; it's the animating it that it seems to fail on.
After some tinkering around, I have discovered that I CAN indeed animate them however I please, provided I get rid of $(this).remove(). That would be fine, if I didn't need to get rid of those elements.
It doesn't seem to matter what I do. I've tried chaining the .remove() to the end of the animate function, I've tried setting a delay equal to the number of elements before emptying the div. I've tried moving the code to populate the thumbnails div from the OnThumbSuccess function to the ajax.done() function.
I'm really at a loss as to how I can do this elegantly. Please let me know what, if any other details I can provide.
I made this test fiddle, maybe this will be of some help: http://jsfiddle.net/kum8d7k9/
Well, in the process of writing this question, I have come up with the following solution, which seems to work quite well:
function GetThumbnails(category) {
$.ajax({
type: "POST",
url: "Filenames.asmx/GetFiles",
contentType: "application/json; charset=utf-8",
data: '{ "folderName" : "' + category + '"}',
dataType: "json",
success: OnThumbSuccess,
failure: function (response) {
alert('failure');
}
}).done(function (response) {
//alert(response.d);
var files = $.parseJSON(response.d);
var $thumbs = $('#Gallery .thumbWindow .thumbReel');
if ($thumbs.children().length > 0) {
setTimeout(function () {
$thumbs.empty();
//loop through the array of json objects
for (var i = 0; i < files.length; i++) {
//images[i] = files[i].fileHREF;
InsertHTML(files[i].thumbHref, i);
}
}, $thumbs.children().length * 300);
}
else {
//loop through the array of json objects
for (var i = 0; i < files.length; i++) {
//images[i] = files[i].fileHREF;
InsertHTML(files[i].thumbHref, i);
}
}
}).fail(function (response) {
alert(response.responseText);
});
}
function OnThumbSuccess(response) {
var $thumbs = $('#Gallery .thumbWindow .thumbReel');
$thumbs.children().each(function (i) {
$(this).delay(i*200).animate({ 'opacity': '0'}, 200, 'easeOutSine');
})
//make sure the thumb reel resets to its original position
$thumbs.css('left', '0px');
}
I have moved the .empty() function to the $.ajax.done() function and set a timeout on it equal to the number of child elements I have to fade multiplied by the animation duration with a little wiggle room.
Next I'll have to conjure up a way to transition those elements in as well. This has been most educational, but if someone has a better solution in mind, I'm all ears.
You don't want to call .remove() until after the animation completes so you will need to use the complete callback function of jQuery animate, http://api.jquery.com/animate/.
$(this).delay(i*300).animate({ 'opacity': '0' }, 500, 'easeOutSine',
function() {
$(this).remove();
}
);
The chaining did not work as the animate function returns immediately rather than after the animation is complete.
$('#remove_me').animate({
opacity: 0
}, 500, function() {
$(this).remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="remove_me">testing remove</div>
Related
I have an tag that is having its contents changed via jquery and then faded in and out (using the velocity js library) utilizing the setInterval function. When I run this it tends to work fine for about 30 seconds before it starts to malfunction and jquery starts to change the contents of the tag before the tag has faded out.
Here is the Javascript code
let counter = 0;
function chooseWord() {
let words = ["foo", "bar", "foo"];
if (counter !== 2) {
counter += 1;
} else {
counter = 0;
}
return words[counter];
}
function refreshText() {
$("#div").text("Foo " + chooseWord())
.velocity("fadeIn", {
duration: 2500
})
.velocity("fadeOut", {
delay: 1500,
duration: 2500
});
}
$(document).ready(function() {
refreshText();
setInterval(function() {
refreshText();
}, 7000);
});
And here is my tag that is being used
<h1 class="foobar" id="div"></h1>
I've tried using Jquery's timer and I have the same issue. Does anyone know what the problem might be or maybe a different way of achieving what I want to do?
You just need to change the order of operations. I have moved the text-change command after fade-out. So the element fades out, and then jQuery will update its text.
$("#div")
.velocity("fadeIn", {
duration: 2500
})
.velocity("fadeOut", {
delay: 1500,
duration: 2500
})
.text("Foo " + chooseWord());
Fiddle: https://jsfiddle.net/Nisarg0/gLed0h1y/
I have checked all the possible questions that could be related to this but I cant seem to find anything that suits my case, either the answers were not good or incomplete.
In my case I have a html page with some php, displaying competition results. As the competition is live the page with results should scroll to the bottom of the page and then the page should refresh (so the possible new scores come in) and then repeat again and again. What would be the best solution for my problem?
The page size/length would increase as more data will come in the tables which are on results page.
Image:
EDIT:
This code now scrolls to the bottom of the page and then jump back to top and repeat and its exactly what I want, but I would like a page to refresh every time I hit the bottom and after this go to the top.
$(function() {
var pageScan = {
speed : 10000,
loop : true,
delayRestart : 1000,
start : function(){
pageHeight = $('body').height() - window.innerHeight;
pageScan.proc(pageHeight);
},
proc : function(to){
$("body").animate(
{scrollTop: to},
pageScan.speed,
"linear",
function(){
if (pageScan.loop) {
setTimeout(function() {
window.scrollTo(0, 0);
pageScan.start();
}, pageScan.delayRestart);
}
});
}
};
pageScan.start();
});
You can add some JavaScript to your page:
<script>
window.scrollTo(0,document.body.scrollHeight);
setTimeout(function (){location.reload()},5000);
</script>
This might be what you are looking for:
// Test data, ignore
for(i = 1; i < 21; i++) {
$('#results').append('<p>Test Result No.' + i + '</p>');
}
// Check every second (for example) if there is new data
// In this example there is always data
window.setInterval(function(){
update_results();
}, 1000);
// Check for new results
function update_results() {
$.ajax({
type: 'POST',
// Test data, ignore
data: {
html: 'new result'
},
// your ajax.php file
url: '/echo/html/',
success: function(data) {
// Append new results to $('#results');
// You might want to give back an array and loop through it with $.each(data, function() {});
// you might also want to check for "false" if there are no new results
$('#results').append('<p>' + data + '</p>');
// Scroll to bottom smoothly
$('html, body').animate({ scrollTop: $(document).height() }, 'slow');
}
});
}
jsfiddle
In your ajax.php-File you can echo the new scores:
echo json_encode($scores);
Given that $scores is an array of your scores which you probably have from your database.
I'm trying to adjust a script I found on another stackoverflow question. Basically I want to be able to get the data attribute which is the count number and count from zero up to that number for each instance of that div.
Basically I'm trying to loop through each div element and make a variable of the data-attribute and then perform the count animation on that respective element.
My HTML:
<div class="count_item" data-count="5000">0</div>
<div class="count_item" data-count="444">0</div>
<div class="count_item" data-count="6666">0</div>
My jQuery:
$(".count_item").each(function(i) {
var count_val = $(this).data('count');
$("body").append(count_val);
console.log(count_val);
$({countNum: $(i).text()}).animate({countNum: count_val}, {
duration: 8000,
easing:'linear',
step: function() {
$(i).text(Math.floor(this.countNum));
},
complete: function() {
$(i).text(this.countNum);
alert('finished');
}
});
});
I can't workout why if you look at the console it's getting two of the values and then it errors before the third. Help appreciated.
Working example: http://jsbin.com/yenunijemo/2/
The issue is that i is not what you expect it to be (it is index of each .count_item in the selection array, but not the element in itself). An easy way to fix that would be to define a variable (e.g.: $this) that will contain the element that you are working with, and replace i with that variable.
If you try the following code, it will work fine:
$(".count_item").each(function(i) {
var count_val = $(this).data('count');
var $this = $(this);
$("body").append(count_val);
console.log(count_val);
$({countNum: $this.text()}).animate({countNum: count_val}, {
duration: 8000,
easing:'linear',
step: function() {
$this.text(Math.floor(this.countNum));
},
complete: function() {
$this.text(this.countNum);
alert('finished');
}
});
});
You can see it working on this JSFiddle: http://jsfiddle.net/nqn09dd0/1/
I have a function that hides and shows divs on scroll based on pageY position, but I also need the ability to have it automatically hide and show divs in order(only the ones with children), sort of like a fake animated Gif, looping forever.
I tried this:
function autoPlay() {
$('.conP').each(function(){
if ($(this).children().length > 0) {
setInterval(function(){
$(this).show().delay('100').hide();
},300);
}
});
}
which is not returning any errors, but it's not hiding or showing any of the divs with class="conP".
Any suggestions as to what I'm doing wrong/how I could improve this?
try this -
function autoPlay() {
$('.conP').each(function(){
if ($(this).children().length > 0) {
var $that = $(this);
setInterval(function(){
$that.show().delay('100').hide();
},300);
}
});
}
You have an incorrect reference to this in your setInterval closure. Refer to "How this works" in JavaScript Garden.
In your case you should save the reference to this in a variable:
$('.conP').each(function() {
var $element = $(this);
setInterval(function () {
$(element).show().delay('100').hide();
}, 300);
});
Or, better use the first argument passed to each, which is equal to $(this) in this case.
Not sure it's a great idea to run intervals inside loops, but I'm guessing the issue is scope inside the interval function :
function autoPlay() {
$('.conP').each(function(i, elem){
if ( $(elem).children().length ) {
setInterval(function(){
$(elem).show().delay(100).hide();
},300);
}
});
}
I really appreciate all the help guys, I seem to have figured out the animation part:
setInterval( function() {
autoPlay();
},120);
function autoPlay() {
var backImg = $('#outterLax div:first');
backImg.hide();
backImg.remove();
$('#outterLax').append(backImg);
backImg.show();
}
By hiding whichever div is first, and removing it from-then appending it back into-the containing div, and showing the new first div, it animates quite nicely!
I have this code which animates between divs sliding out. If an item is clicked, it's relevant content slides out. If another item is clicked, the current content slides back in and the new content slides out.
However,
var lastClicked = null;
var animateClasses = ['ale', 'bramling', 'bullet', 'miami-weisse'];
for (var i=0; i<animateClasses.length; i++) {
(function(animCls) {
$('.each-brew.'+animCls).toggle(function() {
if (lastClicked && lastClicked != this) {
// animate it back
$(lastClicked).trigger('click');
}
lastClicked = this;
$('.each-brew-content.'+animCls).show().animate({ left: '0' }, 1000).css('position','inherit');
}, function() {
$('.each-brew-content.'+animCls)
.animate({ left: '-33.3333%' }, 1000, function() { $(this).hide()}) // hide the element in the animation on-complete callback
.css('position','relative');
});
})(animateClasses[i]); // self calling anonymous function
}
However, the content sliding out once the already open content slides back is sliding out too quickly - it needs to wait until the content has fully slided back in before it slides out. Is this possible?
Here's a link to what I'm currently working on to get an idea (http://goo.gl/s8Tl6).
Cheers in advance,
R
Here's my take on it as a drop-in replacement with no markup changes. You want one of three things to happen when a menu item is clicked:
if the clicked item is currently showing, hide it
if something else is showing, hide it, then show the current item's content
if nothing is showing, show the current item's content
var lastClicked = null;
// here lastClicked points to the currently visible content
var animateClasses = ['ale', 'bramling', 'bullet', 'miami-weisse'];
for (var i=0; i<animateClasses.length; i++) {
(function(animCls) {
$('.each-brew.'+animCls).click(function(event){
if(lastClicked && lastClicked == animCls){
// if the lastClicked is `this` then just hide the content
$('.each-brew-content.'+animCls).animate(
{ left: '-33.3333%' }, 1000,
function() {
$(this).hide();
}).css('position','relative');
lastClicked = null;
}else{
if(lastClicked){
// if something else is lastClicked, hide it,
//then trigger a click on the new target
$('.each-brew-content.'+lastClicked).animate(
{ left: '-33.3333%' }, 1000,
function() {
$(this).hide();
$(event.target).trigger('click');
}).css('position','relative');
lastClicked = null;
}else{
// if there is no currently visible div,
// show our content
$('.each-brew-content.'+animCls).show()
.animate({ left: '0' }, 1000)
.css('position','relative');
lastClicked = animCls;
}
}
});
})(animateClasses[i]); // self calling anonymous function
}
Well, I'm pretty sure there are other more easy possibilities and I didn't have much time but here is a working jsfiddle: http://jsfiddle.net/uaNKz/
Basicly you use the callback function to wait until the animation is complete. In this special case it's the complete: function(){...}
$("document").ready(function(){
$('#ale').click(function(){
if ($('div').hasClass('toggled')){
$('.toggled').animate({ width: "toggle" }, { duration:250, complete: function(){
$('#alecont').animate({ width: "toggle" }, { duration:250 }).addClass('toggled');}
}).removeClass('toggled');
}else{
$('#alecont').animate({ width: "toggle" }, { duration:250 }).addClass('toggled');
}
});
$('#bramling').click(function(){
if ($('div').hasClass('toggled')){
$('.toggled').animate({ width: "toggle" }, { duration:250, complete: function(){
$('#bramcont').animate({ width: "toggle" }, { duration:250 }).addClass('toggled');}
}).removeClass('toggled');
}else{
$('#bramcont').animate({ width: "toggle" }, { duration:250 }).addClass('toggled');
}
});
});
I give a toggled class if a div is expanded. Since the animation on your page seems to be pretty much broken I think this would be a better way to do this. But remember: my code isn't really good. Just fast and it can be refactored. It's working tho..
Rather than using toggles, bind an on "click" handler to your ".each-brew" divs. In the handler, first hide content divs and then show the appropriate content when that animation completes. You can do that with either a promise or a callback. Something like this...
$(".each-brew").on("click", function (event) {
$(".each-brew-content").show().animate({ left: "0" }, 1000, function() {
// Get the brew name from the class list.
// This assumes that the brew is the second class in the list, as in your markup.
var brew = event.currentTarget.className.split(/\s+/)[1];
$(".each-brew-content." + brew).animate({ left: "-33.3333%" }, 1000, function() { $(this).hide(); });
});
});
I think an event and observer would do the trick for you.
set up the callback function on completion of your animation to fire an event.
the listener would first listen for any animation event and after that event is triggered listen for the completion event. when the completion event is fired execute the initial animation event.run method (or whatever you would want to call it)
Within the listener
on newanimationeventtriger(new_anim) wait for x seconds (to eliminate infinite loop poss) while if this lastevent triggers done == true{
new_anim.run();
}