簡體   English   中英

如何在當前光標位置將文本插入文本區域?

[英]How to insert text into the textarea at the current cursor position?

我想創建一個簡單的函數,將文本添加到用戶光標位置的文本區域中。 它需要是一個干凈的功能。 只是基礎知識。 我可以弄清楚其余的。

使用輸入元素的selectionStart / selectionEnd屬性(也適用於<textarea>

function insertAtCursor(myField, myValue) {
    //IE support
    if (document.selection) {
        myField.focus();
        sel = document.selection.createRange();
        sel.text = myValue;
    }
    //MOZILLA and others
    else if (myField.selectionStart || myField.selectionStart == '0') {
        var startPos = myField.selectionStart;
        var endPos = myField.selectionEnd;
        myField.value = myField.value.substring(0, startPos)
            + myValue
            + myField.value.substring(endPos, myField.value.length);
    } else {
        myField.value += myValue;
    }
}

這個片段可以在幾行 jQuery 1.9+ 中幫助你:http: //jsfiddle.net/4MBUG/2/

$('input[type=button]').on('click', function() {
    var cursorPos = $('#text').prop('selectionStart');
    var v = $('#text').val();
    var textBefore = v.substring(0,  cursorPos);
    var textAfter  = v.substring(cursorPos, v.length);

    $('#text').val(textBefore + $(this).val() + textAfter);
});

新答案:

https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setRangeText

我不確定瀏覽器對此的支持。

在 Chrome 81 中測試。

 function typeInTextarea(newText, el = document.activeElement) { const [start, end] = [el.selectionStart, el.selectionEnd]; el.setRangeText(newText, start, end, 'select'); } document.getElementById("input").onkeydown = e => { if (e.key === "Enter") typeInTextarea("lol"); }
 <input id="input" /> <br/><br/> <div>Press Enter to insert "lol" at caret.</div> <div>It'll replace a selection with the given text.</div>

老答案:

Erik Pukinskis 回答的純 JS 修改:

 function typeInTextarea(newText, el = document.activeElement) { const start = el.selectionStart const end = el.selectionEnd const text = el.value const before = text.substring(0, start) const after = text.substring(end, text.length) el.value = (before + newText + after) el.selectionStart = el.selectionEnd = start + newText.length el.focus() } document.getElementById("input").onkeydown = e => { if (e.key === "Enter") typeInTextarea("lol"); }
 <input id="input" /> <br/><br/> <div>Press Enter to insert "lol" at caret.</div>

在 Chrome 47、81 和 Firefox 76 中測試。

如果您想在輸入同一字段時更改當前選定文本的值(用於自動完成或類似效果),請將document.activeElement作為第一個參數傳遞。

這不是最優雅的方法,但它非常簡單。

示例用法:

typeInTextarea('hello');
typeInTextarea('haha', document.getElementById('some-id'));

為了正確的Javascript

HTMLTextAreaElement.prototype.insertAtCaret = function (text) {
  text = text || '';
  if (document.selection) {
    // IE
    this.focus();
    var sel = document.selection.createRange();
    sel.text = text;
  } else if (this.selectionStart || this.selectionStart === 0) {
    // Others
    var startPos = this.selectionStart;
    var endPos = this.selectionEnd;
    this.value = this.value.substring(0, startPos) +
      text +
      this.value.substring(endPos, this.value.length);
    this.selectionStart = startPos + text.length;
    this.selectionEnd = startPos + text.length;
  } else {
    this.value += text;
  }
};

一個簡單的解決方案,適用於 firefox、chrome、opera、safari 和 edge,但可能不適用於舊的 IE 瀏覽器。

var target = document.getElementById("mytextarea_id")

if (target.setRangeText) {
    //if setRangeText function is supported by current browser
    target.setRangeText(data)
} else {
    target.focus()
    document.execCommand('insertText', false /*no UI*/, data);
}

setRangeText函數允許您用提供的文本替換當前選擇,或者如果沒有選擇,則在光標位置插入文本。 據我所知,它僅受 Firefox 支持。

對於其他瀏覽器,“insertText”命令僅影響當前聚焦的 html 元素,並且具有與setRangeText相同的行為

部分靈感來自這篇文章

我喜歡簡單的javascript ,而且我通常有jQuery 這是我根據mparkuk 提出的

function typeInTextarea(el, newText) {
    var start = el.prop("selectionStart")
    var end = el.prop("selectionEnd")
    var text = el.val()
    var before = text.substring(0, start)
    var after  = text.substring(end, text.length)
    el.val(before + newText + after)
    el[0].selectionStart = el[0].selectionEnd = start + newText.length
    el.focus()
}

$("button").on("click", function() {
    typeInTextarea($("textarea"), "some text")
    return false
})

這是一個演示: http ://codepen.io/erikpukinskis/pen/EjaaMY?editors=101

Rab 的回答效果很好,但不適用於 Microsoft Edge,所以我也為 Edge 添加了一個小的改編:

https://jsfiddle.net/et9borp4/

function insertAtCursor(myField, myValue) {
    //IE support
    if (document.selection) {
        myField.focus();
        sel = document.selection.createRange();
        sel.text = myValue;
    }
    // Microsoft Edge
    else if(window.navigator.userAgent.indexOf("Edge") > -1) {
      var startPos = myField.selectionStart; 
      var endPos = myField.selectionEnd; 

      myField.value = myField.value.substring(0, startPos)+ myValue 
             + myField.value.substring(endPos, myField.value.length); 

      var pos = startPos + myValue.length;
      myField.focus();
      myField.setSelectionRange(pos, pos);
    }
    //MOZILLA and others
    else if (myField.selectionStart || myField.selectionStart == '0') {
        var startPos = myField.selectionStart;
        var endPos = myField.selectionEnd;
        myField.value = myField.value.substring(0, startPos)
            + myValue
            + myField.value.substring(endPos, myField.value.length);
    } else {
        myField.value += myValue;
    }
}

如果用戶在插入文本后沒有觸摸輸入,則永遠不會觸發 'input' 事件,並且 value 屬性不會反映更改。 因此,在以編程方式插入文本后觸發輸入事件很重要。 聚焦領域是不夠的。

以下是Snorvarg 的答案副本,最后帶有輸入觸發器:

function insertAtCursor(myField, myValue) {
    //IE support
    if (document.selection) {
        myField.focus();
        sel = document.selection.createRange();
        sel.text = myValue;
    }
    // Microsoft Edge
    else if(window.navigator.userAgent.indexOf("Edge") > -1) {
      var startPos = myField.selectionStart; 
      var endPos = myField.selectionEnd; 

      myField.value = myField.value.substring(0, startPos)+ myValue 
             + myField.value.substring(endPos, myField.value.length); 

      var pos = startPos + myValue.length;
      myField.focus();
      myField.setSelectionRange(pos, pos);
    }
    //MOZILLA and others
    else if (myField.selectionStart || myField.selectionStart == '0') {
        var startPos = myField.selectionStart;
        var endPos = myField.selectionEnd;
        myField.value = myField.value.substring(0, startPos)
            + myValue
            + myField.value.substring(endPos, myField.value.length);
    } else {
        myField.value += myValue;
    }
    triggerEvent(myField,'input');
}

function triggerEvent(el, type){
  if ('createEvent' in document) {
    // modern browsers, IE9+
    var e = document.createEvent('HTMLEvents');
    e.initEvent(type, false, true);
    el.dispatchEvent(e);
  } else {
    // IE 8
    var e = document.createEventObject();
    e.eventType = type;
    el.fireEvent('on'+e.eventType, e);
  }
}

歸功於 plainjs.com的 triggerEvent 函數

更多關於w3schools.com上的 oninput 事件

我在為聊天創建表情符號選擇器時發現了這一點。 如果用戶只是選擇幾個表情符號並點擊“發送”按鈕,則用戶永遠不會觸摸輸入字段。 檢查 value 屬性時,它始終為空,即使插入的表情符號 unicode 在輸入字段中可見。 事實證明,如果用戶不觸摸該字段,則“輸入”事件永遠不會觸發,解決方案是像這樣觸發它。 花了很長時間才弄清楚這個……希望它能節省一些時間。

 function insertAtCaret(text) { const textarea = document.querySelector('textarea') textarea.setRangeText( text, textarea.selectionStart, textarea.selectionEnd, 'end' ) } setInterval(() => insertAtCaret('Hello'), 3000)
 <textarea cols="60">Stack Overflow Stack Exchange Starbucks Coffee</textarea>

下面的代碼是 Dmitriy Kubyshkin 對包https://github.com/grassator/insert-text-at-cursor的 TypeScript 改編。


/**
 * Inserts the given text at the cursor. If the element contains a selection, the selection
 * will be replaced by the text.
 */
export function insertText(input: HTMLTextAreaElement | HTMLInputElement, text: string) {
  // Most of the used APIs only work with the field selected
  input.focus();

  // IE 8-10
  if ((document as any).selection) {
    const ieRange = (document as any).selection.createRange();
    ieRange.text = text;

    // Move cursor after the inserted text
    ieRange.collapse(false /* to the end */);
    ieRange.select();

    return;
  }

  // Webkit + Edge
  const isSuccess = document.execCommand("insertText", false, text);
  if (!isSuccess) {
    const start = input.selectionStart;
    const end = input.selectionEnd;
    // Firefox (non-standard method)
    if (typeof (input as any).setRangeText === "function") {
      (input as any).setRangeText(text);
    } else {
      if (canManipulateViaTextNodes(input)) {
        const textNode = document.createTextNode(text);
        let node = input.firstChild;

        // If textarea is empty, just insert the text
        if (!node) {
          input.appendChild(textNode);
        } else {
          // Otherwise we need to find a nodes for start and end
          let offset = 0;
          let startNode = null;
          let endNode = null;

          // To make a change we just need a Range, not a Selection
          const range = document.createRange();

          while (node && (startNode === null || endNode === null)) {
            const nodeLength = node.nodeValue.length;

            // if start of the selection falls into current node
            if (start >= offset && start <= offset + nodeLength) {
              range.setStart((startNode = node), start - offset);
            }

            // if end of the selection falls into current node
            if (end >= offset && end <= offset + nodeLength) {
              range.setEnd((endNode = node), end - offset);
            }

            offset += nodeLength;
            node = node.nextSibling;
          }

          // If there is some text selected, remove it as we should replace it
          if (start !== end) {
            range.deleteContents();
          }

          // Finally insert a new node. The browser will automatically
          // split start and end nodes into two if necessary
          range.insertNode(textNode);
        }
      } else {
        // For the text input the only way is to replace the whole value :(
        const value = input.value;
        input.value = value.slice(0, start) + text + value.slice(end);
      }
    }

    // Correct the cursor position to be at the end of the insertion
    input.setSelectionRange(start + text.length, start + text.length);

    // Notify any possible listeners of the change
    const e = document.createEvent("UIEvent");
    e.initEvent("input", true, false);
    input.dispatchEvent(e);
  }
}

function canManipulateViaTextNodes(input: HTMLTextAreaElement | HTMLInputElement) {
  if (input.nodeName !== "TEXTAREA") {
    return false;
  }
  let browserSupportsTextareaTextNodes;
  if (typeof browserSupportsTextareaTextNodes === "undefined") {
    const textarea = document.createElement("textarea");
    textarea.value = "1";
    browserSupportsTextareaTextNodes = !!textarea.firstChild;
  }
  return browserSupportsTextareaTextNodes;
}

發布修改功能供自己參考。 此示例從<select>對象插入一個選定項目,並將插入符號放在標記之間:

//Inserts a choicebox selected element into target by id
function insertTag(choicebox,id) {
    var ta=document.getElementById(id)
    ta.focus()
    var ss=ta.selectionStart
    var se=ta.selectionEnd
    ta.value=ta.value.substring(0,ss)+'<'+choicebox.value+'>'+'</'+choicebox.value+'>'+ta.value.substring(se,ta.value.length)
    ta.setSelectionRange(ss+choicebox.value.length+2,ss+choicebox.value.length+2)
}
/**
 * Usage "foo baz".insertInside(4, 0, "bar ") ==> "foo bar baz"
 */
String.prototype.insertInside = function(start, delCount, newSubStr) {
    return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
};

$('textarea').bind("keydown keypress", function (event) {
    var val = $(this).val();
    var indexOf = $(this).prop('selectionStart');
    if(event.which === 13) {
        val = val.insertInside(indexOf, 0,  "<br>\n");
        $(this).val(val);
        $(this).focus();
    }
});

擴展阿德里亞諾的答案,我們也可以考慮光標結束這將使“替換文本”工作

$('input[type=button]').on('click', function() {
    var cursorStart = $('#text').prop('selectionStart');
    var cursorEnd = $('#text').prop('selectionEnd');
    var v = $('#text').val();
    var textBefore = v.substring(0,cursorStart);
    var textAfter  = v.substring(cursorEnd);
    $('#text').val(textBefore + $(this).val() + textAfter);
});

將其更改為getElementById(myField)

function insertAtCursor(myField, myValue) {
    // IE support
    if (document.selection) {
        document.getElementById(myField).focus();
        sel = document.selection.createRange();
        sel.text = myValue;
    }
    // MOZILLA and others
    else if (document.getElementById(myField).selectionStart || document.getElementById(myField).selectionStart == '0') {
        var startPos = document.getElementById(myField).selectionStart;
        var endPos = document.getElementById(myField).selectionEnd;
        document.getElementById(myField).value =
                document.getElementById(myField).value.substring(0, startPos)
                + myValue
                + document.getElementById(myField).value.substring(endPos, document.getElementById(myField).value.length);
    } else {
        document.getElementById(myField).value += myValue;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM