【问题标题】:Show more/less if text does not fit如果文本不合适,则显示更多/更少
【发布时间】:2018-07-18 18:33:24
【问题描述】:

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

我创建了一个fiddle,显示了卡片的创建以及我到目前为止所做的尝试。

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

函数如下:

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 来实现我所需要的。给出的答案仍然有效并且确实解决了我的问题,所以我会保留它作为答案。

【问题讨论】:

  • 你有没有试过调用$(document).ready(function(){});中的checkTruncation函数?
  • @BrankVictoria 卡片通常是通过基于用户交互的 ajax 调用创建的。所以他们没有准备好文件。
  • 那你在哪里调用 checkTruncation 函数呢?我相信您在 ajax 调用的“成功”中调用它。
  • @BrankVictoria 我有一个小提琴链接。在示例中,我没有使用 ajax,只是调用容器的追加。但是您可能会想象,在从服务器获取结果后,追加将发生在 ajax 调用的完成或成功中。我将更新问题以使这一点更清楚。

标签: javascript jquery


【解决方案1】:

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

使用absolute: positionoverflow: hidden,我们可以在“text” 元素的底部隐藏 “button”,并且当该元素达到 "wrapper's" 高度时,隐藏的 "button" 变得可见。

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

堆栈sn-p

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( 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: '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 示例的更新 Stack sn-p 版本

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>

【讨论】:

  • 这也不错。当Read more被按下时你能把它扩大吗?
  • @GiannisParaskevopoulos 更新了解释和更多 CSS 功能
  • 首先我要非常感谢你的努力。我真的很喜欢这个答案(我给它+1)。虽然我确实有一些问题(好吧,我可能在这里反应过度),但我担心浏览器的覆盖范围。例如,我在 IE11 中尝试过此操作,但 sn-p 显示错误。当然,问题是谁足够疯狂,仍然使用 IE11....但我无法为我的用户群回答这个问题。 (我还没有检查分析...)。
  • 再想一想,我的小提琴在 IE11 上也没有加载(实际上 jsfiddle 根本没有加载)......我想知道是否有人再使用它......
  • @GiannisParaskevopoulos IE 不支持箭头功能,.forEach( link =&gt; { ...所以我更新了我的答案并改为.forEach( function(link) {
【解决方案2】:

这是因为您没有将元素附加到文档中,因此其宽度为 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().之前将新元素附加到它上面

并更新调用getCard() 的代码,如下所示:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-18
    • 2022-01-19
    • 2020-01-24
    • 1970-01-01
    • 2012-11-13
    • 2020-04-20
    • 2020-02-15
    相关资源
    最近更新 更多