[removed] Scroll to selection after using textarea.setSelectionRange in Chrome

前端 未结 8 555
离开以前
离开以前 2020-12-31 05:05

A javascript function selects a certain word in a textarea using .setSelectionRange(). In Firefox, the textarea automatically scrolls down to show the selected text. In Chro

相关标签:
8条回答
  • 2020-12-31 05:22

    This is a code inspired by the Matthew Flaschen's answer.

    /**
     * Scroll textarea to position.
     *
     * @param {HTMLInputElement} textarea
     * @param {Number} position
     */
    function scrollTo(textarea, position) {
        if (!textarea) { return; }
        if (position < 0) { return; }
    
        var body = textarea.value;
        if (body) {
            textarea.value = body.substring(0, position);
            textarea.scrollTop = position;
            textarea.value = body;
        }
    }
    

    Basically, the trick is to truncate the textarea, scroll to the end, then restore the second part of the text.

    Use it as follows

    var textarea, start, end;
    /* ... */
    
    scrollTo(textarea, end);
    textarea.focus();
    textarea.setSelectionRange(start, end);
    
    0 讨论(0)
  • 2020-12-31 05:34

    Valeriy Katkov's elegant solution works great but has two problems:

    1. Does not work for long strings
    2. Selected contents are scrolled to the bottom of the textarea, making it hard to see the context which surrounds the selection

    Here's my improved version that works for long strings (tested with at least 50,000 words) and scroll selection to the center of the textarea:

    function setSelectionRange(textarea, selectionStart, selectionEnd) {
        // First scroll selection region to view
        const fullText = textarea.value;
        textarea.value = fullText.substring(0, selectionEnd);
        // For some unknown reason, you must store the scollHeight to a variable
        // before setting the textarea value. Otherwise it won't work for long strings
        const scrollHeight = textarea.scrollHeight
        textarea.value = fullText;
        let scrollTop = scrollHeight;
        const textareaHeight = textarea.clientHeight;
        if (scrollTop > textareaHeight){
            // scroll selection to center of textarea
            scrollTop -= textareaHeight / 2;
        } else{
            scrollTop = 0;
        }
        textarea.scrollTop = scrollTop;
    
        // Continue to set selection range
        textarea.setSelectionRange(selectionStart, selectionEnd);
    }
    

    Works in Chrome 72, Firefox 65, Opera 58, and Edge 42

    For an example of using this function, see my GitHub Project SmartTextarea.

    0 讨论(0)
  • 2020-12-31 05:35

    Here is a simple and efficient solution, pure js :

    //first of all, you ignore any bad english, as i'm french and had a funny evening
    //get the textarea
    var textArea = document.getElementById('myTextArea');
    
    //define your selection
    var selectionStart = 50;
    var selectionEnd = 60;
    textArea.setSelectionRange( selectionStart, selectionEnd);
    
    // now lets do some math
    // we need the number of chars in a row
    var charsPerRow = textArea.cols;
    
    // we need to know at which row our selection starts
    var selectionRow = (selectionStart - (selectionStart % charsPerRow)) / charsPerRow;
    
    // we need to scroll to this row but scrolls are in pixels,
    // so we need to know a row's height, in pixels
    var lineHeight = textArea.clientHeight / textArea.rows;
    
    // scroll !!
    textArea.scrollTop = lineHeight * selectionRow;
    

    Put this in a function, extend the prototype of javascript's Element object with it, and you're good.

    Feel free to ask if you need any further help.

    0 讨论(0)
  • 2020-12-31 05:35

    I published an answer here:

    http://blog.blupixelit.eu/scroll-textarea-to-selected-word-using-javascript-jquery/

    It works perfectly with jsut one needed rule: Set a line-height n the css of the textarea!

    It calculate the position of the word to scroll to just by doing some simple mathematic calculation and it worked perfectly in all my experiments!

    Feel free to ask me anything you need about the code!

    0 讨论(0)
  • 2020-12-31 05:36

    Based on the idea from @naXa and @Valeriy Katkov, I refined the function with less bug. It should work out of the box (It's written with TypeScript. for JavasCript, just remove the type declariation) :

    function scrollTo(textarea: HTMLTextAreaElement, offset: number) {
        const txt = textarea.value;
        if (offset >= txt.length || offset < 0)
          return;
        textarea.scrollTop = 0;  // Important, so that scrollHeight will be adjusted
        textarea.value = txt.substring(0, offset);
        const height = textarea.scrollHeight;
        textarea.value = txt;
        textarea.scrollTop = height - 40;  // Margin between selection and top of viewport
    }
    

    Usage:

    let textarea, start, end;
    /* ... */
    
    scrollTo(textarea, start);
    textarea.focus();
    textarea.setSelectionRange(start, end);
    
    0 讨论(0)
  • 2020-12-31 05:37

    Complete code for Chrome

    <script type="text/javascript">
                var SAR = {};
    
                SAR.find = function () {
                    debugger;
                    var parola_cercata = $("#text_box_1").val(); // the searched word
                    // make text lowercase if search is supposed to be case insensitive
                    var txt = $('#remarks').val().toLowerCase();
                    parola_cercata = parola_cercata.toLowerCase();
    
                    var posi = jQuery('#remarks').getCursorPosEnd(); // take the position of the word in the text
    
                    var termPos = txt.indexOf(parola_cercata, posi);
    
                    if (termPos !== -1) {
                        debugger;
                        var target = document.getElementById("remarks");
                        var parola_cercata2 = $("#text_box_1").val();
                        // select the textarea and the word
                        if (target.setSelectionRange) {
    
                            if ('selectionStart' in target) {
                                target.selectionStart = termPos;
                                target.selectionEnd = termPos;
                                this.selectionStart = this.selectionEnd = target.value.indexOf(parola_cercata2);
                                target.blur();
                                target.focus();
                                target.setSelectionRange(termPos, termPos + parola_cercata.length);
                            }
                        } else {
                            var r = target.createTextRange();
                            r.collapse(true);
                            r.moveEnd('character', termPos + parola_cercata);
                            r.moveStart('character', termPos);
                            r.select();
                        }
                    } else {
                        // not found from cursor pos, so start from beginning
                        termPos = txt.indexOf(parola_cercata);
                        if (termPos !== -1) {
                            var target = document.getElementById("remarks");
                            var parola_cercata2 = $("#text_box_1").val();
                            // select the textarea and the word
                            if (target.setSelectionRange) {
    
                                if ('selectionStart' in target) {
                                    target.selectionStart = termPos;
                                    target.selectionEnd = termPos;
                                    this.selectionStart = this.selectionEnd = target.value.indexOf(parola_cercata2);
                                    target.blur();
                                    target.focus();
                                    target.setSelectionRange(termPos, termPos + parola_cercata.length);
                                }
                            } else {
                                var r = target.createTextRange();
                                r.collapse(true);
                                r.moveEnd('character', termPos + parola_cercata);
                                r.moveStart('character', termPos);
                                r.select();
                            }
                        } else {
                            alert("not found");
                        }
                    }
                };
    
    
                $.fn.getCursorPosEnd = function () {
                    var pos = 0;
                    var input = this.get(0);
                    // IE Support
                    if (document.selection) {
                        input.focus();
                        var sel = document.selection.createRange();
                        pos = sel.text.length;
                    }
                    // Firefox support
                    else if (input.selectionStart || input.selectionStart === '0')
                        pos = input.selectionEnd;
                    return pos;
                };
    </script> 
    
    0 讨论(0)
提交回复
热议问题