【问题标题】:Jquery - Truncate Text by Line (not by character count)Jquery - 按行截断文本(不是按字符数)
【发布时间】:2011-03-09 00:31:42
【问题描述】:

我需要一个 Jquery 脚本来逐行(而不是按字符数)截断文本。

我想实现一个均匀截断的文本块。它应该有一个“更多”和“更少”的链接来扩展和缩短文本段落。我的文本段落包含在一个带有类的 div 中,如下所示:

<div class="content">
<h2>Headline</h2>
<p>The paragraph Text here</p>
</div>

我可以在 SOF 上找到的最接近的解决方案是以下解决方案(但它适用于 textarea 元素,对我不起作用): Limiting number of lines in textarea

非常感谢您提供的任何提示。 本

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    对于基本方法,您可以查看line-height CSS 属性并在计算中使用它。请记住,这种方法不会考虑大于该高度的其他内联元素(例如图像)。

    如果您想要更高级的东西,您可以使用getClientRects() 函数获取有关每一行的信息。此函数返回 TextRectangle 对象的集合,每个对象具有宽度、高度和偏移量。

    请参阅此处的this answer,了解getClientRects() 工作原理的示例(尽管目标无关)。


    更新,有一点时间回来用一个实际的例子更新这个答案。这是基本的,但你明白了:

    http://jsbin.com/ukaqu3/2

    几点建议:

    • getClientRects 返回的集合是静态的,如果包含元素的尺寸发生变化,它不会自动更新。我的示例通过捕获窗口的调整大小事件来解决此问题。

    • 出于一些我不理解的奇怪的标准遵从原因,您调用 getClientRects 的元素必须是内联元素。在我的示例中,我使用了一个容器 div,其中的文本位于另一个 div 中,其中 display: inline

    【讨论】:

    • 这是前进的方向,当然。不知道这个,+1
    • 看起来可以用的东西,谢谢。不过,不幸的是,我不够聪明,无法将整个脚本放在一起,包括更多/更少链接。有人知道怎么做吗?
    • @Bento:真正的问题是 javascript 要求先呈现内容,然后再进行修改。所以你有一个权衡,要么完整地呈现内容并在准备好时将其缩小,或者将其隐藏起来,然后在文档准备好时显示你需要的数量。这是一个非常笨拙的设计,您最好将此问题标记为已回答并询问另一个问题以获得更好的建议。
    • 我不确定所有用于文本截断的 Jquery 脚本如何处理它,即之前/之后。目前我正在使用以下脚本并且效果不可见(以防它s rendering the HTML first and then truncates): http://plugins.learningjquery.com/expander/ It cant 任务太难,因为那里有很多 Jquery 插件,但没有提供逐行截断(仅按字符): plugins.jquery.com/search/node/… 您建议哪些问题?不知道如何用不同的词表达这个问题。感谢您的回复。
    【解决方案2】:

    我编写了这个小 jQuery 代码,允许我逐行截断文本块(通过 CSS 类),请随意使用和评论它。

    这里是jsFiddle,它还包括按字符数或字数截断函数。可以看到目前,调整窗口大小不会刷新块显示,我正在处理。

    /*
    *   Truncate a text bloc after x lines
    *   <p class="t_truncate_l_2">Lorem ipsum magna eiusmod sit labore.</p>
    */  
    $("*").filter(function () { 
        return /t_truncate_l_/.test($(this).attr('class')); 
    }).each(function() {
        var el = $(this);
        var content = el.text();
        var classList = el.attr('class').split(/\s+/);
        $.each(classList, function(index, item){
            if(/^t_truncate_l_/.test(item)) {
                var n = item.substr(13);
                var lineHeight = parseInt(el.css('line-height'));
                if(lineHeight == 1 || el.css('line-height') == 'normal')
                    lineHeight = parseInt(el.css('font-size')) * 1.3;
                var maxHeight = n * lineHeight;
                var truncated = $.trim(content);
                var old; 
                if(el.height() > maxHeight)
                    truncated += '...';
                while(el.height() > maxHeight && old != truncated) {
                    old = truncated;
                    truncated = truncated.replace(/\s[^\s]*\.\.\.$/, '...'); 
                    el.text(truncated);
                }
            }
        });
    });
    

    【讨论】:

      【解决方案3】:

      为什么不用溢出来制作 p 元素:隐藏;给出固定的行高,计算 div 的高度,以便 id 包含您需要的行数,并且唯一从 javascript 更改 p 的高度。

      p{
          overflow:hidden;
          line-height:13px;
          height:26px; /* show only 2 rows */
      }
      <script type="text/javascript">
          function seeMoreRows(){
              $(p).height("52px");
          }
      </script>
      

      【讨论】:

      • 感谢您的提示。虽然,它似乎不够灵活,因为页面上的所有段落都有不同的长度(它实际上是一个新闻项目列表)。如果我将其扩展到即 52px,它可能对某些人来说空间不足,而对其他人来说空间太大。它需要以某种方式动态化。
      • 这是一个例子,我认为您可以动态计算新高度,但安迪的答案看起来比我的想法更好。
      【解决方案4】:

      我制作了一个小模块,可以处理纯文本内容,不允许嵌套标签,也不允许在包含文本的元素上使用 css-padding(但可以轻松添加此功能)。

      HTML:

      <p class="ellipsis" data-ellipsis-max-line-count="3">
          Put some multiline text here
      </p>
      

      Javascript/Jquery:

      ( function() {
      
      $(document).ready(function(){
          store_contents();
          lazy_update(1000);
      });
      
      // Lazy update saves performance for other tasks...
      var lazy_update = function(delay) {
      
          window.lazy_update_timeout = setTimeout(function(){
      
              update_ellipsis();
      
              $(window).one('resize', function() {
                  lazy_update(delay);
              });
      
          }, delay);
      }
      
      var store_contents = function(){
      
          $('.ellipsis').each(function(){
              var p = $(this);
              p.data('ellipsis-storage', p.html());
          });
      }
      
      var update_ellipsis = function(){
      
          $('.ellipsis').each(function(){
      
              var p = $(this);
              var max_line_count = p.data('ellipsis-max-line-count');
              var line_height = p.html('&nbsp').outerHeight();
              var max_height = max_line_count*line_height;
              p.html(p.data('ellipsis-storage'));
              var p_height = p.outerHeight();
      
              while(p_height > max_height){
      
                  var content_arr = p.html().split(' ');
                  content_arr.pop();
                  content_arr.pop();
                  content_arr.push('...');
                  p.html(content_arr.join(' '));
                  p_height = p.outerHeight();
              }
          });
      }
      
      } )();
      

      希望你喜欢!

      【讨论】:

        【解决方案5】:

        如果您使用的是等宽字体,您可能会对此有所了解,因为您很清楚每行可以容纳多少个字母,用于定义宽度的元素。但是,如果一个单词跨行,那么这可能会变得很棘手..

        e:发现另一个问题,这基本上就是你所追求的 - 他们也没有真正的解决方案,但在我看来,行高和元素高度似乎最接近。

        "How can I count text lines inside a dom element"

        【讨论】:

          【解决方案6】:

          tl;dr - 在您的容器 div 上设置一个高度,然后使用 jQuery dotdotdot plugin

          本来打算将@Andy E 的精彩示例制作成插件,但后来意识到https://github.com/BeSite/jQuery.dotdotdot 可以实现这一目标。我们的用例是我们想在桌面宽度上显示一条线,在手机/平板电脑上显示两条线。

          我们的 CSS 将相应地将容器 div 设置为相当于一或两个行高,然后 dotdotdot 插件似乎会处理其余部分。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-01
            • 1970-01-01
            • 2014-08-03
            • 2014-01-24
            • 2015-02-20
            相关资源
            最近更新 更多