<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
article, aside, figure, footer, header, hgroup,
menu, nav, section { display: block; }
</style>
<script>
function MinMod(val,adjust){
if(val<=adjust) return adjust; //never smaller than adjust
return val - val % adjust+adjust;
}
/*
* Copyright 2006 by Scott Tabar
* Usage is granted as long as this credit remains in place.
* If used in a production/commerical product, then please drop
* me a line at http://scott-tabar-safari.blogspot.com
*/
function updateTextareaHeight(obj)
{
var pageGrown = 4; //it growns in 4 new lines wen needed
if ( obj == null ) {
return false;
}
// NOTE: This is using regular expressions to count spaces and linefeeds
var objText = obj.value;
var linefeedsArray = objText.match(/[\n\r]/g);
var linefeeds = ( linefeedsArray == null ? 0 : linefeedsArray.length);
var extraRows = Math.round( objText.length / obj.cols );
var newRows = linefeeds + extraRows;
if ( newRows != obj.rows ) {
obj.rows= MinMod(newRows,pageGrown);
}
}
</script>
</head>
<body>
<p id="hello">Hello World</p>
<textarea cols="40" rows="4" onkeyup="updateTextareaHeight(this);"
id="ta01">
This example combines all of the three code fragments listed above. To reset the example, just reload the page and start anew.
NOTE: Sorry... This blog will not support the use of the script tag so I can not in-line an example. So until I can find an alternative way of presenting it, you can just copy and paste the following into a new text document and open with your browser of choice.
If you done any playing around with the example above, you will be quick to find that it does not work too well. The concept may work great, but trying to guess what the user has typed in and how the browser is displaying the information is yet another thing altogether. The reason why this is so difficult, is that the TEXTAREA object does not report the actualRows that the text actually occupies. if it did, then this task would be quite simple.
Why is it so difficult to predict how many rows of text there will be? The answer lies in the complexity that is given by modern browsers: you can configure or change just about any aspect of how the TEXTAREA is displayed or how the font is rendered. You no longer are limited to just the plain font that the browser defaults to, but you can specify a specific font (and numerous backups if that one does not exist on the client's computer), font size, the font weight, kerning, tracking, horizontal and vertical spacing, font stretching, margins, and etc... Matter of fact, you can even write a JavaScript function that can take one character at a time and perform progressive or random changes so that a paragraph could contain a rainbow of colors, or each character could be a different size and font! So to put it mildly, the sky is the limit on how we can present the text in a TEXTAREA. Don't forget word wrapping in the TEXTAREA for that may be out of our control (aside from hinting that can be performed).
In the following example, I have added a few more matrices to try and better tune the control of how the TEXTAREA is sized. There are a few areas that I have tried to quantify to see if better control can be attainable. Next is a list of these measures and how they are "supposed" to help! ;-)
1. fontFamilyAdj - This is a very simplistic implementation. It assumes that the Courier font is the only mono-spaced font you will be using, and all other fonts will be proportionally spaced. This does fit our example so keep it in mind if you need to expand upon it. It assumes that for a monospaced font, that the weight should be greater than 1.0 for less characters can fit on a line in a TEXTAREA compared to a proportionally spaced font. For example, enter all lowercase i's. Conversely though, try entering all uppercase W's too. The point being, on average, more characters will fit per line with proportionally spaced characters.
2. linfeeds - Since we are using RegularExpressions to count the linefeeds and also the spaces and large words, there exists the strong chance that none exists, and as such a null will be returned. So in the cases were we are needing to count the elements of the result array to get our numbers, there is used an intermediate variable to hold such a value. This prevents the need to perform the Regular Expression twice: first to see if there are any results, second to get the count of the results. Anyway for linefeeds, we are only counting newlines and carriage returns. We are not interested in vertical tabs, form feeds, or others.
3. spaces - Counting the number of spaces can give us the average word size. We can also use the spaces and linefeeds when the density get very low to improve the accuracy, but in this example, it is not implemented as such (ie... low density conditions with a high ratio of linefeeds + spaces implies that there is really nothing to the document except for the linefeeds so using just the linefeeds may be the most accurate result).
4. avgWordSize - This really is not being used in the example below. Perhaps in combination with largeWordSize and adjColumns you can find an equation that would estimate the amount amount of white space that is caused by word wrapping. This could improve the estimation of the number of rows quite considerably.
5. adjColumns - Uses the fontFamilyAdj value to modify the column size to more accurately express how many characters really does fit on one line in a TEXTAREA.
6. largeWordSize - This is the smallest size for a large word, which can cause a large waste of white space if a large word is actually wrapped. This is the factor that tries to keep the TEXTAREA from overflowing if many big words are used.
7. largeWordCount - The number of large words that exist in the document.
8. density - Takes the adjColumns and multiplies it by the number of linefeeds and the extraRows (as calculated up to that point) to arrive at a theoretical number of characters that can fit in the TEXTAREA. It then uses that number as the divisor for the total character count of the text. The density, when very high indicates there are less linefeeds or other conditions involved and that the number of rows can be a few less. When the density appears to fall between .2 and .7, then there tends to be a larger number of linefeeds and/or larger words which can increase the likelihood of word wrapping and as such, more lines are needed to prevent an overflow condition. The value of linefeeds are also backed off a little under these conditions too. But when the density is less than .2, then you will find a high number of linefeeds.
9. newRows - is the combined total of the linefeeds and the final value of extraRows. Only if this value changes will the TEXTAREA.rows be modified.
One thing to note, is that currently, this code is not perfect. It behaves much better for medium to large amounts of text, but if you start typing words it will start resizing it self all over the place. Yes it does need some fine tuning, but the point I was wanting to make is that it is NOT an easy task and that there are many variables involved. The addition of
</textarea>
<script>
{
updateTextareaHeight( document.getElementById( "ta01" ) );
}
</script>
</body>
</html>
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |