jquery - Simplify this javascript for Show one, Hide Rest - Stack Overflow

I am using a script for a gallery in which clicking on an element in the navigation shows only one div,

I am using a script for a gallery in which clicking on an element in the navigation shows only one div, but hides the others.

Currently my script is very specific, as I need to add a new function for every possible instance. See below... You can imagine this grows out of control easily the more images are added.

Can someone help me make this code more generic and elegant? I'm not very experienced with Javascript/JQuery but this is getting a bit embarrassing lol

So in case it's not clear from the code: the #li1, #li2, #li3 etc are the navigational thumbnails which are always visible. The #img1, #img2, #img3 etc. are the variable displayed divs. When one is visible, the rest should be hidden.

Additional questions:

  • for every #img1 displayed, I'd like to also show a title in a separate div, let's say #title1, #title2, etc. How do I do this? So eg clicking #li1 would show #img1 and #title1 but hide all other #img.. and #title..

  • all #'s contain images. I've noticed that when one of the images is broken, the whole script stops working properly (all #img.. divs show at once). Why is that?

  • this script doesn't actually hide all the images until everything is loaded, which you don't notice when running the HTML locally, but you do when you're waiting for the images to download. I'm suspecting because the $("#li1").load(function() refers to a div that is further down in the document. How can I counter this?

I hope I'm not asking too much, I've tried to understand this myself but I can't figure it out.

$("#li1").load(function() {
   $("#img2, #img3, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0, #intro").hide();
   $("#img1").show();
});
$("#li1").on('click', function() {
   $("#img2, #img3, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0").hide();
   $("#img1").show();
});
$("#li2").on('click', function() {
   $("#img1, #img3, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0").hide();
   $("#img2").show();
});
$("#li3").on('click', function() {
   $("#img2, #img1, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0").hide();
   $("#img3").show();
});

etc.

I am using a script for a gallery in which clicking on an element in the navigation shows only one div, but hides the others.

Currently my script is very specific, as I need to add a new function for every possible instance. See below... You can imagine this grows out of control easily the more images are added.

Can someone help me make this code more generic and elegant? I'm not very experienced with Javascript/JQuery but this is getting a bit embarrassing lol

So in case it's not clear from the code: the #li1, #li2, #li3 etc are the navigational thumbnails which are always visible. The #img1, #img2, #img3 etc. are the variable displayed divs. When one is visible, the rest should be hidden.

Additional questions:

  • for every #img1 displayed, I'd like to also show a title in a separate div, let's say #title1, #title2, etc. How do I do this? So eg clicking #li1 would show #img1 and #title1 but hide all other #img.. and #title..

  • all #'s contain images. I've noticed that when one of the images is broken, the whole script stops working properly (all #img.. divs show at once). Why is that?

  • this script doesn't actually hide all the images until everything is loaded, which you don't notice when running the HTML locally, but you do when you're waiting for the images to download. I'm suspecting because the $("#li1").load(function() refers to a div that is further down in the document. How can I counter this?

I hope I'm not asking too much, I've tried to understand this myself but I can't figure it out.

$("#li1").load(function() {
   $("#img2, #img3, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0, #intro").hide();
   $("#img1").show();
});
$("#li1").on('click', function() {
   $("#img2, #img3, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0").hide();
   $("#img1").show();
});
$("#li2").on('click', function() {
   $("#img1, #img3, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0").hide();
   $("#img2").show();
});
$("#li3").on('click', function() {
   $("#img2, #img1, #img4, #img5, #img6, #img7, #img8, #img9, #img10, #img0").hide();
   $("#img3").show();
});

etc.

Share Improve this question asked Sep 24, 2014 at 22:46 Jean CrochetJean Crochet 691 silver badge6 bronze badges 4
  • 1 You should post this question at codereview.stackexchange. – LcSalazar Commented Sep 24, 2014 at 22:48
  • 1 I would add a mon class to all of the items. With one call you can hide all and then show the 1 – Leeish Commented Sep 24, 2014 at 22:49
  • Can you show some HTML sample just to see what are those #li and some parent elements? – Roko C. Buljan Commented Sep 24, 2014 at 22:54
  • Your code snippet is useless without the HTML. – Lee Taylor Commented Sep 24, 2014 at 22:55
Add a ment  | 

8 Answers 8

Reset to default 2

I would probably try something like this:

Thumbnails like:

<li class="thumbnail" data-imageId="0">
  ...thumbnail...
</li>
<li class="thumbnail" data-imageId="1">
  ...thumbnail...
</li>
<li class="thumbnail" data-imageId="2">
  ...thumbnail...
</li>

Images like:

<div class="image" data-imageId="0">
  ...image...
</div>
<div class="image" data-imageId="1" style="display: none;">
  ...image...
</div>
<div class="image" data-imageId="2" style="display: none;">
  ...image...
</div>
<!-- The style attribute in these element hides the element by default,
     while still allowing jQuery to show them using show(). -->

And then the JS:

$(".thumbnail").click(function() {
   // Hides all images.
   $(".image").hide();

   // Shows appropriate one.
   var imageId = $(this).data("imageId"); // Fetches the value of the data-imageId attribute.
   $(".image[data-imageId="+imageId+"]").show();
});

I see that your li's have ids of 'li1', 'li2', etc. Assign them all a specific class, like 'liLinks'.

Then, add an event handler for that class like this:

$(".liLinks").click(function(){    
var ImageToShow = $(this).prop("id").replace("li", ""); // This gets the number of the li

    for (i=0; i<= 10; i++){ //or however many images you have
        if (i != ImageToShow)
            $("#img" + i).hide();
        else
            $("#img" + i).show();
    } 
});

Oh, and you can show and hide any other elements with the same method used above. Just make sure their naming convention is the same, and you should be all set!

So, I have two solutions for you:

First option: Edit the HTML code to fix this logic:

<li class="nav" data-image="0">0</li>
<li class="nav" data-image="1">2</li>
<li class="nav" data-image="2">3</li>
...

...and so on.

Now the JavaScript code will be pretty short and easy, here it is:

function showOne(e) {
    var max = 5, // assuming that there are 5 images, from #img0 to #img4
        toShow = e.target.dataset.image;

    for (var i=0; i < max; i++) {
        if (i == toShow) $('#img'+i).hide();
        else $('#img'+i).show();
    }
}

$('.nav').bind('click', showOne);

If your logic isn't this one then i suggest you to edit the HTML to fix this logic, which is the easiest way to do what you want.


Second option: I am assuming that you use a logic like this:

  • #li0 shows #img0
  • #li1 shows #img1
  • #li2 shows #img2
  • ...
  • #liN shows the Nth img of the array

Here's the code then:

function showOne() {
    var max = 4, // assuming that there are 5 images, from #img0 to #img4
        toShow = this.id.substr(2);


    $('#img'+toShow).show();
    for (var i=0; i < max; i++) {
        if (i != toShow) $('#img'+i).hide();
    }
}

$('#li0, #li1, #li2, #li3, #li4').bind('click', showOne);

In this snippet I only used 5 images, but you can add more images changing the max value and adding the relative li elements in the $('#li0, #li1, ...) selector.

Just hide all of them with CSS, then override the one you care about to show.

<!doctype html>
<html>

  <head>
    <style type="text/css">

      #showbox img { display: none; width: 300px; }

      #showbox.show1 img#img1,
      #showbox.show2 img#img2,
      #showbox.show3 img#img3,
      #showbox.show4 img#img4 { display: block; }

    </style>
  </head>

  <body>

    <div id="showbox" class="3">
      <img id="img1" src="http://upload.wikimedia/wikipedia/mons/6/6f/ChessSet.jpg">
      <img id="img2" src="http://upload.wikimedia/wikipedia/mons/c/c3/Chess_board_opening_staunton.jpg">
      <img id="img3" src="http://www.umbc.edu/studentlife/orgs/chess/images/News%20and%20Events/chess_sets.jpg">
      <img id="img4" src="http://upload.wikimedia/wikipedia/mons/thumb/9/97/Russisches_festungsschach.PNG/350px-Russisches_festungsschach.PNG">
    </div>

    <input onchange="document.getElementById('showbox').className = 'show' + this.value;">

  </body>

</html>

Your images is not hidden while the images is loading because you didn't use $(function () { $("imgs").hide (); }); This function is excuted when the DOM (HTML) is loaded not the images. The code will be "HTML": link1 link2 link3 ...

jQuery: $(function () { $(".img").hide (); $(".nav").click (function (e) { $(".img").show (); }); });

As you might expect you need to change this code to be more progressive but you now get the idea of making them hidden when the page finish liading not when the images finish downloading. And good luck ;) .

var $img = $('#images img'); /* Cache your selector */
$('#nav li').click(function(){
  $img.fadeOut().eq( $(this).index() ).stop().fadeIn();
});
#images{ position:relative; }
#images img{ position:absolute; left:0; }
#images img + img {display:none; } /* hide all but first */
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id=nav>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>

<div id=images>
  <img src="//placehold.it/50x50/cf5" alt="">
  <img src="//placehold.it/50x50/f0f" alt="">
  <img src="//placehold.it/50x50/444" alt="">
</div>

Following is an approach:

  1. Add special classes to identify images.
  2. Use classes to show/hide image like: .showing{display:block;}
  3. Use data attribute to store title like: data-title="title"
  4. Add class to identify li and mark selected li with another class like active

$(function() {
  $("li.switch").click(function() {
    var liActive = $("li.active");
    var imgActive = liActive.data("image");
    $(imgActive).removeClass("showing").addClass("hidden");
    $(liActive).removeClass("active");

    //currently clicked li
    var $this = $(this);
    $this.addClass("active");
    var d = $this.data("image");
    $(d).removeClass("hidden").addClass("showing");
    $("#imgTitle").text($(d).data("title"));
  });
});
.gallery {
  width: 250px;
  height: 250px;
  padding: 10px;
}
img {
  height: 200px;
  width: 200px;
  margin: auto auto;
}
.hidden {
  display: none;
}
.showing {
  display: inline-block;
}
ul {
  list-style: none none outside;
  display: inline;
}
li {
  list-style: none none outside;
  display: inline-block;
  padding: 3px 6px;
  border: 1px solid grey;
  color: #0f0;
  cursor: pointer;
}
li.active {
  border: 2px solid red;
  background-color: #c0c0c0;
  color: #f00;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<div class="gallery">
  <img src='https://c2.staticflickr./4/3862/15320672416_65b28179b4_c.jpg' class='gimage showing' id='img1' data-title="This is image 1" />
  <img src='https://c2.staticflickr./4/3893/15156335390_16e16aa1c9_c.jpg' class='gimage hidden' id='img2' data-title="This is image 2" />
  <img src='https://c1.staticflickr./3/2942/15341799225_09d0f05098_c.jpg' class='gimage hidden' id='img3' data-title="This is image 3" />
  <img src='https://c2.staticflickr./4/3907/15339877992_695dd1daae_c.jpg' class='gimage hidden' id='img4' data-title="This is image 4" />
  <img src='https://farm3.staticflickr./2942/15333547162_325fefd6d1.jpg' class='gimage hidden' id='img5' data-title="This is image 5" />
</div>
<div id="imgTitle"></div>
<ul>
  <li class="switch active" id="li1" data-image="#img1">1</li>
  <li class="switch" id="li1" data-image="#img2">2</li>
  <li class="switch" id="li1" data-image="#img3">3</li>
  <li class="switch" id="li1" data-image="#img4">4</li>
  <li class="switch" id="li1" data-image="#img5">5</li>
</ul>

Try it in this fiddle

Fix from Ricardo van den Broek's code, because

var imageId = $(this).data("imageId");

is seem doesn't work. It's returns "Undefined". So we need to change it to

var imageId = $(this).attr("data-imageId");

Here is all the code,

HTML (Thumbnail section)

<ul>
    <li class="thumbnail" data-imageId="0">
        Thumbnail 0
    </li>
    <li class="thumbnail" data-imageId="1">
        Thumbnail 1
    </li>
    <li class="thumbnail" data-imageId="2">
        Thumbnail 2
    </li>
</ul>

HTML (Image section)

<div class="image" data-imageId="0">
    Image 0
</div>
<div class="image" data-imageId="1" style="display: none;">
    Image 1
</div>
<div class="image" data-imageId="2" style="display: none;">
    Image 2
</div>

JavaScript (jQuery)

$(".thumbnail").click(function() {
    $(".image").hide();

    // Shows the appropriate one.
    var imageId = $(this).attr("data-imageId");

    $(".image[data-imageId="+imageId+"]").show();
});

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745110104a4611796.html

相关推荐

  • jquery - Simplify this javascript for Show one, Hide Rest - Stack Overflow

    I am using a script for a gallery in which clicking on an element in the navigation shows only one div,

    10小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信