1
\$\begingroup\$

I am working towards a script that will show a set small thumbnail images on one side of the page, that when clicked will show a larger version of the same image, plus related text content on the other side of the page. I am not very good with JavaScript yet and wonder if the <script> section here is fussier than necessary to accomplish this. It does seem to work. But can the script/code be simpler to accomplish this? Should I use "id" or "class" for each item?

<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <script>
            $(document).ready(function() {
                $("p").hide();
                $("p.default").show();
                /*$("p.one").show();*/ /*this would probably be default*/
                $(".btn1").click(function() {
                    $("p").hide();
                    $(".one").show();
                });
                $(".btn2").click(function() {
                    $("p").hide();
                    $(".two").show();
                });
                $(".btn3").click(function() {
                    $("p").hide();
                    $(".three").show();
                });
            });
        </script>
    </head>
    <body>
        <div class="btn1">Show1</div>
        <div class="btn2">Show2</div>
        <div class="btn3">Show3</div>  

        <p class="default">This is default content.</p>
        <p class="one">This is content 1.</p>
        <p class="two">This is content 2.</p>
        <p class="three">This is content 3.</p>

    </body>
</html>

Also, my overall goal is to use this with a page that shows, say 20-30 clickable thumbnails/small images, that when clicked will reveal a couple of text paragraphs and multiple (maybe 25) larger images that relate to the clicked thumbnail. I believe I understand that all of that will be loaded/hidden when the page first loads. Does that sound like too much? Is it likely to be a slow page?

(I posted this exact same thing at phpbuilders...but it looks like a lot more JavaScript stuff goes on here.)

\$\endgroup\$

migrated from stackoverflow.com Oct 2 '14 at 19:46

This question came from our site for professional and enthusiast programmers.

  • \$\begingroup\$ you can do all the click handlers in one function using a table like {btn1:"one", btn3:"three"} \$\endgroup\$ – dandavis Sep 10 '14 at 1:53
  • \$\begingroup\$ A little indentation could help \$\endgroup\$ – Bergi Sep 10 '14 at 1:54
1
\$\begingroup\$

Yes, it's too complex. Make the elements relate to each other, so that you can use a single event handler. This is the typical pattern used to link two DOM elements together, so that one can hide/show/otherwise interact with the other.

<a href="#one">Show1</a>
<a href="#two">Show2</a>
<a href="#three">Show3</a>

<p class="default">This is default content.</p>
<p id="one">This is content 1.</p>
<p id="two">This is content 2.</p>
<p id="three">This is content 3.</p>

And:

$('a').click(function (event) {
  event.preventDefault();
  $('p').hide();
  $($(this).attr('href')).show();
});
\$\endgroup\$
  • \$\begingroup\$ Thank you! There are a few concepts in your $ section that I don't know yet. Will try to have a go at using them tomorrow. \$\endgroup\$ – phc_joe Sep 10 '14 at 2:03
  • \$\begingroup\$ I am not understanding this line: "<p id="one" lass="one">This is content 1.</p>" Did you mean "class" and can/should I use both id and class at the same place? \$\endgroup\$ – phc_joe Sep 10 '14 at 2:05
  • \$\begingroup\$ That was a typo. \$\endgroup\$ – meagar Sep 10 '14 at 2:07
  • \$\begingroup\$ Thanks for getting back to me about that. I am so green in javascript, I'll believe anything. Even typos! \$\endgroup\$ – phc_joe Sep 10 '14 at 2:17
  • \$\begingroup\$ How about just $(this.href).show(); \$\endgroup\$ – Derek 朕會功夫 Sep 10 '14 at 2:56
1
\$\begingroup\$

You can have the div classes to be the same and having an attribute that contains the class to show like this:

<div class="btn" data-show="one">Show1</div>
<div class="btn" data-show="two">Show2</div>
<div class="btn" data-show = "three">Show3</div>

And now can have only one function to achieve the goal. Something like this:

$(document).on('click','.btn',function() {
   var show = $(this).attr('data-show');
   $("p").hide();
   $("."+show).show();
});  

Ooooooo....K! Now I get it!

 $(document).ready(function () {   
    $(document).on('click','.btn',function() {
       var show = $(this).attr('data-show');
       $("p").hide();
       $("."+show).show();
    });
$("p").hide();    
$(".default").show();
});

...then do the buttons and content paragraphs like this...

<div class="btn" data-show="one">Show1</div>
<div class="btn" data-show="two">Show2</div>
<div class="btn" data-show="three">Show3</div>

<p class="default">Content default.</p>
<p class="one">Content 1.</p>
<p class="two">Content 2.</p>
<p class="three">Content 3.</p>

BUT Now I would rather have the content in divs rather than paragraphs (so I can format the display and include images, etc.) how would I change $("p").hide(); to $("div").hide(); that would not make all my other divs disappear?

\$\endgroup\$
  • 3
    \$\begingroup\$ Don't invent attributes, use existing ones, or use data- attriutes. \$\endgroup\$ – meagar Sep 10 '14 at 1:57
  • \$\begingroup\$ Wow. I was thinking there must be a way to eliminate all the redundancies in the code. I will give this a try. Thanks! \$\endgroup\$ – phc_joe Sep 10 '14 at 1:59
  • 1
    \$\begingroup\$ instead of $(this).attr('data-show') you can go $(this).data('show') \$\endgroup\$ – jasonscript Sep 10 '14 at 2:42
  • \$\begingroup\$ Okay! I have been making some progress with these suggestions. But I have one more: How do I make the FIRST (default) element visible when the page loads? What do I need to add to the following script to make that happen? $(document).on('click','.btn',function() { var show = $(this).data('show'); $("p").hide(); $("."+show).show(); }); \$\endgroup\$ – phc_joe Sep 10 '14 at 15:58
  • \$\begingroup\$ You can do a .show() on the $(document).ready function for the default element that you want to make visible \$\endgroup\$ – V31 Sep 10 '14 at 18:05
0
\$\begingroup\$

Someone at phpbuilder.com also responded to my original question (posted there) and came up with a somewhat different method. I worked with it a bit this morning (and messed with it a bit for my own edification).

    <style type="text/css">
        /* SYNTAX NOTE: there must be a space between "#displays" and ".hidden" */
        #displays .hidden { /* if any of the items in the id group "displays" group has  the class "hidden", it will not be displayed*/
            display: none;
        }
        #buttons{width: 50%; float: left;}
        #displays{width: 50%; float: left;}
    </style>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
        $(document).ready(function () {
            window.$ViewItem = $('#displays .default'); //displays the div <p class="default">This is default content.</p>
            $('#buttons').on('click', 'div', function (e) {
                var $el = $('#displays .' + e.target.className);
                // .children looks for direct descendants only
                /* $el.removeClass('hidden');  ERROR: THIS LINE SHOULD BE MOVED ONE LOWER*/
                window.$ViewItem.addClass('hidden');  /* whatever WAS being shown gets the "hidden" put back on so that it will disapear*/
                $el.removeClass('hidden');   /*click button & "hidden" class is taken off of any display items, so that they will be displayed*/
                window.$ViewItem = $el;
            }); /*closes the #buttons function*/
        }); /*closes $(document).ready*/
</script> 

<div id="displays">
    <p class="default">This is default content. in a p</p>
    <div class="default">This is default content. in a div</div>
    <p class="one hidden">This is content 1.</p>
    <p class="one hidden">This is more of content 1.</p>
    <p class="two hidden">This is content 2.</p>
    <p class="two hidden">This is more of content 2.</p>    
    <p class="three hidden">This is content 3.</p>
    <div class="three hidden">This is content 3. in a div<div>content in a nested div within 3<br /><img src="archive/imapic.png" /></div></div>
</div>
<div id="buttons">
    <div class="one">Show 1</div>
    <div class="two">Show 2</div>
    <div class="three">Show 3</div>
</div>

This does work and accomplishes everything (and then some) noted in the original question. But I would have never come up with any of it myself. Perhaps it will be of use to someone else.

\$\endgroup\$
  • \$\begingroup\$ I think I am going to go with this solution simply because it is more flexible and I seem to be able to understand it conceptually: it seems easier to display multiple contents of different types (ie a mix of things like Ps and DIVs, etc. that can simply be given the same class name (ie. class="X hidden") which should help me with the overall page layout I am trying for at this point. The other solutions also work and would probably be better choices in other contexts. Thanks to everyone who has helped me here. I learned a lot! \$\endgroup\$ – phc_joe Sep 12 '14 at 16:17
  • \$\begingroup\$ Ooops! Found a problem, the following lines in the script should be reversed: if not re-clicking the same button will make the display disappear...which will be confusing for visitors /* .children looks for direct descendants only */ window.$ViewItem.addClass('hidden'); $el.removeClass('hidden'); \$\endgroup\$ – phc_joe Sep 15 '14 at 19:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy