I have seen websites such as Github Gist and copy.sh that have text boxes with line numbers on the left.
It seems that there is a section on the left containing elements with line numbers, and every time you create a new line, an element is added to the left with a new line number, and when you delete a line, the last line number is deleted.
I looked at the javascript, however I cannot understand it. How would I implement such an section (textbox with line numbers)?
Thanks.
P.S I would prefer to avoid Jquery.
I have seen websites such as Github Gist and copy.sh that have text boxes with line numbers on the left.
It seems that there is a section on the left containing elements with line numbers, and every time you create a new line, an element is added to the left with a new line number, and when you delete a line, the last line number is deleted.
I looked at the javascript, however I cannot understand it. How would I implement such an section (textbox with line numbers)?
Thanks.
P.S I would prefer to avoid Jquery.
Share Improve this question asked Apr 2, 2016 at 20:31 Maxwell ZhaoMaxwell Zhao 2214 silver badges17 bronze badges2 Answers
Reset to default 6I made you a quick example here...
var divCopy = document.getElementById('copyText'),
nmbrBox = document.getElementById('numbers'),
txtBox = document.getElementById('textBox'),
lineHeight = 20;
//Bind events to elements
function addEvents() {
"use strict";
txtBox.addEventListener("keyup", copyText, false);
txtBox.addEventListener("keyup", addLines, false);
}
/*
This function copies the text from the textarea to a div
so we can check the height and then get the number of lines
from that information
*/
function copyText() {
"use strict";
//variable to hold and manipulate the value of our textarea
var txtBoxVal = txtBox.value;
//regular expression to replace new lines with line breaks
txtBoxVal = txtBoxVal.replace(/(?:\r\n|\r|\n)/g, '<br />');
//copies the text from the textarea to the #copyText div
divCopy.innerHTML = txtBoxVal;
}
function addLines() {
"use strict";
var lines = divCopy.offsetHeight / lineHeight, x = 1, holder = '';
for (x = 1; x <= lines; x = x + 1) {
holder += '<div class="row">' + x + '.</div>';
}
if (lines === 0) {
holder = '<div class="row">1.</div>';
}
nmbrBox.innerHTML = holder;
}
window.addEventListener("load", addEvents, false);
html, body{
font-size: 10px;
height: 100%;
}
textarea{
background: #f3f3f3;
color: #111;
font-family: sans-serif;
font-size: 1.8em;
line-height: 20px;
min-height: 600px;
min-width: 800px;
resize: none;
overflow: hidden;
position: absolute;
left: 56px;
}
textarea:focus{
outline: 0;
}
textarea, .rows{
display: inline-block;
}
.rows{
background: #e3e3e3;
box-sizing: border-box;
color: #999;
font-family: monospace;
font-size: 1.8em;
height: 100%;
line-height: 20px;
max-height: 600px;
overflow: hidden;
padding: 0.16em 0em;
text-align: right;
width: 48px;
vertical-align: top;
}
#copyText{
display:inline-block;
font-family: sans-serif;
font-size: 1.8em;
line-height: 20px;
visibility: hidden;
}
<div class="container">
<div class="rows" id="numbers">
<div class="row">1.</div>
</div>
<textarea rows="30" id="textBox"></textarea>
<div id="copyText"></div>
</div>
<script src="script.js" type="text/javascript"></script>
Make sure you put these all in the same directory and save as the filenames I listed. This example only spans about 30 lines but you can modify it yourself to do as you wish. Also, inputting HTML tags will screw it up as well. You could modify that again to suit your needs this was just a quick example.
Basically what you are doing is copying the text from the textarea to a div and then calculating the number of lines in the textarea based on the height of the div.
Hope this helps!
Depending on how well you want this done.
A quick and dirty way to get started would be to add a counter every time return is hit.
To get started:
document.getElementById("myTextArea").on("keypress", function(event) {
var key = event.key;
if(key == 13) {
addLineCount();
}
});
This won't work if you start to delete lines though. You can potentially catch each event and check if it's deleting a return statement and decrease the count when it does.
Another thing you can do is count all the return characters in the textarea:
//the dollar sign is just what I use to know it's a DOM element
var $textToCount = document.getElementById("myTextArea");
$textToCount.on("keypress", function(event) {
//get the number of newlines
var lines = $textToCount.innerHtml.match("\n").length;
setLineCount(lines);
});
This will work but is less efficient. Also, it will have some errors if you use text-wrap where a line number will not represent a wrapped line as just one.
If you don't know how to add the line count column, try this:
function setLineCount(count) {
var out = "";
for(var c < count) {
out += count+"<br>";
}
document.getElementById("lineCountColumn").innerHTML = out;
}
And if you want to do an all functional line counter where text wrapping still numbers the lines correctly, you're going to have to do something clever. In most cases, some bination of the code shown here and in the link will give you a mostly functional line counter. It's up to you to put the pieces together.