Introduction
This is a simple solution for numbering lines in a text in HTML page (i.e., code writing). Since, to my knowledge, there is no HTML element that is offering this possibility by default, I created a small and simple code that perfectly and effectively does the trick, even for very long texts.
It uses 2 textarea
elements, the right one is for writing or pasting text, and the left one is readonly and populated by JavaScript, it shows the lines of the text. The 2 textarea
elements are scroll-synced in the JS code. There is also another element underneath that is showing the current position/selection in the text.
Using the Code
The HTML part is very short, there are 2 textarea
elements, wrapped together in a div
; the textarea
for writing is wrapped together with input
element for showing current position/selection in a span
- this is purely for easier access to these elements from within the JavaScript code.
<body onload="initialize()" onresize="onresize_sub()">
<h1>Line numbering using <textarea></h1>
<div>
<textarea class="rownr" rows="20"
cols="3" value="1" readonly></textarea>
<span>
<textarea class="txt" rows="20"
cols="150" nowrap="nowrap" wrap="off"
autocomplete="off" autocorrect="off"
autocapitalize="off" spellcheck="false"
onclick="selectionchanged(this)"
onkeyup="keyup(this,event)" oninput="input_changed(this)"
onscroll="scroll_changed(this)"></textarea><br/><br/>
<label>Current position:
</label><input id="sel_in" style="border-style:none" readonly>
</span>
</div>
</body>
The CSS is also very simple, some coloring and text alignment:
<style>
.rownr {overflow-y: hidden; background-color: rgb(105,105,105); color: white;
text-align: right; vertical-align:top}
.txt {width: 95%; overflow-x: scroll}
</style>
The main textarea
uses event handlers for:
oninput
(for populating line numbers) onscroll
(for scroll syncing) onclick
and onkeyup
events (for reading current position/selection)
Oninput Event Handler
When some text is entered into the textarea
, function input_changed
is called:
function input_changed(obj_txt)
{
obj_rownr = obj_txt.parentElement.parentElement.getElementsByTagName('textarea')[0];
cntline = count_lines(obj_txt.value);
if(cntline == 0) cntline = 1;
tmp_arr = obj_rownr.value.split('\n');
cntline_old = parseInt(tmp_arr[tmp_arr.length - 1], 10);
if(cntline != cntline_old)
{
obj_rownr.cols = cntline.toString().length;
populate_rownr(obj_rownr, cntline);
scroll_changed(obj_txt);
}
selectionchanged(obj_txt);
}
This function is calling another function count_lines
to count the lines in the text (by splitting text by \n
and counts the elements of the resulting array). Then, if there was indeed a change in the number of lines, rownr textarea
is repopulated.
Onscroll Event Handler
The onscroll event handler ( scroll_changed
) is, basically, reading the scrollTop
attribute of one textarea
, and sets this attribute for the other textarea
. (This function can also work with any 2 scrollable HTML elements.)
function scroll_changed(obj_txt)
{
obj_rownr = obj_txt.parentElement.parentElement.getElementsByTagName('textarea')[0];
scrollsync(obj_txt,obj_rownr);
}
function scrollsync(obj1, obj2)
{
obj2.scrollTop = obj1.scrollTop;
}
Onclick and onkeyup Event Handlers
When the textarea
is clicked, selectionchanged
function is called.
function selectionchanged(obj)
{
var substr = obj.value.substring(0,obj.selectionStart).split('\n');
var row = substr.length;
var col = substr[substr.length-1].length;
var tmpstr = '(' + row.toString() + ',' + col.toString() + ')';
if(obj.selectionStart != obj.selectionEnd)
{
substr = obj.value.substring(obj.selectionStart, obj.selectionEnd).split('\n');
row += substr.length - 1;
col = substr[substr.length-1].length;
tmpstr += ' - (' + row.toString() + ',' + col.toString() + ')';
}
obj.parentElement.getElementsByTagName('input')[0].value = tmpstr;
}
This simple function uses the selectionStart
and selectionEnd
attributes of textarea
objects (also works for some other HTML elements) to calculate the current line and column where the snippet is located.
In order to handle also the arrow keys on the keyboard, plus the Home, End, Page Up and Page Down keys, there is also a handler function for keyUp
event. This function is doing nothing but calling the selectionchanged
function if any of these keys are pressed.
function keyup(obj, e)
{
if(e.keyCode >= 33 && e.keyCode <= 40)
selectionchanged(obj, e.keyCode);
}
History
- 26th July, 2019: Initial version