3

I'm new to JavaScript/JQuery. I'm trying to implement a image slider using only CSS and Jquery. When clicked on one slider's navigation, elements of other slider also starts moving. If i use separate Id for each slider then it works fine, but I don't want to use separate Id for each slider. How I will detect which slider's navigation is clicked and move elements accordingly.

Thanks in advance!!

Here is Demo

<div class="container">
   <div class="row">
      <div class="col-sm-12">
         <div class="outer_pro_layer">
            <div class="presentation">
               <button class="prev" aria-describedby="prevdesc" aria-controls="live">Previous</button>
               <div class="live">
                  <div class="ul">
                     <div class="col-sm-3 li">
                        <div>1</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>2</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>3</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>4</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>5</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>6</div>
                     </div>
                  </div>
               </div>
               <button class="next" aria-describedby="nextdesc" aria-controls="live">Next</button>
            </div>
         </div>
         <div class="outer_pro_layer">
            <div class="presentation">
               <button class="prev" aria-describedby="prevdesc" aria-controls="live">Previous</button>
               <div class="live">
                  <div class="ul">
                     <div class="col-sm-3 li">
                        <div>A</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>B</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>C</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>D</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>E</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>F</div>
                     </div>
                  </div>
               </div>
               <button class="next" aria-describedby="nextdesc" aria-controls="live">Next</button>
            </div>
         </div>
      </div>
   </div>
</div>

CSS

.sr {
     position: absolute;
     clip: rect(1px 1px 1px 1px);
     clip: rect(1px, 1px, 1px, 1px);
     padding: 0;
     border: 0;
     height: 1px;
     width: 1px;
     overflow: hidden;
}
 .ul {
     overflow:hidden;
     height:100px;
}
 .li {
     display: inline-block;
     text-align:center;
     height:100px;
     background:#ccc;
}
 .js #live {
     display:none;
}

Jquery

$(document).ready(function() {
  var slidestash;
  var lastindex = $(".live .ul .li").length - 1;
  var numstashed = 2;

  function setup() {
    $(".live")
      .attr('aria-label', "Rotating list of statistics")
      .attr('aria-live', 'polite')
      .attr('aria-relevant', 'additions')
      .attr('aria-atomic', 'false');
    slidestash = $(".live .ul .li:nth-child(-n+" + numstashed + ")").detach();
  }
  setup();

  $("html").removeClass("js");

  $(".prev").click(function() {

  $(".live .ul").prepend(slidestash);
    slidestash = $(".live .ul .li:nth-child(n+" + lastindex + ")").detach();
    if (!$(this).is(":focus")) $(this).focus(); //iOS hack
  });

  $(".next").click(function() {
    $(".live .ul").append(slidestash);
    slidestash = $(".live .ul .li:nth-child(-n+" + numstashed + ")").detach();
    if (!$(this).is(":focus")) $(this).focus(); //iOS hack
  })
});
3
  • 1
    Possibly not helpful, but why don't you want to use separate IDs for each slider? That seems like a very simple and entirely reasonable solution to the problem, as well as being what the id attribute is for - to enable you to uniquely reference a single element. Commented Mar 30, 2018 at 7:32
  • 1
    "...using only CSS and Jquery" - you made my day! Commented Mar 30, 2018 at 7:33
  • Don't forget to accept the answer you think it's right. We are expecting this from you. Don't just ask and go away. Commented Apr 5, 2018 at 6:09

2 Answers 2

1

What you want to do here is

  1. place all the code for running a slider in a single function
  2. run that function on each of your slider instances
  3. limit the code from one instance to apply inside that element only.

First two points are easy:

1.

 function initSlider(e) {
   ..code here...
 }

2.

 $('presentation').each(function(i,e) {
   initSlider(e);
 })

For 3, you need to pass the instance - $(e) - to all jQuery selectors in your function, as the second param (delimiter), to tell jQuery: "only select inside this element".
For example, $(".live") will become $(".live", $(e)).

Here it is, working:

$(window).on('load', function() {
  $("html").removeClass("js");
  $('.presentation').each(function(i, e) {
    initSlider(e);
  });

  function initSlider(e) {
    var slidestash,
      lastindex = $(".live .ul .li", $(e)).length - 1,
      numstashed = 2;

    function setup() {
      $(".live", $(e))
        .attr('aria-label', "Rotating list of statistics")
        .attr('aria-live', 'polite')
        .attr('aria-relevant', 'additions')
        .attr('aria-atomic', 'false');
      slidestash = $(".live .ul .li:nth-child(-n+" + numstashed + ")", $(e)).detach();
    }
    setup();



    $(".prev", $(e)).click(function() {
      $(".live .ul", $(e)).prepend(slidestash);
      slidestash = $(".live .ul .li:nth-child(n+" + lastindex + ")", $(e)).detach();
      if (!$(this).is(":focus")) $(this).focus(); //iOS hack
    });

    $(".next", $(e)).click(function() {
      $(".live .ul", $(e)).append(slidestash);
      slidestash = $(".live .ul .li:nth-child(-n+" + numstashed + ")", $(e)).detach();
      if (!$(this).is(":focus")) $(this).focus(); //iOS hack
    })
  }
})
.sr {
     position: absolute;
     clip: rect(1px 1px 1px 1px);
     clip: rect(1px, 1px, 1px, 1px);
     padding: 0;
     border: 0;
     height: 1px;
     width: 1px;
     overflow: hidden;
}
 .ul {
     overflow:hidden;
     height:100px;
}
 .li {
     display: inline-block;
     text-align:center;
     height:100px;
     background:#ccc;
}
 .js #live {
     display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>


<div class="container">
   <div class="row">
      <div class="col-sm-12">
         <div class="outer_pro_layer">
            <div class="presentation">
               <button class="prev" aria-describedby="prevdesc" aria-controls="live">Previous</button>
               <div class="live">
                  <div class="ul">
                     <div class="col-sm-3 li">
                        <div>1</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>2</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>3</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>4</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>5</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>6</div>
                     </div>
                  </div>
               </div>
               <button class="next" aria-describedby="nextdesc" aria-controls="live">Next</button>
            </div>
         </div>
         <div class="outer_pro_layer">
            <div class="presentation">
               <button class="prev" aria-describedby="prevdesc" aria-controls="live">Previous</button>
               <div class="live">
                  <div class="ul">
                     <div class="col-sm-3 li">
                        <div>A</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>B</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>C</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>D</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>E</div>
                     </div>
                     <div class="col-sm-3 li">
                        <div>F</div>
                     </div>
                  </div>
               </div>
               <button class="next" aria-describedby="nextdesc" aria-controls="live">Next</button>
            </div>
         </div>
      </div>
   </div>
</div>

As you can see, the JavaScript now works correctly. If you need more help with it, please turn your code into a live snippet, so I can see what I'm doing and how it's supposed to look.

Sign up to request clarification or add additional context in comments.

3 Comments

If I need to stop slider at last element, whats the procedure for this?
You'd need to modify the functions ran on $('.next') and $('.prev') and only execute the code if you're not on last (on next) or on first (on prev). But that should be a separate question. The principle is: I don't only help you, I also help anyone with a similar problem.
Ok...let me check with this. Thanks
1

You are on the right track, but you need to limit the context of the elements. for example, prev button should only affect the slider that the button is contained within.

For this, you can use the .container element as the root of a slider, and search for the elements inside it.

For example:

$(".prev").click(function() {
    var container = $(this).parents(".outer_pro_layer").first();
    // or $(this).closest(".outer_pro_layer") or $(this).parent(".outer_pro_layer")
    container.find(".live .ul").prepend(slidestash);
    slidestash = container.find(".live .ul .li:nth-child(n+"+lastindex+")").detach();
    if (!$(this).is(":focus")) $(this).focus(); //iOS hack
});

1 Comment

Corrected my answer, you should choose .outer_pro_layer or .presentation as the slider container to make this work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.