Skip to content

Instantly share code, notes, and snippets.

@malef
Created May 29, 2012 20:00
Show Gist options
  • Save malef/2830365 to your computer and use it in GitHub Desktop.
Save malef/2830365 to your computer and use it in GitHub Desktop.
Simple ellipsis plugin for jQuery.
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="jquery.ellipsis.js"></script>
<script src="example.js"></script>
<style>
body {
font-family: Ubuntu, Calibri, Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 20px;
}
.ellipsis-wrapper {
display: inline-block;
float: left;
width: 250px;
height: 60px;
overflow: hidden;
background-color: #f0f0f0;
border: 2px solid #e0e0e0;
margin: 10px 10px;
padding: 10px;
}
</style>
</head>
<body>
<div class="ellipsis-wrapper"><span class="ellipsis-inner"><span>Lorem ipsum dolor</span><!-- Does this comment bother anyone? --><span>sit amet,</span> <strong><span>consectetur</span> <span>adipiscing elit</span><span></strong><span>.</span> <span>Vivamus</span> <span>massa</span> <span>ante,</span> <em><span>mollis</span> <span>at</span> <span>vulputate</span> <span>in,</span> <span>consequat</span> <span>auctor</span> <span>velit</span></em><span>.</span></div>
<div class="ellipsis-wrapper"><span class="ellipsis-inner">Donec sagittis, nibh nec consequat mollis, sapien mauris suscipit eros, id commodo leo dui eu ipsum. Curabitur sed consectetur augue.<br />Integer quis gravida odio.<br />Duis nec magna egestas lacus malesuada aliquam tempus et turpis.<br />Ut sed nibh quis mauris feugiat placerat. Nunc ipsum odio, accumsan ut rutrum eu, tincidunt in nunc. Mauris tristique, libero eget dignissim scelerisque, urna turpis lacinia ipsum, at condimentum turpis orci quis enim. Praesent vitae augue turpis. Aenean metus felis, luctus et condimentum nec, interdum quis nisi. Donec quis nisl nisi, non laoreet augue.</span></div>
<div class="ellipsis-wrapper"><span class="ellipsis-inner">Curabitur vulputate nunc ipsum, sed <a href="http://example.com/">scelerisque massa</a>. Proin a augue lectus.</span></div>
<div class="ellipsis-wrapper"><span class="ellipsis-inner">Fusce purus sem, dictum tempus auctor non, lacinia vel leo. <em>Donec iaculis eleifend nibh, eget feugiat leo molestie vel.</em> <strong>Aliquam luctus mattis orci a rhoncus. Ut enim quam, dignissim vitae elementum quis, ultricies a sem.</strong></span></div>
<div class="ellipsis-wrapper"><span class="ellipsis-inner">Aliquam commodo scelerisque augue, quis viverra lacus eleifend id. <a href="http://example.com/"><u>Aliquam <strong>fringilla augue vel bibendum</strong></u> tempor, elit felis accumsan libero, lobortis consequat arcu sapien <strong>vitae nibh</strong>.</a> Maecenas sodales ullamcorper lorem, quis ullamcorper mauris elementum eget. Aliquam auctor mattis ullamcorper. In hac habitasse platea dictumst. Aliquam erat volutpat. Sed nibh arcu, dignissim vel luctus et, molestie tempus urna. Aenean eget neque lorem, non hendrerit turpis.</span></div>
</body>
</html>
(function ($) {
$(function () {
$('.ellipsis-inner').ellipsis({
ellipsisText: '...',
fitCallback: function (element) {
return element.height() <= 60;
},
removeBrTags: true
});
});
}(jQuery));
/**
* Ellipsis jQuery plugin
* (C) 2012 Mariusz Bąk
*/
(function ($) {
"use strict";
$.fn.ellipsis = function(options) {
var NODE_TYPE_TEXT = 3,
defaults = {
ellipsisText: '...',
removeBrTags: false
};
/**
* Remove BR tags from node before applying ellipsis.
*
* @param parentNode Current parent node as DOM element.
*/
function removeBrTags(parentNode) {
var nodes;
if (parentNode.nodeType === 3) {
return;
}
nodes = parentNode.childNodes;
$.each(nodes, function (index, node) {
if (node.tagName === 'BR') {
parentNode.insertBefore(document.createTextNode(' '), node);
parentNode.removeChild(node);
}
else {
removeBrTags(node);
}
});
}
function fitText(text, pos) {
return text.substr(0, pos).replace(/\.?\s*$/, '');
}
/**
* Try to adjust the height of the wrapper by truncating text node's content.
* Uses bisection iteratively.
*
* @param textNode Text node to be truncated as DOM element.
* @param fitCallback Should return true if ellipsisized element fits.
* @return True on success, false otherwise.
*/
function fitTextNode(textNode, fitCallback) {
var originalText = textNode.data,
fittedText,
i = 0, j = originalText.length - 1, k, kp, l;
while (true) {
kp = k;
k = Math.floor((i + j) / 2);
fittedText = fitText(originalText, k);
k = fittedText.length - 1;
if (k === kp) {
break;
}
fittedText += options.ellipsisText;
textNode.data = fittedText;
if (!fitCallback()) {
j = k;
}
else {
i = l = k;
}
if (j - i < 1) {
break;
}
}
if (l === undefined) {
textNode.data = originalText;
return false;
}
textNode.data = fitText(originalText, l) + options.ellipsisText;
return true;
}
/**
* Try to adjust the height of the wrapper by removing its children nodes.
*
* @param parentNode Current parent node as DOM element.
* @param fitCallback Should return true if ellipsisized element fits.
* @param outmostNode Is this the outmost node (ie. wrapper).
* @return True on success, false otherwise.
*/
function fitNodes(parentNode, fitCallback, outmostNode) {
var nodes = parentNode.childNodes,
lastNode,
i;
// If height is equal or lower than the limit then nothing has to be done.
if (fitCallback()) {
return true;
}
// If this is the outmost node then ellipsis should be appended.
if (outmostNode === undefined) {
outmostNode = true;
}
// If this is text node then try to fit its text.
if (parentNode.nodeType === NODE_TYPE_TEXT) {
return fitTextNode(parentNode, fitCallback);
}
// If there are no children nodes that could be removed and the height is
// still greater than desired then we cannot do anything.
if (nodes.length === 0) {
return false;
}
// Otherwise to remove one node at a time.
// Skip final ellipsis node if in outermost node.
i = nodes.length - 1;
do {
lastNode = nodes[i];
parentNode.removeChild(lastNode);
i -= 1;
} while (i >= 0 && !fitCallback());
// Restore last node as we will try to adjust it by recursively calling this
// function for it. Differs for outermost node.
parentNode.appendChild(lastNode);
// If we did not succeed in applying this function recursively for this node's
// children we need to remove last node again as it cannot be fitted in.
// we can return.
if (!fitNodes(lastNode, fitCallback, false)) {
if (lastNode.childNodes.length < 2) {
parentNode.removeChild(lastNode);
}
return false;
}
return true;
}
options = $.extend(defaults, options);
return this.each(function() {
var element = $(this), fitCallbackCurried;
element.attr('ellipsis-html', element.html());
fitCallbackCurried = function () {
return options.fitCallback(element);
};
if (options.removeBrTags) {
removeBrTags(element[0]);
}
fitNodes(element[0], fitCallbackCurried);
});
};
}(jQuery));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment