繁体   English   中英

使用JavaScript将文本截断为2行

[英]Truncating Text to 2 Lines with Javascript

在下面,我编写了一些代码,这些代码在表单元格中包含了一些内容,如果超出,则将其截断为两行。 当试图找到接近2个全行的正确内容长度(但不会超过!)时,我采取对数方法(我认为)。 我首先将内容切成两半。 然后,我再次检查内容,然后加上或减去四分之一(一半的一半)。 等等。

要求:

  • 省略号(...)位于截断文本的末尾。
  • 响应式策略应适用于动态宽度单元

问题:

  • 在代码段中,我包含了一个导致3行的示例。 我如何保证我能以2条线着陆同时又接近2条全线?
  • 我采用了对数方法,因此我不必做诸如弹出单词,重新测试,弹出单词,重新测试等操作。这似乎仍然太昂贵了,我该如何改善呢?

 document.querySelectorAll('.expand').forEach(td => { // get cell styles let styles = window.getComputedStyle(td); let lineHeight = parseInt(styles.lineHeight, 10); // create test element, mostly because td doesn't support max-height let el = document.createElement('div'); el.innerHTML = td.innerHTML; el.style.maxHeight = (lineHeight * 2) + 'px'; el.style.overflow = 'hidden'; td.appendChild(el); // if scrollHeight is greater than clientHeight, we need to do some expand-y stuff if (el.scrollHeight > el.clientHeight) { // store content let content = el.innerHTML.trim(), len = content.length; for (let i=Math.round(len*.5);; i=Math.round(i*.5)) { let over = el.scrollHeight > el.clientHeight; // if over 2 lines, cut by half // else increase by half over ? (len-=i) : (len+=i); // update innerHTML with updated content el.innerHTML = content.slice(0, len); console.log(i, len); // break if within margin of 10 and we landed under if (i<10 && !over) break; } td.innerHTML = ` <div class="hide-expanded">${el.innerHTML.slice(0, -3).trim()}...</div> <div class="show-expanded">${content}</div> <button type="button">Toggle</button>`; td.querySelector('button').addEventListener('click', e => td.classList.toggle('expanded')) } }); 
 html { font-size: 14px; line-height: 24px; font-family: Helvetica, Arial, sans-serif; } table { border-collapse: collapse; } td { white-space: nowrap; padding: 1rem; } .expand { white-space: normal; } .expand:not(.expanded) .show-expanded, .expand.expanded .hide-expanded { display: none; } 
 <table> <tbody> <tr> <td class="expand">This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content.</td> </tr> </tbody> </table> 

这个github仓库是我能找到的最好的(也是最简洁的)解决方案。 我已经适应了一个解决方案。

https://github.com/dollarshaveclub/shave/blob/master/src/shave.js

export default function shave(target, maxHeight, opts) {
  if (!maxHeight) throw Error('maxHeight is required');
  let els = typeof target === 'string' ? document.querySelectorAll(target) : target;
  if (!('length' in els)) els = [els];

  const defaults = {
    character: '…',
    classname: 'js-shave',
    spaces: true,
  };
  const character = opts && opts.character || defaults.character;
  const classname = opts && opts.classname || defaults.classname;
  const spaces = opts && opts.spaces === false ? false : defaults.spaces;
  const charHtml = `<span class="js-shave-char">${character}</span>`;

  for (let i = 0; i < els.length; i++) {
    const el = els[i];
    const span = el.querySelector(`.${classname}`);

    // If element text has already been shaved
    if (span) {
      // Remove the ellipsis to recapture the original text
      el.removeChild(el.querySelector('.js-shave-char'));
      el.textContent = el.textContent; // nuke span, recombine text
    }

    // If already short enough, we're done
    if (el.offsetHeight < maxHeight) continue;

    const fullText = el.textContent;
    const words = spaces ? fullText.split(' ') : fullText;

    // If 0 or 1 words, we're done
    if (words.length < 2) continue;

    // Binary search for number of words which can fit in allotted height
    let max = words.length - 1;
    let min = 0;
    let pivot;
    while (min < max) {
      pivot = (min + max + 1) >> 1;
      el.textContent = spaces ? words.slice(0, pivot).join(' ') : words.slice(0, pivot);
      el.insertAdjacentHTML('beforeend', charHtml);
      if (el.offsetHeight > maxHeight) max = spaces ? pivot - 1 : pivot - 2;
      else min = pivot;
    }

    el.textContent = spaces ? words.slice(0, max).join(' ') : words.slice(0, max);
    el.insertAdjacentHTML('beforeend', charHtml);
    const diff = spaces ? words.slice(max + 1).join(' ') : words.slice(max);

    el.insertAdjacentHTML('beforeend',
      `<span class="${classname}" style="display:none;">${diff}</span>`);
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM