JQuery Slider animation only happens for one cycle - javascript

Ive been attempting to create my own Javascript slider plugin, (I realise there are many out there, but i wanted to treat it as a learning exercise),
an example can be seen here: http://jsfiddle.net/6GTGU/
the problem I'm having is that the animation goes round once, and then stops, Ive tried to examine this to see what i have done wrong but i can't find any reason for it, if anyone can help me i would be very grateful.
HTML
<div id="cjwSlider">
<div style="background-color: #6495ed"></div>
<div style="background-color: #62ed43"></div>
<div style="background-color: #ed5943"></div>
</div>
JAVASCRIPT
var cjwSlider = $('#cjwSlider');
var sliderItems = cjwSlider.children('div');
$(document).ready(function () {
sliderItems.each(function( index ) {
$(this).css('z-index', index);
});
window.setInterval(function(){
var maxValue = findMaxZIndex();
var currentItem = sliderItems.filter(function() {
return $(this).css('z-index') == maxValue;
});
currentItem.addClass("hiddenDiv").delay(1000).queue(function() {
sliderItems.each(function( index ) {
$(this).css('z-index', parseInt($(this).css('z-index')) + 1);
});
currentItem.css('z-index', 0);
currentItem.removeAttr('class');
});
}, 4000);
});
function findMaxZIndex() {
var maxValue = undefined;
$(sliderItems).each(function() {
var val = $(this).css('z-index');
val = parseInt(val, 10);
if (maxValue === undefined || maxValue < val) {
maxValue = val;
}
});
return maxValue;
}

PLUGIN DEMO IN ACTION
You said you want a plugin so here you go.
It even stops on mouseenter. (I personally hate when I cannot stop a gallery by just hovering it.)
I don't understand the need of z-index at all, so you can calmly remove it all from your HTML and don't bother at all.
<div class="cjwFader" id="el1">
<div style="background: red;"> 1 </div>
<div style="background: green;"> 2 </div>
<div style="background: gold;"> 3 </div>
</div>
CSS:
(the only needed, but you can also make jQ apply the children position)
.cjwFader > div {
position: absolute;
}
And finally the plugin:
(function($){
$.fn.cjwFader = function(opts){
// Default Settings
var S = $.extend({
fade: 400,
wait: 2000,
startAt: 0
//, need more? add more.
},opts);
return $(this).each(function(){
var that = $(this),
child = $('>*',that),
nOfChildren = child.length,
sI;
function animate(){
child.eq( S.startAt = ++S.startAt % nOfChildren )
.fadeTo( S.fade,1 )
.siblings().stop().fadeTo(S.fade,0);
}
function loop(){
sI=setInterval( animate, S.wait+S.fade );
}loop();
child.hover(function(e){
return e.type==='mouseenter'? clearInterval(sI) : loop();
}).eq(S.startAt).show().siblings().hide();
});
};
})(jQuery);
Plugin usage:
$(function(){ // DOM ready
// $('#el1').cjwFader(); // Use default plugin settings
$('#el1').cjwFader({ // Let's apply some custom stuff
startAt : 1,
fade : 1000,
wait: 700
});
});

Here is the working slideshow: http://jsfiddle.net/6GTGU/7/
I've updated the HTML slightly to remove the initialization code from your JS. You may decide to revert that back
HTML
<div id="cjwSlider">
<div style="background-color: #6495ed; z-index: 0;"></div>
<div style="background-color: #62ed43; z-index: 1;"></div>
<div style="background-color: #ed5943; z-index: 2;"></div>
</div>
I had to remove a lot of JS code to nail down the problem. I think the current JS is all you may need and don't need to go back to your original one:
var cjwSlider = $('#cjwSlider');
var sliderItems = cjwSlider.children('div');
$(document).ready(function () {
window.setInterval(function () {
var maxValue = $('#cjwSlider').find('div').length - 1;
var currentItem = sliderItems.filter(function () {
return $(this).css('z-index') == maxValue;
});
currentItem.addClass("hiddenDiv").delay(1000).queue(function () {
sliderItems.each(function (index) {
$(this).css('z-index', parseInt($(this).css('z-index')) + 1);
});
currentItem.css('z-index', 0);
currentItem.removeAttr('class');
$(this).dequeue();
});
}, 4000);
});
The crux of the problem was the missing call to dequeue() at the end of the function that was queued up. The function executed fine for the first time but then stayed at the head of the queue and prevented execution of functions queued later on. This is why your animation played for one cycle but not after that.

Related

jquery click conditional statement based on selector top position

I am attempting to create my very first jQuery post slider.
The slider has previous and next buttons which offset the top position of the div containing all the post items. ie. increments or decrements the top position value by the '.post-item' height.
I am facing difficulty with a conditional statement to disable the previous and next buttons based on the value of the CSS top property of the div. For example, disable previous button if top position <= 0
I am new to programming and I was hoping to learn by others examples pertaining to my situation, to better grasp the concepts. Any help and guidance on how to best achieve this would be a huge help for me. At the bottom of the post I have included my rather embarrassing progress on one of my attempts.
JavaScript Source
(function ($) {
$(document).ready(function () {
$('.prev-btn').click(function () {
$(".posts-body").animate({
top: "+=142"
}, {"duration": 400, "easing": "easeOutBack"});
});
$('.next-btn').click(function () {
$(".posts-body").animate({
top: "-=142"
}, {"duration": 400, "easing": "easeOutBack"});
});
});
})(jQuery);
HTML Markup
<div class="buttons">
<span class="prev-btn ">Up</span>
<span class="next-btn ">Down</span>
</div>
<div class="post-slider">
<div class="posts-body">
<div class="post-item">
<h1>Placeholder Text</h1>
</div>
<div class="post-item">
<h1>Placeholder Text</h1>
</div>
<div class="post-item">
<h1>Placeholder Text</h1>
</div>
<div class="post-item">
<h1>Placeholder Text</h1>
</div>
</div>
</div>
Failed Attempt
(function ($) {
$(document).ready(function () {
$('.prev-btn').click(function () {
var selector = document.querySelector(".posts-body");
var offset = selector.offsetTop;
if (selector.css("top") > 0) {
$(".posts-body").animate({
top: "+=142"
}, {"duration": 400, "easing": "easeOutBack"});
}
console.log(offset);
});
$('.next-btn').click(function () {
var selector = document.querySelector(".posts-body");
var offset = selector.offsetTop;
$(".posts-body").animate({
top: "-=142"
}, {"duration": 400, "easing": "easeOutBack"});
console.log(offset);
});
});
})(jQuery);
Thanking you very much for your time and help.
I have managed to find a solution, I am sure the example posted below is full of bad programming techniques(learning something new everyday), however my original question to use an if statement on clicking a button to check div position has been solved.
Note:
The jQuery css() Method returns a string, which was being compared to an integer in the previous example.
JavaScript Source (Solved)
(function ($) {
$(document).ready(function () {
$('.up-btn').click(function () {
var a = parseInt($(".posts-body").css("top"));
if (a === 0) {
$(".posts-body").css("top", "0");
} else {
$(".posts-body").animate({
top: "+=142"
}, {"duration": 400, "easing": "easeOutBack"});
}
});
$('.down-btn').click(function () {
var a = parseInt($(".posts-body").css("top"));
var b = Math.abs(a);
var c = parseInt($(".posts-body").css("height"));
var d = c - (3 * 142);
if (b >= d) {
$(".posts-body").css("top", "d");
} else {
$(".posts-body").animate({
top: "-=142"
}, {"duration": 400, "easing": "easeOutBack"});
}
});
});
})(jQuery);
Sources
CSS-Tricks Link: Check div position with jQuery if/else

The second slideshow waiting for the first slideshow to finish

The second slideshow waits for the first slideshow to finish IN THIS FIDDLE
Imagine if I have to have four slideshows in one page: slideshow one, slideshow two, slideshow three, and slideshow four.
The wrapper of all of the slideshows have the same class and has no ID, and the slideshows are run with a same script:
Actually, only one slideshow (the first) which is going to be shown in the page, while the rest are still hidden. If only the second link which refers to the second slideshow is clicked then the second slideshow will be shown in the page while at the same time the first slideshow will be hidden automatically.
If the second slideshow is shown in a wrapper DIV by clicking its link soon after you load the page, the second slideshow is blank with no content. The problem of its blank is because the second slideshow is waiting for the first slideshow to finish in sliding all the contents inside it.
Here is my html code:
<!--SLIDESHOW ONE-->
<div class="bigandsmall">
<div class="bigPicture">
<div class="easyzoom easyzoom--overlay">
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_1.jpg"></div>
<div class="easyzoom easyzoom--overlay">
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_2.jpg"></div>
</div>
<div class="smallPicture">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_1.jpg">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_2.jpg">
</div>
</div>
<!--END OF SLIDESHOW ONE-->
<!--SLIDESHOW TWO-->
<div class="bigandsmall">
<div class="bigPicture">
<div class="easyzoom easyzoom--overlay">
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_1.jpg"></div>
<div class="easyzoom easyzoom--overlay">
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_2.jpg"></div>
</div>
<div class="smallPicture">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_1.jpg">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_2.jpg">
</div>
</div>
<!--END OF SLIDESHOW TWO-->
Here is the script that I use to run the all slideshows:
var $el = $('.bigandsmall'),
// SETUP ////////
F = 600 , // Fade Time
P = 5000 , // Pause Time
C = 0 , // Counter / Start Slide# (0 based)
///////////////////
$sl = $('.bigPicture > div'),
$th = $('.smallPicture > img'),
N = $sl.length,
T = 10000;
$sl.hide().eq(C).show();
$th.eq(C).addClass('on');
// ANIMATION
function anim() {
$sl.eq(C%N).stop(1).fadeTo(F,1).siblings().fadeTo(F,0);
$th.removeClass('on').eq(C%N).addClass('on');
}
// AUTO ANIMATE
function autoAnim() {
T = setTimeout(function() {
C++;
anim(); // Animate
autoAnim(); // Prepare another iteration
}, P+F);
}
autoAnim(); // Start loop
// HOVER PAUSE
$el.hover(function(e) {
return e.type==='mouseenter'? clearTimeout( T ) : autoAnim();
});
// HOVER THUMBNAILS
$th.on('mouseenter', function() {
C = $th.index( this );
anim();
});
If you rewrite it as a plugin instead, you can manage each slideshow independently:
JSFiddle: http://jsfiddle.net/TrueBlueAussie/CH5YN/2/
Please note this is a just an example, not how you would normally write plugins cleanly. I did not attempt to cleanup the structure or code, just made it use separate instances and elements local to the container it is attached to. I styled them with a horrible yellow border so you can see the objects:
$.fn.slideThis = function () {
this.each(function () {
// Reference to current DOM object
var THIS = this;
// Current DOM object as jQuery object
var $this = $(this);
THIS.$sl = $this.find('.bigPicture > div'),
THIS.$th = $this.find('.smallPicture > img'),
THIS.N = THIS.$sl.length,
THIS.T = 10000;
THIS.C = 6;
THIS.$sl.hide().eq(THIS.C).show();
THIS.$th.eq(THIS.C).addClass('on');
THIS.P = 1000;
THIS.F = 1000;
$this.css({
border: "5px solid yellow"
});
// ANIMATION
THIS.anim = function () {
THIS.$sl.eq(THIS.C % THIS.N).stop(1).fadeTo(THIS.F, 1).siblings().fadeTo(THIS.F, 0);
THIS.$th.removeClass('on').eq(THIS.C % THIS.N).addClass('on');
}
// AUTO ANIMATE
THIS.autoAnim = function () {
THIS.T = setTimeout(function () {
THIS.C++;
THIS.anim(); // Animate
THIS.autoAnim(); // Prepare another iteration
}, THIS.P + THIS.F);
}
THIS.autoAnim(); // Start loop
// HOVER PAUSE
THIS.$sl.hover(function (e) {
return e.type === 'mouseenter' ? clearTimeout(THIS.T) : THIS.autoAnim();
});
// HOVER THUMBNAILS
THIS.$th.on('mouseenter', function () {
THIS.C = THIS.$th.index(this);
THIS.anim();
});
});
};
// Attach one of these to every matching element
$(".bigandsmall").slideThis();
I leave it to you read up on creating jQuery plugins and cleanup the code :)
I did upto some point, I don't think you wrote the js code, but that's not my point. You are forgetting some functions, or are referring variables incorrectly.
This is what I got working:
http://jsfiddle.net/CWjS7/4/
JS
$sl = $('.bigPicture > div'),
$th = $('.smallPicture > img'),
N = $sl.length,
T = 10000;
C = 6;
$sl.hide().eq(C).show();
$th.eq(C).addClass('on');
P = 1000;
F = 1000;
// ANIMATION
function anim() {
$sl.eq(C%N).stop(1).fadeTo(F,1).siblings().fadeTo(F,0);
$th.removeClass('on').eq(C%N).addClass('on');
}
// AUTO ANIMATE
function autoAnim() {
T = setTimeout(function() {
C++;
anim(); // Animate
autoAnim(); // Prepare another iteration
}, P+F);
}
autoAnim(); // Start loop
// HOVER PAUSE
$sl.hover(function(e) {
return e.type==='mouseenter'? clearTimeout( T ) : autoAnim();
});
// HOVER THUMBNAILS
$th.on('mouseenter', function() {
C = $th.index( this );
anim();
});

Slider jQuery not working

I am trying to implement basic sliding functionality using jQuery, pls find the code below:
HTML:
<div class="dashboard-crousel" id="spanCarousel">
<span>My Order</span>
<span class="selected">Recommendations</span>
<span>My Profile</span>
<div id="controls">
</div>
</div>
Javascript:
<script>
var slider = {
length: parseInt($("#spanCarousel").children("span").length),
current: 1,
width: $("#spanCarousel").width(),
next: function(){
if(this.current < this.length){
this.current = this.current + 1;
this.animation();
} else {
this.current = 1;
this.animation();
}
},
animation: function(){
var target = (0 - this.width) * (this.current - 1);
this.run("#spanCarousel", target);
},
prev: function(){
if(this.current > 1){
this.current = this.current - 1;
this.animation();
} else {
this.current = this.length;
this.animation();
}
},
run: function(part, target){
$(part + " .pan").stop().animate(
{"margin-left": target},
1000
);
},
initialize: function(){
$("#controls .dashboard-crouselLeftArrow").click(function(){slider.next();});
$("#controls .dashboard-crouselRightArrow").click(function(){slider.prev();});
}
}
slider.initialize();
</script>
I just want to slide content between the arrows as shown in the image.
I want to move text left to right endless. pls help
I see two mistake in your code. But since i do not have your css i could not make you a working exemple and try out.
The function parseInt is taking two parameters, string and radix. However you are never putting the second parameter.
Secondly a semi colon is missing at the very end of your programm.
initialize: function(){
$("#controls .dashboard-crouselLeftArrow").click(function(){slider.next();});
$("#controls .dashboard-crouselRightArrow").click(function(){slider.prev();});
}};
you might use JSFiddle to debbug your future code, it is a really effective tool.

Return Multiple li's as a "slide"

I'm putting together a quick little status board that shows active and upcoming github issues.
I have them all pulled in and formatted as a simple list and found a nice jQuery plugin that cycles through each item as a sort of slideshow. However, it was requested that it show multiple issues at once to fill up the screen more.
So on each slide swap it would display, say 5 LI items at once versus just 1. And then swap to show the next 5 and so on.
HTML
...
<ul id="issue-list">
<li class="issue"></li>
...
<li class="issue"></li>
</ul>
...
<script type="text/javascript">
$(function() {
$('#issue-list').swapmyli({
swapTime: 900, // Speed of effect in animation
transitionTime: 700, // Speed of Transition of ul (height transformation)
time: 4000, // How long each slide will show
timer: 1, // Show (1) /Hide (0) the timer.
css: 0 // Apply plugin css on the list elements.
});
});
</script>
JS
(function(e) {
e.fn.swapmyli = function(t) {
function s() {
var e = i.parent().find(".timer span");
e.animate({
width: "100%"
}, r);
var n = i.find("li:first").outerHeight(true);
i.find("li:first").fadeOut(120);
i.animate({
height: n
}, t.transitionTime);
i.find("li").hide();
e.animate({
width: "0%"
}, 60);
i.find("li:first").remove().appendTo(i).fadeIn(t.swapTime)
}
var n = {
swapTime: 300,
transitionTime: 900,
time: 2e3,
timer: 1,
css: 1
};
var t = e.extend(n, t);
var r = t.time - t.swapTime;
var i = this;
i.wrap('<div class="swapmyli clearfix"></div>');
i.after('<div class="timer"><span></span></div><br class="clear" />');
e(window).load(function() {
var e = i.find("li:first").outerHeight(true);
i.height(e);
i.find("li").hide();
s()
});
if (t.timer == 0) {
i.parent().find(".timer").hide()
}
if (t.css == 0) {
i.parent().addClass("nocss")
}
setInterval(s, t.time)
}
})(jQuery)
I'm not sure if outerHeight() will function correctly with slice, but you may try changing these lines:
var n = i.find("li:first").outerHeight(true);
i.find("li:first").fadeOut(120);
To the following:
var n = i.find("li").slice(0, 4).outerHeight(true);
i.find("li").slice(0, 4).fadeOut(120);
That's sort of a quick answer, but hopefully you're catching my drift. Probably need to play around with it a little bit :)

Showing/hiding <div> using javascript

For example I have a function called showcontainer. When I click on a button activating it, I want a certain div element, in this case <div id="container">, to fade in. And when I click it again, fade out.
How do I achieve this?
Note: I am not accustomed with jQuery.
So you got a bunch of jQuery answers. That's fine, I tend to use jQuery for this kind of stuff too. But doing that in plain JavaScript is not hard, it's just a lot more verbose:
var container = document.getElementById('container');
var btn = document.getElementById('showcontainer');
btn.onclick = function() {
// Fade out
if(container.style.display != 'none') {
var fade = setInterval(function(){
var opacity = parseFloat(container.style.opacity);
opacity = isNaN(opacity) ? 100 : parseInt(opacity * 100, 10);
opacity -= 5;
container.style.opacity = opacity/100;
if(opacity <= 0) {
clearInterval(fade);
container.style.opacity = 0;
container.style.display = 'none';
}
}, 50);
// Fade in
} else {
container.style.display = 'block';
container.style.opacity = 0;
var fade = setInterval(function(){
var opacity = parseFloat(container.style.opacity);
opacity = isNaN(opacity) ? 100 : parseInt(opacity * 100, 10);
opacity += 5;
container.style.opacity = opacity/100;
if(opacity >= 100) {
clearInterval(fade);
container.style.opacity = 1;
}
}, 50);
}
};
Check the working demo.
Provided you're not opposed to using jQuery per se, you can achieve this easily:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#showcontainer').click(function() {
$('#container').fadeToggle();
});
});
</script>
...
<div id="container">
...
</div>
...
<input type="button" id="showcontainer" value="Show/hide"/>
...
Note the missing http: in the beginning of the source of jQuery. With this trick the browser will automatically use http: or https: based on whether the original page is secure.
The piece of code after including jQuery assigns the handler to the button.
Best thing you could do is start now and get accustomed to jQuery.
The page http://api.jquery.com/fadeIn/ has all the example code that could be written here. Basically you want to have the call to fadeIn in your showcontainer function.
function showcontainer() {
$('#container').fadeIn();
}
You can have a look at jQuery UI Toggle.
The documentation turns the use of the library very simple, and they have many code examples.
You'd be as well off learning jQuery as it makes it a lot easier to do things!
From the sounds of it, you could have the container div already in the HTML but with a style of "display:none;", and then simply show it in your click event using (jQuery):
$('#container').fadeIn('slow', function() {
//Any additional logic after it's visible can go here
});

Categories

Resources