【问题标题】:Table Column too high表格列太高
【发布时间】:2012-11-19 10:53:38
【问题描述】:

我正在使用Datatables,这是一个用于创建自定义表格的 jQuery 插件。我现在正在尝试创建一个包含许多列的表,其中至少一个包含大量文本。问题是长文本的列不是创建得更宽,而是更高,使表格更难于用户阅读。

如何使文本列更宽、更低?

这是我的问题的截图:

这是我的问题可见:

http://live.datatables.net/ujudij/edit#javascript,html

【问题讨论】:

    标签: javascript jquery datatables


    【解决方案1】:

    您可能会考虑使用 css text-overflow 属性:http://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ 并结合具有长文本的单元格的工具提示。

    【讨论】:

    • 这仅在浏览器支持 CSS3 时有效,但我会考虑工具提示的想法。
    • @Dragos 为了使用它,你必须设置一个固定的宽度和高度(除非这些已经由插件设置)。但是,这样做并设置overflow: hidden; 将在不支持text-overflow: ellipsis 的浏览器中工作。 overflow 将像 text-overflow 一样工作,只是它不会自动添加省略号。然后,您可以让td 在悬停时完全可见,或者通过其他方式来适应。除非您手动截断数据并自己添加省略号,否则这可能是您的最佳选择。
    • 这是迄今为止最好的解决方案。其他用户也建议使用工具提示(可能是 jQuery 插件 qTip)并详细说明了这个想法,但您的答案是第一位的,所以我会为您提供赏金。谢谢!
    • @Dragos:感谢您的赏金!
    【解决方案2】:

    您可以在数据表渲染完成后检查每个 td 的文本长度。如果文本长度超过您定义的限制,您可以为该表格单元格设置更大的宽度,即 td。这样,即使您不知道它在表格中的位置,您也可以加宽超出所需高度的任何单元格

    这里是代码

    $(document).ready(function() {
        $('#example').dataTable({
        "sScrollX":"100%",
        "fnInitComplete": function(oSettings, json) {
    
            $('#example tr').each(function(i){
               $('td', this).each(function(j){
                   // get length of text
                   var l = $(this).text().length;
                   // set larger width if text length is greater than 300 characters
                   if(l > 300){
                       $(this).width(400);
                   }
               });
            });
        }
      });
    });
    

    See this code demo here

    您也可以使用 var l = $(this).height(); 来使用单元格高度,但我认为这不会为您提供正确的结果,因为在调整宽度之前,其他单元格相同可能没有大文本的行也具有相同的高度,因此它们的宽度属性也将使用此更改,这不适合您的情况,我猜

    虽然我认为一个更好的主意是修剪文本以限制,添加一个“更多”链接并使用像qTip这样的插件显示全文

    【讨论】:

    • 您建议的解决方案不起作用。通过更改 td 的宽度,我毁了整个表格:标题不再匹配它的内容。这在您的演示中也可见。我会考虑您的其他建议,并可能使用 qTip。
    • 我只是用一个单元格做了一个例子,你总是可以用你的宽度更新索引“j”处的页眉和页脚单元格元素来修复它。但我认为最好不要为它带来那么多复杂性,去修剪和工具提示解决方案
    【解决方案3】:

    我写了一个小的 jQuery 插件来限制元素的文本行数,希望对你有帮助。

    /** 
    * Binaray search with callback
    */
    function bisearch(left, right, search, getter){
        var pos, result;
        if (typeof getter !== "function") {
            getter = function (x) {
                return x;
            };
        }
    
        while (left <= right) {
            pos = (left + right) / 2 | 0;
            result = getter(pos);
    
            if (result < search) {
                left = pos + 1;
            }
            else if (result > search) {
                right = pos - 1;
            }
            else {
                return pos;
            }
        }
        return -1;
    }
    
    ;(function($){
        var getLineHeight = function(el) {
            var self = el,
                $self = $(self),
                content = $self.html(),
                lineHeight;
    
            if (typeof $self.attr("style") !== "undefined") {
                orgStyleAttr = $self.attr("style");             
            }
    
            $self.html("&nbsp;").css("min-height", "0px");
            lineHeight = $self.height();
    
            $self.html(content);
    
            if (typeof orgStyleAttr !== "undefined") {
                $self.attr("style", orgStyleAttr);
            } else {
                $self.removeAttr("style");
            }
            return lineHeight;
        }
        $.fn.limitLines = function(maxLines){
            $(this).each(function(){
                var self = this,
                    $self = $(self),
                    content = $self.html(),
                    height = $self.height(),
                    lineHeight = getLineHeight($self),
                    maxHeight = lineHeight * maxLines;
    
                if (Math.floor(height/lineHeight) <= maxLines) 
                    return;
    
                // this search will stop when the text meet the line count,
                // but the last line will be of any length
                var middleOfLastLine = bisearch(0, content.length, maxLines, function (n){
                    $self.html(content.substring(0, n));
                    return Math.floor($self.height() / lineHeight); 
                });
    
                // search for position from current to current plus one more line, 
                // until we find the excact position(p) to stop,
                // where if one more letter was added, 
                // there will be a new line 
                var endOfLastLine = bisearch(middleOfLastLine, content.length, maxLines + .5, function (n){
                    $self.html(content.substring(0, n - 3) + '...');
                    var before = Math.floor($self.height() / lineHeight);
    
                    $self.html(content.substring(0, n - 2) + '...');
                    var after = Math.floor($self.height() / lineHeight);
    
                    return (before + after) / 2;
                });
                $self.html(content.substring(0, endOfLastLine -3) + '...');
            });
        };
    })(jQuery);
    

    【讨论】:

    • 我用二分搜索重写了代码,这个版本运行得更快。还添加了一个新的 getLineHeight() 函数。
    【解决方案4】:

    您需要使用aoColumnDefs,它允许您按标题或编号定位特定列,并使用插件的原生sWidth 属性设置所需列的宽度:

    $(document).ready(function() {
       var data = $('#example').dataTable({
       "sScrollX":"100%",
       "aoColumnDefs": [
       { "sWidth": "1500px", "aTargets": [5] } // this will target the 6th column (the first being 0) 
    ]
    });
    
    });  
    

    a working example

    documentation

    如果您事先不知道要定位哪些列,您可以随时获取每个单元格中字符串的length,并采取相应措施。也就是说,如果长度超过某个值。字符,您将列号添加到数组中,然后传递给aTargets

    【讨论】:

      【解决方案5】:

      你可以随意放大一列,我用的是 70% 但你也可以使用像 400px 这样的像素

      http://live.datatables.net/ajemid/4/edit

      $(document).ready(function() {
        $('#example').dataTable({
          "sScrollX":"100%",
           "aoColumnDefs": [
            { "sWidth": "70%", "aTargets": [ 0 ] }
          ]
        });
      } );
      

      "aTargets": [ 0 ] 表示第一列,1 表示第二列,依此类推。

      为了限制文本,您可以应用诸如 max-height:200px 之类的 css 属性;和溢出:隐藏;您还可以在单​​元格底部应用垂直渐变(透明到白色),为长单元格提供很好的淡入白效果。

      【讨论】:

        【解决方案6】:
        $(document).ready( function () {
        $('#example').dataTable( {
        "bAutoWidth": false
        } );
        } );
        

        稍后将width 设置为您的表中的&lt;td&gt;

        【讨论】:

        • bAutoWidth 设置为 false 并不能解决我的问题。更重要的是,为我的&lt;td&gt;s 设置不同的宽度会使表格的内容与列标题不同步。它基本上使桌子无法使用。你碰巧有其他建议吗?
        【解决方案7】:

        最简单的做法是使用nobr html 标记将进入表格的所有内容包装起来。它可能不是最优雅的解决方案,但它会起作用,您可以使用 CSS 来限制单元格宽度并设置溢出。我克隆了您的示例here

        通读 DataTables 文档,手动解决方案可能仅在您对现有 DOM 元素调用 datatable() 时才有效。如果您想在从数组或 AJAX 源加载数据时执行此操作,您可能必须使用 jQuery 以编程方式将每个表格单元格中的数据包装为 nobr 标签。这样做的好处是您可以更好地控制您决定不包装的内容。

        DataTables API 提供 pre-initpost-init API 调用 - 您可以将回调绑定到 jQuery 函数,该函数遍历表中的所有 TD 并将内容包装在 nobr 标记中。

        我希望这是有道理的。祝你好运!

        【讨论】:

        • 你说的很有道理。 white-space:nowrap 也可以做到这一点。这里的问题是我得到一个很长的列,因此用另一个问题替换了一个问题。如果我添加一个overflow:auto,按照您的建议控制宽度,我将得到一个带有可滚动单元格的可滚动表格-scrollception :D。感觉有点奇怪。关于如何避免创建更多卷轴,您还有其他建议吗?
        【解决方案8】:

        你可以让它滚动条自动出现在超大数据上

        <style>
        .box{width:250;height:75;overflow:auto}
        </style>
        
        <div class="box" >your data here will only have a scrollbar if it overflows your predefined height width parameters</div>
        

        【讨论】:

          【解决方案9】:

          为每列指定您自己的宽度。

          $(document).ready(function() {
            $('#example').dataTable({
              "sScrollX":"100%",
              "aoColumns": [
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" },
                { "sWidth": "30%" }
              ]
            });
          } );
          

          【讨论】:

          • 这不会改变任何东西。这可能是因为所有 sWidths 的总和大于 100%,这就是忽略规范的原因。
          【解决方案10】:

          您的解决方案是%

          将此 td 类的名称从 odd gradeA 更改为 what_ever 并添加此

              width: 80%;
          

          当然你可以随心所欲地玩它。

          或者改变这个

           <tr class="odd gradeA"> //of the long text
          

            <tr style="width: 80%">  
          

          和所有其他tds 将被触发 所以你也可以对其他tds 做同样的事情% 希望对你有帮助

          【讨论】:

            【解决方案11】:

            在我看来你应该限制你的脚本在服务器端的输出,它会创造更好的视觉效果,但也会节省一些带宽,并会减少页面负载

            【讨论】:

              【解决方案12】:

              即兴发挥@Burhan 的回复:您可以限制单元格中直接显示的字符并将其添加到单元格的标题中,以便创建工具提示类效果(== qTip??)

              $(document).ready(function() {
                  $('#example').dataTable({
                  "sScrollX":"100%",
                  "fnInitComplete": function(oSettings, json) {
              
                      $('#example tr').each(function(i){
                         $('td', this).each(function(j){
                             // get length of text
                             var l = $(this).text().length;
                             var limit = 200;
                             // set larger width if text length is greater than 300 characters
                             if(l > limit){
                                 $(this).attr('title',$(this).text())
                                        .text($(this).text().substr(0,limit));
                             }
                         });
                      });
                  }
                });
              });
              

              将限制变量更改为您觉得舒适的任何值.........

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-02-28
                • 1970-01-01
                • 2011-02-12
                相关资源
                最近更新 更多