Выясните номер строки (строки) курсора в текстовом поле
Я хотел бы узнать и отслеживать "номер строки" (строки) курсора в текстовом поле. ( "Большее изображение" - это синтаксический анализ текста в строке при каждом создании/изменении/выборе новой строки, если, конечно, текст не был вставлен. Это экономит синтаксический анализ всего текста без необходимости с заданными интервалами.)
В StackOverflow есть несколько сообщений, но никто из них не отвечает на мой вопрос, большинство вопросов касаются положения курсора в пикселях или номера строк, кроме текстового поля.
Моя попытка ниже, она отлично работает при запуске в строке 1 и не покидает текстовое поле. Это не удается при нажатии на текстовое поле и обратно на другую строку. Он также терпит неудачу при вставке текста в него, потому что стартовая строка не равна 1.
Мое знание JavaScript довольно ограничено.
<html>
<head>
<title>DEVBug</title>
<script type="text/javascript">
var total_lines = 1; // total lines
var current_line = 1; // current line
var old_line_count;
// main editor function
function code(e) {
// declare some needed vars
var keypress_code = e.keyCode; // key press
var editor = document.getElementById('editor'); // the editor textarea
var source_code = editor.value; // contents of the editor
// work out how many lines we have used in total
var lines = source_code.split("\n");
var total_lines = lines.length;
// do stuff on key presses
if (keypress_code == '13') { // Enter
current_line += 1;
} else if (keypress_code == '8') { // Backspace
if (old_line_count > total_lines) { current_line -= 1; }
} else if (keypress_code == '38') { // Up
if (total_lines > 1 && current_line > 1) { current_line -= 1; }
} else if (keypress_code == '40') { // Down
if (total_lines > 1 && current_line < total_lines) { current_line += 1; }
} else {
//document.getElementById('keycodes').innerHTML += keypress_code;
}
// for some reason chrome doesn't enter a newline char on enter
// you have to press enter and then an additional key for \n to appear
// making the total_lines counter lag.
if (total_lines < current_line) { total_lines += 1 };
// putput the data
document.getElementById('total_lines').innerHTML = "Total lines: " + total_lines;
document.getElementById('current_line').innerHTML = "Current line: " + current_line;
// save the old line count for comparison on next run
old_line_count = total_lines;
}
</script>
</head>
<body>
<textarea id="editor" rows="30" cols="100" value="" onkeydown="code(event)"></textarea>
<div id="total_lines"></div>
<div id="current_line"></div>
</body>
</html>
Ответы
Ответ 1
Вы бы хотели использовать selectionStart
для этого.
<textarea onkeyup="getLineNumber(this, document.getElementById('lineNo'));" onmouseup="this.onkeyup();"></textarea>
<div id="lineNo"></div>
<script>
function getLineNumber(textarea, indicator) {
indicator.innerHTML = textarea.value.substr(0, textarea.selectionStart).split("\n").length;
}
</script>
Это работает, когда вы меняете положение курсора с помощью мыши.
Ответ 2
Это сложно из-за переноса слов. Очень легко подсчитать количество разрывов строк, но что происходит, когда новая строка связана с переносом слов? Чтобы решить эту проблему, полезно создать зеркало (credit: github.com/jevin). Здесь идея:
- Создайте зеркало текстового поля
- Отправьте содержимое с начала текстового поля на курсор на зеркало
- Используйте высоту зеркала для извлечения текущей строки
В JSFiddle
jQuery.fn.trackRows = function() {
return this.each(function() {
var ininitalHeight, currentRow, firstIteration = true;
var createMirror = function(textarea) {
jQuery(textarea).after('<div class="autogrow-textarea-mirror"></div>');
return jQuery(textarea).next('.autogrow-textarea-mirror')[0];
}
var sendContentToMirror = function (textarea) {
mirror.innerHTML = String(textarea.value.substring(0,textarea.selectionStart-1)).replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>').replace(/\n/g, '<br />') + '.<br/>.';
calculateRowNumber();
}
var growTextarea = function () {
sendContentToMirror(this);
}
var calculateRowNumber = function () {
if(firstIteration){
ininitalHeight = $(mirror).height();
currentHeight = ininitalHeight;
firstIteration = false;
} else {
currentHeight = $(mirror).height();
}
// Assume that textarea.rows = 2 initially
currentRow = currentHeight/(ininitalHeight/2) - 1;
//remove tracker in production
$('.tracker').html('Current row: ' + currentRow);
}
// Create a mirror
var mirror = createMirror(this);
// Style the mirror
mirror.style.display = 'none';
mirror.style.wordWrap = 'break-word';
mirror.style.whiteSpace = 'normal';
mirror.style.padding = jQuery(this).css('padding');
mirror.style.width = jQuery(this).css('width');
mirror.style.fontFamily = jQuery(this).css('font-family');
mirror.style.fontSize = jQuery(this).css('font-size');
mirror.style.lineHeight = jQuery(this).css('line-height');
// Style the textarea
this.style.overflow = "hidden";
this.style.minHeight = this.rows+"em";
var ininitalHeight = $(mirror).height();
// Bind the textarea event
this.onkeyup = growTextarea;
// Fire the event for text already present
// sendContentToMirror(this);
});
};
$(function(){
$('textarea').trackRows();
});
Ответ 3
Два комментария Якуба П. Мэй и Эндрю Ли Сепа; указывают, что эти два человека не понимают природу строки в текстовой области.
Обтекание текста в текстовой области дает возможность читать текст без необходимости прокрутки в стороны. Визуальное перенос текста на новую визуальную строку не соответствует новой строке.
Это та же базовая и ожидаемая функциональность, которая существует во всех текстовых редакторах, включая Notepad++, Блокнот, а также Microsoft Word и большинство программ для редактирования текста.
Если текстовая область или текстовый редактор будут вводить жесткий разрыв строки, когда перенос текста будет затруднять определение, когда строка начинается и заканчивается с точки зрения кодирования. Это приведет к разбивке предложений в середине, а не в конце, и это затруднит поиск этого конкретного предложения в текстовом поиске, поскольку разрыв строки будет представлять собой дополнительный символ в предложении, что приведет к сбою ожидаемого соответствия.
Мягкий разрыв строки не является разрывом строки, поэтому текст, несмотря на его внешний вид, остается в той же строке, что и должен быть.