Link to home
Start Free TrialLog in
Avatar of alambres
alambres

asked on

count lines in a textarea

Hi guys !!

it's urgent, so I'm rewarding the maximum amount of points allowed !

I need to count the number of lines a text is taking in a textarea. My first try is splitting the text by the line feed (\n), but it do the work just partially. I mean it just split when there's an explicit line feed (by the user hitting enter) but it does nothing regarding the automatic line feeds, when the text reaches the right margin of the textarea and automatically goes on the next line. Any ideas? Please test it a little before posting, I've already tried several things. Thanx everybody.


alambres
Avatar of archrajan
archrajan

This works for 0, 1 or many lines

<script>
function countLines(){
 txt=document.getElementById('t1').value
 lines=0
 if (txt!=''){
  lines=1
  if (/[\n\r]{2}/.test(txt))
    lines=txt.match(/[\n\r]{2}/g).length
 }
 return lines
}
</script>

<textarea id="t1" rows="10" cols="25">
line 1
line 2

line 3+blank above
</textarea> </p>

<input type="button" onclick="alert(countLines())">
I haven't tested the links from Archana yet, there might be something there.

Otherwise, my little script below might help.

But: You have to use a fixed font in order make this work. That's why I chose courier.

<html>
<head>
<style type="text/css">
body{
background-color: #FFFFFF;
margin:0px;
}
</style>
<script type="text/javascript">
function countLines(){
    var value = document.forms[0].myArea.value;
    var items = value.split('\n');
    var lines = 0;
    for(var no=0;no<items.length;no++){
        lines += Math.ceil(items[no].length/40);    
    }
    document.getElementById('myDiv').innerHTML = lines;    
}

</script>
</head>

<body>
<form>
<textarea cols="41" rows="35" style="font-family:courier" onkeyup="countLines()" name="myArea"></textarea>
</form>
<div id="myDiv"></div>
</body>
</html>
Avatar of Zvonko
Here my version:


<html>
<head>
<script>
function countLines(theArea){
  var theText = theArea.value.replace((new RegExp(".{"+theArea.cols+"}","g")),"\n").split("\n");
  theArea.form.lineCount.value = theText.length;
}
</script>
</head>
<body>
<form>
<textarea name="myText" onKeyUp="countLines(this)" cols="10" rows="10">
</textarea>
<br>
Lines:
<input type=text name="lineCount" size="2" value="0">
</form>
</body>
</html>


Zvonko,

You make me remember that simple is beautiful!!!

Very, very nice:-)
Thanks :)
true but it does not work, this is my try

<script>
function countLines(){
 txt=document.getElementById('t1').value
 if (txt=='') return 0
 txtArr=txt.split('\n')
 return  txtArr.length
}
</script>

<form>
<textarea id="t1" rows="10" cols="25" onkeyup="this.form.count.value=countLines()">
</textarea></p>
<input name="count" size="4"> Lines
</form>

Well, that only count physical newlines.

You have to count both number of characters and new lines. Maybe Zvonko's code will work by modifying theArea.cols in the function. It seems that there's only room for 9 characters in a 10 col textarea.

Batalf
ASKER CERTIFIED SOLUTION
Avatar of Zvonko
Zvonko
Flag of North Macedonia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of alambres

ASKER

Hey guys !!

Thanx everybody!

Zvonko, really great job ! It works superfine. Just with one exception, that I'm getting crazy on trying to solve. My textarea got a css class with Arial font, which is not width-fixed, so I have a great trouble with the cols attribute. I donno. Any idea?

Thinking in another ways, without changing the stylesheet, I wonder if there's a way to get the font height, or line height?
No, there's no easy Javascript  method to measure the width of the letters.

The only way I can think of is if you open each letter in Photoshop, measure the width pixel by pixel and create a javascript array out of those widths. But as you probably understand, it would be unreliable and a nightmare to work with. Font width could also be different on Windows, Mac and Linux.

Batalf
It works for me:
<html>
<head>
<style>
TEXTAREA {
  font-size: 72px;
}
</style>
<script>
function countLines(theArea){
  var theLines = theArea.value.replace((new RegExp(".{"+theArea.cols+"}","g")),"\n").split("\n");
  if(theLines[theLines.length-1]=="") theLines.length--;
  theArea.form.lineCount.value = theLines.length;
}
</script>
</head>
<body>
<form>
<textarea name="myText" onKeyUp="countLines(this)" cols="10" rows="10">
</textarea>
<br>
Lines:
<input type=text name="lineCount" size="2" value="0">
</form>
</body>
</html>

Post your style definitions to see what the problem is, please.
Uhps, sorry, I just discovered you are talking about proportional (non-fixed-width) font:
<style>
TEXTAREA {
  font-family: Arial;
  font-size: 72px;
}
</style>

I have no idea for that, sorry.

Hi again !

I've found a trick to solve the proportional fonts. I'm posting the code, in case you're interested. Anyway, since Zvonko's solution is very fine for the fixed-width fonts, I'm getting him the points. Thank you all.

Here's the code:

<html>
<head>
<style type="text/css">
.campa {  font-family: Arial,Helvetica, sans-serif; font-size: 10pt; color: #000000; background-color: #FFFFFF;}
</style>
<script type="text/javascript">

function countLines(theArea)
{

//zvonko's : for fixed-width fonts (ex. Courier)
  var theLines = theArea.value.replace((new RegExp(".{"+theArea.cols+"}","g")),"\n").split("\n");
  if(theLines[theLines.length-1]=="") theLines.length--;
  theArea.form.lineCount.value = theLines.length;
  theArea.form.charCount.value = theArea.value.length;
}

function countLines2(theArea)
{
//alambres' : for non fixed-width fonts (ex. Arial)
      var TALC = document.getElementById('TA_lineCounter');
      TALC.style.display = 'block';
      TALC.style.width = theArea.offsetWidth + 'px';
      TALC.innerHTML = "a";
      var lineH = TALC.offsetHeight - (parseInt(TALC.style.borderWidth)*2);
      var str = theArea.value.replace(/\n/g,"<br/>");
      
      var bGoOn;
      var aw = theArea.value.split();
      for (var i=0;i<aw.length;i++)
      {
            TALC.innerHTML = aw[i];
            if (TALC.offsetWidth > parseInt(TALC.style.width))
            {
                  bGoOn = true;
                  for (var j=aw[i].length-1;j>0 && bGoOn;j--)
                  {
                        TALC.innerHTML = aw[i].substring(0,j);
                        bGoOn = TALC.offsetWidth > parseInt(TALC.style.width);
                        if (!bGoOn)
                        {
                              str = str.replace(aw[i],aw[i].substring(0,j)+"<br/>"+aw[i].substring(j,aw[i].length));
                              TALC.innerHTML = aw[i].substring(j,j.length);
                              if (TALC.offsetWidth > parseInt(TALC.style.width))
                              {
                                    bGoOn = true;
                                    aw[i] = aw[i].substring(j,aw[i].length);
                                    j = aw[i].length-1;
                              }
                        }
                  }
            }
      }
      
      TALC.innerHTML = str;
      var lines = (TALC.offsetHeight - (parseInt(TALC.style.borderWidth)*2)) / lineH;
      
      theArea.form.charCount.value = theArea.value.length;
      theArea.form.lineCount.value = lines;
 
      TALC.style.display = 'none';

}

</script>
</head>
<body>
<form>
<!-- <textarea name="myText" onKeyUp="countLines(this)" cols="10" rows="10"> -->
<textarea name="myText" onKeyUp="countLines2(this)" rows="10" cols="30" class="campa">
</textarea>

<br/>

<span id="TA_lineCounter" class="campa" style="display:none;overflow-y:scroll;border:3px inset;">
</span>

<br/>
Chars:
<input type=text name="charCount" size="2" value="0"/><br/>
Lines:
<input type=text name="lineCount" size="2" value="0"/><br/>


</form>
</body>
</html>



 alambres