Reputation: 2824
I have found various plugins for auto-growing a textarea, but not input text fields. Does anybody know if any exist?
Upvotes: 68
Views: 36459
Reputation: 6712
I created a plugin called input-autogrow
to solve this problem for my own projects. This plugin was originally based off of James answer but has been improved in many ways.
https://github.com/westonganger/input-autogrow
input-autogrow
is a plugin for autogrowing inputs. This plugin is different from others because most usually target textarea tags, this library is instead targeted at input tags. Requires a DOM library such as jQuery, Zepto, or any that supports $.fn plugins.
Here are some usage examples.
/* Makes elements readonly if they already have the readonly attribute */
$('input.autogrow').inputAutogrow();
/* Manually trigger update */
$('input.autogrow').trigger('autogrow');
/* or */
$('input.autogrow').trigger('change');
/* Custom Options */
$('input.autogrow').inputAutogrow({maxWidth: 500, minWidth: 25, trailingSpace: 10});
/* Remove autogrow from input */
$('input.autogrow').inputAutogrow('destroy');
Upvotes: 0
Reputation: 111910
Here's a plugin that'll do what you're after:
EDIT: I've fixed the plugin as per Mathias' comment. :)
See a demo here: http://jsfiddle.net/rRHzY
The plugin:
(function($){
$.fn.autoGrowInput = function(o) {
o = $.extend({
maxWidth: 1000,
minWidth: 0,
comfortZone: 70
}, o);
this.filter('input:text').each(function(){
var minWidth = o.minWidth || $(this).width(),
val = '',
input = $(this),
testSubject = $('<tester/>').css({
position: 'absolute',
top: -9999,
left: -9999,
width: 'auto',
fontSize: input.css('fontSize'),
fontFamily: input.css('fontFamily'),
fontWeight: input.css('fontWeight'),
letterSpacing: input.css('letterSpacing'),
whiteSpace: 'nowrap'
}),
check = function() {
if (val === (val = input.val())) {return;}
// Enter new content into testSubject
var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>');
testSubject.html(escaped);
// Calculate new width + whether to change
var testerWidth = testSubject.width(),
newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth,
currentWidth = input.width(),
isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)
|| (newWidth > minWidth && newWidth < o.maxWidth);
// Animate width
if (isValidWidthChange) {
input.width(newWidth);
}
};
testSubject.insertAfter(input);
$(this).bind('keyup keydown blur update', check);
});
return this;
};
})(jQuery);
Upvotes: 146
Reputation: 1309
I have create a plugin for the input of type text, that recreates this behaviour. It has some other unique features. You can see an example and view the documentation of the plugin. @james answer has some problems with pasting large text into the input. To fix it, I have made some modifications to his code. Here is a demo, for this example.
(function($){
$.fn.autoGrowInput = function(o) {
o = $.extend({
maxWidth: 200,
minWidth: 1,
comfortZone: 1,
width: 1
}, o);
this.filter('input:text').each(function(){
var minWidth = o.minWidth || $(this).width(),
maxWidth = o.maxWidth,
val = '',
input = $(this),
testSubject = $('<tester/>').css({
position: 'absolute',
top: -9999,
left: -9999,
width: 'auto',
fontSize: input.css('fontSize'),
fontFamily: input.css('fontFamily'),
fontWeight: input.css('fontWeight'),
letterSpacing: input.css('letterSpacing'),
whiteSpace: 'nowrap'
}),
check = function() {
if (val === (val = input.val())) {return;}
// Enter new content into testSubject
var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>');
testSubject.html(escaped);
// Calculate new width + whether to change
var testerWidth = testSubject.width(),
newWidth = testerWidth + o.comfortZone,
currentWidth = input.width();
if (testerWidth < minWidth) {
newWidth = minWidth;
} else if (testerWidth > maxWidth) {
newWidth = maxWidth;
}
input.width(newWidth + o.comfortZone);
};
testSubject.insertAfter(input);
$(this).bind('input', check);
});
return this;
};
})(jQuery);
Upvotes: 2
Reputation: 887
Awsome plugin James ! Thanks. I did add the check suggestion in the end by JP though very effective .
Also I added a some changes on my part. I wanted to set the size for the input to the maximum size if the changed width exceeded the maxWidth so I added :
else if (widthexceeds){
input.width(o.maxWidth);
}
below the if check for isValidWidthChange where widthexceeds = newWidth > o.maxWidth
Upvotes: 0
Reputation: 5979
I have a jQuery plugin on GitHub: https://github.com/MartinF/jQuery.Autosize.Input
It uses the same approach as James answer but have some of the changes mentioned in the comments.
You can see an live example here: http://jsfiddle.net/mJMpw/6/
Example:
<input type="text" value="" placeholder="Autosize" data-autosize-input='{ "space": 40 }' />
input[type="data-autosize-input"] {
width: 90px;
min-width: 90px;
max-width: 300px;
transition: width 0.25s;
}
You just use css to set min/max-width and use a transition on the width if you want a nice effect.
You can specify the space / distance to the end as the value in json notation for the data-autosize-input attribute on the input element.
Of course you can also just initialize it using jQuery
$("selector").autosizeInput();
Upvotes: 9
Reputation: 8577
Funny enough in IE overflow: visible is taken very seriously. You can achieve this effect by applying overflow: visible on your input elements. Not sure if any similar CSS tricks exist for modern browsers.
Upvotes: 0
Reputation: 622
I'd also replaced
$(this).bind('keyup keydown blur update', check)
to
$(this).bind('keyup blur update', check).bind('keydown', function() {
setTimeout(check);
});
in order to get the field resized right after it was re-rendered by browser. It would rid the field from some chattering.
Upvotes: 2
Reputation: 548
just wanted to share a small improvement to James's great plugin. Add this code to the CSS declaration for the tester element to account for text-indent:
textIndent: 0
Without it, in some situations the tester element may inadvertently inherit the text-indent from elsewhere, thus throwing off the size of the input.
Like JP, I also wanted to resize the input to the correct size from the beginning, which I did just slightly differently, by chaining "trigger('keyup')" to the autoGrowInput method call, e.g.:
$('#contact_form').autoGrowInput({comfortZone: 7, minWidth: 10, maxWidth: 200}).trigger('keyup');
As a side note, I signed up to this site purely to comment on James's solution and I'm a bit annoyed to find that I can't because I don't have enough reputation points to start with. Sorry if I've missed something, but that seems to mean that I have to post this is a comment on the main question rather than more appropriately on James's solution.
Upvotes: 4
Reputation: 1027
Good plugin, thank you! I changed two things that seemed to work better in my project though.
Hope this helps.
Upvotes: 7
Reputation: 7215
If you want the textbox to grow when the string within it extends past its width, maybe something like this would work for you... It detects the size attribute of the textbox. If the length of the string goes over that attribute, it extends the textbox to the length of the string on keyup.
In the below script, "#test" is a textbox ID.
<script language="javascript" type="text/javascript">
$(document).ready(function(){
$("#test").keyup(function(){
if($("#test").attr("size") < $("#test").val().length){
size = $("#test").val().length;
$("#test").attr("size",size);
}
})
});
</script>
Upvotes: 0