Replacing text inside textarea without focus

前端 未结 4 1605
慢半拍i
慢半拍i 2021-01-12 23:09

I want to replace selected text(or insert new text after cursor position if nothing is selected). The new text is entered from another textbox.
I want to be able to in

相关标签:
4条回答
  • 2021-01-12 23:33

    Alright, correct me where I am wrong.

    1) When text in the textarea is selected, then the button is clicked, the selected text is replaced by the text in the input.
    2) When no text is selected, no matter the cursor position, text is automatically added at the very end of the textarea.

    If those are the only stipulations, then this javascript would suffice, otherwise I need more information on what you want it to do.

    function pasteIntoInput(text) { 
      el=document.getElementById("text");
      el.focus();    
      if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number" && el.selectionStart != el.selectionEnd) { 
        var val = el.value; 
        var selStart = el.selectionStart;
        el.value = val.slice(0, selStart) + text + val.slice(el.selectionEnd);        
        el.selectionEnd = el.selectionStart = selStart + text.length;
      }
      else
        el.value += text;
    }
    

    Sorry that I cannot be of more assistance, it would be beneficial to understand the use of the function, so I could give the desired action.

    0 讨论(0)
  • 2021-01-12 23:46

    A jquery plugin to get selection index start and end in text area. The above javascript codes didnt work for IE7 and IE8 and gave very inconsistent results, so I have written this small jquery plugin. Allows to temporarily save start and end index of the selection and hightlight the selection at a later time.

    A working example and brief version is here: http://jsfiddle.net/hYuzk/3/

    A more details version with comments etc. is here: http://jsfiddle.net/hYuzk/4/

            // Cross browser plugins to set or get selection/caret position in textarea, input fields etc for IE7,IE8,IE9, FF, Chrome, Safari etc
            $.fn.extend({
                // Gets or sets a selection or caret position in textarea, input field etc.
                // Usage Example: select text from index 2 to 5 --> $('#myTextArea').caretSelection({start: 2, end: 5});
                //                get selected text or caret position --> $('#myTextArea').caretSelection();
                //                if start and end positions are the same, caret position will be set instead o fmaking a selection
                caretSelection : function(options)
                {
                if(options && !isNaN(options.start) && !isNaN(options.end))
                {
                    this.setCaretSelection(options);
                }
                else
                {
                    return this.getCaretSelection();
                }
                },
                setCaretSelection : function(options)
                {
                var inp = this[0];
                if(inp.createTextRange)
                {
                    var selRange = inp.createTextRange();
                    selRange.collapse(true);
                    selRange.moveStart('character', options.start);
                    selRange.moveEnd('character',options.end - options.start);
                    selRange.select();
                }
                else if(inp.setSelectionRange)
                {
                    inp.focus();
                    inp.setSelectionRange(options.start, options.end);
                }
                },
                getCaretSelection: function()
                {
                var inp = this[0], start = 0, end = 0;
                if(!isNaN(inp.selectionStart))
                {
                    start = inp.selectionStart;
                    end = inp.selectionEnd;
                }
                else if( inp.createTextRange )
                {
                    var inpTxtLen = inp.value.length, jqueryTxtLen = this.val().length;
                    var inpRange = inp.createTextRange(), collapsedRange = inp.createTextRange();
    
                    inpRange.moveToBookmark(document.selection.createRange().getBookmark());
                    collapsedRange.collapse(false);
    
                    start = inpRange.compareEndPoints('StartToEnd', collapsedRange) > -1 ? jqueryTxtLen : inpRange.moveStart('character', -inpTxtLen);
                    end = inpRange.compareEndPoints('EndToEnd', collapsedRange) > -1 ? jqueryTxtLen : inpRange.moveEnd('character', -inpTxtLen);
                }
                return {start: Math.abs(start), end: Math.abs(end)};
    
                },
                // Usage: $('#txtArea').replaceCaretSelection({start: startIndex, end: endIndex, text: 'text to replace with', insPos: 'before|after|select'})
                // Options     start: start index of the text to be replaced
                //               end: end index of the text to be replaced
                //              text: text to replace the selection with
                //            insPos: indicates whether to place the caret 'before' or 'after' the replacement text, 'select' will select the replacement text
    
                replaceCaretSelection: function(options)
                {
                var pos = this.caretSelection();
                this.val( this.val().substring(0,pos.start) + options.text + this.val().substring(pos.end) );
                if(options.insPos == 'before')
                {
                    this.caretSelection({start: pos.start, end: pos.start});
                }
                else if( options.insPos == 'after' )
                {
                    this.caretSelection({start: pos.start + options.text.length, end: pos.start + options.text.length});
                }
                else if( options.insPos == 'select' )
                {
                    this.caretSelection({start: pos.start, end: pos.start + options.text.length});
                }
                }
            });
    
    0 讨论(0)
  • 2021-01-12 23:55

    So, you want to persist the selection when you focus out of the textarea and focus on the input tag.

    You need to remember the selection (start and end points when the text area loses focus) and force the selection so that it persists.

    To remember the selection, you can store the el.selectionStart and el.selectionEnd in two global variables inside a function which is called at onblur() event of textarea tag.

    Then inside your pasteIntoInput() you can consider those two points for replacement.

    To force selection - Check this solution for persisting the selection. This uses jquery however, not plain javascript.

    However, I am not sure whether the solution actually works. I tried it here http://jsfiddle.net/sandeepan_nits/qpZdJ/1/ but it does not work as expected.

    Updates

    I doubt if it is possible to persist selection after focus is gone. Probably selection needs focus to be there and the answer link that I gave tries to focus and then select. In that case this will not solve your problem. So, the alternatives could be -

    • faking a text area with an html div. You can define some styles to create a selection like effect and apply it onblur() or use a simple readymade editor if available.

    • Displaying the selection dynamically in a separate area. Check this demo of jquery fieldSelection plugin . Remember that you are already storing the selection in global variables for the actual replacement. You only need to display to the user the selection which will be replaced. I think displaying the selection separately like this demo saves your time and it looks cool too.

    But depends on your requirement of course.

    Further Update

    Check http://jsfiddle.net/sandeepan_nits/qpZdJ/2/ for a working "Replacing text inside textarea without focus" (like you want) but without the selection on blur. I still don't know whether it is possible to keep the selection on blur.

    Another Update (21st December)

    Working solution for IEs as well as other browsers http://jsfiddle.net/sandeepan_nits/qpZdJ/24/

    Here is the same code:-

    The html -

    <textarea id='text' cols="40" rows="20" onbeforedeactivate="storeSelectionIeCase();" onblur="storeSelectionOthersCase();">
    </textarea>
    
    <div id="opt">
        <input id="input" type="text" size="35">
        <input type="button" onclick='pasteIntoInput(document.getElementById("input").value)' value="button"/>
    
    </div>
    

    and all the js

    var storedSelectionStart = null;
    var storedSelectionEnd = null;
    
    function pasteIntoInput(text)
    {
    
        el=document.getElementById("text");
    
        el.focus();    
        if((storedSelectionStart != null) && (storedSelectionEnd != null))
        {
            start = storedSelectionStart;
            end = storedSelectionEnd;
        }
        else
        {
            start = el.selectionStart;
            end = el.selectionEnd;
        }
        if (typeof start  == "number"&& typeof end == "number")
        {
            var val = el.value;
            var selStart = start;
            var end  = selStart + text.length;
            el.value = val.slice(0, selStart) + text + val.slice(end );        
        }
        else if (typeof document.selection != "undefined")
        {
           var textRange = document.selection.createRange();        
           textRange.text = text;       
           textRange.collapse(false);        
           textRange.select();
        }
    }  
    
    function storeSelectionOthersCase()
    {
        if(!(isBrowserIE6() || isBrowserIE7()))
        {
            storeSelection();
        }
        else
        {
            return false;
        }
    }
    
    
    function storeSelectionIeCase()
    {
        if((isBrowserIE6() || isBrowserIE7()))
        {
            storeSelection();
        }
        else
        {
            return false;
        }
    }
    
    
    function storeSelection()
    {
        //get selection
        el=document.getElementById("text");
    
        var el = document.getElementById("text");
        var sel = getInputSelection(el);
        //alert("check"+sel.start + ", " + sel.end);
    
    
        storedSelectionStart  = sel.start;
        storedSelectionEnd = sel.end;
    
       //alert("see"+storedSelectionStart  +" - "+storedSelectionEnd );
    }
    
    function getInputSelection(el)
    {
        var start = 0, end = 0, normalizedValue, range,
            textInputRange, len, endRange;
    
        if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
            start = el.selectionStart;
            end = el.selectionEnd;
        } else {
            range = document.selection.createRange();
    
            if (range && range.parentElement() == el) {
                len = el.value.length;
                normalizedValue = el.value.replace(/\r\n/g, "\n");
    
                // Create a working TextRange that lives only in the input
                textInputRange = el.createTextRange();
                textInputRange.moveToBookmark(range.getBookmark());
    
                // Check if the start and end of the selection are at the very end
                // of the input, since moveStart/moveEnd doesn't return what we want
                // in those cases
                endRange = el.createTextRange();
                endRange.collapse(false);
    
                if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                    start = end = len;
                } else {
                    start = -textInputRange.moveStart("character", -len);
                    start += normalizedValue.slice(0, start).split("\n").length - 1;
    
                    if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                        end = len;
                    } else {
                        end = -textInputRange.moveEnd("character", -len);
                        end += normalizedValue.slice(0, end).split("\n").length - 1;
                    }
                }
            }
        }
    
        return {
            start: start,
            end: end
        };
    }
    
    function isBrowserIE6()
    {
        var ret = false;
        if(($.browser.msie) && (parseInt($.browser.version) == 6) && (!this.XMLHttpRequest))
        {
            ret = true;
        }
        return ret;
    }
    
    function isBrowserIE7()
    {
        var ret = false;
        if(($.browser.msie) && ((parseInt($.browser.version) == 7) && (this.XMLHttpRequest)))
        { //Modification because of IE tester IE7 being detected as IE6
            ret = true;
        }
        return ret;
    }
    

    The previous fiddle was not working in IEs because by the time the onblur() event fires, the selection is destroyed in IE. I have applied some browser based conditions for IE 6 and 7, but not tested yet in IE 8.

    Thanks to Tim Down who helped me in identifying the problem with the previous fiddle.

    0 讨论(0)
  • 2021-01-12 23:59

    This is alternative solution based on answers from above and more ideas.
    For IE only (other browsers support this functionality by default).

    More testing is needed (I tested it just in IE8)

    <script type="text/javascript">
        var pos = 0;
        var len = 0;
    
        function pasteIntoInput(text) {
           var el = document.getElementById("text");
    
            el.focus();
            if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
                var val = el.value;
                var selStart = el.selectionStart;
                el.value = val.slice(0, selStart) + text + val.slice(el.selectionEnd);
                el.selectionEnd = el.selectionStart = selStart + text.length;
            }
            else if (typeof document.selection != "undefined") {
            //var textRange = document.selection.createRange();
            var textRange  = el.createTextRange();
                //  el.focus();
                if (len > 0) { //something selected, so replace
                    textRange.collapse(true);
                    textRange.moveEnd('character', pos+len);
                    textRange.moveStart('character', pos);
                    textRange.select();
                    textRange.text = text;
    
                }
                else {
                    textRange.collapse(true);                   
                    textRange.moveEnd('character', pos);
                    textRange.moveStart('character', pos);                    
                    textRange.text = text;
                    textRange.select();
    
                }
                el.focus();
            }
        }
    
    
        function GetCaretPosition(txtarea) {
    
            pos = 0;
            if (document.selection) {
    
                // get current selection
                var range = document.selection.createRange();
                if (range.text.length>0)
                 len=range.text.length;
    
                // get full range
                var rangeFull = document.body.createTextRange();
                rangeFull.moveToElementText(txtarea);
    
                var sel_start;
                for (sel_start = 0; rangeFull.compareEndPoints('StartToStart', range) < 0; sel_start++) {
                    rangeFull.moveStart('character', 1);
                }                
    
    
                pos = sel_start;                
    
    
            }  
    
        }
    
    </script>
    
    0 讨论(0)
提交回复
热议问题