如果内容太宽,请在HTML标记中插入省略号(...)


148

我有一个带有弹性布局的网页,如果调整了浏览器窗口的大小,该网页的宽度就会改变。

在此布局中,标题(h2)的长度是可变的(实际上是我无法控制的博客文章的标题)。当前-如果它们比窗口宽-分为两行。

是否有一个经过测试的(跨浏览器)优雅的解决方案(例如jQuery),可以缩短该标题标签的innerHTML,并在文本太宽而无法在当前屏幕/容器宽度?


1
2014年更新的答案:stackoverflow.com/a/22811590/759452
Adrien是

我已经基于使用CSS属性的空白和自动换行来格式化文本的线程创建了插件。github.com/nothrem/jQuerySmartEllipsis
Radek Pech

Answers:


119

我有一个可以在FF3,Safari和IE6 +中使用单行和多行文本的解决方案

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

.ellipsis.multiline {
    white-space: normal;
}

<div class="ellipsis" style="width: 100px; border: 1px solid black;">Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
<div class="ellipsis multiline" style="width: 100px; height: 40px; border: 1px solid black; margin-bottom: 100px">Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>

<script type="text/javascript" src="/js/jquery.ellipsis.js"></script>
<script type="text/javascript">
$(".ellipsis").ellipsis();
</script>

jquery.ellipsis.js

(function($) {
    $.fn.ellipsis = function()
    {
        return this.each(function()
        {
            var el = $(this);

            if(el.css("overflow") == "hidden")
            {
                var text = el.html();
                var multiline = el.hasClass('multiline');
                var t = $(this.cloneNode(true))
                    .hide()
                    .css('position', 'absolute')
                    .css('overflow', 'visible')
                    .width(multiline ? el.width() : 'auto')
                    .height(multiline ? 'auto' : el.height())
                    ;

                el.after(t);

                function height() { return t.height() > el.height(); };
                function width() { return t.width() > el.width(); };

                var func = multiline ? height : width;

                while (text.length > 0 && func())
                {
                    text = text.substr(0, text.length - 1);
                    t.html(text + "...");
                }

                el.html(t.html());
                t.remove();
            }
        });
    };
})(jQuery);

22
很好,我一直在寻找如何处理多行溢出。一项改进:不用附加三个句号,而是加上省略号'...'。
Simon Lieschke,2009年

4
这很好。您应该将此内容发布在jQuery网站上。
Edgar

1
尽管在IE中,如果省略号功能应用于仅具有链接的div,则省略号后该链接会消失。关于这个有什么建议吗?
钱兹2011年

6
如果您希望实际操作,可以在这里查看(对插件代码的错误
Dan Esparza

22
为了提高性能,请执行二进制搜索,而不要一次在“ while”循环中删除1个字符。如果100%的文字不合适,请尝试50%的文字;那么,如果50%适合文本的75%,或25%,如果50%不适合,等
StanleyH

182

以下的仅用于CSS的用于在一行上截断文本的解决方案在撰写本文时适用于http://www.caniuse.com上列出的所有浏览器,但Firefox 6.0除外。请注意,除非您需要支持包装多行文本或Firefox的早期版本,否则完全不需要JavaScript。

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

如果您需要早期版本的Firefox支持,请查看我对其他问题的回答


2
这比jQuery方法快几个数量级。在IE7 +和Chrome中正常运行。
JDB仍记得Monica

3
这也适用于古老的浏览器。我们在2004年左右的Google上成功使用了它,要求我们在某些真正的极端浏览器上优雅地支持或降级。
ElBel 2013年

2
JS Fiddle针对那些希望在浏览器上进行采样的人-jsfiddle.net/r39Ad
Deepak Bala

@DilipRajkumar你需要提供更多的细节如一个的jsfiddle例子来展示它不是在IE 8的工作
西蒙Lieschke

1
@SharpCoder你不知道。截断文本的位置由包含文本的元素的宽度决定,即,文本在溢出元素的宽度时会被截断。
Simon Lieschke 2014年

40

我使用其他许多帖子构建了此代码,并进行了以下增强:

  1. 它使用二进制搜索来找到恰到好处的文本长度。
  2. 它通过设置一个一次性显示事件来处理省略号元素最初被隐藏的情况,该事件一次显示该项目时将重新运行省略号代码。这对于最初未显示某些项目的主从视图或树视图非常方便。
  3. 可以选择将title属性与原始文本一起添加,以提供悬停效果。
  4. 添加display: block到样式中,因此工作跨度
  5. 它使用省略号而不是3个句点。
  6. 它会自动使用.ellipsis类运行脚本

CSS:

.ellipsis {
        white-space: nowrap;
        overflow: hidden;
        display: block;
}

.ellipsis.multiline {
        white-space: normal;
}

jquery.ellipsis.js

(function ($) {

    // this is a binary search that operates via a function
    // func should return < 0 if it should search smaller values
    // func should return > 0 if it should search larger values
    // func should return = 0 if the exact value is found
    // Note: this function handles multiple matches and will return the last match
    // this returns -1 if no match is found
    function binarySearch(length, func) {
        var low = 0;
        var high = length - 1;
        var best = -1;
        var mid;

        while (low <= high) {
            mid = ~ ~((low + high) / 2); //~~ is a fast way to convert something to an int
            var result = func(mid);
            if (result < 0) {
                high = mid - 1;
            } else if (result > 0) {
                low = mid + 1;
            } else {
                best = mid;
                low = mid + 1;
            }
        }

        return best;
    }

    // setup handlers for events for show/hide
    $.each(["show", "toggleClass", "addClass", "removeClass"], function () {

        //get the old function, e.g. $.fn.show   or $.fn.hide
        var oldFn = $.fn[this];
        $.fn[this] = function () {

            // get the items that are currently hidden
            var hidden = this.find(":hidden").add(this.filter(":hidden"));

            // run the original function
            var result = oldFn.apply(this, arguments);

            // for all of the hidden elements that are now visible
            hidden.filter(":visible").each(function () {
                // trigger the show msg
                $(this).triggerHandler("show");
            });

            return result;
        };
    });

    // create the ellipsis function
    // when addTooltip = true, add a title attribute with the original text
    $.fn.ellipsis = function (addTooltip) {

        return this.each(function () {
            var el = $(this);

            if (el.is(":visible")) {

                if (el.css("overflow") === "hidden") {
                    var content = el.html();
                    var multiline = el.hasClass('multiline');
                    var tempElement = $(this.cloneNode(true))
                        .hide()
                        .css('position', 'absolute')
                        .css('overflow', 'visible')
                        .width(multiline ? el.width() : 'auto')
                        .height(multiline ? 'auto' : el.height())
                    ;

                    el.after(tempElement);

                    var tooTallFunc = function () {
                        return tempElement.height() > el.height();
                    };

                    var tooWideFunc = function () {
                        return tempElement.width() > el.width();
                    };

                    var tooLongFunc = multiline ? tooTallFunc : tooWideFunc;

                    // if the element is too long...
                    if (tooLongFunc()) {

                        var tooltipText = null;
                        // if a tooltip was requested...
                        if (addTooltip) {
                            // trim leading/trailing whitespace
                            // and consolidate internal whitespace to a single space
                            tooltipText = $.trim(el.text()).replace(/\s\s+/g, ' ');
                        }

                        var originalContent = content;

                        var createContentFunc = function (i) {
                            content = originalContent.substr(0, i);
                            tempElement.html(content + "…");
                        };

                        var searchFunc = function (i) {
                            createContentFunc(i);
                            if (tooLongFunc()) {
                                return -1;
                            }
                            return 0;
                        };

                        var len = binarySearch(content.length - 1, searchFunc);

                        createContentFunc(len);

                        el.html(tempElement.html());

                        // add the tooltip if appropriate
                        if (tooltipText !== null) {
                            el.attr('title', tooltipText);
                        }
                    }

                    tempElement.remove();
                }
            }
            else {
                // if this isn't visible, then hook up the show event
                el.one('show', function () {
                    $(this).ellipsis(addTooltip);
                });
            }
        });
    };

    // ellipsification for items with an ellipsis
    $(document).ready(function () {
        $('.ellipsis').ellipsis(true);
    });

} (jQuery));

2
美丽。Bravo实现了我对二进制搜索的建议。
StanleyH 2012年

2
简要说明一下...值得在tempElement变量中添加.css('max-width','none')...这样一来,您可以在CSS中使用max-width声明,从而使插件更加灵活(至少对于我拥有的大多数用例而言)。还是不错的工作。:)
gordyr 2012年

3
这比上面接受的答案要快得多。如果您有多个.ellipsis元素,并且对它们进行动态处理,则此元素的性能要好得多。
mjvotaw 2012年

你能举个例子吗?我的问题在这里:stackoverflow.com/questions/26344520/…–
SearchForKnowledge

二进制搜索是可取的,但不是非常小的数据集,并且在这种情况下,与诸如indexOf()的直线搜索相比,它会妨碍性能...显然
user1360809

20

我的答案仅支持单行文字。在下面查看gfullam对多行fork的评论,它看起来很有前途。

我将第一个答案的代码重写了几次,我认为这应该是最快的。

它首先找到一个“估计的”文本长度,然后添加或删除一个字符,直到宽度正确为止。

它使用的逻辑如下所示:

在此处输入图片说明

找到“估计的”文本长度后,添加或删除字符,直到达到所需的宽度。

我确定需要进行一些调整,但这是以下代码:

(function ($) {
    $.fn.ellipsis = function () {
        return this.each(function () {
            var el = $(this);

            if (el.css("overflow") == "hidden") {
                var text = el.html().trim();
                var t = $(this.cloneNode(true))
                                        .hide()
                                        .css('position', 'absolute')
                                        .css('overflow', 'visible')
                                        .width('auto')
                                        .height(el.height())
                                        ;
                el.after(t);

                function width() { return t.width() > el.width(); };

                if (width()) {

                    var myElipse = "....";

                    t.html(text);

                    var suggestedCharLength = (text.length * el.width() / t.width()) - myElipse.length;

                    t.html(text.substr(0, suggestedCharLength) + myElipse);

                    var x = 1;
                    if (width()) {
                        while (width()) {
                            t.html(text.substr(0, suggestedCharLength - x) + myElipse);
                            x++;
                        }
                    }
                    else {
                        while (!width()) {
                            t.html(text.substr(0, suggestedCharLength + x) + myElipse);
                            x++;
                        }
                        x--;
                        t.html(text.substr(0, suggestedCharLength + x) + myElipse);
                    }

                    el.html(t.html());
                    t.remove();
                }
            }
        });
    };
})(jQuery);

3
您的解决方案可能不是最好的,但是已经很好地解释了。我喜欢这种近似逻辑。+1 :)
平坦的时间2013年

2
我已分叉此操作,以添加对textareas和多行(垂直)省略号截断的支持:jsfiddle.net/gfullam/j29z7381(我喜欢近似逻辑BTW)
gfullam



8

更加灵活的jQuery插件,使您可以在省略号后保留元素(例如,“阅读更多”按钮)并更新onWindowResize。它还适用于带有标记的文本:

http://dotdotdot.frebsite.nl


我刚刚测试了此插件,但无法使其正常工作。Trunk8对我来说是一个更好的选择。
Guilherme Garnier 2012年


5

实际上利用IE通过非标准和FF支持扩展这一事实,在CSS中实际上是一种非常简单的方法:after

如果愿意,您也可以在JS中执行此操作,方法是检查目标的scrollWidth并将其与父对象的宽度进行比较,但是恕我直言,这种方法不那么可靠。

编辑:这显然比我想象的要发达。CSS3支持可能很快就会存在,并且一些不完善的扩展可供您尝试。

最后一本是一本好书。


实际上,我更喜欢JS解决方案-因为如果文本比可用空间宽,它只会添加“ ...”。
BlaM

3

我最近为客户做了类似的事情。这是我为他们所做的工作的一个版本(示例在Win Vista上的所有最新浏览器版本中进行了测试)。并非全面,但可以很容易地进行调整。

演示:http//enobrev.info/ellipsis/

码:

<html>
    <head>
        <script src="http://www.google.com/jsapi"></script>
        <script>            
            google.load("jquery", "1.2.6");
            google.setOnLoadCallback(function() {
                $('.longtext').each(function() {
                    if ($(this).attr('scrollWidth') > $(this).width()) {
                        $more = $('<b class="more">&hellip;</b>');

                        // add it to the dom first, so it will have dimensions
                        $(this).append($more);

                        // now set the position
                        $more.css({
                            top: '-' + $(this).height() + 'px',
                            left: ($(this).attr('offsetWidth') - $more.attr('offsetWidth')) + 'px'
                        });
                    }
                });
            });
        </script>

        <style>
            .longtext {
                height: 20px;
                width: 300px;
                overflow: hidden;
                white-space: nowrap;
                border: 1px solid #f00;
            }

            .more {
                z-index: 10;
                position: relative;
                display: block;
                background-color: #fff;
                width: 18px;
                padding: 0 2px;
            }
        </style>
    </head>
    <body>
        <p class="longtext">This is some really long text.  This is some really long text.  This is some really long text.  This is some really long text.</p>
    </body>
</html>

3

好吧,一个简单的解决方案是不添加“ ...”,但确实防止<h2>分成两行,那就是添加以下css:

h2 {
    height:some_height_in_px; /* this is the height of the line */
    overflow:hidden; /* so that the second (or third, fourth, etc.)
                        line is not visible */
}

我再三考虑,然后提出了这个解决方案,您必须将h2标签的文本内容换成另一个标签(例如span)(或者将h2s换成具有给定高度的东西),然后您可以使用这种javascript过滤掉不需要的单词:

var elems = document.getElementById('conainter_of_h2s').
                     getElementsByTagName('h2');

    for ( var i = 0, l = elems.length; i < l; i++) {
        var span = elems.item(i).getElementsByTagName('span')[0];
        if ( span.offsetHeight > elems.item(i).offsetHeight ) {
            var text_arr = span.innerHTML.split(' ');
            for ( var j = text_arr.length - 1; j>0 ; j--) {
                delete text_arr[j];
                span.innerHTML = text_arr.join(' ') + '...';
                if ( span.offsetHeight <= 
                                        elems.item(i).offsetHeight ){
                    break;
                }
            }
        }
    }

实际上,我曾经考虑过以此为基础,以作为可能的解决方案的依据,但是我不知道是否-基于此-是否有可能找出现在是否显示整个文本,或者是否需要缩短它并添加“ ...”。只是切断它看起来很奇怪。
BlaM


3

有一种使用纯CSS的多行文本的解决方案。称为line-clamp,但仅在Webkit浏览器中有效。但是,有一种方法可以在所有现代浏览器中(比IE8都新的东西)来模仿。此外,它仅适用于纯色背景,因为您需要背景图片来隐藏最后一行的最后一个单词。这是怎么回事:

鉴于此html:

<p class="example" id="example-1">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>

这是CSS:

p {
    position:relative;
    line-height:1.4em;
    height:4.2em;      /* 3 times the line-height to show 3 lines */
}
p::after {
    content:"...";
    font-weight:bold;
    position:absolute;
    bottom:0;
    right:0;
    padding:0 20px 1px 45px;
    background:url(ellipsis_bg.png) repeat-y;
}

ellipsis_bg.png是与背景颜色相同的图像,宽度约为100px,高度与行高相同。

它不是很漂亮,因为您的文本可能会在字母中间被剪掉,但在某些情况下可能很有用。

参考:http : //www.css-101.org/articles/line-clamp/line-clamp_for_non_webkit-based_browsers.php


很好,但是您需要确保您的文本足够长,因为即使文本足够短以适合可用空间,此CSS也会添加“ ...”。顺便说一句:大约一个月前Apopii提供了相同的答案;)
BlaM 2013年

@BlaM确实差不多。但是我认为渐变技巧很简洁,并且此代码是CSS而不是SASS的代码,因此我认为值得单独回答。
Jules Colle

3

用于文本内容的纯CSS多行省略号:

.container{
    position: relative;  /* Essential */
    background-color: #bbb;  /* Essential */
    padding: 20px; /* Arbritrary */
}
.text {
    overflow: hidden;  /* Essential */
    /*text-overflow: ellipsis; Not needed */
    line-height: 16px;  /* Essential */
    max-height: 48px; /* Multiples of line-height */
}
.ellipsis {
    position: absolute;/* Relies on relative container */
    bottom: 20px; /* Matches container padding */
    right: 20px; /* Matches container padding */
    height: 16px; /* Matches line height */
    width: 30px; /* Arbritrary */
    background-color: inherit; /* Essential...or specify a color */
    padding-left: 8px; /* Arbritrary */
}
<div class="container">
    <div class="text">
        Lorem ipsum dolor sit amet, consectetur eu in adipiscing elit. Aliquam consectetur venenatis blandit. Praesent vehicula, libero non pretium vulputate, lacus arcu facilisis lectus, sed feugiat tellus nulla eu dolor. Nulla porta bibendum lectus quis euismod. Aliquam volutpat ultricies porttitor. Cras risus nisi, accumsan vel cursus ut, sollicitudin vitae dolor. Fusce scelerisque eleifend lectus in bibendum. Suspendisse lacinia egestas felis a volutpat. Aliquam volutpat ultricies porttitor. Cras risus nisi, accumsan vel cursus ut, sollicitudin vitae dolor. Fusce scelerisque eleifend lectus in bibendum. Suspendisse lacinia egestas felis a volutpat.
    </div>
    <div class="ellipsis">...</div>
</div>

请查看代码段以获取实时示例。


2

这类似于Alex的方法,但是以对数时间而不是线性的方式进行,并采用maxHeight参数。

jQuery.fn.ellipsis = function(text, maxHeight) {
  var element = $(this);
  var characters = text.length;
  var step = text.length / 2;
  var newText = text;
  while (step > 0) {
    element.html(newText);
    if (element.outerHeight() <= maxHeight) {
      if (text.length == newText.length) {
        step = 0;
      } else {
        characters += step;
        newText = text.substring(0, characters);
      }
    } else {
      characters -= step;
      newText = newText.substring(0, characters);
    }
    step = parseInt(step / 2);
  }
  if (text.length > newText.length) {
    element.html(newText + "...");
    while (element.outerHeight() > maxHeight && newText.length >= 1) {
      newText = newText.substring(0, newText.length - 1);
      element.html(newText + "...");
    }
  }
};


1

我将Alex的函数重写为MooTools库。我将其更改为单词跳转,而不是在单词中间添加省略号。

Element.implement({
ellipsis: function() {
    if(this.getStyle("overflow") == "hidden") {
        var text = this.get('html');
        var multiline = this.hasClass('multiline');
        var t = this.clone()
            .setStyle('display', 'none')
            .setStyle('position', 'absolute')
            .setStyle('overflow', 'visible')
            .setStyle('width', multiline ? this.getSize().x : 'auto')
            .setStyle('height', multiline ? 'auto' : this.getSize().y)
            .inject(this, 'after');

        function height() { return t.measure(t.getSize).y > this.getSize().y; };
        function width() { return t.measure(t.getSize().x > this.getSize().x; };

        var func = multiline ? height.bind(this) : width.bind(this);

        while (text.length > 0 && func()) {
            text = text.substr(0, text.lastIndexOf(' '));
            t.set('html', text + "...");
        }

        this.set('html', t.get('html'));
        t.dispose();
    }
}
});


1

不过,我对CSS的行为感到有些惊讶。

var cssEllipsis = 
{   "width": "100%","display": "inline-block", 
"vertical-align": "middle", "white-space": "nowrap", 
"overflow": "hidden", "text-overflow": "ellipsis" 
};

除非我为需要绑定省略号的控件提供宽度,否则不会阻止我的事业。宽度是否必须添加?请发表您的想法。


1

使用CSS进行省略号

<html>
<head>
<style type="text/css">
#ellipsisdiv {
    width:200px;
    white-space: nowrap;  
    overflow: hidden;  
    text-overflow: ellipsis;  
}  
</style>
</head>
<body>
<div id="ellipsisdiv">
This content is more than 200px and see how the the ellipsis comes at the end when the content width exceeds the div width.
</div>
</body>
</html>

*此代码可在大多数当前浏览器上使用。如果您在Opera和IE中遇到任何问题(可能不会),请添加以下样式:

-o-text-overflow: ellipsis;  
-ms-text-overflow: ellipsis;

*此功能是CSS3的一部分。它的完整语法为:

text-overflow: clip|ellipsis|string;

1

这是一个不错的窗口小部件/插件库,内置了省略号:http : //www.codeitbetter.co.uk/widgets/ellipsis/您需要做的所有工作都引用该库并调用以下代码:

<script type="text/javascript"> 
   $(document).ready(function () { 
      $(".ellipsis_10").Ellipsis({ 
         numberOfCharacters: 10, 
         showLessText: "less", 
         showMoreText: "more" 
      }); 
   }); 
</script> 
<div class="ellipsis_10"> 
   Some text here that's longer than 10 characters. 
</div>

1

您可以仅使用css轻松完成此操作,例如:sass模式

.truncatedText {
   font-size: 0.875em;
   line-height: 1.2em;
   height: 2.4em; // 2 lines * line-height
   &:after {
      content: " ...";
   }
}

并且您有省略号;)


0

就像@acSlater一样,我找不到适合我需要的东西,所以我自己动手了。共享以防其他人使用:

方法:
ellipsisIfNecessary(mystring,maxlength);
用法:
trimmedString = ellipsisIfNecessary(mystring,50);
代码和演示链接:https : //gist.github.com/cemerson/10368014

有两个注释:a)此代码不检查HTML元素的实际大小。您需要指定一个给定的长度-这可能是必需的功能,但实际上很简单。b)您只需在字符串末尾添加“ ...”。您可以/应该使用省略号“ ...”。
BlaM 2014年

嘿@BlaM-代码实际上确实对照maxlength参数检查了长度。至少对我有用。话虽如此-这只是我对自己的情况的谦卑的一次。如果此解决方案不适用于您的情况,请随意使用上述任何解决方案。
Christopher D. Emerson

是的,它只能使用“长度”,而不能使用“宽度”(像素大小)。
BlaM 2014年

有趣的主意-随时为其提供支持的更新版本。我现在不需要,但将来可能会有用。
Christopher D. Emerson 2014年

0
<html>
<head>
    <!-- By Warren E. Downs, copyright 2016.  Based loosely on a single/multiline JQuery using example by Alex,
    but optimized to avoid JQuery, to use binary search, to use CSS text-overflow: ellipsis for end,
    and adding marquee option as well.
    Credit: Marquee: http://jsfiddle.net/jonathansampson/xxuxd/
            JQuery version: http://stackoverflow.com/questions/536814/insert-ellipsis-into-html-tag-if-content-too-wide
            (by Alex, http://stackoverflow.com/users/71953/alex)
            (Improved with Binary Search as suggested by StanleyH, http://stackoverflow.com/users/475848/stanleyh)
    -->
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta content="utf-8" http-equiv="encoding">
    <style>

        .single {
            overflow:hidden;
            white-space: nowrap;
            width: 10em;
            padding: 10px;
            margin: 0 auto;
            border: solid 1px blue;
        }

        .multiline {
            overflow: hidden;
            white-space: wrap;
            width: 10em;
            height: 4.5em;
            padding: 10px;
            margin: 0 auto;
            border: solid 1px blue;
        }

        .marquee {
            overflow: hidden;
            width: 40em;
            padding: 10px;
            margin: 0 auto;
            border: solid 1px blue;
        }

</style>
    <script>
        var _marqueeNumber=0;
        // mode=start,end,middle
        function clipText(text, len, mode) {
            if(!mode) { mode="end"; }
            else { mode=mode.toLowerCase(); }
            if(mode == "start") { return "&hellip;"+clipText(text,len,"_start"); }
            if(mode == "_start") { return text.substr(text.length - len); }
            if(mode == "middle") { 
                return clipText(text, len/2, "end") + clipText(text, len/2, "_start");
            }
            return text.substr(0, len) + "&hellip;";
        }

        function generateKeyframes(clsName, start, end) {
            var sec=5;
            var totalLen=parseFloat(start)-parseFloat(end);
            if(start.indexOf('em') > -1)      { sec=Math.round(totalLen/3); }
            else if(start.indexOf('px') > -1) { sec=Math.round(totalLen/42); }

            var style = document.createElement('style');
            style.type = 'text/css';
            style.innerHTML = 'body {}';
            document.getElementsByTagName('head')[0].appendChild(style);
            this.stylesheet = document.styleSheets[document.styleSheets.length-1];
            try {
                this.stylesheet.insertRule('.'+clsName+' {\n'+
                    '    animation: '+clsName+' '+sec+'s linear infinite;\n'+
                    '}\n', this.stylesheet.rules.length);
                this.stylesheet.insertRule('.'+clsName+':hover {\n'+
                    '    animation-play-state: paused\n'+
                    '}\n', this.stylesheet.rules.length);
                this.stylesheet.insertRule('@keyframes '+clsName+' {\n'+
                    '    0%   { text-indent: '+start+' }\n'+
                    '    100% { text-indent: '+end+' }\n'+
                    '}', this.stylesheet.rules.length);
            } catch (e) {
                console.log(e.message);
            }
        }

        function addClone(el, multiline, estyle) {
            if(!estyle) { 
                try { estyle=window.getComputedStyle(el); }
                catch(e) { return null; }
            }
            var t = el.cloneNode(true);
            var s=t.style;
            //s.display='none';
            s.visibility='hidden'; // WARNING: Infinite loop if this is not hidden (e.g. while testing)
            s.display='inline-block';
            s.background='black';
            s.color='white';
            s.position='absolute';
            s.left=0;
            s.top=0;
            s.overflow='visible';
            s.width=(multiline ? parseFloat(estyle.width) : 'auto');
            s.height=(multiline ? 'auto' : parseFloat(estyle.height));

            el.parentNode.insertBefore(t, el.nextSibling);

            return t;
        }
        function getTextWidth(el, multiline) {
            var t=addClone(el, multiline);
            if(!t) { return null; }
            var ts=window.getComputedStyle(t);
            var w=ts.width;
            if(multiline) {
                var es=window.getComputedStyle(el);
                var lines=Math.round(parseInt(ts.height)/parseInt(es.height))*2+0.5;
                w=w+'';
                var unit=''; // Extract unit
                for(var xa=0; xa<w.length; xa++) {
                    var c=w[xa];
                    if(c <= '0' || c >= '9') { unit=w.substr(xa-1); }
                }
                w=parseFloat(w);
                w*=lines; // Multiply by lines
                w+=unit; // Append unit again
            }
            t.parentNode.removeChild(t);
            return w;
        }

        // cls=class of element to ellipsize
        // mode=start,end,middle,marq (scrolling marquee instead of clip)
        function ellipsis(cls, mode) {
            mode=mode.toLowerCase();
            var elems=document.getElementsByClassName(cls);
            for(xa in elems) {
                var el=elems[xa];
                var multiline = el.className ? el.className.indexOf('multiline') > -1 : true;
                if(mode == "marq") {       
                    var w=getTextWidth(el, multiline);
                    if(!w) { continue; }
                    var mCls="dsmarquee"+(_marqueeNumber++);
                    var es=window.getComputedStyle(el);
                    generateKeyframes(mCls,es.width, '-'+w);
                    el.className+=" "+mCls; 
                    continue; 
                }
                if(mode == "end" && !multiline) { el.style.textOverflow="ellipsis"; continue; }
                var estyle=null;
                try { estyle=window.getComputedStyle(el); }
                catch(e) { continue; }
                if(estyle.overflow == "hidden") {
                    var text = el.innerHTML;
                    var t=addClone(el, multiline, estyle);

                    function height() {
                        var ts=window.getComputedStyle(t);
                        var es=window.getComputedStyle(el);
                        return parseFloat(ts.height) - parseFloat(es.height); 
                    }
                    function width() { 
                        var ts=window.getComputedStyle(t);
                        var es=window.getComputedStyle(el);
                        return parseFloat(ts.width) - parseFloat(es.width); 
                    }

                    var tooLong = multiline ? height : width;

                    var len=text.length;
                    var diff=1;
                    var olen=0;
                    var jump=len/2;
                    while (len > 0) {
                        var diff=tooLong();
                        if(diff > 0) { len-=jump; jump/=2; }
                        else if(diff < 0) { len+=jump; }
                        len=Math.round(len);
                        //alert('len='+len+';olen='+olen+';diff='+diff+';jump='+jump+';t='+JSON.stringify(t.innerHTML));
                        t.innerHTML=clipText(text, len, mode);
                        if(olen == len) { break; }
                        olen=len;
                    }
                    el.innerHTML=t.innerHTML;
                    t.parentNode.removeChild(t);
                }           
                //break;
                t.style.visibility='hidden';
            }
        }

        function testHarness() {
            ellipsis('ellipsis1', 'start'); 
            ellipsis('ellipsis2', 'end'); 
            ellipsis('ellipsis3', 'middle'); 
            ellipsis('marquee', 'marq')
        }
    </script>
    </head>
    <body onload="testHarness()">
    <div class="single ellipsis1" style="float:left">some long text that should be clipped left</div>
    <div class="single ellipsis2" style="float:right">right clip long text that should be clipped</div>
    <div class="single ellipsis3" style="float:center">some long text that should be clipped in the middle</div>

    <br />

    <p class="single marquee">Windows 8 and Windows RT are focused on your lifeyour friends and family, your apps, and your stuff. With new things like the <a href="http://windows.microsoft.com/en-US/windows-8/start-screen">Start screen</a>, <a href="http://windows.microsoft.com/en-US/windows-8/charms">charms</a>, and a <a href="http://windows.microsoft.com/en-US/windows-8/microsoft-account">Microsoft account</a>, you can spend less time searching and more time doing.</p>
    &nbsp;

    <br />

    <div class="multiline ellipsis1" style="float:left">Test test test test test test, some more long text, such as asdasdasdasdasd, that should be multiline clipped left(*)</div>

    <div class="multiline ellipsis2" style="float:right">right clip multiline long text, such as Test test test test test test, and some more long text that should be multiline clipped right.</div>

    <div class="multiline ellipsis3" style="float:center">Test test test test test test, some more long text, such as asdasdasdasdasd, that should be multiline clipped in the middle(*)</div>

    <br />

    <p class="multiline marquee">Multiline Marquee: Windows 8 and Windows RT are focused on your lifeyour friends and family, your apps, and your stuff. With new things like the <a href="http://windows.microsoft.com/en-US/windows-8/start-screen">Start screen</a>, <a href="http://windows.microsoft.com/en-US/windows-8/charms">charms</a>, and a <a href="http://windows.microsoft.com/en-US/windows-8/microsoft-account">Microsoft account</a>, you can spend less time searching and more time doing.</p>
    &nbsp;

    </body>
</html>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.