HTML -我怎么能显示工具提示只有当省略号被激活

我在我的页面中获得了一个具有ellipsis样式的动态数据跨度。

.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

223333 次浏览

如果你想单独使用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将span插入到DOM中,则可以在插入之前将内容保存在变量中。这样就不需要span上的content属性了。

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

下面是一种使用内置省略号设置的方法,并按需(使用jQuery)在Martin Smith的注释上添加title属性:

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


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

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());
});

这就是我所做的。大多数工具提示脚本要求您执行存储工具提示的函数。这是一个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());
});

上面的解决方案对我都没用,但我想出了一个很棒的解决方案。人们犯的最大错误是在页面加载时在元素上声明所有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'
});
}
});

我们需要检测是否真的应用了省略号,然后显示一个工具提示来显示全文。当元素几乎保存了它的内容,但宽度只多了一到两个像素时,仅比较"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/

这是我的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 < / p >
这是一个纯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;
}

我有CSS类,它决定在哪里放省略号。在此基础上,我做以下操作(元素集可能不同,我写那些,使用省略号,当然它可以是一个单独的类选择器):

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

您可以用另一个跨度包围这个跨度,然后简单地测试原始/内跨度的宽度是否大于新/外跨度的宽度。注意,我说可能——这大致是基于我的情况,我在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());
}
}
});
}

我创建了一个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");
}
}
});
};

下面是另外两个纯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>

这是一个香草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>

这就是我的解决办法,真是妙不可言!

    $(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');
}
});

这就是我最终基于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 );

为2022年添加简单的一次性解决方案,那时你不应该使用jQuery,也不应该尝试支持停产的产品(如IE🤮):

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

试试:https://jsfiddle.net/metalim/cxw26smg/