简体   繁体   中英

How to use jQuery to change attribute of all elements in a group except one

I have following code that shows a light box for my image gallery. There are three images and I need to allow users to click on any of the images to see the gallery in a lightbox. The issue is that when I click on one image it does not show the selected image rather shows the first image in the list / or last image that user has seen last time that opened the lightbox. DEMO

I have a carousel based on http://kenwheeler.github.io/slick/ in my lightbox, so I need to change the order of the carousel. I noticed the plugin generates tabindex attribute so I am trying to change that to 0 for selected image and -1 for all other images but the code does not work. I included a demo but for some reasons it does not work at all. Please use following code while I am trying to solve the issue with JSFiddle.

To solve the issue with attributes, I had a look at these questions 1 , 2 , 3 but could not figure out how to use it.

<!DOCTYPE html>
<html lang="en">
<head>
  <title>slick - the last carousel you'll ever need</title>
  <link href='http://fonts.googleapis.com/css?family=Lato:400,700' rel='stylesheet' type='text/css'>
  <link rel="stylesheet" type="text/css" href="http://kenwheeler.github.io/slick/slick/slick.css"/>
  <link rel="stylesheet" type="text/css" href="http://kenwheeler.github.io/slick/slick/slick-theme.css"/>
  <link rel="stylesheet" type="text/css" href="http://kenwheeler.github.io/slick/slick/style.css">


  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js" type="text/javascript"></script>
  <style>
#cover-page {
  background: #fff none repeat scroll 0 0;
  margin-left: 15%;
  margin-top: 1%;
  position: absolute;
  width: 70%;
  z-index: 1001;
  visibility:hidden;
}
#black-cover {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: #000;
    filter: alpha(opacity=75);
    -moz-opacity: 0.75;
    -khtml-opacity: 0.75;
    opacity: 0.75;
    z-index: 1000;
    visibility:hidden;
}
#close{
    position:absolute;
    top:0;
    right:0;
      visibility:inherit;
}
.slick-slider {
  margin-left: 12%;
  margin-right: 9%;
}
.slick-slider {
    -moz-user-select: none;
    box-sizing: border-box;
    visibility:hidden;
    position: relative;
}
.slick-slide img {
  border: 5px solid #fff;
  display: block;
  width: 100%;
}
.slick-next {
  right: -66px;
}

.slick-prev {
  left: -66px;
}

#lightboxCloseBtn {
  text-decoration: none;
  color: purple;

}

.slick-slide.slick-current.slick-active{
  left: 0;
  opacity: 1;
  position: relative;
  top: 0;
  width: 25%;
  z-index: 999;
}

</style>
</head>
<body>
        <div id="black-cover"></div>
        <div id="cover-page">
       <div id="close"><a id="lightboxCloseBtn" href="#" onclick="closeBtn();">X</a></div>
        <h2 id="lightboxHeader">Images</h2>
        <div class="slider fade">
        <div class="lightbox-image"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRu3mvhWwEfOLKJrXAXS4qATDZNtx-l04Vhwi3oXr_62Mz5lEZ-"/></div>
          <div class="lightbox-image"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSKGgx0Le2Rwg7-XSWS_EeuGeebpL-PGabrEm9hFLk2llz1MnQY"/></div>
           <div class="lightbox-image"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSMKybiZVNTHLJXR5bukMNmKv3lCHGlkP2muKAfGn0u6VceubqMyQ"/></div>

        </div>
        </div>


        <a onclick="showLightBox('https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRu3mvhWwEfOLKJrXAXS4qATDZNtx-l04Vhwi3oXr_62Mz5lEZ-');" href="#"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRu3mvhWwEfOLKJrXAXS4qATDZNtx-l04Vhwi3oXr_62Mz5lEZ-"/></a>
        <a onclick="showLightBox('https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSKGgx0Le2Rwg7-XSWS_EeuGeebpL-PGabrEm9hFLk2llz1MnQY');" href="#"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSKGgx0Le2Rwg7-XSWS_EeuGeebpL-PGabrEm9hFLk2llz1MnQY"/></a>
         <a onclick="showLightBox('https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSMKybiZVNTHLJXR5bukMNmKv3lCHGlkP2muKAfGn0u6VceubqMyQ');" href="#"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSMKybiZVNTHLJXR5bukMNmKv3lCHGlkP2muKAfGn0u6VceubqMyQ"/></a>

    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
    <script type="text/javascript" src="http://kenwheeler.github.io/slick/slick/slick.js"></script>
    <script type="text/javascript" src="http://kenwheeler.github.io/slick/js/scripts.js"></script>
    <script type="text/javascript" src="http://kenwheeler.github.io/slick/js/prism.js"></script>
    <script type="text/javascript">

    function showLightBox(address){
            $("#black-cover").css("visibility","visible");
            $("#cover-page").css("visibility","visible");
            $(".slick-slider").css("visibility","visible");
            if($('.lightbox-image.slick-slide.slick-current.slick-active > img').attr('src') != address) {
              alert("here 2");
    $('.lightbox-image.slick-slide.slick-current.slick-active > img').parent().attr('tabindex','-1');

        }
        if($('.lightbox-image.slick-slide.slick-current.slick-active > img').attr('src') == address) {
              alert("here 1");
    $('.lightbox-image.slick-slide.slick-current.slick-active > img').parent().attr('tabindex','0');

        } 
      }

        function closeBtn(){
            $("#black-cover").css("visibility","hidden");
            $("#cover-page").css("visibility","hidden");
            $(".slick-slider").css("visibility","hidden");

}

        var disqus_shortname = 'slickcarousel';

        (function() {
            var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
            dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
            (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
        })();
    </script>

</body>
</html>

Following is the code that plugin generates:

<div id="cover-page" style="visibility: visible;">
    <div id="close">
        <a onclick="closeBtn();" href="#" id="lightboxCloseBtn">X</a>
    </div>
    <h2 id="lightboxHeader">Images</h2>
    <div class="slider fade slick-initialized slick-slider" role="toolbar"
        style="visibility: visible;">
        <button role="button" aria-label="Previous"
            class="slick-prev slick-arrow" data-role="none" type="button"
            style="display: block;">Previous</button>
        <div class="slick-list draggable" aria-live="polite">
            <div class="slick-track" style="opacity: 1; width: 3735px;"
                role="listbox">
                <div class="lightbox-image slick-slide slick-current slick-active"
                    data-slick-index="0" aria-hidden="false"
                    style="width: 1245px; position: relative; left: 0px; top: 0px; z-index: 999; opacity: 1;"
                    tabindex="-1" role="option" aria-describedby="slick-slide00">
                    <img
                        src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRu3mvhWwEfOLKJrXAXS4qATDZNtx-l04Vhwi3oXr_62Mz5lEZ-">
                </div>
                <div class="lightbox-image slick-slide" data-slick-index="1"
                    aria-hidden="true"
                    style="width: 1245px; position: relative; left: -1245px; top: 0px; z-index: 998; opacity: 0;"
                    tabindex="-1" role="option" aria-describedby="slick-slide01">
                    <img
                        src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSKGgx0Le2Rwg7-XSWS_EeuGeebpL-PGabrEm9hFLk2llz1MnQY">
                </div>
                <div class="lightbox-image slick-slide" data-slick-index="2"
                    aria-hidden="true"
                    style="width: 1245px; position: relative; left: -2490px; top: 0px; z-index: 998; opacity: 0;"
                    tabindex="-1" role="option" aria-describedby="slick-slide02">
                    <img
                        src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSMKybiZVNTHLJXR5bukMNmKv3lCHGlkP2muKAfGn0u6VceubqMyQ">
                </div>
            </div>
        </div>



        <button role="button" aria-label="Next" class="slick-next slick-arrow"
            data-role="none" type="button" style="display: block;">Next</button>
        <ul class="slick-dots" style="display: block;" role="tablist">
            <li class="slick-active" aria-hidden="false" role="presentation"
                aria-selected="true" aria-controls="navigation00" id="slick-slide00"><button
                    tabindex="0" aria-required="false" role="button" data-role="none"
                    type="button">1</button></li>
            <li aria-hidden="true" role="presentation" aria-selected="false"
                aria-controls="navigation01" id="slick-slide01"><button
                    tabindex="0" aria-required="false" role="button" data-role="none"
                    type="button">2</button></li>
            <li aria-hidden="true" role="presentation" aria-selected="false"
                aria-controls="navigation02" id="slick-slide02"><button
                    tabindex="0" aria-required="false" role="button" data-role="none"
                    type="button">3</button></li>
        </ul>
    </div>
</div>

Your issue is that your Javascript is set to load onload , it works fine if you wrap it in the head (and add jQuery in the demo): http://jsfiddle.net/zwugprj3/3/

This happens, because of a different scope of the scripts, so onclick="..." doesn't have access to your function.

Generally, stop using the onclick attribute!

Use addEventHandler instead. You can still put the URL (your parameter) in your HTML by using a data attribute like: <img src="/small.png" data-large-src="/large.png"> .

Update: Read til the end of Slick's documentation: http://jsfiddle.net/zwugprj3/22/ , there's actually a method you should use to change the slide. Changing internal details of a library directly is almost never a good idea....

Try This

HTML CODE:

<a onclick="showLightBox(0);" href="#"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRu3mvhWwEfOLKJrXAXS4qATDZNtx-l04Vhwi3oXr_62Mz5lEZ-"/></a>
    <a onclick="showLightBox(1);" href="#"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSKGgx0Le2Rwg7-XSWS_EeuGeebpL-PGabrEm9hFLk2llz1MnQY"/></a>
     <a onclick="showLightBox(2);" href="#"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSMKybiZVNTHLJXR5bukMNmKv3lCHGlkP2muKAfGn0u6VceubqMyQ"/></a>



JS CODE:

  function showLightBox(idx){
        $("#black-cover").css("visibility","visible");
        $("#cover-page").css("visibility","visible");
        $(".slick-slider").css("visibility","visible");
        $('.slick-dots li button').eq(idx).trigger('click');

  }

Try this code.

HTML

<div id="black-cover" style="display:none;"></div>
<div id="cover-page" style="display:none;">
        <div id="close">
            <a id="lightboxCloseBtn" href="#" onclick="closeBtn();">X</a>
        </div>
        <h2 id="lightboxHeader">Images</h2>
        <div class="your-class">
            <div>
                <img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRu3mvhWwEfOLKJrXAXS4qATDZNtx-l04Vhwi3oXr_62Mz5lEZ-" />
            </div>
            <div>
                <img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSKGgx0Le2Rwg7-XSWS_EeuGeebpL-PGabrEm9hFLk2llz1MnQY" />
            </div>
            <div>
                <img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSMKybiZVNTHLJXR5bukMNmKv3lCHGlkP2muKAfGn0u6VceubqMyQ" />
            </div>
        </div>
</div>
<a href="#" class="img" data-value="0"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRu3mvhWwEfOLKJrXAXS4qATDZNtx-l04Vhwi3oXr_62Mz5lEZ-"/></a>

<a href="#" class="img" data-value="1"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSKGgx0Le2Rwg7-XSWS_EeuGeebpL-PGabrEm9hFLk2llz1MnQY"/></a>

<a href="#" class="img" data-value="2"><img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSMKybiZVNTHLJXR5bukMNmKv3lCHGlkP2muKAfGn0u6VceubqMyQ"/></a>

JS

$(document).ready(function () {
    $('.img').click(function () {
        var CurrentImg = $(this).attr('data-value')
        $("#black-cover").show()
        $("#cover-page").show()
        $('.your-class').slick({
            slidesToShow: 1,
            slidesToScroll: 1,
            initialSlide: CurrentImg
        });
    })
})

function closeBtn() {
    $("#black-cover").hide()
    $("#cover-page").hide()
    $('.your-class').slick('unslick');
}

Demo

It seems that there is a specific parameter called initialSlide (default:0) you can use just for that. Just pass the index of the image that was clicked and you're all set.

As mentioned in the documentation , the parameter initial slide can only be used when initiating the carousel, so as a workaround if you want to decide which image should be focused only when it's clicked, you can initiate the carousel when one of your images is clicked, and when the user closes the carousel, you should destroy it using the unslick parameter like so:

$('.your-slider').slick('unslick');

And then if he clicks on some other image, just re-initiate the carousel with the correct initialSlide parameter.

Look at the documentation: http://kenwheeler.github.io/slick/

When a user clicks the image you should construct the slick slider with the relevant image. You can do so by injecting the image's index to a function holding the slick slider constructor:

function startSlider (index) {
  // put here all the css visibility you did
  $('.your-sliders-class').slick({
    initialSlide: index      // the first slide's index is 0, second is 1...
  })
}

So your onclick function will look like:

for the first image - onclick="startSlider(0)"

for the second image - onclick="startSlider(1)"

and so on...

In addition, you should destroy the slider when user closes the lightbox, so the next time he clicks an image the lightbox will construct with the right initial slide:

function closeBtn(){
   $("#black-cover").css("visibility","hidden");
   $("#cover-page").css("visibility","hidden");
   $(".slick-slider").css("visibility","hidden");
   $('.your-sliders-class').slick('unslick');
}

Your attempt to change the order will not work due to the way the slider is implemented. I have solved the inherent problem by displaying the image you clicked on by default.

  function showLightBox(address){
            $("#black-cover").css("visibility","visible");
            $("#cover-page").css("visibility","visible");
            $(".slick-slider").css("visibility","visible");
            //slick-dots
            var index = $('.lightbox-image.slick-slide > img[src="' + address + '"]').parent().index();
            $('ul.slick-dots > li').eq(index).find('button').click();
      }

        function closeBtn(){
            $("#black-cover").css("visibility","hidden");
            $("#cover-page").css("visibility","hidden");
            $(".slick-slider").css("visibility","hidden");

}

^^ That is the modified javascript from your jsFiddle
My jsFiddle can be viewed here http://jsfiddle.net/q6t8v3zf/1/

looking the Github of slick, i see many issues with the same problem 1 , 2 ....
initialSlide must work but in this issues you can see many examples of workarrounds to solve the problem.This configuration of slick must work.

 $('.my-slider').slick({
        dots: true,
        infinite: true,
        slidesToShow: 4,
        slidesToScroll: 3,
        initialSlide: 2
    });

According your question I feel that you want to manually handle the situation, by changing the index for all the other images to -1 and then set the current selected one, is that correcT? if thats the case let me know I will help you fixing it.

Instead of experimenting with the tabindex attribute, I would instruct the Slick to start showing the images with the selected slide. There is a method called slickGoTo(..) that can be used to do so:

slickGoTo( index : int, dontAnimate : bool) Goes to slide by index, skipping animation if second parameter is set to true

Thus your function would look like:

function showLightBox(address){
    $("#black-cover").css("visibility","visible");
    $("#cover-page").css("visibility","visible");
    $(".slick-slider").css("visibility","visible");

    // find the image with the same address
    var index = 0;
    var notFound = true;

    $('.lightbox-image > img').each( function() {
      var sameAddress = $(this).attr('src') == address ;
      if (notFound && !sameAddress) index++;
      else notFound = false;
    });

    // Set initial slide
    $('.slick-slider').slick('slickGoTo', index, true);
}

See jsfiddle

Two points.
(1) tabIndex is used to set the tab sequence, generally in a form, so that the tab key knows how to navigate from element to element. It does not move a DOM element automatically to the foreground. What you're trying to accomplish is to have the generated carousel 'jump' to the image selected from the main page.
(2) Since you're using slick, you want to use the "initialSlide" parameter on load to tell slick which (of your three) slides to start with.
From their documentation, you would set this when you activate a slide by executing a function like:

$(document).ready(function(){
  $('.your-class').slick({
  initialSlide: 1
  });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM