浏览代码

HUE-3960 [editor] Implement virtual rendering of the result table

Enrico Berti 9 年之前
父节点
当前提交
98a9a01

+ 81 - 22
desktop/core/src/desktop/static/desktop/js/jquery.huedatatable.js

@@ -24,7 +24,7 @@
     var self = this;
     self.$table = null;
 
-    self.fnSetColumnVis = function(index, visible) {
+    self.fnSetColumnVis = function (index, visible) {
       var aoColumns = this.$table.data('aoColumns');
       var change = aoColumns[index].bVisible !== visible;
       aoColumns[index].bVisible = visible;
@@ -38,12 +38,74 @@
       }
     }
 
-    self.fnDraw = function () {};
+    self.isDrawing = false;
+    self.fnDraw = function () {
+      if (!self.isDrawing) {
+        self.isDrawing = true;
+        var rowHeight = 29;
+        var $t = self.$table;
+
+        var aoColumns = self.$table.data('aoColumns');
+        var appendable = $t.children('tbody').length > 0 ? $t.children('tbody') : $t;
+
+        var invisibleOffset = aoColumns.length > 30 ? 1 : 10;
+
+
+        var scrollable = $t.parents($t.data('oInit')['scrollable']);
+        var visibleRows = Math.ceil(scrollable.height() / rowHeight) + invisibleOffset;
+
+        var startRow = $t.offset().top - 73 < 0 ? Math.max(Math.floor(Math.abs($t.offset().top - 73) / rowHeight) - invisibleOffset, 0) : 0;
+        var endRow = startRow + visibleRows;
+
+        var northSpace = rowHeight * startRow;
+        if ($t.find('.ht-north-spacer').length === 0) {
+          $('<tr>').addClass('ht-north-spacer').html('<td colspan="' + (aoColumns.length) + '" style="display: none"></td>').appendTo(appendable);
+        }
+        else {
+          if (northSpace > 0) {
+            $t.find('.ht-north-spacer td').show().height(northSpace);
+          }
+          else {
+            $t.find('.ht-north-spacer td').hide();
+          }
+        }
+
+        $t.find('.ht-visible-row').remove();
+
+        var html = '';
+        for (var i = startRow; i < Math.min(startRow + visibleRows, $t.data('data').length); i++) {
+          var row = $t.data('data')[i];
+          html += '<tr class="ht-visible-row ht-visible-row-' + i + '">';
+          for (var j = 0; j < aoColumns.length; j++) {
+            html += '<td class="ht-cell-' + i + '-' + j + '">' + row[j] + '</td>';
+          }
+          html += '</tr>';
+        }
+
+        $t.find('.ht-north-spacer').after(html);
+
+        var southSpace = rowHeight * ($t.data('data').length - endRow);
+        if ($t.find('.ht-south-spacer').length === 0) {
+          $('<tr>').addClass('ht-south-spacer').html('<td colspan="' + (aoColumns.length) + '" style="height: ' + southSpace + 'px"></td>').appendTo(appendable);
+        }
+        else {
+          $t.find('.ht-south-spacer td').height(southSpace);
+        }
+
+        if ($t.data('oInit')['fnDrawCallback']) {
+          $t.data('oInit')['fnDrawCallback']();
+        }
+        self.isDrawing = false;
+      }
+    };
 
     self.fnAddData = function (mData, bRedraw) {
-      var aoColumns = this.$table.data('aoColumns');
+      var aoColumns = self.$table.data('aoColumns') || [];
 
       var $t = self.$table;
+
+      $t.data('data', $t.data('data').concat(mData));
+
       if (mData.length === 0) {
         return;
       }
@@ -56,26 +118,8 @@
         })
       }
 
+      self.fnDraw();
 
-      var appendable = $t.children('tbody').length > 0 ? $t.children('tbody') : $t;
-      var html = '';
-      mData.forEach(function (row) {
-        html += '<tr>';
-        var index = 0;
-        row.forEach(function (cell) {
-          if (aoColumns[index].bVisible) {
-            html += '<td>' + cell + '</td>';
-          } else {
-            html += '<td style="display: none;">' + cell + '</td>';
-          }
-          index++;
-        });
-        html += '</tr>';
-      });
-      appendable.append(html);
-      if (oInit['fnDrawCallback']){
-        oInit['fnDrawCallback']();
-      }
     };
 
     self.fnSettings = function () {
@@ -93,9 +137,11 @@
       else {
         $t.children('tr').remove();
       }
+      $t.data('data', []);
     };
 
     self.fnDestroy = function () {
+      self.fnClearTable();
       self.$table.unwrap();
       self.$table.removeClass('table-huedatatable');
     };
@@ -106,9 +152,22 @@
       if (parent.hasClass('dataTables_wrapper')) {
         return;
       }
+      self.$table.data('data', []);
       self.$table.data('aoRows', []);
       self.$table.data('aoColumns', []);
       self.$table.wrap('<div class="dataTables_wrapper"></div>');
+
+      if (typeof oInit !== 'undefined') {
+        self.$table.data('oInit', oInit);
+        var drawTimeout = -1;
+        if (self.$table.data('oInit')['scrollable'] && !self.$table.data('isScrollAttached')) {
+          self.$table.data('isScrollAttached', true);
+          self.$table.parents(oInit['scrollable']).on('scroll', function () {
+            window.clearTimeout(drawTimeout);
+            drawTimeout = window.setTimeout(self.fnDraw, 50);
+          });
+        }
+      }
       self.$table.addClass('table-huedatatable');
     });
   };

+ 12 - 95
desktop/libs/notebook/src/notebook/templates/editor_components.mako

@@ -2200,11 +2200,11 @@ ${ hueIcons.symbols() }
   function createHueDatatable(el, snippet, vm) {
     var DATATABLES_MAX_HEIGHT = 330;
     var _dt = $(el).hueDataTable({
-      "oLanguage": {
+      oLanguage: {
         "sEmptyTable": "${_('No data available')}",
         "sZeroRecords": "${_('No matching records')}"
       },
-      "fnDrawCallback": function (oSettings) {
+      fnDrawCallback: function (oSettings) {
         if (vm.editorMode()) {
           DATATABLES_MAX_HEIGHT = $(window).height() - $(el).parent().offset().top - 40;
           $(el).parents('.dataTables_wrapper').css('overflow-x', 'hidden');
@@ -2235,80 +2235,8 @@ ${ hueIcons.symbols() }
             clonedContainerPosition: "absolute"
           });
         }
-      }
-    });
-
-    if (vm.editorMode()) {
-      $(el).parents('.dataTables_wrapper').css('overflow-x', 'hidden');
-      $(el).jHueHorizontalScrollbar();
-    } else {
-      $(el).parents(".dataTables_wrapper").jHueTableScroller({
-        maxHeight: DATATABLES_MAX_HEIGHT,
-        heightAfterCorrection: 0,
-        enableNiceScroll: true
-      });
-    }
-
-    return _dt;
-  }
-
-  function createRegularDatatable(el, snippet, vm) {
-    var DATATABLES_MAX_HEIGHT = 330;
-    var _dt = $(el).dataTable({
-      "bPaginate": false,
-      "bLengthChange": false,
-      "bInfo": false,
-      "bDestroy": true,
-      "bAutoWidth": false,
-      "oLanguage": {
-        "sEmptyTable": "${_('No data available')}",
-        "sZeroRecords": "${_('No matching records')}"
       },
-      "fnDrawCallback": function (oSettings) {
-        if (vm.editorMode()){
-          DATATABLES_MAX_HEIGHT = $(window).height() - $(el).parent().offset().top - 40;
-          $(el).parents('.dataTables_wrapper').css('overflow-x', 'hidden');
-          $(el).jHueTableExtender({
-            fixedHeader: true,
-            fixedFirstColumn: true,
-            lockSelectedRow: true,
-            includeNavigator: false,
-            parentId: 'snippet_' + snippet.id(),
-            mainScrollable: '.right-panel',
-            stickToTopPosition: vm.isPlayerMode() ? 1 : 73,
-            clonedContainerPosition: "fixed"
-          });
-          $(el).jHueHorizontalScrollbar();
-        } else {
-          $(el).parents(".dataTables_wrapper").jHueTableScroller({
-            maxHeight: DATATABLES_MAX_HEIGHT,
-            heightAfterCorrection: 0
-          });
-          $(el).jHueTableExtender({
-            fixedHeader: true,
-            fixedFirstColumn: true,
-            lockSelectedRow: true,
-            includeNavigator: false,
-            mainScrollable: '.right-panel',
-            parentId: 'snippet_' + snippet.id(),
-            clonedContainerPosition: "absolute"
-          });
-        }
-      },
-      "aoColumnDefs": [
-        {
-          "sType": "numeric",
-          "aTargets": [ "sort-numeric" ]
-        },
-        {
-          "sType": "string",
-          "aTargets": [ "sort-string" ]
-        },
-        {
-          "sType": "date",
-          "aTargets": [ "sort-date" ]
-        }
-      ]
+      scrollable: '.right-panel'
     });
 
     if (vm.editorMode()) {
@@ -2321,7 +2249,7 @@ ${ hueIcons.symbols() }
         enableNiceScroll: true
       });
     }
-    $(".dataTables_filter").hide();
+
     return _dt;
   }
 
@@ -2337,7 +2265,7 @@ ${ hueIcons.symbols() }
     }
     $(el).addClass("dt");
 
-    var _dt = snippet.result.hasManyColumns() ? createHueDatatable(el, snippet, vm) : createRegularDatatable(el, snippet, vm)
+    var _dt = createHueDatatable(el, snippet, vm);
 
     var dataTableEl = $(el).parents(".dataTables_wrapper");
 
@@ -2388,12 +2316,7 @@ ${ hueIcons.symbols() }
   }
 
   function toggleAllColumns(linkElement, snippet) {
-    var dt;
-    if (snippet.result.hasManyColumns()) {
-      dt = $(linkElement).parents(".snippet").find("table.resultTable:eq(0)").hueDataTable();
-    } else {
-      dt = $(linkElement).parents(".snippet").find("table.resultTable:eq(0)").dataTable();
-    }
+    var dt = $(linkElement).parents(".snippet").find("table.resultTable:eq(0)").hueDataTable();
     $(linkElement).parents(".snippet").find('.filtered-meta li input').each(function (idx, item) {
       dt.fnSetColumnVis(idx, linkElement.checked, false);
     });
@@ -2401,12 +2324,7 @@ ${ hueIcons.symbols() }
   }
 
   function toggleColumn(linkElement, index, snippet) {
-    var dt;
-    if (snippet.result.hasManyColumns()) {
-      dt = $(linkElement).parents(".snippet").find("table.resultTable:eq(0)").hueDataTable();
-    } else {
-      dt = $(linkElement).parents(".snippet").find("table.resultTable:eq(0)").dataTable();
-    }
+    var dt = $(linkElement).parents(".snippet").find("table.resultTable:eq(0)").hueDataTable();
     dt.fnSetColumnVis(index, linkElement.checked);
   }
 
@@ -3258,9 +3176,9 @@ ${ hueIcons.symbols() }
           $("#eT" + snippet.id() + "jHueTableExtenderClonedContainer").remove();
           $("#eT" + snippet.id() + "jHueTableExtenderClonedContainerColumn").remove();
           $("#eT" + snippet.id() + "jHueTableExtenderClonedContainerCell").remove();
-          if (_el.dataTable()) {
-            _el.dataTable().fnClearTable();
-            _el.dataTable().fnDestroy();
+          if (_el.hueDataTable()) {
+            _el.hueDataTable().fnClearTable();
+            _el.hueDataTable().fnDestroy();
           }
           _el.find("thead tr").empty();
         }
@@ -3291,10 +3209,9 @@ ${ hueIcons.symbols() }
               options.snippet.result.meta.notifySubscribers();
               $("#snippet_" + options.snippet.id()).find("select").trigger("chosen:updated");
               _dt = createDatatable(_el, options.snippet, viewModel);
-            } else if (options.snippet.result.hasManyColumns()) {
+            }
+            else {
               _dt = _el.hueDataTable();
-            } else {
-              _dt = _el.dataTable();
             }
             try {
               _dt.fnAddData(options.data);