-1

I have a table with quite a few rows. And some jquery to expand collapse the rows. However it appears to start ok and then after a short while I find that the animation is jerky, jumpy.

http://jsfiddle.net/felix00111/6jesxoxk/8/

Below is the jquery

$('tr.main-parent')
    .css("cursor", "pointer")
    .click(function () {

    var $children = $(this).nextUntil($('tr').not('.sub'));

    if ($children.find(':visible').length) {
        $children.find('td > div, td').slideUp(1200);
    } else {
        $children.filter('.parent').find('td > div, td').slideDown("slow");
    }
});
$('tr[class^=child-]').find('td > div, td').hide();

$('tr.parent')
    .css("cursor", "pointer")
    .click(function () {
    var $children = $(this).nextUntil($('tr').not('[class^=child-]'));
    $children.find('td > div, td').slideToggle(1200);
});
$('tr.sub').find('td > div, td').hide()

;

Any ideas ? Ive tried hard setting the widths but it still continues.

Thanks,

felix001
  • 15,341
  • 32
  • 94
  • 121

6 Answers6

1

In a nutshell, your solution requires way too much resources, which is the reason for jumpiness.

You're not using a very efficient way of selecting your elements, so looking through such a massive amount of elements isn't an easy task for the cpu. And you're also animating multiple elements simultaneously with a non-hardware-accelerated animation. jQuery animations aren't the most efficient, especially with multiple elements, so it's no wonder your PC is struggling with that animation.

To make it faster to select what needs to be shown or hidden, you could consider creating another table within each row. This way you could use .slideUp() (if that's what you really want to use) on that inner table instead. I realize that's not exactly the same effect, but would imo look good nonetheless and make it much smoother. Here's what I mean:

<table>
    <thead>
        <tr>
            <th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th><th>xyz</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>xyz</td>
            <td>xyz</td>
            <td colspan="18"><!--Your inner table here--></td>
        </tr>
        <!-- more rows -->
    </tbody>
</table>

Then, your inner table can simply be 18 cells wide (or howmany every you had...). Now you can simply animate one element, instead of a whole bunch. Plus, selecting the element will be much faster, because it's right inside the element you clicked on.

This may be already enough, and that jQuery animation might look perfectly smooth with those alterations. And it's understandable if you don't want to deal with CSS transitions, because those require a fixed height for the elements whose height you're animating. CSS transitions however are hardware accelerated, so they would perform better.

You might want to use the .stop() function on the elements before animating them, if you end up using jQuery. This way new animation requests aren't queued, but instead the current animations are stopped and the new one will start instantly.

If you don't want to use CSS animations and jQuery still seems too slow, you could construct your own animation using Window.requestAnimationFrame(), which is hardware accelerated also and would make for smoother animations.

Or, you could use an animation library that does support hardware acceleration, which would have about the same performance benefits as using CSS. One good option would be Velocity.js witch works in conjunction or without jQuery, has the same syntax and has support for things that jQuery doesn't support, like transforms.

Okku
  • 7,468
  • 4
  • 30
  • 43
0

I don't see any problems with the animation, but that's probably because my PC is a little more powerful.

JQuery slideDown() and slideUp() functions can be jumpy sometimes, because they run without hardware rendering.

I would write the animation myself using "requestAnimationFrame", since that function is hardware accelerated, but you might be better of using CSS transitions.

Here is a blog post about it: Using CSS Transitions to SlideUp and SlideDown

If you want more sources or a more detailed description on how CSS transitions work, write a comment and I'll do my best to write a more detailed explanation.

Ziga Petek
  • 3,953
  • 5
  • 33
  • 43
  • 1
    Just to add, this is a good resource I have used in the past: http://ricostacruz.com/jquery.transit/ It uses css transitions if they are available and then js animations as a fallback. – lharby Jun 05 '15 at 12:24
  • I agree, using js animations as a fallback is a good idea, since some browsers (* *cough* * IE9 * *cough* *) don't support CSS transitions. – Ziga Petek Jun 05 '15 at 12:28
0

Add the following CSS (or add as inline CSS) for your table (or your table class)

table {
     table-layout: fixed;
} 

Fiddle - http://jsfiddle.net/7m7w2dm8/

potatopeelings
  • 40,709
  • 7
  • 95
  • 119
  • How does this help? Can you explain? – lharby Jun 05 '15 at 12:22
  • It picks the fixed table layout algorithm. where the width is driven by the width of the columns (specifically the first row) and NOT by the contents. Here's a nice blog on the fixed layout - https://css-tricks.com/fixing-tables-long-strings/. Btw, your fiddle was missing a closing tag. – potatopeelings Jun 05 '15 at 12:26
  • I don't think that has any effect on the animation though. They look the same in your fiddle and the OP fiddle. – lharby Jun 05 '15 at 12:28
  • I don't think its actually a problem with the animation (even though admittedly the question says it is). I think (felix001 would the best person to comment on this) that different rows are being clicked on and if the content is not long enough everything seems normal. If the content is long, the column widths adjust making the whole table jump around. The last line of the question is where I felt that felix001 also felt the same. Sorry about the multiple edits. I keep pressing the enter key. :-) – potatopeelings Jun 05 '15 at 12:31
0

See http://jsfiddle.net/6jesxoxk/23/

I couldn't modify the whole html so I modified the table in code instead. I'm not saying this is what you should do but your html should look like how it looks after running this:

$('#myTable > tbody > tr.main-parent').each(function(i, e){
     $(this)
    .nextUntil($('tr').not('.sub'))
    .filter('.parent')
    .wrapAll('<tr class="containerTr"></tr>')
    .wrapAll('<td colspan="13"></td>')
    .wrapAll('<div class="containerDiv" style:"display:none;"></div>');
});

This changes the html to look like this, all sub trs you want to show are inside a hidden div. This div is inside a td:col-span:13 itself.

new html format

Then when a `main-parent' is clicked you slide the div, instead of td's. Your original code is sliding many elements at once, which is not a very good idea. It's much better to wrap all those elements in a div and slide only the div.

$tr.nextAll('.containerTr:first').find('.containerDiv').eq(0).slideToggle(1200);

I also changed the click handler, instead of binding to tr.main-parent, which will create many handlers, give the table an id and bind to table click and check the target.

artm
  • 8,554
  • 3
  • 26
  • 43
0

Your issue will be resolved, if you replace functions .slideUp(1200), .hide(), slideDown("slow") with .slideToggle(1200).

This is browser friendly, also works efficiently.

Srinivas
  • 133
  • 6
-1

It's because you're clicking too fast, the first animation thread hasn't finished, and you're asking to play another one.

Not sure how to fix it off the top of my head though. But that should point you in the right direction to fix it yourself

Update: Googled it for you.

How to prevent this strange jQuery .animate() lag?

Community
  • 1
  • 1
minijag
  • 59
  • 5