/* * jQuery.fn.autoResize 1.1 * -- * https://github.com/jamespadolsey/jQuery.fn.autoResize * -- * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://sam.zoy.org/wtfpl/COPYING for more details. */ (function($){ var defaults = autoResize.defaults = { onResize: function(){}, animate: { duration: 200, complete: function(){} }, extraSpace: 0, minHeight: 1, maxHeight: 500, minWidth: 'original', maxWidth: 500 }; autoResize.cloneCSSProperties = [ 'lineHeight', 'textDecoration', 'letterSpacing', 'fontSize', 'fontFamily', 'fontStyle', 'fontWeight', 'textTransform', 'textAlign', 'direction', 'wordSpacing', 'fontSizeAdjust', 'padding' ]; autoResize.cloneCSSValues = { position: 'absolute', top: -9999, left: -9999, opacity: 0, overflow: 'hidden' }; autoResize.resizableFilterSelector = 'textarea,input:not(input[type]),input[type=text],input[type=password]'; autoResize.AutoResizer = AutoResizer; $.fn.autoResize = autoResize; function autoResize(config) { this.filter(autoResize.resizableFilterSelector).each(function(){ new AutoResizer( $(this), config ); }); return this; } function AutoResizer(el, config) { config = this.config = $.extend(autoResize.defaults, config); this.el = el; this.nodeName = el[0].nodeName.toLowerCase(); this.originalHeight = el.height(); this.previousScrollTop = null; this.value = el.val(); if (config.maxWidth === 'original') config.maxWidth = el.width(); if (config.minWidth === 'original') config.minWidth = el.width(); if (config.maxHeight === 'original') config.maxHeight = el.height(); if (config.minHeight === 'original') config.minHeight = el.height(); if (this.nodeName === 'textarea') { el.css({ resize: 'none', overflowY: 'hidden' }); } el.data('AutoResizer', this); this.createClone(); this.injectClone(); this.bind(); } AutoResizer.prototype = { bind: function() { var check = $.proxy(function(){ this.check(); return true; }, this); this.unbind(); this.el .bind('keyup.autoResize', check) //.bind('keydown.autoResize', check) .bind('change.autoResize', check); this.check(null, true); }, unbind: function() { this.el.unbind('.autoResize'); }, createClone: function() { var el = this.el, clone; if (this.nodeName === 'textarea') { clone = el.clone().height('auto'); } else { clone = $('').width('auto').css({ whiteSpace: 'nowrap' }); } this.clone = clone; $.each(autoResize.cloneCSSProperties, function(i, p){ clone[0].style[p] = el.css(p); }); clone .removeAttr('name') .removeAttr('id') .attr('tabIndex', -1) .css(autoResize.cloneCSSValues); }, check: function(e, immediate) { var config = this.config, clone = this.clone, el = this.el, value = el.val(); if (this.nodeName === 'input') { clone.text(value); // Calculate new width + whether to change var cloneWidth = clone.width(), newWidth = (cloneWidth + config.extraSpace) >= config.minWidth ? cloneWidth + config.extraSpace : config.minWidth, currentWidth = el.width(); newWidth = Math.min(newWidth, config.maxWidth); if ( (newWidth < currentWidth && newWidth >= config.minWidth) || (newWidth >= config.minWidth && newWidth <= config.maxWidth) ) { config.onResize.call(el); el.scrollLeft(0); config.animate && !immediate ? el.stop(1,1).animate({ width: newWidth }, config.animate) : el.width(newWidth); } return; } // TEXTAREA clone.height(0).val(value).scrollTop(10000); var scrollTop = clone[0].scrollTop + config.extraSpace; // Don't do anything if scrollTop hasen't changed: if (this.previousScrollTop === scrollTop) { return; } this.previousScrollTop = scrollTop; if (scrollTop >= config.maxHeight) { el.css('overflowY', ''); return; } el.css('overflowY', 'hidden'); if (scrollTop < config.minHeight) { scrollTop = config.minHeight; } config.onResize.call(el); // Either animate or directly apply height: config.animate && !immediate ? el.stop(1,1).animate({ height: scrollTop }, config.animate) : el.height(scrollTop); }, destroy: function() { this.unbind(); this.el.removeData('AutoResizer'); this.clone.remove(); delete this.el; delete this.clone; }, injectClone: function() { ( autoResize.cloneContainer || (autoResize.cloneContainer = $('').appendTo('body')) ).append(this.clone); } }; })(jQuery);