Valip
Valip

Reputation: 4610

How to Show/Hide multiple divs

I know that this question has been asked many times before, but I can't find a solution excepting of hard-coding the jQuery file... So, I have to show a description when user presses a button and there are multiple descriptions, each with their buttons.

This is what I've done so far...

HTML:

<div id="trDest1" class="trDest">
    <!-- Some content here -->
    <button class="expandArrow">Show</button>
    <button class="closeArrow">Hide</button>
</div>
<div id="trDest1_details" class="details">
    <p>show details</p>
</div>

<div id="trDest2" class="trDest">
    <!-- Some content here -->
    <button class="expandArrow">Show</button>
    <button class="closeArrow">Hide</button>
</div>
<div id="trDest2_details" class="details">
    <p>show details</p>
</div>

<div id="trDest3" class="trDest">
    <!-- Some content here -->
    <button class="expandArrow">Show</button>
    <button class="closeArrow">Hide</button>
</div>
<div id="trDest3_details" class="details">
    <p>show details</p>
</div>

CSS:

.closeArrow {
  display: none;
}

.visible-description .expandArrow {
  display: none;
}

.visible-description .closeArrow {
  display: inline;
}

.visible-description + .trip_details {
  display: block;
}

.details {
    display: none;
}

jQuery:

  // Show/hide Descriptions
  $('#trDest1 .expandArrow').click(function(){
    $('#trDest1').addClass('visible-description');
    $('#trDest1_details').show();
  });

  $('#trDest1 .closeArrow').click(function(){
    $('#trDest1').removeClass('visible-description');
    $('#trDest1_details').hide();
  });

  // Show/hide Descriptions
  $('#trDest2 .expandArrow').click(function(){
    $('#trDest2').addClass('visible-description');
    $('#trDest2_details').show();
  });

  $('#trDest2 .closeArrow').click(function(){
    $('#trDest2').removeClass('visible-description');
    $('#trDest2_details').hide();
  });

  // Show/hide Descriptions
  $('#trDest3 .expandArrow').click(function(){
    $('#trDest3').addClass('visible-description');
    $('#trDest3_details').show();
  });

  $('#trDest3 .closeArrow').click(function(){
    $('#trDest3').removeClass('visible-description');
    $('#trDest3_details').hide();
  });

As you can see, I wrote a function for each of those divs and I'm wondering if there is another way to clean these functions and add only a function which can do the same...

I can't change the structure of the HTML code.

jsfiddle : https://jsfiddle.net/q84Lnw0y/

Upvotes: 2

Views: 1932

Answers (6)

Marco Magrini
Marco Magrini

Reputation: 749

This should do what you want

$('.trDest button').on('click', function() {
    var myButton = $(this),
        trDest = myButton.parent(),
        detailsId = $('#' + trDest.attr('id') + '_details');

    trDest.toggleClass('visible-description');
    myButton.hasClass('expandArrow') ? detailsId.show() : detailsId.hide();
});

Fiddle here: http://jsfiddle.net/orysrvb2/1/

Upvotes: 1

A. Wolff
A. Wolff

Reputation: 74420

You could use following snippet to target relevant elements:

$('.expandArrow, .hideArrow').on('click', function(){
    var isExpand = $(this).hasClass('expandArrow');
    $(this).closest('.trDest').toggleClass('visible-description', isExpand).next().toggle(isExpand);
});

-jsFiddle

Description:

$(this).closest('.trDest') // Get closest ancestor with class trDest
    .toggleClass('visible-description', isExpand) // Add class `visible-description` if second param `isExpand` is true, else remove class
    .next() // Get immediate next sibling element
    .toggle(isExpand); // Show if `isExpand` is true, else hide it

Upvotes: 4

David Thomas
David Thomas

Reputation: 253308

I'd personally suggest the following:

// delegating the .trDest elements to detect the 'click' events on
// the descendent elements ('.expandArrow, .hideArrow'):
$('.trDest').on('click', '.expandArrow, .hideArrow', function (e) {

    // a reference to the clicked element:
    var arrow = $(this),

        // a reference to the element you want to affect:
        nextDetails = arrow.closest('div').next('.details');

    // checking that the clicked button has the class of
    // 'expandArrow':
    if (arrow.is('.expandArrow')) {

        // it is, we find all the '.details' elements,
        // that are not the the element to affect,
        // and slide them up (hide() could be used,
        // but slideUp() is often less visually jarring):
        $('.details').not(nextDetails).slideUp();

        // then we slideDown() the element we wish to show
        // (if it's already visible then nothing happens):
        nextDetails.slideDown();

    // otherwise the element (because of the restrictions
    // in the selector for the on() method) must be
    // .hideArrow, in which case we hide the
    // nextDetails element by sliding it up:
    } else {
        nextDetails.slideUp();
    }

// here we now look for the descendant '.hideArrow'
// elements and trigger the click event in order that
// that the 'nextDetails' elements are hidden on page-load:
}).find('.hideArrow').click();

$('.trDest').on('click', '.expandArrow, .hideArrow', function(e) {
  var arrow = $(this),
    nextDetails = arrow.closest('div').next('.details');

  if (arrow.is('.expandArrow')) {
    $('.details').not(nextDetails).slideUp();
    nextDetails.slideDown();
  } else {
    nextDetails.slideUp();
  }
}).find('.hideArrow').click();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="trDest1" class="trDest">
  <!-- Some content here -->
  <button class="expandArrow">Show</button>
  <button class="hideArrow">Hide</button>
</div>
<div id="trDest2_details" class="details">
  <p>show details</p>
</div>
<div id="trDest2" class="trDest">
  <!-- Some content here -->
  <button class="expandArrow">Show</button>
  <button class="hideArrow">Hide</button>
</div>
<div id="trDest2_details" class="details">
  <p>show details</p>
</div>
<div id="trDest3" class="trDest">
  <!-- Some content here -->
  <button class="expandArrow">Show</button>
  <button class="hideArrow">Hide</button>
</div>
<div id="trDest2_details" class="details">
  <p>show details</p>
</div>

JS Fiddle demo.

References:

Upvotes: 1

Dhyey Shah
Dhyey Shah

Reputation: 232

one of the ways:

var numberDiv = 3;
for(var i=0; i < 4; i++){
  $('#trDest' + i + ' .expandArrow').i = i;
  $('#trDest' + i + ' .closeArrow').i = i;

  $('#trDest' + i + ' .expandArrow').click(function(){
    $('#trDest'+this.i).addClass('visible-description');
    $('#trDest'+this.i+' _details').show();
  });

  $('#trDest' + i + ' .closeArrow').click(function(){
    $('#trDest' + this.i).removeClass('visible-description');
    $('#trDest'+ this.i +' _details').hide();
  });
}

See if this helps

Upvotes: 0

Alex
Alex

Reputation: 8695

Jsfiddle

  // Show/hide Descriptions
  $('.trDest .expandArrow').click(function() {
    $(this).parent().next().removeClass('hidden');
  });

  $('.trDest .hideArrow').click(function() {
    $(this).parent().next().addClass('hidden');
  });
.hidden {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="trDest1" class="trDest">
  <!-- Some content here -->
  <button class="expandArrow">Show</button>
  <button class="hideArrow">Hide</button>
</div>
<div id="trDest2_details" class="details">
  <p>show details</p>
</div>

<div id="trDest2" class="trDest">
  <!-- Some content here -->
  <button class="expandArrow">Show</button>
  <button class="hideArrow">Hide</button>
</div>
<div id="trDest2_details" class="details">
  <p>show details</p>
</div>

<div id="trDest3" class="trDest">
  <!-- Some content here -->
  <button class="expandArrow">Show</button>
  <button class="hideArrow">Hide</button>
</div>
<div id="trDest2_details" class="details">
  <p>show details</p>
</div>

Upvotes: 0

Arg0n
Arg0n

Reputation: 8423

If you can't change your HTML, maybe something like this will work:

JavaScript

$('.expandArrow').click(function(){
    var parent = $(this).parent();
    parent.addClass('visible-description');
    parent.next('.details').show();
    parent.find(".hideArrow").show();
});

$('.hideArrow').click(function(){
    var parent = $(this).parent();
    parent.removeClass('visible-description');
    parent.next('.details').hide();
    parent.find(".hideArrow").hide();
});

Upvotes: 0

Related Questions