Loading elements one after another - simple jQuery - javascript

I have some JavaScript that loads a stack of separate elements based on their class name. However, I'd like to add a 1second delay on each, so they all appear one after another.
So i1 loads first then a second later i2 loads and so on...
How do I achieve this with my code?
<script>
jQuery(function($){
var i1 = $(".one"),
i2 = $(".two"),
i3 = $(".three");
i4 = $(".four");
i5 = $(".five");
i6 = $(".six");
$('.field').animate( {
marginTop:"0"
},600, function () {
i1.animate({
"opacity": 1
}),
i2.animate({
"opacity": 1
}),
i3.animate({
"opacity": 1
}),
i4.animate({
"opacity": 1
})
i5.animate({
"opacity": 1
}),
i6.animate({
"opacity": 1
}, 500);
});
});
</script>
Many thanks for any help with this :)

You can try this way:-
Html
<div class="one slide">1</div> <!-- give some common class all these-->
<div class="two slide">2</div>
<div class="three slide">3</div>
<div class="four slide">4</div>
<div class="five slide">5</div>
JS
var all = $('.slide').get(); //Get all the element to slide into an array.
function animate() {
var elem = all.shift(); //Remove the top element from the array
//animate it
$(elem).animate({
"opacity": 1
}, function () {
if (all.length > 0)
window.setTimeout(animate, 1000); //set the time out after the delay of 1 sec for next element to animate.
});
}
animate();
Demo

For each element, set animate function inside the callback of animate method of the previous element.
$('.field').animate({
marginTop: "0"
}, 600, function () {
i1.animate({
"opacity": 1
}, function () {
i2.animate({
"opacity": 1
},etc...);

Without leaking variables and having to add a new class, you can loop through the found elements and use setTimeout to delay time until the next. For example:
$(document).ready(function () {
var i1 = $(".one"),
i2 = $(".two"),
i3 = $(".three"),
i4 = $(".four"),
i5 = $(".five"),
i6 = $(".six"),
iterator = function () {
var arr = Array.prototype.slice.call(arguments, 0),
len = arr.length,
iterate = function (index) {
if (index === len) {
return;
}
arr[index].animate({
opacity: 1
}, 600, function () {
setTimeout(function () {
iterate(++index);
}, 1000);
});
};
iterate(0);
};
iterator(i1, i2, i3, i4, i5, i6);
});
DEMO: http://jsfiddle.net/FbGwQ/2/

Try using jQuery .delay(), it allows you to delay the execution of functions that follow it in the queue.
http://api.jquery.com/delay/
UPDATED:
Working jsFiddle Example: http://jsfiddle.net/DylanNunns/su8jp/2/
jQuery(function ($) {
var i1 = $(".one"),
i2 = $(".two"),
i3 = $(".three");
i4 = $(".four");
i5 = $(".five");
i6 = $(".six");
$('.field').animate({
marginTop: "0"
}, 600, function () {
i1.delay(1000).animate({
"opacity": 1
}),
i2.delay(2000).animate({
"opacity": 1
}),
i3.delay(3000).animate({
"opacity": 1
}),
i4.delay(4000).animate({
"opacity": 1
}),
i5.delay(5000).animate({
"opacity": 1
}),
i6.delay(6000).animate({
"opacity": 1
});
});
});

I like to use jQuery's each method along with delay to help out with this because it gives you the index of an element which you can use to set the delay.
jQuery(function () {
var animation_items = [
".one", ".two", ".three", ".four", ".five", ".six"
];
$.each(animation_items, function(index, item) {
$(item).delay(index * 1000).animate({
opacity: 1
}, 500);
});
});
You also get the added bonus of it working with a specific class instead of specifying them all separately. This makes everything more general and easier to maintain. You can simply add another div to your HTML without having to edit the JavaScript.
<div class="fade_in"></div>
<div class="fade_in"></div>
<div class="fade_in"></div>
jQuery(function () {
var delay = 1000;
$('.fade_in').each(function(index, item) {
$(item).delay(index * 1000).animate({
opacity: 1
}, 500);
});
});
Here's a demo

I think I'd rather use a bit of recursion and use the callbacks for a cleaner implementation (in my mind ..)
var oneByOne = function($el) {
$el.fadeIn(600, function() {
if (!$el.next().length == 0)
oneByOne($el.next());
});
};
$first = $('#one-by-one').children().first();
oneByOne($first);
http://jsfiddle.net/mikecmpbll/sbwMx/
Alternatively, still using recursion but working with the array of items instead:
var oneByOne = function(arr) {
$el = $(arr.shift());
$el.fadeIn(600, function() {
if (!$el.next().length == 0)
oneByOne(arr);
});
};
arr = $("#one-by-one").children().get();
oneByOne(arr);
http://jsfiddle.net/mikecmpbll/sbwMx/1/

Related

Update live JavaScript Array while pushing elements to HTML ID

I am facing a slight dilemma as a JavaScript newbie. Let me explain the script:
I have implemented a JavaScript function rss() which pulls from an internet RSS news feed and saves the news headlines into an array newsArray[].
The function headlinesInsert() should push every item in the array to the HTML ID #headlineInsert, similarly to how it is shown here.
However, the linked example's textlist variable (which should be replaced with my local newsArray[]) does not seem to be 'compatible' for some reason as when replacing nothing shows on the HTML side.
The idea is that the rss() function updates the global newsArray[] with new headlines every 10 minutes while the headlinesInsert() pushes this data to the HTML ID constantly (as per the linked example).
With my limited knowledge of JavaScript, I am hoping someone could help me set the following code right and put the idea into action.
// Push RSS Headlines into HTML ID
var newsArray = [];
var listTicker = function headlinesInsert(options) {
var defaults = {
list: [],
startIndex:0,
interval: 8 * 1000,
}
var options = $.extend(defaults, options);
var listTickerInner = function headlinesInsert(index) {
if (options.list.length == 0) return;
if (!index || index < 0 || index > options.list.length) index = 0;
var value = options.list[index];
options.trickerPanel.fadeOut(function headlinesInsert() {
$(this).html(value).fadeIn();
});
var nextIndex = (index + 1) % options.list.length;
setTimeout(function headlinesInsert() {
listTickerInner(nextIndex);
}, options.interval);
};
listTickerInner(options.startIndex);
}
// The following line should hold the values of newsArray[]
var textlist = new Array("News Headline 1", "News Headline 2", "News Headline 3", "News Headline 4");
$(function headlinesInsert() {
listTicker({
list: textlist ,
startIndex:0,
trickerPanel: $('#headlineInsert'),
interval: 8 * 1000,
});
});
$(function slow(){
// Parse News Headlines into array
function rss() {
$.getJSON("https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fwww.stuff.co.nz%2Frss", function(data) {
newsArray = [];
for (var i = 0; i < data.items.length; i++){
newsArray[i] = (data.items[i].title);
}
console.log(newsArray);
})}
// Refresh functions ever 10 minutes
rss()
setInterval(function slow() {
rss();
}, 600000); // 10 Minute refresh time
});
Check following code. You need to initialise listTicker once rss feed is loaded.
<script src='https://code.jquery.com/jquery-3.2.1.min.js'></script>
<script>
var listTicker = function(options) {
var defaults = {
list: [],
startIndex: 0,
interval: 3 * 1000,
}
var options = $.extend(defaults, options);
var listTickerInner = function(index) {
if (options.list.length == 0) return;
if (!index || index < 0 || index > options.list.length) index = 0;
var value = options.list[index];
options.trickerPanel.fadeOut(function() {
$(this).html(value).fadeIn();
});
var nextIndex = (index + 1) % options.list.length;
setTimeout(function() {
listTickerInner(nextIndex);
}, options.interval);
};
listTickerInner(options.startIndex);
}
var textlist = new Array("news1", "news2", "news3");
$(function() {
function rss() {
$.getJSON("https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fwww.stuff.co.nz%2Frss", function(data) {
newsArray = [];
for (var i = 0; i < data.items.length; i++) {
newsArray[i] = (data.items[i].title);
}
console.log(newsArray);
listTicker({
list: newsArray,
startIndex: 0,
trickerPanel: $('#newsPanel'),
interval: 3 * 1000,
});
})
}
rss();
});
</script>
<div id='newsPanel' />

How to setInterval() and removeInterval() in this situation?

I understand that in order to remove an interval you need a stored reference to it, so I figured I'll store function returns in a global array.
But why when I click on a cell the intervals keep going and only one stops (I saw first and last cell to stop flashing)?
What I wanted it to do is append a continuous fadeTo on all cells of a table row (excluding first one), and a listener that on clicking any of these cells would stop animations on all of them.
Here's my best effort so far (jsfiddle):
var intervals;
var target = $('#table');
var qty = target.find('td:contains(Price)');
var row = qty.closest('tr');
arr = new Array();
row.find('td').each( function() {
if ($(this).text() !== "Price" ) {
intervals = new Array();
addAnimation($(this));
}
});
function addAnimation(cell) {
var intv = setInterval(function() {
cell.fadeTo("slow", 0.3);
cell.fadeTo("slow", 1);
}, 1000);
intervals.push(intv);
cell.click(function() {
for (var i = 0; i < intervals.length; intervals++) {
window.clearInterval(intervals[i]);
}
});
}
You are instantiating the intervals array multiple times and incrementing the wrong parameter in the for loop:
var intervals = [],
target = $('#table'),
qty = target.find('td:contains(Price)'),
row = qty.closest('tr');
row.find('td').each( function() {
if ($(this).text() !== "Price" ) {
addAnimation($(this));
}
});
function addAnimation(cell) {
var intv = setInterval(function() {
cell.fadeTo("slow", 0.3);
cell.fadeTo("slow", 1);
}, 1000);
intervals.push(intv);
cell.click(function() {
for (var i = 0; i < intervals.length; i++) {
window.clearInterval(intervals[i]);
}
$(this).stop();
});
}
See: fiddle
Your other problem is here:
var intervals;
...
if ($(this).text() !== "Price" ) {
intervals = new Array();
addAnimation($(this));
That creates a new array each time. You should be initialising intervals when you declare it and delete the line creating a new array in the if block:
var intervals = [];
...
if ($(this).text() !== "Price" ) {
addAnimation($(this));
}
However, you may wish to run this more than once, so you should clear out the array when you clear the intervals, something like:
function addAnimation(cell) {
var intv = setInterval(function() {
cell.fadeTo("slow", 0.3);
cell.fadeTo("slow", 1);
}, 1000);
intervals.push(intv);
cell.click(function() {
for (var i = 0; i < intervals.length; intervals++) {
window.clearInterval(intervals[i]);
}
// reset the array
intervals = [];
});
}
or replace the for loop with something like:
while (intervals.length) {
window.clearInterval(intervals.pop());
}
which stops the intervals and clears the array in one go. :-)

Javascript module pattern - what am I doing wrong?

A working version of this is here: http://est.pagodabox.com/client/svedka
I have the following function which I'm trying to convert into a module pattern, but when I try to use one of the function that I return at the bottom, for example:
est_project.closeContent($html);
I get an error that it's not a function. Is there something i'm doing wrong here?
Thanks!
var est_project = (function(){
// Setup functions
var flexDestroy,
cloneCurrent,
clonePosition,
switchSlide,
projectLayout,
contentHeight,
slidePos,
slideClick,
infoToggle,
closeContent;
// Destroy flexslider
flexDestroy = function($slider,$cleanSlider, $projBg) {
// Insert the clone of the un-initialized slide element, and remove the current flexslider
// Effectively "destroys" the current slider
var $curSlide = $slider.find('.flex-active-slide'),
// Get the zero based index of current slide
curSlideIndex = $curSlide.index() - 1,
curBg = $curSlide.find('img').attr('src'),
slideCount = $cleanSlider.data('count'),
i = 0,
$rearrange = $('');
// When you switch projects, the current slide should stay put
if(curSlideIndex !== 0 && slideCount > 1) {
// Cut from the current slide to the end, paste at the beginning
for(i = 0 ; i < slideCount; i += 1) {
if(curSlideIndex > i) {continue;}
$rearrange = $rearrange.add( $cleanSlider.find('li:eq(' + i + ')') );
}
$rearrange.remove();
$cleanSlider.find('li:first-child').before($rearrange)
$cleanSlider.css({'background-image' : 'url(' + curBg + ')'});
}
$slider.after($cleanSlider).remove();
clonePosition(slideheight);
};
return {
// Clone current
cloneCurrent: function($el) {
var $clean,
slideCount = $el.find('li').length;
$clean = $el.clone();
$clean.removeClass('project-current').find('div').removeClass('img-loading');
$clean.data('count',slideCount);
return $clean;
},
// Set the clone position, for when we add it to the DOM or resize the window
clonePosition: function(slideheight) {
var n = $cleanSlider.index(),
$myBg = $cleanSlider.find('div'),
myPosition = n * slideheight;
// Set the position of the inserted clone
$cleanSlider
.css({height: slideheight, top: myPosition, position : 'absolute'});
$myBg
.css({height: slideheight});
},
switchSlide: function($me, $slider) {
$('.project-current').removeClass('project-current');
$me.addClass('project-current');
// Get rid of current flexslider
flexDestroy($slider,$cleanSlider);
// Clone the unitialized slider so we can add it back in later when it gets destroyed
$cleanSlider = cloneCurrent($me);
$me.addClass('flexslider').flexslider({
animation: "slide",
animationSpeed: 500,
slideshow: false,
manualControls: '.dot-nav li a'
});
// After the flexslider initializes, slide the content
setTimeout(function(){
slidePos($me, $slidewrap, slideheight, $win);
},100);
},
// Custom "masonry" function, absolutely positions each project div according to the slide height
projectLayout: function(slideheight,$proj,$projBg) {
var n = 0;
$proj.each(function(){
var $me = $(this),
myPosition = n * slideheight;
// Set all the heights
$me
.css({top: myPosition, position : 'absolute'})
.add($projBg)
.css({height: slideheight});
n++;
});
},
// Set slide wrapper height to window height
contentHeight: function($win, $slidewrap) {
var winHeight = $win.height();
$slidewrap.css({height: winHeight});
},
// Set slide wrapper position to slide to the clicked slide, and set content position
slidePos: function($me, $slidewrap, slideheight, $win) {
var $contentText = $('.project-content .text'),
projNavHeight = Math.round( $win.height() * .1 ),
curIndex = $me.index(),
curTop = 0 - (curIndex * slideheight) + projNavHeight;
$slidewrap.css({transform: 'translate(0,' + curTop.toString() + 'px)'});
$('.corner-btn').add($contentText).css({'padding-top' : projNavHeight});
setTimeout(function(){
$slidewrap.removeClass('tr-none movin').addClass('tr-all');
$('.project').css({opacity: .4})
}, 100);
},
// Click a project, slide to it
slideClick: function($proj) {
$('.project').live('click',function(){
var $me = $(this),
myHref = $me.data('href'),
myTitle = $me.data('title'),
$slider = $('.flexslider'),
indexMy = $me.index(),
indexCur = $('.project-current').index(),
projDir;
$me.css({opacity: 1});
// Stop here if we click on the current project
if($me.hasClass('project-current')) {
return false;
}
History.pushState(null,myTitle,myHref);
});
},
// Hide and show content
infoToggle: function() {
// Open content
$('#corner-btn-info').on('click',function(){
$html.addClass('show-content');
if($('.project-content .text').height() <= $win.height()) {
$html.addClass('no-overflow');
}
$('.project-content-wrap').css({'z-index': 10});
});
// Close content
$('#corner-btn-close').live('click',function(){
closeContent($html);
});
},
closeContent: function($html) {
$html.removeClass('show-content');
setTimeout(function(){
$('.project-content-wrap').css({'z-index': -1});
$html.removeClass('no-overflow');
$('#classy').animate({scrollTop: 0})
},300);
}
};
});
The problem is that you're not executing the anonymous function, your code is the equivalent of:
var est_project = function() {};
You need to execute the function if you want it to return the functions defined in it.
Just replace the last line:
});
By:
}());
Or you can keep your code and call the closeContent function like this:
est_project().closeContent();
But I guess that's not what you want :-) You'd instantiate a new object everytime you call the est_project function.
At the start and end of your file just attach the object to window with the executed function and wrap whole function inside a self executing function. like this
(function(global) {
//your code goes here
global.est_project = est_project();
})(this)

How can a restart a loop in an animation?

I am trying to build a game like space invader (since I only started coding 5 days ago) where if a shoe hits the zombie, the zombie will disappear and reappear at the top of the screen (coming down again). I just can't seem to make the zombie go back to the top (they remain at the lowest point of the animation)
Below is the test for the collision:
function zombietestCollision(position1, size1, position2, size2) {
if (((position1.left + size1.width) > position2.left) &&
((position1.top + size1.height) > position2.top) &&
((position2.left + size2.width) > position1.left) &&
((position2.top + size2.height) > position1.top)) {
function loop () {
movedown($zombie);
moveup($zombie);
};
$(function zombieloop() {
setInterval( loop, 1 );
});
}
}
I have encompassed this test in my downward movement of the zombie
// down movement of the zombies
function movedown($zombie) {
$zombie.animate({
'left': 300,
}, {
duration:5000,
step:function(){
$.each($("#zombie"), function(index,zombie) {
var $zombie = $(zombie);
var $shoe = $("#shoe");
var shoeSize = {
height: $shoe.height(),
width : $shoe.width()
};
var zombieSize = {
height: $zombie.height(),
width : $zombie.width()
};
zombietestCollision($shoe.position(), shoeSize, $zombie.position(), zombieSize);
});
}
When I run this, the screen is just blank. What have I done in correctly?
If needed here is the full code: http://jsfiddle.net/JKd9K/7/
Sorry but I am completely new to programming, so it's hard for me to understand which part I did wrong. Cheers!
You need to be careful with how you're closing functions. Take a look at this http://jsfiddle.net/JKd9K/2/
Your movedown function should be like this
function movedown($zombie) {
$zombie.animate({
'left': 300
}, {
duration: 5000,
step: function() {
$.each($("#zombie"), function(index, zombie) {
var $zombie = $(zombie);
var $shoe = $("#shoe");
var shoeSize = {
height: $shoe.height(),
width: $shoe.width()
};
var zombieSize = {
height: $zombie.height(),
width: $zombie.width()
};
zombietestCollision(
$shoe.position(),
shoeSize,
$zombie.position(),
zombieSize);
});
}
});
}
Note that there's a bunch of extra braces at the end.

Scope issue with a sequence of fadeIn's

I the following code I have a UL with x3 LI's. I want the LI's to fadeIn in a sequence but am loosing scope somewhere I think. The problem is that only the last item in the sequence is run. I initially thought this was to do with a loop, so I removed all of them. Any help would be great.
Thanks is Advance.
function Sequence() {
var sequence = [];
var pos = 0;
Sequence.prototype.add = function(obj) {
sequence.push(obj);
};
Sequence.prototype.start = function() {
sequence[pos].run();
};
Sequence.prototype.next = function() {
pos++;
sequence[pos].run();
};
};
function fadeIn(params) {
this.id = params.id;
this.onComplete = params.onComplete;
var self = this;
var timer;
var i = params.opacity;
fadeIn.prototype.run = function(){
timer = setInterval(function() {
params.element.style.opacity = i / 10;
i++;
if (i / 10 == 1) {
clearInterval(timer);
self.onComplete();
}
}, params.fps);
}
};
var sequence = new Sequence();
var fader = document.getElementById('fader1');
var items = fader.getElementsByTagName("li");
sequence.add(new fadeIn({
"id": "instance_0",
"element": items[0],
"opacity": 0,
"fps": 80,
"onComplete": function() {
sequence.next();
}
}));
sequence.add(new fadeIn({
"id": "instance_1",
"element": items[1],
"opacity": 0,
"fps": 80,
"onComplete": function() {
sequence.next();
}
}));
sequence.start();
Yes, this is a scope issue. The problem is in the line:
fadeIn.prototype.run = function(){
When you define a method on the prototype, you're defining the method on all instances of the fadeIn class. So each time you call the constructor, you're redefining the method with the new params in the closure.
The solution is to define the method on this (or, as you've renamed it, self), which is the new instance, rather than the class:
self.run = function(){
Working example here: http://jsfiddle.net/nrabinowitz/wrQMa/3/

Categories

Resources