Steve D.
Steve D.

Reputation: 316

Problems implementing "Show/Hide" buttons for panel feature in jQuery?

enter image description hereI am making a blogging site. In this page, I want it to have several blog entries, and I want the user to be able to press the "Show" button to slide the panel down down and show the specific blog entry. Afterwards, the button will be changed using jQuery to say "Hide". Then, if the user clicks on the "Hide" button, the blog entry will slide up and be hidden again. Several blog entries should be able to be displayed (or hidden) at the same time.

This is a snippet of my code: stories.html

            <div style="width:100%;">
                <div class="panel-header" rel="blog-panel1">
                    <h2>Blog Title #1</h2>
                    <button type="button">Show</button>
                    <h4>Date #1</h4>
                </div>
                <div class="panel" id="blog-panel1" >
                    <p>Some Paragraph #1</p>
                </div>
                <div class="panel-header" rel="blog-panel2">
                    <h2>Blog Title #2</h2>
                    <button type="button">Show</button>
                    <h4>Date #2</h4>
                </div>
                <div class="panel" id="blog-panel2">
                    <p>Some Paragraph #2</p>
                </div>
            </div>

main.js

$(function () {
    $(".panel-header button:contains('Show')").on("click", function() {
        //show
        $(this).text("Hide");

        var panelToShow = $(this).parent().attr('rel');

        $('#'+panelToShow).slideDown(300, function() {
            $(this).addClass('active');
        });
        //hide
        $(".panel-header button:contains('Hide')").on("click", function() {
            $(this).text("Show");

            var panelToHide = $(this).parent().attr('rel');

            $('#'+panelToHide).slideUp(300, function() {
                $(this).removeClass('active');
        });
    });
});

In my main.css file, .panel is set display: none and .panel.active is set display: block.

I've already tried putting the hide portion of the JavaScript outside of the callback. But, it did not work (i.e. it was only able to show the blog entry but unable to hide it back).

For this one, it was able to show and hide the blog entry, but only once. Afterwards, it starts doing some weird stuff. It slides down then immediately slides back up after I click the "Show" button.

Any kind of help is greatly appreciated!

EDIT I found the solution. I'm still not sure why the above is wrong, or why putting the hide portion outside of the script is wrong (I'm new to JS/jQuery) If anyone could still explain it to me, that'd be great. But this code below works. I just added a simple if/else statement.

$(".panel-header button").on("click", function() {
        if ($(this).text() == "Show") {
            $(this).text("Hide");

            var panelToShow = $(this).parent().attr('rel');

            $('#'+panelToShow).slideDown(300, function() {
                $(this).addClass('active');
            });
        }
        else {
            $(this).text("Show");

            var panelToHide = $(this).parent().attr('rel');

            $('#'+panelToHide).slideUp(300, function() {
                $(this).removeClass('active');
            });
        }

    });

Upvotes: 1

Views: 1456

Answers (2)

Pablo Igarz&#225;bal
Pablo Igarz&#225;bal

Reputation: 140

The first version of your code was too complex for its own good. Also you had the Hide functionality inside the Show functionality.

I tried to make a simplier version of your code. Check it out:

$(".panel-header button").on("click", function() {
	// We'll save this jQuery selection on a variable
	// since we'll use it more than once.
  // This helps the performance of our script,
  // because jQuery will only look for the element once.
	var $this = $(this);
  
  // This is a ternary if. Just like a regular if but smaller.
  // Perfect to assign different values to the same variable
  // in different situations
	var btnText = ($this.text() === 'Show') ? 'Hide' : 'Show';

	$this
  	.text(btnText)
  	.parent()
    .next('.panel')
    .slideToggle();
});
.container {
  width: 100%;
}

h2,
h4 {
  margin: 5px;  
}

.panel-header {
  background: grey;
}

.panel-header {
  background: grey;
  margin-bottom: 10px;
  overflow: hidden;
}

.panel-header h2 {
  float: left;
}

.panel-header h4,
.panel-header button{
  float: right;
}

.panel-header h2 {
  float: left;
}

.panel {
  display: none;
}

.panel p {
  margin: 0;
  padding: 0 10px 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="panel-header">
    <h2>Blog Title #1</h2>
    <button type="button">Show</button>
    <h4>Date #1</h4>
  </div>
  <div class="panel">
    <p>Some Paragraph #1</p>
  </div>
  <div class="panel-header">
    <h2>Blog Title #2</h2>
    <button type="button">Show</button>
    <h4>Date #2</h4>
  </div>
  <div class="panel">
    <p>Some Paragraph #2</p>
  </div>
</div>

Upvotes: 1

j-printemps
j-printemps

Reputation: 1298

Here a possible way to do an accordion. I use toggleClass and set max-height with an "active" class. And the animation is in CSS.

$('.panel-header').click(function(){
  $(this).parent().toggleClass('active');
});
.panel {
  margin-bottom: 30px;
}

.panel-content {
  max-height: 0;
  overflow: hidden;
  transition: all 1s ease-in-out;
}

.active .panel-content {
  max-height: 1000px;
  transition: all 1s ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul style="width:100%;">
  <li class="panel" rel="blog-panel1">
    <div class="panel-header">
      <h2>Blog Title #1</h2>
      <button class="button" type="button">Show</button>
      <h4>Date #1</h4>
    </div>
		
		<div class="panel-content" id="blog-panel1" >
	    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam</p>
	  </div>
  </li>

  <li class="panel" rel="blog-panel2">
    <div class="panel-header">
      <h2>Blog Title #2</h2>
      <button class="button" type="button">Show</button>
      <h4>Date #2</h4>
    </div>

		<div class="panel-content" id="blog-panel2">
	    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam</p>
	  </div>
  </li>
</ul>

Upvotes: 0

Related Questions