Multiple jQuery kits per image slider
I have an HTML document with several image sliders that use HTML, CSS and jQuery.
HTML:
<div class="slides-container">
<img src="strbd-1.png" class='slides-placeholder'>
<div class='slides-main'>
<img src="strbd-1.png">
</div>
<div class='slides-main'>
<img src="strbd-2.png">
</div>
<div class='slides-main'>
<img src="strbd-3.png">
</div>
<div class='slides-main'>
<img src="strbd-4.png">
</div>
<div class='slides-back slides-nav' onclick='plusDivs(-1)'>
<span><</span>
</div>
<div class='slides-next slides-nav' onclick='plusDivs(1)'>
<span>></span>
</div>
<div class='slides-menu'>
<div class='slides-menu-inner'>
<div class='slides-picker-outer'>
<img class="slides-picker" src="strbd-1.png" onclick="currentDiv(1)">
</div>
<div class='slides-picker-outer'>
<img class="slides-picker" src="strbd-2.png" onclick="currentDiv(2)">
</div>
<div class='slides-picker-outer'>
<img class="slides-picker" src="strbd-3.png" onclick="currentDiv(3)">
</div>
<div class='slides-picker-outer'>
<img class="slides-picker" src="strbd-4.png" onclick="currentDiv(4)">
</div>
</div>
</div>
</div>
JS:
var slideIndex = 1;
showDivs(slideIndex);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function currentDiv(n) {
showDivs(slideIndex = n);
}
function showDivs(n) {
var menuleft = 0;
var x = $(".slides-main");
var i;
var menu = $(".slides-menu");
var dots = $(".slides-picker-outer");
x.hide();
dots.css("opacity","0.2");
if (n > x.length) {slideIndex = 1}
if (n < 1) {slideIndex = x.length}
for (i = 0; i < x.length; i++) {
x.eq(i).fadeOut(200);
}
x.eq(slideIndex-1).fadeIn(200);
dots.eq(slideIndex-1).css("opacity","1.0");
menuleft = dots.eq(slideIndex-1).position().left;
menu.animate({scrollLeft: menuleft},200);
}
This works flawlessly when there is one image slider, but I have several on the same page and all that happens is that all the slider controls only control the first and the rest of the sliders just don't work.
How do I make it so that each image slider gets its own set of JavaScript, and not all conflicting with each other?
I'm new to JavaScript and jQuery and haven't found anything after searching the web. I would appreciate any help.
EDIT:
JSBin - https://jsbin.com/yopoyedaze/edit?html,css,js,output
Only one slider works at a time and they scroll as if they were one large slider and not two separate ones. How to fix it?
source to share
Starting with your JSBin , what I changed is pretty subtle.
I've removed useless functions plusDivs(n)
and currentDiv(n)
.
Adding to is slideIndex
now done within showDivs(n,el)
.
Now you will notice that there is a second argument to the function.
That is, to wrap the element that launches it.
This is the link used to determine which slider is involved in the user's action.
Starting from this element, we find the closest .slides-container
...
And then we can find the corresponding children needed in the function.
So passing a link element is a big trick .
This was your main problem.
var slideIndex = 1;
function showDivs(n,el) {
// Get the right container from the passed element.
var container = el.closest(".slides-container");
// Find the child elements.
var x = container.find(".slides-main");
var menu = container.find(".slides-menu");
var dots = container.find(".slides-picker-outer");
var menuleft = 0;
var i;
// Calculate the new slideIndex.
slideIndex += n;
if (slideIndex > x.length) {slideIndex = 1}
if (slideIndex < 1) {slideIndex = x.length}
// Animate.
x.hide();
dots.css("opacity",0.2);
for (i = 0; i < x.length; i++) {
x.eq(i).fadeOut(200);
}
x.eq(slideIndex-1).fadeIn(200);
dots.eq(slideIndex-1).css("opacity",1);
menuleft = dots.eq(slideIndex-1).position().left;
menu.animate({scrollLeft: menuleft},200);
}
// Click handlers
$(".slides-next").on("click",function(){
showDivs(1,$(this));
});
$(".slides-back").on("click",function(){
showDivs(-1,$(this));
});
$(".slides-picker-outer").on("click",function(){
showDivs($(this).index()+1-slideIndex,$(this));
});
I left you some work ... slideIndex
is common to all sliders.
And this is not very good.
I suggest you store this value in a data attribute in a container.
Something like <div class="slides-container" data-slideIndex="1">
...
You can get it with container.data("slideIndex")
and install it with container.data("slideIndex",newSlideIndex)
.
source to share
This is how you would do it, but not with your slider. Conceptually, this should get you on the right track. This is just one way to think about it. You want each slider to have its own events and closings.
var $box = $('.box');
function toggleBox(boxClass) { // some example 'plugin-like' function
$(boxClass).on('click', function() {
$(this).toggleClass('active');
});
}
toggleBox('.one');
toggleBox('.two');
toggleBox('.three');
.box {
width: 100px;
height: 100px;
border: 1px solid black;
margin: 1rem;
}
.box.active {
background: black;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="box one">box 1</div>
<div class="box two">box 2</div>
<div class="box three">box 3</div>
With that in mind, you can read something like this to make the "plugin" style look more elegant. https://learn.jquery.com/plugins/basic-plugin-creation/
Angle plugin type
(function($, sliderId) { // closure for this 'plugin'
// name of plugin - used as a method on a DOM element
$.fn.initializeSlider = function(options) { // doesnt have options setup... but just to show where they would go
return this.each( function() { // runs a function for each slider - which creates seperate places for all the stuff memory - for each slider in this case
sliderId++; // something to increment so you can name each slider for example
var sliderName = 'Slider-' + sliderId; // just for fun
var $this = $(this); // cache the DOM element/node of 'this' slider so we don't have to keep querying for it...
// cache these nodes
$prev = $this.find('.previous');
$next = $this.find('.next');
// whatever your methods are for a slider
$prev.on('click', function() {
console.log('Slide to previous for ' + sliderName);
});
$next.on('click', function() {
console.log('Slide to next for ' + sliderName);
});
// just showing that multiple instances of this slider are initialized
console.log('You created slider #' + sliderId);
});
}
})(jQuery, 0); // these things at the end are arguments 'passed' in to the larger function... it can feel strange... but it just like any other function
// ourWholeFunction(jQuery, 0);
// think about it like this ^ ... - they take the place of the parameters inside the function.
$('.slider').initializeSlider();
Here's what's in action: https://jsfiddle.net/sheriffderek/ecw95of3/
Check out this repo for a good example: https://github.com/viljamis/ResponsiveSlides.js/blob/master/responsiveslides.js - however jQuery plugins need to have a destroy method and that doesn't.
I actually ... besides learning JavaScript ... you should leave Sliders for the pros. Just use https://flickity.metafizzy.co/
Good luck!
source to share