I've taken over a project that was built by someone else. The site features a custom slideshow on the home page. I've made some changes to the look/feel of the slideshow per client requests, but the last thing it needs is autoplay.
Below is the script for the slideshow. I know about setInterval but I'm not sure where to put it, or if the code needs to be adjusted a bit before dropping that in.
$(document).ready(function() {
// A little script for preloading all of the images
// It"s not necessary, but generally a good idea
$(images).each(function(index, value){
// Ski first image since it is already loaded
if( index != 0 ) {
$("<img/>")[0].src = this;
}
});
// Feature Slider Navagitaion
$('.feature .ei-slider-nav li a').click( function(e) {
e.preventDefault();
var thisLink = $(this);
var navIndex = thisLink.parent('li').index();
thisLink.parents('ul').children('li').removeClass('active');
thisLink.parent('li').addClass('active');
// Is this item already active?
if( !$('.feature .ei-slider-title .ei-slider-title-item:eq('+navIndex+')').hasClass('active')) {
// Fade in/out feature image
$('.feature .ei-slider-large img').animate({opacity: 0}, 500, function() {
// Support for non-opacity browsers
$(this).css('visibility', 'hidden');
// Load new feature image
$(this).attr('src', images[navIndex]);
$(this).attr('alt', imagesAlt[navIndex]);
$(this).css('visibility', 'visible');
$('.feature .ei-slider-large img').animate({opacity: 1}, 500);
});
// Fade in/out feature text
$('.feature .ei-slider-title .ei-slider-title-item.active').fadeOut(500, function() {
$(this).parent().children().removeClass('active');
$('.feature .ei-slider-title .ei-slider-title-item:eq('+navIndex+')').addClass('active').fadeIn();
});
// Fade in/out feature credit
$('.content .ei-slider-credit span.active').fadeOut(500, function() {
$(this).parent().children().removeClass('active');
$('.content .ei-slider-credit span:eq('+navIndex+')').addClass('active').fadeIn();
});
}
});
// Feature Slider Learn More
$('.feature .ei-slider-title-item-learn').click( function(e) {
e.preventDefault();
thisPrev = $(this).prev();
if( thisPrev.css('display') == 'none') {
thisPrev.slideDown();
thisPrev.css('visibility', 'visible');
thisPrev.animate({'opacity': 1}, 500, function() {
});
$(this).html('Hide');
} else {
thisPrev.animate({'opacity': 0}, 500, function() {
thisPrev.slideUp();
thisPrev.css('visibility', 'hidden');
});
$(this).html('Hide');
$(this).html('Learn More');
}
});
});
Thanks!
This would probably be a little bit easier if there were a way to keep track of the current state of the slideshow outside the context of clicking on a slide's navigation link. The first thing I would add, right above $('.feature .ei-slider-nav li a').click( function(e) {... would be:
var eiSlider = {
currentSlideIndex: 0,
nextSlide: null, // we will define this later
autoPlay: null // we will define this later too
};
Then, inside of the function I mentioned above, as the first order of business inside of the check for whether the slide is already active, I'd add this:
// Set the currentSlide index on the global eiSlider tracking object
eiSlider.currentSlide = navIndex;
Next, you'll want to make a function to handle advancing the slideshow automatically:
eiSlider.nextSlide = function() {
var currentSlideIndex = eiSlider.currentSlideIndex,
nextSlideIndex = currentSlideIndex + 1,
totalSlides = $('.ei-slider-large img').length;
// If we are already at the end of the images, loop back to the beginning
if ( nextSlideIndex < totalSlides ) {
nextSlideIndex = 0;
}
// Trigger a click to move forward to the next slide
$('.feature .ei-slider-nav li:eq(' + nextSlideIndex + ') a').trigger('click');
};
I've also moved the work of setting the "active" class on a given slide's nav link to happen inside of the logic around making sure the slide you clicked on wasn't already active, to make sure it doesn't get set incorrectly.
Finally, you can use setInterval (at the bottom of all of the above code) to handle the autoplay portion.
// Auto-advance the slides every 5 seconds. Adjust the value as necessary
eiSlider.autoPlay = window.setInterval(function(){
eiSlider.nextSlide();
}, 5000);
Your final, updated code would look something like this:
$(document).ready(function() {
// A little script for preloading all of the images
// It"s not necessary, but generally a good idea
$(images).each(function(index, value){
// Ski first image since it is already loaded
if( index !== 0 ) {
$("<img/>")[0].src = this;
}
});
// Object for basic state tracking and namespacing of slideshow functions
var eiSlider = {
currentSlideIndex: 0,
nextSlide: null, // we will define this later
autoPlay: null // we will define this later too
};
// Feature Slider Navagitaion
$('.feature .ei-slider-nav li a').click( function(e) {
e.preventDefault();
var thisLink = $(this),
navIndex = thisLink.parent('li').index();
// Is this item already active?
if( !$('.feature .ei-slider-title .ei-slider-title-item:eq('+navIndex+')').hasClass('active')) {
thisLink.closest('li').siblings().removeClass('active');
thisLink.closest('li').addClass('active');
// Set the currentSlide index on the global eiSlider tracking object
eiSlider.currentSlideIndex = navIndex;
// Fade in/out feature image
$('.feature .ei-slider-large img').animate({opacity: 0}, 500, function() {
// Support for non-opacity browsers
$(this).css('visibility', 'hidden');
// Load new feature image
$(this).attr('src', images[navIndex]);
$(this).attr('alt', imagesAlt[navIndex]);
$(this).css('visibility', 'visible');
$('.feature .ei-slider-large img').animate({opacity: 1}, 500);
});
// Fade in/out feature text
$('.feature .ei-slider-title .ei-slider-title-item.active').fadeOut(500, function() {
$(this).parent().children().removeClass('active');
$('.feature .ei-slider-title .ei-slider-title-item:eq('+navIndex+')').addClass('active').fadeIn();
});
// Fade in/out feature credit
$('.content .ei-slider-credit span.active').fadeOut(500, function() {
$(this).parent().children().removeClass('active');
$('.content .ei-slider-credit span:eq('+navIndex+')').addClass('active').fadeIn();
});
}
});
// Feature Slider Learn More
$('.feature .ei-slider-title-item-learn').click( function(e) {
e.preventDefault();
thisPrev = $(this).prev();
if ( thisPrev.css('display') === 'none') {
thisPrev.slideDown();
thisPrev.css('visibility', 'visible');
thisPrev.animate({'opacity': 1}, 500, function() {});
$(this).html('Hide');
} else {
thisPrev.animate({'opacity': 0}, 500, function() {
thisPrev.slideUp();
thisPrev.css('visibility', 'hidden');
});
$(this).html('Hide');
$(this).html('Learn More');
}
});
// Function to handle slide advancement
eiSlider.nextSlide = function() {
var currentSlideIndex = eiSlider.currentSlideIndex,
nextSlideIndex = currentSlideIndex + 1,
totalSlides = $('.ei-slider-large img').length;
// If we are already at the end of the images, loop back to the beginning
if ( currentSlideIndex < (totalSlides - 1) ) {
nextSlideIndex = 0;
}
// Trigger a click to move forward to the next slide
$('.feature .ei-slider-nav li:eq(' + nextSlideIndex + ') a').trigger('click');
};
// Auto-advance the slides every 5 seconds. Adjust the value as necessary
eiSlider.autoPlay = window.setInterval(function(){
eiSlider.nextSlide();
}, 5000);
});
Bear in mind this answer makes a few assumptions, the main one being that the eiSldier namespace is available; if it's not, just use a different namespace than the one I provided, OR add these three new items to the existing namespace so it doesn't get overwritten. The only change in that case would not be defining eiSlider as an object with three properties, but instead defining simply eiSlider.currentSlide = 0, and then proceeding to define the other two functions the way they already are defined later on in the example.
If the eiSlider namespace already exists, it's entirely possible that currentSlide or some equivalent property exists on it already, so you could take advantage of that if it does, rather than making a duplicate (or worse, overriding it in a way that could cause errors in the rest of its functionality).
One thing I should note that the code above doesn't currently do is stop/clear the autoplay out when you manually click on a slide's navigation link. That's a pretty important usability issue that will need to get cleaned up. You can accomplish this by using clearInterval(eiSlider.autoPlay), but to make that really work correctly, you'd need to separate out the code that handles slide advancement from the actual click event.
Check out this slightly modified JS Bin that shows the auto-advance working as intended, plus the changes I mentioned above with clearInterval:
http://jsbin.com/gumaqefere/1/edit?html,js,console,output
Related
I have a list where the first-child element is visible on desktop, and is hidden on screens under 767px, and then every other element cycles through on a loop for all screen sizes.
I have been trying to re-run this jQuery plugin on window resize without success, please could someone help implement window resize function?
I have put together an example here
(function ($){
$.fn.extend({
rotaterator: function(options) {
var defaults = {
fadeSpeed: 500,
pauseSpeed: 100,
child:null
};
var options = $.extend(defaults, options);
return this.each(function() {
var o =options;
var obj = $(this);
var obj2 = "ul li:first-child";
var items = $(obj.children(), obj);
var items2 = $(obj.children(), obj2);
if ($(window).width() < 767) {
items.each(function() {$(this).hide();})
items2.each(function() {$(obj2).hide();})
} else {
items.each(function() {$(this).hide();})
items2.each(function() {$(obj2).show();})
}
if(!o.child){var next = $(obj).children(':nth-child(2)');
}else{var next = o.child;
}
$(next).fadeIn(o.fadeSpeed, function() {
$(next).delay(o.pauseSpeed).fadeOut(o.fadeSpeed, function() {
var next = $(this).next();
if (next.length == 0){
next = $(obj).children(':nth-child(2)');
}
$(obj).rotaterator({child : next, fadeSpeed : o.fadeSpeed, pauseSpeed : o.pauseSpeed});
})
});
});
}
});
})(jQuery);
and call
(function ($) {
$('ul').rotaterator({fadeSpeed:5000, pauseSpeed:1000});
})(jQuery);
Thanks for looking.
UPDATE:
I have added window resize, it seems it's had an affect of how it initially loads and performs thereafter, showing all elements first, please see updated fiddle demo
Your current implementation already adapts to the new window size as soon as the fade-out completes and the next call to rotaterator is made.
If however you want an immediate effect at the resize event, so that the animation restarts taking the new window size into account, then use the jQuery stop method to stop any current animations of an ul child element.
For instance:
$(window).resize(function() {
$('ul *').finish();
$('ul').rotaterator({fadeSpeed:5000, pauseSpeed:1000});
});
What I want: I created a sort of image gallery with a thumbnail slider and I want the thumbnails to scroll when a nav button is clicked but if the button is pushed again before the animation is completed it doesn't keep adding to the que, it clears the que and only completes the current animation.
What my problem is: When the button is clicked it puts the click animation in a que and completes all the clicks in order. Maybe someone can help we word this better.
What I have tried: I have tried adding .finish() and .stop(true, true) to my js file but I can't seem to get it working right. I'm probably putting it in the wrong spot or even using the wrong thing, I don't know and so I need some help.
Here is a functioning jsfiddle: http://jsfiddle.net/ma9j6o09/2/
Some of it is not working since my images are locally hosted but the slider part for the thumbnails is.
This is my function for animating the movement; what do I add to get the effect I need?
var clicks = 0;
$("#right").click(function() {
if ( clicks < 5 ) {
clicks++;
$("#thumbContainer").animate({
left: "-=128px"
}, 500, function() {
// Animation complete.
});
}
});
$("#left").click(function() {
if (clicks > 0) {
clicks--;
$("#thumbContainer").animate({
left: "+=128px"
}, 500, function() {
// Animation complete.
});
}
});
Try this out: http://jsfiddle.net/ma9j6o09/3/
In response to your question about .stop() you would use it like this:
$("#thumbContainer").stop(true, true).animate({
left: "+=128px"
}, 500, function() {
// Animation complete.
});
});
But this will indeed not achieve what you want as it means it will stop the animation and jump to the last frame straight away so you lose the animation you wanted.
Instead use the flag I used in the fiddle which makes it impossible to even try animate whilst an animation is in progress.
var clicks = 0,
animating = false;
$("#right").click(function() {
// Only animate if we are not already animating
if ( clicks < 5 && !animating ) {
animating = true;
clicks++;
$("#thumbContainer").animate({
left: "-=128px"
}, 500, function() {
animating = false; // No longer animating
// Animation complete.
});
}
});
$("#left").click(function() {
// Only animate if we are not already animating
if (clicks > 0 && !animating) {
animating = true;
clicks--;
$("#thumbContainer").animate({
left: "+=128px"
}, 500, function() {
animating = false; // No longer animating
// Animation complete.
});
}
});
I'm am attempting to build a homepage that has animations. I am having hard time controlling my animations though. All I need is to hide elements, and then show elements after a certain time. Loop through that sequence, and pause and show all elements when the someone hovers over the box. Example simple animation.
I have a long way to go. At first I tried using the .css() visibility property, now I'm using .show() and .hide().
I need a way to loop through my animations. I attempt to add another
setTimeout(clear1(), 3000);
to the end of my box1 function, but that wouldn't work for some reason.
I need a way to on a user hover over #box1, that all animations stop. I have tried using .clearQueue, but I couldn't get that to work.
First of all, set to your css:
.box {display: none;}
SHOW ALL BOXES ON HOVER See Demo
This will show all boxes on hover and then continue the animation from where it stopped (will hide the boxes that hadn't shown up during the animation). I think that is what you are after.
var index = 0; // To keep track of the last div showed during animation
var time_of_delay = 1000; // Set the time of delay
// Start the animation
$(document).ready(function () {
box1(time_of_delay);
});
// The hover states
$("#box1_1").hover(
function() {
box1(0);
}, function() {
box1(time_of_delay);
});
// The animation function
function box1 (delay_time) {
var time=delay_time;
if(time>0) {
$(".box").slice(index).each(function() {
$(this).hide().delay(time).show(0);
time=time+time_of_delay;
});
index=0;
} else {
$(".box:visible").each(function() {
index++;
});
$(".box").stop(true).show(0);
}
}
PAUSE ON HOVER See Demo
This will only pause the animation and continue from where it stopped.
var time_of_delay = 1000; // Set the time of delay
// Start the animation
$(document).ready(function () {
box1(time_of_delay);
});
// The hover states
$("#box1_1").hover(
function() {
box1(0);
}, function() {
box1(time_of_delay);
});
// The animation function
function box1 (delay_time) {
var time=delay_time;
if(time>0) {
$(".box:hidden").each(function() {
$(this).delay(time).show(0);
time=time+time_of_delay;
});
} else {
$(".box").stop(true);
}
}
I used setTimeout and clearTimeout and periodically call a function that increments (and resets) the box to display. Since I assign setTimout to boxt, I am able to call clearTimeout(boxt) on box1's hover event so that I can stop specifically that loop. Here's my jsfiddle. It might not be the exact effect you're trying to achieve, but it should be the right functionality and be easily adaptable with a few tweaks. Let me know if this works for you and if you have any questions about how it works :)
LIVE DEMO
var $box = $('#box1').find('.box'),
boxN = $box.length,
c = 0,
intv;
$box.eq(c).show(); // Show initially the '0' indexed .box (first one)
function loop(){
intv = setInterval(function(){
$box.eq(++c%boxN).fadeTo(400,1).siblings().fadeTo(400,0);
},1000);
}
loop(); // Start your loop
$('#box1').on('mouseenter mouseleave', function( e ){
return e.type=='mouseenter' ? (clearInterval(intv))($box.fadeTo(400,1)) : loop();
});
Where ++c%boxN will take care to loop your animation using the Modulo % (reminder) operator inside a setInterval. Than all you need to do is to register a mouseenter and mouseleave on the parent element to:
clear the Interval on mouseenter + fade all your elements
restart your loop function on mouseleave.
Here's one way to do it:
// hide all of the boxes
$('.box').hide();
// reference to each box, the current box in this list and a flag to stop the animation
var divs = box1.getElementsByClassName('box');
var i = 0;
var run = true;
// this will animate each box one after the other
function fade(){
if(i < divs.length && run){
$(divs[i++]).fadeIn(500, function(){
setTimeout(fade, 1000);
});
}
};
fade();
// stop the above function from running when the mouse enters `box1`
$('#box1').on('mouseenter', function(){console.log('enter');
run = false;
});
// start the function again from where we stopped it when the mouse leaves `box1`
$('#box1').on('mouseleave', function(){console.log('leave');
run = true;
fade();
});
Demo: http://jsfiddle.net/louisbros/dKcn5/
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();
}
The Bootstrap carousel is a strange beast. I've tried tweaking $next to prevent infinite looping but end up either breaking it or preventing the slides from going backwards when reaching the end.
I would like the carousel to only slide within the list and not infinitely loop.
Any help would be appreciated.
$next = $next.length ? $next : this.$element.find('.item')[fallback]()
if ($next.hasClass('active')) return
if ($.support.transition && this.$element.hasClass('slide')) {
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$next.addClass(type)
$next[0].offsetWidth // force reflow
$active.addClass(direction)
$next.addClass(direction)
this.$element.one($.support.transition.end, function() {
$next.removeClass([type, direction].join(' ')).addClass('active')
$active.removeClass(['active', direction].join(' '))
that.sliding = false
setTimeout(function() {
that.$element.trigger('slid')
}, 0)
})
} else {
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$active.removeClass('active')
$next.addClass('active')
this.sliding = false
this.$element.trigger('slid')
}
Update: This is unrelated to "autoplay" I'm specifically referring to manually pressing the left and right buttons.
For the carousel to not infinitely loop (using Bootstrap 3.0.0), and stop at the last slide unless the "next" arrow is clicked, the following is the best way to do it:
$('.carousel').carousel({
interval: 5000,
wrap: false
});
Setting the wrap option to false tells the carousel to stop cycling through the slides automatically. I hope this answers your question correctly.
You could just add some code to the page to hide the appropriate carousel controls after a slid event:
$('#myCarousel').on('slid', '', function() {
var $this = $(this);
$this.children('.carousel-control').show();
if($('.carousel-inner .item:first').hasClass('active')) {
$this.children('.left.carousel-control').hide();
} else if($('.carousel-inner .item:last').hasClass('active')) {
$this.children('.right.carousel-control').hide();
}
});
This example assumes the markup used on the Twitter Bootstrap example carousel.
Make sure to hide the left one when you open the page.
Add attribute data-wrap="false" in Div
The easiest way to do this is as follows:
//intro slider
$('#carousel_fade_intro').carousel({
interval: 2500,
pause: "false"
})
//Stop intro slider on last item
var cnt = $('#carousel_fade_intro .item').length;
$('#carousel_fade_intro').on('slid', '', function() {
cnt--;
if (cnt == 1) {
$('#carousel_fade_intro').carousel('pause');
}
});
Not sure if this is only relevent to the newest version of Bootstrap but setting data-wrap="false" on the outermost carousel container will prevent it from proceeding past the final slide.
source: http://getbootstrap.com/javascript/#carousel-options
For people looking for a solution for Bootstrap 3 working for multiple carousels on same page try this:
$(function() {
// init carousel
$('.carousel').carousel({
pause: true, // init without autoplay (optional)
interval: false, // do not autoplay after sliding (optional)
wrap:false // do not loop
});
// init carousels with hidden left control:
$('.carousel').children('.left.carousel-control').hide();
});
// execute function after sliding:
$('.carousel').on('slid.bs.carousel', function () {
// This variable contains all kinds of data and methods related to the carousel
var carouselData = $(this).data('bs.carousel');
// get current index of active element
var currentIndex = carouselData.getItemIndex(carouselData.$element.find('.item.active'));
// hide carousel controls at begin and end of slides
$(this).children('.carousel-control').show();
if(currentIndex == 0){
$(this).children('.left.carousel-control').fadeOut();
}else if(currentIndex+1 == carouselData.$items.length){
$(this).children('.right.carousel-control').fadeOut();
}
});
Please let me now if this is not working in your case.
if you are using bootstrap 3 use this
$('.carousel').carousel({
wrap: false
});
The codes posted here have two problems: doesn't work if you have more than one carousel on the same page and doesn't work if you click on the indicator dots. Also, in Bootstrap 3 the event has changed name.
The below code is an updated version of this code. And here you can find a more detailed explanation
checkitem = function() {
var $this;
$this = $("#slideshow");
if ($("#slideshow .carousel-inner .item:first").hasClass("active")) {
$this.children(".left").hide();
$this.children(".right").show();
} else if ($("#slideshow .carousel-inner .item:last").hasClass("active")) {
$this.children(".right").hide();
$this.children(".left").show();
} else {
$this.children(".carousel-control").show();
}
};
checkitem();
$("#slideshow").on("slid.bs.carousel", "", checkitem);