Alan Shortis
Alan Shortis

Reputation: 1109

Hide visible elements by class name when showing another in jQuery

This should be a nice easy one for someone - I have a table row that slideToggles when an image is clicked. As the table is dynamic, there could be any number of rows so I have had to identify the areas to show/hide by classname.

Not a problem. However, I only ONE instance of the extrainfo div to be shown at once. As one is shown, any already visible should be hidden:

EDIT: Here is a fiddle: http://jsfiddle.net/shpsD/

Added HTML below.

    var toggleSpeed = 300;
    var expandImg = "../Images/expand.png";
    var collapseImg = "../Images/collapse.png";
    $(".moreless").click(function () {
        var detailsRow = $(this).parent().parent().next();
        detailsRow.find('.extrainfo').slideToggle(toggleSpeed);
        if ($(this).attr('src') == collapseImg) {
            $(this).attr('src',expandImg);
            $(this).closest('tr').removeClass('highlight_row');
        }
        else {
            $(this).attr('src',collapseImg);
            $(this).closest('tr').addClass('highlight_row');
        }
    });
});

-

<table>
    <tr>
        <th>Header</th>
        <th></th>
    </tr>
    <tr>
        <td>row 1</td>
        <td><img src="expand.png" class="moreless" /></td>
    </tr>
    <tr>
        <td colspan="2">
            <div class="extrainfo">
                EXTRA INFO!!
            </div>
        </td>
    </tr>    
    <tr>
        <td>row 2</td>
        <td><img src="expand.png" class="moreless" /></td>
    </tr>
    <tr>
        <td colspan="2">
            <div class="extrainfo">
                EXTRA INFO!!
            </div>
        </td>
    </tr>
</table>

Upvotes: 0

Views: 1009

Answers (2)

David Thomas
David Thomas

Reputation: 253308

First hide the elements:

$('table .extrainfo').slideUp();

You could also use the :visible selector, if you want, though it doesn't necessarily make things any faster, but perhaps a little more understandable:

$('table .extrainfo:visible').slideUp();

And then show:

detailsRow.find('.extrainfo').slideDown();

JS Fiddle demo.


Edited with regards to the comment left by the OP (below):

It works fine when switching between rows, but it is not possible to hide all rows, as if only a single row is expanded it slides up and then immediately down. Any ideas?

I'm not sure, this was a pretty quick look once I'd finished work, but I might be over-doing things, but the following seems to work as you'd require:

$(".moreless").click(function() {
    // caching variables:
    var that = $(this),
        table = that.closest('table'),
        row = that.closest('tr'),
        visInfo = table.find('.extrainfo:visible').length,
        extrainfo = row.next().find('.extrainfo');

    // I suspect this conditional is flawed, and redundant,
    // but essentially if there's already a visible element *and*
    // the next '.extrainfo' element in the next row is visible,
    // then we're having to toggle/close
    if (visInfo == 1 && extrainfo.is(':visible')) {
        // we're working on the row that's already visible:
        extrainfo.slideToggle(toggleSpeed);
        row.toggleClass('highlight_row');
    }
    else {
        // not toggling the same table-row, so tidying up previously
        // visible elements (if any)/removing 'highlight_row' class
        // and also setting the src of the image to the expandImg
        var highlighted = table.find('.highlight_row');
        highlighted.find('.moreless').attr('src',expandImg);
        highlighted.removeClass('highlight_row');
        table.find('.extrainfo').slideUp(toggleSpeed);

        // now we're showing stuff/adding the class
        extrainfo.slideDown(toggleSpeed);
        row.addClass('highlight_row');
    }
    // this effectively toggles the src of the clicked image:
    that.attr('src', function(i,v) {
        return v == expandImg ? collapseImg : expandImg;
    });
});​

JS Fiddle demo.

(I'll add references and answer further questions once I've eaten...sorry!)

References:

Upvotes: 4

Caner Akdeniz
Caner Akdeniz

Reputation: 1862

first you can do:

$('.extrainfo').hide();

then once every extrainfo classed ones hide, you can go ahead and do :$(this).closest('.extrainfo').show();

if you know that extrainfo div is right after the link or div you click, you can do:

$(this).next('.extrainfo').show()

Upvotes: 0

Related Questions