Find out the 'line' (row) number of the cursor in a textarea

后端 未结 3 1103
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-01 09:13

I would like to find out and keep track of the \'line number\' (rows) of the cursor in a textarea. (The \'bigger picture\' is to parse the text on the line every time a new

相关标签:
3条回答
  • 2020-12-01 09:57

    This is tough because of word wrap. It's a very easy thing to count the number of line breaks present, but what happens when the new row is because of word wrap? To solve this problem, it's useful to create a mirror (credit: github.com/jevin). Here's the idea:

    1. Create a mirror of the textarea
    2. Send the content from the beginning of the textarea to the cursor to the mirror
    3. Use the height of the mirror to extract the current row

    On 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, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;').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's event
        this.onkeyup = growTextarea;
    
        // Fire the event for text already present
        // sendContentToMirror(this);
    
        });
    };
    
    $(function(){
        $('textarea').trackRows();
    });
    
    0 讨论(0)
  • 2020-12-01 09:59

    This worked for me:

    function getLineNumber(textarea) {
      return textarea.value.substr(0, textarea.selectionStart) // get the substring of the textarea's value up to the cursor position
        .split("\n") // split on explicit line breaks
        .map((line) => 1 + Math.floor(line.length / textarea.cols)) // count the number of line wraps for each split and add 1 for the explicit line break
        .reduce((a, b) => a + b, 0); // add all of these together
    };
    

    Inspired by colab's answer as a starting point, this includes the number of word wraps without having to introduce a mirror (as in bradbarbin's answer).

    The trick is simply counting how many times the number of columns textarea.cols can divide the length of each segment between explicit line breaks \n.

    Note: this starts counting at 1.

    0 讨论(0)
  • 2020-12-01 10:01

    You would want to use selectionStart to do this.

    <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>
    

    This works when you change the cursor position using the mouse as well.

    0 讨论(0)
提交回复
热议问题