如何在火狐浏览器中模拟文本溢出省略号效果?

19

我有一些动态文本包含在一个div中,这个div的大小由用户在文本框中输入的内容来决定。如果文本不能适应这个div,现在它会被截断在边缘,所有超出边界的文本都不可见。我想要截断文本,使其适合盒子内,并在结尾加上省略号(...)。例如:

|----div width------|
 Here is some sample text that is too long.
 Here is some sam...
显然,在这个例子中很容易,因为code标签使用的是等宽字体,所以只需数字符号即可。我使用的是变宽字体,所以如果他们输入“WWWWWWWWWWW”,它将比“................”少用许多字符。
怎么做才是最好的?我在这里找到了一个简单找到文本实际像素宽度的潜在解决方案:http://www.codingforums.com/archive/index.php/t-100367.html 但即使有这样的方法,实现省略号还是有点棘手。例如,如果有20个字符而我发现它不适合,则必须截断到19个字符,添加省略号,然后再次检查是否适合。 然后截断到18(加上省略号)并再次尝试。反复以上步骤,直到它适合为止。 有更好的方法吗?
编辑:根据答案,我已决定采用我的原始方法,但我试图改进上面链接中的解决方案,不创建单独的td元素进行测量,这感觉像一个hack。
这是我的代码:
<div id="tab" class="tab">
    <div id="tabTitle" class="tabTitle">
        <div class="line1">user-supplied text will be put here</div>
        <div class="line2">more user-supplied text will be put here</div>
    </div>
</div>

还有样式:

.tab {
padding: 10px 5px 0px 10px;
margin-right: 1px;
float: left;
width: 136px;
height: 49px;
background-image: url(../images/example.gif);
background-position: left top;
background-repeat: no-repeat;
}    

.tab .tabTitle {
    height: 30px;
width: 122px;
    overflow: hidden;
    text-overflow: ellipsis;
font-size: 12px;
font-weight: bold;
color: #8B8B8B;
}

.tab .tabTitle .line1, .tab .tabTitle .line2 {
    display:inline;
    width:auto;
}

以及截断文本并添加省略号的 JavaScript 代码:

function addOverflowEllipsis( containerElement, maxWidth )
{
    var contents = containerElement.innerHTML;
    var pixelWidth = containerElement.offsetWidth;
    if(pixelWidth > maxWidth)
    {
        contents = contents + "…"; // ellipsis character, not "..." but "…"
    }
    while(pixelWidth > maxWidth)
    {
        contents = contents.substring(0,(contents.length - 2)) + "…";
        containerElement.innerHTML = contents;
        pixelWidth = containerElement.offsetWidth;
    }
}

该函数接受“line1”和“line2” div作为参数。 当单词输入像“WWWWWWWWWWWWWWWWW”时,它能正常工作,但是当多个单词输入像“WWWWW WWWWW WWWWW”时就不行了,因为它只添加了换行符,并将文本的宽度测量为“WWWWW”的宽度。

是否有一种方法可以解决这个问题而不需要将文本复制到隐藏的测量元素中?某种方式来设置行div的样式,使其不换行?


1
现在Firefox 7原生支持此功能! - sourcenouveau
13个回答

11

有没有一种方法可以设置行的样式,使它们不会换行?

你可以使用white-space: nowrap来达到这个效果。是的,即使在旧版本的浏览器中也可以使用。


谢谢,我认为这将完美地发挥作用。额外加分的话,能否诊断一下为什么前几天当我使用实际省略号字符(…)进行测试时可以正常工作,但今天测试时却显示为未知字符问号框? - Brian Schroth
1
你的响应编码有误。请检查头文件和元标签,确保使用 UTF-8 编码。 - BalusC

5
这个问题也必须在Firefox上解决。

HTML
<div class="ellipsis">Here goes too long text and when it is takes more than 200px in "end" of the text appears "..."</div>

CSS

.ellipsis{
width:200px;
text-overflow:ellipsis;
-o-text-overflow:ellipsis;
-moz-binding:url('bindings.xml#ellipsis');//issue for Firefox
}

bindings.xml

<bindings xmlns="http://www.mozilla.org/xbl" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="none">
    <content><children/></content>
</binding>
<binding id="ellipsis">
    <content>
        <xul:label crop="end"><children/></xul:label>
    </content>
    <implementation>
        <field name="label">document.getAnonymousNodes(this)[0]</field>
        <field name="style">this.label.style</field>
        <property name="display">
            <getter>this.style.display</getter>
            <setter>if(this.style.display!= val)this.style.display=val</setter>
        </property>
        <property name="value">
            <getter>this.label.value</getter>
            <setter>if(this.label.value!=val)this.label.value=val</setter>
        </property>
        <method name="update">
            <body>
                var strings= this.textContent.split(/\s+/g)
                if(!strings[0])strings.shift()
                if(!strings[strings.length-1])strings.pop()
                this.value=strings.join('')
                this.display=strings.length?'':'none'
            </body>
        </method>
        <constructor>this.update()</constructor>
    </implementation>
    <handlers>
        <handler event="DOMSubtreeModified">this.update()</handler>
    </handlers>
</binding>
</bindings>

这会导致任何性能问题吗?使用此黑客技巧是否有任何基准测试? - jayarjo
不幸的是,使用这个 Firefox 绑定 XML 的文本是无法选择的。 - timmfin
@Ms2ger: 的确,请参见 https://dev59.com/lG445IYBdhLWcg3wUYnM#5148614 - SamB

4

我没有使用jQuery,所以它对我没有帮助。你发布的示例还可以,但有些错误,并且省略号放在了不应该放置的位置,看起来不太好。我坚持使用我的原始解决方案(将文本存储在可扩展容器中并测量其宽度,然后迭代地切割字符直到适合为止)。这适用于单个长字符串,但如果文本包含空格,则文本只会换行。无论文本有多长或包含什么内容,我都需要文本成为单行。 - Brian Schroth
你应该获取 jQuery 的副本。这可能是解决问题最简单的方法,而且你肯定会在开发中找到其他用途。 - Gausie
1
作为一名公司职员,获得使用jQuery的批准是一项巨大的任务,因此不幸的是我仍在寻找非jQuery的替代方案。 - Brian Schroth
在这种情况下,您可能会发现查看我发布的插件并检查是否可以应用逻辑而不使用库很有用。 - Gausie

3

1
当然,我仍然必须支持IE6,所以“最终”可能要等20年 :( - Brian Schroth
2
实际上(有点令人惊讶的是),IE6已经具备了text-overflow:ellipsis功能,所以你不用担心。 - Jacob Mattison
1
修改了我的帖子以表明当前支持的浏览器:IE6及以上,Safari,Chrome。 - Jacob Mattison

1

回答你提出的一个问题:

如果字符串长度为20个字符,但我发现它不适合,那么我必须将其截断为19个字符,添加省略号,然后再次检查是否适合。然后将其截断为18个字符(加上省略号)并再次尝试。一遍又一遍……直到它适合。有更好的方法吗?

找到正确长度的更快方法是将字符串分成两半,测试一下看是否适合。如果适合:则将原始长度的四分之一加回去,如果不适合,则减去四分之一,然后测试一下看是否适合。以此类推,使用原始长度的1/8、1/16、1/32等,直到这个加/减值小于1。

这是一种寻找算法:对于超过几个单词的字符串,您通常可以将在DOM中需要执行的测试数量减少10倍。


1

简单来说,没有更好的方法,除非采用一些技巧。

例如,你可以使用position:absolute的span标签将"..."定位在实际内容之上,然后在容器上设置overflow:hidden属性,只有当内容适应容器时才隐藏额外的span标签。这样你只需要运行截断代码一次。

个人而言,我会多运行几次像素宽度计算。设置文本并读取宽度是一个快速的操作,所以不应该有明显的延迟。


1
使用 text-overflow:ellipsis。它不只在IE浏览器上可用... 大多数主流浏览器都可以达到这个效果。
但如果你无法实现, 这里有一个jQuery插件 可以帮助你。

0

尝试使用{{link1:dojox.html.ellipsis}}


谢谢,我会试一试...与jQuery不同,dojo是我们已经在使用的库,所以这可能非常完美。 - Brian Schroth

0
关于Firefox 4.0和尚未实现的text-overflow:ellipsis CSS属性: 链接提供了该问题的部分解决方案。
它使用仅CSS就能产生类似于text-overflow:ellipsis的结果。

0

我按照Binyamin的回复,将this.value=strings.join('')改为this.value=strings.join(' '),这样就可以正常工作了!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接