HTML - 如何仅在激活省略号时显示工具提示

发布于 2024-10-27 09:15:19 字数 469 浏览 1 评论 0原文

我的页面中有一个包含动态数据的跨度,具有省略号样式。

.my-class
{
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;  
  width: 71px;
}
<span id="myId" class="my-class"></span>
document.getElementById('myId').innerText = "...";

我想向此元素工具提示添加相同的内容,但我希望它仅在内容很长并且省略号出现在屏幕上时才出现。

有什么办法可以做到吗?
ellipsis 被激活时,浏览器是否会抛出一个事件?

*浏览器:Internet Explorer

I have got a span with dynamic data in my page, with ellipsis style.

.my-class
{
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;  
  width: 71px;
}
<span id="myId" class="my-class"></span>
document.getElementById('myId').innerText = "...";

I'd like to add to this element tooltip with the same content, but I want it to appear only when the content is long and the ellipsis appear on screen.

Is there any way to do it?
Does the browser throw an event when ellipsis is activated?

*Browser: Internet Explorer

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

つ低調成傷 2024-11-03 09:15:19

下面是一种使用内置省略号设置来实现此目的的方法,并根据 Martin Smith 的评论按需添加 title 属性(使用 jQuery):

$('.mightOverflow').bind('mouseenter', function(){
    var $this = $(this);

    if(this.offsetWidth < this.scrollWidth && !$this.attr('title')){
        $this.attr('title', $this.text());
    }
});

Here's a way that does it using the built-in ellipsis setting, and adds the title attribute on-demand (with jQuery) building on Martin Smith's comment:

$('.mightOverflow').bind('mouseenter', function(){
    var $this = $(this);

    if(this.offsetWidth < this.scrollWidth && !$this.attr('title')){
        $this.attr('title', $this.text());
    }
});
情深缘浅 2024-11-03 09:15:19

这是一个纯 CSS 解决方案。不需要 jQuery。
它不会显示工具提示,而是在鼠标悬停时将内容扩展至完整长度。

如果您有可替换的内容,效果会很好。这样您就不必每次都运行 jQuery 函数。

.might-overflow {
    text-overflow: ellipsis;
    overflow : hidden;
    white-space: nowrap;
}

.might-overflow:hover {
    text-overflow: clip;
    white-space: normal;
    word-break: break-all;
}

Here's a pure CSS solution. No need for jQuery.
It won't show a tooltip, instead it'll just expand the content to its full length on mouseover.

Works great if you have content that gets replaced. Then you don't have to run a jQuery function every time.

.might-overflow {
    text-overflow: ellipsis;
    overflow : hidden;
    white-space: nowrap;
}

.might-overflow:hover {
    text-overflow: clip;
    white-space: normal;
    word-break: break-all;
}
迷你仙 2024-11-03 09:15:19

下面是另外两个纯 CSS 解决方案:

  1. 在适当的位置显示截断的文本:
.overflow {
  overflow: hidden;
  -ms-text-overflow: ellipsis;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.overflow:hover {
  overflow: visible;
}

.overflow:hover span {
  position: relative;
  background-color: white;

  box-shadow: 0 0 4px 0 black;
  border-radius: 1px;
}
<div>
  <span class="overflow" style="float: left; width: 50px">
    <span>Long text that might overflow.</span>
  </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>

  1. 显示任意 "工具提示”
.wrap {
  position: relative;
}

.overflow {
  white-space: nowrap; 
  overflow: hidden;
  text-overflow: ellipsis;
  
  pointer-events:none;
}

.overflow:after {
  content:"";
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  width: 20px;
  height: 15px;
  z-index: 1;
  border: 1px solid red; /* for visualization only */
  pointer-events:initial;

}

.overflow:hover:after{
  cursor: pointer;
}

.tooltip {
  /* visibility: hidden; */
  display: none;
  position: absolute;
  top: 10;
  left: 0;
  background-color: #fff;
  padding: 10px;
  -webkit-box-shadow: 0 0 50px 0 rgba(0,0,0,0.3);
  opacity: 0;
  transition: opacity 0.5s ease;
}


.overflow:hover + .tooltip {
  /*visibility: visible; */
  display: initial;
  transition: opacity 0.5s ease;
  opacity: 1;
}
<div>
  <span class="wrap">
    <span class="overflow" style="float: left; width: 50px">Long text that might overflow</span>
    <span class='tooltip'>Long text that might overflow.</span>
  </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>

Here are two other pure CSS solutions:

  1. Show the truncated text in place:

.overflow {
  overflow: hidden;
  -ms-text-overflow: ellipsis;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.overflow:hover {
  overflow: visible;
}

.overflow:hover span {
  position: relative;
  background-color: white;

  box-shadow: 0 0 4px 0 black;
  border-radius: 1px;
}
<div>
  <span class="overflow" style="float: left; width: 50px">
    <span>Long text that might overflow.</span>
  </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>

  1. Show an arbitrary "tooltip":

.wrap {
  position: relative;
}

.overflow {
  white-space: nowrap; 
  overflow: hidden;
  text-overflow: ellipsis;
  
  pointer-events:none;
}

.overflow:after {
  content:"";
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  width: 20px;
  height: 15px;
  z-index: 1;
  border: 1px solid red; /* for visualization only */
  pointer-events:initial;

}

.overflow:hover:after{
  cursor: pointer;
}

.tooltip {
  /* visibility: hidden; */
  display: none;
  position: absolute;
  top: 10;
  left: 0;
  background-color: #fff;
  padding: 10px;
  -webkit-box-shadow: 0 0 50px 0 rgba(0,0,0,0.3);
  opacity: 0;
  transition: opacity 0.5s ease;
}


.overflow:hover + .tooltip {
  /*visibility: visible; */
  display: initial;
  transition: opacity 0.5s ease;
  opacity: 1;
}
<div>
  <span class="wrap">
    <span class="overflow" style="float: left; width: 50px">Long text that might overflow</span>
    <span class='tooltip'>Long text that might overflow.</span>
  </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>

心凉 2024-11-03 09:15:19

uosɐſ的答案基本上是正确的,但您可能不想在 mouseenter 事件中执行此操作。每次您将鼠标悬停在该元素上时,这都会导致它进行计算以确定是否需要。除非元素的大小发生变化,否则没有理由这样做。

最好在将元素添加到 DOM 后立即调用此代码:

var $ele = $('#mightOverflow');
var ele = $ele.eq(0);
if (ele.offsetWidth < ele.scrollWidth)
    $ele.attr('title', $ele.text());

或者,如果您不知道添加的确切时间,则在页面加载完成后调用该代码。

如果您需要使用多个元素来执行此操作,那么您可以为它们提供相同的类(例如“mightOverflow”),并使用以下代码来更新它们:

$('.mightOverflow').each(function() {
    var $ele = $(this);
    if (this.offsetWidth < this.scrollWidth)
        $ele.attr('title', $ele.text());
});

uosɐſ's answer is fundamentally correct, but you probably don't want to do it in the mouseenter event. That's going to cause it to do the calculation to determine if it's needed, each time you mouse over the element. Unless the size of the element is changing, there's no reason to do that.

It would be better to just call this code immediately after the element is added to the DOM:

var $ele = $('#mightOverflow');
var ele = $ele.eq(0);
if (ele.offsetWidth < ele.scrollWidth)
    $ele.attr('title', $ele.text());

Or, if you don't know when exactly it's added, then call that code after the page is finished loading.

if you have more than a single element that you need to do this with, then you can give them all the same class (such as "mightOverflow"), and use this code to update them all:

$('.mightOverflow').each(function() {
    var $ele = $(this);
    if (this.offsetWidth < this.scrollWidth)
        $ele.attr('title', $ele.text());
});
緦唸λ蓇 2024-11-03 09:15:19

这是我的 jQuery 插件:

(function($) {
    'use strict';
    $.fn.tooltipOnOverflow = function() {
        $(this).on("mouseenter", function() {
            if (this.offsetWidth < this.scrollWidth) {
                $(this).attr('title', $(this).text());
            } else {
                $(this).removeAttr("title");
            }
        });
    };
})(jQuery);

用法:

$("td, th").tooltipOnOverflow();

编辑:

我已经为这个插件做了一个要点。
https://gist.github.com/UziTech/d45102cdffb1039d4415

Here is my jQuery plugin:

(function($) {
    'use strict';
    $.fn.tooltipOnOverflow = function() {
        $(this).on("mouseenter", function() {
            if (this.offsetWidth < this.scrollWidth) {
                $(this).attr('title', $(this).text());
            } else {
                $(this).removeAttr("title");
            }
        });
    };
})(jQuery);

Usage:

$("td, th").tooltipOnOverflow();

Edit:

I have made a gist for this plugin.
https://gist.github.com/UziTech/d45102cdffb1039d4415

昇り龍 2024-11-03 09:15:19

这是一个普通的 JavaScript 解决方案:

var cells = document.getElementsByClassName("cell");

for(const cell of cells) {
  cell.addEventListener('mouseenter', setTitleIfNecessary, false);
}

function setTitleIfNecessary() {
  if(this.offsetWidth < this.scrollWidth) {
    this.setAttribute('title', this.innerHTML);
  }
}
.cell {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px;
  border-style: solid;
  width: 120px; 
}
<div class="cell">hello world!</div>
<div class="cell">hello mars! kind regards, world</div>

Here's a Vanilla JavaScript solution:

var cells = document.getElementsByClassName("cell");

for(const cell of cells) {
  cell.addEventListener('mouseenter', setTitleIfNecessary, false);
}

function setTitleIfNecessary() {
  if(this.offsetWidth < this.scrollWidth) {
    this.setAttribute('title', this.innerHTML);
  }
}
.cell {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px;
  border-style: solid;
  width: 120px; 
}
<div class="cell">hello world!</div>
<div class="cell">hello mars! kind regards, world</div>

注定孤独终老 2024-11-03 09:15:19

我们需要检测是否真正应用了省略号,然后显示工具提示以显示全文。当元素几乎保留其内容但宽度仅缺少一两个像素时,仅比较“this.offsetWidth < this.scrollWidth”是不够的,尤其是对于全角文本中文/日文/韩文字符。

这是一个例子: http://jsfiddle.net/28r5D/5/

我找到了一种方法改进省略号检测:

  1. 首先比较“this.offsetWidth < this.scrollWidth”,如果失败则继续步骤#2。
  2. 将 css 样式暂时切换为 {'overflow': 'visible', 'white-space': 'normal', 'word-break': 'break-all'}。
  3. 让浏览器进行重新布局。如果发生自动换行,元素将扩展其高度,这也意味着需要省略号。
  4. 恢复CSS样式。

这是我的改进: http://jsfiddle.net/28r5D/6/

We need to detect whether ellipsis is really applied, then to show a tooltip to reveal full text. It is not enough by only comparing "this.offsetWidth < this.scrollWidth" when the element nearly holding its content but only lacking one or two more pixels in width, especially for the text of full-width Chinese/Japanese/Korean characters.

Here is an example: http://jsfiddle.net/28r5D/5/

I found a way to improve ellipsis detection:

  1. Compare "this.offsetWidth < this.scrollWidth" first, continue step #2 if failed.
  2. Switch css style temporally to {'overflow': 'visible', 'white-space': 'normal', 'word-break': 'break-all'}.
  3. Let browser do relayout. If word-wrap happening, the element will expands its height which also means ellipsis is required.
  4. Restore css style.

Here is my improvement: http://jsfiddle.net/28r5D/6/

陌生 2024-11-03 09:15:19

我创建了一个 jQuery 插件,它使用 Bootstrap 的工具提示而不是浏览器的内置工具提示。请注意,这尚未在旧版浏览器上进行过测试。

JSFiddle: https://jsfiddle.net/0bhsoavy/4/

$.fn.tooltipOnOverflow = function(options) {
    $(this).on("mouseenter", function() {
    if (this.offsetWidth < this.scrollWidth) {
        options = options || { placement: "auto"}
        options.title = $(this).text();
      $(this).tooltip(options);
      $(this).tooltip("show");
    } else {
      if ($(this).data("bs.tooltip")) {
        $tooltip.tooltip("hide");
        $tooltip.removeData("bs.tooltip");
      }
    }
  });
};

I created a jQuery plugin that uses Bootstrap's tooltip instead of the browser's build-in tooltip. Please note that this has not been tested with older browser.

JSFiddle: https://jsfiddle.net/0bhsoavy/4/

$.fn.tooltipOnOverflow = function(options) {
    $(this).on("mouseenter", function() {
    if (this.offsetWidth < this.scrollWidth) {
        options = options || { placement: "auto"}
        options.title = $(this).text();
      $(this).tooltip(options);
      $(this).tooltip("show");
    } else {
      if ($(this).data("bs.tooltip")) {
        $tooltip.tooltip("hide");
        $tooltip.removeData("bs.tooltip");
      }
    }
  });
};
避讳 2024-11-03 09:15:19

为 2022 年添加简单的一次性解决方案,此时您不应使用 jQuery,也不应尝试支持已停产的产品(例如 IE

Adding simple one-off solution for year 2022, when you should not use jQuery, and should not try to support discontinued products (like IE ????):

document.querySelectorAll('.overflow').forEach(span => {
  if (span.scrollWidth > span.clientWidth) {
    span.title = span.innerText
  }
})

Try it out: https://jsfiddle.net/metalim/cxw26smg/

人生百味 2024-11-03 09:15:19

这是我的解决方案,很有魅力!

    $(document).on('mouseover', 'input, span', function() {
      var needEllipsis = $(this).css('text-overflow') && (this.offsetWidth < this.scrollWidth);
      var hasNotTitleAttr = typeof $(this).attr('title') === 'undefined';
      if (needEllipsis === true) {
          if(hasNotTitleAttr === true){
            $(this).attr('title', $(this).val());
          }
      }
      if(needEllipsis === false && hasNotTitleAttr == false){
        $(this).removeAttr('title');
      }
  });

This was my solution, works as a charm!

    $(document).on('mouseover', 'input, span', function() {
      var needEllipsis = $(this).css('text-overflow') && (this.offsetWidth < this.scrollWidth);
      var hasNotTitleAttr = typeof $(this).attr('title') === 'undefined';
      if (needEllipsis === true) {
          if(hasNotTitleAttr === true){
            $(this).attr('title', $(this).val());
          }
      }
      if(needEllipsis === false && hasNotTitleAttr == false){
        $(this).removeAttr('title');
      }
  });
云柯 2024-11-03 09:15:19

这就是我最终根据 https://stackoverflow.com/a/13259660/1714951 所做的事情并添加删除当元素不再溢出时 title 属性的值。这是纯 JS (ES6),使用事件委托来提高性能(当使用具有相同类的多个元素时)并使用保护子句来提高可读性:

// You may want to change document by an element closer to your target
// so that the handler is not executed as much
document.addEventListener( 'mouseenter', event => {
    let eventTarget = event.target;
    // This could be easily applied to text-truncate instead of my-class if you use bootstrap
    if ( !eventTarget.classList?.contains( 'my-class' ) ) {
        return;
    }
    if ( eventTarget.offsetWidth < eventTarget.scrollWidth ) {
        eventTarget.setAttribute( 'title', eventTarget.innerText );
        return;
    }
    eventTarget.removeAttribute( 'title' );
}, true );

This is what I ended up doing based on https://stackoverflow.com/a/13259660/1714951 and adding the removal of the title attribute when the element doesn't overflow anymore. This is pure JS (ES6), uses event delegation for performance (when using several elements with the same class) and guard clauses for readability:

// You may want to change document by an element closer to your target
// so that the handler is not executed as much
document.addEventListener( 'mouseenter', event => {
    let eventTarget = event.target;
    // This could be easily applied to text-truncate instead of my-class if you use bootstrap
    if ( !eventTarget.classList?.contains( 'my-class' ) ) {
        return;
    }
    if ( eventTarget.offsetWidth < eventTarget.scrollWidth ) {
        eventTarget.setAttribute( 'title', eventTarget.innerText );
        return;
    }
    eventTarget.removeAttribute( 'title' );
}, true );
挖个坑埋了你 2024-11-03 09:15:19

如果你想仅使用 javascript 来完成此操作,我会执行以下操作。为 span 指定一个 id 属性(以便可以轻松地从 DOM 中检索它)并将所有内容放入名为“content”的属性中:

<span id='myDataId' style='text-overflow: ellipsis; overflow : hidden;
 white-space: nowrap; width: 71;' content='{$myData}'>${myData}</span>

然后,在您的 javascript 中,您可以在将元素插入到DOM。

var elemInnerText, elemContent;
elemInnerText = document.getElementById("myDataId").innerText;
elemContent = document.getElementById("myDataId").getAttribute('content')
if(elemInnerText.length <= elemContent.length)
{
   document.getElementById("myDataId").setAttribute('title', elemContent); 
}

当然,如果您使用 javascript 将跨度插入到 DOM 中,则可以在插入之前将内容保留在变量中。这样,您就不需要跨度上的内容属性。

如果您想使用 jQuery,还有比这更优雅的解决方案。

If you want to do this solely using javascript, I would do the following. Give the span an id attribute (so that it can easily be retrieved from the DOM) and place all the content in an attribute named 'content':

<span id='myDataId' style='text-overflow: ellipsis; overflow : hidden;
 white-space: nowrap; width: 71;' content='{$myData}'>${myData}</span>

Then, in your javascript, you can do the following after the element has been inserted into the DOM.

var elemInnerText, elemContent;
elemInnerText = document.getElementById("myDataId").innerText;
elemContent = document.getElementById("myDataId").getAttribute('content')
if(elemInnerText.length <= elemContent.length)
{
   document.getElementById("myDataId").setAttribute('title', elemContent); 
}

Of course, if you're using javascript to insert the span into the DOM, you could just keep the content in a variable before inserting it. This way you don't need a content attribute on the span.

There are more elegant solutions than this if you want to use jQuery.

夏の忆 2024-11-03 09:15:19

这就是我所做的。大多数工具提示脚本要求您执行存储工具提示的函数。这是一个 jQuery 示例:

$.when($('*').filter(function() {
   return $(this).css('text-overflow') == 'ellipsis';
}).each(function() {
   if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
      $(this).attr('title', $(this).text());
   }
})).done(function(){ 
   setupTooltip();
});

如果您不想检查省略号 css,您可以像这样简化:

$.when($('*').filter(function() {
   return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
   $(this).attr('title', $(this).text());
})).done(function(){ 
   setupTooltip();
});

我在它周围有“when”,这样“setupTooltip”函数就不会执行,直到所有标题都已更新。将“setupTooltip”替换为您的工具提示函数,并将 * 替换为您要检查的元素。 * 如果你离开的话,将会把它们全部浏览一遍。

如果您只想使用浏览器工具提示更新标题属性,您可以简化如下:

$('*').filter(function() {
   return $(this).css('text-overflow') == 'ellipsis';
}).each(function() {
   if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
      $(this).attr('title', $(this).text());
   }
});

或者不检查省略号:

$.when($('*').filter(function() {
   return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
   $(this).attr('title', $(this).text());
});

This is what I did. Most tooltip scripts require you to execute a function that stores the tooltips. This is a jQuery example:

$.when($('*').filter(function() {
   return $(this).css('text-overflow') == 'ellipsis';
}).each(function() {
   if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
      $(this).attr('title', $(this).text());
   }
})).done(function(){ 
   setupTooltip();
});

If you didn't want to check for ellipsis css, you could simplify like:

$.when($('*').filter(function() {
   return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
   $(this).attr('title', $(this).text());
})).done(function(){ 
   setupTooltip();
});

I have the "when" around it, so that the "setupTooltip" function doesn't execute until all titles have been updated. Replace the "setupTooltip", with your tooltip function and the * with the elements you want to check. * will go through them all if you leave it.

If you simply want to just update the title attributes with the browsers tooltip, you can simplify like:

$('*').filter(function() {
   return $(this).css('text-overflow') == 'ellipsis';
}).each(function() {
   if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
      $(this).attr('title', $(this).text());
   }
});

Or without check for ellipsis:

$.when($('*').filter(function() {
   return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
   $(this).attr('title', $(this).text());
});
零時差 2024-11-03 09:15:19

可重用的 React 解决方案

// useTitleWhenTruncated.ts

import { HTMLAttributes, useState } from 'react';

type TitleProps = Pick<HTMLAttributes<HTMLElement>, 'title' | 'onMouseEnter'>;

export function useTitleWhenTruncated(title: string): TitleProps {
  const [isTruncated, setIsTruncated] = useState(false);

  return {
    title: isTruncated ? title : undefined,
    onMouseEnter: event => {
      setIsTruncated(
        event.currentTarget.offsetWidth < event.currentTarget.scrollWidth,
      );
    },
  };
}


// usage example

const SampleComponent = ({ label }: { label: string }) => {
  const titleProps = useTitleWhenTruncated(label);
  
  return (
    <div 
      style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }} 
      {...titleProps}
    >
      {label}
    </div>
  );
}

Reusable solution for React

// useTitleWhenTruncated.ts

import { HTMLAttributes, useState } from 'react';

type TitleProps = Pick<HTMLAttributes<HTMLElement>, 'title' | 'onMouseEnter'>;

export function useTitleWhenTruncated(title: string): TitleProps {
  const [isTruncated, setIsTruncated] = useState(false);

  return {
    title: isTruncated ? title : undefined,
    onMouseEnter: event => {
      setIsTruncated(
        event.currentTarget.offsetWidth < event.currentTarget.scrollWidth,
      );
    },
  };
}


// usage example

const SampleComponent = ({ label }: { label: string }) => {
  const titleProps = useTitleWhenTruncated(label);
  
  return (
    <div 
      style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }} 
      {...titleProps}
    >
      {label}
    </div>
  );
}
你与清晨阳光 2024-11-03 09:15:19

我有 CSS 类,它决定了省略号的放置位置。基于此,我执行以下操作(元素集可能不同,我编写这些,其中使用省略号,当然它可以是单独的类选择器):

$(document).on('mouseover', 'input, td, th', function() {
    if ($(this).css('text-overflow') && typeof $(this).attr('title') === 'undefined') {
        $(this).attr('title', $(this).val());
    }
});

I have CSS class, which determines where to put ellipsis. Based on that, I do the following (element set could be different, i write those, where ellipsis is used, of course it could be a separate class selector):

$(document).on('mouseover', 'input, td, th', function() {
    if ($(this).css('text-overflow') && typeof $(this).attr('title') === 'undefined') {
        $(this).attr('title', $(this).val());
    }
});
忆依然 2024-11-03 09:15:19
import { FC, HTMLAttributes } from 'react'
import { cn } from 'src/lib/utils/classNames'

export const AutoTooltip: FC<HTMLAttributes<HTMLDivElement>> = ({
  className,
  children,
}) => {
  return (
    <div
      className={cn('truncate', className)}
      onMouseEnter={({ currentTarget }) => {
        if (currentTarget.scrollWidth > currentTarget.clientWidth) {
          currentTarget.title = currentTarget.innerText
        }
      }}
    >
      {children}
    </div>
  )
}

向组件添加省略号类:

.truncate {
    text-overflow: ellipsis;
    overflow: hidden
    white-space: nowrap;
}

使用

<AutoTooltip>
    some text you want to show in tooltip if width is overflow...
</AutoTooltip>
import { FC, HTMLAttributes } from 'react'
import { cn } from 'src/lib/utils/classNames'

export const AutoTooltip: FC<HTMLAttributes<HTMLDivElement>> = ({
  className,
  children,
}) => {
  return (
    <div
      className={cn('truncate', className)}
      onMouseEnter={({ currentTarget }) => {
        if (currentTarget.scrollWidth > currentTarget.clientWidth) {
          currentTarget.title = currentTarget.innerText
        }
      }}
    >
      {children}
    </div>
  )
}

add ellipsis class to component:

.truncate {
    text-overflow: ellipsis;
    overflow: hidden
    white-space: nowrap;
}

use

<AutoTooltip>
    some text you want to show in tooltip if width is overflow...
</AutoTooltip>
欢你一世 2024-11-03 09:15:19

上面的解决方案都不适合我,但我找到了一个很好的解决方案。人们犯的最大错误是在页面加载时在元素上声明所有 3 个 CSS 属性。如果且仅当您想要省略号的跨度比其父跨度宽时,您必须动态添加这些样式+工具提示。

    $('table').each(function(){
        var content = $(this).find('span').text();
        var span = $(this).find('span');
        var td = $(this).find('td');
        var styles = {
            'text-overflow':'ellipsis',
            'white-space':'nowrap',
            'overflow':'hidden',
            'display':'block',
            'width': 'auto'
        };
        if (span.width() > td.width()){
            span.css(styles)
                .tooltip({
                trigger: 'hover',
                html: true,
                title: content,
                placement: 'bottom'
            });
        }
    });

None of the solutions above worked for me, but I figured out a great solution. The biggest mistake people are making is having all the 3 CSS properties declared on the element upon pageload. You have to add those styles+tooltip dynamically IF and ONLY IF the span you want an ellipses on is wider than its parent.

    $('table').each(function(){
        var content = $(this).find('span').text();
        var span = $(this).find('span');
        var td = $(this).find('td');
        var styles = {
            'text-overflow':'ellipsis',
            'white-space':'nowrap',
            'overflow':'hidden',
            'display':'block',
            'width': 'auto'
        };
        if (span.width() > td.width()){
            span.css(styles)
                .tooltip({
                trigger: 'hover',
                html: true,
                title: content,
                placement: 'bottom'
            });
        }
    });
风吹过旳痕迹 2024-11-03 09:15:19

就我而言,我不仅使用了 text-overflow: ellipsis; ,还使用了 line-clamp 属性,因此省略号仅在第二行文本之后应用。这是我的 div 的样式:

.text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
}

我在这里使用 React,但我认为该方法也可以应用于 vanilla js。这里是:

const MyComponent = ({text}: {text: string}) => {
  const [titleActive, setTitleActive] = useState(false)
  const ref = useCallback<(node: HTMLDivElement) => void>(
    (node) => {
      if (node) {
        const blockWidth = node.offsetWidth

        /* setting width to `max-content` makes div's width equal to text 
           rendered in one line */
        node.style.width = 'max-content';
        const textWidth = node.offsetWidth;
        node.style.width = 'auto';
        
        /* the multiplier of `blockWidth` is the number of lines shown 
           before ellipsis applied. In my case this is 2 (same 
           as in `-webkit-line-clamp` css property).
           For one condition will be just `(textWidth > blockWidth)`
        */
        if (textWidth > blockWidth * 2) {
          setTitleActive(true)
        }
      }
    },
    []
  );

  return (
    <div 
      className="text" 
      title={titleActive ? text : undefined}
      ref={ref}
    >
      {text}
    </div>
  )
}

In my case i used not only text-overflow: ellipsis; but also line-clamp property, so the ellipsis was applied only after the second line of text. Here is the styles of my div:

.text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
}

I'm using React here, but i think that approach can be applied to vanilla js too. Here it is:

const MyComponent = ({text}: {text: string}) => {
  const [titleActive, setTitleActive] = useState(false)
  const ref = useCallback<(node: HTMLDivElement) => void>(
    (node) => {
      if (node) {
        const blockWidth = node.offsetWidth

        /* setting width to `max-content` makes div's width equal to text 
           rendered in one line */
        node.style.width = 'max-content';
        const textWidth = node.offsetWidth;
        node.style.width = 'auto';
        
        /* the multiplier of `blockWidth` is the number of lines shown 
           before ellipsis applied. In my case this is 2 (same 
           as in `-webkit-line-clamp` css property).
           For one condition will be just `(textWidth > blockWidth)`
        */
        if (textWidth > blockWidth * 2) {
          setTitleActive(true)
        }
      }
    },
    []
  );

  return (
    <div 
      className="text" 
      title={titleActive ? text : undefined}
      ref={ref}
    >
      {text}
    </div>
  )
}
自在安然 2024-11-03 09:15:19

您可以用另一个跨度包围该跨度,然后简单地测试原始/内部跨度的宽度是否大于新/外部跨度的宽度。请注意,我说可能 - 这大致是基于我的情况,我在 td 内有一个 span ,所以我实际上不知道它是否可以与span 内有 span

不过,这是我的代码,供其他可能发现自己处于与我类似的位置的人使用;我不加修改地复制/粘贴它,即使它是在 Angular 上下文中,我认为这不会降低可读性和基本概念。我将其编码为一种服务方法,因为我需要在多个地方应用它。我传入的选择器是一个将匹配多个实例的类选择器。

CaseService.applyTooltip = function(selector) {
    angular.element(selector).on('mouseenter', function(){
        var td = $(this)
        var span = td.find('span');

        if (!span.attr('tooltip-computed')) {
            //compute just once
            span.attr('tooltip-computed','1');

            if (span.width() > td.width()){
                span.attr('data-toggle','tooltip');
                span.attr('data-placement','right');
                span.attr('title', span.html());
            }
        }
    });
}

You could possibly surround the span with another span, then simply test if the width of the original/inner span is greater than that of the new/outer span. Note that I say possibly -- it is roughly based on my situation where I had a span inside of a td so I don't actually know that if it will work with a span inside of a span.

Here though is my code for others who may find themselves in a position similar to mine; I'm copying/pasting it without modification even though it is in an Angular context, I don't think that detracts from the readability and the essential concept. I coded it as a service method because I needed to apply it in more than one place. The selector I've been passing in has been a class selector that will match multiple instances.

CaseService.applyTooltip = function(selector) {
    angular.element(selector).on('mouseenter', function(){
        var td = $(this)
        var span = td.find('span');

        if (!span.attr('tooltip-computed')) {
            //compute just once
            span.attr('tooltip-computed','1');

            if (span.width() > td.width()){
                span.attr('data-toggle','tooltip');
                span.attr('data-placement','right');
                span.attr('title', span.html());
            }
        }
    });
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文