How to get accurate height of table on various re-draw events?

How to get accurate height of table on various re-draw events?

astollerastoller Posts: 6Questions: 2Answers: 1

SCENARIO
I have a grid-layout section on my page that looks something like the following (hopefully this comes out clearly):

    +-------------------+------------------------------------+
    |                   |                   a                |
    |                   +------------------------------------+
    |          T        |                                    |
    |                   |                   b                |
    |                   |                                    |
    +-------------------+------------------------------------+

Where:
* 'T' represents an id'd DataTable table (paginated) sitting within an id'd div
* 'a' represents an id'd div containing an h1 title
* 'b' represents an id'd div area containing various pieces of id'd spans that are to be hidden/exposed based on what is selected in the table (T)

My goal is to make sure that the height of the 'b' div is the height of the 'T' table minus the height of the 'a' div.

CODE SO FAR
My code looks like this:

    var table = $('#lyric_table').DataTable({
        ...
    }).on('draw', function() {
        var h1 = $("#table_area").height();
        var h2 = $("#lyric_title").height();
        var h3 = h1 - h2;
        console.log(h1 + " - " + h2 + " = " + h3); /*#=#*/
        $("#lyric_area").height(h3);
    }).on('length', function() {
        var h1 = $("#table_area").height();
        var h2 = $("#lyric_title").height();
        var h3 = h1 - h2;
        console.log(h1 + " - " + h2 + " = " + h3); /*#=#*/
        $("#lyric_area").height(h3);
    }).on('page', function() {
        var h1 = $("#table_area").height();
        var h2 = $("#lyric_title").height();
        var h3 = h1 - h2;
        console.log(h1 + " - " + h2 + " = " + h3); /*#=#*/
        $("#lyric_area").height(h3);
    }).on('click', 'tbody tr', function(event) {
        ...
    });

Notes:
* #table_area is the id of the DataTable (T) - not the div it is within
* #lyric_title is the id of the div (a) in which the heading for the second major column appears
* #lyric_area is the id of the div (b) in which various sections of text will be hidden/exposed based on what is selected in table (T)

CONSOLE LOG RESULTS:
(line numbers changed to correspond with above)
* 487 - 40 = 447 (my.js, line 7)
[Above: initial rendering of page/table with 15 rows displayed - draw event]
* 487 - 40 = 447 (my.js, line 13)
* 717 - 40 = 677 (my.js, line 7)
[Above: changed to 25 rows displayed - length, then draw event]
* 717 - 40 = 677 (my.js, line 13)
* 717 - 40 = 677 (my.js, line 7)
[Above: changed back to 15 rows displayed - length then draw event]
* 717 - 40 = 677 (my.js, line 19)
* 717 - 40 = 677 (my.js, line 7)
[Above: changed to next page of table, still with 15 rows displayed - page then draw event]

PROBLEM(S):
As can be seen from above, once I've increased the number of rows displayed, the height of the #table_area correctly increased, but when I decrease the number of rows displayed, the height of the #table_area does not correctly (IMO) decrease accordingly. Nor, when I go to a new page in the table with the reduced number of rows does the height of the #table_area adjust back to the lower number.
Is this a bug, am I doing something wrong here, or is this truly the correct and expected behavior (if so, why)?

Additionally, I could not figure out a way to put my 4-5 lines of code into a named function and call it by name from the on(event, ...) directive to avoid replicating the code N-times. Is there a way to do that? If so, please elaborate.

Thanks in advance,

This question has an accepted answers - jump to answer

Answers

  • astollerastoller Posts: 6Questions: 2Answers: 1

    I should also mention that if I do a Search - it appears to call the "draw" code (line 7) multiple times, all with the same resulting numbers.
    This is the one case where I'd like to not adjust the height of 'b' - so, assuming I can get the initial problem resolved, is there a way to distinguish changes to the number of rows (height of table) due to Search as opposed to changes to the Show N entries drop-down menu?

  • colincolin Posts: 15,236Questions: 1Answers: 2,598

    Hi @astoller ,

    This thread here might help. It keeps the table at a consistent height, so that would make your sums a bit easier.

    Cheers,

    Colin

  • astollerastoller Posts: 6Questions: 2Answers: 1
    Answer ✓

    @colin,

    Thanks, but while that solution would help when reducing the number of cells (such as in the case of either choosing to show fewer entries per page or filtering via Search - a definite possibility, though it doesn't seem to identify how one might determine that a filter was applied) - it doesn't help with the changing of the number of entries up, then down since row-height is not a constant (due to potentially wrapped lines)

    However - it did make me think about this in a slightly different way and I managed to come up with a solution:

    var titleId = ""; /* previously present but not documented in posting */
    var lyricId = ""; /* previously present but not documented in posting */
    var minLyricHeight = 0; /* new */
    
    var table = $('#lyric_table').DataTable({
        ...
    }).on('draw', function() {
        var lyricHeight = getLyricHeight(table); /* the main part of the solution - see below */
        /* this code takes care of setting, and sticking to, a minimum height for the lyric area based on the initial rendering */
       /* especially useful for handling results of search filtering */
        if (minLyricHeight == 0) {
            minLyricHeight = lyricHeight;
        }
        else if (lyricHeight < minLyricHeight) {
            lyricHeight = minLyricHeight;
        }
        $("#lyric_area").height(lyricHeight);
    }).on('page.dt', function() {  /* new code to handle clearing lyric area on paging */
        clearState();
    }).on('search.dt', function() { /* new code to handle clearing lyric area on search filtering */
        clearState();
    }).on('click', 'tbody tr', function(event) { /* code unchanged from original to hide/show lyrics based on selected title */
        ...
    });
    table.order([0, "asc"]).draw();
    
    /* ==== NEW ROUTINES ==== */
    /* Calculate height by adding the height of the table heading(s) and content row(s) */
    function getLyricHeight(tbl) {
        var h = getHeight($(tbl.header()));
        var b = getHeight($(tbl.body()));
        var res = h+b;
        console.log("HEIGHT: ("+h+" + "+b+") = "+res);/*#=#*/
        return res;
    }
    
    /* iterate over [header or body] table rows to get cumulative height */
    function getHeight(obj) {
        var kids = $(obj).children();
        var nkids = kids.length;
        var height = 0;
        for (var i = 0; i < nkids; i++) {
            var hdr = $(kids[i]).height();
            height += hdr;
        }
        return height;
    }
    
    /* clear state when switching pages or search filtering */
    function clearState() {
        if (lyricId != "") {
            $("#"+lyricId).addClass("hidden");
            $("#"+titleId).removeClass("selected");
            lyricId = "";
            titleId = "";
        }
    }
    
  • astollerastoller Posts: 6Questions: 2Answers: 1

    (is there a way as marking my own post as "the answer"?)

This discussion has been closed.