如何在视口中始终保留textarea的插入符号?

时间:2012-10-24 21:38:54

标签: javascript html textarea

我有一个页面,其中包含很长的文本区域,用于编辑大量文本。通常,当您键入时,当插入符号接近textarea的底部时,页面将自动滚动以使插入符号始终位于视口内(Firefox将一次滚动一行,Chrome将滚动插入符号的中心视口)。

我的问题来自于我根据用户输入的内容以编程方式更改文本区域的内容。在某些情况下,这涉及添加额外的内容,从而推动插入符号。

一旦用户点击一个键,自动滚动就会启动并且插入符号会滚动到视图中 - 但不是之前,因此当用户键入时他们会看不到插入符号。我希望我可以简单地触发textarea上的关键事件,让浏览器自动滚动,但是触发的事件不能完全模拟用户行为,我也没有得到回复。

我现在能看到的唯一解决方案是尝试通过以下方式获取插入符号的XY坐标:

  1. 找到插入符号的字符位置。
  2. 使用插入位置处的标记构建一个反映textarea内容的div。
  3. 测量标记的位置。
  4. 有更简单的方法吗?

3 个答案:

答案 0 :(得分:1)

我讨厌建议为一个问题添加整个库,但请考虑查看CodeMirror。它为您处理所有这些东西,并且使用起来相当简单。

http://codemirror.net/

答案 1 :(得分:0)

[之前的解决方案与Chrome(WebKit?)无法兼容]

IF,如果将额外内容附加到输入的末尾,则下面的练习可以提供解决方案:

<html>
  <head>
    <script>
      function btnGoOnClick(ctrl)
      {
        //-- For this POC the text content is reset to 160 lines of dummy text -
        //----------------------------------------------------------------------

        ctrl.value = "";

        for (var i = 0; i < 160; ++i)
        {
          ctrl.value += "dummy!\n";
        }

        //-- Then the carret is set to the last position -----------------------
        //----------------------------------------------------------------------

        if (ctrl.createTextRange)
        {
          //-- IE specific methods to move the carret to the last position

          var textRange = ctrl.createTextRange();
          textRange.moveStart("character", ctrl.value.length);
          textRange.moveEnd("character", 0);
          textRange.select();
        }
        else
        {
          //-- Mozilla and WebKit methods to move the carret

          ctrl.setSelectionRange(ctrl.value.length, ctrl.value.length);
        }

        //-- For WebKit, the scroll bar has to be explicitly set ---------------
        //----------------------------------------------------------------------

        ctrl.scrollTop = ctrl.scrollHeight;

        //-- Almost there: make sure the control has fucos and is into view ----
        //----------------------------------------------------------------------

        ctrl.focus();
        ctrl.scrollIntoView(false);
      }
    </script>
  </head>
  <body>
    <form name="form">
      <input type="button" name="btnGo" value="Go!" onClick="btnGoOnClick(document.form.text);" />
      <div style="height: 1000px"></div>
      <textarea name="text" rows="80"></textarea>
    </form>
  </body>
</html>

答案 2 :(得分:0)

由于您已经在javascript路径上并且假设动态textarea高度会造成设计问题,您可以尝试按内容自动调整textarea:

function resizeTextarea(textarea) {
  var lines = textarea.value.split('\n');
  var width = textarea.cols;
  var height = 1;
  for (var i = 0; i < lines.length; i++) {
    var linelength = lines[i].length;
    if (linelength >= width) {
      height += Math.ceil(linelength / width);
    }
  }
  height += lines.length;
  textarea.rows = height;
}

我知道这不会回答您帖子中列出的细节,但它提供了一种适合您的问题标题的替代方法。所以,即使它对你没有用,也可能只是那些访问这个问题的人。

我个人讨厌太小的文本区域并依赖于案例,他们更喜欢自动化。