Prevent resize on draw

Prevent resize on draw

GregPGregP Posts: 487Questions: 8Answers: 0
edited May 2016 in Free community support

Interesting rendering issue, and it seems like DT already has the solution internally, but I'm coming across it by accident!!

This is in Chrome, DT 1.10. Example of a config:

    {
        "info": false,
        "searching": false,
        "stateSave": true,
        "scrollX": true,
        "paging": true,
        "ajax": {
          "url": url,
          "data": function () {
            return centralJS.selectedItemsHashtable()
          },
          "dataSrc": function (json) {
            var dataSet = json.mapSessions;
            amplify.publish("newData", json);
            return dataSet;
          },
          "error": function (jqXHR, textStatus, errorThrown) {
            amplify.publish("genericError", jqXHR);

          }
        },
        "createdRow": function (row, data, dataIndex) {
          $(row).data('itemData', data);
        },
        "columns": [
          {"data": "source.nodeName"},
          {"data": "destination.nodeName"},
          {"data": "username"},
          {"data": "transferStart"},
          {"data": "status"},
          {"data": "filename"},
          {"data": "transferRate"},
          {"data": "rtt"},
          {"data": "timeRemaining"}
        ]
      }

Steps:

  1. Create a table that well exceeds the height of the viewport/window. The viewport/window should not have a static height set on it (ie it should be auto). A table with 100 entries will usually do it.
  2. Scroll down the WINDOW to the bottom of the table (not scrollY within the DT).
  3. Reload the table. (note: I am using Ajax data source)

Observe: your scrollbar is jumped up. I presume this is because for a brief moment, the DT was emptied before it had the new rows inserted. The window shrank back down to its auto size (containing the empty table), and then when the table got embiggened, the scroll handle stayed up near the top.

Now here's an interesting edge case:

  1. Prepare for such a test, but the table is only showing 10/25 or whatever by default (mine is 25).
  2. Select "100 entries" from the page length drop down.

Observe: when you scroll down, it stays scrolled down on table reload! This is the desired behaviour. Awesome!

  1. Navigate to page 2 using the pagination widget.

Observe: the scrollbar jumping is back. Dang! Why was it fine for a brief shining moment??

Thanks for any help! If it's just a configurable option I've missed, that'd be super sweet! Very curious about that second test case, too... mainly just for idle curiosity... how can it work by changing the length, but then be lost by navigating? So interesting....

Answers

  • GregPGregP Posts: 487Questions: 8Answers: 0
    edited May 2016

    Huh. I don't think the body size is actually changing, just the scroll position... I will need to investigate any instances of manipulating the scrollbar (shouldn't be any) and I wonder if that stateSave has anything to do with it.

    The issue IS resolved by setting a large enough min-height on the tables... which is why I believe it's at the table level.

    Information that may not turn out to be incidental: I have multiple DTs on this page.

  • allanallan Posts: 61,920Questions: 1Answers: 10,153 Site admin

    Interesting indeed! When you call ajax.reload() it internally called this method - note that it doesn't actually manipulate the DOM at all, it just truncates the storage arrays DataTables has. It leaves the DOM tidy up to the draw (a note for the interested reader - this doesn't mean that there is a memory leak with DOM elements floating around that don't have a reference in Javascript - it needs a draw to tidy them up).

    The way the draw works is it uses a document fragment and simply replaces the existing DOM elements with the new ones to show. So there shouldn't be a case where the table shrinks and then suddenly grows.

    Having said that, scrolling does complicate matters - and to be honest, I'd need to step through the code to recall exactly what is happening there. Are you using a reasonably new version of DT, or an old one?

    Allan

  • GregPGregP Posts: 487Questions: 8Answers: 0
    edited May 2016

    Reasonably new. Let's see here....

    1.10.8

    Given the information in your response, I'm wondering if I'm being too quick to ignore my own code. I should set up a few tables with bog-standard options to see if it's still happening.

    A bit more information I had forgotten which might be important:

    We are using the Bootstrap integration files, as well as providing a custom function for dom formatting. The initial draw depends on a "caption" element, which is used to store a title (why not the "title" attribute you ask? Mainly because I am including markup, and although I could store markup in a title attribute somehow, it'd be ugly). The custom dom filter grabs the contents of the caption and moves them to a Bootstrap table header.

    Here's that method, though it probably doesn't factor in. Not trying to create a red herring, just rambling like I do:

    $.fn.dataTable.HeadingFromCaption = function (settings) {
      var $table = $(settings.nTable);
      var $caption = $table.find('caption');
      var tableId = $table.attr('id');
      if ($caption.length > 0) {
        var captionClass = $caption.attr('class');
        var captionId = $caption.attr('id');
        var newElement = '<div class="link-emulation dataTables_title';
        if (typeof captionClass !== "undefined") {
          newElement += " "
                  + captionClass;
        }
        newElement += '" ';
        if (typeof captionId !== "undefined") {
          newElement += 'id="'
                  + captionId
                  + '"';
        }
        newElement += '>'
                + '<i class="fa fa-minus-square panelToggle" data-toggle="' + tableId + '"></i>&nbsp;'
                + $caption.html()
                + '</div>';
        $caption.hide();
        return newElement;
      }
    };
    
    $.fn.dataTable.ext.feature.push({
      fnInit: function (settings) {
        var heading = $.fn.dataTable.HeadingFromCaption(settings);
        return heading;
      },
      cFeature: 'T'
    });
    

    And we are also overriding the dom template that comes with the Bootstrap integration files, thus:

    /* Set the defaults for DataTables initialisation */
    $.extend(true, $.fn.DataTable.defaults, {
      dom: "<'panel panel-default panel-shadow'<'panel-heading row'<'col-sm-4'T><'col-sm-8'fpl>>t>",
      renderer: 'bootstrap'
    });
    

    Side note: if you like, I can find a way to bundle this all up as an alternate Bootstrap 3 wrapper (just in time for Bootstrap 4 to arrive, mind you...!) It produces quite a clean-looking table.

    Anyhow, I don't know if that caption (which, per spec, is an element right inside the table element) is the issue, or if custom cFeatures can throw the rendering out of wack... but for what it's worth, that's some information that could prove handy.

  • allanallan Posts: 61,920Questions: 1Answers: 10,153 Site admin

    I don't see anything in that code that springs out at me as obviously going to cause an issue. I suspect its going to need stepping through the code in a debugger to see where the jump occurs.

    Allan

  • GregPGregP Posts: 487Questions: 8Answers: 0

    Allan, let me step through first to see what I can see. I fear it's my own bespoke code, and I wouldn't wish code-stepping upon you for something that turns out to be my own fault. I'll report back.

This discussion has been closed.