assets/js/jquery.elastic.source.js
/**
* @name Elastic
* @descripton Elastic is Jquery plugin that grow and shrink your textareas automaticliy
* @version 1.6.5
* @requires Jquery 1.2.6+
*
* @author Jan Jarfalk
* @author-email jan.jarfalk@unwrongest.com
* @author-website http://www.unwrongest.com
*
* @licens MIT License - http://www.opensource.org/licenses/mit-license.php
*/
(function (jQuery) {
jQuery.fn.extend({
elastic: function () {
// We will create a div clone of the textarea
// by copying these attributes from the textarea to the div.
var mimics = [
'paddingTop',
'paddingRight',
'paddingBottom',
'paddingLeft',
'fontSize',
'lineHeight',
'fontFamily',
'width',
'fontWeight'];
return this.each(function () {
// Elastic only works on textareas
if (this.type != 'textarea') {
return false;
}
var $textarea = jQuery(this),
$twin = jQuery('<div />').css({'position': 'absolute', 'display': 'none', 'word-wrap': 'break-word'}),
lineHeight = parseInt($textarea.css('line-height'), 10) || parseInt($textarea.css('font-size'), '10'),
minheight = parseInt($textarea.css('height'), 10) || lineHeight * 3,
maxheight = parseInt($textarea.css('max-height'), 10) || Number.MAX_VALUE,
goalheight = 0,
i = 0;
// Opera returns max-height of -1 if not set
if (maxheight < 0) {
maxheight = Number.MAX_VALUE;
}
// Append the twin to the DOM
// We are going to meassure the height of this, not the textarea.
$twin.appendTo($textarea.parent());
// Copy the essential styles (mimics) from the textarea to the twin
var i = mimics.length;
while (i--) {
$twin.css(mimics[i].toString(), $textarea.css(mimics[i].toString()));
}
// Sets a given height and overflow state on the textarea
function setHeightAndOverflow(height, overflow) {
curratedHeight = Math.floor(parseInt(height, 10));
if ($textarea.height() != curratedHeight) {
$textarea.css({'height': curratedHeight + 'px', 'overflow': overflow});
}
}
// This function will update the height of the textarea if necessary
function update() {
// Get curated content from the textarea.
var textareaContent = $textarea.val().replace(/&/g, '&').replace(/ /g, ' ').replace(/<|>/g, '>').replace(/\n/g, '<br />');
// Compare curated content with curated twin.
var twinContent = $twin.html().replace(/<br>/ig, '<br />');
if (textareaContent + ' ' != twinContent) {
// Add an extra white space so new rows are added when you are at the end of a row.
$twin.html(textareaContent + ' ');
// Change textarea height if twin plus the height of one line differs more than 3 pixel from textarea height
if (Math.abs($twin.height() + lineHeight - $textarea.height()) > 3) {
var goalheight = $twin.height() + lineHeight;
if (goalheight >= maxheight) {
setHeightAndOverflow(maxheight, 'auto');
} else if (goalheight <= minheight) {
setHeightAndOverflow(minheight, 'hidden');
} else {
setHeightAndOverflow(goalheight, 'hidden');
}
}
}
}
// Hide scrollbars
$textarea.css({'overflow': 'hidden'});
// Update textarea size on keyup, change, cut and paste
$textarea.bind('keyup change cut paste', function () {
update();
});
// Compact textarea on blur
// Lets animate this....
$textarea.bind('blur', function () {
if ($twin.height() < maxheight) {
if ($twin.height() > minheight) {
$textarea.height($twin.height());
} else {
$textarea.height(minheight);
}
}
});
// And this line is to catch the browser paste event
$textarea.on('input paste', function (e) {
setTimeout(update, 250);
});
// Run update once when elastic is initialized
update();
});
}
});
})(jQuery);