I found a new jQuery plugin bigTarget.js via http://www.noupe.com/css/using-javascript-to-fix-12-common-browser-headaches.html. I thought the technique would work great to improve my ListView's where I am using the truncate plugin that I found and initially posted about here Truncate Lengthy Text for Cleaner Display in ASP.NET ListView Using jQuery.
Essentially, instead of just presenting a more or less link for the user to click, the user can click anywhere in a cell to expand or contract the text.
Demo | Download (ASP.NET 3.5)
End Product:
Instead of using the bigTarget.js plugin, I adapted the technique into the truncate plugin instead. I removed the following lines:
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;
});
and replaced them with:
full_node.parent().click(function() {
truncated_node.toggle();
full_node.toggle();
return false;
})
.hover(function() {
$(this).addClass(opts.hoverClass);
}, function() {
$(this).removeClass(opts.hoverClass);
});
I also added the hoverClass to the options.
Full Plugin Code:
// HTML Truncator for jQuery
// by Henrik Nyh <http://henrik.nyh.se> 2008-02-28.
// Free to modify and redistribute with credit.
// Modified By Bill Beckelman <http://beckelman.net> 2008-10-13 to include bigTarget technique
// found at <http://newism.com.au/blog/post/58/bigtarget-js-increasing-the-size-of-clickable-targets/>
(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);
truncated_node.insertAfter(full_node);
// This is an ugly approximation for getting the last block tag:
// we just pick the last <p> or else the container itself.
truncated_node.find('p:last').add(truncated_node).eq(0).append(' <a href="#show more content">' + opts.more + '</a>');
full_node.hide();
full_node.find('p:last').add(full_node).eq(0).append(' <a href="#show less content">' + opts.less + '</a>');
full_node.parent().click(function() {
truncated_node.toggle();
full_node.toggle();
return false;
})
.hover(function() {
$(this).addClass(opts.hoverClass);
}, function() {
$(this).removeClass(opts.hoverClass);
});
});
}
// Note that the "more" link and its wrapping counts towards the max length:
// so "more" and a max length of 10 might give "123 (more)"
$.fn.truncate.defaults = {
max_length: 100,
more: ' more...',
less: 'less',
hoverClass: 'hover'
};
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().html("");
node.contents().each(function() {
var remaining_length = max_length - new_node.text().length;
if (remaining_length == 0) return;
new_node.append(recursivelyTruncate(this, remaining_length));
});
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, ' ');
}
})(jQuery);
Be sure to checkout the demo. I undoubtedly missed something. Please let me know how this can be improved in the comments.