代码之家  ›  专栏  ›  技术社区  ›  Giannis Paraskevopoulos

如果文本不适合,则显示“多/少”

  •  2
  • Giannis Paraskevopoulos  · 技术社区  · 7 年前

    我正在使用jquery创建一些具有动态数据的卡。有一个描述属性,该属性是否适合卡。当它不合适时,我想保持卡片与其他卡片的大小相同,但添加了一个“显示更多/更少”按钮,该按钮将展开卡片以显示其余的描述。

    我创造了一个 fiddle 显示卡的创建以及到目前为止我尝试过的操作。

    在这一点上我有一个函数 checkTruncation 这将检查文本是否适合其容器。该问题似乎依赖于元素尚未呈现的事实,因此它们的宽度为0,这使得函数始终返回为真。

    功能如下:

    let checkTruncation = function (jqueryElement) {
        var $element = jqueryElement;
        if ($element) {
            var $c = $element
                .clone()
                .css({ display: 'inline', width: 'auto', visibility: 'hidden' })
                .appendTo('body');
    
            let truncated = $c.width() > $element.width()
            console.log($c.width(), $element.width(), $c.width() > $element.width())
            $c.remove();
    
            return truncated;
        }
        return false;
    }
    

    另外,除了我重新设计轮子之外,还有什么建议的库可以实现这个功能吗?我知道我见过这样的行为,但记不起在哪里。

    更新

    在上面的小提琴中,我只是调用getcard函数,它负责为卡片提供模板,两次只是为了显示一些示例。在现实生活中,当用户单击某个按钮时,我通过Ajax获取数据并使用以下方法填充卡片:

    $('.fetchButton').on('click', function(){
        $.get(url, filter)
            .done(function (data) {
                jQuery.each(data, function (index, item) {
                    $('.container').append(getCard(item));
                })
            }
    })
    

    更新2

    在…的帮助下 @LGSon 我来这里了 scenario 它主要使用CSS来实现我所需要的。尽管如此,给出的答案是有效的,确实解决了我的问题,所以我会保留它作为答案。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Chayim Friedman    7 年前

    这是因为您没有将元素附加到文档中,所以它的宽度是0。因此,请按以下方式更新代码:

    let checkTruncation = function($element) {
      if ($element) {
        var $c = $element
          .clone()
          .css({ display: 'inline', width: 'auto', visibility: 'hidden' })
          .appendTo('body');
    
        let truncated = $c.width() > $element.width();
        // console.log($c.width(), $element.width(), $c.width() > $element.width());
        $c.remove();
    
        return truncated;
      }
        
      return false;
    };
    
    let baseUrl ='';
    
    let getCard = function(item, $parent) {
      let outerDiv = $('<div>').addClass('shops-content-right');
      let boxDiv = $('<div>').addClass('boxes-right row');
      let shopDiv = $('<div>').addClass('one-shop-box col-md-6 offset-md-3');
      let cubeDiv = $('<div>').addClass('cube text-center');
      let descriptionP = $('<p>').addClass('text-disc').text(item.description).addClass('collapsed');
      let loadMoreP = $('<p>').css({ 'font-size': '16px', 'cursor': 'pointer' }).text("More >");
    
      cubeDiv.append(descriptionP).append(loadMoreP);
      shopDiv.append(cubeDiv);
      boxDiv.append(shopDiv);
      outerDiv.append(boxDiv);
      $parent.append(outerDiv);
    
      loadMoreP.on('click', function () {
        if (descriptionP.hasClass('collapsed')) {
          descriptionP.removeClass('collapsed');
          loadMoreP.text("Less <");
        } else {
          descriptionP.addClass('collapsed');
          loadMoreP.text("More >");
        }
      });
    
      if (checkTruncation(descriptionP)) {
        loadMoreP.show();
      } else {
        loadMoreP.hide();
      }
    };
    
    const $container = $('.container');
    
    getCard({
      description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
    }, $container);
    
    getCard({
      description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit'
    }, $container);
    .row {
      background: #f8f9fa;
      margin-top: 20px;
    }
    
    .col {
      border: solid 1px #6c757d;
      padding: 10px;
    }
    
    .one-shop-box {
      border:1px solid;
    }
    
    .shops-content-right .one-shop-box .cube p.text-disc {
      font-size: 16px;
      height: 50px;
      overflow: hidden;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    
    <div class="container"></div>

    我转到函数 getCard() 容器元素,并在调用函数之前将新元素附加到它 checkTruncation().

    并更新调用的代码 获取卡() 如下:

    const $container = $('.container');
    $('.fetchButton').on('click', function() {
      $.get(url, filter).done(function(data) {
        $.each(data, function(index, item) {
          getCard(item, $container);
        });
      });
    });
    
        2
  •  2
  •   Asons Oliver Joseph Ash    7 年前

    除了给出的答案(解释了原始代码为什么不起作用)之外,这里还有一个不同的方法,展示了如何使用CSS来显示/隐藏 “阅读更多…” 按钮

    absolute: position overflow: hidden 我们可以 隐藏 “按钮” 在A的底部 “文本” 元素,当该元素到达 “包装纸” 高度,隐藏 “按钮” 可见。

    我还使用了伪元素和 data-* 要保留的属性 “按钮文本” 在标记和CSS中 attr() 在显示/隐藏文本时切换。

    堆栈段

    document.querySelectorAll('.readmore').forEach( function(link) {
      link.addEventListener('click', function() {
        this.closest('.wrapper').classList.toggle('show');
      });
    });
    .wrapper {
      height: 70px;
      border: 1px solid gray;
      overflow: hidden;
    }
    .wrapper.show {
      height: auto;
    }
    
    .text {
      position: relative;
      overflow: hidden;
    }
    
    .readmore {
      position: absolute;
      width: 100%;
      top: 52px;
      left: 0;
      background: white;
      color: red;
      cursor: pointer;
    }
      .readmore::before {
        content: attr(data-more)
      }
      .wrapper.show .readmore {
        position: relative;
        top: auto;
        display: block;
      }
      .wrapper.show .readmore::before {
        content: attr(data-less)
      }
    <div class="wrapper">
      <div class="text">
        Some smaller dummy text here
    
        <span class="readmore" data-more="Show more..." data-less="Show less..."></span>
      </div>
    </div>
    
    <div class="wrapper">
      <div class="text">
        Some bigger dummy text here <br>
        Some bigger dummy text here <br>
        Some bigger dummy text here <br>
        Some bigger dummy text here <br>
        Some bigger dummy text here <br>
        
        <span class="readmore" data-more="Show more..." data-less="Show less..."></span>
      </div>
    </div>

    如果可能的话, “显示更多/更少…” 当然,可以在CSS中设置文本,以简化维护并将其放在一个位置。

    document.queryselectorall('.readmore').foreach(函数(链接){
    link.addEventListener('click',function()。{
    this.closest(“.wrapper”).classlist.toggle(“show”);
    (});
    (});
    .wrapper {
      height: 70px;
      border: 1px solid gray;
      overflow: hidden;
    }
    .wrapper.show {
      height: auto;
    }
    
    .text {
      position: relative;
      overflow: hidden;
    }
    
    .readmore {
      position: absolute;
      width: 100%;
      top: 52px;
      left: 0;
      background: white;
      color: red;
      cursor: pointer;
    }
      .readmore::before {
        content: 'Show more...'
      }
      .wrapper.show .readmore {
        position: relative;
        top: auto;
        display: block;
      }
      .wrapper.show .readmore::before {
        content: 'Show less...'
      }
    <div class="wrapper">
      <div class="text">
        Some smaller dummy text here
    
        <span class="readmore"></span>
      </div>
    </div>
    
    <div class="wrapper">
      <div class="text">
        Some bigger dummy text here <br>
        Some bigger dummy text here <br>
        Some bigger dummy text here <br>
        Some bigger dummy text here <br>
        Some bigger dummy text here <br>
        
        <span class="readmore"></span>
      </div>
    </div>

    根据评论更新

    以下是您的 Fiddle / Codepen 样品

    let getCard = function(options) {
      let item = options.data;
      let $parent = options.parent;
    
      let outerDiv = $('<div>').addClass('shops-content-right');
      let boxDiv = $('<div>').addClass('boxes-right row');
      let shopDiv = $('<div>').addClass('one-shop-box col-md-6 offset-md-3');
      let cubeDiv = $('<div>').addClass('cube text-center');
    
      let wrapperDiv = $('<div>').addClass('wrapper');
      let textDiv = $('<div>').addClass('text');
      let descriptionP = $('<p>').addClass('text-disc').text(item.description);
    
      let loadMoreP = $('<span>More >').addClass('readmore');
    
      textDiv.append([descriptionP, loadMoreP]);
      wrapperDiv.append(textDiv);
      cubeDiv
        .append(wrapperDiv);
    
      shopDiv.append(cubeDiv);
      boxDiv.append(shopDiv);
      outerDiv.append(boxDiv);
    
      $parent.append(outerDiv);
    
      loadMoreP.on('click', function() {
        if (wrapperDiv.hasClass('collapsed')) {
          wrapperDiv.removeClass('collapsed');
          loadMoreP.text("More >");
        } else {
          wrapperDiv.addClass('collapsed');
          loadMoreP.text("Less <");
        }
      })
    
      return outerDiv;
    }
    
    
    $('.fetchButton').on('click', function() {
      getCard({
        data: {
          description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
        },
        parent: $('.container'),
        lines: 3
      })
      getCard({
        data: {
          description: 'Lorem ipsum dolor sit amet, consectetur'
        },
        parent: $('.container'),
        lines: 3
      })
    })
    .row {
      background: #f8f9fa;
      margin-top: 20px;
    }
    
    .col {
      border: solid 1px #6c757d;
      padding: 10px;
    }
    
    .one-shop-box {
      border: 1px solid;
    }
    
    .shops-content-right .one-shop-box .cube p.text-disc {
      font-size: 16px;
      /*height: 50px;*/
      overflow: hidden;
    }
    
    .wrapper {
      height: 90px;
      overflow: hidden;
    }
    
    .wrapper.collapsed {
      height: auto;
    }
    
    .text {
      position: relative;
      overflow: hidden;
    }
    
    .readmore {
      position: absolute;
      width: 100%;
      top: 72px;
      left: 0;
      background: white;
      color: red;
    }
    
    .wrapper.collapsed .readmore {
      position: relative;
      top: auto;
      display: block;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <!-- 
      Bootstrap docs: https://getbootstrap.com/docs
    -->
    
    <div class="container">
      <button class="fetchButton">
    Fetch Data
    </button>
    
    </div>