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

时间:2009-02-11 13:43:08

标签: javascript html ellipsis elasticlayout

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

在此布局中,标题(h2)将具有可变长度(实际上是我无法控制的博客标题的头条新闻)。目前 - 如果它们比窗户宽 - 它们分成两行。

是否有一个优雅的,经过测试的(跨浏览器)解决方案 - 例如使用jQuery - 缩短了标题标记的innerHTML,如果文本太宽而无法放入一行,则会添加“...”当前屏幕/容器宽度?

24 个答案:

答案 0 :(得分:179)

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

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

如果您需要支持早期版本的Firefox,请查看my answer on this other question

答案 1 :(得分:118)

我有一个在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);

答案 2 :(得分:39)

我使用了许多其他帖子构建了此代码,其中包含以下增强功能:

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

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

答案 3 :(得分:20)

我的回答只支持单行文字。查看下面gfullam对多线分支的评论,它看起来很有希望。

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

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

它使用的逻辑如下所示:

enter image description here

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

我确定它需要一些调整,但这是代码:

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

答案 4 :(得分:18)

我制作了一个非常酷的jQuery插件,用于处理各种文本省略号,一个名为ThreeDots @ http://tpgblog.com/threedots

它比CSS方法更灵活,并支持更高级,可自定义的行为和交互。

享受。

答案 5 :(得分:18)

以防万一你们在2013年结束这里 - 这是我在这里找到的一种纯粹的CSS方法:http://css-tricks.com/snippets/css/truncate-string-with-ellipsis/

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

效果很好。

答案 6 :(得分:8)

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

http://dotdotdot.frebsite.nl

答案 7 :(得分:8)

trunk8 jQuery插件支持多行,并且可以使用任何html而不仅仅是省略号字符作为截断后缀:https://github.com/rviscomi/trunk8

在这里演示:http://jrvis.com/trunk8/

答案 8 :(得分:5)

实际上有一种非常简单的方法do this in CSS利用IE扩展非标准和FF支持:after

的事实

如果您愿意,也可以通过检查目标的scrollWidth并将其与父亲的宽度进行比较来do this in JS,但是这样不那么健壮。

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

最后一个是好读。

答案 9 :(得分: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是与背景颜色相同的图像,宽度约为100像素,高度与行高相同。

它不是很漂亮,因为你的文字可能会在一个字母的中间剪切,但在某些情况下可能会有用。

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

答案 10 :(得分:3)

嗯,一个简单的解决方案,并没有完全添加“...”,但确实阻止了&lt; h2&gt;从分为两行将添加这一点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标签的文本内容(或者用具有给定高度的东西包裹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;
                }
            }
        }
    }

答案 11 :(得分:3)

这是另一个JavaScript解决方案。 工作非常好,非常快。

https://github.com/dobiatowski/jQuery.FastEllipsis

在Windows和Mac上的Chrome,FF,IE上进行了测试。

答案 12 :(得分: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>

答案 13 :(得分:2)

文本内容的纯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>

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

答案 14 :(得分: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 + "...");
    }
  }
};

答案 15 :(得分:2)

Devon Govett有一个简单的jQuery解决方案:

https://gist.github.com/digulla/5796047

  

要使用,只需在jQuery对象上调用省略号()。例如:

     

$( “跨度”)省略号();

答案 16 :(得分:1)

使用仅限CSS

进行ELLIPSIS
<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;

答案 17 :(得分:1)

只使用css可以更轻松地完成这项工作,例如:sass mode

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

你有省略号;)

答案 18 :(得分: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>

答案 19 :(得分:1)

虽然我对css的行为感到有些惊讶。

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

除非我提供了我需要绑定的控件的宽度,省略号并没有支持我的原因。宽度是必须添加的属性吗??? 请把你的想法。

答案 20 :(得分:1)

我找不到一个完全按照我的意愿工作的脚本,所以我自己为jQuery做了一些 - 在他们的路上设置了更多的选项:)

https://github.com/rmorse/AutoEllipsis

答案 21 :(得分: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();
    }
}
});

答案 22 :(得分:0)

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

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

答案 23 :(得分: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 life—your 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 life—your 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>