Reputation: 4610
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
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
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);
});
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
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>
References:
Upvotes: 1
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
Reputation: 8695
// 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
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