How can I “replace” a selected text-range in a tex

2019-02-18 06:43发布

I'm trying to use Javascript to replace the selected text in an arbitrary selected TEXTAREA node in Chrome (! not a content editable div !) The code fragment I see repeated in lots of places to replace selected text basically does this:

var sel = window.getSelection();
var range = sel.getRangeAt(0);
range.insertNode( document.createTextNode("test "));

However, this does not work for input fields such as TEXTAREA or INPUT TYPE=TEXT. The text is inserted BEFORE the TEXTAREA instead of inside it.

There is an alternative method to modify the selection text inside a text area using textarea.selectionStart and textarea.selectionEnd. However, these require figuring out which textarea element is actually active/selected. Chrome/Webkit document.activeElement seems to be broken and has been broken for a long time. I can't figure out any workaround to find the "currently selected textarea". See the bug here...

http://code.google.com/p/chromium/issues/detail?id=14436

You can see a micro-demo of the problem I'm trying to solve here.

http://dj1.willowmail.com/~jeske/_drop/insertIssue/1.html

http://ajaxandxml.blogspot.com/2007/11/emulating-activeelement-property-with.html

Any thoughts on this?

Given a webpage with an arbitrary bit of text selected in an arbitrary TEXTAREA node, without knowing ahead of time what textarea the focus is in, how do I find the active textarea and replace the selected text with some other text?

(( FYI: I'm using this code in a Chrome extension. An in-page javascript content script is extending the page javascript, so I have no idea what the page structure is ahead of time. It needs to work for any webpage. ))

2条回答
在下西门庆
2楼-- · 2019-02-18 06:58

I think the problem you may be having is that the active element changes as a result of clicking the button before your code runs. If you instead use the mousedown event and prevent the default button action, it works fine in Chrome:

http://jsfiddle.net/b3Fk5/2/

查看更多
Root(大扎)
3楼-- · 2019-02-18 07:08

It appears that as of 8/23/2012, Chrome does not properly support activeElement, as it is often set to "body" when it shouldn't be.

There may also be some challenges because in my chrome extension, right-clicking to get a context menu might be altering the activeElement.

The solution was to provide a focus handler to create a more reliable activeElement in Chrome, and then use direct interaction with the TEXTAREA to handle the selection replacement.

var dActiveElement = null;

function _dom_trackActiveElement(evt) {
    if (evt && evt.target) {
      dActiveElement = evt.target;
      console.log("focus on: " + dActiveElement.nodeName + 
                  " id: " + dActiveElement.id);
    } else {
      console.log("focus else..");
    }
}

if (document.addEventListener) {
   document.addEventListener("focus",_dom_trackActiveElement,true);
}

function insertTextAtCursor(text) {
    console.log("insertTextAtCursor : " + text);    

    if (dActiveElement.nodeName.toUpperCase() == "TEXTAREA") {
       console.log("selection in textarea!  id: " + dActiveElement.id);

       var ta = dActiveElement;
       var saveSelectionStart = ta.selectionStart;

       var newvalue = ta.value.slice(0,ta.selectionStart) + 
                         text + ta.value.slice(ta.selectionEnd,ta.length);
       console.log("output : " + newvalue  + ", len : " + newvalue.length);
       var newSelectionEnd = ta.selectionStart + text.length;

       ta.value = newvalue;
       ta.selectionStart = ta.selectionEnd = (newSelectionEnd);       
    }
 }
查看更多
登录 后发表回答