// HTML Truncator for jQuery// by Henrik Nyh <http://henrik.nyh.se> 2008-02-28.// Free to modify and redistribute with credit. 
(function($) {   var trailing_whitespace = true;   $.fn.truncate = function(options) {     var opts = $.extend({}, $.fn.truncate.defaults, options);        $(this).each(function() {       var content_length = $.trim(squeeze($(this).text())).length;      if (content_length <= opts.max_length)        return;  
// bail early if not overlong       
var actual_max_length = opts.max_length - opts.more.length - 3;  // 3 for " ()"      
var truncated_node = recursivelyTruncate(this, actual_max_length);      var full_node = $(this).hide();       truncated_node.insertAfter(full_node);            findNodeForMore(truncated_node).append(' (<a href="#show more content">'+opts.more+'</a>)');      findNodeForLess(full_node).append(' (<a href="#show less content">'+opts.less+'</a>)');            truncated_node.find('a:last').click(function() {        truncated_node.hide(); full_node.show(); return false;      });      full_node.find('a:last').click(function() {        truncated_node.show(); full_node.hide(); return false;      });     });  }   
// Note that the " (…more)" bit counts towards the max length – so a max  
// length of 10 would truncate "1234567890" to "12 (…more)".  
$.fn.truncate.defaults = {    max_length: 100,    more: '...more',    less: 'less'  };   function recursivelyTruncate(node, max_length) {    return (node.nodeType == 3) ? truncateText(node, max_length) : truncateNode(node, max_length);  }   function truncateNode(node, max_length) {    var node = $(node);    var new_node = node.clone().empty();    var truncatedChild;    node.contents().each(function() {      var remaining_length = max_length - new_node.text().length;      if (remaining_length == 0) return;  
// breaks the loop      
truncatedChild = recursivelyTruncate(this, remaining_length);      
if (truncatedChild) new_node.append(truncatedChild);    });    return new_node;  }   function truncateText(node, max_length) {    var text = squeeze(node.data);    if (trailing_whitespace)  
// remove initial whitespace if last text      
text = text.replace(/^ /, '');  
// node had trailing whitespace.    
trailing_whitespace = !!text.match(/ $/);    var text = text.slice(0, max_length);    
// Ensure HTML entities are encoded    
// http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb    
text = $('<div/>').text(text).html();    return text;  }   
// Collapses a sequence of whitespace into a single space.  
function squeeze(string) {    return string.replace(/\s+/g, ' ');  }    
// Finds the last, innermost block-level element  
function findNodeForMore(node) {    var $node = $(node);    var last_child = $node.children(":last");    
if (!last_child) return node;    var display = last_child.css('display');    if (!display || display=='inline') return $node;    return findNodeForMore(last_child);  };   
// Finds the last child if it's a p; otherwise the parent  
function findNodeForLess(node) {    var $node = $(node);    var last_child = $node.children(":last");    if (last_child && last_child.is('p')) return last_child;    return node;  }; })(jQuery); 