I am trying to add go to line and find text functionalities on an editor that employs textarea and a numbering div.
I have tried the following code but it is not scrolling the editor to focus on the line or text entered by the user in the prompt;
Please help me on how to implement the go to line and find text functions on the editor.
const ta = document.querySelector('textarea')
function updateRowNumbering() {
const num = ta.value.split("n").length;
const numbers = ta.parentNode.querySelector(".numbers");
numbers.innerHTML = Array(num).fill("<span></span>").join("");
}
ta.value = `One
Two
Three
Four
Five
Six
Seven
Eight
Nine
Ten
Eleven
Kumi na Mbili
`
updateRowNumbering()
//Trying to implement go to line and find text;
const numbers = ta.parentNode.querySelector('.numbers');
const gotoLinePrompt = document.querySelector('.goto-line-prompt');
const findPrompt = document.querySelector('.find-prompt');
// Hide the prompts by default.
gotoLinePrompt.style.display = 'none';
findPrompt.style.display = 'none';
// Add event listeners to the "Go to Line" and "Find" buttons.
document.querySelector('.goto-line-button').addEventListener('click', function() {
gotoLinePrompt.style.display = 'block';
});
document.querySelector('.find-button').addEventListener('click', function() {
findPrompt.style.display = 'block';
});
// Add event listeners to the "OK" buttons in the prompts.
gotoLinePrompt.querySelector('.ok-button').addEventListener('click', function() {
const lineNumber = gotoLinePrompt.querySelector('input').value;
if (lineNumber !== null) {
const lineHeight = ta.scrollHeight / ta.clientHeight;
ta.scrollTop = (lineNumber - 1) * lineHeight;
numbers.scrollTop = ta.scrollTop;
}
gotoLinePrompt.style.display = 'none';
});
findPrompt.querySelector('.ok-button').addEventListener('click', function() {
const searchTerm = findPrompt.querySelector('input').value;
if (searchTerm !== null) {
const text = ta.textContent;
const index = text.indexOf(searchTerm);
if (index !== -1) {
const lineNumber = Math.floor(index / ta.value.split('n')[0].length) + 1;
ta.scrollTop = (lineNumber - 1) * lineHeight;
numbers.scrollTop = ta.scrollTop;
}
}
findPrompt.style.display = 'none';
});
body, textarea {
font-family: Consolas, "Courier New", Courier, monospace;
}
.editor {
display: inline-grid;
grid-template-columns: 3em auto;
gap: 10px;
line-height: 21px;
background: rgb(40 42 58);
border-radius: 2px;
overflow-y: auto;
max-height: 250px;
}
.editor>* {
padding-top: 10px;
padding-bottom: 10px;
}
.numbers {
text-align: right;
background: #333;
padding-right: 5px;
}
.numbers span {
counter-increment: linenumber;
}
.numbers span::before {
content: counter(linenumber);
display: block;
color: #888;
}
textarea {
line-height: 21px;
border: 0;
background: transparent;
color: #fff;
min-width: 500px;
outline: none;
resize: none;
padding-right: 10px;
}
<div class="actions">
<div class="goto-line-prompt" style="display: none;">
<h1>Go to Line</h1>
<input type="number" placeholder="Enter the line number to go to:" />
<button type="button" class="ok-button">OK</button>
</div>
<div class="find-prompt" style="display: none;">
<h1>Find</h1>
<input type="text" placeholder="Enter the text to find:" />
<button type="button" class="ok-button">OK</button>
</div>
<button class="goto-line-button">Go to Line</button>
<button class="find-button">Find</button>
</div>
<div class="editor">
<div class="numbers">
<span></span>
</div>
<textarea wrap="off" onkeyup="updateRowNumbering()"></textarea>
</div>
2
Answers
.value
is NEVER going to be null so that check is useless. There is notextContent
for a text area.There are built in apis to scroll to an element into the view so there is no reason to reinvent the wheel.
There are a few issues I can see here, but I think the core of your problem is that you’re targeting the textarea to scroll when you should be targeting the editor component. You’ll notice that if you set the height/min-height on
.editor
(not.editor>*
) to something tiny like 40px, you get a double scrollbar scenario where the textarea scrolls, as well as the editor – and if you try to scroll the numbers, the entire editor scrolls, whereas when focused on the textarea, only the text scrolls.Directionally, something like this may help:
+1 also to @epascarello’s answer with points on not reinventing scrolling APIs, this will help make sure things scroll correctly whichever element you end up scrolling.