0

I have a table which is populated with details of jobs a user is looking for. The structure is akin to this:

<div class="container">
    <table class="table-responsive table-hover table-bordered col-sm-12 col-md-6 col-md-offset-1 col-lg-6 col-lg-offset-1" id="resultsTable" border="0" cellspacing="0" cellpadding="0"><tbody>
        <tr class="selectable selected">
            <td class="summary">A Summary</td>
        </tr>
        <tr>
            <td class="detail" id="32113607" style="display: table-cell;">This is some detail</td>
        </tr>
<!-- And so on ....................... -->
    </tbody></table>
</div>

I then have a function that handles the expand and retraction of the table rows.

$(function () {

    //When clicking a row in the table, hide the other rows...
    $("#resultsTable").on('click', '.selectable', function (e) {
        $(this).addClass('selected').siblings().removeClass('selected');
        $(this).siblings().children("td.detail").slideUp();

        $(this).next("tr").children("td.detail").slideDown();
    });
});

There's also some basic CSS, but nothing major. This is all in a fiddle here: http://jsfiddle.net/v9ec3/1176/

The strange thing is, if you start at the bottom and work upwards, it doesn't have any problems. If you start at the top and work down, it will jump partway through one of the records.

Having stepped through this in the dev tools, it looks like jQuery is trying to help in moving to offset the slide.

I have tried:

  • e.preventDefault()
  • e.stopPropogation()
  • setting width/height
  • setting overflow-y
  • animations (i.e. going to id x)
  • CSS transitions
j08691
  • 204,283
  • 31
  • 260
  • 272
Reisclef
  • 2,056
  • 1
  • 22
  • 25
  • It only jumps around when you scroll past an opened one and open the next. This is of course expected, because the page is maintaining the current scroll position and you've done nothing to modify it. From the bottom it works because, again, it's maintaining the current scroll position, which is the bottom. – Kevin B May 01 '17 at 15:51
  • @KevinB Yes, I did consider that. I can see why it would try and work that way. I did try and use the id to move the page there, but maybe my timing was conflicting with the slideUp and slideDown. As you mentioned the current scroll position, what else can I do? Could I get the height pre-slideUp, and the adjust the scroll by x pixels? Or am I just missing something painfully obvious? – Reisclef May 01 '17 at 15:59
  • 1
    something like this: http://stackoverflow.com/questions/10836428/how-to-maintain-page-scroll-position-after-a-jquery-event-is-carried-out You'll have to decide though what to base your new scroll position on, whether it be the height of the content you're hiding or a previous scroll position. What complicates it further is that you're also showing more content. – Kevin B May 01 '17 at 16:01
  • @KevinB . Thank you very much for the recommendation. I must admit I'd not seen that. I'd seen scrollTop's getter used for an animation, but not the setter. I'll post an answer to my question as it's now working. Wish I could give rep for comments. :) – Reisclef May 01 '17 at 18:45

1 Answers1

0

Thanks to Kevin B's link (which I hadn't found previously), I was able to work out what was required to keep the elements in place:

$("#resultsTable").on('click', '.selectable', function (e) {

        var prevSelectedHeight = $(".selectable.selected ").next("tr").height();
        var currentScrollTop = $(window).scrollTop();

        $(this).addClass('selected').siblings().removeClass('selected');
        $(this).siblings().children("td.detail").hide();

        if (currentScrollTop > prevSelectedHeight) {
            $(window).scrollTop(currentScrollTop - prevSelectedHeight)
        }
        $(this).next("tr").children("td.detail").slideDown();
});

This now works for most cases. There are a few edge cases where the page is scrolled to the bottom, and the elements shuffle upwards. However, for the vast majority of items in the list, it is working well.

Reisclef
  • 2,056
  • 1
  • 22
  • 25