Caret position inside textarea
by Mdot
HTML
Place your cursor inside the textarea and move the caret. Selecting text also works.<br>
Position is: <span>0%</span><br>
<textarea>
4. foo bar
5. bar
6. foo foo snoo
7. hello world
8. hey there
9.
10. foo bar bar
11. bar
14.
15. goodbye
:)
</textarea>
CSS
textarea {
height: 300px;
width: 300px;
}
JavaScript
const textarea = document.querySelector('textarea');
const span = document.querySelector('span');
function get_current_caret_pos() {
let current_line = 1;
let char_count = 0;
const lines = textarea.value.split(/\n/);
// Accounts for actually selected text and calculates the mean.
const selection_pos = Math.round((textarea.selectionStart + textarea.selectionEnd) / 2);
for (let line_index = 0, line; line_index < lines.length; line_index++) {
line = lines[line_index];
// +1 for new-line that we stripped with split().
char_count += line.length + 1;
if (selection_pos < char_count) {
current_line = line_index + 1;
break;
}
}
// The "true" current line position would be:
// return 100 / lines.length * current_line;
// But since we have no 0th line, we interpolate for that.
// So: 1st line = 0%, last line = 100%
return (current_line - 1) / (lines.length - 1) * 100;
}
// selectionchange isn't input-specific so we have to check if it's our desired input.
// There is https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/selectionchange_event
// but so far, only Firefox has it implemented.
document.addEventListener('selectionchange', event => {
if (document.activeElement === textarea) {
const caret_pos = get_current_caret_pos();
span.textContent = `${new Intl.NumberFormat().format(caret_pos)}%`;
}
});