Delay fadeIn() in a for-loop - javascript

I created a menu with Jquery FadeIn animation, i want to open the menu when my mouse is hover but i also want to fadein the previous tab content.
This should works like this :
My mouse is one the third tab, the first tab popin, then the second one, then the third with a little delay between each animation.
I tried to do this with Jquery :
$('.navigation li').hover(
// When mouse enters the .navigation element
function () {
var tab = $(this).attr('id');
var numTab = tab.substring(2);
//Fade in the navigation submenu
for ( var i = 0; i <= numTab ; i++ ) {
var domElt = '#Et' + i + ' ul';
$(domElt).fadeIn(300); // fadeIn will show the sub cat menu
console.log(domElt);
}
},
// When mouse leaves the .navigation element
function () {
var tab = $(this).attr('id');
var numTab = tab.substring(2);
//Fade out the navigation submenu
for ( var i = 0; i <= numTab ; i++ ) {
var domElt = '#Et' + i + ' ul';
$(domElt).fadeOut(); // fadeIn will show the sub cat menu
}
}
);
As you see on the live version of it, it don't really works, all the tabs are fadein together, or seems to. How can i add a delay to get the "one-after-one fadein effect"?

Add dynamic delay like this -
$(domElt).delay(i*100).fadeOut();
Demo ---> http://jsfiddle.net/abJkD/2/

You can chain the fades:
function () {
var tab = this.id;
var numTab = +(tab.substring(2));
//Fade in the navigation submenu
var i = 0;
function doFade() {
if (i === numTab) return;
// In the fiddle provided, the element id values
// start at 1, not zero
var domElt = '#Et' + (i + 1) + ' ul';
i = i + 1;
$(domElt).fadeIn(300, doFade);
}
doFade();
},
(and similarly for the fade out)

Related

How to auto scroll rotate using J query

the figures should auto rotate. after completing one cycle, it should start from the previous cycle
$(function() {
var interval = setInterval(function() {
if ($("#div1").scrollTop() != $('#div1')[0].scrollHeight) {
$("#div1").scrollTop($("#div1").scrollTop() + 10);
} else {
clearInterval(interval);
}
}, 1000);
});
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div id="div1" style="height:60px;width:100%;border:1px solid #ccc;overflow:auto">>
/array to store IDs of our tabs
var tabs = [];
//index for array
var ind = 0;
//store setInterval reference
var inter;
//change tab and highlight current tab title
function change(stringref){
//hide the other tabs
jQuery('.tab:not(#' + stringref + ')').hide();
//show proper tab, catch IE6 bug
if (jQuery.browser.msie && jQuery.browser.version.substr(0,3) == "6.0")
jQuery('.tab#' + stringref).show();
else
jQuery('.tab#' + stringref).fadeIn();
//clear highlight from previous tab title
jQuery('.htabs a:not(#' + stringref + 't)').removeClass('active');
//highlight currenttab title
jQuery('.htabs a[href=#' + stringref + ']').addClass('active');
}
function next(){
//call change to display next tab
change(tabs[ind++]);
//if it's the last tab, clear the index
if(ind >= tabs.length)
ind = 0;
}
jQuery(document).ready(function(){
//store all tabs in array
jQuery(".tab").map(function(){
tabs[ind++] = jQuery(this).attr("id");
})
//set index to next element to fade
ind = 1;
//initialize tabs, display the current tab
jQuery(".tab:not(:first)").hide();
jQuery(".tab:first").show();
//highlight the current tab title
jQuery('#' + tabs[0] + 't').addClass('active');
//handler for clicking on tabs
jQuery(".htabs a").click(function(){
//if tab is clicked, stop rotating
clearInterval(inter);
//store reference to clicked tab
stringref = jQuery(this).attr("href").split('#')[1];
//display referenced tab
change(stringref);
return false;
});
//start rotating tabs
inter = setInterval("next()", 7500);
});

jQuery: How to properly pause a recursion?

I know there are a lot of questions on the topic, but it seems none of the answers works for me (or maybe I don't see something obvious). I am building a featured content slider that should pause on hover. However, if I move over with the mouse 5-6 times, it goes through the loop 5-6 times at once and it becomes buggy. The previous recursion doesn't stop and a new one is initiated too.
My function:
gravityFeatured.prototype.loop = function(slide) {
// Begin
var self = this;
if(typeof slide == 'undefined') {
slide = 0;
}
self.slidesWrapper.find('.slide-wrapper').removeClass('current next prev');
self.navigation.find('.navigation-item').removeClass('current');
// Current slide
currentSlide = self.slidesWrapper.find('.slide-wrapper[data-slide="' + slide + '"]');
currentNav = self.navigation.find('.navigation-item[data-slide="' + slide + '"]');
// Next slide
var nextSlide = self.slidesWrapper.find('.slide-wrapper[data-slide="' + (slide + 1) + '"]');
var next = slide+1;
if(!nextSlide.length) {
nextSlide = self.slidesWrapper.find('.slide-wrapper[data-slide="0"]');
next = 0;
}
// Prev slide
var prevSlide = self.slidesWrapper.find('.slide-wrapper[data-slide="' + (slide - 1) + '"]');
if(!prevSlide.length) {
prevSlide = self.slidesWrapper.find('.slide-wrapper[data-slide="' + (self.slides.length - 1) + '"]');
}
// Assign classes
currentSlide.addClass('current');
currentNav.addClass('current');
nextSlide.addClass('next');
prevSlide.addClass('prev');
self.scrollNavigation(slide);
// Loop
var timeout = setTimeout(function(){
self.loop(next);
}, self.options['delay']);
self.slidesWrapper.hover(function(){
clearTimeout(timeout);
}, function(){
timeout = setTimeout(function(){self.loop(next);});
});
}
So with the current setup every time you mouseout you trigger a move. Thus in and out 5 times is going to trigger 5 moves. Perhaps better behavious is to pause the countdown while the mouse is in the hovering. This would look something like:
gravityFeatured.countdown = null,
gravityFeatured.isPaused = false,
gravityFeatured.prototype.loop = function(slide) {
...
self.scrollNavigation(slide);
self.countdown = self.options['delay'] * 1000;
var timeout = null; /* need this in loopCheck */
var loopCheck = function() {
if (!this.isPaused)
this.countdown -= 500;
if (this.countdown <= 0)
this.loop(next);
else
timeout = setTimeout(loopCheck,500); /* check every half sec */
}
timeout = setTimeout(loopCheck,500);
self.slidesWrapper.hover(function(){
self.isPaused = true
}, function(){
self.isPaused = false;
});
}
A half second timeout might be a little long, could probably go down to 250ms if necessary. Should handle lots of mouse movement okay though.

Custom Lazy Load - IE9 Memory Leak

I'm currently developing a basic image gallery that dynamically loads new images in the following order (on document.ready):
Uses an ajax call to get JSON which contains all the information needed to dynamically render images.
Iterates over the JSON object to create proper divs/img elements which are then appended to the page.
$.ajax({
url: '/wp-content/themes/base/library/ajax/posts-json.php',
type: 'get',
//dataType: 'json',
success: function(data) {
// turn string response to JSON array
window.responseArray = JSON.parse(data);
window.lastPhotoIndex = 0;
// make sure there is a response
if (responseArray.length > 0) {
// get container
var container = document.getElementById("photos-container");
var ulElement = document.createElement('ul');
ulElement.className = "rig columns-3";
ulElement.setAttribute("id", "photo-list");
// iterate over each response
window.photoCount = 0;
for (var i = 0; i < responseArray.length; i += 1) {
// Only load first 10 images
if (responseArray[i]["post-type"] == "photo" && photoCount < 20) {
// Set the last photo index to this photo
lastPhotoIndex = i;
// create the li
var liElement = document.createElement("li");
liElement.className = liElement.className + responseArray[i]["day"];
//create class name string from WP tags
if (responseArray[i].tags.length > 0) {
for (var ii = 0; ii < responseArray[i].tags.length; ii += 1) {
nospaceTagName = responseArray[i].tags[ii].split(' ').join('');
liElement.className += " " + nospaceTagName;
}
}
//create image element and append to div
var imgTag = document.createElement("img");
imgTag.src = responseArray[i]["thumb-url"];
liElement.appendChild(imgTag);
//Add modal class info to outer div
liElement.className += " md-trigger";
//Add data-modal attribute to outer div
liElement.setAttribute("data-modal", "photo-modal");
ulElement.appendChild(liElement);
//next slide
photoCount++;
}
}
//append ul to container
container.appendChild(ulElement);
}
},
error: function(xhr, desc, err) {
console.log(xhr);
console.log("Details: " + desc + "\nError:" + err);
}
});// end ajax call
After the ajax call, I add a window scroll event that will be called while there are still more photos in the JSON object.
// Window scroll event
$(window).scroll(function () {
var trigger = $(document).height() - 300;
if (trigger <= $(window).scrollTop() + $(window).height()) {
//Call function to load next 10
loadNextPhotos();
}
});
The function called by the scroll even simply starts off at the previously left off index (lastPhotoIndex variable set at the beginning of ajax call - 'window.lastPhotoIndex'). The function looks like this:
function loadNextPhotos() {
if (photoCount < getPhotoCount()) {
var photosOutput = 0;
var startingIndex = lastPhotoIndex + 1;
var photoList = $('#photo-list');
for (var i = startingIndex; i < responseArray.length; i += 1) {
if (responseArray[i]["post-type"] == "photo" && photosOutput < 10) {
lastPhotoIndex = i;
photosOutput++;
// create the li needed
var element = document.createElement("li");
element.className = responseArray[i]["day"];
//create class name string from tags
if (responseArray[i].tags.length > 0) {
for (var ii = 0; ii < responseArray[i].tags.length; ii += 1) {
nospaceTagName = responseArray[i].tags[ii].split(' ').join('');
element.className = element.className + " " + nospaceTagName;
}
}
//create image element and append to li
var imgTag = document.createElement("img");
imgTag.src = responseArray[i]["thumb-url"];
element.appendChild(imgTag);
//Add modal class info to li
element.className = element.className + " md-trigger";
//Add data-modal attribute to outer div
element.setAttribute("data-modal", "photo-modal");
photoList.append(element);
// Keep track of photo numbers so modal works for appropriate slide number
photoCount++;
}
}
}
}
Bear in mind, this code is stripped down a lot from the full application. It works fine in Chrome, Safari, Firefox, IE10+.
When loaded in IE9, I'm experiencing crazy memory leaks as I hit the scroll event and append more items to the UL.
My guess is that I'm not following best practices when creating new items to be appended and they're staying in memory longer than they should. The only issue is I'm not sure how to solve it/debug it because the page crashes so quickly in IE9.
Any help would be awesome. Thanks!
EDIT:
I've tried implementing Darmesh's solution with no real luck. As I said in his comment it only delays the rate at which memory is leaked. I've also added jquery.visible.js on top of a scroll event so it looks like this:
$(window).scroll(function () {
if($('#lazy-load-trigger').visible() && window.isLoadingPhotos != true) {
console.log("VISIBLE!");
loadNextPhotos();
}
});
But it also only delays the memory leak. I still believe there are issues with Garbage Collection in IE9, but am not sure how to troubleshoot.
I think this is due to the browser calling loadNextPhotos function multiple times at the same time every time you scroll. This might work, give it a try,
function loadNextPhotos() {
// Add flag to indicate new photos adding started
window.isLoadingPhotos = true;
....
....
....
....
// Indicate new photos adding completed
window.isLoadingPhotos = false;
}
And,
$(window).scroll(function () {
var trigger = $(document).height() - 300;
if (trigger <= $(window).scrollTop() + $(window).height()) {
if(!window.isLoadingPhotos) {
//Call function to load next 10
loadNextPhotos();
}
}
});

how to use Javascript for slide left

i have use the javascript for sliding the element up and down as fallow
<script type="text/javascript">
$(function () {
var $divSlide = $("div.slide");
$divSlide.hide().eq(0).show();
var panelCnt = $divSlide.length;
setInterval(panelSlider, 3000);
function panelSlider() {
$divSlide.eq(($divSlide.length++) % panelCnt)
.slideUp("slow", function () {
$divSlide.eq(($divSlide.length) % panelCnt)
.slideDown("slow");
});
}
});
</script>
which slide the panel up and down having slide tag panals are added as fallow
//protion
DataTable promo = SQl.ExecuteSelectCommand("select Promo_Code,Promo_Discription,Promo_Min_Ammount,Persent_Off,Start_Date,End_Date,Supp_Name from Prommosion_Details_View ");
if (promo.Rows.Count > 0)
{
for (int i = 0; i <= promo.Rows.Count - 1; i++)
{
Panel p = new Panel();
p.CssClass = "slide";
PromoUC PUC = (PromoUC)Page.LoadControl("PromoUC.ascx");
PUC.setText(promo.Rows[i][3].ToString(), promo.Rows[i][1].ToString(), promo.Rows[i][4].ToString(), promo.Rows[i][5].ToString(), promo.Rows[i][0].ToString(), " From " + promo.Rows[i]["Supp_Name"].ToString());
p.Controls.Add(PUC);
searchBoxPromoPlaceHolder.Controls.Add(p);
}
}
above code is working fine but the problem is tat i have to scroll it left and right with elastic effect
You should check the jQuery.animate() which helps you to do any animation effect.
you can animate any css property,in your case the width could fit your needs.check the examples online.

replacing images inplace

I have a array of static images that I am using for an animation.
I have one frame image that I want to update the image of and I have seen a lot of tutorials on animating images with javascript just simply update the source of an image.
frame.src = animation[2].src; etc
When I look at the resource tracking in chrome, it doesnt look like they are getting cached even thought the web browser does download the image more than once but not once for each time it is displayed, so there is still some browser caching going on.
What is the best way to replace the frame image object with another image?
Well, you can either position all images absolute and give them a z-index, then use jQuery/JS to shuffle their z-indexes, bringing a new one to the top in a cross fader style,
or you can take all the id's and fadeone in slightly faster than the last one fades out.
Like so:
function fader(func) {
var currID = $('#mainimg ul').data('currLI');
var currLiStr = '#mainimg ul li#' + currID;
img = $(currLiStr).find('img').attr('src');
nextID = (currID == 'six') ? 'one' : $(currLiStr).next().attr('id');
nextLiStr = $('#mainimg ul li#' + nextID);
$(currLiStr).fadeOut(3000);
$(nextLiStr).fadeIn(2000).find('div.inner').delay(3000).fadeIn('slow').delay(6000).fadeOut('slow');
$('#mainimg ul').data('currLI',nextID);
}
Note 'six' is the id of the last li, reseting it back to one, but if you do $('#mainimg ul li:last').attr('id'); and $('#mainimg ul li:first').attr('id') to get the last and first id's, you can allow it to cope with any amount of images (obviously this is with li's given id's one, two and so on, but if you are finding out the last and first id you could use any structure.
Or you can set a ul width a width of all the li's multiplied, and give the li's the width of the images, and set overflow to hidden, then use JS to pull the li's left by the width of 1 li on each iteration in a slider like I have done here: http://www.reclaimedfloorboards.com/
There are loads of options
I ended up using jquery's replaceWith command and gave all the frames a class "frame" that i could select with $('.frame') which happened to only select visible frames.
<script type="text/javascript">
var animation = [];
var firstFrame = 1;
var lastFrame = 96;
var animationFrames = 16;
var loadedImageCount = 0;
$(function() {
$("button, input:submit",'#forecastForm').button();
$("#progressbar").progressbar({
value: 0
});
$('#id_Species').attr('onChange', 'loadAnimation($(\'#id_Species\').val(),$(\'#id_Layer\').val(),$(\'#id_StartTime\').val(),$(\'#id_EndTime\').val())' )
$('#id_Layer').attr('onChange', 'loadAnimation($(\'#id_Species\').val(),$(\'#id_Layer\').val(),$(\'#id_StartTime\').val(),$(\'#id_EndTime\').val())' )
$('#id_StartTime').attr('onChange', 'loadAnimation($(\'#id_Species\').val(),$(\'#id_Layer\').val(),$(\'#id_StartTime\').val(),$(\'#id_EndTime\').val())' )
$('#id_EndTime').attr('onChange', 'loadAnimation($(\'#id_Species\').val(),$(\'#id_Layer\').val(),$(\'#id_StartTime\').val(),$(\'#id_EndTime\').val())' )
});
if (document.images) { // Preloaded images
loadAnimation('Dry_GEM',1,1,96);
}
function rotate(animation, frame)
{
if (frame >= animation.length)
frame = 0;
$('.frame').replaceWith(animation[frame]);
window.setTimeout('rotate(animation,'+eval(frame+1)+')',150);
}
function loadAnimation(species, layer, startTime, endTime)
{
layer = Number(layer);
startTime = Number(startTime);
endTime = Number(endTime);
if (startTime > endTime)
{
swap = startTime;
startTime = endTime;
endTime = swap;
delete swap;
}
for (i=0;i<animation.length;i++)
delete animation[i];
delete animation;
animation = []
$('#progressbar').progressbar({value: 0});
loadedImgCount = 0;
animationFrames = endTime - startTime + 1;
for(i=0;i < animationFrames;i++)
{
animation[i] = new Image();
animation[i].height = 585;
animation[i].width = 780;
$(animation[i]).attr('class','frame');
animation[i].onload = function()
{
loadedImgCount += 1;
$('#progressbar').progressbar({value: eval(loadedImgCount / animationFrames * 100)});
};
animation[i].src = 'http://[[url]]/hemi_2d/' + species + '_' + layer + '_' + eval(i+startTime) + '.png';
}
}
</script>
The easiest way to do it is create a separate hidden image for each frame. Something like this:
var nextImage = (function(){
var imagePaths='basn0g01.png,basn0g02.png,basn0g04.png,basn0g08.png'.split(','),
imageHolder=document.getElementById('custom-header'),
i=imagePaths.length, imageIndex=i-1, img;
for (;i--;) {
img=document.createElement('img');
img.src='http://www.schaik.com/pngsuite/' + imagePaths[i];
if (i) img.style.display='none';
imageHolder.appendChild(img);
}
return function(){
imageHolder.childNodes[imageIndex].style.display='none';
if (++imageIndex >= imageHolder.childNodes.length) imageIndex=0;
imageHolder.childNodes[imageIndex].style.display='inline-block';
}
}());
Try this example on this page; paste it in the console and then call nextImage() a few times. Watch the top of the page.
edit
If you already have all the images in your HTML document, you can skip most of the above and just do something like this:
var nextImage = (function(){
var imageHolder=document.getElementById('custom-header'),
images=imageHolder.getElementsByTagName('img'),
i=images.length, imageIndex=0, img;
for (;i--;) if (i) images[0].style.display='none';
return function(){
imageHolder.childNodes[imageIndex].style.display='none';
if (++imageIndex >= imageHolder.childNodes.length) imageIndex=0;
imageHolder.childNodes[imageIndex].style.display='inline-block';
}
}());

Categories

Resources