在光标使用 Javascript/jquery 的位置插入文本

Posted

技术标签:

【中文标题】在光标使用 Javascript/jquery 的位置插入文本【英文标题】:Inserting a text where cursor is using Javascript/jquery 【发布时间】:2010-11-07 00:54:22 【问题描述】:

我有一个包含很多文本框的页面。当有人单击链接时,我希望在光标所在的位置插入一两个词,或附加到具有焦点的文本框。

例如,如果光标/焦点位于显示“apple”的文本框上,并且他单击显示“[email]”的链接,那么我希望文本框显示“apple bob@example.com”。

我该怎么做?这甚至可能吗,因为如果焦点在单选/下拉/非文本框元素上怎么办?可以记住最后一个关注的文本框吗?

【问题讨论】:

我认为这是可能的,因为它是所见即所得编辑器的基础,我不知道该怎么做。 How do I insert a character at the caret with javascript?的可能重复 感谢您提出这个问题...现在我可以使用 Chrome 扩展程序在光标处插入“[version]”! 如果您正在寻找一个支持撤消的简单模块,请尝试insert-text-textarea。如果您需要 IE8+ 支持,请尝试使用 insert-text-at-cursor 包。 【参考方案1】:

使用这个,来自here:

function insertAtCaret(areaId, text) 
  var txtarea = document.getElementById(areaId);
  if (!txtarea) 
    return;
  

  var scrollPos = txtarea.scrollTop;
  var strPos = 0;
  var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ?
    "ff" : (document.selection ? "ie" : false));
  if (br == "ie") 
    txtarea.focus();
    var range = document.selection.createRange();
    range.moveStart('character', -txtarea.value.length);
    strPos = range.text.length;
   else if (br == "ff") 
    strPos = txtarea.selectionStart;
  

  var front = (txtarea.value).substring(0, strPos);
  var back = (txtarea.value).substring(strPos, txtarea.value.length);
  txtarea.value = front + text + back;
  strPos = strPos + text.length;
  if (br == "ie") 
    txtarea.focus();
    var ieRange = document.selection.createRange();
    ieRange.moveStart('character', -txtarea.value.length);
    ieRange.moveStart('character', strPos);
    ieRange.moveEnd('character', 0);
    ieRange.select();
   else if (br == "ff") 
    txtarea.selectionStart = strPos;
    txtarea.selectionEnd = strPos;
    txtarea.focus();
  

  txtarea.scrollTop = scrollPos;
<textarea id="textareaid"></textarea>
<a href="#" onclick="insertAtCaret('textareaid', 'text to insert');return false;">Click Here to Insert</a>

【讨论】:

这很好用,但它不能像所有文本编辑器那样处理替换选定的文本。发帖人的原始问题可能不需要这个,但如果你需要它,你可以简单地将'strPos'替换为'txtArea.selectionEnd'。如果您不需要支持旧版本的 IE,我在下面的回答会显示这一点,并删除浏览器检测代码。 有没有办法用areaId选择所有元素? 您可以通过插入这样的功能来实现自动删除选定的文本。 function deleteTxt() var ele = document.getElementById('yourTextarea'); var text = ele.value; text = text.slice(0, ele.selectionStart) + text.slice(ele.selectionEnd); ele.value = text; return text; 如何在鼠标位置插入文字? 你是最棒的!【参考方案2】:

也许一个更短的版本,会更容易理解?

    jQuery("#btn").on('click', function() 
        var $txt = jQuery("#txt");
        var caretPos = $txt[0].selectionStart;
        var textAreaTxt = $txt.val();
        var txtToAdd = "stuff";
        $txt.val(textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos) );
    );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<textarea id="txt" rows="15" cols="70">There is some text here.</textarea>
<input type="button" id="btn" value="OK" />

我写这个是为了回复How to add a text to a textbox from the current position of the pointer with jquery?

【讨论】:

您还可以在更改值后恢复插入符号位置:document.getElementById("txt").selectionStart = caretPos + txtToAdd.length 为我工作,谢谢。仅供参考,通过 jquery 选择器 $("#") 不存在“selectionStart”属性。你需要通过 document.getElementById() jsfiddle.net/NaHTw/802 是您的解决方案,添加了一些额外内容以将所选区域替换为粘贴的内容 好吧,如果您打算移除 jQuery,您不妨remove it all。 ;^) 只是为了提供帮助,这里是完整的解决方案,包括插入符号位置恢复以及用粘贴的内容替换选定区域:jsfiddle.net/NaHTw/1028【参考方案3】:

George Claghorn 批准的答案非常适合在光标位置简单地插入文本。如果用户选择了文本,并且您希望替换该文本(大多数文本的默认体验),则需要在设置“后退”变量时进行一些小的更改。

另外,如果你不需要支持旧版本的 IE,现代版本支持 textarea.selectionStart,这样你就可以取出所有的浏览器检测,以及 IE 特定的代码。

这是一个至少适用于 Chrome 和 IE11 的简化版本,并处理替换选定的文本。

function insertAtCaret(areaId, text) 
    var txtarea = document.getElementById(areaId);
    var scrollPos = txtarea.scrollTop;
    var caretPos = txtarea.selectionStart;

    var front = (txtarea.value).substring(0, caretPos);
    var back = (txtarea.value).substring(txtarea.selectionEnd, txtarea.value.length);
    txtarea.value = front + text + back;
    caretPos = caretPos + text.length;
    txtarea.selectionStart = caretPos;
    txtarea.selectionEnd = caretPos;
    txtarea.focus();
    txtarea.scrollTop = scrollPos;

【讨论】:

这很好,但它没有考虑元素的maxlength,因此插入后的结果值可能比最大值长。【参考方案4】:

上面的代码在 IE 中对我不起作用。这是一些基于this answer的代码。

我取出了getElementById,以便以不同的方式引用该元素。

function insertAtCaret(element, text) 
  if (document.selection) 
    element.focus();
    var sel = document.selection.createRange();
    sel.text = text;
    element.focus();
   else if (element.selectionStart || element.selectionStart === 0) 
    var startPos = element.selectionStart;
    var endPos = element.selectionEnd;
    var scrollTop = element.scrollTop;
    element.value = element.value.substring(0, startPos) +
      text + element.value.substring(endPos, element.value.length);
    element.focus();
    element.selectionStart = startPos + text.length;
    element.selectionEnd = startPos + text.length;
    element.scrollTop = scrollTop;
   else 
    element.value += text;
    element.focus();
  
inputwidth:100px
labeldisplay:block;margin:10px 0
<label for="in2copy">Copy text from: <input id="in2copy" type="text" value="x"></label>
<label for="in2ins">Element to insert: <input id="in2ins" type="text" value="1,2,3" autofocus></label>
<button onclick="insertAtCaret(document.getElementById('in2ins'),document.getElementById('in2copy').value)">Insert</button>

编辑:添加了一个正在运行的 sn-p,jQuery 没有被使用

【讨论】:

元素是否是 jquery 对象? element.value 和 element.focus() 不能同时工作... element.focus() 是 DOMElements 上的合法 JavaScript 方法:w3schools.com/jsref/met_html_focus.asp 最好的办法是放弃 IE 兼容性。 是的,我在 7 年前写了这个答案。此时 IE 11 是一个很好的最低支持版本,上面的代码在那里工作。【参考方案5】:

使用@quick_sliv 回答:

function insertAtCaret(el, text) 
    var caretPos = el.selectionStart;
    var textAreaTxt = el.value;
    el.value = textAreaTxt.substring(0, caretPos) + text + textAreaTxt.substring(caretPos);
;

【讨论】:

我发现的最简单的答案,效果很好!这应该是公认的答案。【参考方案6】:

如何通过 JQuery 和 JavaScript 在 TextBox 的当前光标位置插入一些文本

过程

    查找当前光标位置 获取要复制的文本 在那边设置文本 更新光标位置

这里我有 2 个文本框和一个按钮。我必须单击文本框上的某个位置,然后单击按钮以粘贴文本 其他文本框到前一个文本框的位置。

这里的主要问题是获取我们将粘贴文本的当前光标位置。

//Textbox on which to be pasted
<input type="text" id="txtOnWhichToBePasted" />

//Textbox from where to be pasted
<input type="text" id="txtFromWhichToBePasted" />


//Button on which click the text to be pasted
<input type="button" id="btnInsert" value="Insert"/>


<script type="text/javascript">

$(document).ready(function () 
    $('#btnInsert').bind('click', function () 
            var TextToBePasted = $('#txtFromWhichToBePasted').value;
            var ControlOnWhichToBePasted = $('#txtOnWhichToBePasted');

            //Paste the Text
            PasteTag(ControlOnWhichToBePasted, TextToBePasted);
        );
    );

//Function Pasting The Text
function PasteTag(ControlOnWhichToBePasted,TextToBePasted) 
    //Get the position where to be paste

    var CaretPos = 0;
    // IE Support
    if (document.selection) 

        ControlOnWhichToBePasted.focus();
        var Sel = document.selection.createRange();

        Sel.moveStart('character', -ctrl.value.length);

        CaretPos = Sel.text.length;
    
    // Firefox support
    else if (ControlOnWhichToBePasted.selectionStart || ControlOnWhichToBePasted.selectionStart == '0')
        CaretPos = ControlOnWhichToBePasted.selectionStart;

    //paste the text
    var WholeString = ControlOnWhichToBePasted.value;
    var txt1 = WholeString.substring(0, CaretPos);
    var txt2 = WholeString.substring(CaretPos, WholeString.length);
    WholeString = txt1 + TextToBePasted + txt2;
    var CaretPos = txt1.length + TextToBePasted.length;
    ControlOnWhichToBePasted.value = WholeString;

    //update The cursor position 
    setCaretPosition(ControlOnWhichToBePasted, CaretPos);


function setCaretPosition(ControlOnWhichToBePasted, pos) 

    if (ControlOnWhichToBePasted.setSelectionRange) 
        ControlOnWhichToBePasted.focus();
        ControlOnWhichToBePasted.setSelectionRange(pos, pos);
    
    else if (ControlOnWhichToBePasted.createTextRange) 
        var range = ControlOnWhichToBePasted.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
    


</script>

【讨论】:

【参考方案7】:

将文本添加到当前光标位置涉及两个步骤:

    在当前光标位置添加文本 更新当前光标位置

演示:https://codepen.io/anon/pen/qZXmgN

在 Chrome 48、Firefox 45、IE 11 和 Edge 25 中测试

JS:

function addTextAtCaret(textAreaId, text) 
    var textArea = document.getElementById(textAreaId);
    var cursorPosition = textArea.selectionStart;
    addTextAtCursorPosition(textArea, cursorPosition, text);
    updateCursorPosition(cursorPosition, text, textArea);

function addTextAtCursorPosition(textArea, cursorPosition, text) 
    var front = (textArea.value).substring(0, cursorPosition);
    var back = (textArea.value).substring(cursorPosition, textArea.value.length);
    textArea.value = front + text + back;

function updateCursorPosition(cursorPosition, text, textArea) 
    cursorPosition = cursorPosition + text.length;
    textArea.selectionStart = cursorPosition;
    textArea.selectionEnd = cursorPosition;
    textArea.focus();    

HTML:

<div>
    <button type="button" onclick="addTextAtCaret('textArea','Apple')">Insert Apple!</button>
    <button type="button" onclick="addTextAtCaret('textArea','Mango')">Insert Mango!</button>
    <button type="button" onclick="addTextAtCaret('textArea','Orange')">Insert Orange!</button>
</div>
<textarea id="textArea" rows="20" cols="50"></textarea>

【讨论】:

【参考方案8】:

我认为您可以使用以下 JavaScript 来跟踪最后聚焦的文本框:

<script>
var holdFocus;

function updateFocus(x)

    holdFocus = x;


function appendTextToLastFocus(text)

    holdFocus.value += text;

</script>

用法:

<input type="textbox" onfocus="updateFocus(this)" />
<a href="#" onclick="appendTextToLastFocus('textToAppend')" />

以前的解决方案(gclaghorn 的道具)使用 textarea 并计算光标的位置,因此它可能更适合您想要的。另一方面,如果您正在寻找,这个会更轻量级。

【讨论】:

好主意。我使用了 jquery,因此每个具有特定类的文本框都将此事件应用于它们,而不必将“onfocus = ...”放在每个文本框的 html 中。但是好的方法:)【参考方案9】:

这个问题的答案是很久以前发布的,我通过谷歌搜索偶然发现了它。 HTML5 提供了包含setRangeText() 方法的HTMLInputElement API,该方法将&lt;input&gt;&lt;textarea&gt; 元素中的一系列文本替换为新字符串:

element.setRangeText('abc');

以上内容会将element 中的选择替换为abc。您还可以指定要替换输入值的哪一部分:

element.setRangeText('abc', 3, 5);

上面将用abc 替换输入值的第 4 到第 6 个字符。您还可以通过提供以下字符串之一作为第 4 个参数来指定在替换文本后应如何设置选择:

'preserve' 尝试保留选择。这是默认设置。 'select' 选择新插入的文本。 'start' 将所选内容移动到插入文本之前。 'end' 将所选内容移动到插入的文本之后。

浏览器兼容性

setRangeText 的 MDN 页面没有提供浏览器兼容性数据,但我猜应该和HTMLInputElement.setSelectionRange() 一样,基本上都是现代浏览器,IE 9 及以上,Edge 12 及以上。

【讨论】:

您链接的“setRangeText”mozilla 页面现在底部有一个“浏览器兼容性”部分:不支持 IE,但其他所有现代浏览器(Chrome、FF、Edge 等)都支持.要完全回答操作员的问题,这里有一些附加信息:您可以使用 element.selectionStartelement.selectionEnd 来查找光标的位置。如果 start!=end,那么用户标记了一些文本,否则它只是光标的位置。 “0”表示在文本元素的最开始,如果有换行符(例如在文本区域中),它会继续计数。 一些更多信息,因为我已经完成了所有测试:我建议使用end 以获得最“自然”的感觉:光标放在插入文本的末尾,这使得它成为可能在一行中插入多个内容,而无需移动光标。它还允许替换已经存在的文本,之后,与preserve 不同,它不会选择之前选择的“从到”,而是再次将光标放在插入文本的末尾。 Windows 就是这样做的(不是 100% 确定 macOS 或 Linux),我真的很惊讶它不是默认设置。【参考方案10】:

接受的答案在 Internet Explorer 9 上对我不起作用。 我检查了它,浏览器检测没有正常工作,当我在 Internet Explorer 时它检测到 ff (firefox)。

我刚刚做了这个改变:

if ($.browser.msie) 

代替:

if (br == "ie")  

生成的代码是这个:

function insertAtCaret(areaId,text) 
    var txtarea = document.getElementById(areaId);
    var scrollPos = txtarea.scrollTop;
    var strPos = 0;
    var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ? 
        "ff" : (document.selection ? "ie" : false ) );

    if ($.browser.msie)  
        txtarea.focus();
        var range = document.selection.createRange();
        range.moveStart ('character', -txtarea.value.length);
        strPos = range.text.length;
    
    else if (br == "ff") strPos = txtarea.selectionStart;

    var front = (txtarea.value).substring(0,strPos);  
    var back = (txtarea.value).substring(strPos,txtarea.value.length); 
    txtarea.value=front+text+back;
    strPos = strPos + text.length;
    if (br == "ie")  
        txtarea.focus();
        var range = document.selection.createRange();
        range.moveStart ('character', -txtarea.value.length);
        range.moveStart ('character', strPos);
        range.moveEnd ('character', 0);
        range.select();
    
    else if (br == "ff") 
        txtarea.selectionStart = strPos;
        txtarea.selectionEnd = strPos;
        txtarea.focus();
    
    txtarea.scrollTop = scrollPos;

【讨论】:

【参考方案11】:

This jQuery plugin 为您提供了一种预制的选择/插入符号操作方式。

【讨论】:

【参考方案12】:

您只能聚焦所需的文本框并在那里插入文本。没有办法找出AFAIK的焦点在哪里(也许在所有DOM节点上进行交互?)。

检查此 *** - 它为您提供了解决方案: How do I find out which DOM element has the focus?

【讨论】:

【参考方案13】:

内容可编辑、HTML 或任何其他 DOM 元素选择

如果您尝试在 &lt;div contenteditable="true"&gt; 上插入插入符号,这将变得更加困难,尤其是当可编辑容器中有子项时。

使用 Rangy 库我真的很幸运:

GIT:https://github.com/timdown/rangy NPM:https://www.npmjs.com/package/rangy

它有很多很棒的功能,例如:

保存位置或选择 然后,恢复位置或选择 获取选择的 HTML 或纯文本 还有很多

我上次检查的在线演示无法正常工作,但是 repo 有工作演示。要开始使用,只需从 Git 或 NPM 下载 Repo,然后打开 ./rangy/demos/index.html

它使使用插入符号位置和文本选择变得轻而易举!

【讨论】:

以上是关于在光标使用 Javascript/jquery 的位置插入文本的主要内容,如果未能解决你的问题,请参考以下文章

Javascript(jQuery)在拖动项目时禁用页面滚动

有没有办法改变owl-carousel的光标? (不是 owl-dots 或 owl-nav)

使用 DIV 作为按钮时保持文本选择

在 javascript/jquery 中使用 PHP print_r 数组

我无法在 iOs 上使用任何 javascript (jQuery)

使用 javascript/jquery 检测 Asp.Net 表单是不是有效