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

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

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

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

【问题讨论】:

标签: javascript jquery


【解决方案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();
  }
}
input{width:100px}
label{display: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 的当前光标位置插入一些文本

过程

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

这里我有 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】:

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

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

    演示: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节点上进行交互?)。

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

          【讨论】:

            【解决方案13】:

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

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

            我在使用 Rangy 库时非常幸运:

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

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

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

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

            【讨论】:

              猜你喜欢
              • 2012-04-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多