├── README.md ├── examples ├── css-or-js.html └── examples.html ├── lib └── jquery.text-overflow.js └── todo /README.md: -------------------------------------------------------------------------------- 1 | ## jQuery Text Overflow plugin 2 | 3 | This jQuery plugin implements a simplified version of the 4 | [CSS3 text-overflow](https://developer.mozilla.org/en/CSS/text-overflow) 5 | property. The `text-overflow` property allows stylesheet authors to 6 | specify how and where text should be clipped. This is usually done 7 | by adding an ellipsis character "`…`" or three dots at the point 8 | the text should be cut off. Various browsers support this property, 9 | such as Opera, Internet Explorer and Safari. Firefox unfortunately 10 | does not. However, using this plugin you can simulate this 11 | functionality (well, as close as you can get without a native 12 | implementation.) 13 | 14 | To use it you simply call the `textOverflow` method on elements you 15 | want clipped. Clipping is only applied when the browser does not 16 | support it natively. The following is an example of how to clip all 17 | header elements on a page using the default plugin settings. 18 | 19 | $('h1').textOverflow(); 20 | 21 | The `textOverflow` method optionally supports an options object containing: the 22 | string to use for clipping the text, and a boolean to determine 23 | whether the plugin should automatically update the clipping when a 24 | change in the document has been detected. 25 | 26 | textOverflow(options) 27 | 28 | The options object can contain the following properties: 29 |
30 |
`str`
31 |
The string to append to the content before it is clipped. Defaults to the ellipsis character "`…`". May also contain HTML, but the string itself is not subject to being clipped.
32 |
`autoUpdate`
33 |
Automatically update the clipped text when the available space for the text becomes smaller or larger. Defaults to false (because it incurs some extra costs.)
34 |
`trim`
35 |
True to remove trailing white-space at the point where content is clipped. False to leave the white-space. Defaults to true.
36 |
`title`
37 |
True to add the full text as a title attribute on the clipped element. Defaults to false.
38 |
`className`
39 |
Class name to add to the element whose content is clipped. Note that elements whose content fit in the container will not have this class name added.
40 |
`wholeWord`
41 |
True to clip content only at whole word boundaries. False might clip a word anywhere. Defaults to false.
42 |
43 | 44 | The following example shows how to replace the default ellipsis 45 | character on all list elements with a three dot version, and turn 46 | on automatic updating. 47 | 48 | $('li').textOverflow({ 49 | str: '...', 50 | autoUpdate: true 51 | }); 52 | 53 | Please see the [examples page](examples/examples.html) for more examples on 54 | how to use the plugin. 55 | 56 | ## Frequently asked questions 57 | 58 | Q: Does this plugin support HTML elements inside the clipped content? 59 | 60 | A: Yes. 61 | 62 | Q: How do I use this in combination with browsers that support the 63 | text-overflow property? 64 | 65 | A: Simply use the CSS3 `text-overflow` property as you would normally, 66 | e.g. 67 | 68 | overflow: hidden; 69 | white-space: nowrap; 70 | text-overflow: ellipsis; 71 | 72 | Then also call the `textOverflow` plugin method on the same 73 | elements. When a browser has native support for the `text-overflow` 74 | property, the text overflow plugin will let the browse handle it 75 | natively, and otherwise it will apply its own text truncation code. 76 | For more details, see the 77 | [CSS and JavaScript text overflow example](examples/css-or-js.html), or the 78 | [Quirkmode's article on the text-overflow property](http://www.quirksmode.org/css/textoverflow.html). 79 | 80 | Q: How do I restore the original contents of the clipped elements? 81 | 82 | A: It depends on what your use case is. If you want to show more or 83 | less of the clipped element based on browser or element resize 84 | events, simply turn the `autoUpdate` functionality on. If you want 85 | to manually restore the original content, you'll have to store it 86 | somewhere yourself before applying the text overflow plugin. 87 | 88 | Q: Text overflow doesn't work when applied to hidden elements (using 89 | `display: none`.) 90 | 91 | A: This is caused by the browser taking the elements out of the page 92 | flow. When an element is not in the page flow it has zero width and 93 | height. The text overflow plugin uses the width and height to 94 | calculate where to clip the text, so it can not do its work when an 95 | element is hidden. There are two approaches to work around this 96 | problem: the most simple solution is to only call the text overflow 97 | plugin after you display the hidden elements. Alternatively you 98 | could position the hidden elements offscreen and set its 99 | `visibility` property to `hidden` and then measure it. 100 | 101 | ## Credits 102 | 103 | - 104 | [Devon Govett](http://devongovett.wordpress.com/2009/04/06/text-overflow-ellipsis-for-firefox-via-jquery/) 105 | ― Original plugin. 106 | 107 | - 108 | Andrew A. Kononykhin ― Bug fix for markup reset on cloned 109 | elements. 110 | 111 | - 112 | Micky Hulse ― Bug report on ellipsis character encoding & incorrect 113 | DOM tree truncation. 114 | 115 | - 116 | Edward Shtern ― Suggestions for: className, title and wholeWord options. 117 | 118 | 119 | ### License 120 | 121 | This plugin is licensed under the 122 | [new BSD license](http://www.bramstein.com/licenses/BSD.txt). To summarize the license; the 123 | plugin is completely free for commercial and non-commercial use and 124 | you can do with it whatever you want, except claim it as your own 125 | work. 126 | 127 | -------------------------------------------------------------------------------- /examples/css-or-js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Text Overflow Example 6 | 7 | 8 | 13 | 25 | 26 | 27 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Text Overflow Example 6 | 7 | 8 | 32 | 38 | 39 | 40 |

jQuery Text Overflow examples

41 |

This first example shows the default settings at work. It just calls the textOverflow method on the list elements without any parameters. Note that container elements and inline elements are properly conserved and lines are truncated after words (i.e. trailing spaces are removed.)

42 | 43 |
44 | $('#default li').textOverflow();
45 | 			
46 |
47 | 55 |

The second example shows how custom strings can be used for clipping. Note that the string contains dynamically generated HTML code. 56 | 57 |

58 | $('#custom li').each(function (index) {
59 | 	$(this).textOverflow({
60 | 		str: '... <a href="#' + index + '">read more</a>'
61 | 	});
62 | });
63 | 			
64 | 65 | 70 |

The next example uses the autoUpdate parameter to the textOverflow method to automatically update the clipping when the parent container is resized. You can try this out by pressing the "Resize parent" button (code for this is not shown.)

71 | 72 |
73 | $('#dynamic li').textOverflow({
74 | 	autoUpdate: true
75 | });
76 | 			
77 |
78 |

It passes null as the first parameter, indicating we wish to use the default value for clipping (the ellipsis character.)

79 | 80 | 85 | 86 |

More information & details

87 |

More details and API documentation can be found on the jQuery text overflow plugin website.

88 | 89 | 90 | -------------------------------------------------------------------------------- /lib/jquery.text-overflow.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve jQuery Text Overflow v0.7.4 3 | * 4 | * Licensed under the new BSD License. 5 | * Copyright 2009-2011, Bram Stein 6 | * All rights reserved. 7 | */ 8 | /*global jQuery, document, setInterval*/ 9 | (function ($) { 10 | var style = document.documentElement.style, 11 | hasTextOverflow = ('textOverflow' in style || 'OTextOverflow' in style), 12 | 13 | rtrim = function (str) { 14 | return str.replace(/\s+$/g, ''); 15 | }, 16 | 17 | propertyName = document.createTextNode('').textContent ? 'textContent' : 'data', 18 | 19 | domSplit = function (root, maxIndex, options) { 20 | var index = 0, result = [], 21 | domSplitAux = function (nodes) { 22 | var i = 0, tmp, clipIndex = 0; 23 | 24 | if (index > maxIndex) { 25 | return; 26 | } 27 | 28 | for (i = 0; i < nodes.length; i += 1) { 29 | if (nodes[i].nodeType === 1) { 30 | tmp = nodes[i].cloneNode(false); 31 | result[result.length - 1].appendChild(tmp); 32 | result.push(tmp); 33 | domSplitAux(nodes[i].childNodes); 34 | result.pop(); 35 | } else if (nodes[i].nodeType === 3) { 36 | if (index + nodes[i].length < maxIndex) { 37 | result[result.length - 1].appendChild(nodes[i].cloneNode(false)); 38 | } else { 39 | tmp = nodes[i].cloneNode(false); 40 | clipIndex = maxIndex - index; 41 | if (options.wholeWord) { 42 | clipIndex = Math.min(maxIndex - index, tmp.textContent.substring(0, maxIndex - index).lastIndexOf(' ')); 43 | } 44 | tmp[propertyName] = options.trim ? rtrim(tmp[propertyName].substring(0, clipIndex)) : tmp[propertyName].substring(0, clipIndex); 45 | result[result.length - 1].appendChild(tmp); 46 | } 47 | index += nodes[i].length; 48 | } else { 49 | result.appendChild(nodes[i].cloneNode(false)); 50 | } 51 | } 52 | }; 53 | result.push(root.cloneNode(false)); 54 | domSplitAux(root.childNodes); 55 | return $(result.pop().childNodes); 56 | }; 57 | 58 | $.extend($.fn, { 59 | textOverflow: function (options) { 60 | var o = $.extend({ 61 | str: '…', 62 | autoUpdate: false, 63 | trim: true, 64 | title: false, 65 | className: undefined, 66 | wholeWord: false 67 | }, options); 68 | 69 | if (!hasTextOverflow) { 70 | return this.each(function () { 71 | var element = $(this), 72 | 73 | // the clone element we modify to measure the width 74 | clone = element.clone(), 75 | 76 | // we save a copy so we can restore it if necessary 77 | originalElement = element.clone(), 78 | originalText = element.text(), 79 | originalWidth = element.width(), 80 | low = 0, mid = 0, 81 | high = originalText.length, 82 | reflow = function () { 83 | if (originalWidth !== element.width()) { 84 | element.replaceWith(originalElement); 85 | element = originalElement; 86 | originalElement = element.clone(); 87 | element.textOverflow($.extend({}, o, { autoUpdate: false})); 88 | originalWidth = element.width(); 89 | } 90 | }; 91 | 92 | element.after(clone.hide().css({ 93 | 'position': 'absolute', 94 | 'width': 'auto', 95 | 'overflow': 'visible', 96 | 'max-width': 'inherit', 97 | 'min-width': 'inherit' 98 | })); 99 | 100 | if (clone.width() > originalWidth) { 101 | while (low < high) { 102 | mid = Math.floor(low + ((high - low) / 2)); 103 | clone.empty().append(domSplit(originalElement.get(0), mid, o)).append(o.str); 104 | if (clone.width() < originalWidth) { 105 | low = mid + 1; 106 | } else { 107 | high = mid; 108 | } 109 | } 110 | 111 | if (low < originalText.length) { 112 | element.empty().append(domSplit(originalElement.get(0), low - 1, o)).append(o.str); 113 | if (o.title) { 114 | element.attr('title', originalText); 115 | } 116 | if (o.className) { 117 | element.addClass(o.className); 118 | } 119 | } 120 | } 121 | clone.remove(); 122 | 123 | if (o.autoUpdate) { 124 | setInterval(reflow, 200); 125 | } 126 | }); 127 | } else { 128 | return this; 129 | } 130 | } 131 | }); 132 | }(jQuery)); 133 | -------------------------------------------------------------------------------- /todo: -------------------------------------------------------------------------------- 1 | http://www.w3.org/TR/2002/WD-css3-text-20021024/#text-overflow-props 2 | 3 | Correct: 4 | 1) find all descendant block elements of the text-overflow element (element.find('*').filter(function () {}); 5 | 2) filter out the ones that have their own flow (or are laid out statically, relative and have no width or height) 6 | 3) perform text overflow on those. 7 | --------------------------------------------------------------------------------