在光标位置将文本插入textarea(Javascript)

Jos*_*ams 102 javascript textarea

我想创建一个简单的函数,将文本添加到用户光标位置的文本区域.它需要是一个干净的功能.只是基础知识.我可以弄明白其余的.

Raa*_*aab 95

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 修复"丢失插入符号位置":在`}之前添加这些行,然后添加{``myField.selectionStart = startPos + myValue.length;``myField.selectionEnd = startPos + myValue.length;` (15认同)
  • 谢谢Rab的答案和@ user340140的修复.这是一个[工作示例](http://jsfiddle.net/Znarkus/Z99mK/). (10认同)
  • @user340140,您的“丢失插入符号药水”修复仅在我将焦点集中在您建议的行之前的输入上时才有效。似乎不可能更改非焦点字段的选择,至少在 Chrome 中(当前版本 62.0) (2认同)
  • 此代码有一个小问题:“selectionStart”是一个数值,因此应该与“0”而不是“0”进行比较,并且可能应该使用 [`===`](https:// stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons?rq=1) (2认同)

小智 72

这个片段可以帮助你在几行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);
});
Run Code Online (Sandbox Code Playgroud)

  • 对于任何想要替换所选文本的人:http://jsfiddle.net/4abr7jc5/2/ (8认同)
  • 感谢您提供有用的提琴。我已经对其进行了更新,以重置插入符号的位置,并使其成为一个jQuery插件:http://jsfiddle.net/70gqn153/ (2认同)

Eri*_*ner 30

为了正确的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;
  }
};
Run Code Online (Sandbox Code Playgroud)

  • 扩展您不拥有的对象的原型并不是一个好主意。只要让它成为一个常规函数,它也能正常工作。 (7认同)
  • @ErikAigner 那是不对的。在 ES6 之前,`A.prototype.fn = X` 是拥有“类”/继承的唯一方法。仅仅因为您可以扩展对象,并不意味着您应该扩展_native_对象。想象一下,10 年前,您实现了“Array#map”,然后“Array#map”成为了原生 API,但与您的 API 不兼容。现在有人打开你的代码库并看到 `[].map()` 并假设它是本机 API。你好,头痛和错误。 (2认同)

Jay*_*wal 12

对Erik Pukinskis的回答的纯JS修改:

function typeInTextarea(el, newText) {
  var start = el.selectionStart
  var end = el.selectionEnd
  var text = el.value
  var before = text.substring(0, start)
  var after  = text.substring(end, text.length)
  el.value = (before + newText + after)
  el.selectionStart = el.selectionEnd = start + newText.length
  el.focus()
}
Run Code Online (Sandbox Code Playgroud)

仅在Chrome 47中测试过.

如果要在键入相同字段时更改当前所选文本的值(对于自动完成或类似效果),请document.activeElement作为第一个参数传递.

这不是最优雅的方式,但它非常简单.

  • @Phoenix分号在Javascript中是可选的.没有它们也可以工作.虽然,如果需要,您可以用分号编辑.没什么大不了的. (3认同)
  • [我在JSFiddle上做了一个演示.](https://jsfiddle.net/j77uezpL/)它也可以使用`Version 54.0.2813.0 canary(64-bit)`,它基本上是Chrome Canary 54.0.2813.0.最后,如果您希望它通过ID插入文本框,请使用`document.getElementById('insertyourIDhere')`代替函数中的`el`. (3认同)
  • 嘿@ErikAigner!我的坏,没有意识到这个问题得到了两个Erik的回答.我的意思是'Erik Pukinskis`.我会更新答案以更好地反映这一点. (2认同)

Sno*_*arg 9

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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Eri*_*kis 8

我喜欢简单的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
})
Run Code Online (Sandbox Code Playgroud)

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


Ram*_*ast 6

一个适用于Firefox,Chrome,Opera,Safari,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);
  }
}
Run Code Online (Sandbox Code Playgroud)

setRangeText功能允许您用提供的文本替换当前选择,如果没有选择,则将文本插入光标位置。据我所知,只有Firefox支持。

对于其他浏览器,存在“ insertText”命令,该命令仅影响当前聚焦的html元素,其行为与 setRangeText

受到本文的部分启发


井上智*_*上智文 6

function insertAtCaret(text) {
  const textarea = document.querySelector('textarea')
  textarea.setRangeText(
    text,
    textarea.selectionStart,
    textarea.selectionEnd,
    'end'
  )
}

setInterval(() => insertAtCaret('Hello'), 3000)
Run Code Online (Sandbox Code Playgroud)
<textarea cols="60">Stack Overflow Stack Exchange Starbucks Coffee</textarea>
Run Code Online (Sandbox Code Playgroud)


Jet*_*tte 5

如果用户在插入文本后没有触摸输入,则永远不会触发 '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);
  }
}
Run Code Online (Sandbox Code Playgroud)

感谢plainjs.com为triggerEvent功能

有关w3schools.com 上的 oninput 事件的更多信息

我在为聊天创建表情符号选择器时发现了这一点。如果用户只是选择几个表情符号并点击“发送”按钮,则用户永远不会触摸输入字段。检查 value 属性时,它始终为空,即使插入的 emoji unicodes 在输入字段中可见。事实证明,如果用户不触摸该字段,则 'input' 事件永远不会触发,解决方案是像这样触发它。花了很长时间才弄明白这个……希望它可以节省一些时间。