Running continuous events after each other - javascript

I've been trying to make this for 2 days, I apologize I'm new to Javascript/Jquery and I'm in the learning process.
I'm trying to create a javascript when the page is loaded will have an image fade in and fade out and after the first image fades in and out then a second, third, etc. however many I need.
I know this is a newby question but I'm clearly not sure what to look for at this point. And I have been doing research and learning along the way, I just would like to have it sooner than I may be able to accomplish.
Any help is appreciated.
This is what I came up with which to me looks completely invalid, but seems to work:
<div class="splashbg1" style="display: none;"></div>
<div class="splashbg2" style="display: none;"></div>
<div class="splashbg3" style="display: none;"></div>
<div class="splashbg4" style="display: none;"></div>
<div class="splashbg5" style="display: none;"></div>
<script>
$(document).ready(function() {
$('.splashbg1').fadeIn(1300, function() {
$('.splashbg1').fadeOut(1300, function() {
$('.splashbg2').fadeIn(1300, function() {
$('.splashbg2').fadeOut(1300, function() {
$('.splashbg3').fadeIn(1300, function() {
$('.splashbg3').fadeOut(1300, function() {
$('.splashbg4').fadeIn(1300, function() {
$('.splashbg4').fadeOut(1300, function() {
$('.splashbg5').fadeIn(1300, function() {
});
});
});
});
});
});
});
});
});
});
</script>

example HTML:
<div id="images>
<img src="">
<img src="">
...
</div>
example Javascript:
function switchImage(){
$('#images img:visible').fadeOut(function(){
$(this).next().length ? $(this).next().fadeIn() : $('#images img').eq(0).fadeIn();
});
};
$('#images img').hide().eq(0).show(); // show only the first image
setInterval(switchImage, 2000); // loop through images every 2000 milliseconds
example: http://jsfiddle.net/ampersand/nhp2v/

You can use an array and a variable containing the current image, then fade them in and out. It depends on how your images are stored. If you have one <img> element with an ID of myImg, for example, you could do this:
var images = ['http://someurl.com/someimg.jpg', 'somethingelse.png', 'hello.gif'];
var currentImage = 0;
function next() {
$('#myImg').fadeOut(function() {
$('#myImg').prop('src', images[currentImage]).fadeIn(); // Set the image and fade in
currentImage++; // Get ready for the next image
});
}
next();
If you wanted it to wrap, you could do images[currentImage % images.length]. If there are a bunch of different images, you can do about the same thing, just keep the IDs of the images in images instead.

I wrote a quick function called sequence below. Make a list of the images you'd like to animate using jQuery selectors like this:
var list = [
$('first'),
$('second'),
$('third')
];
Then call the function below with something like this sequence( list, 200, function(){} );
var sequence = function( array, duration, callback ){
var list = array,
length = list.length,
i = 0,
duration = duration,
callback = callback;
function chainFade(){
if( i < length )
array[i].fadeIn( duration )
.fadeOut( duration, function(){
i++;
chainFade();
});
else
typeof callback == 'function' && callback();
}
chainFade();
};
I haven't tested it yet so let me know if you run into any bugs.

Related

Loop jQuery function with fadeIn

I'm using a simple jQuery function to create a small image slider:
function gridhover() {
$(".grid-item .slide-image").each(function(index) {
$(this).delay(400*index).fadeIn(300);
});
}
$( ".grid-item" ).hover(function() {
gridhover();
});
If the function plays once, it stops. Is there a way to loop the function? Check out my CodePen!
The idea here is that since you fadeIn something you must also fade it out and repeat the same process again and again
function gridhover() {
$(".grid-item .slide-image").each(function(index) {
$(this).delay(2000*index).fadeIn(300);
});
$(".grid-item .slide-image").each(function(index) {
$(this).delay(2000*index).fadeOut(300);
});
}
try this but with better timming
Based on this example I prepared this jsFiddle for you.
<div id="cycler">
<img class="active" src="image1.jpg" alt="My image" />
<img src="image2.jpg" alt="My image" />
...
</div>
What he does in his example is he picks the .active element and looks for it's next sibling to know which one to show next. If it does not exist, it means the current active is the last one, so he takes the first one again. Simple.
I took his function and applied it to the .hover(). And also set the myInterval variable as global so you can access it from the .hover() and it's callback function.
var milisecs = 1000;
var myInterval;
$("#cycler").hover(function(){
myInterval = setInterval(function(){cycleImages()}, milisecs);
}, function(){
clearInterval(myInterval);
});
...
Check out the jsFiddle for the whole thing.
Hope it helps.

jQuery Custom events for data attribute

I'm building a custom widget system for an app I'm working on. What I want to have happen is the ability for one widget to update another widget by changing out the data attributes value. On page load, the initial data is loaded into this data-attr via PHP and using jQuery to switch out the data after the fact.
For instance, one widget would work as follows:
PHP loads json data into DOM element
jQuery function is passed the elements ID and retrieves data from data-attr and uses it to produce a graph for example
Based on user interaction, another widget sends data to element's data-attr while also firing a custom jQuery event
Initial function gets the new data and updates it's graph
I've started a demo:
// Ranomize Number & Replace Variable
$(function() {
$('#random').click(function(e) {
e.preventDefault();
num = Math.random() + 100;
$('#data').attr('data-receiver', num);
});
});
// Receive Data & Output
$(function() {
var output = $('#output');
var received = $('#data').attr('data-receiver');
output.html(received);
// Not sure what to do next
});
#content {
background: #efefef;
margin: 40px auto;
display: block;
padding: 50px;
width: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="content">
<div id="data" data-receiver="10"></div>
<strong>Output:</strong>
<span id="output"></span>
<br/>
<br/>
Randomize
</div>
But to be honest I'm not sure how to start. I have some code putting a random value into the receiving DOM element, but not sure how to setup the event or write another function to receive and update the #output div.
I'm happy to answer questions or write more code to help better explain my goal. Thanks in advance.
Try utilizing .queue() , .promise() to create a "subscriber" , "publisher" pattern
var output = $("#output");
var process = function process(next) {
// `this`:`#data`
var num = Math.random() * 100;
$(this).data("receiver", num);
return next()
};
var update = function update() {
// `this`:`#data`
$(this).promise("process").then(function(received) {
// `received`:`#data`,
// do stuff with `received`
console.log(received.data("receiver"));
output.html(received.data("receiver"));
received.queue("process", process);
// add `process` to `received` `"process"` queue
console.log(received, received.queue("process"));
});
};
// queue first call to `process`
$("#data").queue("process", process);
$("#random").click(function (e) {
e.preventDefault();
update.call($("#data").dequeue("process"));
});
jsfiddle http://jsfiddle.net/jev4wuej/2/
I prefer to use custom events which allows for the code to be more decoupe and independent of each other.
jsfiddle
JS
var toolbar = {
init: function() {
$('.data-randomizer').click(this.handleRandomizer);
},
handleRandomizer: function() {
var number = Math.random() + 100;
$.event.trigger('update-request.storage-widget', [number]);
}
};
var output = {
init: function() {
$(document).on('updated.storage-widget', this.handleDisplay);
$.event.trigger('data-request.storage-widget', this.handleDisplay);
},
handleDisplay: function(event, number) {
$('.data-output-widget #output').text(number);
},
requestOut: function() {
}
};
var storage = {
init: function() {
$(document).on('update-request.storage-widget', this.handleUpdateRequest);
$(document).on('data-request.storage-widget', this.handleDataRequest);
},
handleUpdateRequest: function(event, number) {
$('.data-storage-widget').attr('data-receiver', number);
$.event.trigger('updated.storage-widget', [number]);
},
handleDataRequest: function(event, callback) {
var number = $('.data-storage-widget').data('receiver');
callback(event, number);
}
};
toolbar.init();
storage.init();
output.init();
HTML
<div id="content">
<div class="data-storage-widget" data-receiver="10"></div>
<div class="data-output-widget">
<strong>Output:</strong>
<span id="output"></span>
</div>
<div class="tool-bar-widget">
Randomize
</div>
</div>

Loop through element and change based on link attribute

Trying to figure this out. I am inexperienced at jQuery, and not understanding how to loop through elements and match one.
I have 3 divs:
<div class="first-image">
<img src="images/first.png">
</div>
<div class="second-image">
<img src="images/second.png">
</div>
<div class="third-image">
<img src="images/third.png">
</div>
And off to the side, links in a div named 'copy' with rel = first-image, etc.:
...
Clicking the link will fade up the image in the associated div (using GSAP TweenMax)
Here is the function I've been working on to do this... but I am not fully understanding how to loop through all the "rel" elements, and make a match to the one that has been clicked on.
<script>
//pause slideshow on members to ledger when text is clicked, and show associated image
$(function() {
$('.copy').on('click','a',function(e) {
e.preventDefault();
var slideName = $(this).attr('rel');
$("rel").each(function(i){
if (this.rel == slideName) {
console.log(this);
}
});
//var change_screens_tween = TweenMax.to('.'+slideName+'', 1, {
//autoAlpha:1
//});
});
});
</script>
What am I doing wrong? I don't even get an error in my browser. :-(
Thanks to the answer below, I got farther. Here is my revised code.
$('[rel]').each(function(k, v){
if (v == slideName) {
var change_screens_tween = TweenMax.to('.'+slideName+'', 1, {
autoAlpha:1
});
} else {
var change_screens_tween = TweenMax.to('.'+slideName+'', 1, {
autoAlpha:0
});
}
});
});
This is starting to work, but makes the screenshots appear and then instantly fade out. And it only works once. Any thoughts?
Add brackets around rel, like so:
$('[rel]').each(function() {
if ($(this).attr('rel') == slideName) {
console.log(this);
}
});

jQuery loop image fadeout/in with time interval

I have a jQuery function to fadeIn/Out images in a div. But when the function reaches last image, it gets stopped. Any way to get it in a loop, so that at the end of last image, it will start again from the first image.
here is the code
HTML:
<div id="homeimg">
<img src="image1.jpg" />
<img src="image2.jpg" />
<img src="image3.jpg" />
<img src="image4.jpg" />
</div>
jQuery:
$(document).ready(function(){
$('#homeimg img:first-child').addClass('activeimg');
setInterval('cycleMe()', 4000);
});
function cycleMe() {
$('.activeimg').next().css('z-index', 10);
$('.activeimg').next().fadeIn(1500);
$('.activeimg').fadeOut(1500, function(){
$(this).next().fadeIn(0);
$(this).next().addClass('activeimg');
$(this).css('z-index', 5).removeClass('activeimg');
});
}
Any possibilities?
First of all, you're passing the function in as a string, which is a no-no. I think you're over-complicating your code, and there are some jQuery efficiencies you can leverage.
First, I don't think it's necessary to modify the z-index of your images: the fading should handle all that. Secondly, you can chain jQuery calls (see below how fadeIn and addClass chained). Lastly, every time you do $('.activeimage'), jQuery has to scan the DOM again, which is inefficient. Best to do it once and cache the answer (whenever I store a jQuery object, I begin it with a dollar sign by convention, so I always know I'm dealing with a jQuery-wrapped object).
Here's how I would re-write this:
$(document).ready(function(){
$('#homeimg img:first-child').addClass('activeimg');
setInterval(cycleMe, 4000);
});
function cycleMe() {
var $active = $('#homeimg .activeimg');
var $next = $active.next('img');
if(!$next.length) $next = $('#homeimg img:first-child');
$active.fadeOut(1500, function(){
$(this).removeClass('activeimg');
$next.fadeIn().addClass('activeimg');
});
}
Working jsfiddle: http://jsfiddle.net/6MHDn/
You can also do this with simple array manipulation:
$(document).ready(function () {
$('#homeimg img:first-child').addClass('activeimg');
setInterval(cycleMe, 4000);
// get an array of your images
var arrImgs = $('#homeimg img');
function cycleMe() {
var currImg = arrImgs[0];
var nextImg = arrImgs[1];
// You can do this with simple array splicing and pushing
$(nextImg).css('z-index', 10);
$(nextImg).fadeIn(1500);
$(currImg).fadeOut(1500, function () {
$(nextImg).fadeIn(0);
$(this).css('z-index', 5);
// remove the first item from the array
arrImgs.splice(0,1);
// add it to the end of the array
arrImgs.push(currImg);
});
}
});
jsFiddle: http://jsfiddle.net/mori57/4FbVD/
Taking into consideration some of Ethan's comments, I also tried it this way:
http://jsfiddle.net/mori57/4FbVD/2/
$(document).ready(function () {
$('#homeimg img:first-child').addClass('activeimg');
setInterval(cycleMe, 4000);
// get an array of your images
var arrImgs = $('#homeimg img');
function cycleMe() {
var currImg = $(arrImgs[0]);
var nextImg = $(arrImgs[1]);
// You can do this with simple array splicing and pushing
nextImg.fadeIn(1500);
currImg.fadeOut(1500, function () {
currImg.removeClass('activeimg');
nextImg.fadeIn(0).addClass('activeimg');
// remove the first item from the array
arrImgs.splice(0,1);
// add it to the end of the array
arrImgs.push(currImg);
});
}
});
In my previous attempt, I was having to requery the DOM both for css change and fadeIn ... inefficient. Cache the jQuery object, /then/ do the manipulation, and sans-z-index as in Ethan's approach. I'd still rather not have to requery the DOM at all for each element inside an infinite loop. If I find a way around that, I'll post it as well.

How to detect mouseleave() on two elements at once?

Answer can be in vanilla js or jQuery. I want to hide a div with the id "myDiv" if the user is no longer hovering over a link with the id "myLink" or a span with the id "mySpan". If the user has his mouse over either element "myDiv" will still show, but the second the user is not hover over either of the two (doesn't matter which element the user's mouse leaves first) "myDiv" will disappear from the face of existence.
In other words this is how I detect mouse leave on one element:
$('#someElement').mouseleave(function() {
// do something
});
but how to say (in a way that will actually work):
$('#someElement').mouseleave() || $('#someOtherElement').mouseleave()) {
// do something
});
How to detect this?
Something like this should work:
var count = 0;
$('#myLink, #mySpan').mouseenter(function(){
count++;
$('#myDiv').show();
}).mouseleave(function(){
count--;
if (!count) {
$('#myDiv').hide();
}
});
jsfiddle
You could use a multiple selector:
$("#someElement, #someOtherElement").mouseleave(function() {
// Do something.
});
You can beautifully use setTimeout() to give the mouseleave() function some "tolerance", that means if you leave the divs but re-enter one of them within a given period of time, it does not trigger the hide() function.
Here is the code (added to lonesomeday's answer):
var count = 0;
var tolerance = 500;
$('#d1, #d2').mouseenter(function(){
count++;
$('#d3').show();
}).mouseleave(function(){
count--;
setTimeout(function () {
if (!count) {
$('#d3').hide();
}
}, tolerance);
});
http://jsfiddle.net/pFTfm/195/
I think, it's your solution!!!
$(document).ready(function() {
var someOtherElement = "";
$("#someElement").hover(function(){
var someOtherElement = $(this).attr("href");
$(someOtherElement).show();
});
$("#someElement").mouseleave(function(){
var someOtherElement= $(this).attr("href");
$(someOtherElement).mouseenter(function(){
$(someOtherElement).show();
});
$(someOtherElement).mouseleave(function(){
$(someOtherElement).hide();
});
});
});
----
html
----
<div id="someElement">
<ul>
<li>element1</li>
<li>element2</li>
</ul>
</div>
<div id="tab1" style="display: none"> TAB1 </div>
<div id="tab2" style="display: none"> TAB1 </div>
While the answer from lonesomeday is perfectly valid I changed my html to have both elements in one container. I originally wanted to avoid this hence I had to do more refactoring for my clients in other html templates, but I think it will pay out on the long term.
<div id="my-container">
<div class="elem1">Foo</div>
<div class="elem2">Bar</div>
</div>
$('#my-container').mouseleave(function() { console.log("left"); });

Categories

Resources