SOURCE

// (旧版)限制数据库换行文本最大行数 JS片段 - author: JeffreyChen

(function() {
  var animationFrameRequestId = null; // 用于存储 requestAnimationFrame 的 ID
  const rowsSelector = '.av__row:not(.av__row--header) ';

  // 获取当前单元格的函数
  function getCurrentCells() {
    return Array.from(document.querySelectorAll(rowsSelector + '.av__cell[data-wrap="true"]'));
  }

  // 计算单元格内所有文本元素的总高度的函数
  function calculateTotalHeight(cell) {
    const textElements = Array.from(cell.querySelectorAll('.av__celltext'));
    const tempSpan = document.createElement('span');
    tempSpan.style.visibility = 'hidden';
    tempSpan.style.display = 'block';
    
    // 根据 data-dtype 属性设置 whiteSpace 样式
    if (cell.dataset.dtype === 'relation' || cell.dataset.dtype === 'rollup') {
      tempSpan.style.whiteSpace = 'normal'; // 对于 relation 和 rollup
    } else {
      tempSpan.style.whiteSpace = 'pre-wrap'; // 其他情况使用 pre-wrap
    }

    cell.appendChild(tempSpan); // 将其附加到单元格以便准确测量

    // 将所有文本内容与分隔符 ", " 组合
    const combinedText = textElements.map(textElement => textElement.textContent.trim()).join(', ');

    tempSpan.textContent = combinedText; // 设置组合文本以进行高度计算
    const totalHeight = tempSpan.scrollHeight; // 获取总高度

    // 清理临时 span
    cell.removeChild(tempSpan);
    return totalHeight;
  }

  function updateAriaLabels(cells) {
    if (animationFrameRequestId !== null) {
      cancelAnimationFrame(animationFrameRequestId);
    }
    animationFrameRequestId = requestAnimationFrame(function() {
      cells.forEach(cell => {
        const currentLabel = cell.getAttribute('aria-label');
        const totalHeight = calculateTotalHeight(cell);
        const isTruncated = totalHeight > cell.clientHeight;

        // 将所有文本组合成一个字符串以用于 aria-label
        const textElements = cell.querySelectorAll('.av__celltext');
        let combinedText;

        // 特殊处理 .av__cell[data-dtype="relation"] 和 .av__cell[data-dtype="rollup"] 元素
        if (cell.dataset.dtype === 'relation' || cell.dataset.dtype === 'rollup') {
          combinedText = Array.from(textElements).map(textElement => {
            // 获取文本并替换换行符
            const cleanedText = textElement.textContent.replace(/\n+/g, ' ').trim();
            return cleanedText;
          }).join(',\n');
        } else {
          combinedText = Array.from(textElements).map(textElement => textElement.textContent.trim()).join(', ');
        }

        // 根据组合文本长度更新 aria-label
        if (isTruncated && !currentLabel) {
          cell.setAttribute('aria-label', combinedText);
        } else if (!isTruncated && currentLabel) {
          cell.removeAttribute('aria-label');
        }
      });
      animationFrameRequestId = null;
    });
  }

  function deferredUpdateAriaLabels() {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => {
      const cells = getCurrentCells();
      updateAriaLabels(cells);
    }, 500); // 500 毫秒延时。
  }

  var timeoutId = null;
  // 创建一个新的 MutationObserver 实例
  const observer = new MutationObserver((mutations) => {
    for (let mutation of mutations) {
      if (mutation.type === 'attributes') {
        const target = mutation.target;
        // 数据库渲染检查
        if (target.classList.contains('av') && target.getAttribute('data-render') === 'true') {
          deferredUpdateAriaLabels();
        // 列头调整或切换页签检查
        } else if (target.classList.contains('av__cell--header') && target.getAttribute('data-wrap') === 'true' || target.classList.contains('item--focus')) {
          deferredUpdateAriaLabels();
        }
      }
    }
  });

  // 配置并开始观察
  const config = { attributes: true, childList: false, subtree: true };
  observer.observe(document.body, config);

  // 创建并添加 CSS 代码
  const style = document.createElement('style');
  style.textContent = `
  /* 限制数据库换行文本最大行数 CSS片段 */
  .av__row:not(.av__row--header) .av__cell[data-wrap="true"]:not([data-dtype="relation"]):not([data-dtype="rollup"]):not([data-dtype="mAsset"]) {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3; /* 最多3行 */
    overflow: hidden;
  }
  .av__celltext--ref {
    border-bottom: 0px;
    text-decoration: underline; /* 下划线 */
    text-decoration-color: rgb(0 202 255 / 85%); /* 浅蓝色 */
    text-decoration-thickness: 2px;
  }
  /* 针对关联字段、汇总字段 */
  .av__row:not(.av__row--header) .av__cell[data-wrap="true"][data-dtype="relation"],
  .av__row:not(.av__row--header) .av__cell[data-wrap="true"][data-dtype="rollup"] {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3; /* 最多3行 */
    overflow: hidden;
    white-space: normal;
  }
  /* 资源字段变为滚动容器 */
  .av__row:not(.av__row--header) .av__cell[data-wrap="true"][data-dtype="mAsset"] {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3; /* 最多3行 */
    text-overflow: clip; /* 用于去掉多余的 "..." ,但不起效,要等 CSS4 再看有没有合适的 CSS 属性*/
    overflow: auto;
    overflow-x: hidden;
  }
  `;
  document.head.appendChild(style);
})();