[jquery] How to Use slideDown (or show) function on a table row?

I'm trying to add a row to a table and have that row slide into view, however the slidedown function seems to be adding a display:block style to the table row which messes up the layout.

Any ideas how to work around this?

Here's the code:

$.get('/some_url', 
  { 'val1': id },

  function (data) {
    var row = $('#detailed_edit_row');
    row.hide();
    row.html(data);
    row.slideDown(1000);
  }
);

This question is related to jquery animation html-table slidedown

The answer is


If you need to slide and fade a table row at the same time, try using these:

jQuery.fn.prepareTableRowForSliding = function() {
    $tr = this;
    $tr.children('td').wrapInner('<div style="display: none;" />');
    return $tr;
};

jQuery.fn.slideFadeTableRow = function(speed, easing, callback) {
    $tr = this;
    if ($tr.is(':hidden')) {
        $tr.show().find('td > div').animate({opacity: 'toggle', height: 'toggle'}, speed, easing, callback);
    } else {
        $tr.find('td > div').animate({opacity: 'toggle', height: 'toggle'}, speed, easing, function(){
            $tr.hide();
            callback();
        });
    }
    return $tr;
};

$(document).ready(function(){
    $('tr.special').hide().prepareTableRowForSliding();
    $('a.toggle').toggle(function(){
        $button = $(this);
        $tr = $button.closest('tr.special'); //this will be specific to your situation
        $tr.slideFadeTableRow(300, 'swing', function(){
            $button.text('Hide table row');
        });
    }, function(){
        $button = $(this);
        $tr = $button.closest('tr.special'); //this will be specific to your situation
        $tr.slideFadeTableRow(300, 'swing', function(){
            $button.text('Display table row');
        });
});
});

http://jsfiddle.net/PvwfK/136/

<table cellspacing='0' cellpadding='0' class='table01' id='form_table' style='width:100%;'>
<tr>
    <td style='cursor:pointer; width:20%; text-align:left;' id='header'>
        <label style='cursor:pointer;'> <b id='header01'>? Customer Details</b>

        </label>
    </td>
</tr>
<tr>
    <td style='widtd:20%; text-align:left;'>
        <div id='content' class='content01'>
            <table cellspacing='0' cellpadding='0' id='form_table'>
                <tr>
                    <td>A/C ID</td>
                    <td>:</td>
                    <td>3000/A01</td>
                </tr>
                <tr>
                    <td>A/C ID</td>
                    <td>:</td>
                    <td>3000/A01</td>
                </tr>
                <tr>
                    <td>A/C ID</td>
                    <td>:</td>
                    <td>3000/A01</td>
                </tr>
            </table>
        </div>
    </td>
</tr>

$(function () {
$(".table01 td").on("click", function () {
    var $rows = $('.content01');
    if ($(".content01:first").is(":hidden")) {
        $("#header01").text("? Customer Details");
        $(".content01:first").slideDown();
    } else {
        $("#header01").text("? Customer Details");
        $(".content01:first").slideUp();
    }
});

});


I had problems with all the other solutions offered but ended up doing this simple thing that is smooth as butter.

Set up your HTML like so:

<tr id=row1 style='height:0px'><td>
  <div id=div1 style='display:none'>
    Hidden row content goes here
  </div>
</td></tr>

Then set up your javascript like so:

function toggleRow(rowid){
  var row = document.getElementById("row" + rowid)

  if(row.style.height == "0px"){
      $('#div' + rowid).slideDown('fast');
      row.style.height = "1px";   
  }else{
      $('#div' + rowid).slideUp('fast');
      row.style.height = "0px";   
  } 
}

Basically, make the "invisible" row 0px high, with a div inside.
Use the animation on the div (not the row) and then set the row height to 1px.

To hide the row again, use the opposite animation on the div and set the row height back to 0px.


You could try wrapping the contents of the row in a <span> and having your selector be $('#detailed_edit_row span'); - a bit hackish, but I just tested it and it works. I also tried the table-row suggestion above and it didn't seem to work.

update: I've been playing around with this problem, and from all indications jQuery needs the object it performs slideDown on to be a block element. So, no dice. I was able to conjure up a table where I used slideDown on a cell and it didn't affect the layout at all, so I am not sure how yours is set up. I think your only solution is to refactor the table in such a way that it's ok with that cell being a block, or just .show(); the damn thing. Good luck.


I'm a bit behind the times on answering this, but I found a way to do it :)

function eventinfo(id) {
    tr = document.getElementById("ei"+id);
    div = document.getElementById("d"+id);
    if (tr.style.display == "none") {
        tr.style.display="table-row";
        $(div).slideDown('fast');
    } else {
        $(div).slideUp('fast');
        setTimeout(function(){tr.style.display="none";}, 200);
    }
}

I just put a div element inside the table data tags. when it is set visible, as the div expands, the whole row comes down. then tell it to fade back up (then timeout so you see the effect) before hiding the table row again :)

Hope this helps someone!


I simply wrap the tr dynamically then remove it once the slideUp/slideDown has complete. It's a pretty small overhead adding and removing one or a couple of tags and then removing them once the animation is complete, I don't see any visible lag at all doing it.

SlideUp:

$('#my_table > tbody > tr.my_row')
 .find('td')
 .wrapInner('<div style="display: block;" />')
 .parent()
 .find('td > div')
 .slideUp(700, function(){

  $(this).parent().parent().remove();

 });

SlideDown:

$('#my_table > tbody > tr.my_row')
 .find('td')
 .wrapInner('<div style="display: none;" />')
 .parent()
 .find('td > div')
 .slideDown(700, function(){

  var $set = $(this);
  $set.replaceWith($set.contents());

 });

I have to pay tribute to fletchzone.com as I took his plugin and stripped it back to the above, cheers mate.


The plug offered by Vinny is really close, but I found and fixed a couple of small issues.

  1. It greedily targeted td elements beyond just the children of the row being hidden. This would have been kind of ok if it had then sought out those children when showing the row. While it got close, they all ended up with "display: none" on them, rendering them hidden.
  2. It didn't target child th elements at all.
  3. For table cells with lots of content (like a nested table with lots of rows), calling slideRow('up'), regardless of the slideSpeed value provided, it'd collapse the view of the row as soon as the padding animation was done. I fixed it so the padding animation doesn't trigger until the slideUp() method on the wrapping is done.

    (function($){
        var sR = {
            defaults: {
                slideSpeed: 400
              , easing: false
              , callback: false
            }
          , thisCallArgs:{
                slideSpeed: 400
              , easing: false
              , callback: false
            }
          , methods:{
                up: function(arg1, arg2, arg3){
                    if(typeof arg1 == 'object'){
                        for(p in arg1){
                            sR.thisCallArgs.eval(p) = arg1[p];
                        }
                    }else if(typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')){
                        sR.thisCallArgs.slideSpeed = arg1;
                    }else{
                        sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
                    }
    
                    if(typeof arg2 == 'string'){
                        sR.thisCallArgs.easing = arg2;
                    }else if(typeof arg2 == 'function'){
                        sR.thisCallArgs.callback = arg2;
                    }else if(typeof arg2 == 'undefined'){
                        sR.thisCallArgs.easing = sR.defaults.easing;    
                    }
                    if(typeof arg3 == 'function'){
                        sR.thisCallArgs.callback = arg3;
                    }else if(typeof arg3 == 'undefined' && typeof arg2 != 'function'){
                        sR.thisCallArgs.callback = sR.defaults.callback;    
                    }
                    var $cells = $(this).children('td, th');
                    $cells.wrapInner('<div class="slideRowUp" />');
                    var currentPadding = $cells.css('padding');
                    $cellContentWrappers = $(this).find('.slideRowUp');
                    $cellContentWrappers.slideUp(sR.thisCallArgs.slideSpeed, sR.thisCallArgs.easing, function(){
                        $(this).parent().animate({ paddingTop: '0px', paddingBottom: '0px' }, {
                            complete: function(){
                                $(this).children('.slideRowUp').replaceWith($(this).children('.slideRowUp').contents());
                                $(this).parent().css({ 'display': 'none' });
                                $(this).css({ 'padding': currentPadding });
                            }
                        });
                    });
                    var wait = setInterval(function(){
                        if($cellContentWrappers.is(':animated') === false){
                            clearInterval(wait);
                            if(typeof sR.thisCallArgs.callback == 'function'){
                                sR.thisCallArgs.callback.call(this);
                            }
                        }
                    }, 100);                                                                                                    
                    return $(this);
                }
              , down: function (arg1, arg2, arg3){
                    if(typeof arg1 == 'object'){
                        for(p in arg1){
                            sR.thisCallArgs.eval(p) = arg1[p];
                        }
                    }else if(typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')){
                        sR.thisCallArgs.slideSpeed = arg1;
                    }else{
                        sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
                    }
    
                    if(typeof arg2 == 'string'){
                        sR.thisCallArgs.easing = arg2;
                    }else if(typeof arg2 == 'function'){
                        sR.thisCallArgs.callback = arg2;
                    }else if(typeof arg2 == 'undefined'){
                        sR.thisCallArgs.easing = sR.defaults.easing;    
                    }
                    if(typeof arg3 == 'function'){
                        sR.thisCallArgs.callback = arg3;
                    }else if(typeof arg3 == 'undefined' && typeof arg2 != 'function'){
                        sR.thisCallArgs.callback = sR.defaults.callback;    
                    }
                    var $cells = $(this).children('td, th');
                    $cells.wrapInner('<div class="slideRowDown" style="display:none;" />');
                    $cellContentWrappers = $cells.find('.slideRowDown');
                    $(this).show();
                    $cellContentWrappers.slideDown(sR.thisCallArgs.slideSpeed, sR.thisCallArgs.easing, function() { $(this).replaceWith( $(this).contents()); });
    
                    var wait = setInterval(function(){
                        if($cellContentWrappers.is(':animated') === false){
                            clearInterval(wait);
                            if(typeof sR.thisCallArgs.callback == 'function'){
                                sR.thisCallArgs.callback.call(this);
                            }
                        }
                    }, 100);
                    return $(this);
                }
            }
        };
    
        $.fn.slideRow = function(method, arg1, arg2, arg3){
            if(typeof method != 'undefined'){
                if(sR.methods[method]){
                    return sR.methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
                }
            }
        };
    })(jQuery);
    

Have a table row with nested table:

<tr class='dummyRow' style='display: none;'>
    <td>
        <table style='display: none;'>All row content inside here</table>
    </td>
</tr>

To slideDown the row:

$('.dummyRow').show().find("table").slideDown();

Note: the row and it's content (here it is "table") both should be hidden before animation starts.


To slideUp the row:

$('.dummyRow').find("table").slideUp('normal', function(){$('.dummyRow').hide();});

The second parameter (function()) is a callback.


Simple!!

Note that there are also several options that can be added as parameters of the slide up/down functions (the most common being durations of 'slow' and 'fast').


I'd like to add a comment to #Vinny's post but dont have the rep so have to post an answer...

Found a bug with your plugin - when you just pass an object in with arguments they get overwritten if no other arguments are passed in. Easily resolved by changing the order the arguments are processed, code below. I've also added an option for destroying the row after closing (only as I had a need for it!): $('#row_id').slideRow('up', true); // destroys the row

(function ($) {
    var sR = {
        defaults: {
            slideSpeed: 400,
            easing: false,
            callback: false
        },
        thisCallArgs: {
            slideSpeed: 400,
            easing: false,
            callback: false,
            destroyAfterUp: false
        },
        methods: {
            up: function (arg1, arg2, arg3) {
                if (typeof arg2 == 'string') {
                    sR.thisCallArgs.easing = arg2;
                } else if (typeof arg2 == 'function') {
                    sR.thisCallArgs.callback = arg2;
                } else if (typeof arg2 == 'undefined') {
                    sR.thisCallArgs.easing = sR.defaults.easing;
                }
                if (typeof arg3 == 'function') {
                    sR.thisCallArgs.callback = arg3;
                } else if (typeof arg3 == 'undefined' && typeof arg2 != 'function') {
                    sR.thisCallArgs.callback = sR.defaults.callback;
                }
                if (typeof arg1 == 'object') {
                    for (p in arg1) {
                        sR.thisCallArgs[p] = arg1[p];
                    }
                } else if (typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')) {
                    sR.thisCallArgs.slideSpeed = arg1;
                } else if (typeof arg1 != 'undefined' && (typeof arg1 == 'boolean')) {
                    sR.thisCallArgs.destroyAfterUp = arg1;
                } else {
                    sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
                }

                var $row = $(this);
                var $cells = $row.children('th, td');
                $cells.wrapInner('<div class="slideRowUp" />');
                var currentPadding = $cells.css('padding');
                $cellContentWrappers = $(this).find('.slideRowUp');
                $cellContentWrappers.slideUp(sR.thisCallArgs.slideSpeed, sR.thisCallArgs.easing).parent().animate({
                    paddingTop: '0px',
                    paddingBottom: '0px'
                }, {
                    complete: function () {
                        $(this).children('.slideRowUp').replaceWith($(this).children('.slideRowUp').contents());
                        $(this).parent().css({ 'display': 'none' });
                        $(this).css({ 'padding': currentPadding });
                    }
                });
                var wait = setInterval(function () {
                    if ($cellContentWrappers.is(':animated') === false) {
                        clearInterval(wait);
                        if (sR.thisCallArgs.destroyAfterUp)
                        {
                            $row.replaceWith('');
                        }
                        if (typeof sR.thisCallArgs.callback == 'function') {
                            sR.thisCallArgs.callback.call(this);
                        }
                    }
                }, 100);
                return $(this);
            },
            down: function (arg1, arg2, arg3) {

                if (typeof arg2 == 'string') {
                    sR.thisCallArgs.easing = arg2;
                } else if (typeof arg2 == 'function') {
                    sR.thisCallArgs.callback = arg2;
                } else if (typeof arg2 == 'undefined') {
                    sR.thisCallArgs.easing = sR.defaults.easing;
                }
                if (typeof arg3 == 'function') {
                    sR.thisCallArgs.callback = arg3;
                } else if (typeof arg3 == 'undefined' && typeof arg2 != 'function') {
                    sR.thisCallArgs.callback = sR.defaults.callback;
                }
                if (typeof arg1 == 'object') {
                    for (p in arg1) {
                        sR.thisCallArgs.eval(p) = arg1[p];
                    }
                } else if (typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')) {
                    sR.thisCallArgs.slideSpeed = arg1;
                } else {
                    sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
                }

                var $cells = $(this).children('th, td');
                $cells.wrapInner('<div class="slideRowDown" style="display:none;" />');
                $cellContentWrappers = $cells.find('.slideRowDown');
                $(this).show();
                $cellContentWrappers.slideDown(sR.thisCallArgs.slideSpeed, sR.thisCallArgs.easing, function () { $(this).replaceWith($(this).contents()); });

                var wait = setInterval(function () {
                    if ($cellContentWrappers.is(':animated') === false) {
                        clearInterval(wait);
                        if (typeof sR.thisCallArgs.callback == 'function') {
                            sR.thisCallArgs.callback.call(this);
                        }
                    }
                }, 100);
                return $(this);
            }
        }
    };

    $.fn.slideRow = function (method, arg1, arg2, arg3) {
        if (typeof method != 'undefined') {
            if (sR.methods[method]) {
                return sR.methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
            }
        }
    };
})(jQuery);

Here's a plug-in that I wrote up for this, it takes a little from Fletch's implementation, but mine is used solely to slide a row up or down (no inserting rows).

(function($) {
var sR = {
    defaults: {
        slideSpeed: 400,
        easing: false,
        callback: false     
    },
    thisCallArgs: {
        slideSpeed: 400,
        easing: false,
        callback: false
    },
    methods: {
        up: function (arg1,arg2,arg3) {
            if(typeof arg1 == 'object') {
                for(p in arg1) {
                    sR.thisCallArgs.eval(p) = arg1[p];
                }
            }else if(typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')) {
                sR.thisCallArgs.slideSpeed = arg1;
            }else{
                sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
            }

            if(typeof arg2 == 'string'){
                sR.thisCallArgs.easing = arg2;
            }else if(typeof arg2 == 'function'){
                sR.thisCallArgs.callback = arg2;
            }else if(typeof arg2 == 'undefined') {
                sR.thisCallArgs.easing = sR.defaults.easing;    
            }
            if(typeof arg3 == 'function') {
                sR.thisCallArgs.callback = arg3;
            }else if(typeof arg3 == 'undefined' && typeof arg2 != 'function'){
                sR.thisCallArgs.callback = sR.defaults.callback;    
            }
            var $cells = $(this).find('td');
            $cells.wrapInner('<div class="slideRowUp" />');
            var currentPadding = $cells.css('padding');
            $cellContentWrappers = $(this).find('.slideRowUp');
            $cellContentWrappers.slideUp(sR.thisCallArgs.slideSpeed,sR.thisCallArgs.easing).parent().animate({
                                                                                                                paddingTop: '0px',
                                                                                                                paddingBottom: '0px'},{
                                                                                                                complete: function () {
                                                                                                                    $(this).children('.slideRowUp').replaceWith($(this).children('.slideRowUp').contents());
                                                                                                                    $(this).parent().css({'display':'none'});
                                                                                                                    $(this).css({'padding': currentPadding});
                                                                                                                }});
            var wait = setInterval(function () {
                if($cellContentWrappers.is(':animated') === false) {
                    clearInterval(wait);
                    if(typeof sR.thisCallArgs.callback == 'function') {
                        sR.thisCallArgs.callback.call(this);
                    }
                }
            }, 100);                                                                                                    
            return $(this);
        },
        down: function (arg1,arg2,arg3) {
            if(typeof arg1 == 'object') {
                for(p in arg1) {
                    sR.thisCallArgs.eval(p) = arg1[p];
                }
            }else if(typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')) {
                sR.thisCallArgs.slideSpeed = arg1;
            }else{
                sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
            }

            if(typeof arg2 == 'string'){
                sR.thisCallArgs.easing = arg2;
            }else if(typeof arg2 == 'function'){
                sR.thisCallArgs.callback = arg2;
            }else if(typeof arg2 == 'undefined') {
                sR.thisCallArgs.easing = sR.defaults.easing;    
            }
            if(typeof arg3 == 'function') {
                sR.thisCallArgs.callback = arg3;
            }else if(typeof arg3 == 'undefined' && typeof arg2 != 'function'){
                sR.thisCallArgs.callback = sR.defaults.callback;    
            }
            var $cells = $(this).find('td');
            $cells.wrapInner('<div class="slideRowDown" style="display:none;" />');
            $cellContentWrappers = $cells.find('.slideRowDown');
            $(this).show();
            $cellContentWrappers.slideDown(sR.thisCallArgs.slideSpeed, sR.thisCallArgs.easing, function() { $(this).replaceWith( $(this).contents()); });

            var wait = setInterval(function () {
                if($cellContentWrappers.is(':animated') === false) {
                    clearInterval(wait);
                    if(typeof sR.thisCallArgs.callback == 'function') {
                        sR.thisCallArgs.callback.call(this);
                    }
                }
            }, 100);
            return $(this);
        }
    }
};

$.fn.slideRow = function(method,arg1,arg2,arg3) {
    if(typeof method != 'undefined') {
        if(sR.methods[method]) {
            return sR.methods[method].apply(this, Array.prototype.slice.call(arguments,1));
        }
    }
};
})(jQuery);

Basic Usage:

$('#row_id').slideRow('down');
$('#row_id').slideRow('up');

Pass slide options as individual arguments:

$('#row_id').slideRow('down', 500); //slide speed
$('#row_id').slideRow('down', 500, function() { alert('Row available'); }); // slide speed and callback function
$('#row_id').slideRow('down', 500, 'linear', function() { alert('Row available'); }); slide speed, easing option and callback function
$('#row_id').slideRow('down', {slideSpeed: 500, easing: 'linear', callback: function() { alert('Row available');} }); //options passed as object

Basically, for the slide down animation, the plug-in wraps the contents of the cells in DIVs, animates those, then removes them, and vice versa for the slide up (with some extra steps to get rid of the cell padding). It also returns the object you called it on, so you can chain methods like so:

$('#row_id').slideRow('down').css({'font-color':'#F00'}); //make the text in the row red

Hope this helps someone.


I liked the plugin that Vinny's written and have been using. But in case of tables inside sliding row (tr/td), the rows of nested table are always hidden even after slid up. So I did a quick and simple hack in the plugin not to hide the rows of nested table. Just change the following line

var $cells = $(this).find('td');

to

var $cells = $(this).find('> td');

which finds only immediate tds not nested ones. Hope this helps someone using the plugin and have nested tables.


Quick/Easy Fix:

Use JQuery .toggle() to show/hide the rows onclick of either Row or an Anchor.

A function will need to be written to identify the rows you would like hidden, but toggle creates the functionality you are looking for.


I had problems with all the other solutions offered but ended up doing this simple thing that is smooth as butter.

Set up your HTML like so:

<tr id=row1 style='height:0px'><td>
  <div id=div1 style='display:none'>
    Hidden row content goes here
  </div>
</td></tr>

Then set up your javascript like so:

function toggleRow(rowid){
  var row = document.getElementById("row" + rowid)

  if(row.style.height == "0px"){
      $('#div' + rowid).slideDown('fast');
      row.style.height = "1px";   
  }else{
      $('#div' + rowid).slideUp('fast');
      row.style.height = "0px";   
  } 
}

Basically, make the "invisible" row 0px high, with a div inside.
Use the animation on the div (not the row) and then set the row height to 1px.

To hide the row again, use the opposite animation on the div and set the row height back to 0px.


I liked the plugin that Vinny's written and have been using. But in case of tables inside sliding row (tr/td), the rows of nested table are always hidden even after slid up. So I did a quick and simple hack in the plugin not to hide the rows of nested table. Just change the following line

var $cells = $(this).find('td');

to

var $cells = $(this).find('> td');

which finds only immediate tds not nested ones. Hope this helps someone using the plugin and have nested tables.


This code works!

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <title></title>
        <script>
            function addRow() {
                $('.displaynone').show();
                $('.displaynone td')
                .wrapInner('<div class="innerDiv" style="height:0" />');
                $('div').animate({"height":"20px"});
            }
        </script>
        <style>
            .mycolumn{border: 1px solid black;}
            .displaynone{display: none;}
        </style>
    </head>
    <body>
        <table align="center" width="50%">
            <tr>
                <td class="mycolumn">Row 1</td>
            </tr>
            <tr>
                <td class="mycolumn">Row 2</td>
            </tr>
            <tr class="displaynone">
                <td class="mycolumn">Row 3</td>
            </tr>
            <tr>
                <td class="mycolumn">Row 4</td>
            </tr>
        </table>
        <br>
        <button onclick="addRow();">add</button>    
    </body>
</html>

I want to slide whole tbody and I've managed this problem by combining fade and slide effects.

I've done this in 3 stages (2nd and 3rd steps are replaced in case you want to slide down or up)

  1. Assigning height to tbody,
  2. Fading all td and th,
  3. Sliding tbody.

Example of slideUp:

tbody.css('height', tbody.css('height'));
tbody.find('td, th').fadeOut(200, function(){
    tbody.slideUp(300)
});

Here's a plug-in that I wrote up for this, it takes a little from Fletch's implementation, but mine is used solely to slide a row up or down (no inserting rows).

(function($) {
var sR = {
    defaults: {
        slideSpeed: 400,
        easing: false,
        callback: false     
    },
    thisCallArgs: {
        slideSpeed: 400,
        easing: false,
        callback: false
    },
    methods: {
        up: function (arg1,arg2,arg3) {
            if(typeof arg1 == 'object') {
                for(p in arg1) {
                    sR.thisCallArgs.eval(p) = arg1[p];
                }
            }else if(typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')) {
                sR.thisCallArgs.slideSpeed = arg1;
            }else{
                sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
            }

            if(typeof arg2 == 'string'){
                sR.thisCallArgs.easing = arg2;
            }else if(typeof arg2 == 'function'){
                sR.thisCallArgs.callback = arg2;
            }else if(typeof arg2 == 'undefined') {
                sR.thisCallArgs.easing = sR.defaults.easing;    
            }
            if(typeof arg3 == 'function') {
                sR.thisCallArgs.callback = arg3;
            }else if(typeof arg3 == 'undefined' && typeof arg2 != 'function'){
                sR.thisCallArgs.callback = sR.defaults.callback;    
            }
            var $cells = $(this).find('td');
            $cells.wrapInner('<div class="slideRowUp" />');
            var currentPadding = $cells.css('padding');
            $cellContentWrappers = $(this).find('.slideRowUp');
            $cellContentWrappers.slideUp(sR.thisCallArgs.slideSpeed,sR.thisCallArgs.easing).parent().animate({
                                                                                                                paddingTop: '0px',
                                                                                                                paddingBottom: '0px'},{
                                                                                                                complete: function () {
                                                                                                                    $(this).children('.slideRowUp').replaceWith($(this).children('.slideRowUp').contents());
                                                                                                                    $(this).parent().css({'display':'none'});
                                                                                                                    $(this).css({'padding': currentPadding});
                                                                                                                }});
            var wait = setInterval(function () {
                if($cellContentWrappers.is(':animated') === false) {
                    clearInterval(wait);
                    if(typeof sR.thisCallArgs.callback == 'function') {
                        sR.thisCallArgs.callback.call(this);
                    }
                }
            }, 100);                                                                                                    
            return $(this);
        },
        down: function (arg1,arg2,arg3) {
            if(typeof arg1 == 'object') {
                for(p in arg1) {
                    sR.thisCallArgs.eval(p) = arg1[p];
                }
            }else if(typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')) {
                sR.thisCallArgs.slideSpeed = arg1;
            }else{
                sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
            }

            if(typeof arg2 == 'string'){
                sR.thisCallArgs.easing = arg2;
            }else if(typeof arg2 == 'function'){
                sR.thisCallArgs.callback = arg2;
            }else if(typeof arg2 == 'undefined') {
                sR.thisCallArgs.easing = sR.defaults.easing;    
            }
            if(typeof arg3 == 'function') {
                sR.thisCallArgs.callback = arg3;
            }else if(typeof arg3 == 'undefined' && typeof arg2 != 'function'){
                sR.thisCallArgs.callback = sR.defaults.callback;    
            }
            var $cells = $(this).find('td');
            $cells.wrapInner('<div class="slideRowDown" style="display:none;" />');
            $cellContentWrappers = $cells.find('.slideRowDown');
            $(this).show();
            $cellContentWrappers.slideDown(sR.thisCallArgs.slideSpeed, sR.thisCallArgs.easing, function() { $(this).replaceWith( $(this).contents()); });

            var wait = setInterval(function () {
                if($cellContentWrappers.is(':animated') === false) {
                    clearInterval(wait);
                    if(typeof sR.thisCallArgs.callback == 'function') {
                        sR.thisCallArgs.callback.call(this);
                    }
                }
            }, 100);
            return $(this);
        }
    }
};

$.fn.slideRow = function(method,arg1,arg2,arg3) {
    if(typeof method != 'undefined') {
        if(sR.methods[method]) {
            return sR.methods[method].apply(this, Array.prototype.slice.call(arguments,1));
        }
    }
};
})(jQuery);

Basic Usage:

$('#row_id').slideRow('down');
$('#row_id').slideRow('up');

Pass slide options as individual arguments:

$('#row_id').slideRow('down', 500); //slide speed
$('#row_id').slideRow('down', 500, function() { alert('Row available'); }); // slide speed and callback function
$('#row_id').slideRow('down', 500, 'linear', function() { alert('Row available'); }); slide speed, easing option and callback function
$('#row_id').slideRow('down', {slideSpeed: 500, easing: 'linear', callback: function() { alert('Row available');} }); //options passed as object

Basically, for the slide down animation, the plug-in wraps the contents of the cells in DIVs, animates those, then removes them, and vice versa for the slide up (with some extra steps to get rid of the cell padding). It also returns the object you called it on, so you can chain methods like so:

$('#row_id').slideRow('down').css({'font-color':'#F00'}); //make the text in the row red

Hope this helps someone.


This code works!

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <title></title>
        <script>
            function addRow() {
                $('.displaynone').show();
                $('.displaynone td')
                .wrapInner('<div class="innerDiv" style="height:0" />');
                $('div').animate({"height":"20px"});
            }
        </script>
        <style>
            .mycolumn{border: 1px solid black;}
            .displaynone{display: none;}
        </style>
    </head>
    <body>
        <table align="center" width="50%">
            <tr>
                <td class="mycolumn">Row 1</td>
            </tr>
            <tr>
                <td class="mycolumn">Row 2</td>
            </tr>
            <tr class="displaynone">
                <td class="mycolumn">Row 3</td>
            </tr>
            <tr>
                <td class="mycolumn">Row 4</td>
            </tr>
        </table>
        <br>
        <button onclick="addRow();">add</button>    
    </body>
</html>

You could try wrapping the contents of the row in a <span> and having your selector be $('#detailed_edit_row span'); - a bit hackish, but I just tested it and it works. I also tried the table-row suggestion above and it didn't seem to work.

update: I've been playing around with this problem, and from all indications jQuery needs the object it performs slideDown on to be a block element. So, no dice. I was able to conjure up a table where I used slideDown on a cell and it didn't affect the layout at all, so I am not sure how yours is set up. I think your only solution is to refactor the table in such a way that it's ok with that cell being a block, or just .show(); the damn thing. Good luck.


Select the contents of the row like this:

$(row).contents().slideDown();

.contents() - Get the children of each element in the set of matched elements, including text and comment nodes.


I did use the ideas provided here and faced some problems. I fixed them all and have a smooth one-liner I'd like to share.

$('#row_to_slideup').find('> td').css({'height':'0px'}).wrapInner('<div style=\"display:block;\" />').parent().find('td > div').slideUp('slow', function() {$(this).parent().parent().remove();});

It uses css on the td element. It reduces the height to 0px. That way only the height of the content of the newly created div-wrapper inside of each td element matters.

The slideUp is on slow. If you make it even slower you might realize some glitch. A small jump at the beginning. This is because of the mentioned css setting. But without those settings the row would not decrease in height. Only its content would.

At the end the tr element gets removed.

The whole line only contains JQuery and no native Javascript.

Hope it helps.

Here is an example code:

    <html>
            <head>
                    <script src="https://code.jquery.com/jquery-3.2.0.min.js">               </script>
            </head>
            <body>
                    <table>
                            <thead>
                                    <tr>
                                            <th>header_column 1</th>
                                            <th>header column 2</th>
                                    </tr>
                            </thead>
                            <tbody>
                                    <tr id="row1"><td>row 1 left</td><td>row 1 right</td></tr>
                                    <tr id="row2"><td>row 2 left</td><td>row 2 right</td></tr>
                                    <tr id="row3"><td>row 3 left</td><td>row 3 right</td></tr>
                                    <tr id="row4"><td>row 4 left</td><td>row 4 right</td></tr>
                            </tbody>
                    </table>
                    <script>
    setTimeout(function() {
    $('#row2').find('> td').css({'height':'0px'}).wrapInner('<div style=\"display:block;\" />').parent().find('td > div').slideUp('slow',         function() {$(this).parent().parent().remove();});
    }, 2000);
                    </script>
            </body>
    </html>

Have a table row with nested table:

<tr class='dummyRow' style='display: none;'>
    <td>
        <table style='display: none;'>All row content inside here</table>
    </td>
</tr>

To slideDown the row:

$('.dummyRow').show().find("table").slideDown();

Note: the row and it's content (here it is "table") both should be hidden before animation starts.


To slideUp the row:

$('.dummyRow').find("table").slideUp('normal', function(){$('.dummyRow').hide();});

The second parameter (function()) is a callback.


Simple!!

Note that there are also several options that can be added as parameters of the slide up/down functions (the most common being durations of 'slow' and 'fast').


I've gotten around this by using the td elements in the row:

$(ui.item).children("td").effect("highlight", { color: "#4ca456" }, 1000);

Animating the row itself causes strange behaviour, mostly async animation problems.

For the above code, I am highlighting a row that gets dragged and dropped around in the table to highlight that the update has succeeded. Hope this helps someone.


http://jsfiddle.net/PvwfK/136/

<table cellspacing='0' cellpadding='0' class='table01' id='form_table' style='width:100%;'>
<tr>
    <td style='cursor:pointer; width:20%; text-align:left;' id='header'>
        <label style='cursor:pointer;'> <b id='header01'>? Customer Details</b>

        </label>
    </td>
</tr>
<tr>
    <td style='widtd:20%; text-align:left;'>
        <div id='content' class='content01'>
            <table cellspacing='0' cellpadding='0' id='form_table'>
                <tr>
                    <td>A/C ID</td>
                    <td>:</td>
                    <td>3000/A01</td>
                </tr>
                <tr>
                    <td>A/C ID</td>
                    <td>:</td>
                    <td>3000/A01</td>
                </tr>
                <tr>
                    <td>A/C ID</td>
                    <td>:</td>
                    <td>3000/A01</td>
                </tr>
            </table>
        </div>
    </td>
</tr>

$(function () {
$(".table01 td").on("click", function () {
    var $rows = $('.content01');
    if ($(".content01:first").is(":hidden")) {
        $("#header01").text("? Customer Details");
        $(".content01:first").slideDown();
    } else {
        $("#header01").text("? Customer Details");
        $(".content01:first").slideUp();
    }
});

});


You could try wrapping the contents of the row in a <span> and having your selector be $('#detailed_edit_row span'); - a bit hackish, but I just tested it and it works. I also tried the table-row suggestion above and it didn't seem to work.

update: I've been playing around with this problem, and from all indications jQuery needs the object it performs slideDown on to be a block element. So, no dice. I was able to conjure up a table where I used slideDown on a cell and it didn't affect the layout at all, so I am not sure how yours is set up. I think your only solution is to refactor the table in such a way that it's ok with that cell being a block, or just .show(); the damn thing. Good luck.


I did use the ideas provided here and faced some problems. I fixed them all and have a smooth one-liner I'd like to share.

$('#row_to_slideup').find('> td').css({'height':'0px'}).wrapInner('<div style=\"display:block;\" />').parent().find('td > div').slideUp('slow', function() {$(this).parent().parent().remove();});

It uses css on the td element. It reduces the height to 0px. That way only the height of the content of the newly created div-wrapper inside of each td element matters.

The slideUp is on slow. If you make it even slower you might realize some glitch. A small jump at the beginning. This is because of the mentioned css setting. But without those settings the row would not decrease in height. Only its content would.

At the end the tr element gets removed.

The whole line only contains JQuery and no native Javascript.

Hope it helps.

Here is an example code:

    <html>
            <head>
                    <script src="https://code.jquery.com/jquery-3.2.0.min.js">               </script>
            </head>
            <body>
                    <table>
                            <thead>
                                    <tr>
                                            <th>header_column 1</th>
                                            <th>header column 2</th>
                                    </tr>
                            </thead>
                            <tbody>
                                    <tr id="row1"><td>row 1 left</td><td>row 1 right</td></tr>
                                    <tr id="row2"><td>row 2 left</td><td>row 2 right</td></tr>
                                    <tr id="row3"><td>row 3 left</td><td>row 3 right</td></tr>
                                    <tr id="row4"><td>row 4 left</td><td>row 4 right</td></tr>
                            </tbody>
                    </table>
                    <script>
    setTimeout(function() {
    $('#row2').find('> td').css({'height':'0px'}).wrapInner('<div style=\"display:block;\" />').parent().find('td > div').slideUp('slow',         function() {$(this).parent().parent().remove();});
    }, 2000);
                    </script>
            </body>
    </html>

I can be done if you set the td's in the row to display none at the same time you start animating the height on the row

tbody tr{
    min-height: 50px;
}
tbody tr.ng-hide td{
    display: none;
}
tr.hide-line{
    -moz-transition: .4s linear all;
    -o-transition: .4s linear all;
    -webkit-transition: .4s linear all;
    transition: .4s linear all;
    height: 50px;
    overflow: hidden;

    &.ng-hide { //angularJs specific
        height: 0;
        min-height: 0;
    }
}

Select the contents of the row like this:

$(row).contents().slideDown();

.contents() - Get the children of each element in the set of matched elements, including text and comment nodes.


I neded a table with hidden rows that slide in and out of view on row click.

_x000D_
_x000D_
$('.tr-show-sub').click(function(e) {  _x000D_
    var elOne = $(this);_x000D_
    $('.tr-show-sub').each(function(key, value) {_x000D_
        var elTwoe = $(this);_x000D_
        _x000D_
        if(elOne.get(0) !== elTwoe.get(0)) {_x000D_
            if($(this).next('.tr-sub').hasClass('tr-sub-shown')) {_x000D_
                elTwoe.next('.tr-sub').removeClass('tr-sub-shown');_x000D_
                elTwoe.next('tr').find('td').find('div').slideUp();_x000D_
                elTwoe.next('tr').find('td').slideUp();_x000D_
            }_x000D_
        }_x000D_
        _x000D_
        if(elOne.get(0) === elTwoe.get(0)) {_x000D_
            if(elOne.next('.tr-sub').hasClass('tr-sub-shown')) {_x000D_
                elOne.next('.tr-sub').removeClass('tr-sub-shown');_x000D_
                elOne.next('tr').find('td').find('div').slideUp();_x000D_
                elOne.next('tr').find('td').slideUp();_x000D_
            } else {_x000D_
                elOne.next('.tr-sub').addClass('tr-sub-shown');_x000D_
                elOne.next('tr').find('td').slideDown();_x000D_
                elOne.next('tr').find('td').find('div').slideDown();_x000D_
            }_x000D_
        }_x000D_
    })_x000D_
});
_x000D_
body {_x000D_
        background: #eee;_x000D_
    }_x000D_
    _x000D_
    .wrapper {_x000D_
        margin: auto;_x000D_
        width: 50%;_x000D_
        padding: 10px;_x000D_
        margin-top: 10%;_x000D_
    }_x000D_
    _x000D_
    table {_x000D_
        background: white;_x000D_
        width: 100%;_x000D_
    }_x000D_
    _x000D_
    table th {_x000D_
        background: gray;_x000D_
        text-align: left;_x000D_
    }_x000D_
    _x000D_
    table th, td {_x000D_
        border-bottom: 1px solid lightgray;_x000D_
        padding: 5px;_x000D_
    }_x000D_
    _x000D_
    table .tr-show-sub {_x000D_
        background: #EAEAEA;_x000D_
        cursor: pointer;_x000D_
    }_x000D_
_x000D_
    table .tr-sub td {_x000D_
        display: none;_x000D_
    }_x000D_
    _x000D_
    table .tr-sub td .div-sub {_x000D_
        display: none;_x000D_
    }
_x000D_
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>_x000D_
<div class="wrapper">_x000D_
    <table cellspacing="0" cellpadding="3">_x000D_
        <thead>_x000D_
            <tr class="table">_x000D_
                <th>col 1</th>_x000D_
                <th>col 2</th>_x000D_
                <th>col 3</th>_x000D_
            </tr>_x000D_
        </thead>_x000D_
        <tbody>_x000D_
            <tr class="tr-show-sub">_x000D_
                <td>col 1</td>_x000D_
                <td>col 2</td>_x000D_
                <td>col 3</td>_x000D_
            </tr>_x000D_
            <tr class="tr-sub">_x000D_
                <td colspan="5"><div class="div-sub">_x000D_
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis auctor tortor sit amet sem tempus rhoncus. Etiam scelerisque ligula id ligula congue semper interdum in neque. Vestibulum condimentum id nibh ac pretium. Proin a dapibus nibh. Suspendisse quis elit volutpat, aliquet nisi et, rhoncus quam. Quisque nec ex quis diam tristique hendrerit. Nullam sagittis metus sem, placerat scelerisque dolor congue eu. Pellentesque ultricies purus turpis, convallis congue felis iaculis sed. Cras semper elementum nibh at semper. Suspendisse libero augue, auctor facilisis tincidunt eget, suscipit eu ligula. Nam in diam at ex facilisis tincidunt. Fusce erat enim, placerat ac massa facilisis, tempus aliquet metus. Fusce placerat nulla sed tristique tincidunt. Duis vulputate vestibulum libero, nec lobortis elit ornare vel. Mauris imperdiet nulla non suscipit cursus. Sed sed dui ac elit rutrum mollis sed sit amet lorem. _x000D_
                </div></td>_x000D_
            </tr>_x000D_
            <tr class="tr-show-sub">_x000D_
                <td>col 1</td>_x000D_
                <td>col 2</td>_x000D_
                <td>col 3</td>_x000D_
            </tr>_x000D_
            <tr class="tr-sub">_x000D_
                <td colspan="5"><div class="div-sub">_x000D_
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis auctor tortor sit amet sem tempus rhoncus. Etiam scelerisque ligula id ligula congue semper interdum in neque. Vestibulum condimentum id nibh ac pretium. Proin a dapibus nibh. Suspendisse quis elit volutpat, aliquet nisi et, rhoncus quam. Quisque nec ex quis diam tristique hendrerit. Nullam sagittis metus sem, placerat scelerisque dolor congue eu. Pellentesque ultricies purus turpis, convallis congue felis iaculis sed. Cras semper elementum nibh at semper. Suspendisse libero augue, auctor facilisis tincidunt eget, suscipit eu ligula. Nam in diam at ex facilisis tincidunt. Fusce erat enim, placerat ac massa facilisis, tempus aliquet metus. Fusce placerat nulla sed tristique tincidunt. Duis vulputate vestibulum libero, nec lobortis elit ornare vel. Mauris imperdiet nulla non suscipit cursus. Sed sed dui ac elit rutrum mollis sed sit amet lorem. _x000D_
                </div></td>_x000D_
            </tr>_x000D_
            <tr>_x000D_
                <td>col 1</td>_x000D_
                <td>col 2</td>_x000D_
                <td>col 3</td>_x000D_
            </tr>_x000D_
        </tbody>_x000D_
    </table>_x000D_
</div>
_x000D_
_x000D_
_x000D_


If you need to slide and fade a table row at the same time, try using these:

jQuery.fn.prepareTableRowForSliding = function() {
    $tr = this;
    $tr.children('td').wrapInner('<div style="display: none;" />');
    return $tr;
};

jQuery.fn.slideFadeTableRow = function(speed, easing, callback) {
    $tr = this;
    if ($tr.is(':hidden')) {
        $tr.show().find('td > div').animate({opacity: 'toggle', height: 'toggle'}, speed, easing, callback);
    } else {
        $tr.find('td > div').animate({opacity: 'toggle', height: 'toggle'}, speed, easing, function(){
            $tr.hide();
            callback();
        });
    }
    return $tr;
};

$(document).ready(function(){
    $('tr.special').hide().prepareTableRowForSliding();
    $('a.toggle').toggle(function(){
        $button = $(this);
        $tr = $button.closest('tr.special'); //this will be specific to your situation
        $tr.slideFadeTableRow(300, 'swing', function(){
            $button.text('Hide table row');
        });
    }, function(){
        $button = $(this);
        $tr = $button.closest('tr.special'); //this will be specific to your situation
        $tr.slideFadeTableRow(300, 'swing', function(){
            $button.text('Display table row');
        });
});
});

I've gotten around this by using the td elements in the row:

$(ui.item).children("td").effect("highlight", { color: "#4ca456" }, 1000);

Animating the row itself causes strange behaviour, mostly async animation problems.

For the above code, I am highlighting a row that gets dragged and dropped around in the table to highlight that the update has succeeded. Hope this helps someone.


I'd like to add a comment to #Vinny's post but dont have the rep so have to post an answer...

Found a bug with your plugin - when you just pass an object in with arguments they get overwritten if no other arguments are passed in. Easily resolved by changing the order the arguments are processed, code below. I've also added an option for destroying the row after closing (only as I had a need for it!): $('#row_id').slideRow('up', true); // destroys the row

(function ($) {
    var sR = {
        defaults: {
            slideSpeed: 400,
            easing: false,
            callback: false
        },
        thisCallArgs: {
            slideSpeed: 400,
            easing: false,
            callback: false,
            destroyAfterUp: false
        },
        methods: {
            up: function (arg1, arg2, arg3) {
                if (typeof arg2 == 'string') {
                    sR.thisCallArgs.easing = arg2;
                } else if (typeof arg2 == 'function') {
                    sR.thisCallArgs.callback = arg2;
                } else if (typeof arg2 == 'undefined') {
                    sR.thisCallArgs.easing = sR.defaults.easing;
                }
                if (typeof arg3 == 'function') {
                    sR.thisCallArgs.callback = arg3;
                } else if (typeof arg3 == 'undefined' && typeof arg2 != 'function') {
                    sR.thisCallArgs.callback = sR.defaults.callback;
                }
                if (typeof arg1 == 'object') {
                    for (p in arg1) {
                        sR.thisCallArgs[p] = arg1[p];
                    }
                } else if (typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')) {
                    sR.thisCallArgs.slideSpeed = arg1;
                } else if (typeof arg1 != 'undefined' && (typeof arg1 == 'boolean')) {
                    sR.thisCallArgs.destroyAfterUp = arg1;
                } else {
                    sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
                }

                var $row = $(this);
                var $cells = $row.children('th, td');
                $cells.wrapInner('<div class="slideRowUp" />');
                var currentPadding = $cells.css('padding');
                $cellContentWrappers = $(this).find('.slideRowUp');
                $cellContentWrappers.slideUp(sR.thisCallArgs.slideSpeed, sR.thisCallArgs.easing).parent().animate({
                    paddingTop: '0px',
                    paddingBottom: '0px'
                }, {
                    complete: function () {
                        $(this).children('.slideRowUp').replaceWith($(this).children('.slideRowUp').contents());
                        $(this).parent().css({ 'display': 'none' });
                        $(this).css({ 'padding': currentPadding });
                    }
                });
                var wait = setInterval(function () {
                    if ($cellContentWrappers.is(':animated') === false) {
                        clearInterval(wait);
                        if (sR.thisCallArgs.destroyAfterUp)
                        {
                            $row.replaceWith('');
                        }
                        if (typeof sR.thisCallArgs.callback == 'function') {
                            sR.thisCallArgs.callback.call(this);
                        }
                    }
                }, 100);
                return $(this);
            },
            down: function (arg1, arg2, arg3) {

                if (typeof arg2 == 'string') {
                    sR.thisCallArgs.easing = arg2;
                } else if (typeof arg2 == 'function') {
                    sR.thisCallArgs.callback = arg2;
                } else if (typeof arg2 == 'undefined') {
                    sR.thisCallArgs.easing = sR.defaults.easing;
                }
                if (typeof arg3 == 'function') {
                    sR.thisCallArgs.callback = arg3;
                } else if (typeof arg3 == 'undefined' && typeof arg2 != 'function') {
                    sR.thisCallArgs.callback = sR.defaults.callback;
                }
                if (typeof arg1 == 'object') {
                    for (p in arg1) {
                        sR.thisCallArgs.eval(p) = arg1[p];
                    }
                } else if (typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')) {
                    sR.thisCallArgs.slideSpeed = arg1;
                } else {
                    sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
                }

                var $cells = $(this).children('th, td');
                $cells.wrapInner('<div class="slideRowDown" style="display:none;" />');
                $cellContentWrappers = $cells.find('.slideRowDown');
                $(this).show();
                $cellContentWrappers.slideDown(sR.thisCallArgs.slideSpeed, sR.thisCallArgs.easing, function () { $(this).replaceWith($(this).contents()); });

                var wait = setInterval(function () {
                    if ($cellContentWrappers.is(':animated') === false) {
                        clearInterval(wait);
                        if (typeof sR.thisCallArgs.callback == 'function') {
                            sR.thisCallArgs.callback.call(this);
                        }
                    }
                }, 100);
                return $(this);
            }
        }
    };

    $.fn.slideRow = function (method, arg1, arg2, arg3) {
        if (typeof method != 'undefined') {
            if (sR.methods[method]) {
                return sR.methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
            }
        }
    };
})(jQuery);

You could try wrapping the contents of the row in a <span> and having your selector be $('#detailed_edit_row span'); - a bit hackish, but I just tested it and it works. I also tried the table-row suggestion above and it didn't seem to work.

update: I've been playing around with this problem, and from all indications jQuery needs the object it performs slideDown on to be a block element. So, no dice. I was able to conjure up a table where I used slideDown on a cell and it didn't affect the layout at all, so I am not sure how yours is set up. I think your only solution is to refactor the table in such a way that it's ok with that cell being a block, or just .show(); the damn thing. Good luck.


I can be done if you set the td's in the row to display none at the same time you start animating the height on the row

tbody tr{
    min-height: 50px;
}
tbody tr.ng-hide td{
    display: none;
}
tr.hide-line{
    -moz-transition: .4s linear all;
    -o-transition: .4s linear all;
    -webkit-transition: .4s linear all;
    transition: .4s linear all;
    height: 50px;
    overflow: hidden;

    &.ng-hide { //angularJs specific
        height: 0;
        min-height: 0;
    }
}

function hideTr(tr) {
  tr.find('td').wrapInner('<div style="display: block;" />').parent().find('td > div').slideUp(50, function () {
    tr.hide();
    var $set = jQuery(this);
    $set.replaceWith($set.contents());
  });
}

function showTr(tr) {
  tr.show()
  tr.find('td').wrapInner('<div style="display: none;" />').parent().find('td > div').slideDown(50, function() {
    var $set = jQuery(this);
    $set.replaceWith($set.contents());
  });
}

you can use these methods like:

jQuery("[data-toggle-tr-trigger]").click(function() {
  var $tr = jQuery(this).parents(trClass).nextUntil(trClass);
  if($tr.is(':hidden')) {
    showTr($tr);
  } else {
    hideTr($tr);
  }
});

I simply wrap the tr dynamically then remove it once the slideUp/slideDown has complete. It's a pretty small overhead adding and removing one or a couple of tags and then removing them once the animation is complete, I don't see any visible lag at all doing it.

SlideUp:

$('#my_table > tbody > tr.my_row')
 .find('td')
 .wrapInner('<div style="display: block;" />')
 .parent()
 .find('td > div')
 .slideUp(700, function(){

  $(this).parent().parent().remove();

 });

SlideDown:

$('#my_table > tbody > tr.my_row')
 .find('td')
 .wrapInner('<div style="display: none;" />')
 .parent()
 .find('td > div')
 .slideDown(700, function(){

  var $set = $(this);
  $set.replaceWith($set.contents());

 });

I have to pay tribute to fletchzone.com as I took his plugin and stripped it back to the above, cheers mate.


I'm a bit behind the times on answering this, but I found a way to do it :)

function eventinfo(id) {
    tr = document.getElementById("ei"+id);
    div = document.getElementById("d"+id);
    if (tr.style.display == "none") {
        tr.style.display="table-row";
        $(div).slideDown('fast');
    } else {
        $(div).slideUp('fast');
        setTimeout(function(){tr.style.display="none";}, 200);
    }
}

I just put a div element inside the table data tags. when it is set visible, as the div expands, the whole row comes down. then tell it to fade back up (then timeout so you see the effect) before hiding the table row again :)

Hope this helps someone!


I want to slide whole tbody and I've managed this problem by combining fade and slide effects.

I've done this in 3 stages (2nd and 3rd steps are replaced in case you want to slide down or up)

  1. Assigning height to tbody,
  2. Fading all td and th,
  3. Sliding tbody.

Example of slideUp:

tbody.css('height', tbody.css('height'));
tbody.find('td, th').fadeOut(200, function(){
    tbody.slideUp(300)
});

Quick/Easy Fix:

Use JQuery .toggle() to show/hide the rows onclick of either Row or an Anchor.

A function will need to be written to identify the rows you would like hidden, but toggle creates the functionality you are looking for.


function hideTr(tr) {
  tr.find('td').wrapInner('<div style="display: block;" />').parent().find('td > div').slideUp(50, function () {
    tr.hide();
    var $set = jQuery(this);
    $set.replaceWith($set.contents());
  });
}

function showTr(tr) {
  tr.show()
  tr.find('td').wrapInner('<div style="display: none;" />').parent().find('td > div').slideDown(50, function() {
    var $set = jQuery(this);
    $set.replaceWith($set.contents());
  });
}

you can use these methods like:

jQuery("[data-toggle-tr-trigger]").click(function() {
  var $tr = jQuery(this).parents(trClass).nextUntil(trClass);
  if($tr.is(':hidden')) {
    showTr($tr);
  } else {
    hideTr($tr);
  }
});

The plug offered by Vinny is really close, but I found and fixed a couple of small issues.

  1. It greedily targeted td elements beyond just the children of the row being hidden. This would have been kind of ok if it had then sought out those children when showing the row. While it got close, they all ended up with "display: none" on them, rendering them hidden.
  2. It didn't target child th elements at all.
  3. For table cells with lots of content (like a nested table with lots of rows), calling slideRow('up'), regardless of the slideSpeed value provided, it'd collapse the view of the row as soon as the padding animation was done. I fixed it so the padding animation doesn't trigger until the slideUp() method on the wrapping is done.

    (function($){
        var sR = {
            defaults: {
                slideSpeed: 400
              , easing: false
              , callback: false
            }
          , thisCallArgs:{
                slideSpeed: 400
              , easing: false
              , callback: false
            }
          , methods:{
                up: function(arg1, arg2, arg3){
                    if(typeof arg1 == 'object'){
                        for(p in arg1){
                            sR.thisCallArgs.eval(p) = arg1[p];
                        }
                    }else if(typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')){
                        sR.thisCallArgs.slideSpeed = arg1;
                    }else{
                        sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
                    }
    
                    if(typeof arg2 == 'string'){
                        sR.thisCallArgs.easing = arg2;
                    }else if(typeof arg2 == 'function'){
                        sR.thisCallArgs.callback = arg2;
                    }else if(typeof arg2 == 'undefined'){
                        sR.thisCallArgs.easing = sR.defaults.easing;    
                    }
                    if(typeof arg3 == 'function'){
                        sR.thisCallArgs.callback = arg3;
                    }else if(typeof arg3 == 'undefined' && typeof arg2 != 'function'){
                        sR.thisCallArgs.callback = sR.defaults.callback;    
                    }
                    var $cells = $(this).children('td, th');
                    $cells.wrapInner('<div class="slideRowUp" />');
                    var currentPadding = $cells.css('padding');
                    $cellContentWrappers = $(this).find('.slideRowUp');
                    $cellContentWrappers.slideUp(sR.thisCallArgs.slideSpeed, sR.thisCallArgs.easing, function(){
                        $(this).parent().animate({ paddingTop: '0px', paddingBottom: '0px' }, {
                            complete: function(){
                                $(this).children('.slideRowUp').replaceWith($(this).children('.slideRowUp').contents());
                                $(this).parent().css({ 'display': 'none' });
                                $(this).css({ 'padding': currentPadding });
                            }
                        });
                    });
                    var wait = setInterval(function(){
                        if($cellContentWrappers.is(':animated') === false){
                            clearInterval(wait);
                            if(typeof sR.thisCallArgs.callback == 'function'){
                                sR.thisCallArgs.callback.call(this);
                            }
                        }
                    }, 100);                                                                                                    
                    return $(this);
                }
              , down: function (arg1, arg2, arg3){
                    if(typeof arg1 == 'object'){
                        for(p in arg1){
                            sR.thisCallArgs.eval(p) = arg1[p];
                        }
                    }else if(typeof arg1 != 'undefined' && (typeof arg1 == 'number' || arg1 == 'slow' || arg1 == 'fast')){
                        sR.thisCallArgs.slideSpeed = arg1;
                    }else{
                        sR.thisCallArgs.slideSpeed = sR.defaults.slideSpeed;
                    }
    
                    if(typeof arg2 == 'string'){
                        sR.thisCallArgs.easing = arg2;
                    }else if(typeof arg2 == 'function'){
                        sR.thisCallArgs.callback = arg2;
                    }else if(typeof arg2 == 'undefined'){
                        sR.thisCallArgs.easing = sR.defaults.easing;    
                    }
                    if(typeof arg3 == 'function'){
                        sR.thisCallArgs.callback = arg3;
                    }else if(typeof arg3 == 'undefined' && typeof arg2 != 'function'){
                        sR.thisCallArgs.callback = sR.defaults.callback;    
                    }
                    var $cells = $(this).children('td, th');
                    $cells.wrapInner('<div class="slideRowDown" style="display:none;" />');
                    $cellContentWrappers = $cells.find('.slideRowDown');
                    $(this).show();
                    $cellContentWrappers.slideDown(sR.thisCallArgs.slideSpeed, sR.thisCallArgs.easing, function() { $(this).replaceWith( $(this).contents()); });
    
                    var wait = setInterval(function(){
                        if($cellContentWrappers.is(':animated') === false){
                            clearInterval(wait);
                            if(typeof sR.thisCallArgs.callback == 'function'){
                                sR.thisCallArgs.callback.call(this);
                            }
                        }
                    }, 100);
                    return $(this);
                }
            }
        };
    
        $.fn.slideRow = function(method, arg1, arg2, arg3){
            if(typeof method != 'undefined'){
                if(sR.methods[method]){
                    return sR.methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
                }
            }
        };
    })(jQuery);
    

I neded a table with hidden rows that slide in and out of view on row click.

_x000D_
_x000D_
$('.tr-show-sub').click(function(e) {  _x000D_
    var elOne = $(this);_x000D_
    $('.tr-show-sub').each(function(key, value) {_x000D_
        var elTwoe = $(this);_x000D_
        _x000D_
        if(elOne.get(0) !== elTwoe.get(0)) {_x000D_
            if($(this).next('.tr-sub').hasClass('tr-sub-shown')) {_x000D_
                elTwoe.next('.tr-sub').removeClass('tr-sub-shown');_x000D_
                elTwoe.next('tr').find('td').find('div').slideUp();_x000D_
                elTwoe.next('tr').find('td').slideUp();_x000D_
            }_x000D_
        }_x000D_
        _x000D_
        if(elOne.get(0) === elTwoe.get(0)) {_x000D_
            if(elOne.next('.tr-sub').hasClass('tr-sub-shown')) {_x000D_
                elOne.next('.tr-sub').removeClass('tr-sub-shown');_x000D_
                elOne.next('tr').find('td').find('div').slideUp();_x000D_
                elOne.next('tr').find('td').slideUp();_x000D_
            } else {_x000D_
                elOne.next('.tr-sub').addClass('tr-sub-shown');_x000D_
                elOne.next('tr').find('td').slideDown();_x000D_
                elOne.next('tr').find('td').find('div').slideDown();_x000D_
            }_x000D_
        }_x000D_
    })_x000D_
});
_x000D_
body {_x000D_
        background: #eee;_x000D_
    }_x000D_
    _x000D_
    .wrapper {_x000D_
        margin: auto;_x000D_
        width: 50%;_x000D_
        padding: 10px;_x000D_
        margin-top: 10%;_x000D_
    }_x000D_
    _x000D_
    table {_x000D_
        background: white;_x000D_
        width: 100%;_x000D_
    }_x000D_
    _x000D_
    table th {_x000D_
        background: gray;_x000D_
        text-align: left;_x000D_
    }_x000D_
    _x000D_
    table th, td {_x000D_
        border-bottom: 1px solid lightgray;_x000D_
        padding: 5px;_x000D_
    }_x000D_
    _x000D_
    table .tr-show-sub {_x000D_
        background: #EAEAEA;_x000D_
        cursor: pointer;_x000D_
    }_x000D_
_x000D_
    table .tr-sub td {_x000D_
        display: none;_x000D_
    }_x000D_
    _x000D_
    table .tr-sub td .div-sub {_x000D_
        display: none;_x000D_
    }
_x000D_
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>_x000D_
<div class="wrapper">_x000D_
    <table cellspacing="0" cellpadding="3">_x000D_
        <thead>_x000D_
            <tr class="table">_x000D_
                <th>col 1</th>_x000D_
                <th>col 2</th>_x000D_
                <th>col 3</th>_x000D_
            </tr>_x000D_
        </thead>_x000D_
        <tbody>_x000D_
            <tr class="tr-show-sub">_x000D_
                <td>col 1</td>_x000D_
                <td>col 2</td>_x000D_
                <td>col 3</td>_x000D_
            </tr>_x000D_
            <tr class="tr-sub">_x000D_
                <td colspan="5"><div class="div-sub">_x000D_
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis auctor tortor sit amet sem tempus rhoncus. Etiam scelerisque ligula id ligula congue semper interdum in neque. Vestibulum condimentum id nibh ac pretium. Proin a dapibus nibh. Suspendisse quis elit volutpat, aliquet nisi et, rhoncus quam. Quisque nec ex quis diam tristique hendrerit. Nullam sagittis metus sem, placerat scelerisque dolor congue eu. Pellentesque ultricies purus turpis, convallis congue felis iaculis sed. Cras semper elementum nibh at semper. Suspendisse libero augue, auctor facilisis tincidunt eget, suscipit eu ligula. Nam in diam at ex facilisis tincidunt. Fusce erat enim, placerat ac massa facilisis, tempus aliquet metus. Fusce placerat nulla sed tristique tincidunt. Duis vulputate vestibulum libero, nec lobortis elit ornare vel. Mauris imperdiet nulla non suscipit cursus. Sed sed dui ac elit rutrum mollis sed sit amet lorem. _x000D_
                </div></td>_x000D_
            </tr>_x000D_
            <tr class="tr-show-sub">_x000D_
                <td>col 1</td>_x000D_
                <td>col 2</td>_x000D_
                <td>col 3</td>_x000D_
            </tr>_x000D_
            <tr class="tr-sub">_x000D_
                <td colspan="5"><div class="div-sub">_x000D_
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis auctor tortor sit amet sem tempus rhoncus. Etiam scelerisque ligula id ligula congue semper interdum in neque. Vestibulum condimentum id nibh ac pretium. Proin a dapibus nibh. Suspendisse quis elit volutpat, aliquet nisi et, rhoncus quam. Quisque nec ex quis diam tristique hendrerit. Nullam sagittis metus sem, placerat scelerisque dolor congue eu. Pellentesque ultricies purus turpis, convallis congue felis iaculis sed. Cras semper elementum nibh at semper. Suspendisse libero augue, auctor facilisis tincidunt eget, suscipit eu ligula. Nam in diam at ex facilisis tincidunt. Fusce erat enim, placerat ac massa facilisis, tempus aliquet metus. Fusce placerat nulla sed tristique tincidunt. Duis vulputate vestibulum libero, nec lobortis elit ornare vel. Mauris imperdiet nulla non suscipit cursus. Sed sed dui ac elit rutrum mollis sed sit amet lorem. _x000D_
                </div></td>_x000D_
            </tr>_x000D_
            <tr>_x000D_
                <td>col 1</td>_x000D_
                <td>col 2</td>_x000D_
                <td>col 3</td>_x000D_
            </tr>_x000D_
        </tbody>_x000D_
    </table>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to animation

Simple CSS Animation Loop – Fading In & Out "Loading" Text Slidedown and slideup layout with animation How to have css3 animation to loop forever jQuery animated number counter from zero to value CSS Auto hide elements after 5 seconds Fragment transaction animation: slide in and slide out Android Animation Alpha Show and hide a View with a slide up/down animation Controlling fps with requestAnimationFrame? powerpoint loop a series of animation

Examples related to html-table

Table column sizing DataTables: Cannot read property 'length' of undefined TypeError: a bytes-like object is required, not 'str' in python and CSV How to get the <td> in HTML tables to fit content, and let a specific <td> fill in the rest How to stick table header(thead) on top while scrolling down the table rows with fixed header(navbar) in bootstrap 3? Sorting table rows according to table header column using javascript or jquery How to make background of table cell transparent How to auto adjust table td width from the content bootstrap responsive table content wrapping How to print table using Javascript?

Examples related to slidedown

Slidedown and slideup layout with animation How to Use slideDown (or show) function on a table row?