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.)
-
\$\begingroup\$ you can do all the click handlers in one function using a table like {btn1:"one", btn3:"three"} \$\endgroup\$dandavis– dandavis2014年09月10日 01:53:46 +00:00Commented Sep 10, 2014 at 1:53
-
\$\begingroup\$ A little indentation could help \$\endgroup\$Bergi– Bergi2014年09月10日 01:54:58 +00:00Commented Sep 10, 2014 at 1:54
3 Answers 3
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();
});
-
\$\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– phc_joe2014年09月10日 02:03:18 +00:00Commented Sep 10, 2014 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– phc_joe2014年09月10日 02:05:52 +00:00Commented Sep 10, 2014 at 2:05
-
\$\begingroup\$ That was a typo. \$\endgroup\$user229044– user2290442014年09月10日 02:07:17 +00:00Commented Sep 10, 2014 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– phc_joe2014年09月10日 02:17:11 +00:00Commented Sep 10, 2014 at 2:17
-
\$\begingroup\$ How about just
$(this.href).show();
\$\endgroup\$Derek 朕會功夫– Derek 朕會功夫2014年09月10日 02:56:31 +00:00Commented Sep 10, 2014 at 2:56
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?
-
3\$\begingroup\$ Don't invent attributes, use existing ones, or use
data-
attriutes. \$\endgroup\$user229044– user2290442014年09月10日 01:57:34 +00:00Commented Sep 10, 2014 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– phc_joe2014年09月10日 01:59:40 +00:00Commented Sep 10, 2014 at 1:59
-
1\$\begingroup\$ instead of
$(this).attr('data-show')
you can go$(this).data('show')
\$\endgroup\$jasonscript– jasonscript2014年09月10日 02:42:08 +00:00Commented Sep 10, 2014 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– phc_joe2014年09月10日 15:58:33 +00:00Commented Sep 10, 2014 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– V312014年09月10日 18:05:55 +00:00Commented Sep 10, 2014 at 18:05
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>
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.<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>
-
\$\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– phc_joe2014年09月12日 16:17:32 +00:00Commented Sep 12, 2014 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– phc_joe2014年09月15日 19:41:21 +00:00Commented Sep 15, 2014 at 19:41